@nightshadeui/util 2.12.6 → 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,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/index.d.ts CHANGED
@@ -2,6 +2,7 @@ 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';
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
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 CHANGED
@@ -2,6 +2,7 @@ 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';
7
8
  //# sourceMappingURL=index.js.map
package/out/index.js.map CHANGED
@@ -1 +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,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nightshadeui/util",
3
- "version": "2.12.6",
3
+ "version": "2.13.0",
4
4
  "description": "Shared utility helpers for Nightshade packages",
5
5
  "author": "Boris Okunskiy",
6
6
  "license": "ISC",
@@ -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';