@thanhthbm/scene-editor 0.1.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.
Files changed (136) hide show
  1. package/README.md +169 -0
  2. package/dist/index.css +921 -0
  3. package/dist/index.js +14076 -0
  4. package/package.json +49 -0
  5. package/src/editor/css/main.css +1030 -0
  6. package/src/editor/js/Animation.js +618 -0
  7. package/src/editor/js/AnimationResizer.js +73 -0
  8. package/src/editor/js/Command.js +40 -0
  9. package/src/editor/js/Config.js +86 -0
  10. package/src/editor/js/Editor.js +1006 -0
  11. package/src/editor/js/EditorControls.js +489 -0
  12. package/src/editor/js/GLTFImportDialog.js +112 -0
  13. package/src/editor/js/History.js +321 -0
  14. package/src/editor/js/Loader.js +1162 -0
  15. package/src/editor/js/LoaderUtils.js +90 -0
  16. package/src/editor/js/Menubar.Add.js +559 -0
  17. package/src/editor/js/Menubar.Edit.js +155 -0
  18. package/src/editor/js/Menubar.File.js +585 -0
  19. package/src/editor/js/Menubar.Help.js +73 -0
  20. package/src/editor/js/Menubar.Render.js +858 -0
  21. package/src/editor/js/Menubar.Status.js +51 -0
  22. package/src/editor/js/Menubar.View.js +193 -0
  23. package/src/editor/js/Menubar.js +29 -0
  24. package/src/editor/js/Player.js +53 -0
  25. package/src/editor/js/Resizer.js +65 -0
  26. package/src/editor/js/Script.js +532 -0
  27. package/src/editor/js/Selector.js +129 -0
  28. package/src/editor/js/Sidebar.Geometry.BoxGeometry.js +121 -0
  29. package/src/editor/js/Sidebar.Geometry.BufferGeometry.js +124 -0
  30. package/src/editor/js/Sidebar.Geometry.CapsuleGeometry.js +109 -0
  31. package/src/editor/js/Sidebar.Geometry.CircleGeometry.js +97 -0
  32. package/src/editor/js/Sidebar.Geometry.CylinderGeometry.js +121 -0
  33. package/src/editor/js/Sidebar.Geometry.DodecahedronGeometry.js +73 -0
  34. package/src/editor/js/Sidebar.Geometry.ExtrudeGeometry.js +196 -0
  35. package/src/editor/js/Sidebar.Geometry.IcosahedronGeometry.js +73 -0
  36. package/src/editor/js/Sidebar.Geometry.LatheGeometry.js +98 -0
  37. package/src/editor/js/Sidebar.Geometry.Modifiers.js +73 -0
  38. package/src/editor/js/Sidebar.Geometry.OctahedronGeometry.js +74 -0
  39. package/src/editor/js/Sidebar.Geometry.PlaneGeometry.js +97 -0
  40. package/src/editor/js/Sidebar.Geometry.RingGeometry.js +121 -0
  41. package/src/editor/js/Sidebar.Geometry.ShapeGeometry.js +76 -0
  42. package/src/editor/js/Sidebar.Geometry.SphereGeometry.js +133 -0
  43. package/src/editor/js/Sidebar.Geometry.TetrahedronGeometry.js +74 -0
  44. package/src/editor/js/Sidebar.Geometry.TextGeometry.js +136 -0
  45. package/src/editor/js/Sidebar.Geometry.TorusGeometry.js +109 -0
  46. package/src/editor/js/Sidebar.Geometry.TorusKnotGeometry.js +121 -0
  47. package/src/editor/js/Sidebar.Geometry.TubeGeometry.js +135 -0
  48. package/src/editor/js/Sidebar.Geometry.js +471 -0
  49. package/src/editor/js/Sidebar.Material.BooleanProperty.js +60 -0
  50. package/src/editor/js/Sidebar.Material.ColorProperty.js +87 -0
  51. package/src/editor/js/Sidebar.Material.ConstantProperty.js +62 -0
  52. package/src/editor/js/Sidebar.Material.MapProperty.js +277 -0
  53. package/src/editor/js/Sidebar.Material.NumberProperty.js +60 -0
  54. package/src/editor/js/Sidebar.Material.Program.js +73 -0
  55. package/src/editor/js/Sidebar.Material.RangeValueProperty.js +63 -0
  56. package/src/editor/js/Sidebar.Material.js +751 -0
  57. package/src/editor/js/Sidebar.Object.js +892 -0
  58. package/src/editor/js/Sidebar.Project.App.js +218 -0
  59. package/src/editor/js/Sidebar.Project.Materials.js +82 -0
  60. package/src/editor/js/Sidebar.Project.Renderer.js +193 -0
  61. package/src/editor/js/Sidebar.Project.Resources.js +242 -0
  62. package/src/editor/js/Sidebar.Project.js +21 -0
  63. package/src/editor/js/Sidebar.Properties.js +73 -0
  64. package/src/editor/js/Sidebar.Scene.js +643 -0
  65. package/src/editor/js/Sidebar.Script.js +129 -0
  66. package/src/editor/js/Sidebar.Settings.History.js +146 -0
  67. package/src/editor/js/Sidebar.Settings.Shortcuts.js +198 -0
  68. package/src/editor/js/Sidebar.Settings.js +58 -0
  69. package/src/editor/js/Sidebar.js +41 -0
  70. package/src/editor/js/Storage.js +98 -0
  71. package/src/editor/js/Strings.js +2718 -0
  72. package/src/editor/js/TextureParametersDialog.js +293 -0
  73. package/src/editor/js/Toolbar.js +75 -0
  74. package/src/editor/js/Viewport.Controls.js +98 -0
  75. package/src/editor/js/Viewport.Info.js +144 -0
  76. package/src/editor/js/Viewport.Pathtracer.js +27 -0
  77. package/src/editor/js/Viewport.ViewHelper.js +41 -0
  78. package/src/editor/js/Viewport.XR.js +7 -0
  79. package/src/editor/js/Viewport.js +982 -0
  80. package/src/editor/js/commands/AddObjectCommand.js +68 -0
  81. package/src/editor/js/commands/AddScriptCommand.js +75 -0
  82. package/src/editor/js/commands/Commands.js +24 -0
  83. package/src/editor/js/commands/MoveObjectCommand.js +117 -0
  84. package/src/editor/js/commands/MultiCmdsCommand.js +85 -0
  85. package/src/editor/js/commands/RemoveObjectCommand.js +88 -0
  86. package/src/editor/js/commands/RemoveScriptCommand.js +81 -0
  87. package/src/editor/js/commands/SetColorCommand.js +73 -0
  88. package/src/editor/js/commands/SetGeometryCommand.js +86 -0
  89. package/src/editor/js/commands/SetGeometryValueCommand.js +70 -0
  90. package/src/editor/js/commands/SetMaterialColorCommand.js +87 -0
  91. package/src/editor/js/commands/SetMaterialCommand.js +80 -0
  92. package/src/editor/js/commands/SetMaterialMapCommand.js +144 -0
  93. package/src/editor/js/commands/SetMaterialRangeCommand.js +92 -0
  94. package/src/editor/js/commands/SetMaterialValueCommand.js +91 -0
  95. package/src/editor/js/commands/SetMaterialVectorCommand.js +88 -0
  96. package/src/editor/js/commands/SetPositionCommand.js +84 -0
  97. package/src/editor/js/commands/SetRotationCommand.js +84 -0
  98. package/src/editor/js/commands/SetScaleCommand.js +84 -0
  99. package/src/editor/js/commands/SetSceneCommand.js +104 -0
  100. package/src/editor/js/commands/SetScriptValueCommand.js +80 -0
  101. package/src/editor/js/commands/SetShadowValueCommand.js +73 -0
  102. package/src/editor/js/commands/SetTextureParametersCommand.js +143 -0
  103. package/src/editor/js/commands/SetUuidCommand.js +70 -0
  104. package/src/editor/js/commands/SetValueCommand.js +75 -0
  105. package/src/editor/js/libs/acorn/acorn.js +3236 -0
  106. package/src/editor/js/libs/acorn/acorn_loose.js +1299 -0
  107. package/src/editor/js/libs/acorn/walk.js +344 -0
  108. package/src/editor/js/libs/app/index.html +51 -0
  109. package/src/editor/js/libs/app.js +14 -0
  110. package/src/editor/js/libs/codemirror/addon/dialog.css +32 -0
  111. package/src/editor/js/libs/codemirror/addon/dialog.js +163 -0
  112. package/src/editor/js/libs/codemirror/addon/show-hint.css +36 -0
  113. package/src/editor/js/libs/codemirror/addon/show-hint.js +529 -0
  114. package/src/editor/js/libs/codemirror/addon/tern.css +87 -0
  115. package/src/editor/js/libs/codemirror/addon/tern.js +750 -0
  116. package/src/editor/js/libs/codemirror/codemirror.css +344 -0
  117. package/src/editor/js/libs/codemirror/codemirror.js +9849 -0
  118. package/src/editor/js/libs/codemirror/mode/glsl.js +233 -0
  119. package/src/editor/js/libs/codemirror/mode/javascript.js +959 -0
  120. package/src/editor/js/libs/codemirror/theme/monokai.css +41 -0
  121. package/src/editor/js/libs/esprima.js +6401 -0
  122. package/src/editor/js/libs/jsonlint.js +453 -0
  123. package/src/editor/js/libs/signals.min.js +14 -0
  124. package/src/editor/js/libs/tern-threejs/build-defs.js +233 -0
  125. package/src/editor/js/libs/ternjs/comment.js +87 -0
  126. package/src/editor/js/libs/ternjs/def.js +588 -0
  127. package/src/editor/js/libs/ternjs/doc_comment.js +401 -0
  128. package/src/editor/js/libs/ternjs/infer.js +1635 -0
  129. package/src/editor/js/libs/ternjs/polyfill.js +80 -0
  130. package/src/editor/js/libs/ternjs/signal.js +26 -0
  131. package/src/editor/js/libs/ternjs/tern.js +993 -0
  132. package/src/editor/js/libs/ui.js +1305 -0
  133. package/src/editor/js/libs/ui.three.js +946 -0
  134. package/src/events.js +273 -0
  135. package/src/index.js +284 -0
  136. package/src/presets/machines.js +239 -0
@@ -0,0 +1,1305 @@
1
+ class UIElement {
2
+
3
+ constructor( dom ) {
4
+
5
+ this.dom = dom;
6
+
7
+ }
8
+
9
+ add() {
10
+
11
+ for ( let i = 0; i < arguments.length; i ++ ) {
12
+
13
+ const argument = arguments[ i ];
14
+
15
+ if ( argument instanceof UIElement ) {
16
+
17
+ this.dom.appendChild( argument.dom );
18
+
19
+ } else {
20
+
21
+ console.error( 'UIElement:', argument, 'is not an instance of UIElement.' );
22
+
23
+ }
24
+
25
+ }
26
+
27
+ return this;
28
+
29
+ }
30
+
31
+ remove() {
32
+
33
+ for ( let i = 0; i < arguments.length; i ++ ) {
34
+
35
+ const argument = arguments[ i ];
36
+
37
+ if ( argument instanceof UIElement ) {
38
+
39
+ this.dom.removeChild( argument.dom );
40
+
41
+ } else {
42
+
43
+ console.error( 'UIElement:', argument, 'is not an instance of UIElement.' );
44
+
45
+ }
46
+
47
+ }
48
+
49
+ return this;
50
+
51
+ }
52
+
53
+ clear() {
54
+
55
+ while ( this.dom.children.length ) {
56
+
57
+ this.dom.removeChild( this.dom.lastChild );
58
+
59
+ }
60
+
61
+ }
62
+
63
+ setId( id ) {
64
+
65
+ this.dom.id = id;
66
+
67
+ return this;
68
+
69
+ }
70
+
71
+ getId() {
72
+
73
+ return this.dom.id;
74
+
75
+ }
76
+
77
+ setClass( name ) {
78
+
79
+ this.dom.className = name;
80
+
81
+ return this;
82
+
83
+ }
84
+
85
+ addClass( name ) {
86
+
87
+ this.dom.classList.add( name );
88
+
89
+ return this;
90
+
91
+ }
92
+
93
+ removeClass( name ) {
94
+
95
+ this.dom.classList.remove( name );
96
+
97
+ return this;
98
+
99
+ }
100
+
101
+ toggleClass( name, toggle ) {
102
+
103
+ this.dom.classList.toggle( name, toggle );
104
+
105
+ return this;
106
+
107
+ }
108
+
109
+ setStyle( style, array ) {
110
+
111
+ for ( let i = 0; i < array.length; i ++ ) {
112
+
113
+ this.dom.style[ style ] = array[ i ];
114
+
115
+ }
116
+
117
+ return this;
118
+
119
+ }
120
+
121
+ setHidden( isHidden ) {
122
+
123
+ this.dom.hidden = isHidden;
124
+
125
+ return this;
126
+
127
+ }
128
+
129
+ isHidden() {
130
+
131
+ return this.dom.hidden;
132
+
133
+ }
134
+
135
+ setDisabled( value ) {
136
+
137
+ this.dom.disabled = value;
138
+
139
+ return this;
140
+
141
+ }
142
+
143
+ setTextContent( value ) {
144
+
145
+ this.dom.textContent = value;
146
+
147
+ return this;
148
+
149
+ }
150
+
151
+ setInnerHTML( value ) {
152
+
153
+ this.dom.innerHTML = value;
154
+
155
+ }
156
+
157
+ getIndexOfChild( element ) {
158
+
159
+ return Array.prototype.indexOf.call( this.dom.children, element.dom );
160
+
161
+ }
162
+
163
+ }
164
+
165
+ // properties
166
+
167
+ const properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height',
168
+ 'display', 'verticalAlign', 'overflow', 'color', 'background', 'backgroundColor', 'opacity',
169
+ 'border', 'borderLeft', 'borderTop', 'borderRight', 'borderBottom', 'borderColor',
170
+ 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom',
171
+ 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom',
172
+ 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
173
+
174
+ properties.forEach( function ( property ) {
175
+
176
+ const method = 'set' + property.substring( 0, 1 ).toUpperCase() + property.substring( 1 );
177
+
178
+ UIElement.prototype[ method ] = function () {
179
+
180
+ this.setStyle( property, arguments );
181
+
182
+ return this;
183
+
184
+ };
185
+
186
+ } );
187
+
188
+ // events
189
+
190
+ const events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'DblClick', 'Change', 'Input' ];
191
+
192
+ events.forEach( function ( event ) {
193
+
194
+ const method = 'on' + event;
195
+
196
+ UIElement.prototype[ method ] = function ( callback ) {
197
+
198
+ this.dom.addEventListener( event.toLowerCase(), callback.bind( this ) );
199
+
200
+ return this;
201
+
202
+ };
203
+
204
+ } );
205
+
206
+ class UISpan extends UIElement {
207
+
208
+ constructor() {
209
+
210
+ super( document.createElement( 'span' ) );
211
+
212
+ }
213
+
214
+ }
215
+
216
+ class UIDiv extends UIElement {
217
+
218
+ constructor() {
219
+
220
+ super( document.createElement( 'div' ) );
221
+
222
+ }
223
+
224
+ }
225
+
226
+ class UIRow extends UIDiv {
227
+
228
+ constructor() {
229
+
230
+ super();
231
+
232
+ this.dom.className = 'Row';
233
+
234
+ }
235
+
236
+ }
237
+
238
+ class UIPanel extends UIDiv {
239
+
240
+ constructor() {
241
+
242
+ super();
243
+
244
+ this.dom.className = 'Panel';
245
+
246
+ }
247
+
248
+ }
249
+
250
+ class UIText extends UISpan {
251
+
252
+ constructor( text ) {
253
+
254
+ super();
255
+
256
+ this.dom.className = 'Text';
257
+ this.dom.style.cursor = 'default';
258
+ this.dom.style.display = 'inline-block';
259
+
260
+ this.setValue( text );
261
+
262
+ }
263
+
264
+ getValue() {
265
+
266
+ return this.dom.textContent;
267
+
268
+ }
269
+
270
+ setValue( value ) {
271
+
272
+ if ( value !== undefined ) {
273
+
274
+ this.dom.textContent = value;
275
+
276
+ }
277
+
278
+ return this;
279
+
280
+ }
281
+
282
+ }
283
+
284
+
285
+ class UIInput extends UIElement {
286
+
287
+ constructor( text ) {
288
+
289
+ super( document.createElement( 'input' ) );
290
+
291
+ this.dom.className = 'Input';
292
+ this.dom.style.padding = '2px';
293
+ this.dom.style.border = '1px solid transparent';
294
+
295
+ this.dom.setAttribute( 'autocomplete', 'off' );
296
+
297
+ this.dom.addEventListener( 'keydown', function ( event ) {
298
+
299
+ event.stopPropagation();
300
+
301
+ } );
302
+
303
+ this.setValue( text );
304
+
305
+ }
306
+
307
+ getValue() {
308
+
309
+ return this.dom.value;
310
+
311
+ }
312
+
313
+ setValue( value ) {
314
+
315
+ this.dom.value = value;
316
+
317
+ return this;
318
+
319
+ }
320
+
321
+ }
322
+
323
+ class UITextArea extends UIElement {
324
+
325
+ constructor() {
326
+
327
+ super( document.createElement( 'textarea' ) );
328
+
329
+ this.dom.className = 'TextArea';
330
+ this.dom.style.padding = '2px';
331
+ this.dom.spellcheck = false;
332
+
333
+ this.dom.setAttribute( 'autocomplete', 'off' );
334
+
335
+ this.dom.addEventListener( 'keydown', function ( event ) {
336
+
337
+ event.stopPropagation();
338
+
339
+ if ( event.code === 'Tab' ) {
340
+
341
+ event.preventDefault();
342
+
343
+ const cursor = this.selectionStart;
344
+
345
+ this.value = this.value.substring( 0, cursor ) + '\t' + this.value.substring( cursor );
346
+ this.selectionStart = cursor + 1;
347
+ this.selectionEnd = this.selectionStart;
348
+
349
+ }
350
+
351
+ } );
352
+
353
+ }
354
+
355
+ getValue() {
356
+
357
+ return this.dom.value;
358
+
359
+ }
360
+
361
+ setValue( value ) {
362
+
363
+ this.dom.value = value;
364
+
365
+ return this;
366
+
367
+ }
368
+
369
+ }
370
+
371
+ class UISelect extends UIElement {
372
+
373
+ constructor() {
374
+
375
+ super( document.createElement( 'select' ) );
376
+
377
+ this.dom.className = 'Select';
378
+ this.dom.style.padding = '2px';
379
+
380
+ this.dom.setAttribute( 'autocomplete', 'off' );
381
+
382
+ this.dom.addEventListener( 'pointerdown', function ( event ) {
383
+
384
+ event.stopPropagation();
385
+
386
+ } );
387
+
388
+ }
389
+
390
+ setMultiple( boolean ) {
391
+
392
+ this.dom.multiple = boolean;
393
+
394
+ return this;
395
+
396
+ }
397
+
398
+ setOptions( options ) {
399
+
400
+ const selected = this.dom.value;
401
+
402
+ while ( this.dom.children.length > 0 ) {
403
+
404
+ this.dom.removeChild( this.dom.firstChild );
405
+
406
+ }
407
+
408
+ for ( const key in options ) {
409
+
410
+ const option = document.createElement( 'option' );
411
+ option.value = key;
412
+ option.innerHTML = options[ key ];
413
+ this.dom.appendChild( option );
414
+
415
+ }
416
+
417
+ this.dom.value = selected;
418
+
419
+ return this;
420
+
421
+ }
422
+
423
+ getValue() {
424
+
425
+ return this.dom.value;
426
+
427
+ }
428
+
429
+ setValue( value ) {
430
+
431
+ value = String( value );
432
+
433
+ if ( this.dom.value !== value ) {
434
+
435
+ this.dom.value = value;
436
+
437
+ }
438
+
439
+ return this;
440
+
441
+ }
442
+
443
+ }
444
+
445
+ class UICheckbox extends UIElement {
446
+
447
+ constructor( boolean ) {
448
+
449
+ super( document.createElement( 'input' ) );
450
+
451
+ this.dom.className = 'Checkbox Input';
452
+ this.dom.type = 'checkbox';
453
+
454
+ this.dom.addEventListener( 'pointerdown', function ( event ) {
455
+
456
+ // Workaround for TransformControls blocking events in Viewport.Controls checkboxes
457
+
458
+ event.stopPropagation();
459
+
460
+ } );
461
+
462
+ this.setValue( boolean );
463
+
464
+ }
465
+
466
+ getValue() {
467
+
468
+ return this.dom.checked;
469
+
470
+ }
471
+
472
+ setValue( value ) {
473
+
474
+ if ( value !== undefined ) {
475
+
476
+ this.dom.checked = value;
477
+
478
+ }
479
+
480
+ return this;
481
+
482
+ }
483
+
484
+ }
485
+
486
+
487
+ class UIColor extends UIElement {
488
+
489
+ constructor() {
490
+
491
+ super( document.createElement( 'input' ) );
492
+
493
+ this.dom.className = 'Color Input';
494
+ this.dom.style.width = '32px';
495
+ this.dom.style.height = '16px';
496
+ this.dom.style.border = '0px';
497
+ this.dom.style.padding = '2px';
498
+ this.dom.style.backgroundColor = 'transparent';
499
+
500
+ this.dom.setAttribute( 'autocomplete', 'off' );
501
+
502
+ try {
503
+
504
+ this.dom.type = 'color';
505
+ this.dom.value = '#ffffff';
506
+
507
+ } catch ( exception ) {}
508
+
509
+ }
510
+
511
+ getValue() {
512
+
513
+ return this.dom.value;
514
+
515
+ }
516
+
517
+ getHexValue() {
518
+
519
+ return parseInt( this.dom.value.substring( 1 ), 16 );
520
+
521
+ }
522
+
523
+ setValue( value ) {
524
+
525
+ this.dom.value = value;
526
+
527
+ return this;
528
+
529
+ }
530
+
531
+ setHexValue( hex ) {
532
+
533
+ this.dom.value = '#' + ( '000000' + hex.toString( 16 ) ).slice( - 6 );
534
+
535
+ return this;
536
+
537
+ }
538
+
539
+ }
540
+
541
+ class UINumber extends UIElement {
542
+
543
+ constructor( number ) {
544
+
545
+ super( document.createElement( 'input' ) );
546
+
547
+ this.dom.style.cursor = 'ns-resize';
548
+ this.dom.className = 'Number Input';
549
+ this.dom.value = '0.00';
550
+
551
+ this.dom.setAttribute( 'autocomplete', 'off' );
552
+
553
+ this.value = 0;
554
+
555
+ this.min = - Infinity;
556
+ this.max = Infinity;
557
+
558
+ this.precision = 2;
559
+ this.step = 1;
560
+ this.unit = '';
561
+ this.nudge = 0.01;
562
+
563
+ this.setValue( number );
564
+
565
+ const scope = this;
566
+
567
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
568
+
569
+ let distance = 0;
570
+ let onMouseDownValue = 0;
571
+
572
+ const pointer = { x: 0, y: 0 };
573
+ const prevPointer = { x: 0, y: 0 };
574
+
575
+ function onPointerDown( event ) {
576
+
577
+ if ( document.activeElement === scope.dom ) return;
578
+
579
+ event.preventDefault();
580
+
581
+ distance = 0;
582
+
583
+ onMouseDownValue = scope.value;
584
+
585
+ prevPointer.x = event.clientX;
586
+ prevPointer.y = event.clientY;
587
+
588
+ scope.dom.setPointerCapture( event.pointerId );
589
+
590
+ scope.dom.addEventListener( 'pointermove', onPointerMove );
591
+ scope.dom.addEventListener( 'pointerup', onPointerUp );
592
+
593
+ }
594
+
595
+ function onPointerMove( event ) {
596
+
597
+ const currentValue = scope.value;
598
+
599
+ pointer.x = event.clientX;
600
+ pointer.y = event.clientY;
601
+
602
+ distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
603
+
604
+ let value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
605
+ value = Math.min( scope.max, Math.max( scope.min, value ) );
606
+
607
+ if ( currentValue !== value ) {
608
+
609
+ scope.setValue( value );
610
+ scope.dom.dispatchEvent( changeEvent );
611
+
612
+ }
613
+
614
+ prevPointer.x = event.clientX;
615
+ prevPointer.y = event.clientY;
616
+
617
+ }
618
+
619
+ function onPointerUp( event ) {
620
+
621
+ scope.dom.releasePointerCapture( event.pointerId );
622
+
623
+ scope.dom.removeEventListener( 'pointermove', onPointerMove );
624
+ scope.dom.removeEventListener( 'pointerup', onPointerUp );
625
+
626
+ if ( Math.abs( distance ) < 2 ) {
627
+
628
+ scope.dom.focus();
629
+ scope.dom.select();
630
+
631
+ }
632
+
633
+ }
634
+
635
+ function onChange() {
636
+
637
+ scope.setValue( scope.dom.value );
638
+
639
+ }
640
+
641
+ function onFocus() {
642
+
643
+ scope.dom.style.backgroundColor = '';
644
+ scope.dom.style.cursor = '';
645
+
646
+ }
647
+
648
+ function onBlur() {
649
+
650
+ scope.dom.style.backgroundColor = 'transparent';
651
+ scope.dom.style.cursor = 'ns-resize';
652
+
653
+ }
654
+
655
+ function onKeyDown( event ) {
656
+
657
+ event.stopPropagation();
658
+
659
+ switch ( event.code ) {
660
+
661
+ case 'Enter':
662
+ scope.dom.blur();
663
+ break;
664
+
665
+ case 'ArrowUp':
666
+ event.preventDefault();
667
+ scope.setValue( scope.getValue() + scope.nudge );
668
+ scope.dom.dispatchEvent( changeEvent );
669
+ break;
670
+
671
+ case 'ArrowDown':
672
+ event.preventDefault();
673
+ scope.setValue( scope.getValue() - scope.nudge );
674
+ scope.dom.dispatchEvent( changeEvent );
675
+ break;
676
+
677
+ }
678
+
679
+ }
680
+
681
+ onBlur();
682
+
683
+ this.dom.addEventListener( 'keydown', onKeyDown );
684
+ this.dom.addEventListener( 'pointerdown', onPointerDown );
685
+ this.dom.addEventListener( 'change', onChange );
686
+ this.dom.addEventListener( 'focus', onFocus );
687
+ this.dom.addEventListener( 'blur', onBlur );
688
+
689
+ }
690
+
691
+ getValue() {
692
+
693
+ return this.value;
694
+
695
+ }
696
+
697
+ setValue( value ) {
698
+
699
+ if ( value !== undefined ) {
700
+
701
+ value = parseFloat( value );
702
+
703
+ if ( value < this.min ) value = this.min;
704
+ if ( value > this.max ) value = this.max;
705
+
706
+ this.value = value;
707
+ this.dom.value = value.toFixed( this.precision );
708
+
709
+ if ( this.unit !== '' ) this.dom.value += ' ' + this.unit;
710
+
711
+ }
712
+
713
+ return this;
714
+
715
+ }
716
+
717
+ setPrecision( precision ) {
718
+
719
+ this.precision = precision;
720
+
721
+ return this;
722
+
723
+ }
724
+
725
+ setStep( step ) {
726
+
727
+ this.step = step;
728
+
729
+ return this;
730
+
731
+ }
732
+
733
+ setNudge( nudge ) {
734
+
735
+ this.nudge = nudge;
736
+
737
+ return this;
738
+
739
+ }
740
+
741
+ setRange( min, max ) {
742
+
743
+ this.min = min;
744
+ this.max = max;
745
+
746
+ return this;
747
+
748
+ }
749
+
750
+ setUnit( unit ) {
751
+
752
+ this.unit = unit;
753
+
754
+ this.setValue( this.value );
755
+
756
+ return this;
757
+
758
+ }
759
+
760
+ }
761
+
762
+ class UIInteger extends UIElement {
763
+
764
+ constructor( number ) {
765
+
766
+ super( document.createElement( 'input' ) );
767
+
768
+ this.dom.style.cursor = 'ns-resize';
769
+ this.dom.className = 'Number Input';
770
+ this.dom.value = '0';
771
+
772
+ this.dom.setAttribute( 'autocomplete', 'off' );
773
+
774
+ this.value = 0;
775
+
776
+ this.min = - Infinity;
777
+ this.max = Infinity;
778
+
779
+ this.step = 1;
780
+ this.nudge = 1;
781
+
782
+ this.setValue( number );
783
+
784
+ const scope = this;
785
+
786
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
787
+
788
+ let distance = 0;
789
+ let onMouseDownValue = 0;
790
+
791
+ const pointer = { x: 0, y: 0 };
792
+ const prevPointer = { x: 0, y: 0 };
793
+
794
+ function onPointerDown( event ) {
795
+
796
+ if ( document.activeElement === scope.dom ) return;
797
+
798
+ event.preventDefault();
799
+
800
+ distance = 0;
801
+
802
+ onMouseDownValue = scope.value;
803
+
804
+ prevPointer.x = event.clientX;
805
+ prevPointer.y = event.clientY;
806
+
807
+ scope.dom.setPointerCapture( event.pointerId );
808
+
809
+ scope.dom.addEventListener( 'pointermove', onPointerMove );
810
+ scope.dom.addEventListener( 'pointerup', onPointerUp );
811
+
812
+ }
813
+
814
+ function onPointerMove( event ) {
815
+
816
+ const currentValue = scope.value;
817
+
818
+ pointer.x = event.clientX;
819
+ pointer.y = event.clientY;
820
+
821
+ distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
822
+
823
+ let value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
824
+ value = Math.min( scope.max, Math.max( scope.min, value ) ) | 0;
825
+
826
+ if ( currentValue !== value ) {
827
+
828
+ scope.setValue( value );
829
+ scope.dom.dispatchEvent( changeEvent );
830
+
831
+ }
832
+
833
+ prevPointer.x = event.clientX;
834
+ prevPointer.y = event.clientY;
835
+
836
+ }
837
+
838
+ function onPointerUp( event ) {
839
+
840
+ scope.dom.releasePointerCapture( event.pointerId );
841
+
842
+ scope.dom.removeEventListener( 'pointermove', onPointerMove );
843
+ scope.dom.removeEventListener( 'pointerup', onPointerUp );
844
+
845
+ if ( Math.abs( distance ) < 2 ) {
846
+
847
+ scope.dom.focus();
848
+ scope.dom.select();
849
+
850
+ }
851
+
852
+ }
853
+
854
+ function onChange() {
855
+
856
+ scope.setValue( scope.dom.value );
857
+
858
+ }
859
+
860
+ function onFocus() {
861
+
862
+ scope.dom.style.backgroundColor = '';
863
+ scope.dom.style.cursor = '';
864
+
865
+ }
866
+
867
+ function onBlur() {
868
+
869
+ scope.dom.style.backgroundColor = 'transparent';
870
+ scope.dom.style.cursor = 'ns-resize';
871
+
872
+ }
873
+
874
+ function onKeyDown( event ) {
875
+
876
+ event.stopPropagation();
877
+
878
+ switch ( event.code ) {
879
+
880
+ case 'Enter':
881
+ scope.dom.blur();
882
+ break;
883
+
884
+ case 'ArrowUp':
885
+ event.preventDefault();
886
+ scope.setValue( scope.getValue() + scope.nudge );
887
+ scope.dom.dispatchEvent( changeEvent );
888
+ break;
889
+
890
+ case 'ArrowDown':
891
+ event.preventDefault();
892
+ scope.setValue( scope.getValue() - scope.nudge );
893
+ scope.dom.dispatchEvent( changeEvent );
894
+ break;
895
+
896
+ }
897
+
898
+ }
899
+
900
+ onBlur();
901
+
902
+ this.dom.addEventListener( 'keydown', onKeyDown );
903
+ this.dom.addEventListener( 'pointerdown', onPointerDown );
904
+ this.dom.addEventListener( 'change', onChange );
905
+ this.dom.addEventListener( 'focus', onFocus );
906
+ this.dom.addEventListener( 'blur', onBlur );
907
+
908
+ }
909
+
910
+ getValue() {
911
+
912
+ return this.value;
913
+
914
+ }
915
+
916
+ setValue( value ) {
917
+
918
+ if ( value !== undefined ) {
919
+
920
+ value = parseInt( value );
921
+
922
+ this.value = value;
923
+ this.dom.value = value;
924
+
925
+ }
926
+
927
+ return this;
928
+
929
+ }
930
+
931
+ setStep( step ) {
932
+
933
+ this.step = parseInt( step );
934
+
935
+ return this;
936
+
937
+ }
938
+
939
+ setNudge( nudge ) {
940
+
941
+ this.nudge = nudge;
942
+
943
+ return this;
944
+
945
+ }
946
+
947
+ setRange( min, max ) {
948
+
949
+ this.min = min;
950
+ this.max = max;
951
+
952
+ return this;
953
+
954
+ }
955
+
956
+ }
957
+
958
+ class UIBreak extends UIElement {
959
+
960
+ constructor() {
961
+
962
+ super( document.createElement( 'br' ) );
963
+
964
+ this.dom.className = 'Break';
965
+
966
+ }
967
+
968
+ }
969
+
970
+ class UIHorizontalRule extends UIElement {
971
+
972
+ constructor() {
973
+
974
+ super( document.createElement( 'hr' ) );
975
+
976
+ this.dom.className = 'HorizontalRule';
977
+
978
+ }
979
+
980
+ }
981
+
982
+ class UIButton extends UIElement {
983
+
984
+ constructor( value ) {
985
+
986
+ super( document.createElement( 'button' ) );
987
+
988
+ this.dom.className = 'Button';
989
+ this.dom.textContent = value;
990
+
991
+ }
992
+
993
+ }
994
+
995
+ class UIProgress extends UIElement {
996
+
997
+ constructor( value ) {
998
+
999
+ super( document.createElement( 'progress' ) );
1000
+
1001
+ this.dom.value = value;
1002
+
1003
+ }
1004
+
1005
+ setValue( value ) {
1006
+
1007
+ this.dom.value = value;
1008
+
1009
+ }
1010
+
1011
+ }
1012
+
1013
+ class UITabbedPanel extends UIDiv {
1014
+
1015
+ constructor() {
1016
+
1017
+ super();
1018
+
1019
+ this.dom.className = 'TabbedPanel';
1020
+
1021
+ this.tabs = [];
1022
+ this.panels = [];
1023
+
1024
+ this.tabsDiv = new UIDiv();
1025
+ this.tabsDiv.setClass( 'Tabs' );
1026
+
1027
+ this.panelsDiv = new UIDiv();
1028
+ this.panelsDiv.setClass( 'Panels' );
1029
+
1030
+ this.add( this.tabsDiv );
1031
+ this.add( this.panelsDiv );
1032
+
1033
+ this.selected = '';
1034
+
1035
+ }
1036
+
1037
+ select( id ) {
1038
+
1039
+ let tab;
1040
+ let panel;
1041
+ const scope = this;
1042
+
1043
+ // Deselect current selection
1044
+ if ( this.selected && this.selected.length ) {
1045
+
1046
+ tab = this.tabs.find( function ( item ) {
1047
+
1048
+ return item.dom.id === scope.selected;
1049
+
1050
+ } );
1051
+ panel = this.panels.find( function ( item ) {
1052
+
1053
+ return item.dom.id === scope.selected;
1054
+
1055
+ } );
1056
+
1057
+ if ( tab ) {
1058
+
1059
+ tab.removeClass( 'selected' );
1060
+
1061
+ }
1062
+
1063
+ if ( panel ) {
1064
+
1065
+ panel.setDisplay( 'none' );
1066
+
1067
+ }
1068
+
1069
+ }
1070
+
1071
+ tab = this.tabs.find( function ( item ) {
1072
+
1073
+ return item.dom.id === id;
1074
+
1075
+ } );
1076
+ panel = this.panels.find( function ( item ) {
1077
+
1078
+ return item.dom.id === id;
1079
+
1080
+ } );
1081
+
1082
+ if ( tab ) {
1083
+
1084
+ tab.addClass( 'selected' );
1085
+
1086
+ }
1087
+
1088
+ if ( panel ) {
1089
+
1090
+ panel.setDisplay( '' );
1091
+
1092
+ }
1093
+
1094
+ this.selected = id;
1095
+
1096
+ // Scrolls to tab
1097
+ if ( tab ) {
1098
+
1099
+ const tabOffsetRight = tab.dom.offsetLeft + tab.dom.offsetWidth;
1100
+ const containerWidth = this.tabsDiv.dom.getBoundingClientRect().width;
1101
+
1102
+ if ( tabOffsetRight > containerWidth ) {
1103
+
1104
+ this.tabsDiv.dom.scrollTo( { left: tabOffsetRight - containerWidth, behavior: 'smooth' } );
1105
+
1106
+ }
1107
+
1108
+ if ( tab.dom.offsetLeft < this.tabsDiv.dom.scrollLeft ) {
1109
+
1110
+ this.tabsDiv.dom.scrollTo( { left: 0, behavior: 'smooth' } );
1111
+
1112
+ }
1113
+
1114
+ }
1115
+
1116
+ return this;
1117
+
1118
+ }
1119
+
1120
+ addTab( id, label, items ) {
1121
+
1122
+ const tab = new UITab( label, this );
1123
+ tab.setId( id );
1124
+ this.tabs.push( tab );
1125
+ this.tabsDiv.add( tab );
1126
+
1127
+ const panel = new UIDiv();
1128
+ panel.setId( id );
1129
+ panel.add( items );
1130
+ panel.setDisplay( 'none' );
1131
+ this.panels.push( panel );
1132
+ this.panelsDiv.add( panel );
1133
+
1134
+ this.select( id );
1135
+
1136
+ }
1137
+
1138
+ }
1139
+
1140
+ class UITab extends UIText {
1141
+
1142
+ constructor( text, parent ) {
1143
+
1144
+ super( text );
1145
+
1146
+ this.dom.className = 'Tab';
1147
+
1148
+ this.parent = parent;
1149
+
1150
+ const scope = this;
1151
+
1152
+ this.dom.addEventListener( 'click', function () {
1153
+
1154
+ scope.parent.select( scope.dom.id );
1155
+
1156
+ } );
1157
+
1158
+ }
1159
+
1160
+ }
1161
+
1162
+ class UIListbox extends UIDiv {
1163
+
1164
+ constructor() {
1165
+
1166
+ super();
1167
+
1168
+ this.dom.className = 'Listbox';
1169
+ this.dom.tabIndex = 0;
1170
+
1171
+ this.items = [];
1172
+ this.types = [];
1173
+ this.listitems = [];
1174
+ this.selectedIndex = 0;
1175
+ this.selectedValue = null;
1176
+
1177
+ }
1178
+
1179
+ setItems( items, types = [] ) {
1180
+
1181
+ if ( Array.isArray( items ) ) {
1182
+
1183
+ this.items = items;
1184
+
1185
+ }
1186
+
1187
+ if ( Array.isArray( types ) ) {
1188
+
1189
+ this.types = types;
1190
+
1191
+ }
1192
+
1193
+ this.render();
1194
+
1195
+ }
1196
+
1197
+ render( ) {
1198
+
1199
+ while ( this.listitems.length ) {
1200
+
1201
+ const item = this.listitems[ 0 ];
1202
+
1203
+ item.dom.remove();
1204
+
1205
+ this.listitems.splice( 0, 1 );
1206
+
1207
+ }
1208
+
1209
+ for ( let i = 0; i < this.items.length; i ++ ) {
1210
+
1211
+ const item = this.items[ i ];
1212
+
1213
+ const listitem = new ListboxItem( this );
1214
+ listitem.setId( item.id || `Listbox-${i}` );
1215
+ listitem.setTextContent( item.name || this.types[ i ] || item.type );
1216
+ this.add( listitem );
1217
+
1218
+ }
1219
+
1220
+ }
1221
+
1222
+ add() {
1223
+
1224
+ const items = Array.from( arguments );
1225
+
1226
+ this.listitems = this.listitems.concat( items );
1227
+
1228
+ UIElement.prototype.add.apply( this, items );
1229
+
1230
+ }
1231
+
1232
+ selectIndex( index ) {
1233
+
1234
+ if ( index >= 0 && index < this.items.length ) {
1235
+
1236
+ this.setValue( this.listitems[ index ].getId() );
1237
+
1238
+ }
1239
+
1240
+ this.selectedIndex = index;
1241
+
1242
+ }
1243
+
1244
+ getValue() {
1245
+
1246
+ return this.selectedValue;
1247
+
1248
+ }
1249
+
1250
+ setValue( value ) {
1251
+
1252
+ for ( let i = 0; i < this.listitems.length; i ++ ) {
1253
+
1254
+ const element = this.listitems[ i ];
1255
+
1256
+ if ( element.getId() === value ) {
1257
+
1258
+ element.addClass( 'active' );
1259
+
1260
+ } else {
1261
+
1262
+ element.removeClass( 'active' );
1263
+
1264
+ }
1265
+
1266
+ }
1267
+
1268
+ this.selectedValue = value;
1269
+
1270
+ const changeEvent = new Event( 'change', { bubbles: true, cancelable: true } );
1271
+ this.dom.dispatchEvent( changeEvent );
1272
+
1273
+ }
1274
+
1275
+ }
1276
+
1277
+ class ListboxItem extends UIDiv {
1278
+
1279
+ constructor( parent ) {
1280
+
1281
+ super();
1282
+
1283
+ this.dom.className = 'ListboxItem';
1284
+
1285
+ this.parent = parent;
1286
+
1287
+ const scope = this;
1288
+
1289
+ function onClick() {
1290
+
1291
+ if ( scope.parent ) {
1292
+
1293
+ scope.parent.setValue( scope.getId( ) );
1294
+
1295
+ }
1296
+
1297
+ }
1298
+
1299
+ this.dom.addEventListener( 'click', onClick );
1300
+
1301
+ }
1302
+
1303
+ }
1304
+
1305
+ export { UIElement, UISpan, UIDiv, UIRow, UIPanel, UIText, UIInput, UITextArea, UISelect, UICheckbox, UIColor, UINumber, UIInteger, UIBreak, UIHorizontalRule, UIButton, UIProgress, UITabbedPanel, UIListbox, ListboxItem };