muigui 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +72 -7
  2. package/package.json +9 -6
  3. package/src/controllers/Button.js +34 -0
  4. package/src/controllers/Canvas.js +17 -0
  5. package/src/controllers/Checkbox.js +11 -0
  6. package/src/controllers/Color.js +31 -0
  7. package/src/controllers/ColorChooser.js +12 -0
  8. package/src/controllers/Container.js +58 -0
  9. package/src/controllers/Controller.js +138 -0
  10. package/src/controllers/Direction.js +23 -0
  11. package/src/controllers/Divider.js +9 -0
  12. package/src/controllers/Folder.js +37 -0
  13. package/src/controllers/Label.js +14 -0
  14. package/src/controllers/LabelController.js +32 -0
  15. package/src/controllers/PopDownController.js +84 -0
  16. package/src/controllers/RadioGrid.js +17 -0
  17. package/src/controllers/Range.js +11 -0
  18. package/src/controllers/Select.js +14 -0
  19. package/src/controllers/Slider.js +12 -0
  20. package/src/controllers/TabHolder.js +36 -0
  21. package/src/controllers/Text.js +10 -0
  22. package/src/controllers/TextNumber.js +18 -0
  23. package/src/controllers/ValueController.js +107 -0
  24. package/src/controllers/Vec2.js +50 -0
  25. package/src/controllers/create-controller.js +43 -0
  26. package/src/layout/Column.js +7 -0
  27. package/src/layout/Frame.js +11 -0
  28. package/src/layout/Grid.js +7 -0
  29. package/src/layout/Layout.js +47 -0
  30. package/src/layout/Row.js +7 -0
  31. package/src/libs/assert.js +5 -0
  32. package/src/libs/color-utils.js +406 -0
  33. package/src/libs/conversions.js +14 -0
  34. package/src/libs/css-utils.js +3 -0
  35. package/src/libs/elem.js +8 -3
  36. package/src/libs/emitter.js +68 -0
  37. package/src/libs/iterable-array.js +57 -0
  38. package/src/libs/key-values.js +25 -0
  39. package/src/libs/keyboard.js +32 -0
  40. package/src/libs/resize-helpers.js +22 -0
  41. package/src/libs/svg.js +33 -0
  42. package/src/libs/taskrunner.js +56 -0
  43. package/src/libs/touch.js +50 -0
  44. package/src/libs/utils.js +38 -2
  45. package/src/libs/wheel.js +10 -0
  46. package/src/muigui.js +79 -19
  47. package/src/styles/muigui.css.js +640 -0
  48. package/src/umd.js +3 -0
  49. package/src/views/CheckboxView.js +21 -0
  50. package/src/views/ColorChooserView.js +124 -0
  51. package/src/views/ColorView.js +50 -0
  52. package/src/views/DirectionView.js +127 -0
  53. package/src/views/EditView.js +100 -0
  54. package/src/views/ElementView.js +8 -0
  55. package/src/views/GridView.js +15 -0
  56. package/src/views/NumberView.js +67 -0
  57. package/src/views/RadioGridView.js +46 -0
  58. package/src/views/RangeView.js +73 -0
  59. package/src/views/SelectView.js +23 -0
  60. package/src/views/SliderView.js +194 -0
  61. package/src/views/TextView.js +49 -0
  62. package/src/views/ValueView.js +11 -0
  63. package/src/views/Vec2View.js +51 -0
  64. package/src/views/View.js +56 -0
  65. package/src/widgets/checkbox.js +0 -0
  66. package/src/widgets/divider.js +0 -0
  67. package/src/widgets/menu.js +0 -0
  68. package/src/widgets/radio.js +0 -0
  69. package/src/widgets/select.js +0 -1
  70. package/src/widgets/slider.js +0 -41
  71. package/src/widgets/text.js +0 -0
  72. package/src/widgets/widget.js +0 -51
@@ -0,0 +1,14 @@
1
+ import SelectView from '../views/SelectView.js';
2
+ import ValueController from './ValueController.js';
3
+ import { convertToKeyValues } from '../libs/key-values.js';
4
+
5
+ export default class Select extends ValueController {
6
+ constructor(object, property, options) {
7
+ super(object, property, 'muigui-select');
8
+ const valueIsNumber = typeof this.getValue() === 'number';
9
+ const {keyValues: keyValuesInput} = options;
10
+ const keyValues = convertToKeyValues(keyValuesInput, valueIsNumber);
11
+ this.add(new SelectView(this, keyValues));
12
+ this.updateDisplay();
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ import ValueController from './ValueController.js';
2
+ import NumberView from '../views/NumberView.js';
3
+ import SliderView from '../views/SliderView.js';
4
+
5
+ export default class Slider extends ValueController {
6
+ constructor(object, property, options = {}) {
7
+ super(object, property, 'muigui-slider');
8
+ this.add(new SliderView(this, options));
9
+ this.add(new NumberView(this, options));
10
+ this.updateDisplay();
11
+ }
12
+ }
@@ -0,0 +1,36 @@
1
+ import { createElem } from '../libs/elem.js';
2
+ import Controller from './Controller.js';
3
+
4
+ export default class TabHolder extends Controller {
5
+ #labelElem;
6
+
7
+ constructor(name = 'Controls', className = 'muigui-tab-holder') {
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.name(name);
15
+ this.open();
16
+ }
17
+ open(open = true) {
18
+ this.domElement.classList.toggle('muigui-closed', !open);
19
+ this.domElement.classList.toggle('muigui-open', open);
20
+ return this;
21
+ }
22
+ close() {
23
+ return this.open(false);
24
+ }
25
+ name(name) {
26
+ this.#labelElem.textContent = name;
27
+ return this;
28
+ }
29
+ title(title) {
30
+ return this.name(title);
31
+ }
32
+ toggleOpen() {
33
+ this.open(!this.domElement.classList.contains('muigui-open'));
34
+ return this;
35
+ }
36
+ }
@@ -0,0 +1,10 @@
1
+ import TextView from '../views/TextView.js';
2
+ import ValueController from './ValueController.js';
3
+
4
+ export default class Text extends ValueController {
5
+ constructor(object, property) {
6
+ super(object, property, 'muigui-checkbox');
7
+ this.add(new TextView(this));
8
+ this.updateDisplay();
9
+ }
10
+ }
@@ -0,0 +1,18 @@
1
+
2
+ import NumberView from '../views/NumberView.js';
3
+ import ValueController from './ValueController.js';
4
+
5
+ // Wanted to name this `Number` but it conflicts with
6
+ // JavaScript `Number`. It most likely wouldn't be
7
+ // an issue? But users might `import {Number} ...` and
8
+ // things would break.
9
+ export default class TextNumber extends ValueController {
10
+ #textView;
11
+ #step;
12
+
13
+ constructor(object, property, options = {}) {
14
+ super(object, property, 'muigui-checkbox');
15
+ this.#textView = this.add(new NumberView(this, options));
16
+ this.updateDisplay();
17
+ }
18
+ }
@@ -0,0 +1,107 @@
1
+ import {addTask, removeTask} from '../libs/taskrunner.js';
2
+ import { isTypedArray } from '../libs/utils.js';
3
+ import LabelController from './LabelController.js';
4
+
5
+ export default class ValueController extends LabelController {
6
+ #object;
7
+ #property;
8
+ #initialValue;
9
+ #listening;
10
+ #views;
11
+ #updateFn;
12
+
13
+ constructor(object, property, className = '') {
14
+ super(className, property);
15
+ this.#object = object;
16
+ this.#property = property;
17
+ this.#initialValue = this.getValue();
18
+ this.#listening = false;
19
+ this.#views = [];
20
+ }
21
+ get initialValue() {
22
+ return this.#initialValue;
23
+ }
24
+ get object() {
25
+ return this.#object;
26
+ }
27
+ get property() {
28
+ return this.#property;
29
+ }
30
+ add(view) {
31
+ this.#views.push(view);
32
+ super.add(view);
33
+ this.updateDisplay();
34
+ return view;
35
+ }
36
+ #setValueImpl(v, ignoreCache) {
37
+ if (typeof v === 'object') {
38
+ const dst = this.#object[this.#property];
39
+ // don't replace objects, just their values.
40
+ if (Array.isArray(v)) {
41
+ for (let i = 0; i < v.length; ++i) {
42
+ dst[i] = v[i];
43
+ }
44
+ } else if (isTypedArray(v)) {
45
+ dst.set(v);
46
+ } else {
47
+ Object.assign(dst, v);
48
+ }
49
+ } else {
50
+ this.#object[this.#property] = v;
51
+ }
52
+ this.updateDisplay(ignoreCache);
53
+ this.emitChange(this.getValue(), this.#object, this.#property);
54
+ return this;
55
+ }
56
+ setValue(v) {
57
+ this.#setValueImpl(v);
58
+ }
59
+ setFinalValue(v) {
60
+ this.#setValueImpl(v, true);
61
+ this.emitFinalChange(this.getValue(), this.#object, this.#property);
62
+ return this;
63
+ }
64
+ updateDisplay(ignoreCache) {
65
+ const newV = this.getValue();
66
+ for (const view of this.#views) {
67
+ view.updateDisplayIfNeeded(newV, ignoreCache);
68
+ }
69
+ return this;
70
+ }
71
+ setOptions(options) {
72
+ for (const view of this.#views) {
73
+ view.setOptions(options);
74
+ }
75
+ this.updateDisplay();
76
+ return this;
77
+ }
78
+ getValue() {
79
+ return this.#object[this.#property];
80
+ }
81
+ value(v) {
82
+ this.setValue(v);
83
+ return this;
84
+ }
85
+ reset() {
86
+ this.setValue(this.#initialValue);
87
+ return this;
88
+ }
89
+ listen(listen = true) {
90
+ if (!this.#updateFn) {
91
+ this.#updateFn = this.updateDisplay.bind(this);
92
+ }
93
+ if (listen) {
94
+ if (!this.#listening) {
95
+ this.#listening = true;
96
+ addTask(this.#updateFn);
97
+ }
98
+ } else {
99
+ if (this.#listening) {
100
+ this.#listening = false;
101
+ removeTask(this.#updateFn);
102
+ }
103
+ }
104
+ return this;
105
+ }
106
+ }
107
+
@@ -0,0 +1,50 @@
1
+ import GridView from '../views/GridView.js';
2
+ import NumberView from '../views/NumberView.js';
3
+ import Vec2View from '../views/Vec2View.js';
4
+ import PopDownController from './PopDownController.js';
5
+ import { strToNumber } from '../libs/conversions.js';
6
+
7
+ // TODO: zoom with wheel and pinch?
8
+ // TODO: grid?
9
+ // // options
10
+ // scale:
11
+ // range: number (both x and y + /)
12
+ // range: array (min, max)
13
+ // xRange:
14
+ // deg/rad/turn
15
+
16
+ export default class Vec2 extends PopDownController {
17
+ constructor(object, property) {
18
+ super(object, property, 'muigui-vec2');
19
+
20
+ const makeSetter = (ndx) => {
21
+ return {
22
+ setValue: (v) => {
23
+ const newV = this.getValue();
24
+ newV[ndx] = v;
25
+ this.setValue(newV);
26
+ },
27
+ setFinalValue: (v) => {
28
+ const newV = this.getValue();
29
+ newV[ndx] = v;
30
+ this.setFinalValue(newV);
31
+ },
32
+ };
33
+ };
34
+
35
+ this.addTop(new NumberView(makeSetter(0), {
36
+ converters: {
37
+ to: v => v[0],
38
+ from: strToNumber.from,
39
+ },
40
+ }));
41
+ this.addTop(new NumberView(makeSetter(1), {
42
+ converters: {
43
+ to: v => v[1],
44
+ from: strToNumber.from,
45
+ },
46
+ }));
47
+ this.addBottom(new Vec2View(this));
48
+ this.updateDisplay();
49
+ }
50
+ }
@@ -0,0 +1,43 @@
1
+ import Button from './Button.js';
2
+ import Checkbox from './Checkbox.js';
3
+ import TextNumber from './TextNumber.js';
4
+ import Select from './Select.js';
5
+ import Range from './Range.js';
6
+ import Text from './Text.js';
7
+
8
+ // const isConversion = o => typeof o.to === 'function' && typeof o.from === 'function';
9
+
10
+ /**
11
+ * possible inputs
12
+ * add(o, p, min: number, max: number)
13
+ * add(o, p, min: number, max: number, step: number)
14
+ * add(o, p, array: [value])
15
+ * add(o, p, array: [[key, value]])
16
+ *
17
+ * @param {*} object
18
+ * @param {string} property
19
+ * @param {...any} args
20
+ * @returns {Controller}
21
+ */
22
+ export function createController(object, property, ...args) {
23
+ const [arg1] = args;
24
+ if (Array.isArray(arg1)) {
25
+ return new Select(object, property, {keyValues: arg1});
26
+ }
27
+
28
+ const t = typeof object[property];
29
+ switch (t) {
30
+ case 'number':
31
+ return args.length === 0
32
+ ? new TextNumber(object, property, ...args)
33
+ : new Range(object, property, ...args);
34
+ case 'boolean':
35
+ return new Checkbox(object, property, ...args);
36
+ case 'function':
37
+ return new Button(object, property, ...args);
38
+ case 'string':
39
+ return new Text(object, property, ...args);
40
+ default:
41
+ throw new Error(`unhandled type ${t} for property ${property}`);
42
+ }
43
+ }
@@ -0,0 +1,7 @@
1
+ import Layout from './Layout.js';
2
+
3
+ export default class Column extends Layout {
4
+ constructor() {
5
+ super('div', 'muigui-row');
6
+ }
7
+ }
@@ -0,0 +1,11 @@
1
+ import Layout from './Layout.js';
2
+
3
+ export default class Frame extends Layout {
4
+ static css = 'foo';
5
+ constructor() {
6
+ super('div', 'muigui-frame');
7
+ }
8
+ static get foo() {
9
+ return 'boo';
10
+ }
11
+ }
@@ -0,0 +1,7 @@
1
+ import Layout from './Layout.js';
2
+
3
+ export default class Grid extends Layout {
4
+ constructor() {
5
+ super('div', 'muigui-grid');
6
+ }
7
+ }
@@ -0,0 +1,47 @@
1
+ import { createElem } from '../libs/elem.js';
2
+ import View from '../views/View.js';
3
+
4
+ function showCSS(ob) {
5
+ if (ob.prototype.css) {
6
+ console.log(ob.prototype.css);
7
+ showCSS(ob.prototype);
8
+ }
9
+ }
10
+
11
+ export default class Layout extends View {
12
+ static css = 'bar';
13
+ constructor(tag, className) {
14
+ super(createElem(tag, {className}));
15
+
16
+ showCSS(this);
17
+ }
18
+ }
19
+
20
+ /*
21
+ class ValueController ?? {
22
+ const row = this.add(new Row());
23
+ const label = row.add(new Label());
24
+ const div = row.add(new Div());
25
+ const row = div.add(new Row());
26
+ }
27
+ */
28
+
29
+ /*
30
+ class MyCustomThing extends ValueController {
31
+ constructor(object, property, options) {
32
+ const topRow = this.add(new Row());
33
+ const bottomRow = this.add(new Row());
34
+ topRow.add(new NumberView());
35
+ topRow.add(new NumberView());
36
+ topRow.add(new NumberView());
37
+ topRow.add(new NumberView());
38
+ bottomRow.add(new DirectionView());
39
+ bottomRow.add(new DirectionView());
40
+ bottomRow.add(new DirectionView());
41
+ bottomRow.add(new DirectionView());
42
+ }
43
+ }
44
+ new Grid([
45
+ [new
46
+ ]
47
+ */
@@ -0,0 +1,7 @@
1
+ import Layout from './Layout.js';
2
+
3
+ export default class Row extends Layout {
4
+ constructor() {
5
+ super('div', 'muigui-row');
6
+ }
7
+ }
@@ -0,0 +1,5 @@
1
+ export function assert(truthy, msg = '') {
2
+ if (!truthy) {
3
+ throw new Error(msg);
4
+ }
5
+ }