@gjsify/dom-elements 0.4.0 → 0.4.4

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.
Files changed (53) hide show
  1. package/lib/types/location-stub.d.ts +1 -1
  2. package/package.json +78 -75
  3. package/src/attr.ts +0 -61
  4. package/src/character-data.ts +0 -79
  5. package/src/comment.ts +0 -31
  6. package/src/document-fragment.ts +0 -137
  7. package/src/document.ts +0 -103
  8. package/src/dom-matrix.ts +0 -109
  9. package/src/dom-token-list.ts +0 -140
  10. package/src/element.ts +0 -316
  11. package/src/font-face.ts +0 -97
  12. package/src/gst-time.ts +0 -26
  13. package/src/html-canvas-element.ts +0 -90
  14. package/src/html-element.ts +0 -502
  15. package/src/html-image-element.spec.ts +0 -285
  16. package/src/html-image-element.ts +0 -295
  17. package/src/html-media-element.ts +0 -123
  18. package/src/html-video-element.ts +0 -143
  19. package/src/image.ts +0 -31
  20. package/src/index.spec.ts +0 -914
  21. package/src/index.ts +0 -39
  22. package/src/intersection-observer.ts +0 -42
  23. package/src/location-stub.ts +0 -20
  24. package/src/match-media.ts +0 -32
  25. package/src/mutation-observer.ts +0 -39
  26. package/src/named-node-map.ts +0 -159
  27. package/src/namespace-uri.ts +0 -11
  28. package/src/node-list.ts +0 -52
  29. package/src/node-type.ts +0 -14
  30. package/src/node.ts +0 -280
  31. package/src/property-symbol.ts +0 -23
  32. package/src/register/canvas.ts +0 -23
  33. package/src/register/document.ts +0 -64
  34. package/src/register/font-face.ts +0 -18
  35. package/src/register/helpers.ts +0 -15
  36. package/src/register/image.ts +0 -8
  37. package/src/register/location.ts +0 -6
  38. package/src/register/match-media.ts +0 -6
  39. package/src/register/navigator.ts +0 -6
  40. package/src/register/observers.ts +0 -10
  41. package/src/register.spec.ts +0 -136
  42. package/src/register.ts +0 -13
  43. package/src/resize-observer.ts +0 -28
  44. package/src/stubs.spec.ts +0 -284
  45. package/src/test.browser.mts +0 -686
  46. package/src/test.mts +0 -9
  47. package/src/text.ts +0 -67
  48. package/src/types/i-html-image-element.ts +0 -44
  49. package/src/types/image-data.ts +0 -12
  50. package/src/types/index.ts +0 -3
  51. package/src/types/predefined-color-space.ts +0 -1
  52. package/tsconfig.json +0 -37
  53. package/tsconfig.tsbuildinfo +0 -1
@@ -1,502 +0,0 @@
1
- // Adapted from happy-dom (refs/happy-dom/packages/happy-dom/src/nodes/html-element/HTMLElement.ts)
2
- // Copyright (c) David Ortner (capricorn86). MIT license.
3
- // Modifications: Simplified for gjsify — minimal CSSStyleDeclaration stub, no dataset/DOMStringMap,
4
- // no innerText/outerText, no custom element lifecycle, minimal on* handlers
5
-
6
- import { Event } from '@gjsify/dom-events';
7
-
8
- import { Element } from './element.js';
9
- import * as PS from './property-symbol.js';
10
-
11
- /**
12
- * Minimal CSSStyleDeclaration stub — stores property strings but has no effect.
13
- * GTK manages layout; CSS values written here (e.g. by three.js WebGLRenderer.setSize)
14
- * are silently accepted and ignored.
15
- */
16
- export class CSSStyleDeclaration {
17
- [key: string]: unknown;
18
- private _cssText = '';
19
-
20
- /** Setting cssText parses individual declarations and stores them as camelCase properties,
21
- * matching browser behavior for feature-detection checks like Excalibur's rgbaSupport. */
22
- get cssText(): string { return this._cssText; }
23
- set cssText(value: string) {
24
- this._cssText = value;
25
- for (const decl of value.split(';')) {
26
- const colon = decl.indexOf(':');
27
- if (colon === -1) continue;
28
- const prop = decl.slice(0, colon).trim();
29
- const val = decl.slice(colon + 1).trim();
30
- if (!prop) continue;
31
- const camel = prop.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());
32
- (this as Record<string, unknown>)[camel] = val;
33
- }
34
- }
35
-
36
- setProperty(property: string, value: string, _priority?: string): void {
37
- (this as Record<string, unknown>)[property] = value;
38
- }
39
- getPropertyValue(property: string): string {
40
- const v = (this as Record<string, unknown>)[property];
41
- return typeof v === 'string' ? v : '';
42
- }
43
- removeProperty(property: string): string {
44
- const v = (this as Record<string, unknown>)[property];
45
- delete (this as Record<string, unknown>)[property];
46
- return typeof v === 'string' ? v : '';
47
- }
48
- getPropertyPriority(_property: string): string { return ''; }
49
- }
50
-
51
- /**
52
- * HTML Element base class.
53
- *
54
- * Reference: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
55
- */
56
- export class HTMLElement extends Element {
57
- // -- Style stub (no layout engine — assignments are no-ops) --
58
- readonly style: CSSStyleDeclaration = new CSSStyleDeclaration();
59
-
60
- // -- dataset: Proxy-backed DOMStringMap over data-* attributes --
61
- // Converts `data-original-src` ↔ `originalSrc` (camelCase). Used by
62
- // Excalibur's ImageSource which sets data-original-src on images for
63
- // debugging and TextureLoader.checkImageSizeSupportedAndLog.
64
- get dataset(): Record<string, string> {
65
- const el = this;
66
- return new Proxy({} as Record<string, string>, {
67
- get(_target, prop: string): string | undefined {
68
- if (typeof prop !== 'string') return undefined;
69
- const attr = 'data-' + prop.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
70
- const value = el.getAttribute(attr);
71
- return value ?? undefined;
72
- },
73
- set(_target, prop: string, value: string): boolean {
74
- if (typeof prop !== 'string') return false;
75
- const attr = 'data-' + prop.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
76
- el.setAttribute(attr, String(value));
77
- return true;
78
- },
79
- deleteProperty(_target, prop: string): boolean {
80
- if (typeof prop !== 'string') return false;
81
- const attr = 'data-' + prop.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
82
- el.removeAttribute(attr);
83
- return true;
84
- },
85
- has(_target, prop: string): boolean {
86
- if (typeof prop !== 'string') return false;
87
- const attr = 'data-' + prop.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
88
- return el.hasAttribute(attr);
89
- },
90
- });
91
- }
92
-
93
- // -- Attribute-backed string properties --
94
-
95
- get title(): string {
96
- return this.getAttribute('title') ?? '';
97
- }
98
-
99
- set title(value: string) {
100
- this.setAttribute('title', value);
101
- }
102
-
103
- get lang(): string {
104
- return this.getAttribute('lang') ?? '';
105
- }
106
-
107
- set lang(value: string) {
108
- this.setAttribute('lang', value);
109
- }
110
-
111
- get dir(): string {
112
- return this.getAttribute('dir') ?? '';
113
- }
114
-
115
- set dir(value: string) {
116
- this.setAttribute('dir', value);
117
- }
118
-
119
- get accessKey(): string {
120
- return this.getAttribute('accesskey') ?? '';
121
- }
122
-
123
- set accessKey(value: string) {
124
- this.setAttribute('accesskey', value);
125
- }
126
-
127
- get accessKeyLabel(): string {
128
- return this.getAttribute('accesskey') ?? '';
129
- }
130
-
131
- // -- Attribute-backed boolean properties --
132
-
133
- get hidden(): boolean {
134
- return this.hasAttribute('hidden');
135
- }
136
-
137
- set hidden(value: boolean) {
138
- if (value) {
139
- this.setAttribute('hidden', '');
140
- } else {
141
- this.removeAttribute('hidden');
142
- }
143
- }
144
-
145
- get draggable(): boolean {
146
- return this.getAttribute('draggable') === 'true';
147
- }
148
-
149
- set draggable(value: boolean) {
150
- this.setAttribute('draggable', String(value));
151
- }
152
-
153
- get spellcheck(): boolean {
154
- const attr = this.getAttribute('spellcheck');
155
- if (attr === 'false') return false;
156
- return attr !== null;
157
- }
158
-
159
- set spellcheck(value: boolean) {
160
- this.setAttribute('spellcheck', String(value));
161
- }
162
-
163
- get translate(): boolean {
164
- const attr = this.getAttribute('translate');
165
- return attr !== 'no';
166
- }
167
-
168
- set translate(value: boolean) {
169
- this.setAttribute('translate', value ? 'yes' : 'no');
170
- }
171
-
172
- // -- Attribute-backed numeric properties --
173
-
174
- get tabIndex(): number {
175
- const attr = this.getAttribute('tabindex');
176
- return attr !== null ? Number(attr) : -1;
177
- }
178
-
179
- set tabIndex(value: number) {
180
- this.setAttribute('tabindex', String(value));
181
- }
182
-
183
- // -- Content editable --
184
-
185
- get contentEditable(): string {
186
- const attr = this.getAttribute('contenteditable');
187
- if (attr === '' || attr === 'true') return 'true';
188
- if (attr === 'false') return 'false';
189
- return 'inherit';
190
- }
191
-
192
- set contentEditable(value: string) {
193
- if (value === 'inherit') {
194
- this.removeAttribute('contenteditable');
195
- } else {
196
- this.setAttribute('contenteditable', value);
197
- }
198
- }
199
-
200
- get isContentEditable(): boolean {
201
- return this.contentEditable === 'true';
202
- }
203
-
204
- // -- Layout stubs (return 0 — no layout engine) --
205
-
206
- get offsetHeight(): number { return 0; }
207
- get offsetWidth(): number { return 0; }
208
- get offsetLeft(): number { return 0; }
209
- get offsetTop(): number { return 0; }
210
- get offsetParent(): Element | null { return null; }
211
- get clientHeight(): number { return 0; }
212
- get clientWidth(): number { return 0; }
213
- get clientLeft(): number { return 0; }
214
- get clientTop(): number { return 0; }
215
- get scrollHeight(): number { return 0; }
216
- get scrollWidth(): number { return 0; }
217
- get scrollTop(): number { return 0; }
218
- set scrollTop(_value: number) { /* no layout engine */ }
219
- get scrollLeft(): number { return 0; }
220
- set scrollLeft(_value: number) { /* no layout engine */ }
221
-
222
- getBoundingClientRect(): { x: number; y: number; top: number; left: number; right: number; bottom: number; width: number; height: number; toJSON(): object } {
223
- const w = this.clientWidth;
224
- const h = this.clientHeight;
225
- return { x: 0, y: 0, top: 0, left: 0, right: w, bottom: h, width: w, height: h, toJSON() { return this; } };
226
- }
227
-
228
- // -- Interaction methods --
229
-
230
- click(): void {
231
- this.dispatchEvent(new Event('click', { bubbles: true, cancelable: true }));
232
- }
233
-
234
- blur(): void {
235
- this.dispatchEvent(new Event('blur'));
236
- }
237
-
238
- focus(): void {
239
- this.dispatchEvent(new Event('focus'));
240
- }
241
-
242
- // -- on* event handler properties --
243
- // Following happy-dom pattern: stored in propertyEventListeners Map,
244
- // dispatched automatically by Element.dispatchEvent override
245
-
246
- get onclick(): ((event: Event) => void) | null {
247
- return this[PS.propertyEventListeners].get('onclick') ?? null;
248
- }
249
-
250
- set onclick(value: ((event: Event) => void) | null) {
251
- this[PS.propertyEventListeners].set('onclick', value);
252
- }
253
-
254
- get ondblclick(): ((event: Event) => void) | null {
255
- return this[PS.propertyEventListeners].get('ondblclick') ?? null;
256
- }
257
-
258
- set ondblclick(value: ((event: Event) => void) | null) {
259
- this[PS.propertyEventListeners].set('ondblclick', value);
260
- }
261
-
262
- get onload(): ((event: Event) => void) | null {
263
- return this[PS.propertyEventListeners].get('onload') ?? null;
264
- }
265
-
266
- set onload(value: ((event: Event) => void) | null) {
267
- this[PS.propertyEventListeners].set('onload', value);
268
- }
269
-
270
- get onerror(): ((event: Event) => void) | null {
271
- return this[PS.propertyEventListeners].get('onerror') ?? null;
272
- }
273
-
274
- set onerror(value: ((event: Event) => void) | null) {
275
- this[PS.propertyEventListeners].set('onerror', value);
276
- }
277
-
278
- get onabort(): ((event: Event) => void) | null {
279
- return this[PS.propertyEventListeners].get('onabort') ?? null;
280
- }
281
-
282
- set onabort(value: ((event: Event) => void) | null) {
283
- this[PS.propertyEventListeners].set('onabort', value);
284
- }
285
-
286
- get onfocus(): ((event: Event) => void) | null {
287
- return this[PS.propertyEventListeners].get('onfocus') ?? null;
288
- }
289
-
290
- set onfocus(value: ((event: Event) => void) | null) {
291
- this[PS.propertyEventListeners].set('onfocus', value);
292
- }
293
-
294
- get onblur(): ((event: Event) => void) | null {
295
- return this[PS.propertyEventListeners].get('onblur') ?? null;
296
- }
297
-
298
- set onblur(value: ((event: Event) => void) | null) {
299
- this[PS.propertyEventListeners].set('onblur', value);
300
- }
301
-
302
- get onchange(): ((event: Event) => void) | null {
303
- return this[PS.propertyEventListeners].get('onchange') ?? null;
304
- }
305
-
306
- set onchange(value: ((event: Event) => void) | null) {
307
- this[PS.propertyEventListeners].set('onchange', value);
308
- }
309
-
310
- get oninput(): ((event: Event) => void) | null {
311
- return this[PS.propertyEventListeners].get('oninput') ?? null;
312
- }
313
-
314
- set oninput(value: ((event: Event) => void) | null) {
315
- this[PS.propertyEventListeners].set('oninput', value);
316
- }
317
-
318
- get onsubmit(): ((event: Event) => void) | null {
319
- return this[PS.propertyEventListeners].get('onsubmit') ?? null;
320
- }
321
-
322
- set onsubmit(value: ((event: Event) => void) | null) {
323
- this[PS.propertyEventListeners].set('onsubmit', value);
324
- }
325
-
326
- get onreset(): ((event: Event) => void) | null {
327
- return this[PS.propertyEventListeners].get('onreset') ?? null;
328
- }
329
-
330
- set onreset(value: ((event: Event) => void) | null) {
331
- this[PS.propertyEventListeners].set('onreset', value);
332
- }
333
-
334
- get onscroll(): ((event: Event) => void) | null {
335
- return this[PS.propertyEventListeners].get('onscroll') ?? null;
336
- }
337
-
338
- set onscroll(value: ((event: Event) => void) | null) {
339
- this[PS.propertyEventListeners].set('onscroll', value);
340
- }
341
-
342
- get onresize(): ((event: Event) => void) | null {
343
- return this[PS.propertyEventListeners].get('onresize') ?? null;
344
- }
345
-
346
- set onresize(value: ((event: Event) => void) | null) {
347
- this[PS.propertyEventListeners].set('onresize', value);
348
- }
349
-
350
- // Mouse events
351
- get onmousedown(): ((event: Event) => void) | null {
352
- return this[PS.propertyEventListeners].get('onmousedown') ?? null;
353
- }
354
-
355
- set onmousedown(value: ((event: Event) => void) | null) {
356
- this[PS.propertyEventListeners].set('onmousedown', value);
357
- }
358
-
359
- get onmouseup(): ((event: Event) => void) | null {
360
- return this[PS.propertyEventListeners].get('onmouseup') ?? null;
361
- }
362
-
363
- set onmouseup(value: ((event: Event) => void) | null) {
364
- this[PS.propertyEventListeners].set('onmouseup', value);
365
- }
366
-
367
- get onmousemove(): ((event: Event) => void) | null {
368
- return this[PS.propertyEventListeners].get('onmousemove') ?? null;
369
- }
370
-
371
- set onmousemove(value: ((event: Event) => void) | null) {
372
- this[PS.propertyEventListeners].set('onmousemove', value);
373
- }
374
-
375
- get onmouseover(): ((event: Event) => void) | null {
376
- return this[PS.propertyEventListeners].get('onmouseover') ?? null;
377
- }
378
-
379
- set onmouseover(value: ((event: Event) => void) | null) {
380
- this[PS.propertyEventListeners].set('onmouseover', value);
381
- }
382
-
383
- get onmouseout(): ((event: Event) => void) | null {
384
- return this[PS.propertyEventListeners].get('onmouseout') ?? null;
385
- }
386
-
387
- set onmouseout(value: ((event: Event) => void) | null) {
388
- this[PS.propertyEventListeners].set('onmouseout', value);
389
- }
390
-
391
- get onmouseenter(): ((event: Event) => void) | null {
392
- return this[PS.propertyEventListeners].get('onmouseenter') ?? null;
393
- }
394
-
395
- set onmouseenter(value: ((event: Event) => void) | null) {
396
- this[PS.propertyEventListeners].set('onmouseenter', value);
397
- }
398
-
399
- get onmouseleave(): ((event: Event) => void) | null {
400
- return this[PS.propertyEventListeners].get('onmouseleave') ?? null;
401
- }
402
-
403
- set onmouseleave(value: ((event: Event) => void) | null) {
404
- this[PS.propertyEventListeners].set('onmouseleave', value);
405
- }
406
-
407
- get oncontextmenu(): ((event: Event) => void) | null {
408
- return this[PS.propertyEventListeners].get('oncontextmenu') ?? null;
409
- }
410
-
411
- set oncontextmenu(value: ((event: Event) => void) | null) {
412
- this[PS.propertyEventListeners].set('oncontextmenu', value);
413
- }
414
-
415
- // Wheel events — Excalibur detects wheel support via
416
- // `'onwheel' in document.createElement('div')` and only registers its
417
- // wheel listener when the property is present on the prototype chain.
418
- get onwheel(): ((event: Event) => void) | null {
419
- return this[PS.propertyEventListeners].get('onwheel') ?? null;
420
- }
421
-
422
- set onwheel(value: ((event: Event) => void) | null) {
423
- this[PS.propertyEventListeners].set('onwheel', value);
424
- }
425
-
426
- // Keyboard events
427
- get onkeydown(): ((event: Event) => void) | null {
428
- return this[PS.propertyEventListeners].get('onkeydown') ?? null;
429
- }
430
-
431
- set onkeydown(value: ((event: Event) => void) | null) {
432
- this[PS.propertyEventListeners].set('onkeydown', value);
433
- }
434
-
435
- get onkeyup(): ((event: Event) => void) | null {
436
- return this[PS.propertyEventListeners].get('onkeyup') ?? null;
437
- }
438
-
439
- set onkeyup(value: ((event: Event) => void) | null) {
440
- this[PS.propertyEventListeners].set('onkeyup', value);
441
- }
442
-
443
- // Touch events
444
- get ontouchstart(): ((event: Event) => void) | null {
445
- return this[PS.propertyEventListeners].get('ontouchstart') ?? null;
446
- }
447
-
448
- set ontouchstart(value: ((event: Event) => void) | null) {
449
- this[PS.propertyEventListeners].set('ontouchstart', value);
450
- }
451
-
452
- get ontouchend(): ((event: Event) => void) | null {
453
- return this[PS.propertyEventListeners].get('ontouchend') ?? null;
454
- }
455
-
456
- set ontouchend(value: ((event: Event) => void) | null) {
457
- this[PS.propertyEventListeners].set('ontouchend', value);
458
- }
459
-
460
- get ontouchmove(): ((event: Event) => void) | null {
461
- return this[PS.propertyEventListeners].get('ontouchmove') ?? null;
462
- }
463
-
464
- set ontouchmove(value: ((event: Event) => void) | null) {
465
- this[PS.propertyEventListeners].set('ontouchmove', value);
466
- }
467
-
468
- // Pointer events
469
- get onpointerdown(): ((event: Event) => void) | null {
470
- return this[PS.propertyEventListeners].get('onpointerdown') ?? null;
471
- }
472
-
473
- set onpointerdown(value: ((event: Event) => void) | null) {
474
- this[PS.propertyEventListeners].set('onpointerdown', value);
475
- }
476
-
477
- get onpointerup(): ((event: Event) => void) | null {
478
- return this[PS.propertyEventListeners].get('onpointerup') ?? null;
479
- }
480
-
481
- set onpointerup(value: ((event: Event) => void) | null) {
482
- this[PS.propertyEventListeners].set('onpointerup', value);
483
- }
484
-
485
- get onpointermove(): ((event: Event) => void) | null {
486
- return this[PS.propertyEventListeners].get('onpointermove') ?? null;
487
- }
488
-
489
- set onpointermove(value: ((event: Event) => void) | null) {
490
- this[PS.propertyEventListeners].set('onpointermove', value);
491
- }
492
-
493
- // -- Clone --
494
-
495
- cloneNode(deep = false): HTMLElement {
496
- return super.cloneNode(deep) as HTMLElement;
497
- }
498
-
499
- get [Symbol.toStringTag](): string {
500
- return 'HTMLElement';
501
- }
502
- }