muigui 0.0.1 → 0.0.3
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 +72 -7
- package/package.json +10 -6
- package/src/controllers/Button.js +34 -0
- package/src/controllers/Canvas.js +17 -0
- package/src/controllers/Checkbox.js +11 -0
- package/src/controllers/Color.js +31 -0
- package/src/controllers/ColorChooser.js +12 -0
- package/src/controllers/Container.js +58 -0
- package/src/controllers/Controller.js +138 -0
- package/src/controllers/Direction.js +23 -0
- package/src/controllers/Divider.js +9 -0
- package/src/controllers/Folder.js +37 -0
- package/src/controllers/Label.js +14 -0
- package/src/controllers/LabelController.js +32 -0
- package/src/controllers/PopDownController.js +84 -0
- package/src/controllers/RadioGrid.js +17 -0
- package/src/controllers/Range.js +11 -0
- package/src/controllers/Select.js +14 -0
- package/src/controllers/Slider.js +12 -0
- package/src/controllers/TabHolder.js +36 -0
- package/src/controllers/Text.js +10 -0
- package/src/controllers/TextNumber.js +18 -0
- package/src/controllers/ValueController.js +107 -0
- package/src/controllers/Vec2.js +50 -0
- package/src/controllers/create-controller.js +49 -0
- package/src/layout/Column.js +7 -0
- package/src/layout/Frame.js +11 -0
- package/src/layout/Grid.js +7 -0
- package/src/layout/Layout.js +47 -0
- package/src/layout/Row.js +7 -0
- package/src/libs/assert.js +5 -0
- package/src/libs/color-utils.js +406 -0
- package/src/libs/conversions.js +14 -0
- package/src/libs/css-utils.js +3 -0
- package/src/libs/elem.js +8 -3
- package/src/libs/emitter.js +68 -0
- package/src/libs/iterable-array.js +57 -0
- package/src/libs/key-values.js +25 -0
- package/src/libs/keyboard.js +32 -0
- package/src/libs/resize-helpers.js +22 -0
- package/src/libs/svg.js +33 -0
- package/src/libs/taskrunner.js +56 -0
- package/src/libs/touch.js +50 -0
- package/src/libs/utils.js +38 -2
- package/src/libs/wheel.js +10 -0
- package/src/muigui.js +79 -19
- package/src/styles/muigui.css.js +641 -0
- package/src/umd.js +3 -0
- package/src/views/CheckboxView.js +21 -0
- package/src/views/ColorChooserView.js +124 -0
- package/src/views/ColorView.js +50 -0
- package/src/views/DirectionView.js +127 -0
- package/src/views/EditView.js +100 -0
- package/src/views/ElementView.js +8 -0
- package/src/views/GridView.js +15 -0
- package/src/views/NumberView.js +67 -0
- package/src/views/RadioGridView.js +46 -0
- package/src/views/RangeView.js +73 -0
- package/src/views/SelectView.js +23 -0
- package/src/views/SliderView.js +194 -0
- package/src/views/TextView.js +49 -0
- package/src/views/ValueView.js +11 -0
- package/src/views/Vec2View.js +51 -0
- package/src/views/View.js +56 -0
- package/src/widgets/checkbox.js +0 -0
- package/src/widgets/divider.js +0 -0
- package/src/widgets/menu.js +0 -0
- package/src/widgets/radio.js +0 -0
- package/src/widgets/select.js +0 -1
- package/src/widgets/slider.js +0 -41
- package/src/widgets/text.js +0 -0
- package/src/widgets/widget.js +0 -51
package/README.md
CHANGED
|
@@ -1,29 +1,94 @@
|
|
|
1
1
|
# muigui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# NOT READY for USE
|
|
4
|
+
|
|
5
|
+
<!---
|
|
4
6
|
|
|
5
7
|
<img src="./images/muigui.png" style="max-width: 640px">
|
|
6
8
|
|
|
7
9
|
A simple Web UI library.
|
|
8
10
|
|
|
9
11
|
muigui is a simple UI library in the spirit of
|
|
10
|
-
[dat.gui](https://github.com/dataarts/dat.gui).
|
|
12
|
+
[dat.gui](https://github.com/dataarts/dat.gui) and/or [lil-gui](https://github.com/georgealways/).
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
import GUI from 'https://muigui.org/dist/0.x/muigui.module.js';
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<script src="https://muigui.org/dist/0.x/muigui.min.js"></script>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const s = {
|
|
30
|
+
someNumber: 123,
|
|
31
|
+
someString: "hello",
|
|
32
|
+
someOption: "dog",
|
|
33
|
+
someColor: '#ED3281',
|
|
34
|
+
someFunction: () => console.log('called')
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const gui = new GUI();
|
|
38
|
+
gui.add(s, 'someNumber', 0, 200); // range 0 to 200
|
|
39
|
+
gui.add(s, 'someString);
|
|
40
|
+
gui.add(s, 'someOption, ['cat', 'bird', 'dog']);
|
|
41
|
+
gui.addColor(s, 'someColor');
|
|
42
|
+
gui.add(s, 'someFunction');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
produces
|
|
46
|
+
|
|
47
|
+
<img src="./images/muigui-screenshot.png" style="max-width: 275px">
|
|
48
|
+
|
|
49
|
+
or a shorter version
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const s = {
|
|
53
|
+
someNumber: 123,
|
|
54
|
+
someString: "hello",
|
|
55
|
+
someOption: "dog",
|
|
56
|
+
someColor: '#ED3281',
|
|
57
|
+
someFunction: () => console.log('called')
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const options = {
|
|
61
|
+
someNumber: [1, 200], // range 0 to 200
|
|
62
|
+
someOption: ['cat', 'bird', 'dog'],
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const gui = new GUI();
|
|
66
|
+
gui.add(s, options);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## What
|
|
11
70
|
|
|
12
71
|
It is not a general purpose library for every type of GUI.
|
|
13
72
|
Rather, it is a small, easy to use library for small apps.
|
|
14
73
|
Basically I liked how simple it was to use dat.gui to add
|
|
15
|
-
a few sliders and options to a demo.
|
|
16
|
-
|
|
17
|
-
try to make a DOM based UI
|
|
18
|
-
require CSS to style it and see how far I got.
|
|
74
|
+
a few sliders and options to a demo.
|
|
75
|
+
|
|
76
|
+
I thought I'd try to make a CSS/DOM based UI standard elements
|
|
77
|
+
only and then require CSS to style it and see how far I got.
|
|
19
78
|
|
|
20
79
|
### Not invented here syndrome
|
|
21
80
|
|
|
22
81
|
It's possible this already exists but if so I couldn't find it.
|
|
23
82
|
Most UI libraries seem to be giant and require a build step.
|
|
24
|
-
I wanted something hopefully not
|
|
83
|
+
I wanted something hopefully not too big and something I could
|
|
25
84
|
easily add to any example with 1 file (or 2 if you add CSS).
|
|
26
85
|
|
|
86
|
+
## muigui - wat?
|
|
87
|
+
|
|
88
|
+
https://user-images.githubusercontent.com/234804/177000460-3449c2dd-da94-4119-903f-cc7460b46e7b.mp4
|
|
89
|
+
|
|
90
|
+
-->
|
|
91
|
+
|
|
27
92
|
## License
|
|
28
93
|
|
|
29
94
|
[MIT](https://github.com/greggman/muigui/blob/main/LICENSE.md)
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muigui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "A Simple GUI",
|
|
5
5
|
"main": "muigui.js",
|
|
6
6
|
"module": "src/muigui.js",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"scripts": {
|
|
8
|
-
"build": "
|
|
9
|
+
"build": "npm run build-normal",
|
|
10
|
+
"build-normal": "rollup -c",
|
|
11
|
+
"build-min": "rollup -c",
|
|
9
12
|
"eslint": "eslint \"**/*.js\"",
|
|
10
13
|
"pre-push": "npm run eslint",
|
|
11
14
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -30,11 +33,12 @@
|
|
|
30
33
|
],
|
|
31
34
|
"homepage": "https://github.com/greggman/muiguiy#readme",
|
|
32
35
|
"devDependencies": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
36
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
37
|
+
"@rollup/plugin-terser": "^0.4.0",
|
|
38
|
+
"eslint": "^8.20.0",
|
|
39
|
+
"eslint-plugin-html": "^7.1.0",
|
|
35
40
|
"eslint-plugin-optional-comma-spacing": "0.0.4",
|
|
36
41
|
"eslint-plugin-require-trailing-comma": "0.0.1",
|
|
37
|
-
"rollup": "^
|
|
38
|
-
"rollup-plugin-node-resolve": "^5.2.0"
|
|
42
|
+
"rollup": "^3.20.2"
|
|
39
43
|
}
|
|
40
44
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createElem,
|
|
3
|
+
} from '../libs/elem.js';
|
|
4
|
+
import { copyExistingProperties } from '../libs/utils.js';
|
|
5
|
+
import Controller from './Controller.js';
|
|
6
|
+
|
|
7
|
+
export default class Button extends Controller {
|
|
8
|
+
#object;
|
|
9
|
+
#property;
|
|
10
|
+
#buttonElem;
|
|
11
|
+
#options = {
|
|
12
|
+
name: '',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
constructor(object, property, options = {}) {
|
|
16
|
+
super('muigui-button', '');
|
|
17
|
+
this.#object = object;
|
|
18
|
+
this.#property = property;
|
|
19
|
+
|
|
20
|
+
this.#buttonElem = this.addElem(
|
|
21
|
+
createElem('button', {
|
|
22
|
+
type: 'button',
|
|
23
|
+
onClick: () => {
|
|
24
|
+
this.#object[this.#property](this);
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
this.setOptions({name: property, ...options});
|
|
28
|
+
}
|
|
29
|
+
setOptions(options) {
|
|
30
|
+
copyExistingProperties(this.#options, options);
|
|
31
|
+
const {name} = this.#options;
|
|
32
|
+
this.#buttonElem.textContent = name;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import ElementView from '../views/ElementView.js';
|
|
2
|
+
import LabelController from './LabelController.js';
|
|
3
|
+
|
|
4
|
+
// TODO: remove this? Should just be user side
|
|
5
|
+
export default class Canvas extends LabelController {
|
|
6
|
+
#canvasElem;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
super('muigui-canvas');
|
|
10
|
+
this.#canvasElem = this.add(
|
|
11
|
+
new ElementView('canvas', 'muigui-canvas'),
|
|
12
|
+
).domElement;
|
|
13
|
+
}
|
|
14
|
+
get canvas() {
|
|
15
|
+
return this.#canvasElem;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import CheckboxView from '../views/CheckboxView.js';
|
|
2
|
+
import ValueController from './ValueController.js';
|
|
3
|
+
|
|
4
|
+
export default class Checkbox extends ValueController {
|
|
5
|
+
constructor(object, property) {
|
|
6
|
+
super(object, property, 'muigui-checkbox');
|
|
7
|
+
const id = this.id;
|
|
8
|
+
this.add(new CheckboxView(this, id));
|
|
9
|
+
this.updateDisplay();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
colorFormatConverters,
|
|
3
|
+
guessFormat,
|
|
4
|
+
} from '../libs/color-utils.js';
|
|
5
|
+
import ValueController from './ValueController.js';
|
|
6
|
+
import TextView from '../views/TextView.js';
|
|
7
|
+
import ColorView from '../views/ColorView.js';
|
|
8
|
+
|
|
9
|
+
export default class Color extends ValueController {
|
|
10
|
+
#colorView;
|
|
11
|
+
#textView;
|
|
12
|
+
|
|
13
|
+
constructor(object, property, options = {}) {
|
|
14
|
+
super(object, property, 'muigui-color');
|
|
15
|
+
const format = options.format || guessFormat(this.getValue());
|
|
16
|
+
const {color, text} = colorFormatConverters[format];
|
|
17
|
+
this.#colorView = this.add(new ColorView(this, {converters: color}));
|
|
18
|
+
this.#textView = this.add(new TextView(this, {converters: text}));
|
|
19
|
+
this.updateDisplay();
|
|
20
|
+
}
|
|
21
|
+
setOptions(options) {
|
|
22
|
+
const {format} = options;
|
|
23
|
+
if (format) {
|
|
24
|
+
const {color, text} = colorFormatConverters[format];
|
|
25
|
+
this.#colorView.setOptions({converters: color});
|
|
26
|
+
this.#textView.setOptions({converters: text});
|
|
27
|
+
}
|
|
28
|
+
super.setOptions(options);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ColorChooserView from '../views/ColorChooserView.js';
|
|
2
|
+
import TextView from '../views/TextView.js';
|
|
3
|
+
import PopDownController from './PopDownController.js';
|
|
4
|
+
|
|
5
|
+
export default class ColorChooser extends PopDownController {
|
|
6
|
+
constructor(object, property) {
|
|
7
|
+
super(object, property, 'muigui-color-chooser');
|
|
8
|
+
this.addTop(new TextView(this));
|
|
9
|
+
this.addBottom(new ColorChooserView(this));
|
|
10
|
+
this.updateDisplay();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Controller from './Controller.js';
|
|
2
|
+
|
|
3
|
+
export default class Container extends Controller {
|
|
4
|
+
#controllers;
|
|
5
|
+
#childDestController;
|
|
6
|
+
|
|
7
|
+
constructor(className) {
|
|
8
|
+
super(className);
|
|
9
|
+
this.#controllers = [];
|
|
10
|
+
this.#childDestController = this;
|
|
11
|
+
}
|
|
12
|
+
get children() {
|
|
13
|
+
return this.#controllers; // should we return a copy?
|
|
14
|
+
}
|
|
15
|
+
get controllers() {
|
|
16
|
+
return this.#controllers.filter(c => !(c instanceof Container));
|
|
17
|
+
}
|
|
18
|
+
get folders() {
|
|
19
|
+
return this.#controllers.filter(c => c instanceof Container);
|
|
20
|
+
}
|
|
21
|
+
reset(recursive = true) {
|
|
22
|
+
for (const controller of this.#controllers) {
|
|
23
|
+
if (!(controller instanceof Container) || recursive) {
|
|
24
|
+
controller.reset(recursive);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
remove(controller) {
|
|
30
|
+
const ndx = this.#controllers.indexOf(controller);
|
|
31
|
+
if (ndx >= 0) {
|
|
32
|
+
const c = this.#controllers.splice(ndx, 1);
|
|
33
|
+
const c0 = c[0];
|
|
34
|
+
const elem = c0.domElement;
|
|
35
|
+
elem.remove();
|
|
36
|
+
c0.setParent(null);
|
|
37
|
+
}
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
_addControllerImpl(controller) {
|
|
41
|
+
this.domElement.appendChild(controller.domElement);
|
|
42
|
+
this.#controllers.push(controller);
|
|
43
|
+
controller.setParent(this);
|
|
44
|
+
return controller;
|
|
45
|
+
}
|
|
46
|
+
addController(controller) {
|
|
47
|
+
return this.#childDestController._addControllerImpl(controller);
|
|
48
|
+
}
|
|
49
|
+
pushContainer(container) {
|
|
50
|
+
this.addController(container);
|
|
51
|
+
this.#childDestController = container;
|
|
52
|
+
return container;
|
|
53
|
+
}
|
|
54
|
+
popContainer() {
|
|
55
|
+
this.#childDestController = this.#childDestController.parent;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { createElem } from '../libs/elem.js';
|
|
2
|
+
import { removeArrayElem } from '../libs/utils.js';
|
|
3
|
+
import View from '../views/View.js';
|
|
4
|
+
|
|
5
|
+
export default class Controller extends View {
|
|
6
|
+
#changeFns;
|
|
7
|
+
#finishChangeFns;
|
|
8
|
+
#parent;
|
|
9
|
+
|
|
10
|
+
constructor(className) {
|
|
11
|
+
super(createElem('div', {className: 'muigui-controller'}));
|
|
12
|
+
this.#changeFns = [];
|
|
13
|
+
this.#finishChangeFns = [];
|
|
14
|
+
// we need the specialization to come last so it takes precedence.
|
|
15
|
+
if (className) {
|
|
16
|
+
this.domElement.classList.add(className);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
get parent() {
|
|
20
|
+
return this.#parent;
|
|
21
|
+
}
|
|
22
|
+
setParent(parent) {
|
|
23
|
+
this.#parent = parent;
|
|
24
|
+
this.enable(!this.disabled());
|
|
25
|
+
}
|
|
26
|
+
show(show = true) {
|
|
27
|
+
this.domElement.classList.toggle('muigui-hide', !show);
|
|
28
|
+
this.domElement.classList.toggle('muigui-show', show);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
hide() {
|
|
32
|
+
return this.show(false);
|
|
33
|
+
}
|
|
34
|
+
disabled() {
|
|
35
|
+
return !!this.domElement.closest('.muigui-disabled');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
enable(enable = true) {
|
|
39
|
+
this.domElement.classList.toggle('muigui-disabled', !enable);
|
|
40
|
+
|
|
41
|
+
// If disabled we need to set the attribute 'disabled=true' to all
|
|
42
|
+
// input/select/button/textarea's below
|
|
43
|
+
//
|
|
44
|
+
// If enabled we need to set the attribute 'disabled=false' to all below
|
|
45
|
+
// until we hit a disabled controller.
|
|
46
|
+
//
|
|
47
|
+
// ATM the problem is we can find the input/select/button/textarea elements
|
|
48
|
+
// but we can't easily find which controller they belong do.
|
|
49
|
+
// But we don't need to? We can just check up if it or parent has
|
|
50
|
+
// '.muigui-disabled'
|
|
51
|
+
['input', 'button', 'select', 'textarea'].forEach(tag => {
|
|
52
|
+
this.domElement.querySelectorAll(tag).forEach(elem => {
|
|
53
|
+
const disabled = !!elem.closest('.muigui-disabled');
|
|
54
|
+
elem.disabled = disabled;
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
disable(disable = true) {
|
|
61
|
+
return this.enable(!disable);
|
|
62
|
+
}
|
|
63
|
+
onChange(fn) {
|
|
64
|
+
this.removeChange(fn);
|
|
65
|
+
this.#changeFns.push(fn);
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
removeChange(fn) {
|
|
69
|
+
removeArrayElem(this.#changeFns, fn);
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
onFinishChange(fn) {
|
|
73
|
+
this.removeFinishChange(fn);
|
|
74
|
+
this.#finishChangeFns.push(fn);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
removeFinishChange(fn) {
|
|
78
|
+
removeArrayElem(this.#finishChangeFns, fn);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
#callListeners(fns, newV) {
|
|
82
|
+
for (const fn of fns) {
|
|
83
|
+
fn.call(this, newV);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
emitChange(value, object, property) {
|
|
87
|
+
this.#callListeners(this.#changeFns, value);
|
|
88
|
+
if (this.#parent) {
|
|
89
|
+
if (object === undefined) {
|
|
90
|
+
this.#parent.emitChange(value);
|
|
91
|
+
} else {
|
|
92
|
+
this.#parent.emitChange({
|
|
93
|
+
object,
|
|
94
|
+
property,
|
|
95
|
+
value,
|
|
96
|
+
controller: this,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
emitFinalChange(value, object, property) {
|
|
102
|
+
this.#callListeners(this.#finishChangeFns, value);
|
|
103
|
+
if (this.#parent) {
|
|
104
|
+
if (object === undefined) {
|
|
105
|
+
this.#parent.emitChange(value);
|
|
106
|
+
} else {
|
|
107
|
+
this.#parent.emitFinalChange({
|
|
108
|
+
object,
|
|
109
|
+
property,
|
|
110
|
+
value,
|
|
111
|
+
controller: this,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
getColors() {
|
|
117
|
+
const toCamelCase = s => s.replace(/-([a-z])/g, (m, m1) => m1.toUpperCase());
|
|
118
|
+
const keys = [
|
|
119
|
+
'color',
|
|
120
|
+
'bg-color',
|
|
121
|
+
'value-color',
|
|
122
|
+
'value-bg-color',
|
|
123
|
+
'hover-bg-color',
|
|
124
|
+
'menu-bg-color',
|
|
125
|
+
'menu-sep-color',
|
|
126
|
+
'disabled-color',
|
|
127
|
+
];
|
|
128
|
+
const div = createElem('div');
|
|
129
|
+
this.domElement.appendChild(div);
|
|
130
|
+
const colors = Object.fromEntries(keys.map(key => {
|
|
131
|
+
div.style.color = `var(--${key})`;
|
|
132
|
+
const s = getComputedStyle(div);
|
|
133
|
+
return [toCamelCase(key), s.color];
|
|
134
|
+
}));
|
|
135
|
+
div.remove();
|
|
136
|
+
return colors;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { identity } from '../libs/conversions.js';
|
|
2
|
+
import DirectionView from '../views/DirectionView.js';
|
|
3
|
+
import NumberView from '../views/NumberView.js';
|
|
4
|
+
// import ValueController from './ValueController.js';
|
|
5
|
+
import PopDownController from './PopDownController.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// deg2rad
|
|
9
|
+
// where is 0
|
|
10
|
+
// range (0, 360), (-180, +180), (0,0) Really this is a range
|
|
11
|
+
|
|
12
|
+
export default class Direction extends PopDownController {
|
|
13
|
+
#options;
|
|
14
|
+
constructor(object, property, options) {
|
|
15
|
+
super(object, property, 'muigui-direction');
|
|
16
|
+
this.#options = options; // FIX
|
|
17
|
+
this.addTop(new NumberView(this,
|
|
18
|
+
identity));
|
|
19
|
+
this.addBottom(new DirectionView(this, options));
|
|
20
|
+
this.updateDisplay();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createElem } from '../libs/elem.js';
|
|
2
|
+
import Container from './Container.js';
|
|
3
|
+
|
|
4
|
+
export default class Folder extends Container {
|
|
5
|
+
#labelElem;
|
|
6
|
+
|
|
7
|
+
constructor(name = 'Controls', className = 'muigui-menu') {
|
|
8
|
+
super(className);
|
|
9
|
+
this.#labelElem = createElem('label');
|
|
10
|
+
this.addElem(createElem('button', {
|
|
11
|
+
type: 'button',
|
|
12
|
+
onClick: () => this.toggleOpen(),
|
|
13
|
+
}, [this.#labelElem]));
|
|
14
|
+
this.pushContainer(new Container());
|
|
15
|
+
this.name(name);
|
|
16
|
+
this.open();
|
|
17
|
+
}
|
|
18
|
+
open(open = true) {
|
|
19
|
+
this.domElement.classList.toggle('muigui-closed', !open);
|
|
20
|
+
this.domElement.classList.toggle('muigui-open', open);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
close() {
|
|
24
|
+
return this.open(false);
|
|
25
|
+
}
|
|
26
|
+
name(name) {
|
|
27
|
+
this.#labelElem.textContent = name;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
title(title) {
|
|
31
|
+
return this.name(title);
|
|
32
|
+
}
|
|
33
|
+
toggleOpen() {
|
|
34
|
+
this.open(!this.domElement.classList.contains('muigui-open'));
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Controller from './Controller.js';
|
|
2
|
+
|
|
3
|
+
// This feels like it should be something else like
|
|
4
|
+
// gui.addDividing = new Controller()
|
|
5
|
+
export default class Label extends Controller {
|
|
6
|
+
constructor(text) {
|
|
7
|
+
super('muigui-label');
|
|
8
|
+
this.text(text);
|
|
9
|
+
}
|
|
10
|
+
text(text) {
|
|
11
|
+
this.domElement.textContent = text;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createElem } from '../libs/elem.js';
|
|
2
|
+
import { makeId } from '../libs/ids.js';
|
|
3
|
+
import ValueView from '../views/ValueView.js';
|
|
4
|
+
import Controller from './Controller.js';
|
|
5
|
+
|
|
6
|
+
export default class LabelController extends Controller {
|
|
7
|
+
#id;
|
|
8
|
+
#nameElem;
|
|
9
|
+
|
|
10
|
+
constructor(className = '', name = '') {
|
|
11
|
+
super('muigui-label-controller');
|
|
12
|
+
this.#id = makeId();
|
|
13
|
+
this.#nameElem = createElem('label', {for: this.#id});
|
|
14
|
+
this.domElement.appendChild(this.#nameElem);
|
|
15
|
+
this.pushSubView(new ValueView(className));
|
|
16
|
+
this.name(name);
|
|
17
|
+
}
|
|
18
|
+
get id() {
|
|
19
|
+
return this.#id;
|
|
20
|
+
}
|
|
21
|
+
name(name) {
|
|
22
|
+
if (this.#nameElem.title === this.#nameElem.textContent) {
|
|
23
|
+
this.#nameElem.title = name;
|
|
24
|
+
}
|
|
25
|
+
this.#nameElem.textContent = name;
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
tooltip(tip) {
|
|
29
|
+
this.#nameElem.title = tip;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import ElementView from '../views/ElementView.js';
|
|
2
|
+
import ValueController from './ValueController.js';
|
|
3
|
+
import CheckboxView from '../views/CheckboxView.js';
|
|
4
|
+
import { copyExistingProperties } from '../libs/utils.js';
|
|
5
|
+
import { createElem } from '../libs/elem.js';
|
|
6
|
+
/*
|
|
7
|
+
|
|
8
|
+
holder = new TabHolder
|
|
9
|
+
tab = holder.add(new Tab("name"))
|
|
10
|
+
tab.add(...)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
pc = new PopdownController
|
|
14
|
+
top = pc.add(new Row())
|
|
15
|
+
top.add(new Button());
|
|
16
|
+
values = topRow.add(new Div())
|
|
17
|
+
bottom = pc.add(new Row());
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
pc = new PopdownController
|
|
22
|
+
pc.addTop
|
|
23
|
+
pc.addTop
|
|
24
|
+
|
|
25
|
+
pc.addBottom
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
function makeSetter(object, property) {
|
|
31
|
+
return {
|
|
32
|
+
setValue(v) {
|
|
33
|
+
object[property] = v;
|
|
34
|
+
},
|
|
35
|
+
setFinalValue(v) {
|
|
36
|
+
this.setValue(v);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default class PopDownController extends ValueController {
|
|
42
|
+
#top;
|
|
43
|
+
#valuesView;
|
|
44
|
+
#bottom;
|
|
45
|
+
#options = {open: false};
|
|
46
|
+
|
|
47
|
+
constructor(object, property, options = {}) {
|
|
48
|
+
super(object, property, 'muigui-pop-down-controller');
|
|
49
|
+
/*
|
|
50
|
+
[ValueView
|
|
51
|
+
[[B][values]] upper row
|
|
52
|
+
[[ visual ]] lower row
|
|
53
|
+
]
|
|
54
|
+
*/
|
|
55
|
+
this.#top = this.add(new ElementView('div', 'muigui-pop-down-top'));
|
|
56
|
+
// this.#top.add(new CheckboxView(makeSetter(this.#options, 'open')));
|
|
57
|
+
const checkboxElem = this.#top.addElem(createElem('input', {
|
|
58
|
+
type: 'checkbox',
|
|
59
|
+
onChange: () => {
|
|
60
|
+
this.#options.open = checkboxElem.checked;
|
|
61
|
+
},
|
|
62
|
+
}));
|
|
63
|
+
this.#valuesView = this.#top.add(new ElementView('div', 'muigui-pop-down-values'));
|
|
64
|
+
this.#bottom = this.add(new ElementView('div', 'muigui-pop-down-bottom'));
|
|
65
|
+
this.setOptions(options);
|
|
66
|
+
}
|
|
67
|
+
updateDisplay() {
|
|
68
|
+
super.updateDisplay();
|
|
69
|
+
const {open} = this.#options;
|
|
70
|
+
this.domElement.children[1].classList.toggle('muigui-open', open);
|
|
71
|
+
this.domElement.children[1].classList.toggle('muigui-closed', !open);
|
|
72
|
+
}
|
|
73
|
+
setOptions(options) {
|
|
74
|
+
copyExistingProperties(this.#options, options);
|
|
75
|
+
super.setOptions(options);
|
|
76
|
+
this.updateDisplay();
|
|
77
|
+
}
|
|
78
|
+
addTop(view) {
|
|
79
|
+
return this.#valuesView.add(view);
|
|
80
|
+
}
|
|
81
|
+
addBottom(view) {
|
|
82
|
+
return this.#bottom.add(view);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import RadioGridView from '../views/RadioGridView.js';
|
|
2
|
+
import ValueController from './ValueController.js';
|
|
3
|
+
import { convertToKeyValues } from '../libs/key-values.js';
|
|
4
|
+
|
|
5
|
+
export default class RadioGrid extends ValueController {
|
|
6
|
+
constructor(object, property, options) {
|
|
7
|
+
super(object, property, 'muigui-radio-grid');
|
|
8
|
+
const valueIsNumber = typeof this.getValue() === 'number';
|
|
9
|
+
const {
|
|
10
|
+
keyValues: keyValuesInput,
|
|
11
|
+
cols = 3,
|
|
12
|
+
} = options;
|
|
13
|
+
const keyValues = convertToKeyValues(keyValuesInput, valueIsNumber);
|
|
14
|
+
this.add(new RadioGridView(this, keyValues, cols));
|
|
15
|
+
this.updateDisplay();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ValueController from './ValueController.js';
|
|
2
|
+
import NumberView from '../views/NumberView.js';
|
|
3
|
+
import RangeView from '../views/RangeView.js';
|
|
4
|
+
|
|
5
|
+
export default class Range extends ValueController {
|
|
6
|
+
constructor(object, property, options) {
|
|
7
|
+
super(object, property, 'muigui-range');
|
|
8
|
+
this.add(new RangeView(this, options));
|
|
9
|
+
this.add(new NumberView(this, options));
|
|
10
|
+
}
|
|
11
|
+
}
|