perfect-gui 4.2.0 → 4.2.1

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/README.md CHANGED
@@ -16,10 +16,24 @@ A nice, simple and (probably not) perfect GUI for JavaScript.
16
16
 
17
17
  ## Install
18
18
 
19
+ ### With NPM
20
+
19
21
  ```bash
20
22
  npm i perfect-gui
21
23
  ```
22
24
 
25
+ ### Import from a CDN
26
+
27
+ ```javascript
28
+ <script type="importmap">
29
+ {
30
+ "imports": {
31
+ "perfect-gui": "https://unpkg.com/perfect-gui@latest/dist/perfect-gui.mjs",
32
+ }
33
+ }
34
+ </script>
35
+ ```
36
+
23
37
  ## Hello world
24
38
 
25
39
  ```javascript
@@ -0,0 +1,722 @@
1
+ function y(w) {
2
+ return (
3
+ /* css */
4
+ `
5
+ .p-gui {
6
+ --main-border-radius: 5px;
7
+ --color-bg: #121212;
8
+ --color-border: #484848;
9
+ --color-border-2: rgba(255,255,255,.1);
10
+ --color-accent: #1681ca;
11
+ --color-accent-hover: #218fda;
12
+
13
+ position: ${w};
14
+ top: 0;
15
+ left: 0;
16
+ transform: translate3d(0,0,0);
17
+ padding-top: 21px;
18
+ background: var(--color-bg);
19
+ display: flex;
20
+ justify-content: center;
21
+ flex-wrap: wrap;
22
+ font-family: Verdana, Arial, sans-serif;
23
+ width: 290px;
24
+ overflow: auto;
25
+ box-shadow: 0 0 2px black;
26
+ box-sizing: border-box;
27
+ z-index: 99999;
28
+ user-select: none;
29
+ border-bottom-right-radius: 3px;
30
+ border-bottom-left-radius: 3px;
31
+ cursor: auto;
32
+ border-radius: var(--main-border-radius);
33
+ border: 1px solid var(--color-border);
34
+ }
35
+
36
+ .p-gui * {
37
+ font-size: 11px;
38
+ }
39
+
40
+ .p-gui::-webkit-scrollbar,
41
+ .p-gui *::-webkit-scrollbar {
42
+ width: 10px;
43
+ }
44
+
45
+ .p-gui::-webkit-scrollbar-track,
46
+ .p-gui *::-webkit-scrollbar-track {
47
+ background: #2f2f2f;
48
+ border-radius: 3px;
49
+ }
50
+
51
+ .p-gui::-webkit-scrollbar-thumb,
52
+ .p-gui *::-webkit-scrollbar-thumb {
53
+ background: #757576;
54
+ border-radius: 10px;
55
+ box-sizing: border-box;
56
+ border: 1px solid #2f2f2f;
57
+ }
58
+
59
+ .p-gui--collapsed {
60
+ height: 0;
61
+ padding: 21px 10px 0 10px;
62
+ overflow: hidden;
63
+ }
64
+
65
+ .p-gui__header {
66
+ position: absolute;
67
+ top: 0;
68
+ left: 0;
69
+ width: 100%;
70
+ height: 20px;
71
+ background-color: rgba(0, 0, 0, .8);
72
+ cursor: grab;
73
+ color: grey;
74
+ font-size: 10px;
75
+ line-height: 20px;
76
+ padding-left: 12px;
77
+ box-sizing: border-box;
78
+ touch-action: none;
79
+ }
80
+
81
+ .p-gui__header-close {
82
+ width: 20px;
83
+ height: 20px;
84
+ position: absolute;
85
+ top: 0;
86
+ right: 5px;
87
+ cursor: pointer;
88
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUAQMAAAC3R49OAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAABFJREFUCNdjIAb8//8BjIkAAOrOBd3TR0jRAAAAAElFTkSuQmCC);
89
+ background-size: 50% 50%;
90
+ background-position: center;
91
+ background-repeat: no-repeat;
92
+ }
93
+
94
+ .p-gui--collapsed .p-gui__header-close {
95
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUAQMAAAC3R49OAAAABlBMVEUAAAD///+l2Z/dAAAAAXRSTlMAQObYZgAAABVJREFUCNdjYEhgIIj///8AwsSoBQD43QydY5mb0QAAAABJRU5ErkJggg==);
96
+ }
97
+
98
+ .p-gui__image-container {
99
+ width: 100%;
100
+ display: grid;
101
+ grid-template-columns: repeat(auto-fill, 32%);
102
+ justify-content: space-between;
103
+ padding: 0 2%;
104
+ }
105
+
106
+ .p-gui__image {
107
+ aspect-ratio: 1 / 1;
108
+ background-size: cover;
109
+ cursor: pointer;
110
+ position: relative;
111
+ margin-top: 1px;
112
+ margin-bottom: 19px;
113
+ }
114
+
115
+ .p-gui__image-text {
116
+ position: absolute;
117
+ bottom: -15px;
118
+ color: #eee;
119
+ text-shadow: 0 -1px 0 #111;
120
+ white-space: nowrap;
121
+ width: 100%;
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ }
125
+
126
+ .p-gui__button,
127
+ .p-gui__switch,
128
+ .p-gui__list,
129
+ .p-gui__vector2,
130
+ .p-gui__color {
131
+ width: 100%;
132
+ padding: 7px 13px;
133
+ color: white;
134
+ cursor: pointer;
135
+ position: relative;
136
+ box-sizing: border-box;
137
+ margin-bottom: 3px;
138
+ margin: 3px;
139
+
140
+ border: 1px solid var(--color-border-2);
141
+ border-radius: var(--main-border-radius);
142
+ }
143
+
144
+ .p-gui__vector2 {
145
+ padding: 7px;
146
+ }
147
+
148
+ .p-gui__button,
149
+ .p-gui__switch {
150
+ margin-right: 4px;
151
+ margin-left: 4px;
152
+ }
153
+
154
+ .p-gui__button {
155
+ background: var(--color-accent);
156
+ text-align: center;
157
+ color: white;
158
+ border: none;
159
+ }
160
+
161
+ .p-gui__button:hover {
162
+ background: var(--color-accent-hover);
163
+ }
164
+
165
+ .p-gui__switch {
166
+ background: rgba(255, 255, 255, .05);
167
+ }
168
+
169
+ .p-gui__switch:hover {
170
+ background: rgba(255, 255, 255, .1);
171
+ }
172
+
173
+ .p-gui__folder .p-gui__button,
174
+ .p-gui__folder .p-gui__switch {
175
+ margin-right: 0;
176
+ margin-left: 0;
177
+ }
178
+
179
+ .p-gui__vector2 {
180
+ background: transparent;
181
+ aspect-ratio: 1;
182
+ padding-bottom: 0;
183
+ }
184
+
185
+ .p-gui__vector2-area {
186
+ position: relative;
187
+ background: rgba(0, 0, 0, .3);
188
+ margin-top: 8px;
189
+ width: 100%;
190
+ height: calc(100% - 28px);
191
+ touch-action: none;
192
+ }
193
+
194
+ .p-gui__vector2-line {
195
+ position: absolute;
196
+ background: white;
197
+ opacity: .3;
198
+ pointer-events: none;
199
+ }
200
+
201
+ .p-gui__vector2-line-x {
202
+ width: 100%;
203
+ height: 1px;
204
+ left: 0;
205
+ top: 50%;
206
+ transform: translateY(-50%);
207
+ }
208
+
209
+ .p-gui__vector2-line-y {
210
+ width: 1px;
211
+ height: 100%;
212
+ top: 0;
213
+ left: 50%;
214
+ transform: translateX(-50%);
215
+ }
216
+
217
+ .p-gui__vector2-dot {
218
+ position: absolute;
219
+ top: 0;
220
+ left: 0;
221
+ width: 8px;
222
+ height: 8px;
223
+ border-radius: 50%;
224
+ background: #d5d5d5;
225
+ border: 2px solid #ff9999;
226
+ transform: translate(-50%, -50%);
227
+ pointer-events: none;
228
+ }
229
+
230
+ .p-gui__switch-checkbox {
231
+ width: 5px;
232
+ height: 5px;
233
+ background-color: rgba(0, 0, 0, .5);
234
+ border: 1px solid grey;
235
+ position: absolute;
236
+ top: 0;
237
+ right: 10px;
238
+ bottom: 0;
239
+ margin: auto;
240
+ border-radius: 50%;
241
+ pointer-events: none;
242
+ }
243
+
244
+ .p-gui__switch-checkbox--active {
245
+ background-color: #00ff89;
246
+ box-shadow: 0 0 7px #00ff89;
247
+ }
248
+
249
+ .p-gui__list,
250
+ .p-gui__color {
251
+ cursor: default;
252
+ }
253
+
254
+ .p-gui__list-dropdown,
255
+ .p-gui__color-picker {
256
+ position: absolute;
257
+ right: 5px;
258
+ top: 0;
259
+ bottom: 0;
260
+ margin: auto;
261
+ height: 21px;
262
+ cursor: pointer;
263
+ border-radius: 3px;
264
+ border: 1px solid var(--color-border-2);
265
+ }
266
+
267
+ .p-gui__list-dropdown {
268
+ background: rgba(255, 255, 255,.05);
269
+ color: white;
270
+ padding: 0 12px;
271
+ top: 0px;
272
+ }
273
+
274
+ .p-gui__list-dropdown:hover {
275
+ background: rgba(255, 255, 255, .1);
276
+ }
277
+
278
+ .p-gui__color-picker {
279
+ -webkit-appearance: none;
280
+ padding: 0;
281
+ background-color: transparent;
282
+ border: 1px solid #222222;
283
+ overflow: hidden;
284
+ }
285
+
286
+ .p-gui__color-picker::-webkit-color-swatch-wrapper {
287
+ padding: 0;
288
+ }
289
+ .p-gui__color-picker::-webkit-color-swatch {
290
+ border: none;
291
+ }
292
+
293
+ .p-gui__slider {
294
+ width: 100%;
295
+ margin-bottom: 8px;
296
+ padding: 7px;
297
+ color: white;
298
+ position: relative;
299
+ min-height: 14px;
300
+ }
301
+
302
+ .p-gui__slider-ctrl {
303
+ -webkit-appearance: none;
304
+ padding: 0;
305
+ font: inherit;
306
+ outline: none;
307
+ opacity: .8;
308
+ background: var(--color-accent);
309
+ box-sizing: border-box;
310
+ cursor: pointer;
311
+ position: absolute;
312
+ bottom: -4px; /* 5px height -1px de dépassement du curseur */
313
+ right: 0;
314
+ height: 5px;
315
+ width: 100%;
316
+ margin: 0;
317
+ }
318
+
319
+ /* la zone de déplacement */
320
+ .p-gui__slider-ctrl::-webkit-slider-runnable-track {
321
+ height: 13px;
322
+ border: none;
323
+ border-radius: 0;
324
+ background-color: transparent; /* supprimé définie sur l'input */
325
+ }
326
+
327
+ /* Curseur */
328
+ .p-gui__slider-ctrl::-webkit-slider-thumb {
329
+ -webkit-appearance: none; /* également nécessaire sur le curseur */
330
+ width: 15px;
331
+ height: 7px;
332
+ border: none; /* pris en compte sur Webkit et Edge */
333
+ background: white; /* pris en compte sur Webkit only */
334
+ position: relative;
335
+ top: 3px;
336
+ border-radius: 1px;
337
+ }
338
+
339
+ .p-gui__slider-value,
340
+ .p-gui__vector-value {
341
+ display: inline-block;
342
+ position: absolute;
343
+ right: 7px;
344
+ }
345
+
346
+ .p-gui__folder {
347
+ width: 100%;
348
+ position: relative;
349
+ background: #434343;
350
+ overflow: auto;
351
+ margin-bottom: 3px;
352
+ display: flex;
353
+ flex-wrap: wrap;
354
+ border-left: 3px solid grey;
355
+ border-bottom: 1px solid grey;
356
+ padding: 0 3px;
357
+ }
358
+
359
+ .p-gui__folder:last-of-type {
360
+ margin-bottom: 0;
361
+ border-bottom: none;
362
+ }
363
+
364
+ .p-gui__folder--first {
365
+ margin-top: 0;
366
+ }
367
+
368
+ .p-gui__folder--closed {
369
+ height: 32px;
370
+ overflow: hidden;
371
+ }
372
+
373
+ .p-gui__folder-header {
374
+ padding: 10px 5px;
375
+ background-color: rgba(0, 0, 0, .5);
376
+ color: white;
377
+ cursor: pointer;
378
+ width: 100%;
379
+ margin: 0 -2px 2px -3px;
380
+ }
381
+
382
+ .p-gui__folder-header:hover {
383
+ background-color: rgba(0, 0, 0, .75);
384
+ }
385
+
386
+ .p-gui__folder-arrow {
387
+ width: 8px;
388
+ height: 8px;
389
+ display: inline-block;
390
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAAD///////////////////////////////////8kfJuVAAAACXRSTlMA9Z1fCdMo1yxEJnA0AAAAK0lEQVQI12PABlRgjKkJUMZMYRhjpgqMAZSEMICSaIzpDWiKhdENhEhgAgATSg5jyWnYewAAAABJRU5ErkJggg==);
391
+ background-size: contain;
392
+ margin-right: 5px;
393
+ transform: rotate(90deg)
394
+ }
395
+
396
+ .p-gui__folder--closed .p-gui__folder-arrow {
397
+ transform: rotate(0deg);
398
+ }
399
+ `
400
+ );
401
+ }
402
+ class h {
403
+ constructor(e = {}) {
404
+ if (e.container ? (this.container = typeof e.container == "string" ? document.querySelector(e.container) : e.container, this.position_type = "absolute") : (this.container = document.body, this.position_type = "fixed"), this.propReferences = [], this.folders = [], e.isFolder) {
405
+ this._folderConstructor(e.folderOptions);
406
+ return;
407
+ }
408
+ this.name = e != null && typeof e.name == "string" ? e.name : "", this.backgroundColor = e.color || null, this.container == document.body ? this.maxHeight = window.innerHeight : this.maxHeight = Math.min(this.container.clientHeight, window.innerHeight), e.maxHeight && (this.initMaxHeight = e.maxHeight, this.maxHeight = Math.min(this.initMaxHeight, this.maxHeight)), this.screenCorner = this._parseScreenCorner(e.position), this instanceof h && (typeof h[h.instanceCounter] != "number" ? h[h.instanceCounter] = 0 : h[h.instanceCounter]++), this.instanceId = h[h.instanceCounter], this.wrapperWidth = e.width || 290, this.stylesheet = document.createElement("style"), this.stylesheet.setAttribute("type", "text/css"), this.stylesheet.setAttribute("id", "lm-gui-stylesheet"), document.head.append(this.stylesheet), this.instanceId == 0 && this._addStyles(`${y(this.position_type)}`), this._styleInstance(), this._addWrapper(), this.wrapper.setAttribute("data-corner-x", this.screenCorner.x), this.wrapper.setAttribute("data-corner-y", this.screenCorner.y), e.autoRepositioning != !1 && window.addEventListener("resize", this._handleResize.bind(this)), this._handleResize(), this.hasBeenDragged = !1, e.draggable == !0 && this._makeDraggable(), this.closed = !1, e.closed && this.toggleClose();
409
+ }
410
+ _styleInstance() {
411
+ let e = this._getScrollbarWidth(this.container);
412
+ if (this.screenCorner.x == "left" ? this.xOffset = 0 : this.xOffset = this.container.clientWidth - this.wrapperWidth - e, this.instanceId > 0) {
413
+ let t = this.container.querySelectorAll(".p-gui");
414
+ for (let i = 0; i < t.length; i++)
415
+ this.screenCorner.y == t[i].dataset.cornerY && (this.screenCorner.x == "left" && t[i].dataset.cornerX == "left" ? this.xOffset += t[i].offsetWidth : this.screenCorner.x == "right" && t[i].dataset.cornerX == "right" && (this.xOffset -= t[i].offsetWidth));
416
+ }
417
+ this.yOffset = 0, this.position = {
418
+ prevX: this.xOffset,
419
+ prevY: this.yOffset,
420
+ x: this.xOffset,
421
+ y: this.yOffset
422
+ }, this._addStyles(`#p-gui-${this.instanceId} {
423
+ width: ${this.wrapperWidth}px;
424
+ max-height: ${this.maxHeight}px;
425
+ transform: translate3d(${this.xOffset}px,${this.yOffset}px,0);
426
+ ${this.screenCorner.y == "top" ? "" : "top: auto; bottom: 0;"}
427
+ ${this.backgroundColor ? "background: " + this.backgroundColor + ";" : ""}
428
+ }`);
429
+ }
430
+ _folderConstructor(e) {
431
+ this.wrapper = e.wrapper;
432
+ }
433
+ _parseScreenCorner(e) {
434
+ let t = { x: "right", y: "top" };
435
+ return e == null || (typeof e != "string" && console.error("[perfect-gui] Position must be a string."), e.includes("left") && (t.x = "left"), e.includes("bottom") && (t.y = "bottom")), t;
436
+ }
437
+ _getScrollbarWidth(e) {
438
+ return e === document.body ? window.innerWidth - document.documentElement.clientWidth : e.offsetWidth - e.clientWidth;
439
+ }
440
+ _handleResize() {
441
+ if (this.container == document.body ? this.maxHeight = window.innerHeight : this.maxHeight = Math.min(this.container.clientHeight, window.innerHeight), this.initMaxHeight && (this.maxHeight = Math.min(this.initMaxHeight, this.maxHeight)), this.wrapper.style.maxHeight = this.maxHeight + "px", this.hasBeenDragged)
442
+ return;
443
+ let e = this._getScrollbarWidth(this.container);
444
+ if (this.xOffset = this.screenCorner.x == "left" ? 0 : this.container.clientWidth - this.wrapperWidth - e, this.instanceId > 0) {
445
+ let t = this.container.querySelectorAll(`.p-gui:not(#${this.wrapper.id}):not([data-dragged])`);
446
+ for (let i = 0; i < t.length && !(parseInt(t[i].id.replace("p-gui-", "")) > this.instanceId); i++)
447
+ this.screenCorner.y == t[i].dataset.cornerY && (this.screenCorner.x == "left" && t[i].dataset.cornerX == "left" ? this.xOffset += t[i].offsetWidth : this.screenCorner.x == "right" && t[i].dataset.cornerX == "right" && (this.xOffset -= t[i].offsetWidth));
448
+ }
449
+ this.position = { prevX: this.xOffset, prevY: this.yOffset, x: this.xOffset, y: this.yOffset }, this.wrapper.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0)`;
450
+ }
451
+ _createElement(e) {
452
+ e.el = e.el || "div";
453
+ var t = document.createElement(e.el);
454
+ if (e.id && (t.id = e.id), e.class && (t.className = e.class), e.inline && (t.style = e.inline), e.href && (t.href = e.href), e.onclick && (t.onclick = e.onclick), e.onchange && (t.onchange = e.onchange), e.textContent && (t.textContent = e.textContent), e.innerHTML && (t.innerHTML = e.innerHTML), e.type && (t.type = e.type), e.value && (t.value = e.value), e.customAttributes)
455
+ for (var i in e.customAttributes)
456
+ t.setAttribute(i, e.customAttributes[i]);
457
+ return e.parent = e.parent ? e.parent : this.wrapper, e.parent.append(t), t;
458
+ }
459
+ _addStyles(e) {
460
+ this.stylesheet.innerHTML += e;
461
+ }
462
+ _addWrapper() {
463
+ this.wrapper = this._createElement({
464
+ parent: this.container,
465
+ id: "p-gui-" + this.instanceId,
466
+ class: "p-gui"
467
+ }), this.header = this._createElement({
468
+ parent: this.wrapper,
469
+ class: "p-gui__header",
470
+ textContent: this.name,
471
+ inline: `${this.backgroundColor ? "border-color: " + this.backgroundColor + ";" : ""}`
472
+ }), this._createElement({
473
+ parent: this.header,
474
+ class: "p-gui__header-close",
475
+ onclick: this.toggleClose.bind(this)
476
+ });
477
+ }
478
+ button(e, t) {
479
+ typeof e != "string" && (typeof e == "object" && (e != null && e.hasOwnProperty("name")) ? e = e.name : e = " "), e === "" && (e = " "), this.imageContainer = null, typeof t != "function" && (t = () => {
480
+ }), this._createElement({
481
+ class: "p-gui__button",
482
+ textContent: e,
483
+ onclick: t
484
+ });
485
+ }
486
+ image(e = {}, t) {
487
+ if (typeof e != "object")
488
+ throw Error(`[GUI] image() first parameter must be an object. Received: ${typeof e}.`);
489
+ let i;
490
+ if (typeof e.path == "string")
491
+ i = e.path;
492
+ else
493
+ throw typeof e.path == null ? Error("[GUI] image() path must be provided.") : Error("[GUI] image() path must be a string.");
494
+ let o = i.replace(/^.*[\\\/]/, ""), r;
495
+ e.name == null ? r = o : r = typeof e.name == "string" && e.name || " ", this.imageContainer || (this.imageContainer = this._createElement({
496
+ class: "p-gui__image-container"
497
+ }));
498
+ var n = this._createElement({
499
+ class: "p-gui__image",
500
+ inline: `background-image: url(${i})`,
501
+ parent: this.imageContainer
502
+ });
503
+ this._createElement({
504
+ parent: n,
505
+ class: "p-gui__image-text",
506
+ textContent: r
507
+ }), typeof t == "function" && (n.onclick = () => t({ path: i, text: r }));
508
+ }
509
+ slider(e = {}, t) {
510
+ if (typeof e != "object")
511
+ throw Error(`[GUI] slider() first parameter must be an object. Received: ${typeof e}.`);
512
+ let i = typeof e.name == "string" && e.name || " ", o = !1, r = null, n = e.obj || e.object, s = e.prop || e.property, a = typeof e.value == "number" ? e.value : null, p = e.min ?? 0, f = e.max ?? 1, g = e.step || (f - p) / 100;
513
+ if (a !== null)
514
+ (s != null || n != null) && console.warn('[GUI] slider() "obj" and "property" parameters are ignored when a "value" parameter is used.');
515
+ else if (s != null && n != null) {
516
+ if (typeof s != "string")
517
+ throw Error(`[GUI] slider() "prop" (or "property") parameter must be an string. Received: ${typeof s}.`);
518
+ if (typeof n != "object")
519
+ throw Error(`[GUI] slider() "obj" (or "object") parameter must be an object. Received: ${typeof n}.`);
520
+ i == " " && (i = s), r = this.propReferences.push(n[s]) - 1, o = !0;
521
+ } else
522
+ (s != null && n == null || s == null && n == null) && console.warn('[GUI] slider() "obj" and "prop" parameters must be used together.'), a = (f - p) / 2;
523
+ this.imageContainer = null;
524
+ var d = this._createElement({
525
+ class: "p-gui__slider",
526
+ textContent: i
527
+ }), u = this._createElement({
528
+ parent: d,
529
+ el: "input",
530
+ class: "p-gui__slider-ctrl",
531
+ customAttributes: {
532
+ type: "range",
533
+ min: p,
534
+ max: f,
535
+ step: g,
536
+ value: o ? n[s] : a
537
+ }
538
+ }), _ = this._createElement({
539
+ parent: d,
540
+ class: "p-gui__slider-value",
541
+ textContent: String(o ? n[s] : a)
542
+ });
543
+ u.addEventListener("input", () => {
544
+ _.textContent = u.value, o && (n[s] = u.value), typeof t == "function" && t(parseFloat(u.value));
545
+ }), o && Object.defineProperty(n, s, {
546
+ set: (b) => {
547
+ this.propReferences[r] = b, u.value = b, _.textContent = String(b);
548
+ },
549
+ get: () => this.propReferences[r]
550
+ });
551
+ }
552
+ toggle(e = {}, t) {
553
+ if (typeof e != "object")
554
+ throw Error(`[GUI] toggle() first parameter must be an object. Received: ${typeof e}.`);
555
+ let i = typeof e.name == "string" && e.name || " ", o = e.value === !0;
556
+ this.imageContainer = null;
557
+ let r = this._createElement({
558
+ class: "p-gui__switch",
559
+ onclick: (s) => {
560
+ let a = s.target.childNodes[1], p = !0;
561
+ a.classList.contains("p-gui__switch-checkbox--active") && (p = !1), a.classList.toggle("p-gui__switch-checkbox--active"), typeof t == "function" && t(p);
562
+ },
563
+ textContent: i
564
+ }), n = o ? " p-gui__switch-checkbox--active" : "";
565
+ this._createElement({
566
+ parent: r,
567
+ class: "p-gui__switch-checkbox" + n
568
+ });
569
+ }
570
+ list(e = {}, t) {
571
+ if (typeof e != "object")
572
+ throw Error(`[GUI] list() first parameter must be an object. Received: ${typeof e}.`);
573
+ let i = typeof e.name == "string" ? e.name : " ", o = Array.isArray(e.values) ? e.values : null;
574
+ t = typeof t == "function" ? t : null, this.imageContainer = null;
575
+ let r = this._createElement({
576
+ class: "p-gui__list",
577
+ textContent: i
578
+ }), n = this._createElement({
579
+ parent: r,
580
+ el: "select",
581
+ class: "p-gui__list-dropdown",
582
+ onchange: (s) => {
583
+ t && t(s.target.value);
584
+ }
585
+ });
586
+ o.forEach((s) => {
587
+ this._createElement({
588
+ parent: n,
589
+ el: "option",
590
+ customAttributes: {
591
+ value: s
592
+ },
593
+ textContent: s
594
+ });
595
+ });
596
+ }
597
+ options(e, t) {
598
+ if (typeof e != "object")
599
+ throw Error(`[GUI] options() first parameter must be an object. Received: ${typeof e}.`);
600
+ this.list(e, t);
601
+ }
602
+ vector2(e = {}, t) {
603
+ if (typeof e != "object")
604
+ throw Error(`[GUI] vector2() first parameter must be an object. Received: ${typeof e}.`);
605
+ let i = typeof e.name == "string" && e.name || " ";
606
+ const o = e.x.min ?? 0, r = e.x.max ?? 1, n = e.y.min ?? 0, s = e.y.max ?? 1, a = e.x.obj || e.x.object, p = e.x.prop || e.x.property, f = this.propReferences.push(a[p]) - 1, g = e.y.obj || e.y.object, d = e.y.prop || e.y.property, u = this.propReferences.push(g[d]) - 1;
607
+ t = typeof t == "function" ? t : null, this.imageContainer = null;
608
+ const _ = this._createElement({
609
+ class: "p-gui__vector2",
610
+ textContent: i
611
+ }), b = this._createElement({
612
+ parent: _,
613
+ class: "p-gui__vector-value",
614
+ textContent: a[p] + ", " + g[d]
615
+ }), l = this._createElement({
616
+ parent: _,
617
+ el: "div",
618
+ class: "p-gui__vector2-area",
619
+ onclick: (c) => {
620
+ a[p] = parseFloat(this._mapLinear(c.offsetX, 0, l.clientWidth, o, r).toFixed(2)), g[d] = parseFloat(this._mapLinear(c.offsetY, 0, l.clientHeight, s, n).toFixed(2)), t && t(a[p], a[d]);
621
+ }
622
+ });
623
+ let m = !1;
624
+ l.addEventListener("pointerdown", (c) => {
625
+ m = !0;
626
+ }), l.addEventListener("pointerup", () => {
627
+ m = !1;
628
+ }), l.addEventListener("pointermove", (c) => {
629
+ m && (a[p] = parseFloat(this._mapLinear(c.offsetX, 0, l.clientWidth, o, r).toFixed(2)), g[d] = parseFloat(this._mapLinear(c.offsetY, 0, l.clientHeight, s, n).toFixed(2)), t && t(a[p], a[d]));
630
+ }), this._createElement({
631
+ parent: l,
632
+ class: "p-gui__vector2-line p-gui__vector2-line-x"
633
+ }), this._createElement({
634
+ parent: l,
635
+ class: "p-gui__vector2-line p-gui__vector2-line-y"
636
+ });
637
+ const x = this._createElement({
638
+ parent: l,
639
+ class: "p-gui__vector2-dot"
640
+ });
641
+ x.style.left = this._mapLinear(a[p], o, r, 0, l.clientWidth) + "px", x.style.top = this._mapLinear(g[d], n, s, l.clientHeight, 0) + "px", Object.defineProperty(a, p, {
642
+ set: (c) => {
643
+ this.propReferences[f] = c, x.style.left = this._mapLinear(c, o, r, 0, l.clientWidth) + "px", b.textContent = String(c) + ", " + g[d];
644
+ },
645
+ get: () => this.propReferences[f]
646
+ }), Object.defineProperty(g, d, {
647
+ set: (c) => {
648
+ this.propReferences[u] = c, x.style.top = this._mapLinear(c, n, s, l.clientHeight, 0) + "px", b.textContent = a[p] + ", " + String(c);
649
+ },
650
+ get: () => this.propReferences[u]
651
+ });
652
+ }
653
+ color(e = {}, t) {
654
+ if (typeof e != "object")
655
+ throw Error(`[GUI] color() first parameter must be an object. Received: ${typeof e}.`);
656
+ let i = typeof e.name == "string" && e.name || " ", o;
657
+ typeof e.value == "string" && (e.value.length != 7 || e.value[0] != "#" ? console.error(`[GUI] color() 'value' parameter must be an hexadecimal string in the format "#ffffff". Received: "${e.value}".`) : o = e.value), o || (o = "#000000");
658
+ const r = this._createElement({
659
+ el: "div",
660
+ class: "p-gui__color",
661
+ textContent: i
662
+ }), n = this._createElement({
663
+ parent: r,
664
+ el: "input",
665
+ class: "p-gui__color-picker",
666
+ type: "color",
667
+ value: o
668
+ });
669
+ typeof t == "function" && n.addEventListener("input", () => {
670
+ t(n.value);
671
+ });
672
+ }
673
+ folder(e = {}) {
674
+ let t = typeof e.closed == "boolean" ? e.closed : !1, i = e.name || "", o = e.color || null, r = e.maxHeight || null;
675
+ this.imageContainer = null;
676
+ let n = "p-gui__folder";
677
+ this.folders.length == 0 && (n += " p-gui__folder--first"), t && (n += " p-gui__folder--closed");
678
+ let s = o ? `background-color: ${o};` : "";
679
+ s += r ? `max-height: ${r}px;` : "";
680
+ let a = this._createElement({
681
+ class: n,
682
+ inline: s
683
+ });
684
+ this._createElement({
685
+ innerHTML: `<span class="p-gui__folder-arrow"></span>${i}`,
686
+ class: "p-gui__folder-header",
687
+ onclick: function() {
688
+ this.parentNode.classList.toggle("p-gui__folder--closed");
689
+ },
690
+ parent: a
691
+ });
692
+ let p = new h({ isFolder: !0, folderOptions: {
693
+ wrapper: a
694
+ } });
695
+ return this.folders.push(p), p;
696
+ }
697
+ _makeDraggable() {
698
+ var e = this;
699
+ this.header.addEventListener("pointerdown", t), this.header.addEventListener("pointerup", o);
700
+ function t(r) {
701
+ r.preventDefault(), e.position.initX = e.position.x, e.position.initY = e.position.y, e.position.prevX = r.clientX, e.position.prevY = r.clientY, document.addEventListener("pointermove", i);
702
+ }
703
+ function i(r) {
704
+ r.preventDefault(), e.hasBeenDragged || (e.hasBeenDragged = !0, e.wrapper.setAttribute("data-dragged", "true")), e.position.x = e.position.initX + r.clientX - e.position.prevX, e.position.y = e.position.initY + r.clientY - e.position.prevY, e.wrapper.style.transform = "translate3d(" + e.position.x + "px," + e.position.y + "px,0)";
705
+ }
706
+ function o(r) {
707
+ document.removeEventListener("pointermove", i);
708
+ }
709
+ }
710
+ toggleClose() {
711
+ this.closed = !this.closed, this.wrapper.classList.toggle("p-gui--collapsed");
712
+ }
713
+ kill() {
714
+ this.wrapper.remove();
715
+ }
716
+ _mapLinear(e, t, i, o, r) {
717
+ return o + (e - t) * (r - o) / (i - t);
718
+ }
719
+ }
720
+ export {
721
+ h as default
722
+ };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "perfect-gui",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "Nice and simple GUI for JavaScript",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "build": "vite build"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
@@ -18,5 +18,8 @@
18
18
  "bugs": {
19
19
  "url": "https://github.com/thibka/perfect-gui/issues"
20
20
  },
21
- "homepage": "https://thibka.github.io/perfect-gui/public/"
21
+ "homepage": "https://thibka.github.io/perfect-gui/public/",
22
+ "devDependencies": {
23
+ "vite": "^4.5.0"
24
+ }
22
25
  }
package/vite.config.js ADDED
@@ -0,0 +1,11 @@
1
+ import { resolve } from "path";
2
+ import { defineConfig } from "vite";
3
+
4
+ export default defineConfig({
5
+ build: {
6
+ lib: {
7
+ entry: resolve(__dirname, "src/index.js"),
8
+ name: "Perfect GUI"
9
+ }
10
+ },
11
+ });