muigui 0.0.6 → 0.0.10
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/package.json +1 -1
- package/src/controllers/Container.js +6 -0
- package/src/controllers/Controller.js +3 -0
- package/src/controllers/PopDownController.js +0 -12
- package/src/controllers/ValueController.js +15 -7
- package/src/controllers/Vec2.js +0 -1
- package/src/layout/Layout.js +0 -1
- package/src/libs/color-utils.js +22 -2
- package/src/libs/touch.js +2 -2
- package/src/libs/utils.js +31 -0
- package/src/muigui.js +75 -12
- package/src/styles/muigui.css.js +67 -4
- package/src/views/CheckboxView.js +3 -1
- package/src/views/ColorChooserView.js +0 -4
- package/src/views/RangeView.js +10 -4
package/package.json
CHANGED
|
@@ -26,6 +26,12 @@ export default class Container extends Controller {
|
|
|
26
26
|
}
|
|
27
27
|
return this;
|
|
28
28
|
}
|
|
29
|
+
updateDisplay() {
|
|
30
|
+
for (const controller of this.#controllers) {
|
|
31
|
+
controller.updateDisplay();
|
|
32
|
+
}
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
29
35
|
remove(controller) {
|
|
30
36
|
const ndx = this.#controllers.indexOf(controller);
|
|
31
37
|
if (ndx >= 0) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import ElementView from '../views/ElementView.js';
|
|
2
2
|
import ValueController from './ValueController.js';
|
|
3
|
-
import CheckboxView from '../views/CheckboxView.js';
|
|
4
3
|
import { copyExistingProperties } from '../libs/utils.js';
|
|
5
4
|
import { createElem } from '../libs/elem.js';
|
|
6
5
|
/*
|
|
@@ -27,17 +26,6 @@ pc.addBottom
|
|
|
27
26
|
|
|
28
27
|
*/
|
|
29
28
|
|
|
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
29
|
export default class PopDownController extends ValueController {
|
|
42
30
|
#top;
|
|
43
31
|
#valuesView;
|
|
@@ -34,31 +34,39 @@ export default class ValueController extends LabelController {
|
|
|
34
34
|
return view;
|
|
35
35
|
}
|
|
36
36
|
#setValueImpl(v, ignoreCache) {
|
|
37
|
+
let isDifferent = false;
|
|
37
38
|
if (typeof v === 'object') {
|
|
38
39
|
const dst = this.#object[this.#property];
|
|
39
40
|
// don't replace objects, just their values.
|
|
40
|
-
if (Array.isArray(v)) {
|
|
41
|
+
if (Array.isArray(v) || isTypedArray(v)) {
|
|
41
42
|
for (let i = 0; i < v.length; ++i) {
|
|
43
|
+
isDifferent ||= dst[i] !== v[i];
|
|
42
44
|
dst[i] = v[i];
|
|
43
45
|
}
|
|
44
|
-
} else if (isTypedArray(v)) {
|
|
45
|
-
dst.set(v);
|
|
46
46
|
} else {
|
|
47
|
+
for (const key of Object.keys(v)) {
|
|
48
|
+
isDifferent ||= dst[key] !== v[key];
|
|
49
|
+
}
|
|
47
50
|
Object.assign(dst, v);
|
|
48
51
|
}
|
|
49
52
|
} else {
|
|
53
|
+
isDifferent = this.#object[this.#property] !== v;
|
|
50
54
|
this.#object[this.#property] = v;
|
|
51
55
|
}
|
|
52
56
|
this.updateDisplay(ignoreCache);
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
if (isDifferent) {
|
|
58
|
+
this.emitChange(this.getValue(), this.#object, this.#property);
|
|
59
|
+
}
|
|
60
|
+
return isDifferent;
|
|
55
61
|
}
|
|
56
62
|
setValue(v) {
|
|
57
63
|
this.#setValueImpl(v);
|
|
58
64
|
}
|
|
59
65
|
setFinalValue(v) {
|
|
60
|
-
this.#setValueImpl(v, true);
|
|
61
|
-
|
|
66
|
+
const isDifferent = this.#setValueImpl(v, true);
|
|
67
|
+
if (isDifferent) {
|
|
68
|
+
this.emitFinalChange(this.getValue(), this.#object, this.#property);
|
|
69
|
+
}
|
|
62
70
|
return this;
|
|
63
71
|
}
|
|
64
72
|
updateDisplay(ignoreCache) {
|
package/src/controllers/Vec2.js
CHANGED
package/src/layout/Layout.js
CHANGED
package/src/libs/color-utils.js
CHANGED
|
@@ -34,12 +34,14 @@ const cssRGBToHex = v => {
|
|
|
34
34
|
const m = cssRGBRegex.exec(v);
|
|
35
35
|
return uint8RGBToHex([m[1], m[2], m[3]].map(v => parseInt(v)));
|
|
36
36
|
};
|
|
37
|
+
const cssRGBARegex = /^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/;
|
|
37
38
|
|
|
38
39
|
const hexToCssHSL = v => {
|
|
39
40
|
const hsl = rgbUint8ToHsl(hexToUint8RGB(v)).map(v => f0(v));
|
|
40
41
|
return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`;
|
|
41
42
|
};
|
|
42
43
|
const cssHSLRegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/;
|
|
44
|
+
const cssHSLARegex = /^\s*hsl\(\s*(\d+)(?:deg|)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)\s*$/;
|
|
43
45
|
|
|
44
46
|
const hex3DigitTo6Digit = v => `${v[0]}${v[0]}${v[1]}${v[1]}${v[2]}${v[2]}`;
|
|
45
47
|
const cssHSLToHex = v => {
|
|
@@ -121,13 +123,20 @@ export function rgbFloatToHSV01([r, g, b]) {
|
|
|
121
123
|
window.hsv01ToRGBFloat = hsv01ToRGBFloat;
|
|
122
124
|
window.rgbFloatToHSV01 = rgbFloatToHSV01;
|
|
123
125
|
|
|
126
|
+
// Yea, meh!
|
|
127
|
+
export const hasAlpha = format => format.endsWith('a') || format.startsWith('hex8');
|
|
128
|
+
|
|
124
129
|
const cssStringFormats = [
|
|
125
130
|
{ re: /^#(?:[0-9a-f]){6}$/i, format: 'hex6' },
|
|
126
131
|
{ re: /^(?:[0-9a-f]){6}$/i, format: 'hex6-no-hash' },
|
|
132
|
+
{ re: /^#(?:[0-9a-f]){8}$/i, format: 'hex8' },
|
|
133
|
+
{ re: /^(?:[0-9a-f]){8}$/i, format: 'hex8-no-hash' },
|
|
127
134
|
{ re: /^#(?:[0-9a-f]){3}$/i, format: 'hex3' },
|
|
128
135
|
{ re: /^(?:[0-9a-f]){3}$/i, format: 'hex3-no-hash' },
|
|
129
136
|
{ re: cssRGBRegex, format: 'css-rgb' },
|
|
130
137
|
{ re: cssHSLRegex, format: 'css-hsl' },
|
|
138
|
+
{ re: cssRGBARegex, format: 'css-rgba' },
|
|
139
|
+
{ re: cssHSLARegex, format: 'css-hsla' },
|
|
131
140
|
];
|
|
132
141
|
|
|
133
142
|
function guessStringColorFormat(v) {
|
|
@@ -142,7 +151,8 @@ function guessStringColorFormat(v) {
|
|
|
142
151
|
export function guessFormat(v) {
|
|
143
152
|
switch (typeof v) {
|
|
144
153
|
case 'number':
|
|
145
|
-
|
|
154
|
+
console.warn('can not reliably guess format based on a number. You should pass in a format like {format: "uint32-rgb"} or {format: "uint32-rgb"}');
|
|
155
|
+
return v <= 0xFFFFFF ? 'uint32-rgb' : 'uint32-rgba';
|
|
146
156
|
case 'string': {
|
|
147
157
|
const formatInfo = guessStringColorFormat(v.trim());
|
|
148
158
|
if (formatInfo) {
|
|
@@ -154,18 +164,28 @@ export function guessFormat(v) {
|
|
|
154
164
|
if (v instanceof Uint8Array || v instanceof Uint8ClampedArray) {
|
|
155
165
|
if (v.length === 3) {
|
|
156
166
|
return 'uint8-rgb';
|
|
167
|
+
} else if (v.length === 4) {
|
|
168
|
+
return 'uint8-rgba';
|
|
157
169
|
}
|
|
158
170
|
} else if (v instanceof Float32Array) {
|
|
159
171
|
if (v.length === 3) {
|
|
160
172
|
return 'float-rgb';
|
|
173
|
+
} else if (v.length === 4) {
|
|
174
|
+
return 'float-rgba';
|
|
161
175
|
}
|
|
162
176
|
} else if (Array.isArray(v)) {
|
|
163
177
|
if (v.length === 3) {
|
|
164
178
|
return 'float-rgb';
|
|
179
|
+
} else if (v.length === 4) {
|
|
180
|
+
return 'float-rgba';
|
|
165
181
|
}
|
|
166
182
|
} else {
|
|
167
183
|
if ('r' in v && 'g' in v && 'b' in v) {
|
|
168
|
-
|
|
184
|
+
if ('a' in v) {
|
|
185
|
+
return 'object-rgba';
|
|
186
|
+
} else {
|
|
187
|
+
return 'object-rgb';
|
|
188
|
+
}
|
|
169
189
|
}
|
|
170
190
|
}
|
|
171
191
|
}
|
package/src/libs/touch.js
CHANGED
|
@@ -29,9 +29,9 @@ export function addTouchEvents(elem, {onDown = noop, onMove = noop, onUp = noop}
|
|
|
29
29
|
elem.releasePointerCapture(event.pointerId);
|
|
30
30
|
elem.removeEventListener('pointermove', pointerMove);
|
|
31
31
|
elem.removeEventListener('pointerup', pointerUp);
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
document.body.style.backgroundColor = '';
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
onUp('up');
|
|
36
36
|
};
|
|
37
37
|
|
package/src/libs/utils.js
CHANGED
|
@@ -72,3 +72,34 @@ export const makeRangeOptions = ({from, to, step}) => {
|
|
|
72
72
|
};
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
// TODO: remove an use one in conversions. Move makeRangeConverters there?
|
|
76
|
+
export const identity = {
|
|
77
|
+
to: v => v,
|
|
78
|
+
from: v => [true, v],
|
|
79
|
+
};
|
|
80
|
+
export function makeMinMaxPair(gui, properties, minPropName, maxPropName, options) {
|
|
81
|
+
const { converters: { from } = identity } = options;
|
|
82
|
+
const { min, max } = options;
|
|
83
|
+
const guiMinRange = options.minRange || 0;
|
|
84
|
+
const valueMinRange = from(guiMinRange)[1];
|
|
85
|
+
const minGui = gui
|
|
86
|
+
.add(properties, minPropName, {
|
|
87
|
+
...options,
|
|
88
|
+
min,
|
|
89
|
+
max: max - guiMinRange,
|
|
90
|
+
})
|
|
91
|
+
.onChange(v => {
|
|
92
|
+
maxGui.setValue(Math.min(max, Math.max(v + valueMinRange, properties[maxPropName])));
|
|
93
|
+
});
|
|
94
|
+
const maxGui = gui
|
|
95
|
+
.add(properties, maxPropName, {
|
|
96
|
+
...options,
|
|
97
|
+
min: min + guiMinRange,
|
|
98
|
+
max,
|
|
99
|
+
})
|
|
100
|
+
.onChange(v => {
|
|
101
|
+
minGui.setValue(Math.max(min, Math.min(v - valueMinRange, properties[minPropName])));
|
|
102
|
+
});
|
|
103
|
+
return [ minGui, maxGui ];
|
|
104
|
+
}
|
|
105
|
+
|
package/src/muigui.js
CHANGED
|
@@ -5,16 +5,22 @@ import {
|
|
|
5
5
|
mapRange,
|
|
6
6
|
makeRangeConverters,
|
|
7
7
|
makeRangeOptions,
|
|
8
|
+
makeMinMaxPair,
|
|
8
9
|
} from './libs/utils.js';
|
|
9
10
|
import {
|
|
10
11
|
converters
|
|
11
12
|
} from './libs/conversions.js';
|
|
13
|
+
import {
|
|
14
|
+
hasAlpha,
|
|
15
|
+
guessFormat,
|
|
16
|
+
} from './libs/color-utils.js';
|
|
12
17
|
import Canvas from './controllers/Canvas.js';
|
|
13
18
|
import Color from './controllers/Color.js';
|
|
14
19
|
import Divider from './controllers/Divider.js';
|
|
15
20
|
import Folder from './controllers/Folder.js';
|
|
16
21
|
import Label from './controllers/Label.js';
|
|
17
22
|
import Controller from './controllers/Controller.js';
|
|
23
|
+
import ColorChooser from './controllers/ColorChooser.js';
|
|
18
24
|
|
|
19
25
|
import Column from './layout/Column.js';
|
|
20
26
|
import Frame from './layout/Frame.js';
|
|
@@ -28,9 +34,6 @@ export {
|
|
|
28
34
|
Row,
|
|
29
35
|
};
|
|
30
36
|
|
|
31
|
-
let stylesInjected = false;
|
|
32
|
-
const styleElem = createElem('style');
|
|
33
|
-
|
|
34
37
|
export class GUIFolder extends Folder {
|
|
35
38
|
add(object, property, ...args) {
|
|
36
39
|
const controller = object instanceof Controller
|
|
@@ -41,8 +44,13 @@ export class GUIFolder extends Folder {
|
|
|
41
44
|
addCanvas(name) {
|
|
42
45
|
return this.addController(new Canvas(name));
|
|
43
46
|
}
|
|
44
|
-
addColor(object, property,
|
|
45
|
-
|
|
47
|
+
addColor(object, property, options = {}) {
|
|
48
|
+
const value = object[property];
|
|
49
|
+
if (hasAlpha(options.format || guessFormat(value))) {
|
|
50
|
+
return this.addController(new ColorChooser(object, property, options));
|
|
51
|
+
} else {
|
|
52
|
+
return this.addController(new Color(object, property, options));
|
|
53
|
+
}
|
|
46
54
|
}
|
|
47
55
|
addDivider() {
|
|
48
56
|
return this.addController(new Divider());
|
|
@@ -55,11 +63,50 @@ export class GUIFolder extends Folder {
|
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
|
|
66
|
+
class MuiguiElement extends HTMLElement {
|
|
67
|
+
constructor() {
|
|
68
|
+
super();
|
|
69
|
+
this.shadow = this.attachShadow({mode: 'open'});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
customElements.define('muigui-element', MuiguiElement);
|
|
74
|
+
|
|
75
|
+
const baseStyleSheet = new CSSStyleSheet();
|
|
76
|
+
baseStyleSheet.replaceSync(css.default);
|
|
77
|
+
const userStyleSheet = new CSSStyleSheet();
|
|
78
|
+
|
|
79
|
+
function makeStyleSheetUpdater(styleSheet) {
|
|
80
|
+
let newCss;
|
|
81
|
+
let newCssPromise;
|
|
82
|
+
|
|
83
|
+
function updateStyle() {
|
|
84
|
+
if (newCss && !newCssPromise) {
|
|
85
|
+
const s = newCss;
|
|
86
|
+
newCss = undefined;
|
|
87
|
+
newCssPromise = styleSheet.replace(s).then(() => {
|
|
88
|
+
newCssPromise = undefined;
|
|
89
|
+
updateStyle();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return function updateStyleSheet(css) {
|
|
95
|
+
newCss = css;
|
|
96
|
+
updateStyle();
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const updateBaseStyle = makeStyleSheetUpdater(baseStyleSheet);
|
|
101
|
+
const updateUserStyle = makeStyleSheetUpdater(userStyleSheet);
|
|
102
|
+
|
|
58
103
|
export class GUI extends GUIFolder {
|
|
59
104
|
static converters = converters;
|
|
60
105
|
static mapRange = mapRange;
|
|
61
106
|
static makeRangeConverters = makeRangeConverters;
|
|
62
107
|
static makeRangeOptions = makeRangeOptions;
|
|
108
|
+
static makeMinMaxPair = makeMinMaxPair;
|
|
109
|
+
#localStyleSheet = new CSSStyleSheet();
|
|
63
110
|
|
|
64
111
|
constructor(options = {}) {
|
|
65
112
|
super('Controls', 'muigui-root');
|
|
@@ -70,16 +117,11 @@ export class GUI extends GUIFolder {
|
|
|
70
117
|
autoPlace = true,
|
|
71
118
|
width,
|
|
72
119
|
title = 'Controls',
|
|
73
|
-
injectStyles = true,
|
|
74
120
|
} = options;
|
|
75
121
|
let {
|
|
76
122
|
parent,
|
|
77
123
|
} = options;
|
|
78
|
-
|
|
79
|
-
stylesInjected = true;
|
|
80
|
-
(document.head || document.documentElement).appendChild(styleElem);
|
|
81
|
-
styleElem.textContent = css;
|
|
82
|
-
}
|
|
124
|
+
|
|
83
125
|
if (width) {
|
|
84
126
|
this.domElement.style.width = /^\d+$/.test(width) ? `${width}px` : width;
|
|
85
127
|
}
|
|
@@ -88,13 +130,34 @@ export class GUI extends GUIFolder {
|
|
|
88
130
|
this.domElement.classList.add('muigui-auto-place');
|
|
89
131
|
}
|
|
90
132
|
if (parent) {
|
|
91
|
-
|
|
133
|
+
const muiguiElement = createElem('muigui-element');
|
|
134
|
+
muiguiElement.shadowRoot.adoptedStyleSheets = [baseStyleSheet, userStyleSheet, this.#localStyleSheet];
|
|
135
|
+
muiguiElement.shadow.appendChild(this.domElement);
|
|
136
|
+
parent.appendChild(muiguiElement);
|
|
92
137
|
}
|
|
93
138
|
if (title) {
|
|
94
139
|
this.title(title);
|
|
95
140
|
}
|
|
96
141
|
this.domElement.classList.add('muigui', 'muigui-colors');
|
|
97
142
|
}
|
|
143
|
+
setStyle(css) {
|
|
144
|
+
this.#localStyleSheet.replace(css);
|
|
145
|
+
}
|
|
146
|
+
static setBaseStyles(css) {
|
|
147
|
+
updateBaseStyle(css);
|
|
148
|
+
}
|
|
149
|
+
static getBaseStyleSheet() {
|
|
150
|
+
return baseStyleSheet;
|
|
151
|
+
}
|
|
152
|
+
static setUserStyles(css) {
|
|
153
|
+
updateUserStyle(css);
|
|
154
|
+
}
|
|
155
|
+
static getUserStyleSheet() {
|
|
156
|
+
return userStyleSheet;
|
|
157
|
+
}
|
|
158
|
+
static setTheme(name) {
|
|
159
|
+
GUI.setBaseStyles(`${css.default}\n${css.themes[name] || ''}`);
|
|
160
|
+
}
|
|
98
161
|
}
|
|
99
162
|
|
|
100
163
|
export default GUI;
|
package/src/styles/muigui.css.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export default
|
|
2
|
-
|
|
1
|
+
export default {
|
|
2
|
+
default: `
|
|
3
|
+
.muigui {
|
|
3
4
|
--bg-color: #ddd;
|
|
4
5
|
--color: #222;
|
|
6
|
+
--contrast-color: #eee;
|
|
5
7
|
--value-color: #145 ;
|
|
6
8
|
--value-bg-color: #eeee;
|
|
7
9
|
--disabled-color: #999;
|
|
@@ -24,9 +26,10 @@ export default `
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
@media (prefers-color-scheme: dark) {
|
|
27
|
-
.muigui
|
|
29
|
+
.muigui {
|
|
28
30
|
--bg-color: #222222;
|
|
29
31
|
--color: #dddddd;
|
|
32
|
+
--contrast-color: #000;
|
|
30
33
|
--value-color: #43e5f7;
|
|
31
34
|
--value-bg-color: #444444;
|
|
32
35
|
--disabled-color: #666666;
|
|
@@ -678,5 +681,65 @@ export default `
|
|
|
678
681
|
z-index: 100001;
|
|
679
682
|
}
|
|
680
683
|
|
|
681
|
-
|
|
684
|
+
`,
|
|
685
|
+
themes: {
|
|
686
|
+
default: '',
|
|
687
|
+
float: `
|
|
688
|
+
:root {
|
|
689
|
+
color-scheme: light dark,
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
.muigui {
|
|
693
|
+
--width: 400px;
|
|
694
|
+
--bg-color: initial;
|
|
695
|
+
--label-width: 25%;
|
|
696
|
+
--number-width: 20%;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
input,
|
|
700
|
+
.muigui-label-controller>label {
|
|
701
|
+
text-shadow:
|
|
702
|
+
-1px -1px 0 var(--contrast-color),
|
|
703
|
+
1px -1px 0 var(--contrast-color),
|
|
704
|
+
-1px 1px 0 var(--contrast-color),
|
|
705
|
+
1px 1px 0 var(--contrast-color);
|
|
706
|
+
}
|
|
682
707
|
|
|
708
|
+
.muigui-controller > label:nth-child(1) {
|
|
709
|
+
place-content: center end;
|
|
710
|
+
margin-right: 1em;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.muigui-value > :nth-child(2) {
|
|
714
|
+
margin-left: 1em;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.muigui-root>*:nth-child(1) {
|
|
718
|
+
display: none;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.muigui-range input[type=range]::-webkit-slider-thumb {
|
|
722
|
+
border-radius: 1em;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.muigui-range input[type=range]::-webkit-slider-runnable-track {
|
|
726
|
+
-webkit-appearance: initial;
|
|
727
|
+
appearance: none;
|
|
728
|
+
border: 1px solid rgba(0, 0, 0, 0.25);
|
|
729
|
+
height: 2px;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.muigui-colors {
|
|
733
|
+
--value-color: var(--color );
|
|
734
|
+
--value-bg-color: rgba(0, 0, 0, 0.1);
|
|
735
|
+
--disabled-color: #cccccc;
|
|
736
|
+
--menu-bg-color: rgba(0, 0, 0, 0.1);
|
|
737
|
+
--menu-sep-color: #bbbbbb;
|
|
738
|
+
--hover-bg-color: rgba(0, 0, 0, 0);
|
|
739
|
+
--invalid-color: #FF0000;
|
|
740
|
+
--selected-color: rgba(0, 0, 0, 0.3);
|
|
741
|
+
--range-color: rgba(0, 0, 0, 0.125);
|
|
742
|
+
}
|
|
743
|
+
`,
|
|
744
|
+
},
|
|
745
|
+
};
|
|
@@ -2,6 +2,7 @@ import { createElem } from '../libs/elem.js';
|
|
|
2
2
|
import EditView from './EditView.js';
|
|
3
3
|
|
|
4
4
|
export default class CheckboxView extends EditView {
|
|
5
|
+
#checkboxElem;
|
|
5
6
|
constructor(setter, id) {
|
|
6
7
|
const checkboxElem = createElem('input', {
|
|
7
8
|
type: 'checkbox',
|
|
@@ -14,8 +15,9 @@ export default class CheckboxView extends EditView {
|
|
|
14
15
|
},
|
|
15
16
|
});
|
|
16
17
|
super(createElem('label', {}, [checkboxElem]));
|
|
18
|
+
this.#checkboxElem = checkboxElem;
|
|
17
19
|
}
|
|
18
20
|
updateDisplay(v) {
|
|
19
|
-
this.
|
|
21
|
+
this.#checkboxElem.checked = v;
|
|
20
22
|
}
|
|
21
23
|
}
|
|
@@ -3,14 +3,10 @@ import { addTouchEvents } from '../libs/touch.js';
|
|
|
3
3
|
import { clamp } from '../libs/utils.js';
|
|
4
4
|
import EditView from './EditView.js';
|
|
5
5
|
import {
|
|
6
|
-
hexToUint8RGB,
|
|
7
6
|
hexToFloatRGB,
|
|
8
|
-
hslToRgbUint8,
|
|
9
7
|
hsv01ToRGBFloat,
|
|
10
8
|
rgbFloatToHSV01,
|
|
11
|
-
rgbUint8ToHsl,
|
|
12
9
|
floatRGBToHex,
|
|
13
|
-
uint8RGBToHex,
|
|
14
10
|
} from '../libs/color-utils.js';
|
|
15
11
|
|
|
16
12
|
const svg = `
|
package/src/views/RangeView.js
CHANGED
|
@@ -22,16 +22,22 @@ export default class RangeView extends EditView {
|
|
|
22
22
|
type: 'range',
|
|
23
23
|
onInput: () => {
|
|
24
24
|
this.#skipUpdate = true;
|
|
25
|
-
const
|
|
25
|
+
const {min, max, step} = this.#options;
|
|
26
|
+
const v = parseFloat(this.domElement.value);
|
|
27
|
+
const newV = clamp(stepify(v, v => v, step), min, max);
|
|
28
|
+
const [valid, validV] = this.#from(newV);
|
|
26
29
|
if (valid) {
|
|
27
|
-
setter.setValue(
|
|
30
|
+
setter.setValue(validV);
|
|
28
31
|
}
|
|
29
32
|
},
|
|
30
33
|
onChange: () => {
|
|
31
34
|
this.#skipUpdate = true;
|
|
32
|
-
const
|
|
35
|
+
const {min, max, step} = this.#options;
|
|
36
|
+
const v = parseFloat(this.domElement.value);
|
|
37
|
+
const newV = clamp(stepify(v, v => v, step), min, max);
|
|
38
|
+
const [valid, validV] = this.#from(newV);
|
|
33
39
|
if (valid) {
|
|
34
|
-
setter.setFinalValue(
|
|
40
|
+
setter.setFinalValue(validV);
|
|
35
41
|
}
|
|
36
42
|
},
|
|
37
43
|
onWheel: e => {
|