@nightshadeui/util 2.12.5 → 2.13.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.
@@ -0,0 +1,10 @@
1
+ type Listener = EventListenerOrEventListenerObject;
2
+ export declare class DomEventProxy {
3
+ private target;
4
+ private entries;
5
+ constructor(target: EventTarget);
6
+ add(type: string, listener: Listener, options?: AddEventListenerOptions | boolean): void;
7
+ removeAll(): void;
8
+ }
9
+ export {};
10
+ //# sourceMappingURL=DomEventProxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DomEventProxy.d.ts","sourceRoot":"","sources":["../src/DomEventProxy.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,kCAAkC,CAAC;AAQnD,qBAAa,aAAa;IAIV,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,OAAO,CAAe;gBAEV,MAAM,EAAE,WAAW;IAEvC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO;IAKjF,SAAS;CAOZ"}
@@ -0,0 +1,17 @@
1
+ export class DomEventProxy {
2
+ constructor(target) {
3
+ this.target = target;
4
+ this.entries = [];
5
+ }
6
+ add(type, listener, options) {
7
+ this.target.addEventListener(type, listener, options);
8
+ this.entries.push({ type, listener, options });
9
+ }
10
+ removeAll() {
11
+ for (const entry of this.entries) {
12
+ this.target.removeEventListener(entry.type, entry.listener, entry.options);
13
+ }
14
+ this.entries = [];
15
+ }
16
+ }
17
+ //# sourceMappingURL=DomEventProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DomEventProxy.js","sourceRoot":"","sources":["../src/DomEventProxy.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,aAAa;IAItB,YAAoB,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;QAF/B,YAAO,GAAY,EAAE,CAAC;IAEY,CAAC;IAE3C,GAAG,CAAC,IAAY,EAAE,QAAkB,EAAE,OAA2C;QAC7E,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,SAAS;QACL,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACtB,CAAC;CAEJ"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Tracks global pointer position, button and modifier state, and dispatches
3
+ * semantic UI events (`uiclick`, `uidrag*`, `uiactivate`) on the DOM.
4
+ *
5
+ * Call {@link mount} when the application should begin listening (typically when
6
+ * your shell is mounted) and {@link unmount} to remove listeners.
7
+ */
8
+ export declare class InputStateManager {
9
+ lastMousePos: {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ lmbPressed: boolean;
14
+ mmbPressed: boolean;
15
+ rmbPressed: boolean;
16
+ altKey: boolean;
17
+ ctrlKey: boolean;
18
+ metaKey: boolean;
19
+ shiftKey: boolean;
20
+ /** Minimum pointer movement (px) before a press becomes a drag. */
21
+ dragDistance: number;
22
+ private windowEvents;
23
+ private lastMouseDownPos;
24
+ private lastMouseDownTarget;
25
+ private dragTarget;
26
+ private inClickVicinity;
27
+ private listening;
28
+ get ctrlOrMetaKey(): boolean;
29
+ mount(): void;
30
+ unmount(): void;
31
+ private onMouseDown;
32
+ private onMouseMove;
33
+ private onMouseUp;
34
+ private onKeyDown;
35
+ private onKeyUp;
36
+ private updateModifiers;
37
+ private dispatchActivate;
38
+ private isDragAllowed;
39
+ private cloneMouseEvent;
40
+ }
41
+ //# sourceMappingURL=InputStateManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputStateManager.d.ts","sourceRoot":"","sources":["../src/InputStateManager.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAE1B,YAAY;;;MAA+D;IAE3E,UAAU,UAAS;IACnB,UAAU,UAAS;IACnB,UAAU,UAAS;IAEnB,MAAM,UAAS;IACf,OAAO,UAAS;IAChB,OAAO,UAAS;IAChB,QAAQ,UAAS;IAEjB,mEAAmE;IACnE,YAAY,SAAK;IAEjB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,gBAAgB,CAA+D;IACvF,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAS;IAE1B,IAAI,aAAa,YAEhB;IAED,KAAK;IAYL,OAAO;IAWP,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,eAAe;CAiB1B"}
@@ -0,0 +1,160 @@
1
+ import { DomEventProxy } from './DomEventProxy.js';
2
+ const NO_DRAG_SELECTORS = [
3
+ 'button', 'a', 'input', 'textarea', 'select',
4
+ '[role="textbox"]', '[role="button"]', '[nodrag]',
5
+ ];
6
+ /**
7
+ * Tracks global pointer position, button and modifier state, and dispatches
8
+ * semantic UI events (`uiclick`, `uidrag*`, `uiactivate`) on the DOM.
9
+ *
10
+ * Call {@link mount} when the application should begin listening (typically when
11
+ * your shell is mounted) and {@link unmount} to remove listeners.
12
+ */
13
+ export class InputStateManager {
14
+ constructor() {
15
+ this.lastMousePos = { x: window.innerWidth * 0.5, y: window.innerHeight * 0.5 };
16
+ this.lmbPressed = false;
17
+ this.mmbPressed = false;
18
+ this.rmbPressed = false;
19
+ this.altKey = false;
20
+ this.ctrlKey = false;
21
+ this.metaKey = false;
22
+ this.shiftKey = false;
23
+ /** Minimum pointer movement (px) before a press becomes a drag. */
24
+ this.dragDistance = 4;
25
+ this.windowEvents = new DomEventProxy(window);
26
+ this.lastMouseDownPos = { x: window.innerWidth * 0.5, y: window.innerHeight * 0.5 };
27
+ this.lastMouseDownTarget = null;
28
+ this.dragTarget = null;
29
+ this.inClickVicinity = false;
30
+ this.listening = false;
31
+ }
32
+ get ctrlOrMetaKey() {
33
+ return this.ctrlKey || this.metaKey;
34
+ }
35
+ mount() {
36
+ if (this.listening) {
37
+ return;
38
+ }
39
+ this.listening = true;
40
+ this.windowEvents.add('mousedown', event => this.onMouseDown(event));
41
+ this.windowEvents.add('mousemove', event => this.onMouseMove(event));
42
+ this.windowEvents.add('mouseup', event => this.onMouseUp(event));
43
+ this.windowEvents.add('keydown', event => this.onKeyDown(event));
44
+ this.windowEvents.add('keyup', event => this.onKeyUp(event));
45
+ }
46
+ unmount() {
47
+ if (!this.listening) {
48
+ return;
49
+ }
50
+ this.listening = false;
51
+ this.windowEvents.removeAll();
52
+ this.dragTarget = null;
53
+ this.inClickVicinity = false;
54
+ this.lastMouseDownTarget = null;
55
+ }
56
+ onMouseDown(ev) {
57
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
58
+ this.lmbPressed = ev.button === 0;
59
+ this.mmbPressed = ev.button === 1;
60
+ this.rmbPressed = ev.button === 2;
61
+ if (ev.button !== 0) {
62
+ return;
63
+ }
64
+ this.lastMouseDownPos = { x: ev.pageX, y: ev.pageY };
65
+ this.lastMouseDownTarget = ev.target;
66
+ this.inClickVicinity = true;
67
+ }
68
+ onMouseMove(ev) {
69
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
70
+ if (!this.lmbPressed) {
71
+ return;
72
+ }
73
+ if (this.dragTarget) {
74
+ this.dragTarget.dispatchEvent(this.cloneMouseEvent('uidragmove', ev));
75
+ return;
76
+ }
77
+ if (!this.inClickVicinity || !this.lastMouseDownTarget) {
78
+ return;
79
+ }
80
+ const dx = ev.pageX - this.lastMouseDownPos.x;
81
+ const dy = ev.pageY - this.lastMouseDownPos.y;
82
+ if (Math.hypot(dx, dy) < this.dragDistance) {
83
+ return;
84
+ }
85
+ this.inClickVicinity = false;
86
+ if (this.isDragAllowed(this.lastMouseDownTarget)) {
87
+ this.dragTarget = this.lastMouseDownTarget;
88
+ this.dragTarget.dispatchEvent(this.cloneMouseEvent('uidragstart', ev));
89
+ }
90
+ }
91
+ onMouseUp(ev) {
92
+ if (ev.button === 0) {
93
+ const dragTarget = this.dragTarget;
94
+ const inClickVicinity = this.inClickVicinity;
95
+ const lastMouseDownTarget = this.lastMouseDownTarget;
96
+ this.dragTarget = null;
97
+ this.inClickVicinity = false;
98
+ this.lastMouseDownTarget = null;
99
+ if (dragTarget) {
100
+ dragTarget.dispatchEvent(this.cloneMouseEvent('uidragend', ev));
101
+ }
102
+ if (inClickVicinity && lastMouseDownTarget) {
103
+ lastMouseDownTarget.dispatchEvent(this.cloneMouseEvent('uiclick', ev));
104
+ this.dispatchActivate(lastMouseDownTarget, ev);
105
+ }
106
+ }
107
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
108
+ this.lmbPressed = false;
109
+ this.mmbPressed = false;
110
+ this.rmbPressed = false;
111
+ }
112
+ onKeyDown(ev) {
113
+ this.updateModifiers(ev);
114
+ if ((ev.key === 'Enter' || ev.key === ' ') && ev.target) {
115
+ if (ev.target === document.body && ev.key === ' ') {
116
+ ev.preventDefault();
117
+ }
118
+ this.dispatchActivate(ev.target, ev);
119
+ }
120
+ }
121
+ onKeyUp(ev) {
122
+ this.updateModifiers(ev);
123
+ }
124
+ updateModifiers(ev) {
125
+ this.altKey = ev.altKey;
126
+ this.ctrlKey = ev.ctrlKey;
127
+ this.metaKey = ev.metaKey;
128
+ this.shiftKey = ev.shiftKey;
129
+ }
130
+ dispatchActivate(target, baseEvent) {
131
+ const el = target;
132
+ if (el.closest(':disabled')) {
133
+ return;
134
+ }
135
+ target.dispatchEvent(new CustomEvent('uiactivate', { detail: baseEvent }));
136
+ }
137
+ isDragAllowed(target) {
138
+ if (!(target instanceof Element)) {
139
+ return false;
140
+ }
141
+ return !target.closest(NO_DRAG_SELECTORS.join(','));
142
+ }
143
+ cloneMouseEvent(type, ev) {
144
+ return new MouseEvent(type, {
145
+ bubbles: true,
146
+ cancelable: true,
147
+ clientX: ev.clientX,
148
+ clientY: ev.clientY,
149
+ screenX: ev.screenX,
150
+ screenY: ev.screenY,
151
+ button: ev.button,
152
+ buttons: ev.buttons,
153
+ ctrlKey: ev.ctrlKey,
154
+ shiftKey: ev.shiftKey,
155
+ altKey: ev.altKey,
156
+ metaKey: ev.metaKey,
157
+ });
158
+ }
159
+ }
160
+ //# sourceMappingURL=InputStateManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputStateManager.js","sourceRoot":"","sources":["../src/InputStateManager.ts"],"names":[],"mappings":"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"}
package/out/box.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { type Point } from './point.js';
2
+ export type Box = [Point, Point];
3
+ export declare function boxFromPoints(a: Point, b: Point): Box;
4
+ export declare function boxOverlap(a: Box, b: Box): boolean;
5
+ export declare function boxContains(box: Box, point: Point): boolean;
6
+ export declare function boxCovers(boundingBox: Box, box: Box): boolean;
7
+ export declare function boxEquals(a: Box, b: Box): boolean;
8
+ export declare function boxScale(box: Box, scale: number): Box;
9
+ export declare function boxCenter(box: Box): Point;
10
+ export declare function boundingBox(a: Box, b: Box): Box;
11
+ export declare function boxArea(box: Box): number;
12
+ export declare function clampPointToBox(point: Point, box: Box): Point;
13
+ //# sourceMappingURL=box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../src/box.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAA2B,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAEjC,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,GAAG,CAIrD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAKlD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAE3D;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAI7D;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,WAEvC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,OAE/C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK,CAMzC;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,GAAG,CAW/C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,UAI/B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,KAAK,CAK7D"}
package/out/box.js ADDED
@@ -0,0 +1,58 @@
1
+ import { clamp } from './math.js';
2
+ import { pointsEqual, scalePoint } from './point.js';
3
+ export function boxFromPoints(a, b) {
4
+ const min = { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y) };
5
+ const max = { x: Math.max(a.x, b.x), y: Math.max(a.y, b.y) };
6
+ return [min, max];
7
+ }
8
+ export function boxOverlap(a, b) {
9
+ // https://stackoverflow.com/questions/20925818/algorithm-to-check-if-two-boxes-overlap
10
+ const xOverlap = a[1].x >= b[0].x && b[1].x >= a[0].x;
11
+ const yOverlap = a[1].y >= b[0].y && b[1].y >= a[0].y;
12
+ return xOverlap && yOverlap;
13
+ }
14
+ export function boxContains(box, point) {
15
+ return boxOverlap(box, [point, point]);
16
+ }
17
+ export function boxCovers(boundingBox, box) {
18
+ const [a, b] = boundingBox;
19
+ const [c, d] = box;
20
+ return a.x <= c.x && a.y <= c.y && b.x >= d.x && b.y >= d.y;
21
+ }
22
+ export function boxEquals(a, b) {
23
+ return pointsEqual(a[0], b[0]) && pointsEqual(a[1], b[1]);
24
+ }
25
+ export function boxScale(box, scale) {
26
+ return boxFromPoints(scalePoint(box[0], scale), scalePoint(box[1], scale));
27
+ }
28
+ export function boxCenter(box) {
29
+ const [min, max] = box;
30
+ return {
31
+ x: (max.x - min.x) * .5 + min.x,
32
+ y: (max.y - min.y) * .5 + min.y,
33
+ };
34
+ }
35
+ export function boundingBox(a, b) {
36
+ return [
37
+ {
38
+ x: Math.min(a[0].x, b[0].x),
39
+ y: Math.min(a[0].y, b[0].y),
40
+ },
41
+ {
42
+ x: Math.max(a[1].x, b[1].x),
43
+ y: Math.max(a[1].y, b[1].y),
44
+ },
45
+ ];
46
+ }
47
+ export function boxArea(box) {
48
+ const a = Math.abs(box[0].x - box[1].x);
49
+ const b = Math.abs(box[0].y - box[1].y);
50
+ return a * b;
51
+ }
52
+ export function clampPointToBox(point, box) {
53
+ return {
54
+ x: clamp(point.x, box[0].x, box[1].x),
55
+ y: clamp(point.y, box[0].y, box[1].y),
56
+ };
57
+ }
58
+ //# sourceMappingURL=box.js.map
package/out/box.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.js","sourceRoot":"","sources":["../src/box.ts"],"names":[],"mappings":"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"}
package/out/css.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function getCssVar(el: HTMLElement | null | undefined, name: string, fallback: string): string;
2
+ export declare function getCssVarNumber(el: HTMLElement | null | undefined, name: string, fallback: number): number;
3
+ export declare function getCssColorVar(el: HTMLElement | null | undefined, name: string, fallback: string): string;
4
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAI3F;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAIjG;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,UAahG"}
package/out/css.js ADDED
@@ -0,0 +1,25 @@
1
+ export function getCssVar(el, name, fallback) {
2
+ const root = el ?? document.documentElement;
3
+ const value = getComputedStyle(root).getPropertyValue(name).trim();
4
+ return value || fallback;
5
+ }
6
+ export function getCssVarNumber(el, name, fallback) {
7
+ const raw = getCssVar(el, name, String(fallback));
8
+ const parsed = Number(raw.replace(/px|em|%|vh|vw/g, ''));
9
+ return Number.isFinite(parsed) ? parsed : fallback;
10
+ }
11
+ export function getCssColorVar(el, name, fallback) {
12
+ const root = el ?? document.documentElement;
13
+ const value = getCssVar(el, name, fallback);
14
+ const probe = document.createElement('span');
15
+ probe.style.position = 'absolute';
16
+ probe.style.visibility = 'hidden';
17
+ probe.style.pointerEvents = 'none';
18
+ probe.style.color = fallback;
19
+ probe.style.color = value;
20
+ root.appendChild(probe);
21
+ const resolved = getComputedStyle(probe).color.trim();
22
+ probe.remove();
23
+ return resolved || fallback;
24
+ }
25
+ //# sourceMappingURL=css.js.map
package/out/css.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAC,EAAkC,EAAE,IAAY,EAAE,QAAgB;IACxF,MAAM,IAAI,GAAG,EAAE,IAAI,QAAQ,CAAC,eAAe,CAAC;IAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACnE,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAkC,EAAE,IAAY,EAAE,QAAgB;IAC9F,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAkC,EAAE,IAAY,EAAE,QAAgB;IAC7F,MAAM,IAAI,GAAG,EAAE,IAAI,QAAQ,CAAC,eAAe,CAAC;IAC5C,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;IAClC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;IACnC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC;IAC7B,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC1B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACtD,KAAK,CAAC,MAAM,EAAE,CAAC;IACf,OAAO,QAAQ,IAAI,QAAQ,CAAC;AAChC,CAAC"}
package/out/grid.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare function createGridLinesSvg(cellSize: number, subdivisions: number, majorColor: string, minorColor: string): string;
2
+ export declare function createGridDotsSvg(cellSize: number, subdivisions: number, majorColor: string, majorRadius: number | undefined, minorColor: string, minorRadius?: number): string;
3
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,UAwBrB;AAED,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,oBAAI,EACf,UAAU,EAAE,MAAM,EAClB,WAAW,SAAI,UA8BlB"}
package/out/grid.js ADDED
@@ -0,0 +1,55 @@
1
+ export function createGridLinesSvg(cellSize, subdivisions, majorColor, minorColor) {
2
+ const subdivCoords = getSubdivCoords(cellSize, subdivisions)
3
+ .map(_ => _ + 1);
4
+ const lines = [
5
+ `<svg xmlns="http://www.w3.org/2000/svg"
6
+ width="${cellSize}"
7
+ height="${cellSize}"
8
+ viewBox="0 0 ${cellSize} ${cellSize}">`
9
+ ];
10
+ // Minor lines
11
+ for (const c of subdivCoords) {
12
+ lines.push(`<path d="M0,${c} H ${cellSize}" stroke="${minorColor}" stroke-width="1"/>`);
13
+ lines.push(`<path d="M${c},0 V ${cellSize}" stroke="${minorColor}" stroke-width="1"/>`);
14
+ }
15
+ // Major lines
16
+ lines.push(`<path d="M0,1 H ${cellSize}" stroke="${majorColor}" stroke-width="1"/>`);
17
+ lines.push(`<path d="M1,0 V ${cellSize}" stroke="${majorColor}" stroke-width="1"/>`);
18
+ lines.push('</svg>');
19
+ return lines.join('');
20
+ }
21
+ export function createGridDotsSvg(cellSize, subdivisions, majorColor, majorRadius = 2, minorColor, minorRadius = 1) {
22
+ const minorCoords = [0, ...getSubdivCoords(cellSize, subdivisions), cellSize];
23
+ const majorCoords = [0, cellSize];
24
+ const lines = [
25
+ `<svg xmlns="http://www.w3.org/2000/svg"
26
+ width="${cellSize}"
27
+ height="${cellSize}"
28
+ viewBox="0 0 ${cellSize} ${cellSize}">`,
29
+ ];
30
+ if (minorRadius) {
31
+ for (const x of minorCoords) {
32
+ for (const y of minorCoords) {
33
+ lines.push(`<circle cx="${x}" cy="${y}" r="${minorRadius}" fill="${minorColor}"/>`);
34
+ }
35
+ }
36
+ }
37
+ if (majorRadius) {
38
+ for (const x of majorCoords) {
39
+ for (const y of majorCoords) {
40
+ lines.push(`<circle cx="${x}" cy="${y}" r="${majorRadius}" fill="${majorColor}"/>`);
41
+ }
42
+ }
43
+ }
44
+ lines.push('</svg>');
45
+ return lines.join('');
46
+ }
47
+ function getSubdivCoords(cellSize, subdivisions) {
48
+ const subdivCoords = [];
49
+ const k = Math.round(cellSize / subdivisions);
50
+ for (let i = 1; i < subdivisions; i++) {
51
+ subdivCoords.push(k * i);
52
+ }
53
+ return subdivCoords;
54
+ }
55
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAC9B,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,UAAkB;IAElB,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC;SACvD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,MAAM,KAAK,GAAG;QACV;iBACS,QAAQ;kBACP,QAAQ;uBACH,QAAQ,IAAI,QAAQ,IAAI;KAC1C,CAAC;IACF,cAAc;IACd,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACN,eAAe,CAAC,MAAM,QAAQ,aAAa,UAAU,sBAAsB,CAC9E,CAAC;QACF,KAAK,CAAC,IAAI,CACN,aAAa,CAAC,QAAQ,QAAQ,aAAa,UAAU,sBAAsB,CAC9E,CAAC;IACN,CAAC;IACD,cAAc;IACd,KAAK,CAAC,IAAI,CAAC,mBAAmB,QAAQ,aAAa,UAAU,sBAAsB,CAAC,CAAC;IACrF,KAAK,CAAC,IAAI,CAAC,mBAAmB,QAAQ,aAAa,UAAU,sBAAsB,CAAC,CAAC;IACrF,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC7B,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,WAAW,GAAG,CAAC,EACf,UAAkB,EAClB,WAAW,GAAG,CAAC;IAEf,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG;QACV;iBACS,QAAQ;kBACP,QAAQ;uBACH,QAAQ,IAAI,QAAQ,IAAI;KAC1C,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CACN,eAAe,CAAC,SAAS,CAAC,QAAQ,WAAW,WAAW,UAAU,KAAK,CAC1E,CAAC;YACN,CAAC;QACL,CAAC;IACL,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CACN,eAAe,CAAC,SAAS,CAAC,QAAQ,WAAW,WAAW,UAAU,KAAK,CAC1E,CAAC;YACN,CAAC;QACL,CAAC;IACL,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB,EAAE,YAAoB;IAC3D,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,YAAY,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,YAAY,CAAC;AACxB,CAAC"}
package/out/index.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './box.js';
2
+ export * from './css.js';
3
+ export * from './DomEventProxy.js';
4
+ export * from './grid.js';
5
+ export * from './InputStateManager.js';
6
+ export * from './math.js';
7
+ export * from './point.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
package/out/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from './box.js';
2
+ export * from './css.js';
3
+ export * from './DomEventProxy.js';
4
+ export * from './grid.js';
5
+ export * from './InputStateManager.js';
6
+ export * from './math.js';
7
+ export * from './point.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
package/out/math.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function clamp(value: number, min: number, max: number): number;
2
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAE5D"}
package/out/math.js ADDED
@@ -0,0 +1,4 @@
1
+ export function clamp(value, min, max) {
2
+ return Math.max(min, Math.min(max, value));
3
+ }
4
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IACzD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/C,CAAC"}
package/out/point.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export interface Point {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export declare function pointsEqual(a: Point, b: Point, threshold?: number): boolean;
6
+ export declare function clonePoint(point: Point): Point;
7
+ export declare function addPoints(a: Point, b: Point): Point;
8
+ export declare function subtractPoints(a: Point, b: Point): Point;
9
+ export declare function scalePoint(p: Point, fac: number): Point;
10
+ export declare function normalizePoint(p: Point): Point;
11
+ //# sourceMappingURL=point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../src/point.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,KAAK;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,SAAI,WAE5D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE9C;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAKnD;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAKxD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAKvD;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAS9C"}
package/out/point.js ADDED
@@ -0,0 +1,35 @@
1
+ export function pointsEqual(a, b, threshold = 0) {
2
+ return Math.abs(a.x - b.x) <= threshold && Math.abs(a.y - b.y) <= threshold;
3
+ }
4
+ export function clonePoint(point) {
5
+ return { x: point.x, y: point.y };
6
+ }
7
+ export function addPoints(a, b) {
8
+ return {
9
+ x: a.x + b.x,
10
+ y: a.y + b.y,
11
+ };
12
+ }
13
+ export function subtractPoints(a, b) {
14
+ return {
15
+ x: a.x - b.x,
16
+ y: a.y - b.y,
17
+ };
18
+ }
19
+ export function scalePoint(p, fac) {
20
+ return {
21
+ x: p.x * fac,
22
+ y: p.y * fac,
23
+ };
24
+ }
25
+ export function normalizePoint(p) {
26
+ const l = Math.hypot(p.x, p.y);
27
+ if (l === 0) {
28
+ return { x: 0, y: 0 };
29
+ }
30
+ return {
31
+ x: p.x / l,
32
+ y: p.y / l,
33
+ };
34
+ }
35
+ //# sourceMappingURL=point.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point.js","sourceRoot":"","sources":["../src/point.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,WAAW,CAAC,CAAQ,EAAE,CAAQ,EAAE,SAAS,GAAG,CAAC;IACzD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAY;IACnC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAQ,EAAE,CAAQ;IACxC,OAAO;QACH,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACZ,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;KACf,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAQ,EAAE,CAAQ;IAC7C,OAAO;QACH,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACZ,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;KACf,CAAC;AACN,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAQ,EAAE,GAAW;IAC5C,OAAO;QACH,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;QACZ,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;KACf,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAQ;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACV,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO;QACH,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACV,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;KACb,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,12 +1,28 @@
1
1
  {
2
2
  "name": "@nightshadeui/util",
3
- "version": "2.12.5",
3
+ "version": "2.13.0",
4
4
  "description": "Shared utility helpers for Nightshade packages",
5
5
  "author": "Boris Okunskiy",
6
6
  "license": "ISC",
7
+ "type": "module",
7
8
  "sideEffects": false,
8
9
  "exports": {
9
- ".": "./src/index.ts",
10
- "./src": "./src/index.ts"
10
+ ".": {
11
+ "types": "./out/index.d.ts",
12
+ "import": "./out/index.js",
13
+ "default": "./out/index.js"
14
+ },
15
+ "./src": {
16
+ "types": "./src/index.ts",
17
+ "import": "./src/index.ts",
18
+ "default": "./src/index.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "out",
23
+ "src"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc -b"
11
27
  }
12
28
  }
@@ -0,0 +1,179 @@
1
+ import { DomEventProxy } from './DomEventProxy.js';
2
+
3
+ const NO_DRAG_SELECTORS = [
4
+ 'button', 'a', 'input', 'textarea', 'select',
5
+ '[role="textbox"]', '[role="button"]', '[nodrag]',
6
+ ];
7
+
8
+ type Modifiers = Pick<KeyboardEvent, 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'>;
9
+
10
+ /**
11
+ * Tracks global pointer position, button and modifier state, and dispatches
12
+ * semantic UI events (`uiclick`, `uidrag*`, `uiactivate`) on the DOM.
13
+ *
14
+ * Call {@link mount} when the application should begin listening (typically when
15
+ * your shell is mounted) and {@link unmount} to remove listeners.
16
+ */
17
+ export class InputStateManager {
18
+
19
+ lastMousePos = { x: window.innerWidth * 0.5, y: window.innerHeight * 0.5 };
20
+
21
+ lmbPressed = false;
22
+ mmbPressed = false;
23
+ rmbPressed = false;
24
+
25
+ altKey = false;
26
+ ctrlKey = false;
27
+ metaKey = false;
28
+ shiftKey = false;
29
+
30
+ /** Minimum pointer movement (px) before a press becomes a drag. */
31
+ dragDistance = 4;
32
+
33
+ private windowEvents = new DomEventProxy(window);
34
+ private lastMouseDownPos = { x: window.innerWidth * 0.5, y: window.innerHeight * 0.5 };
35
+ private lastMouseDownTarget: EventTarget | null = null;
36
+ private dragTarget: EventTarget | null = null;
37
+ private inClickVicinity = false;
38
+ private listening = false;
39
+
40
+ get ctrlOrMetaKey() {
41
+ return this.ctrlKey || this.metaKey;
42
+ }
43
+
44
+ mount() {
45
+ if (this.listening) {
46
+ return;
47
+ }
48
+ this.listening = true;
49
+ this.windowEvents.add('mousedown', event => this.onMouseDown(event as MouseEvent));
50
+ this.windowEvents.add('mousemove', event => this.onMouseMove(event as MouseEvent));
51
+ this.windowEvents.add('mouseup', event => this.onMouseUp(event as MouseEvent));
52
+ this.windowEvents.add('keydown', event => this.onKeyDown(event as KeyboardEvent));
53
+ this.windowEvents.add('keyup', event => this.onKeyUp(event as KeyboardEvent));
54
+ }
55
+
56
+ unmount() {
57
+ if (!this.listening) {
58
+ return;
59
+ }
60
+ this.listening = false;
61
+ this.windowEvents.removeAll();
62
+ this.dragTarget = null;
63
+ this.inClickVicinity = false;
64
+ this.lastMouseDownTarget = null;
65
+ }
66
+
67
+ private onMouseDown(ev: MouseEvent) {
68
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
69
+ this.lmbPressed = ev.button === 0;
70
+ this.mmbPressed = ev.button === 1;
71
+ this.rmbPressed = ev.button === 2;
72
+ if (ev.button !== 0) {
73
+ return;
74
+ }
75
+ this.lastMouseDownPos = { x: ev.pageX, y: ev.pageY };
76
+ this.lastMouseDownTarget = ev.target;
77
+ this.inClickVicinity = true;
78
+ }
79
+
80
+ private onMouseMove(ev: MouseEvent) {
81
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
82
+ if (!this.lmbPressed) {
83
+ return;
84
+ }
85
+ if (this.dragTarget) {
86
+ this.dragTarget.dispatchEvent(this.cloneMouseEvent('uidragmove', ev));
87
+ return;
88
+ }
89
+ if (!this.inClickVicinity || !this.lastMouseDownTarget) {
90
+ return;
91
+ }
92
+ const dx = ev.pageX - this.lastMouseDownPos.x;
93
+ const dy = ev.pageY - this.lastMouseDownPos.y;
94
+ if (Math.hypot(dx, dy) < this.dragDistance) {
95
+ return;
96
+ }
97
+ this.inClickVicinity = false;
98
+ if (this.isDragAllowed(this.lastMouseDownTarget)) {
99
+ this.dragTarget = this.lastMouseDownTarget;
100
+ this.dragTarget.dispatchEvent(this.cloneMouseEvent('uidragstart', ev));
101
+ }
102
+ }
103
+
104
+ private onMouseUp(ev: MouseEvent) {
105
+ if (ev.button === 0) {
106
+ const dragTarget = this.dragTarget;
107
+ const inClickVicinity = this.inClickVicinity;
108
+ const lastMouseDownTarget = this.lastMouseDownTarget;
109
+ this.dragTarget = null;
110
+ this.inClickVicinity = false;
111
+ this.lastMouseDownTarget = null;
112
+ if (dragTarget) {
113
+ dragTarget.dispatchEvent(this.cloneMouseEvent('uidragend', ev));
114
+ }
115
+ if (inClickVicinity && lastMouseDownTarget) {
116
+ lastMouseDownTarget.dispatchEvent(this.cloneMouseEvent('uiclick', ev));
117
+ this.dispatchActivate(lastMouseDownTarget, ev);
118
+ }
119
+ }
120
+ this.lastMousePos = { x: ev.pageX, y: ev.pageY };
121
+ this.lmbPressed = false;
122
+ this.mmbPressed = false;
123
+ this.rmbPressed = false;
124
+ }
125
+
126
+ private onKeyDown(ev: KeyboardEvent) {
127
+ this.updateModifiers(ev);
128
+ if ((ev.key === 'Enter' || ev.key === ' ') && ev.target) {
129
+ if (ev.target === document.body && ev.key === ' ') {
130
+ ev.preventDefault();
131
+ }
132
+ this.dispatchActivate(ev.target, ev);
133
+ }
134
+ }
135
+
136
+ private onKeyUp(ev: KeyboardEvent) {
137
+ this.updateModifiers(ev);
138
+ }
139
+
140
+ private updateModifiers(ev: Modifiers) {
141
+ this.altKey = ev.altKey;
142
+ this.ctrlKey = ev.ctrlKey;
143
+ this.metaKey = ev.metaKey;
144
+ this.shiftKey = ev.shiftKey;
145
+ }
146
+
147
+ private dispatchActivate(target: EventTarget, baseEvent: Event) {
148
+ const el = target as HTMLElement;
149
+ if (el.closest(':disabled')) {
150
+ return;
151
+ }
152
+ target.dispatchEvent(new CustomEvent('uiactivate', { detail: baseEvent }));
153
+ }
154
+
155
+ private isDragAllowed(target: EventTarget) {
156
+ if (!(target instanceof Element)) {
157
+ return false;
158
+ }
159
+ return !target.closest(NO_DRAG_SELECTORS.join(','));
160
+ }
161
+
162
+ private cloneMouseEvent(type: string, ev: MouseEvent) {
163
+ return new MouseEvent(type, {
164
+ bubbles: true,
165
+ cancelable: true,
166
+ clientX: ev.clientX,
167
+ clientY: ev.clientY,
168
+ screenX: ev.screenX,
169
+ screenY: ev.screenY,
170
+ button: ev.button,
171
+ buttons: ev.buttons,
172
+ ctrlKey: ev.ctrlKey,
173
+ shiftKey: ev.shiftKey,
174
+ altKey: ev.altKey,
175
+ metaKey: ev.metaKey,
176
+ });
177
+ }
178
+
179
+ }
package/src/index.ts CHANGED
@@ -2,5 +2,6 @@ export * from './box.js';
2
2
  export * from './css.js';
3
3
  export * from './DomEventProxy.js';
4
4
  export * from './grid.js';
5
+ export * from './InputStateManager.js';
5
6
  export * from './math.js';
6
7
  export * from './point.js';
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "include": [
4
- "**/*.ts"
5
- ],
6
- "compilerOptions": {
7
- "rootDir": "src",
8
- "lib": [
9
- "ES2022",
10
- "DOM",
11
- "DOM.Iterable"
12
- ],
13
- "noEmit": true
14
- }
15
- }