vintage-frames 0.6.1 → 0.7.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 +1257 -172
- package/dist/components/vf-desktop.d.ts +34 -0
- package/dist/components/vf-desktop.js +66 -43
- package/dist/components/vf-dialog.d.ts +9 -0
- package/dist/components/vf-icon-field.d.ts +144 -0
- package/dist/components/vf-icon-field.js +173 -0
- package/dist/components/vf-icon.d.ts +196 -6
- package/dist/components/vf-icon.js +374 -122
- package/dist/components/vf-number-field.js +1 -1
- package/dist/components/vf-scroll-area.d.ts +25 -6
- package/dist/components/vf-scroll-area.js +34 -28
- package/dist/components/vf-text-field.d.ts +2 -1
- package/dist/components/vf-text-field.js +1 -1
- package/dist/components/vf-window.d.ts +24 -0
- package/dist/components/vf-window.js +66 -59
- package/dist/drag.d.ts +28 -4
- package/dist/drag.js +15 -6
- package/dist/index.d.ts +2 -1
- package/dist/index.js +13 -12
- package/dist/modal-dialog.d.ts +33 -0
- package/dist/modal-dialog.js +66 -36
- package/dist/open-art.d.ts +60 -1
- package/dist/open-art.js +47 -1
- package/dist/position.d.ts +35 -0
- package/dist/position.js +63 -45
- package/dist/text-control.d.ts +8 -1
- package/dist/text-control.js +2 -7
- package/docs/SPEC.md +26 -10
- package/editor/vscode.html-custom-data.json +51 -4
- package/editor/web-types.json +133 -5
- package/package.json +2 -1
package/dist/modal-dialog.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ export declare const modalDialogStyles: import("lit").CSSResult;
|
|
|
32
32
|
* event, an Escape-close no longer leaves a stale origin behind, so the next
|
|
33
33
|
* open re-derives it.
|
|
34
34
|
*
|
|
35
|
+
* It also owns the two keyboard rules every classic dialog followed (see
|
|
36
|
+
* {@link defaultButton} and {@link initialFocusTarget}): Return or Enter
|
|
37
|
+
* activates the default button from anywhere in the dialog, and the box opens
|
|
38
|
+
* with the insertion point in its first text field — or, with none, focus on
|
|
39
|
+
* the default button.
|
|
40
|
+
*
|
|
35
41
|
* Removing an open modal from the DOM is a close path too. HTML's dialog
|
|
36
42
|
* *removing steps* take the element out of the top layer **without** running
|
|
37
43
|
* the close algorithm — no `close` event, no focus restoration — which is
|
|
@@ -124,6 +130,33 @@ export declare class VfModalDialog extends LitElement {
|
|
|
124
130
|
* drag from squeezing the box.
|
|
125
131
|
*/
|
|
126
132
|
protected get dialogSize(): Record<string, string | null>;
|
|
133
|
+
/**
|
|
134
|
+
* The dialog's default button — the one wearing the bold ring
|
|
135
|
+
* (`vf-button[variant="default"]`) — or null with none, or none enabled.
|
|
136
|
+
* Looked for among the slotted content first, then in the shadow tree, so a
|
|
137
|
+
* consumer's own modal that renders its buttons itself is covered too.
|
|
138
|
+
* Override to name it some other way.
|
|
139
|
+
*/
|
|
140
|
+
protected get defaultButton(): HTMLElement | null;
|
|
141
|
+
/**
|
|
142
|
+
* Where focus lands on open. The classic Dialog Manager put the insertion
|
|
143
|
+
* point in the first editable text item and gave nothing else focus at all;
|
|
144
|
+
* the web needs a focused control for the keyboard to have anywhere to be,
|
|
145
|
+
* so with no text field the default button takes it (which is also what
|
|
146
|
+
* makes Return and Space work there without a Tab). In order:
|
|
147
|
+
*
|
|
148
|
+
* 1. a slotted control carrying `autofocus` — the author's say;
|
|
149
|
+
* 2. the first enabled text-entry control (`vf-text-field`,
|
|
150
|
+
* `vf-number-field`, `vf-text-area`, or a native text input/textarea);
|
|
151
|
+
* 3. the {@link defaultButton};
|
|
152
|
+
* 4. null — leave the browser's own choice alone.
|
|
153
|
+
*
|
|
154
|
+
* Left to itself, `showModal()` focuses the first focusable thing in flat
|
|
155
|
+
* tree order, which for a Cancel/OK row is Cancel, and for a body with a
|
|
156
|
+
* link in it is the link — so Return did the one thing a classic dialog's
|
|
157
|
+
* Return never did. Override to choose differently.
|
|
158
|
+
*/
|
|
159
|
+
protected get initialFocusTarget(): HTMLElement | null;
|
|
127
160
|
/** Open the modal (native `showModal()`), pinned onto the device grid. */
|
|
128
161
|
show(): void;
|
|
129
162
|
/** Close the modal. Fires `vf-close` with `{ reason: 'close' }`. */
|
package/dist/modal-dialog.js
CHANGED
|
@@ -4,7 +4,15 @@ import o from "./_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js"
|
|
|
4
4
|
import { DocumentListenersController as s } from "./document-listeners.js";
|
|
5
5
|
import { LitElement as c, css as l } from "lit";
|
|
6
6
|
import { property as u, query as d } from "lit/decorators.js";
|
|
7
|
-
var f = 24, p =
|
|
7
|
+
var f = 24, p = /* @__PURE__ */ new Set([
|
|
8
|
+
"text",
|
|
9
|
+
"search",
|
|
10
|
+
"url",
|
|
11
|
+
"tel",
|
|
12
|
+
"email",
|
|
13
|
+
"password",
|
|
14
|
+
"number"
|
|
15
|
+
]), m = (e) => e instanceof HTMLInputElement ? p.has(e.type) : !0, h = l`
|
|
8
16
|
dialog {
|
|
9
17
|
padding: 0;
|
|
10
18
|
margin: auto;
|
|
@@ -43,32 +51,43 @@ var f = 24, p = l`
|
|
|
43
51
|
the fallback is the arrow it always showed. */
|
|
44
52
|
cursor: var(--vf-cursor, default);
|
|
45
53
|
}
|
|
46
|
-
`,
|
|
54
|
+
`, g = class extends c {
|
|
47
55
|
constructor(...e) {
|
|
48
56
|
super(...e), this.scale = new t(this), this.open = !1, this.lightDismiss = !1, this.#e = !1, this.#n = null, this.#r = null, this.#i = new s(this, () => [
|
|
49
57
|
[
|
|
50
58
|
this._dialog,
|
|
51
59
|
"pointerdown",
|
|
52
|
-
this.#
|
|
60
|
+
this.#s
|
|
53
61
|
],
|
|
54
62
|
[
|
|
55
63
|
this._dialog,
|
|
56
64
|
"pointerup",
|
|
57
|
-
this.#
|
|
65
|
+
this.#c
|
|
58
66
|
],
|
|
59
67
|
[
|
|
60
68
|
this._dialog,
|
|
61
69
|
"pointercancel",
|
|
62
|
-
this.#
|
|
70
|
+
this.#l
|
|
71
|
+
],
|
|
72
|
+
[
|
|
73
|
+
this._dialog,
|
|
74
|
+
"keydown",
|
|
75
|
+
this.#o
|
|
63
76
|
]
|
|
64
|
-
]), this.#
|
|
77
|
+
]), this.#o = (e) => {
|
|
78
|
+
if (e.key !== "Enter" || e.defaultPrevented || e.isComposing || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
79
|
+
let t = e.composedPath();
|
|
80
|
+
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
|
+
let n = this.defaultButton;
|
|
82
|
+
n && (e.preventDefault(), n.click());
|
|
83
|
+
}, this.#s = (e) => {
|
|
65
84
|
this.#r = e.target === this._dialog ? e.pointerId : null;
|
|
66
|
-
}, this.#
|
|
85
|
+
}, this.#c = (e) => {
|
|
67
86
|
let t = this.#r === e.pointerId;
|
|
68
87
|
this.#r = null, !(!t || e.target !== this._dialog || !this.lightDismiss) && (this.#n = "outside", this.close());
|
|
69
|
-
}, this.#
|
|
88
|
+
}, this.#l = () => {
|
|
70
89
|
this.#r = null;
|
|
71
|
-
}, this.#
|
|
90
|
+
}, this.#u = null, this.#g = () => this.settle();
|
|
72
91
|
}
|
|
73
92
|
get dialogSize() {
|
|
74
93
|
return {
|
|
@@ -88,42 +107,53 @@ var f = 24, p = l`
|
|
|
88
107
|
#n;
|
|
89
108
|
#r;
|
|
90
109
|
#i;
|
|
91
|
-
|
|
110
|
+
get defaultButton() {
|
|
111
|
+
let e = "vf-button[variant=\"default\"]";
|
|
112
|
+
return [...this.querySelectorAll(e), ...this.renderRoot.querySelectorAll(e)].find((e) => !e.matches(":disabled")) ?? null;
|
|
113
|
+
}
|
|
114
|
+
get initialFocusTarget() {
|
|
115
|
+
return this.querySelector("[autofocus]") || ([...this.querySelectorAll("vf-text-field, vf-number-field, vf-text-area, textarea, input")].find((e) => m(e) && !e.matches(":disabled")) ?? this.defaultButton);
|
|
116
|
+
}
|
|
117
|
+
#a() {
|
|
118
|
+
this.initialFocusTarget?.focus();
|
|
119
|
+
}
|
|
92
120
|
#o;
|
|
93
121
|
#s;
|
|
94
122
|
#c;
|
|
123
|
+
#l;
|
|
124
|
+
#u;
|
|
95
125
|
show() {
|
|
96
|
-
this.open = !0, this.hasUpdated && this.#
|
|
126
|
+
this.open = !0, this.hasUpdated && this.#h();
|
|
97
127
|
}
|
|
98
128
|
close() {
|
|
99
|
-
this.open = !1, this.hasUpdated && this.#
|
|
129
|
+
this.open = !1, this.hasUpdated && this.#h();
|
|
100
130
|
}
|
|
101
131
|
updated(e) {
|
|
102
|
-
e.has("open") && this.#
|
|
132
|
+
e.has("open") && this.#h(), (e.has("top") || e.has("left")) && this.settle(), this.#t();
|
|
103
133
|
}
|
|
104
|
-
#
|
|
134
|
+
#d() {
|
|
105
135
|
let e = document.documentElement;
|
|
106
136
|
return {
|
|
107
137
|
width: a(e.clientWidth || window.innerWidth, this),
|
|
108
138
|
height: a(e.clientHeight || window.innerHeight, this)
|
|
109
139
|
};
|
|
110
140
|
}
|
|
111
|
-
#
|
|
112
|
-
let n = this.#
|
|
141
|
+
#f(e, t) {
|
|
142
|
+
let n = this.#d(), r = a(this._dialog?.offsetWidth ?? 0, this);
|
|
113
143
|
return {
|
|
114
144
|
x: Math.min(Math.max(e, f - r), n.width - f),
|
|
115
145
|
y: Math.min(Math.max(t, 0), Math.max(0, n.height - f))
|
|
116
146
|
};
|
|
117
147
|
}
|
|
118
|
-
#
|
|
119
|
-
let e = this.#
|
|
148
|
+
#p() {
|
|
149
|
+
let e = this.#d(), t = this._dialog?.getBoundingClientRect();
|
|
120
150
|
return {
|
|
121
151
|
x: (e.width - a(t?.width ?? 0, this)) / 2,
|
|
122
152
|
y: (e.height - a(t?.height ?? 0, this)) / 2
|
|
123
153
|
};
|
|
124
154
|
}
|
|
125
155
|
placeAt(e, t) {
|
|
126
|
-
let n = this.#
|
|
156
|
+
let n = this.#f(e, t);
|
|
127
157
|
this.left = r(n.x, this), this.top = r(n.y, this);
|
|
128
158
|
}
|
|
129
159
|
settle() {
|
|
@@ -132,10 +162,10 @@ var f = 24, p = l`
|
|
|
132
162
|
let t = this.left != null || this.top != null ? {
|
|
133
163
|
x: this.left ?? 0,
|
|
134
164
|
y: this.top ?? 0
|
|
135
|
-
} : this.#
|
|
165
|
+
} : this.#p(), n = this.#f(t.x, t.y);
|
|
136
166
|
e.style.left = i(r(n.x, this)), e.style.top = i(r(n.y, this)), e.style.right = "auto", e.style.bottom = "auto", e.style.margin = "0";
|
|
137
167
|
}
|
|
138
|
-
#
|
|
168
|
+
#m() {
|
|
139
169
|
let e = this._dialog?.style;
|
|
140
170
|
if (e) for (let t of [
|
|
141
171
|
"left",
|
|
@@ -145,44 +175,44 @@ var f = 24, p = l`
|
|
|
145
175
|
"margin"
|
|
146
176
|
]) e.removeProperty(t);
|
|
147
177
|
}
|
|
148
|
-
#
|
|
178
|
+
#h() {
|
|
149
179
|
let e = this._dialog;
|
|
150
|
-
e && (this.open && !e.open ? (this.#
|
|
180
|
+
e && (this.open && !e.open ? (this.#u = document.activeElement, e.showModal(), this.#a(), this.settle(), this.#y(e), this.#i.attach()) : !this.open && e.open && e.close());
|
|
151
181
|
}
|
|
152
|
-
#m;
|
|
153
|
-
#h;
|
|
154
182
|
#g;
|
|
155
|
-
#_
|
|
156
|
-
|
|
183
|
+
#_;
|
|
184
|
+
#v;
|
|
185
|
+
#y(e) {
|
|
186
|
+
typeof ResizeObserver < "u" && !this.#_ && (this.#_ = new ResizeObserver(this.#g), this.#_.observe(e)), window.addEventListener("resize", this.#g), this.#v ??= n(this.#g);
|
|
157
187
|
}
|
|
158
|
-
#
|
|
159
|
-
this.#
|
|
188
|
+
#b() {
|
|
189
|
+
this.#_?.disconnect(), this.#_ = void 0, window.removeEventListener("resize", this.#g), this.#v?.(), this.#v = void 0;
|
|
160
190
|
}
|
|
161
191
|
disconnectedCallback() {
|
|
162
|
-
super.disconnectedCallback(), this.#
|
|
192
|
+
super.disconnectedCallback(), this.#b();
|
|
163
193
|
let e = this._dialog;
|
|
164
194
|
if (e?.open) {
|
|
165
195
|
e.close();
|
|
166
|
-
let t = this.#
|
|
196
|
+
let t = this.#u, n = document.activeElement;
|
|
167
197
|
t instanceof HTMLElement && t.isConnected && (n === null || n === document.body) && t.focus();
|
|
168
198
|
}
|
|
169
|
-
this.#
|
|
199
|
+
this.#u = null;
|
|
170
200
|
}
|
|
171
201
|
_onNativeCancel() {
|
|
172
202
|
this.#n = "escape";
|
|
173
203
|
}
|
|
174
204
|
_onNativeClose() {
|
|
175
205
|
let t = this.#n ?? "close";
|
|
176
|
-
this.#n = null, this.#
|
|
206
|
+
this.#n = null, this.#u = null, this.#r = null, this.#i.detach(), this.#b(), this.open = !1, this.#m(), e(this, "vf-close", { reason: t });
|
|
177
207
|
}
|
|
178
208
|
};
|
|
179
209
|
o([u({
|
|
180
210
|
type: Boolean,
|
|
181
211
|
reflect: !0
|
|
182
|
-
})],
|
|
212
|
+
})], g.prototype, "open", void 0), o([u({ type: Number })], g.prototype, "width", void 0), o([u({ type: Number })], g.prototype, "height", void 0), o([u({ type: Number })], g.prototype, "top", void 0), o([u({ type: Number })], g.prototype, "left", void 0), o([u({
|
|
183
213
|
type: Boolean,
|
|
184
214
|
reflect: !0,
|
|
185
215
|
attribute: "light-dismiss"
|
|
186
|
-
})],
|
|
216
|
+
})], g.prototype, "lightDismiss", void 0), o([d("dialog")], g.prototype, "_dialog", void 0);
|
|
187
217
|
//#endregion
|
|
188
|
-
export {
|
|
218
|
+
export { g as VfModalDialog, h as modalDialogStyles };
|
package/dist/open-art.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The Finder "open" ghost — an icon's art redrawn as outline plus dither,
|
|
3
|
-
* derived from the art itself in the client
|
|
3
|
+
* derived from the art itself in the client — and, on the same terms, the
|
|
4
|
+
* dotted outline an icon drags as ({@link deriveDragOutline}).
|
|
4
5
|
*
|
|
5
6
|
* When a folder or application is open, the Finder redraws its icon as a
|
|
6
7
|
* ghost: the outline stays, and everything inside it becomes pattern. The kit
|
|
@@ -38,3 +39,61 @@
|
|
|
38
39
|
* an environment refusing a 2d context.
|
|
39
40
|
*/
|
|
40
41
|
export declare function deriveOpenArt(art: HTMLImageElement | HTMLCanvasElement): HTMLCanvasElement | null;
|
|
42
|
+
/** A box inside an icon's frame, in system px. */
|
|
43
|
+
export interface DragOutlineBox {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
width: number;
|
|
47
|
+
height: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Where an icon's parts sit inside its frame, in system px — measured by the
|
|
51
|
+
* icon, so the outline lands on the same pixels the frame paints.
|
|
52
|
+
*/
|
|
53
|
+
export interface DragOutlineGeometry {
|
|
54
|
+
/** The frame. */
|
|
55
|
+
width: number;
|
|
56
|
+
height: number;
|
|
57
|
+
/**
|
|
58
|
+
* The art's own box, where it paints. Null when the pipeline has nothing
|
|
59
|
+
* to draw — nothing slotted, a failed load, an inline `<svg>` — and the
|
|
60
|
+
* cell's rectangle stands in.
|
|
61
|
+
*/
|
|
62
|
+
art: DragOutlineBox | null;
|
|
63
|
+
/** The reserved art cell. */
|
|
64
|
+
cell: DragOutlineBox;
|
|
65
|
+
/** The name plate, or null with no name. */
|
|
66
|
+
plate: DragOutlineBox | null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Derive the outline an icon drags as: the mask's boundary — the same
|
|
70
|
+
* one-pixel ring the open ghost finds, by the same erosion — and the name
|
|
71
|
+
* plate's rectangle, solid black on transparent, one canvas the size of the
|
|
72
|
+
* icon's frame at one image px per system px. Not yet dotted: the ring is
|
|
73
|
+
* derived once per drag, and {@link dotOutline} re-applies the checker at
|
|
74
|
+
* each step's phase.
|
|
75
|
+
*
|
|
76
|
+
* Art the pipeline cannot draw falls back to the cell's rectangle — the
|
|
77
|
+
* ghost's rule: never a blank where a state cannot show. Compositing only,
|
|
78
|
+
* never a readback, so cross-origin art derives too.
|
|
79
|
+
*
|
|
80
|
+
* Returns null for a frame with no size, or an environment refusing a 2d
|
|
81
|
+
* context.
|
|
82
|
+
*/
|
|
83
|
+
export declare function deriveDragOutline(art: HTMLImageElement | HTMLCanvasElement | null, geometry: DragOutlineGeometry): HTMLCanvasElement | null;
|
|
84
|
+
/**
|
|
85
|
+
* Paint a selection rectangle — the rubber band `vf-icon-field` drags on its
|
|
86
|
+
* background — into `into`: a one-pixel outline `width` × `height` system px,
|
|
87
|
+
* dotted at `phase` the way the drag outline is. A degenerate axis paints as
|
|
88
|
+
* a one-pixel line rather than nothing.
|
|
89
|
+
*/
|
|
90
|
+
export declare function paintSelectionRect(into: HTMLCanvasElement, width: number, height: number, phase: number): void;
|
|
91
|
+
/**
|
|
92
|
+
* Paint `ring` into `into` dotted with the checker at `phase` — 0 keeps the
|
|
93
|
+
* dots where `x + y` is even in the canvas's own coordinates, 1 where it is
|
|
94
|
+
* odd. The caller picks the phase from where the outline lands on screen,
|
|
95
|
+
* so the dots share the desktop dither's phase wherever the outline goes,
|
|
96
|
+
* as QuickDraw's screen-anchored pattern pen did. Sizing `into` to the ring
|
|
97
|
+
* clears it, so each step is a fresh paint.
|
|
98
|
+
*/
|
|
99
|
+
export declare function dotOutline(ring: HTMLCanvasElement, into: HTMLCanvasElement, phase: number): void;
|
package/dist/open-art.js
CHANGED
|
@@ -31,5 +31,51 @@ function r(t) {
|
|
|
31
31
|
let c = o.ctx.createPattern(s, "repeat");
|
|
32
32
|
return c && (o.ctx.globalCompositeOperation = "source-atop", o.ctx.fillStyle = c, o.ctx.fillRect(0, 0, r, i)), a.ctx.globalCompositeOperation = "source-over", a.ctx.drawImage(o.canvas, 0, 0), a.canvas;
|
|
33
33
|
}
|
|
34
|
+
var i = null, a = () => {
|
|
35
|
+
if (!i) {
|
|
36
|
+
let t = e(2, 2);
|
|
37
|
+
if (!t) return null;
|
|
38
|
+
t.ctx.fillStyle = "#000", t.ctx.fillRect(0, 0, 1, 1), t.ctx.fillRect(1, 1, 1, 1), i = t.canvas;
|
|
39
|
+
}
|
|
40
|
+
return i;
|
|
41
|
+
}, o = (e, t) => {
|
|
42
|
+
t.width <= 0 || t.height <= 0 || (e.fillStyle = "#000", e.fillRect(t.x, t.y, t.width, t.height), t.width > 2 && t.height > 2 && e.clearRect(t.x + 1, t.y + 1, t.width - 2, t.height - 2));
|
|
43
|
+
};
|
|
44
|
+
function s(t, n) {
|
|
45
|
+
let { width: r, height: i } = n;
|
|
46
|
+
if (!r || !i) return null;
|
|
47
|
+
let a = e(r, i);
|
|
48
|
+
if (!a) return null;
|
|
49
|
+
let s = t ? n.art : null;
|
|
50
|
+
if (t && s && s.width > 0 && s.height > 0) {
|
|
51
|
+
let n = e(r, i), o = e(r, i);
|
|
52
|
+
if (!n || !o) return null;
|
|
53
|
+
n.ctx.drawImage(t, s.x, s.y, s.width, s.height), n.ctx.globalCompositeOperation = "source-in", n.ctx.fillStyle = "#000", n.ctx.fillRect(0, 0, r, i), o.ctx.drawImage(n.canvas, 0, 0), o.ctx.globalCompositeOperation = "destination-in";
|
|
54
|
+
for (let [e, t] of [
|
|
55
|
+
[1, 0],
|
|
56
|
+
[-1, 0],
|
|
57
|
+
[0, 1],
|
|
58
|
+
[0, -1]
|
|
59
|
+
]) o.ctx.drawImage(n.canvas, e, t);
|
|
60
|
+
a.ctx.drawImage(n.canvas, 0, 0), a.ctx.globalCompositeOperation = "destination-out", a.ctx.drawImage(o.canvas, 0, 0), a.ctx.globalCompositeOperation = "source-over";
|
|
61
|
+
} else o(a.ctx, n.cell);
|
|
62
|
+
return n.plate && o(a.ctx, n.plate), a.canvas;
|
|
63
|
+
}
|
|
64
|
+
function c(t, n, r, i) {
|
|
65
|
+
let a = Math.max(1, Math.round(n)), s = Math.max(1, Math.round(r)), c = e(a, s);
|
|
66
|
+
c && (o(c.ctx, {
|
|
67
|
+
x: 0,
|
|
68
|
+
y: 0,
|
|
69
|
+
width: a,
|
|
70
|
+
height: s
|
|
71
|
+
}), l(c.canvas, t, i));
|
|
72
|
+
}
|
|
73
|
+
function l(e, t, n) {
|
|
74
|
+
let r = a(), i = t.getContext("2d");
|
|
75
|
+
if (!r || !i) return;
|
|
76
|
+
t.width = e.width, t.height = e.height, i.imageSmoothingEnabled = !1, i.drawImage(e, 0, 0);
|
|
77
|
+
let o = i.createPattern(r, "repeat");
|
|
78
|
+
o && (i.globalCompositeOperation = "destination-in", i.fillStyle = o, i.translate(n & 1, 0), i.fillRect(-2, 0, e.width + 2, e.height), i.setTransform(1, 0, 0, 1, 0, 0), i.globalCompositeOperation = "source-over");
|
|
79
|
+
}
|
|
34
80
|
//#endregion
|
|
35
|
-
export { r as deriveOpenArt };
|
|
81
|
+
export { s as deriveDragOutline, r as deriveOpenArt, l as dotOutline, c as paintSelectionRect };
|
package/dist/position.d.ts
CHANGED
|
@@ -84,6 +84,16 @@ type PositionedHost = HTMLElement & {
|
|
|
84
84
|
* unrelated update — a heading change, a desktop toggling `active` — never
|
|
85
85
|
* re-asserts a coordinate and costs nothing.
|
|
86
86
|
*
|
|
87
|
+
* **Every write it makes is announced** as `vf-placement-change` (bubbles,
|
|
88
|
+
* `composed: false`, detail `{ left, top }` — nulls on a return to flow). It
|
|
89
|
+
* is an internal coordination event on the terms of the menu handshakes:
|
|
90
|
+
* parent and child share one light tree, and a kit protocol must not leak out
|
|
91
|
+
* of a consumer's shadow boundary. `vf-scroll-area` listens for it and
|
|
92
|
+
* re-measures, because a placed child moved through `top`/`left` changes the
|
|
93
|
+
* scroll range with no box changing anywhere a ResizeObserver can see — the
|
|
94
|
+
* plane's box is never grown by an absolutely positioned child. One funnel
|
|
95
|
+
* covers a drop, an arrow nudge and a page's own `icon.left = …` alike.
|
|
96
|
+
*
|
|
87
97
|
* **`fixed`** holds the placement against the *visible* region of the nearest
|
|
88
98
|
* scrolling ancestor instead of its scrolled plane — a tool strip over a
|
|
89
99
|
* document, a column header over rows — and the flag alone places at (0,0).
|
|
@@ -103,6 +113,25 @@ type PositionedHost = HTMLElement & {
|
|
|
103
113
|
* `overflow: hidden`) holds it exactly where placement would.
|
|
104
114
|
*/
|
|
105
115
|
export declare const VfPositioned: <T extends Constructor<LitElement>>(Base: T) => Constructor<VfPositionedInterface> & T;
|
|
116
|
+
/**
|
|
117
|
+
* A viewport point as a placement in `anchor`'s coordinates: `{ left, top }`
|
|
118
|
+
* in whole system px on the placement lattice, measured from the anchor's
|
|
119
|
+
* box the way a placed child's `top`/`left` are — the unit and lattice a
|
|
120
|
+
* drag lands on, so the result can be written straight to a child's pair.
|
|
121
|
+
*
|
|
122
|
+
* The three containers whose anchor sits in shadow DOM (`vf-window`'s
|
|
123
|
+
* content region, `vf-desktop`'s screen, `vf-scroll-area`'s plane) expose it
|
|
124
|
+
* as `placementAt(clientX, clientY)`; everywhere else the anchor is the
|
|
125
|
+
* element's own padding box, and `toSysExact` against
|
|
126
|
+
* `getBoundingClientRect()` is the documented conversion. The anchor is
|
|
127
|
+
* expected to carry no border of its own (the three do not), so its border
|
|
128
|
+
* box is its padding box; `scaleAt` is the element whose `--vf-scale` the
|
|
129
|
+
* conversion reads — the component's host.
|
|
130
|
+
*/
|
|
131
|
+
export declare function placementIn(anchor: Element, clientX: number, clientY: number, scaleAt?: Element): {
|
|
132
|
+
left: number;
|
|
133
|
+
top: number;
|
|
134
|
+
};
|
|
106
135
|
/** The box a gesture is clamped into, in system px — see {@link PlacementClamp}. */
|
|
107
136
|
export type PlacementBounds = {
|
|
108
137
|
width: number;
|
|
@@ -155,6 +184,12 @@ export declare class PlacementController {
|
|
|
155
184
|
constructor(host: PositionedHost, clamp: PlacementClamp);
|
|
156
185
|
/** Whether a gesture has placed this host (as opposed to markup or CSS). */
|
|
157
186
|
get placed(): boolean;
|
|
187
|
+
/**
|
|
188
|
+
* The box the gesture is clamped into, in system px: the one {@link seed}
|
|
189
|
+
* measured, or a fresh measurement before any gesture. A group drag reads
|
|
190
|
+
* it to clamp a whole selection's delta at once.
|
|
191
|
+
*/
|
|
192
|
+
get bounds(): PlacementBounds;
|
|
158
193
|
/**
|
|
159
194
|
* The origin a move adds its delta to, in system px.
|
|
160
195
|
*
|
package/dist/position.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import r from "./
|
|
3
|
-
import
|
|
1
|
+
import { emit as e } from "./events.js";
|
|
2
|
+
import { snapSys as t, sysLength as n, toSysExact as r } from "./scale.js";
|
|
3
|
+
import i from "./_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.js";
|
|
4
|
+
import { property as a } from "lit/decorators.js";
|
|
4
5
|
//#region src/position.ts
|
|
5
|
-
var
|
|
6
|
+
var o = {
|
|
6
7
|
inline: "block",
|
|
7
8
|
"inline-block": "block",
|
|
8
9
|
"inline-flex": "flex",
|
|
9
10
|
"inline-grid": "grid",
|
|
10
11
|
"inline-table": "table"
|
|
11
|
-
},
|
|
12
|
+
}, s = (e) => {
|
|
12
13
|
class t extends e {
|
|
13
14
|
constructor(...e) {
|
|
14
|
-
super(...e), this.fixed = !1, new
|
|
15
|
+
super(...e), this.fixed = !1, new c(this);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
return
|
|
18
|
+
return i([a({ type: Number })], t.prototype, "top", void 0), i([a({ type: Number })], t.prototype, "left", void 0), i([a({
|
|
18
19
|
type: Boolean,
|
|
19
20
|
reflect: !0
|
|
20
21
|
})], t.prototype, "fixed", void 0), t;
|
|
21
|
-
},
|
|
22
|
+
}, c = class {
|
|
22
23
|
#e;
|
|
23
24
|
#t = null;
|
|
24
25
|
#n = null;
|
|
@@ -29,56 +30,70 @@ var a = {
|
|
|
29
30
|
this.#e = e, e.addController(this);
|
|
30
31
|
}
|
|
31
32
|
hostConnected() {
|
|
32
|
-
this.#i && this.#r && this.#
|
|
33
|
+
this.#i && this.#r && this.#l();
|
|
33
34
|
}
|
|
34
35
|
hostDisconnected() {
|
|
35
36
|
this.#a?.disconnect(), this.#a = null;
|
|
36
37
|
}
|
|
37
38
|
hostUpdated() {
|
|
38
|
-
let e = this.#e.top ?? null,
|
|
39
|
-
if (e === null &&
|
|
39
|
+
let e = this.#e.top ?? null, t = this.#e.left ?? null, r = this.#e.fixed === !0, i = this.#e.style;
|
|
40
|
+
if (e === null && t === null && !r) {
|
|
40
41
|
if (!this.#i) return;
|
|
41
|
-
this.#r && this.#
|
|
42
|
+
this.#r && this.#c(), this.#i = !1, this.#r = !1, i.removeProperty("position"), i.removeProperty("top"), i.removeProperty("left"), i.removeProperty("right"), i.removeProperty("bottom"), i.removeProperty("margin"), this.#o(null, null);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
|
-
if (this.#i && e === this.#t &&
|
|
45
|
+
if (this.#i && e === this.#t && t === this.#n && r === this.#r) return;
|
|
45
46
|
let a = this.#i && this.#r;
|
|
46
|
-
this.#i = !0, this.#t = e, this.#n =
|
|
47
|
+
this.#i = !0, this.#t = e, this.#n = t, this.#r = r, i.position = r ? "sticky" : "absolute", i.top = n(e ?? 0), i.left = n(t ?? 0), i.right = "auto", i.bottom = "auto", r ? a || this.#s() : (a && this.#c(), i.margin = "0"), this.#o(t ?? 0, e ?? 0);
|
|
48
|
+
}
|
|
49
|
+
#o(t, n) {
|
|
50
|
+
e(this.#e, "vf-placement-change", {
|
|
51
|
+
left: t,
|
|
52
|
+
top: n
|
|
53
|
+
}, { composed: !1 });
|
|
47
54
|
}
|
|
48
|
-
#
|
|
55
|
+
#s() {
|
|
49
56
|
let e = this.#e.style;
|
|
50
|
-
e.maxWidth = "fit-content", e.zIndex = "1", this.#
|
|
57
|
+
e.maxWidth = "fit-content", e.zIndex = "1", this.#u = !1;
|
|
51
58
|
let t = this.#e.getBoundingClientRect();
|
|
52
|
-
(t.width > 0 || t.height > 0) && this.#
|
|
59
|
+
(t.width > 0 || t.height > 0) && this.#d(t.width, t.height), this.#l();
|
|
53
60
|
}
|
|
54
|
-
#
|
|
55
|
-
this.#a?.disconnect(), this.#a = null, this.#
|
|
61
|
+
#c() {
|
|
62
|
+
this.#a?.disconnect(), this.#a = null, this.#u = !1;
|
|
56
63
|
let e = this.#e.style;
|
|
57
64
|
e.removeProperty("display"), e.removeProperty("max-width"), e.removeProperty("z-index");
|
|
58
65
|
}
|
|
59
|
-
#
|
|
66
|
+
#l() {
|
|
60
67
|
this.#a ??= new ResizeObserver((e) => {
|
|
61
68
|
let t = e[e.length - 1]?.borderBoxSize?.[0];
|
|
62
|
-
if (t) this.#
|
|
69
|
+
if (t) this.#d(t.inlineSize, t.blockSize);
|
|
63
70
|
else {
|
|
64
71
|
let e = this.#e.getBoundingClientRect();
|
|
65
|
-
this.#
|
|
72
|
+
this.#d(e.width, e.height);
|
|
66
73
|
}
|
|
67
74
|
}), this.#a.observe(this.#e);
|
|
68
75
|
}
|
|
69
|
-
#
|
|
70
|
-
#
|
|
76
|
+
#u = !1;
|
|
77
|
+
#d(e, t) {
|
|
71
78
|
let n = this.#e.style;
|
|
72
|
-
if (!this.#
|
|
79
|
+
if (!this.#u) {
|
|
73
80
|
let e = getComputedStyle(this.#e).display;
|
|
74
81
|
if (e) {
|
|
75
|
-
let t =
|
|
76
|
-
t && (n.display = t), this.#
|
|
82
|
+
let t = o[e];
|
|
83
|
+
t && (n.display = t), this.#u = !0;
|
|
77
84
|
}
|
|
78
85
|
}
|
|
79
86
|
n.margin = `0 ${-e}px ${-t}px 0`;
|
|
80
87
|
}
|
|
81
|
-
}
|
|
88
|
+
};
|
|
89
|
+
function l(e, n, i, a = e) {
|
|
90
|
+
let o = e.getBoundingClientRect();
|
|
91
|
+
return {
|
|
92
|
+
left: t(r(n - o.left, a), a),
|
|
93
|
+
top: t(r(i - o.top, a), a)
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
var u = class {
|
|
82
97
|
#e;
|
|
83
98
|
#t;
|
|
84
99
|
#n = !1;
|
|
@@ -89,36 +104,39 @@ var a = {
|
|
|
89
104
|
get placed() {
|
|
90
105
|
return this.#n;
|
|
91
106
|
}
|
|
107
|
+
get bounds() {
|
|
108
|
+
return this.#r ?? this.#i();
|
|
109
|
+
}
|
|
92
110
|
seed() {
|
|
93
|
-
let
|
|
94
|
-
if (this.#r = this.#i(),
|
|
95
|
-
x:
|
|
96
|
-
y:
|
|
111
|
+
let e = this.#e;
|
|
112
|
+
if (this.#r = this.#i(), e.left != null || e.top != null) return {
|
|
113
|
+
x: e.left ?? 0,
|
|
114
|
+
y: e.top ?? 0
|
|
97
115
|
};
|
|
98
|
-
let
|
|
116
|
+
let n = getComputedStyle(e), i = d.has(n.position), a = i ? parseFloat(n.left) || 0 : e.offsetLeft, o = i ? parseFloat(n.top) || 0 : e.offsetTop;
|
|
99
117
|
return {
|
|
100
|
-
x:
|
|
101
|
-
y:
|
|
118
|
+
x: t(r(a, e), e),
|
|
119
|
+
y: t(r(o, e), e)
|
|
102
120
|
};
|
|
103
121
|
}
|
|
104
|
-
moveTo(
|
|
105
|
-
let r = this.#e, i = this.#t(
|
|
106
|
-
r.left =
|
|
122
|
+
moveTo(e, n) {
|
|
123
|
+
let r = this.#e, i = this.#t(e, n, this.#r ?? this.#i());
|
|
124
|
+
r.left = t(i.x, r), r.top = t(i.y, r), this.#n = !0;
|
|
107
125
|
}
|
|
108
126
|
#i() {
|
|
109
|
-
let e = this.#e, t = e.offsetParent,
|
|
127
|
+
let e = this.#e, t = e.offsetParent, n = t && t.clientWidth > 0 && t.clientHeight > 0 ? t : null;
|
|
110
128
|
return {
|
|
111
|
-
width: n
|
|
112
|
-
height: n
|
|
129
|
+
width: r(n?.clientWidth ?? window.innerWidth, e),
|
|
130
|
+
height: r(n?.clientHeight ?? window.innerHeight, e)
|
|
113
131
|
};
|
|
114
132
|
}
|
|
115
|
-
},
|
|
133
|
+
}, d = /* @__PURE__ */ new Set([
|
|
116
134
|
"absolute",
|
|
117
135
|
"fixed",
|
|
118
136
|
"sticky"
|
|
119
137
|
]);
|
|
120
|
-
function
|
|
121
|
-
let r = e.top != null || e.left != null || e.fixed === !0, i =
|
|
138
|
+
function f(e, t, n) {
|
|
139
|
+
let r = e.top != null || e.left != null || e.fixed === !0, i = d.has(getComputedStyle(e).position), a = null;
|
|
122
140
|
if (!r && !i) a = "unplaced";
|
|
123
141
|
else {
|
|
124
142
|
let t = e.offsetParent;
|
|
@@ -127,4 +145,4 @@ function u(e, t, n) {
|
|
|
127
145
|
return a !== null && (console.warn(a === "unplaced" ? `${t}: movable, but in normal flow — so the first drag has to pull it out, reflowing everything after it on the page. State the origin in system px and it never was in flow: ${n}` : `${t}: the positioning parent has no box, so there is nowhere to drag to. Give it a size (and \`position: relative\`, if it is not a kit container) — the clamp is falling back to the viewport meanwhile.`), !0);
|
|
128
146
|
}
|
|
129
147
|
//#endregion
|
|
130
|
-
export {
|
|
148
|
+
export { u as PlacementController, s as VfPositioned, l as placementIn, f as warnMovableContract };
|
package/dist/text-control.d.ts
CHANGED
|
@@ -116,8 +116,15 @@ export declare class VfTextControlBase extends VfShadowRoleControl {
|
|
|
116
116
|
* inner button, which runs the same transient-proxy path a pointer does. A
|
|
117
117
|
* disabled default button means no submission at all, as in HTML; a form
|
|
118
118
|
* with no submit button falls back to the bare call, also as in HTML.
|
|
119
|
+
*
|
|
120
|
+
* Returns whether a form owner took the press — true even when a disabled
|
|
121
|
+
* default button meant no submission, since HTML gave the press to the form
|
|
122
|
+
* either way. The callers cancel the keydown on true, so a modal shell
|
|
123
|
+
* (`VfModalDialog`) sees the press as spoken for and does not also route it
|
|
124
|
+
* to the dialog's default button; with no form the press goes on to the
|
|
125
|
+
* dialog untouched.
|
|
119
126
|
*/
|
|
120
|
-
protected requestImplicitSubmit():
|
|
127
|
+
protected requestImplicitSubmit(): boolean;
|
|
121
128
|
/**
|
|
122
129
|
* Dispatch a bubbling, composed value event (SPEC §4). Text fields use the
|
|
123
130
|
* default `{ value }` detail; `vf-number-field` passes an enriched detail that
|
package/dist/text-control.js
CHANGED
|
@@ -56,14 +56,9 @@ var l = class extends a {
|
|
|
56
56
|
}
|
|
57
57
|
requestImplicitSubmit() {
|
|
58
58
|
let e = this.internals.form;
|
|
59
|
-
if (!e) return;
|
|
59
|
+
if (!e) return !1;
|
|
60
60
|
let t = [...e.elements].find((e) => e instanceof HTMLButtonElement && e.type === "submit" || e instanceof HTMLInputElement && (e.type === "submit" || e.type === "image") || e.localName === "vf-button" && e.type?.toLowerCase() === "submit");
|
|
61
|
-
|
|
62
|
-
if (t.matches(":disabled")) return;
|
|
63
|
-
t.click();
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
e.requestSubmit();
|
|
61
|
+
return t ? (t.matches(":disabled") || t.click(), !0) : (e.requestSubmit(), !0);
|
|
67
62
|
}
|
|
68
63
|
emitValue(t, n = { value: this.value }) {
|
|
69
64
|
e(this, t, n);
|