vintage-frames 0.14.1 → 0.15.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/custom-elements.json +94 -14
- package/dist/components/vf-button.d.ts +5 -1
- package/dist/components/vf-button.js +1 -1
- package/dist/components/vf-dialog.d.ts +7 -1
- package/dist/events.d.ts +3 -2
- package/dist/events.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/modal-dialog.d.ts +31 -4
- package/dist/modal-dialog.js +98 -82
- package/dist/position.js +25 -20
- package/dist/shell/alert.d.ts +17 -9
- package/dist/shell/alert.js +25 -28
- package/dist/shell/finder.d.ts +41 -1
- package/dist/shell/finder.js +212 -178
- package/dist/shell/index.d.ts +1 -3
- package/dist/shell/index.js +5 -6
- package/dist/shell/shell.d.ts +25 -11
- package/dist/shell/shell.js +143 -122
- package/dist/shell/windows.d.ts +21 -2
- package/dist/shell/windows.js +169 -125
- package/dist/text-control.d.ts +6 -0
- package/dist/text-control.js +2 -2
- package/docs/SPEC.md +5 -5
- package/editor/vscode.html-custom-data.json +2 -2
- package/editor/web-types.json +11 -6
- package/package.json +1 -1
package/dist/modal-dialog.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ScaleController as
|
|
3
|
-
import
|
|
4
|
-
import { DocumentListenersController as
|
|
5
|
-
import { LitElement as
|
|
6
|
-
import { property as
|
|
7
|
-
var
|
|
1
|
+
import { deferActivation as e, emit as t } from "./events.js";
|
|
2
|
+
import { ScaleController as n, onScaleChange as r, snapSys as i, sysLength as a, toSysExact as o } from "./scale.js";
|
|
3
|
+
import s from "./_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
4
|
+
import { DocumentListenersController as c } from "./document-listeners.js";
|
|
5
|
+
import { LitElement as l, css as u } from "lit";
|
|
6
|
+
import { property as d, query as f } from "lit/decorators.js";
|
|
7
|
+
var p = 24, m = /* @__PURE__ */ new Set([
|
|
8
8
|
"text",
|
|
9
9
|
"search",
|
|
10
10
|
"url",
|
|
@@ -12,7 +12,7 @@ var f = 24, p = /* @__PURE__ */ new Set([
|
|
|
12
12
|
"email",
|
|
13
13
|
"password",
|
|
14
14
|
"number"
|
|
15
|
-
]),
|
|
15
|
+
]), h = (e) => e instanceof HTMLInputElement ? m.has(e.type) : !0, g = u`
|
|
16
16
|
dialog {
|
|
17
17
|
padding: 0;
|
|
18
18
|
margin: auto;
|
|
@@ -51,110 +51,119 @@ var f = 24, p = /* @__PURE__ */ new Set([
|
|
|
51
51
|
the fallback is the arrow it always showed. */
|
|
52
52
|
cursor: var(--vf-cursor, default);
|
|
53
53
|
}
|
|
54
|
-
`,
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
`, _ = class extends l {
|
|
55
|
+
get dialogSize() {
|
|
56
|
+
return {
|
|
57
|
+
width: a(this.width ?? 260),
|
|
58
|
+
height: this.height === void 0 ? null : a(this.height)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
#e;
|
|
62
|
+
#t() {
|
|
63
|
+
if (this.#e || !this.open) return;
|
|
64
|
+
let e = [];
|
|
65
|
+
if (this.width === void 0 && e.push("width (falling back to 260 system px)"), this.height === void 0 && e.push("height (falling back to the content)"), e.length === 0) return;
|
|
66
|
+
this.#e = !0;
|
|
67
|
+
let t = this.getAttribute("heading") ?? this.getAttribute("label") ?? "";
|
|
68
|
+
console.warn(`${this.localName}${t ? ` ("${t}")` : ""}: no ${e.join(", no ")}. A modal owns its whole box — declare both in system px: <${this.localName} width="320" height="140">.`);
|
|
69
|
+
}
|
|
70
|
+
#n;
|
|
71
|
+
#r;
|
|
72
|
+
constructor() {
|
|
73
|
+
super(), this.scale = new n(this), this.open = !1, this.returnValue = "", this.lightDismiss = !1, this.#e = !1, this.#n = null, this.#r = null, this.#i = (t) => {
|
|
74
|
+
let n = t.target;
|
|
75
|
+
if (!(n instanceof HTMLFormElement) || v(n) !== this) return;
|
|
76
|
+
let r = t.submitter;
|
|
77
|
+
if ((r?.hasAttribute("formmethod") ? r.getAttribute("formmethod") : n.getAttribute("method"))?.toLowerCase() !== "dialog") return;
|
|
78
|
+
let i = r instanceof HTMLButtonElement || r instanceof HTMLInputElement ? r.value : void 0;
|
|
79
|
+
e(this, t, () => this.close(i));
|
|
80
|
+
}, this.#a = null, this.#o = new c(this, () => [
|
|
57
81
|
[
|
|
58
82
|
this._dialog,
|
|
59
83
|
"pointerdown",
|
|
60
|
-
this.#
|
|
84
|
+
this.#l
|
|
61
85
|
],
|
|
62
86
|
[
|
|
63
87
|
this._dialog,
|
|
64
88
|
"pointerup",
|
|
65
|
-
this.#
|
|
89
|
+
this.#u
|
|
66
90
|
],
|
|
67
91
|
[
|
|
68
92
|
this._dialog,
|
|
69
93
|
"pointercancel",
|
|
70
|
-
this.#
|
|
94
|
+
this.#d
|
|
71
95
|
],
|
|
72
96
|
[
|
|
73
97
|
this._dialog,
|
|
74
98
|
"keydown",
|
|
75
|
-
this.#
|
|
99
|
+
this.#c
|
|
76
100
|
]
|
|
77
|
-
]), this.#
|
|
101
|
+
]), this.#c = (e) => {
|
|
78
102
|
if (e.key !== "Enter" || e.defaultPrevented || e.isComposing || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
79
103
|
let t = e.composedPath();
|
|
80
104
|
if (t.some((e) => e instanceof HTMLAnchorElement && e.hasAttribute("href")) || t.some((e) => e instanceof HTMLTextAreaElement || e instanceof HTMLElement && e.isContentEditable) && e.code !== "NumpadEnter") return;
|
|
81
105
|
let n = this.defaultButton;
|
|
82
106
|
n && (e.preventDefault(), n.click());
|
|
83
|
-
}, this.#
|
|
84
|
-
this.#
|
|
85
|
-
}, this.#
|
|
86
|
-
let t = this.#
|
|
87
|
-
this.#
|
|
88
|
-
}, this.#
|
|
89
|
-
this.#
|
|
90
|
-
}, this.#
|
|
91
|
-
}
|
|
92
|
-
get dialogSize() {
|
|
93
|
-
return {
|
|
94
|
-
width: i(this.width ?? 260),
|
|
95
|
-
height: this.height === void 0 ? null : i(this.height)
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
#e;
|
|
99
|
-
#t() {
|
|
100
|
-
if (this.#e || !this.open) return;
|
|
101
|
-
let e = [];
|
|
102
|
-
if (this.width === void 0 && e.push("width (falling back to 260 system px)"), this.height === void 0 && e.push("height (falling back to the content)"), e.length === 0) return;
|
|
103
|
-
this.#e = !0;
|
|
104
|
-
let t = this.getAttribute("heading") ?? this.getAttribute("label") ?? "";
|
|
105
|
-
console.warn(`${this.localName}${t ? ` ("${t}")` : ""}: no ${e.join(", no ")}. A modal owns its whole box — declare both in system px: <${this.localName} width="320" height="140">.`);
|
|
107
|
+
}, this.#l = (e) => {
|
|
108
|
+
this.#a = e.target === this._dialog ? e.pointerId : null;
|
|
109
|
+
}, this.#u = (e) => {
|
|
110
|
+
let t = this.#a === e.pointerId;
|
|
111
|
+
this.#a = null, !(!t || e.target !== this._dialog || !this.lightDismiss) && (this.#n = "outside", this.close());
|
|
112
|
+
}, this.#d = () => {
|
|
113
|
+
this.#a = null;
|
|
114
|
+
}, this.#f = null, this.#v = () => this.settle(), this.addEventListener("submit", this.#i);
|
|
106
115
|
}
|
|
107
|
-
#n;
|
|
108
|
-
#r;
|
|
109
116
|
#i;
|
|
117
|
+
#a;
|
|
118
|
+
#o;
|
|
110
119
|
get defaultButton() {
|
|
111
120
|
let e = "vf-button[variant=\"default\"]";
|
|
112
121
|
return [...this.querySelectorAll(e), ...this.renderRoot.querySelectorAll(e)].find((e) => !e.matches(":disabled")) ?? null;
|
|
113
122
|
}
|
|
114
123
|
get initialFocusTarget() {
|
|
115
|
-
return this.querySelector("[autofocus]") || ([...this.querySelectorAll("vf-text-field, vf-number-field, vf-text-area, textarea, input")].find((e) =>
|
|
124
|
+
return this.querySelector("[autofocus]") || ([...this.querySelectorAll("vf-text-field, vf-number-field, vf-text-area, textarea, input")].find((e) => h(e) && !e.matches(":disabled")) ?? this.defaultButton);
|
|
116
125
|
}
|
|
117
|
-
#
|
|
126
|
+
#s() {
|
|
118
127
|
this.initialFocusTarget?.focus();
|
|
119
128
|
}
|
|
120
|
-
#o;
|
|
121
|
-
#s;
|
|
122
129
|
#c;
|
|
123
130
|
#l;
|
|
124
131
|
#u;
|
|
132
|
+
#d;
|
|
133
|
+
#f;
|
|
125
134
|
show() {
|
|
126
|
-
this.open = !0, this.hasUpdated && this.#
|
|
135
|
+
this.open = !0, this.hasUpdated && this.#_();
|
|
127
136
|
}
|
|
128
|
-
close() {
|
|
129
|
-
this.open = !1, this.hasUpdated && this.#
|
|
137
|
+
close(e) {
|
|
138
|
+
this.open && e !== void 0 && (this.#r = e), this.open = !1, this.hasUpdated && this.#_();
|
|
130
139
|
}
|
|
131
140
|
updated(e) {
|
|
132
|
-
e.has("open") && this.#
|
|
141
|
+
e.has("open") && this.#_(), (e.has("top") || e.has("left")) && this.settle(), this.#t();
|
|
133
142
|
}
|
|
134
|
-
#
|
|
143
|
+
#p() {
|
|
135
144
|
let e = document.documentElement;
|
|
136
145
|
return {
|
|
137
|
-
width:
|
|
138
|
-
height:
|
|
146
|
+
width: o(e.clientWidth || window.innerWidth, this),
|
|
147
|
+
height: o(e.clientHeight || window.innerHeight, this)
|
|
139
148
|
};
|
|
140
149
|
}
|
|
141
|
-
#
|
|
142
|
-
let n = this.#
|
|
150
|
+
#m(e, t) {
|
|
151
|
+
let n = this.#p(), r = o(this._dialog?.offsetWidth ?? 0, this);
|
|
143
152
|
return {
|
|
144
|
-
x: Math.min(Math.max(e,
|
|
145
|
-
y: Math.min(Math.max(t, 0), Math.max(0, n.height -
|
|
153
|
+
x: Math.min(Math.max(e, p - r), n.width - p),
|
|
154
|
+
y: Math.min(Math.max(t, 0), Math.max(0, n.height - p))
|
|
146
155
|
};
|
|
147
156
|
}
|
|
148
|
-
#
|
|
149
|
-
let e = this.#
|
|
157
|
+
#h() {
|
|
158
|
+
let e = this.#p(), t = this._dialog?.getBoundingClientRect();
|
|
150
159
|
return {
|
|
151
|
-
x: (e.width -
|
|
152
|
-
y: (e.height -
|
|
160
|
+
x: (e.width - o(t?.width ?? 0, this)) / 2,
|
|
161
|
+
y: (e.height - o(t?.height ?? 0, this)) / 2
|
|
153
162
|
};
|
|
154
163
|
}
|
|
155
164
|
placeAt(e, t) {
|
|
156
|
-
let n = this.#
|
|
157
|
-
this.left =
|
|
165
|
+
let n = this.#m(e, t);
|
|
166
|
+
this.left = i(n.x, this), this.top = i(n.y, this);
|
|
158
167
|
}
|
|
159
168
|
settle() {
|
|
160
169
|
let e = this._dialog;
|
|
@@ -162,10 +171,10 @@ var f = 24, p = /* @__PURE__ */ new Set([
|
|
|
162
171
|
let t = this.left != null || this.top != null ? {
|
|
163
172
|
x: this.left ?? 0,
|
|
164
173
|
y: this.top ?? 0
|
|
165
|
-
} : this.#
|
|
166
|
-
e.style.left = i(
|
|
174
|
+
} : this.#h(), n = this.#m(t.x, t.y);
|
|
175
|
+
e.style.left = a(i(n.x, this)), e.style.top = a(i(n.y, this)), e.style.right = "auto", e.style.bottom = "auto", e.style.margin = "0";
|
|
167
176
|
}
|
|
168
|
-
#
|
|
177
|
+
#g() {
|
|
169
178
|
let e = this._dialog?.style;
|
|
170
179
|
if (e) for (let t of [
|
|
171
180
|
"left",
|
|
@@ -175,44 +184,51 @@ var f = 24, p = /* @__PURE__ */ new Set([
|
|
|
175
184
|
"margin"
|
|
176
185
|
]) e.removeProperty(t);
|
|
177
186
|
}
|
|
178
|
-
#
|
|
187
|
+
#_() {
|
|
179
188
|
let e = this._dialog;
|
|
180
|
-
e && (this.open && !e.open ? (this.#
|
|
189
|
+
e && (this.open && !e.open ? (this.#f = document.activeElement, this.returnValue = "", e.showModal(), this.#s(), this.settle(), this.#x(e), this.#o.attach()) : !this.open && e.open && e.close());
|
|
181
190
|
}
|
|
182
|
-
#g;
|
|
183
|
-
#_;
|
|
184
191
|
#v;
|
|
185
|
-
#y
|
|
186
|
-
|
|
192
|
+
#y;
|
|
193
|
+
#b;
|
|
194
|
+
#x(e) {
|
|
195
|
+
typeof ResizeObserver < "u" && !this.#y && (this.#y = new ResizeObserver(this.#v), this.#y.observe(e)), window.addEventListener("resize", this.#v), this.#b ??= r(this.#v);
|
|
187
196
|
}
|
|
188
|
-
#
|
|
189
|
-
this.#
|
|
197
|
+
#S() {
|
|
198
|
+
this.#y?.disconnect(), this.#y = void 0, window.removeEventListener("resize", this.#v), this.#b?.(), this.#b = void 0;
|
|
190
199
|
}
|
|
191
200
|
disconnectedCallback() {
|
|
192
|
-
super.disconnectedCallback(), this.#
|
|
201
|
+
super.disconnectedCallback(), this.#S();
|
|
193
202
|
let e = this._dialog;
|
|
194
203
|
if (e?.open) {
|
|
195
204
|
e.close();
|
|
196
|
-
let t = this.#
|
|
205
|
+
let t = this.#f, n = document.activeElement;
|
|
197
206
|
t instanceof HTMLElement && t.isConnected && (n === null || n === document.body) && t.focus();
|
|
198
207
|
}
|
|
199
|
-
this.#
|
|
208
|
+
this.#f = null;
|
|
200
209
|
}
|
|
201
210
|
_onNativeCancel() {
|
|
202
211
|
this.#n = "escape";
|
|
203
212
|
}
|
|
204
213
|
_onNativeClose() {
|
|
205
|
-
let
|
|
206
|
-
this.#n = null, this.#
|
|
214
|
+
let e = this.#n ?? "close", n = this.#r;
|
|
215
|
+
this.#n = null, this.#r = null, n !== null && (this.returnValue = n), this.#f = null, this.#a = null, this.#o.detach(), this.#S(), this.open = !1, this.#g(), t(this, "vf-close", {
|
|
216
|
+
reason: e,
|
|
217
|
+
returnValue: n
|
|
218
|
+
});
|
|
207
219
|
}
|
|
208
220
|
};
|
|
209
|
-
|
|
221
|
+
s([d({
|
|
210
222
|
type: Boolean,
|
|
211
223
|
reflect: !0
|
|
212
|
-
})],
|
|
224
|
+
})], _.prototype, "open", void 0), s([d({ type: Number })], _.prototype, "width", void 0), s([d({ type: Number })], _.prototype, "height", void 0), s([d({ type: Number })], _.prototype, "top", void 0), s([d({ type: Number })], _.prototype, "left", void 0), s([d({
|
|
213
225
|
type: Boolean,
|
|
214
226
|
reflect: !0,
|
|
215
227
|
attribute: "light-dismiss"
|
|
216
|
-
})],
|
|
228
|
+
})], _.prototype, "lightDismiss", void 0), s([f("dialog")], _.prototype, "_dialog", void 0);
|
|
229
|
+
function v(e) {
|
|
230
|
+
for (let t = e.parentElement; t; t = t.parentElement) if (t instanceof _) return t;
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
217
233
|
//#endregion
|
|
218
|
-
export {
|
|
234
|
+
export { _ as VfModalDialog, g as modalDialogStyles };
|
package/dist/position.js
CHANGED
|
@@ -70,25 +70,25 @@ var h = class {
|
|
|
70
70
|
return u(e.width, e.height, this.#s, t(this.#e));
|
|
71
71
|
}
|
|
72
72
|
hostConnected() {
|
|
73
|
-
this.#a && (this.#r || this.#l) && this.#
|
|
73
|
+
this.#a && (this.#r || this.#l) && this.#b();
|
|
74
74
|
}
|
|
75
75
|
hostDisconnected() {
|
|
76
|
-
this.#
|
|
76
|
+
this.#x();
|
|
77
77
|
}
|
|
78
78
|
hostUpdated() {
|
|
79
79
|
let e = this.#e.top ?? null, t = this.#e.left ?? null, n = this.#e.fixed === !0, r = this.#e.origin ?? null, i = this.#e.style;
|
|
80
80
|
if (r !== this.#o && (this.#o = r, this.#s = this.#p(r)), e === null && t === null && !n) {
|
|
81
81
|
if (!this.#a) return;
|
|
82
|
-
this.#r && this.#
|
|
82
|
+
this.#r && this.#y(), this.#x(), this.#a = !1, this.#r = !1, this.#l = !1, this.#u = 0, this.#d = 0, i.removeProperty("position"), i.removeProperty("top"), i.removeProperty("left"), i.removeProperty("right"), i.removeProperty("bottom"), i.removeProperty("margin"), this.#_(null, null);
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
if (this.#a && e === this.#t && t === this.#n && n === this.#r && r === this.#i) return;
|
|
86
86
|
let a = this.#a && this.#r, o = this.#s !== c;
|
|
87
87
|
if (this.#a = !0, this.#t = e, this.#n = t, this.#r = n, this.#i = r, this.#l = o, i.position = n ? "sticky" : "absolute", o) {
|
|
88
88
|
let e = this.#e.getBoundingClientRect();
|
|
89
|
-
(e.width > 0 || e.height > 0) && this.#
|
|
89
|
+
(e.width > 0 || e.height > 0) && this.#g(e.width, e.height);
|
|
90
90
|
} else this.#u = 0, this.#d = 0;
|
|
91
|
-
this.#m(), i.right = "auto", i.bottom = "auto", n ? a || this.#
|
|
91
|
+
this.#m(), i.right = "auto", i.bottom = "auto", n ? a || this.#v() : (a && this.#y(), i.margin = "0", this.#h()), n || o ? this.#b() : this.#x(), this.#_(t ?? 0, e ?? 0);
|
|
92
92
|
}
|
|
93
93
|
#p(e) {
|
|
94
94
|
if (e == null) return c;
|
|
@@ -97,49 +97,54 @@ var h = class {
|
|
|
97
97
|
}
|
|
98
98
|
#m() {
|
|
99
99
|
let e = this.#e.style;
|
|
100
|
-
e.top = r((this.#t ?? 0) - this.#d), e.left = r((this.#n ?? 0) - this.#u);
|
|
100
|
+
e.top = r((this.#t ?? 0) - this.#d), e.left = r((this.#n ?? 0) - this.#u), this.#h();
|
|
101
101
|
}
|
|
102
|
-
#h(
|
|
102
|
+
#h() {
|
|
103
|
+
!this.#l || this.#r || (this.#e.style.marginRight = r(-((this.#n ?? 0) - this.#u)));
|
|
104
|
+
}
|
|
105
|
+
#g(e, n) {
|
|
103
106
|
let r = u(e, n, this.#s, t(this.#e));
|
|
104
107
|
return r.x === this.#u && r.y === this.#d ? !1 : (this.#u = r.x, this.#d = r.y, !0);
|
|
105
108
|
}
|
|
106
|
-
#
|
|
109
|
+
#_(t, n) {
|
|
107
110
|
e(this.#e, "vf-placement-change", {
|
|
108
111
|
left: t,
|
|
109
112
|
top: n
|
|
110
113
|
}, { composed: !1 });
|
|
111
114
|
}
|
|
112
|
-
#
|
|
115
|
+
#v() {
|
|
113
116
|
let e = this.#e.style;
|
|
114
|
-
e.maxWidth = "fit-content", e.zIndex = "1", this.#
|
|
117
|
+
e.maxWidth = "fit-content", e.zIndex = "1", this.#S = !1;
|
|
115
118
|
let t = this.#e.getBoundingClientRect();
|
|
116
|
-
(t.width > 0 || t.height > 0) && this.#
|
|
119
|
+
(t.width > 0 || t.height > 0) && this.#C(t.width, t.height);
|
|
117
120
|
}
|
|
118
|
-
#
|
|
119
|
-
this.#
|
|
121
|
+
#y() {
|
|
122
|
+
this.#S = !1;
|
|
120
123
|
let e = this.#e.style;
|
|
121
124
|
e.removeProperty("display"), e.removeProperty("max-width"), e.removeProperty("z-index");
|
|
122
125
|
}
|
|
123
|
-
#
|
|
126
|
+
#b() {
|
|
124
127
|
this.#f ??= new ResizeObserver((e) => {
|
|
125
128
|
let t = e[e.length - 1]?.borderBoxSize?.[0], n = t ? {
|
|
126
129
|
width: t.inlineSize,
|
|
127
130
|
height: t.blockSize
|
|
128
131
|
} : this.#e.getBoundingClientRect();
|
|
129
|
-
this.#r && this.#
|
|
132
|
+
this.#r && this.#C(n.width, n.height);
|
|
133
|
+
let r = n.width > 0 || n.height > 0;
|
|
134
|
+
this.#l && r && this.#g(n.width, n.height) && (this.#m(), this.#_(this.#n ?? 0, this.#t ?? 0));
|
|
130
135
|
}), this.#f.observe(this.#e);
|
|
131
136
|
}
|
|
132
|
-
#
|
|
137
|
+
#x() {
|
|
133
138
|
this.#f?.disconnect(), this.#f = null;
|
|
134
139
|
}
|
|
135
|
-
#
|
|
136
|
-
#
|
|
140
|
+
#S = !1;
|
|
141
|
+
#C(e, t) {
|
|
137
142
|
let n = this.#e.style;
|
|
138
|
-
if (!this.#
|
|
143
|
+
if (!this.#S) {
|
|
139
144
|
let e = getComputedStyle(this.#e).display;
|
|
140
145
|
if (e) {
|
|
141
146
|
let t = d[e];
|
|
142
|
-
t && (n.display = t), this.#
|
|
147
|
+
t && (n.display = t), this.#S = !0;
|
|
143
148
|
}
|
|
144
149
|
}
|
|
145
150
|
n.margin = `0 ${-e}px ${-t}px 0`;
|
package/dist/shell/alert.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The Finder's alert: a plain-framed `vf-dialog` with the site's caution art,
|
|
3
3
|
* a message and a row of buttons, sized to the message — composed from kit
|
|
4
|
-
* elements, as every alert in the kit is.
|
|
4
|
+
* elements, as every alert in the kit is. Its buttons submit a
|
|
5
|
+
* `<form method="dialog">`, so it answers with the pressed button's `value`
|
|
6
|
+
* like any dialog an application holds.
|
|
5
7
|
*
|
|
6
8
|
* The layout follows the plain frame's body, its width and height less 10:
|
|
7
9
|
* the art and the message 16 in from the body's top-left, the buttons'
|
|
8
10
|
* bottom-right corner 16 in from the body's.
|
|
9
11
|
*/
|
|
12
|
+
import type { VfDialog } from '../index.js';
|
|
10
13
|
/** One button of an alert. */
|
|
11
14
|
export interface AlertButton {
|
|
12
15
|
label: string;
|
|
13
|
-
/** What the alert
|
|
16
|
+
/** What the alert answers when it is pressed. */
|
|
14
17
|
value: string;
|
|
15
18
|
/** The default button, which Return presses. */
|
|
16
19
|
default?: boolean;
|
|
@@ -20,13 +23,18 @@ export interface AlertOptions {
|
|
|
20
23
|
buttons?: AlertButton[];
|
|
21
24
|
/** The dialog's width, system px. Default 400. */
|
|
22
25
|
width?: number;
|
|
23
|
-
/** The 32×32 art beside the message
|
|
26
|
+
/** The 32×32 art beside the message, or null for none. */
|
|
24
27
|
art?: string | null;
|
|
25
28
|
/** The dialog's accessible name. Default "Alert". */
|
|
26
29
|
label?: string;
|
|
27
30
|
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*/
|
|
32
|
-
|
|
31
|
+
/** An alert, made but not yet shown. */
|
|
32
|
+
export interface ComposedAlert {
|
|
33
|
+
dialog: VfDialog;
|
|
34
|
+
/** Resolves once its parts have rendered, so `show()` opens it at once. Call it once the dialog is in the page. */
|
|
35
|
+
rendered(): Promise<unknown>;
|
|
36
|
+
/** Size the box to the message. Call it right after `show()`: a closed dialog lays out nothing. */
|
|
37
|
+
fit(): void;
|
|
38
|
+
}
|
|
39
|
+
/** Make an alert for `message`. */
|
|
40
|
+
export declare function composeAlert(message: string, options?: AlertOptions): ComposedAlert;
|
package/dist/shell/alert.js
CHANGED
|
@@ -2,43 +2,40 @@ import { effectiveScale as e } from "../scale.js";
|
|
|
2
2
|
import "../index.js";
|
|
3
3
|
//#region src/shell/alert.ts
|
|
4
4
|
var t = 10, n = 16, r = 32, i = 28;
|
|
5
|
-
|
|
6
|
-
let { buttons:
|
|
5
|
+
function a(a, o = {}) {
|
|
6
|
+
let { buttons: s = [{
|
|
7
7
|
label: "OK",
|
|
8
8
|
value: "ok",
|
|
9
9
|
default: !0
|
|
10
|
-
}], width:
|
|
11
|
-
|
|
12
|
-
let
|
|
13
|
-
|
|
10
|
+
}], width: c = 400, art: l = null, label: u = "Alert" } = o, d = document.createElement("vf-dialog");
|
|
11
|
+
d.frame = "plain", d.label = u, d.width = c, d.height = 120;
|
|
12
|
+
let f = document.createElement("form");
|
|
13
|
+
f.method = "dialog", f.noValidate = !0;
|
|
14
|
+
let p = l ? 64 : n;
|
|
15
|
+
if (l) {
|
|
14
16
|
let e = document.createElement("vf-img");
|
|
15
17
|
e.width = r, e.height = r, e.left = n, e.top = n;
|
|
16
18
|
let t = document.createElement("img");
|
|
17
|
-
t.src =
|
|
19
|
+
t.src = l, t.alt = "", e.append(t), f.append(e);
|
|
18
20
|
}
|
|
19
21
|
let m = document.createElement("vf-paragraph");
|
|
20
|
-
m.face = "display", m.width =
|
|
22
|
+
m.face = "display", m.width = c - t - p - n, m.left = p, m.top = n, m.textContent = a, f.append(m);
|
|
21
23
|
let h = document.createElement("vf-button-group");
|
|
22
|
-
h.origin = "bottom right"
|
|
23
|
-
let g = c.map((e) => {
|
|
24
|
+
return h.origin = "bottom right", h.append(...s.map((e) => {
|
|
24
25
|
let t = document.createElement("vf-button");
|
|
25
|
-
return t.textContent = e.label, t.
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
f.addEventListener("vf-close", () => {
|
|
39
|
-
f.remove(), e(t);
|
|
40
|
-
}, { once: !0 }), f.show();
|
|
41
|
-
});
|
|
26
|
+
return t.textContent = e.label, t.type = "submit", t.value = e.value, e.default && (t.variant = "default"), t;
|
|
27
|
+
})), f.append(h), d.append(f), {
|
|
28
|
+
dialog: d,
|
|
29
|
+
rendered: () => Promise.all([
|
|
30
|
+
d.updateComplete,
|
|
31
|
+
m.updateComplete,
|
|
32
|
+
h.updateComplete
|
|
33
|
+
]),
|
|
34
|
+
fit() {
|
|
35
|
+
let r = Math.ceil(m.getBoundingClientRect().height / e(m)), a = Math.max(l ? 48 : 0, n + r) + n + i + n;
|
|
36
|
+
d.height = a + t, h.left = c - t - n, h.top = a - n;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
42
39
|
}
|
|
43
40
|
//#endregion
|
|
44
|
-
export { a as
|
|
41
|
+
export { a as composeAlert };
|
package/dist/shell/finder.d.ts
CHANGED
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
* View (Arrange Windows), Special (Clean Up, Empty Trash…), each disabled
|
|
24
24
|
* while it has nothing to act on. A site switches commands off and adds
|
|
25
25
|
* its own.
|
|
26
|
+
* - Alerts are the Finder's own, composed with the site's caution art and
|
|
27
|
+
* held by it while they are up. A site answers any of them with its own
|
|
28
|
+
* dialog through `alertWith`.
|
|
26
29
|
*/
|
|
27
30
|
import type { VfIcon, VfMenuItem, VfViewportBox } from '../index.js';
|
|
28
31
|
import type { Catalog, CatalogStorage, Item, Volumes } from './catalog.js';
|
|
@@ -43,7 +46,40 @@ export interface FinderArt {
|
|
|
43
46
|
disk?: string;
|
|
44
47
|
/** 12×12: the mark before the item count in the Trash's window and trashed folders. */
|
|
45
48
|
trashMark?: string;
|
|
49
|
+
/** 32×32: beside the message in the Finder's alerts. Without it they have no art. */
|
|
50
|
+
caution?: string;
|
|
46
51
|
}
|
|
52
|
+
/** What a failed command was, in the `failed` alert. */
|
|
53
|
+
export type FinderFailedAction = 'new-folder' | 'empty-trash' | 'paste' | 'add-file';
|
|
54
|
+
/** The Finder's alerts, by id, with the details each one's handler gets. */
|
|
55
|
+
export interface FinderAlerts {
|
|
56
|
+
/** Special → Empty Trash…: an answer of `'ok'` empties the Trash. */
|
|
57
|
+
'empty-trash': {
|
|
58
|
+
count: number;
|
|
59
|
+
bytes: number;
|
|
60
|
+
};
|
|
61
|
+
/** New Folder, Paste or a dropped file, without storage. */
|
|
62
|
+
'storage-unavailable': Record<string, never>;
|
|
63
|
+
/** A rename past the limit. */
|
|
64
|
+
'name-too-long': {
|
|
65
|
+
limit: number;
|
|
66
|
+
};
|
|
67
|
+
/** A rename to nothing. */
|
|
68
|
+
'name-rejected': Record<string, never>;
|
|
69
|
+
/** A filing storage refused. */
|
|
70
|
+
'move-failed': {
|
|
71
|
+
error: Error;
|
|
72
|
+
};
|
|
73
|
+
/** New Folder, Empty Trash, Paste or a dropped file failed. */
|
|
74
|
+
failed: {
|
|
75
|
+
action: FinderFailedAction;
|
|
76
|
+
error: Error;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** One of the Finder's alerts. */
|
|
80
|
+
export type FinderAlert = keyof FinderAlerts;
|
|
81
|
+
/** Answers one of the Finder's alerts: resolves the answer, or null. */
|
|
82
|
+
export type FinderAlertHandler<K extends FinderAlert> = (details: FinderAlerts[K]) => string | null | Promise<string | null>;
|
|
47
83
|
/** The Finder's own commands, each of which a site can switch off. */
|
|
48
84
|
export type FinderCommand = 'open' | 'new-folder' | 'close' | 'copy' | 'paste' | 'select-all' | 'arrange' | 'clean-up' | 'empty-trash';
|
|
49
85
|
/** The Finder's menus, by `data-menu`. */
|
|
@@ -85,6 +121,8 @@ export interface FinderApi {
|
|
|
85
121
|
iconFor(id: string): VfIcon | null;
|
|
86
122
|
/** Add a command to the Finder's menus. Call it from `extend`, before the menus first reach the bar. */
|
|
87
123
|
addCommand(spec: FinderCommandSpec): VfMenuItem;
|
|
124
|
+
/** Answer one of the Finder's alerts with the site's own dialog. Call it from `extend`. */
|
|
125
|
+
alertWith<K extends FinderAlert>(id: K, handler: FinderAlertHandler<K>): void;
|
|
88
126
|
}
|
|
89
127
|
export interface FinderOptions {
|
|
90
128
|
/** Where the catalog is kept: `memoryStorage()`, `indexedDbStorage(name)`, the site's own, or null for nothing. */
|
|
@@ -107,7 +145,9 @@ export interface FinderOptions {
|
|
|
107
145
|
cleanUpAfterResize?: boolean;
|
|
108
146
|
/** Switch commands off: `{ 'empty-trash': false }`. */
|
|
109
147
|
commands?: Partial<Record<FinderCommand, boolean>>;
|
|
110
|
-
/**
|
|
148
|
+
/** The site's dialogs for the Finder, each with a `data-dialog` name, held by it: `ctx.dialog(name)` in `extend`. */
|
|
149
|
+
dialogs?: string;
|
|
150
|
+
/** Add the site's own commands, and answer the Finder's alerts. */
|
|
111
151
|
extend?(finder: FinderApi, ctx: AppContext): void;
|
|
112
152
|
/** A folder window's size, system px. Default 320 × 223: three columns and two rows of icons. */
|
|
113
153
|
window?: Size;
|