@usman404/crowjs 1.0.2
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/CONTRIBUTING.md +1 -0
- package/Core/Component.js +426 -0
- package/Core/GUIEvent/GUIEvent.js +23 -0
- package/Core/GUIEvent/KeyboardEvent.js +14 -0
- package/Core/GUIEvent/MouseEvent.js +22 -0
- package/Core/Root.js +558 -0
- package/Frames/DummyFrame.js +185 -0
- package/Frames/Frame.js +531 -0
- package/Frames/FrameComponent.js +54 -0
- package/Frames/GridFrame.js +574 -0
- package/Frames/ScrollFrame.js +764 -0
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/UIComponents/Input.js +78 -0
- package/UIComponents/Label.js +234 -0
- package/UIComponents/TextField.js +551 -0
- package/UIComponents/UIComponent.js +97 -0
- package/crowjs-01-01.png +0 -0
- package/index.html +15 -0
- package/package.json +23 -0
- package/sketch.js +65 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { GUIEvent } from "./GUIEvent/GUIEvent.js";
|
|
2
|
+
|
|
3
|
+
export class Component{
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new Component instance
|
|
6
|
+
* @param {number} x - The x-coordinate of the component
|
|
7
|
+
* @param {number} y - The y-coordinate of the component
|
|
8
|
+
* @param {number} width - The width of the component
|
|
9
|
+
* @param {number} height - The height of the component
|
|
10
|
+
* @param {Object} options - Configuration options
|
|
11
|
+
* @param {string} options.type - The type identifier of the component
|
|
12
|
+
* @param {string|null} options.id - Unique identifier for the component
|
|
13
|
+
*/
|
|
14
|
+
constructor(x, y, width, height, {type="", id=null} = {}){
|
|
15
|
+
this.x = x;
|
|
16
|
+
this.y = y;
|
|
17
|
+
this.id = id;
|
|
18
|
+
this.height = height;
|
|
19
|
+
this.width = width;
|
|
20
|
+
this.parent = null;
|
|
21
|
+
this.type = type;
|
|
22
|
+
this.root = null;
|
|
23
|
+
this.eventListeners = {};
|
|
24
|
+
this.children = [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//to show itself
|
|
28
|
+
/**
|
|
29
|
+
* Renders the component on the canvas
|
|
30
|
+
* @abstract
|
|
31
|
+
*/
|
|
32
|
+
show(){};
|
|
33
|
+
|
|
34
|
+
//you can add multiple callback functions to one eventType
|
|
35
|
+
//for each component
|
|
36
|
+
/**
|
|
37
|
+
* Registers an event listener for the component
|
|
38
|
+
*
|
|
39
|
+
* @param {EventType} eventType - The type of event to listen for. Available options:
|
|
40
|
+
*
|
|
41
|
+
* ## Mouse Events
|
|
42
|
+
* - `"hover"` - Fires continuously while mouse is over the component (use in draw loop)
|
|
43
|
+
* - `"mouseEnter"` - Fires once when mouse enters component boundaries
|
|
44
|
+
* - `"mouseLeave"` - Fires once when mouse leaves component boundaries
|
|
45
|
+
* - `"click"` - Fires on mouse click (press + release on same component)
|
|
46
|
+
* - `"press"` - Fires when mouse button is pressed down
|
|
47
|
+
* - `"release"` - Fires when mouse button is released
|
|
48
|
+
* - `"drag"` - Fires continuously while mouse is dragged with button pressed
|
|
49
|
+
* - `"doubleClick"` - Fires on double click
|
|
50
|
+
* - `"scroll"` - Fires on mouse wheel scroll
|
|
51
|
+
*
|
|
52
|
+
* ## Keyboard Events
|
|
53
|
+
* - `"keyPress"` - Fires once when a key is pressed
|
|
54
|
+
* - `"keyDown"` - Fires continuously while a key is held down (use in draw loop)
|
|
55
|
+
*
|
|
56
|
+
* ## Frame Events (Frame, GridFrame, ScrollFrame only)
|
|
57
|
+
* - `"resize"` - Fires when frame is being resized by user
|
|
58
|
+
* - `"reposition"` - Fires when frame is being dragged/moved by user
|
|
59
|
+
*
|
|
60
|
+
* ## Input Events (TextField, Input only)
|
|
61
|
+
* - `"focus"` - Fires when input field gains focus
|
|
62
|
+
* - `"blur"` - Fires when input field loses focus
|
|
63
|
+
*
|
|
64
|
+
* @param {function(GUIEvent): void} callback - The function to call when event occurs.
|
|
65
|
+
* The callback receives a GUIEvent object with the following properties:
|
|
66
|
+
* - `x` {number} - The x-coordinate where event occurred
|
|
67
|
+
* - `y` {number} - The y-coordinate where event occurred
|
|
68
|
+
* - `type` {string} - The event type that triggered
|
|
69
|
+
* - `target` {Component} - The component that received the event
|
|
70
|
+
* - `propagationStopped` {boolean} - Whether event propagation was stopped
|
|
71
|
+
*
|
|
72
|
+
* For specific event types:
|
|
73
|
+
* - **MouseEvent** (extends GUIEvent): All mouse-related events
|
|
74
|
+
* - **KeyboardEvent** (extends GUIEvent): `keyPress`, `keyDown`
|
|
75
|
+
* - **Scroll events**: Includes `delta` property for scroll direction
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Basic click handler
|
|
79
|
+
* component.addEventListener("click", (event) => {
|
|
80
|
+
* console.log(`Clicked at ${event.x}, ${event.y}`);
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* // Frame resize handler
|
|
85
|
+
* frame.addEventListener("resize", (event) => {
|
|
86
|
+
* console.log(`Frame resized to ${event.target.width}x${event.target.height}`);
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* // Input focus handler
|
|
91
|
+
* textField.addEventListener("focus", (event) => {
|
|
92
|
+
* event.target.borderWidth += 2; // Visual feedback
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* // Stop event propagation
|
|
97
|
+
* component.addEventListener("click", (event) => {
|
|
98
|
+
* event.stopPropagation(); // Prevents parent components from receiving event
|
|
99
|
+
* console.log("Event handled here only");
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* @throws {Error} If eventType is not a string or callback is not a function
|
|
103
|
+
*
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
addEventListener(eventType, callback){
|
|
107
|
+
if(!this.eventListeners[eventType]){
|
|
108
|
+
this.eventListeners[eventType] = [];
|
|
109
|
+
}
|
|
110
|
+
this.eventListeners[eventType].push(callback);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Dispatches a mouse enter event to the component
|
|
114
|
+
* @param {MouseEvent} event - The mouse enter event
|
|
115
|
+
*/
|
|
116
|
+
dispatchMouseEnterEvent(event){
|
|
117
|
+
this.dispatchMouseEnterLeaveEventUtil(event);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Dispatches a mouse leave event to the component
|
|
121
|
+
* @param {MouseEvent} event - The mouse leave event
|
|
122
|
+
*/
|
|
123
|
+
dispatchMouseLeaveEvent(event){
|
|
124
|
+
this.dispatchMouseEnterLeaveEventUtil(event);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Internal utility for mouse enter/leave event handling
|
|
128
|
+
* @param {MouseEvent} event - The mouse event
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
dispatchMouseEnterLeaveEventUtil(event){
|
|
132
|
+
if(this.eventListeners[event.type]){
|
|
133
|
+
for(let callback of this.eventListeners[event.type]){
|
|
134
|
+
callback(event);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//to take action upon event occurence
|
|
140
|
+
/**
|
|
141
|
+
* Dispatches an event to the component and propagates to parents
|
|
142
|
+
* @param {GUIEvent} event - The event to dispatch
|
|
143
|
+
*/
|
|
144
|
+
dispatchEvent(event){
|
|
145
|
+
// console.log("Dispatching to:", event.target, "Event type:", event.type);
|
|
146
|
+
if(this.eventListeners[event.type]){
|
|
147
|
+
for(let callback of this.eventListeners[event.type]){
|
|
148
|
+
callback(event);
|
|
149
|
+
if(event.propagationStopped){
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Bubble up to parent
|
|
155
|
+
if(this.parent){
|
|
156
|
+
this.parent.dispatchEvent(event);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Dispatches an event only to this component (no propagation)
|
|
162
|
+
* @param {GUIEvent} event - The event to dispatch
|
|
163
|
+
*/
|
|
164
|
+
dispatchEventOnlyOnSelf(event){
|
|
165
|
+
if(this.eventListeners[event.type]){
|
|
166
|
+
for(let callback of this.eventListeners[event.type]){
|
|
167
|
+
callback(event);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Dispatches an event to this component and all children
|
|
174
|
+
* @param {GUIEvent} event - The event to dispatch
|
|
175
|
+
*/
|
|
176
|
+
dispatchTrickleDownEvent(event){
|
|
177
|
+
if(this.eventListeners[event.type]){
|
|
178
|
+
for(let callback of this.eventListeners[event.type]){
|
|
179
|
+
callback(event);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for(let i=0; i<this.children.length; i++){
|
|
184
|
+
this.children[i].dispatchTrickleDownEvent(event);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Disables resizing and repositioning for this component (if Frame) and all of its children
|
|
190
|
+
*/
|
|
191
|
+
turnResizingAndRepositionOff(){
|
|
192
|
+
if(this.type==="Frame"){
|
|
193
|
+
this.enableResizing=false;
|
|
194
|
+
this.enableReposition=false;
|
|
195
|
+
|
|
196
|
+
for(let i=0; i<this.children.length; i++){
|
|
197
|
+
this.children[i].turnResizingAndRepositionOff();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Checks if the mouse is inside the component boundaries
|
|
204
|
+
* @returns {boolean} True if mouse is inside the component
|
|
205
|
+
*/
|
|
206
|
+
isInside() {
|
|
207
|
+
let insideRect = mouseX > this.x && mouseX < this.x + this.width &&
|
|
208
|
+
mouseY > this.y && mouseY < this.y + this.height;
|
|
209
|
+
|
|
210
|
+
if (!insideRect) return false;
|
|
211
|
+
|
|
212
|
+
let r = this.cornerRadius || 0;
|
|
213
|
+
|
|
214
|
+
// If corner radius is 0, we don't need further checks
|
|
215
|
+
if (r <= 0) return this.checkParent();
|
|
216
|
+
|
|
217
|
+
// Define the 4 corner centers
|
|
218
|
+
let corners = [
|
|
219
|
+
{ x: this.x + r, y: this.y + r }, // top-left
|
|
220
|
+
{ x: this.x + this.width - r, y: this.y + r }, // top-right
|
|
221
|
+
{ x: this.x + r, y: this.y + this.height - r }, // bottom-left
|
|
222
|
+
{ x: this.x + this.width - r, y: this.y + this.height - r }, // bottom-right
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
// Check if mouse is within the quarter circle of any corner
|
|
226
|
+
if (mouseX < this.x + r && mouseY < this.y + r && dist(mouseX, mouseY, corners[0].x, corners[0].y) > r)
|
|
227
|
+
return false;
|
|
228
|
+
if (mouseX > this.x + this.width - r && mouseY < this.y + r && dist(mouseX, mouseY, corners[1].x, corners[1].y) > r)
|
|
229
|
+
return false;
|
|
230
|
+
if (mouseX < this.x + r && mouseY > this.y + this.height - r && dist(mouseX, mouseY, corners[2].x, corners[2].y) > r)
|
|
231
|
+
return false;
|
|
232
|
+
if (mouseX > this.x + this.width - r && mouseY > this.y + this.height - r && dist(mouseX, mouseY, corners[3].x, corners[3].y) > r)
|
|
233
|
+
return false;
|
|
234
|
+
|
|
235
|
+
return this.checkParent();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//removes child from children array
|
|
239
|
+
//only from the immediate children
|
|
240
|
+
/**
|
|
241
|
+
* Removes a child component from immediate children
|
|
242
|
+
* @param {Component} element - The child component to remove
|
|
243
|
+
* @returns {boolean} True if component was found and removed
|
|
244
|
+
*/
|
|
245
|
+
removeChild(element){
|
|
246
|
+
if(this.children.includes(element)){
|
|
247
|
+
this.children = this.children.filter((elem)=>elem!==element);
|
|
248
|
+
// console.log(`element (id: ${element.id}) removed successfully from ${this.constructor.name} (id: ${this.id})!`);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// helper to deal with scrollable parent
|
|
256
|
+
/**
|
|
257
|
+
* Helper method to check parent boundaries for scrollable containers
|
|
258
|
+
* @returns {boolean} True if parent boundaries allow interaction
|
|
259
|
+
* @private
|
|
260
|
+
*/
|
|
261
|
+
checkParent() {
|
|
262
|
+
if (this.parent && this.parent.constructor.name === "ScrollFrame" &&
|
|
263
|
+
(this.parent.enableVScroll || this.parent.enableHScroll)) {
|
|
264
|
+
return this.parent.isInside();
|
|
265
|
+
}
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
//finds element recursively among children
|
|
271
|
+
/**
|
|
272
|
+
* Recursively searches for an element in the children tree
|
|
273
|
+
* @param {Component} element - The element to find
|
|
274
|
+
* @returns {boolean} True if element is found in the hierarchy or matches to self
|
|
275
|
+
*/
|
|
276
|
+
findElement(element){
|
|
277
|
+
if(element==this){
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
for(let i = this.children.length - 1; i >= 0; i--){
|
|
282
|
+
let child = this.children[i];
|
|
283
|
+
if(child.findElement(element)){
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Finds the index of a child element
|
|
293
|
+
* @param {Component} element - The child element to find
|
|
294
|
+
* @returns {number} Index of the element or -1 if not found
|
|
295
|
+
*/
|
|
296
|
+
findIndexOfElement(element){
|
|
297
|
+
return this.children.findIndex((elem)=> elem===element);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// cheking if it or any of its children have ids
|
|
301
|
+
// already present in the map
|
|
302
|
+
// if there is, then the duplicate id is returned
|
|
303
|
+
/**
|
|
304
|
+
* Checks if this component can be safely added to the elements map
|
|
305
|
+
* @param {Map} map - The elements map to check against
|
|
306
|
+
* @returns {string} "<<no_match_found>>" if safe, duplicate ID otherwise
|
|
307
|
+
*/
|
|
308
|
+
safeToFillElementsMap(map){
|
|
309
|
+
if(map.has(this.id)){
|
|
310
|
+
return this.id;//false
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
for(let i=0; i<this.children.length; i++){
|
|
314
|
+
let res = this.children[i].safeToFillElementsMap(map);
|
|
315
|
+
if(res!=="<<no_match_found>>"){
|
|
316
|
+
return res;//return the duplicate id
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return "<<no_match_found>>";//true
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Fills the elements map with this component and all children
|
|
324
|
+
* @param {Map} map - The elements map to populate
|
|
325
|
+
* @returns {string} "<<map_filled_successfully>>" or duplicate ID
|
|
326
|
+
*/
|
|
327
|
+
fillElementsMap(map){
|
|
328
|
+
let res = this.safeToFillElementsMap(map);
|
|
329
|
+
if(res!=="<<no_match_found>>"){
|
|
330
|
+
return res;//return duplicate id
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
this.fillElementsMapUtil(map);
|
|
334
|
+
return "<<map_filled_successfully>>";
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Internal recursive method to populate elements map
|
|
338
|
+
* @param {Map} map - The elements map to populate
|
|
339
|
+
* @private
|
|
340
|
+
*/
|
|
341
|
+
fillElementsMapUtil(map){
|
|
342
|
+
if(this.id!==null){
|
|
343
|
+
map.set(this.id, this);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
for(let i=0; i<this.children.length; i++){
|
|
347
|
+
this.children[i].fillElementsMapUtil(map);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
//recursively finds element by ID
|
|
352
|
+
/**
|
|
353
|
+
* Recursively finds a component by its ID
|
|
354
|
+
* @param {string} id - The ID to search for
|
|
355
|
+
* @returns {Component|null} The found component or null
|
|
356
|
+
*/
|
|
357
|
+
getElementById(id){
|
|
358
|
+
if(id===null){
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if(this.id===id){
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
for(let i=0; i<this.children.length; i++){
|
|
367
|
+
let result = this.children[i].getElementById(id);
|
|
368
|
+
if(result){
|
|
369
|
+
return result;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
//recursively finds target component
|
|
377
|
+
/**
|
|
378
|
+
* Recursively finds the target component for mouse events
|
|
379
|
+
* @returns {Component|null} The deepest component under the mouse
|
|
380
|
+
*/
|
|
381
|
+
findTarget(){
|
|
382
|
+
for(let i = this.children.length - 1; i >= 0; i--){
|
|
383
|
+
let child = this.children[i];
|
|
384
|
+
if(child.isInside()){
|
|
385
|
+
return child.findTarget();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if(this.isInside()){
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Checks if this component is a child of the specified element
|
|
397
|
+
* @param {Component} elem - The potential parent element
|
|
398
|
+
* @returns {boolean} True if this is a child of the element
|
|
399
|
+
*/
|
|
400
|
+
isChildOf(elem){
|
|
401
|
+
if(!this.parent || !elem){
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if(this.parent === elem){
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return this.parent.isChildOf(elem);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
//recursively sets root of itself and of its children
|
|
413
|
+
/**
|
|
414
|
+
* Sets the root reference for this component and all children
|
|
415
|
+
* @param {Root} root - The root manager instance
|
|
416
|
+
*/
|
|
417
|
+
setRoot(root){
|
|
418
|
+
this.root = root;
|
|
419
|
+
|
|
420
|
+
for(let i=0; i<this.children.length; i++){
|
|
421
|
+
let child = this.children[i];
|
|
422
|
+
child.setRoot(root);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class GUIEvent {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a base GUI event
|
|
4
|
+
* @param {number} x - The x-coordinate where the event occurred
|
|
5
|
+
* @param {number} y - The y-coordinate where the event occurred
|
|
6
|
+
* @param {string} type - The type of event (e.g., "click", "hover")
|
|
7
|
+
* @param {Component} target - The component that is the target of the event
|
|
8
|
+
*/
|
|
9
|
+
constructor(x, y, type, target) {
|
|
10
|
+
this.x = x;
|
|
11
|
+
this.y = y;
|
|
12
|
+
this.type = type;
|
|
13
|
+
this.target = target;
|
|
14
|
+
this.propagationStopped = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Stops the event from propagating to parent components
|
|
19
|
+
*/
|
|
20
|
+
stopPropagation() {
|
|
21
|
+
this.propagationStopped = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GUIEvent } from "./GUIEvent.js";
|
|
2
|
+
|
|
3
|
+
export class KeyboardEvent extends GUIEvent{
|
|
4
|
+
/**
|
|
5
|
+
* Creates a keyboard-specific event
|
|
6
|
+
* @param {number} x - The current mouse x-coordinate
|
|
7
|
+
* @param {number} y - The current mouse y-coordinate
|
|
8
|
+
* @param {string} type - The type of keyboard event
|
|
9
|
+
* @param {Component} target - The target component
|
|
10
|
+
*/
|
|
11
|
+
constructor(x, y, type, target){
|
|
12
|
+
super(x, y, type, target);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GUIEvent } from "./GUIEvent.js";
|
|
2
|
+
|
|
3
|
+
export class MouseEvent extends GUIEvent{
|
|
4
|
+
/**
|
|
5
|
+
* Creates a mouse-specific event
|
|
6
|
+
* @param {number} x - The x-coordinate of the mouse event
|
|
7
|
+
* @param {number} y - The y-coordinate of the mouse event
|
|
8
|
+
* @param {string} type - The type of mouse event
|
|
9
|
+
* @param {Component} target - The target component
|
|
10
|
+
* @param {Object} options - Additional options
|
|
11
|
+
* @param {WheelEvent|null} options.event - The original wheel event for scroll events
|
|
12
|
+
*/
|
|
13
|
+
constructor(x, y, type, target, {event=null}={}){
|
|
14
|
+
super(x, y, type, target);
|
|
15
|
+
//storing scroll info
|
|
16
|
+
if(event){
|
|
17
|
+
//positive delta value denotes scroll up
|
|
18
|
+
//non-positive denotes scroll down
|
|
19
|
+
this.delta = event.delta;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|