vintage-frames 0.19.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  import { DocumentListenersController as e } from "./document-listeners.js";
2
2
  import "./motion.js";
3
+ import { openPath as t } from "./menu-navigation.js";
3
4
  //#region src/menu-press.ts
4
- var t = class {
5
+ var n = class {
5
6
  #e;
6
7
  #t;
7
8
  #n;
@@ -9,89 +10,122 @@ var t = class {
9
10
  #i;
10
11
  #a;
11
12
  #o;
13
+ #s;
14
+ #c;
15
+ #l;
12
16
  constructor(t, n) {
13
- this.target = n, this.#e = !1, this.#t = !1, this.#n = !1, this.#r = null, this.#i = 0, this.#a = null, this.onPointerDown = (e) => {
17
+ this.target = n, this.#e = !1, this.#t = !1, this.#n = !1, this.#r = null, this.#i = 0, this.#a = !1, this.#o = !1, this.#s = null, this.onPointerDown = (e) => {
14
18
  if (e.button > 0 || !e.isPrimary) return;
15
- let t = this.#p(e.clientX, e.clientY);
16
- if (t) {
17
- if (e.preventDefault(), this.#e = !0, this.#n = !1, this.#r = t.item ?? t.menu, this.#i = e.timeStamp, this.#t = !t.menu.open, this.#o.attach(), t.item) {
18
- this.#f(t.item);
19
+ let t = this.#_(e.clientX, e.clientY);
20
+ if (!(!t || !t.title && !t.item)) {
21
+ if (e.preventDefault(), this.#e = !0, this.#n = !1, this.#r = t.item ?? t.menu, this.#i = e.timeStamp, this.#t = !t.menu.open, this.#l.attach(), t.item) {
22
+ this.#h(t);
19
23
  return;
20
24
  }
21
25
  t.menu.focus(), this.#t && this.target.open(t.menu);
22
26
  }
23
- }, this.#s = (e) => {
24
- if (!this.#e) return;
25
- e.preventDefault();
26
- let t = this.#p(e.clientX, e.clientY), n = t ? t.item ?? t.menu : null;
27
- !this.#n && n !== this.#r && (this.#n = !0), t && !t.item && !t.menu.open && this.target.open(t.menu), this.#f(t?.item ?? null);
28
- }, this.#c = (e) => {
27
+ }, this.#u = (e) => {
28
+ if (this.#o) return;
29
+ let t = this.#_(e.clientX, e.clientY);
30
+ if (this.#e) {
31
+ e.preventDefault();
32
+ let n = t ? t.item ?? (t.title ? t.menu : null) : null;
33
+ !this.#n && n !== this.#r && (this.#n = !0), t?.title && !t.menu.open && this.target.open(t.menu);
34
+ }
35
+ this.#h(t);
36
+ }, this.#d = (e) => {
29
37
  if (!this.#e) return;
30
- let t = this.#p(e.clientX, e.clientY), n = this.#t, r = !this.#n, i = e.timeStamp - this.#i < 200;
31
- this.#u(), !(n && r && i) && this.#d(t?.item ?? null);
32
- }, this.#l = () => {
33
- this.#u(), this.#f(null);
34
- }, t.addController(this), this.#o = new e(t, () => [
38
+ let t = this.#_(e.clientX, e.clientY), n = this.#t, r = !this.#n, i = e.timeStamp - this.#i < 200;
39
+ this.#p(), !(n && r && i) && this.#m(t && !t.title ? t : null);
40
+ }, this.#f = () => {
41
+ this.#p(), this.#h(null);
42
+ }, t.addController(this), this.#l = new e(t, () => [
35
43
  [
36
44
  document,
37
45
  "pointermove",
38
- this.#s,
46
+ this.#u,
39
47
  !0
40
48
  ],
41
49
  [
42
50
  document,
43
51
  "pointerup",
44
- this.#c,
52
+ this.#d,
45
53
  !0
46
54
  ],
47
55
  [
48
56
  document,
49
57
  "pointercancel",
50
- this.#l,
58
+ this.#f,
51
59
  !0
52
60
  ]
53
61
  ]);
54
62
  }
55
63
  hostDisconnected() {
56
- this.#u(), this.#f(null);
64
+ this.#p(), this.track(!1);
57
65
  }
58
- #s;
59
- #c;
60
- #l;
61
- #u() {
62
- this.#e && (this.#e = !1, this.#r = null, this.#o.detach());
66
+ track(e) {
67
+ if (this.#a = e, e) {
68
+ this.#l.attach();
69
+ return;
70
+ }
71
+ this.#o = !1, this.#s = null, this.#g(), this.#e || this.#l.detach();
63
72
  }
64
- #d(e) {
65
- if (!e || e.disabled) {
66
- this.#f(null), this.target.close();
73
+ #u;
74
+ #d;
75
+ #f;
76
+ #p() {
77
+ this.#e && (this.#e = !1, this.#r = null, this.#a || this.#l.detach());
78
+ }
79
+ #m(e) {
80
+ let t = e?.item;
81
+ if (!e || !t || t.disabled) {
82
+ this.target.close();
67
83
  return;
68
84
  }
69
- this.#f(e), this.#a = null, e.activate();
85
+ if (this.#g(), t.submenu) {
86
+ e.menu.expand(t);
87
+ return;
88
+ }
89
+ this.#h(e), this.#o = !0, t.activate();
90
+ }
91
+ #h(e) {
92
+ let n = e && !e.title ? {
93
+ menu: e.menu,
94
+ row: e.item && !e.item.disabled ? e.item : null
95
+ } : null, r = this.#s;
96
+ if (r?.menu === n?.menu && r?.row === n?.row) return;
97
+ this.#s = n;
98
+ for (let e of this.target.menus()) if (e.open) for (let r of t(e)) r.pointerOver(r === n?.menu ? n.row : void 0);
99
+ if (this.#g(), !n) return;
100
+ let { menu: i, row: a } = n, o = i.expandedItem;
101
+ (a === null || a !== o) && (o ? this.#c = window.setTimeout(() => i.expand(a?.submenu ? a : null), 300) : a?.submenu && (this.#c = window.setTimeout(() => i.expand(a), 150)));
70
102
  }
71
- #f(e) {
72
- let t = e && !e.disabled ? e : null;
73
- t !== this.#a && (this.#a && (this.#a.active = !1), this.#a = t, t && (t.active = !0));
103
+ #g() {
104
+ this.#c !== void 0 && window.clearTimeout(this.#c), this.#c = void 0;
74
105
  }
75
- #p(e, t) {
76
- let r = this.target.menus(), i = r.find((e) => e.open);
77
- if (i) {
78
- for (let r of i.allItems) if (n(r.getBoundingClientRect(), e, t)) return {
106
+ #_(e, n) {
107
+ let i = this.target.menus(), a = i.find((e) => e.open);
108
+ if (a) for (let i of t(a).reverse()) {
109
+ let t = i.panelRect;
110
+ if (!(!t || !r(t, e, n))) return {
79
111
  menu: i,
80
- item: r
112
+ title: !1,
113
+ item: i.allItems.find((t) => r(t.getBoundingClientRect(), e, n)) ?? null
81
114
  };
82
115
  }
83
- for (let i of r) {
84
- let r = i.labelRect;
85
- if (r && n(r, e, t)) return {
86
- menu: i,
116
+ for (let t of i) {
117
+ let i = t.labelRect;
118
+ if (i && r(i, e, n)) return {
119
+ menu: t,
120
+ title: !0,
87
121
  item: null
88
122
  };
89
123
  }
90
124
  return null;
91
125
  }
92
126
  };
93
- function n(e, t, n) {
127
+ function r(e, t, n) {
94
128
  return t >= e.left && t < e.right && n >= e.top && n < e.bottom;
95
129
  }
96
130
  //#endregion
97
- export { t as MenuPressController };
131
+ export { n as MenuPressController };
package/dist/motion.d.ts CHANGED
@@ -19,6 +19,16 @@ export declare function prefersReducedMotion(): boolean;
19
19
  * drag-pick regardless of duration.
20
20
  */
21
21
  export declare const PRESS_HOLD_MS = 200;
22
+ /**
23
+ * How long (ms) the pointer rests on a menu item before its submenu opens,
24
+ * and how long it may stray onto another row of the same menu before an open
25
+ * submenu closes. The second is the longer, so a diagonal slide from an item
26
+ * into its submenu can cross the rows between. Not gated on
27
+ * `prefers-reduced-motion`: they are the interaction, not decoration, the
28
+ * reasoning {@link MENU_SCROLL_INTERVAL_MS} gives. Provisional, tuned by hand.
29
+ */
30
+ export declare const SUBMENU_OPEN_MS = 150;
31
+ export declare const SUBMENU_CLOSE_MS = 300;
22
32
  /**
23
33
  * How long (ms) a press on a selected icon's name waits before it opens the
24
34
  * rename box — long enough that a double-click has already declared itself.
@@ -17,8 +17,10 @@
17
17
  * on the startup disk (the desktop without one) holding Apple Menu Items
18
18
  * and Startup Items, listed after the volumes. What they hold is anyone's,
19
19
  * and the shell reads it: the Apple menu, and what opens at startup.
20
- * - An alias stands for another item: its data names the original's id, and
21
- * `resolve` finds the original wherever it moved, until it is removed.
20
+ * - An alias stands for another item: its data names the original's id and
21
+ * kind, and `resolve` finds the original wherever it moved, until it is
22
+ * removed. An alias of a container takes a drop for its original, and
23
+ * keeps taking one, to say so, once the original is gone.
22
24
  * - A folder never goes into itself or a folder inside it. A parent with no
23
25
  * record reads as the desktop.
24
26
  * - An item whose kind no application registers is left out of the listing
@@ -166,6 +168,26 @@ export declare function isInside(state: CatalogState, id: string, ancestor: stri
166
168
  export declare function enclosingFolders(state: CatalogState, id: string | null | undefined): string[];
167
169
  /** Whether `id` is the Trash or anything inside it. */
168
170
  export declare function isTrashed(state: CatalogState, id: string | null | undefined): boolean;
171
+ /**
172
+ * Whether Make Alias takes item `id`: an application, a document, a folder
173
+ * or the startup disk, or an alias of one, outside the Trash. Never the
174
+ * Trash itself, and never an alias whose original is gone.
175
+ */
176
+ export declare function canAlias(state: CatalogState, id: string | null | undefined): boolean;
177
+ /** What a drop onto an item files into: a container's id, or the alias of a container whose original is gone. */
178
+ export type DropTarget = {
179
+ folder: string;
180
+ } | {
181
+ missing: Item;
182
+ };
183
+ /**
184
+ * What a drop onto item `id` files into. A container takes it itself, and
185
+ * an alias of one passes it to the original, so filing judges the original:
186
+ * a folder never goes into itself through an alias either. An alias of a
187
+ * container whose original is gone still takes the drop and files nothing:
188
+ * `missing`, the alias. Anything else takes none: null.
189
+ */
190
+ export declare function dropTargetOf(state: CatalogState, id: string | null | undefined): DropTarget | null;
169
191
  /** Everything under a container, each container before what it holds; a loop is walked once. */
170
192
  export declare function descendantsOf(state: CatalogState, parent: string | null): Item[];
171
193
  /** The first free folder name in a container: "untitled folder", "untitled folder 2", … */
@@ -182,6 +204,22 @@ export declare function aliasName(state: CatalogState, parent: string | null, na
182
204
  export declare const appleMenuItemsOf: (state: CatalogState) => Item[];
183
205
  /** What Startup Items holds, by name: what opens at startup. None without the System Folder. */
184
206
  export declare const startupItemsOf: (state: CatalogState) => Item[];
207
+ /** One entry of the Apple menu, and what it holds when it is a folder's. */
208
+ export interface AppleMenuEntry {
209
+ /** The entry's own item: an alias stays the alias. */
210
+ item: Item;
211
+ /** What the folder holds, or the folder an alias stands for, by name. */
212
+ entries?: AppleMenuEntry[];
213
+ }
214
+ /**
215
+ * The Apple menu as a tree: what Apple Menu Items holds, by name, and for a
216
+ * folder in it, or an alias of one, what that folder holds, the same way,
217
+ * down to five levels below the menu. A folder already on the way down
218
+ * (Apple Menu Items starts it), an empty folder and a folder past the fifth
219
+ * level have no entries, so the tree never loops. None without the System
220
+ * Folder.
221
+ */
222
+ export declare function appleMenuOf(state: CatalogState): AppleMenuEntry[];
185
223
  /** The catalog's operations, over its listing. */
186
224
  export interface Catalog {
187
225
  get(): CatalogState;