@nebularstreams/libmui 2.0.12 → 2.0.14
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/dist/libui.css +1 -1
- package/dist/libui.esm.js +1 -1
- package/dist/libui.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/css/ui.popup.css +9 -12
- package/src/index.js +53 -4
- package/src/meta/Emojis.js +32136 -0
- package/src/meta/FontAwesome.js +8012 -0
- package/src/meta/InputTemplates.js +3 -0
- package/src/util/colorjoe.js +1371 -0
- package/src/util/tainter.js +31 -0
- package/src/util/util.tokenizer.js +7 -1
- package/src/widgets/ButtonChoiceWidget.js +72 -0
- package/src/widgets/ColorJoeWidget.js +144 -0
- package/src/widgets/ComboWidget.js +155 -0
- package/src/widgets/FontSelectorButton.js +36 -0
- package/src/widgets/PlusMinusWidget.js +55 -0
- package/src/widgets/SelectFileMiniButton.js +194 -0
- package/src/widgets/SmileysButton.js +18 -0
- package/src/widgets/SmileysPanel.js +20 -0
- package/src/widgets/SmileysWidget.js +199 -0
- package/src/widgets/TemplatedInputWidget.js +1219 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
|
|
3
|
+
let
|
|
4
|
+
gTainted = false;
|
|
5
|
+
|
|
6
|
+
function taint() {
|
|
7
|
+
gTainted = true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function taintRedraw() {
|
|
11
|
+
const r = gTainted;
|
|
12
|
+
gTainted = true;
|
|
13
|
+
// eslint-disable-next-line no-unused-expressions
|
|
14
|
+
r && m.redraw();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isTainted() {
|
|
18
|
+
return gTainted;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function untaint() {
|
|
22
|
+
gTainted = false;
|
|
23
|
+
m.redraw();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
taint,
|
|
28
|
+
taintRedraw,
|
|
29
|
+
isTainted,
|
|
30
|
+
untaint
|
|
31
|
+
};
|
|
@@ -215,6 +215,11 @@ function tokenizeUrl(tokenizedUrl, parameters, options) {
|
|
|
215
215
|
return message || "(not enough parameters)";
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
+
function sanitizeFilename(filename) {
|
|
219
|
+
return filename ? filename.trim()
|
|
220
|
+
.toLowerCase()
|
|
221
|
+
.replace(/[^0-9A-Z.-]+/gi, "") : null;
|
|
222
|
+
}
|
|
218
223
|
|
|
219
224
|
export {
|
|
220
225
|
tokenize,
|
|
@@ -223,5 +228,6 @@ export {
|
|
|
223
228
|
tokenizeKeep,
|
|
224
229
|
tokenizeWithDefault,
|
|
225
230
|
tokenizeUrl,
|
|
226
|
-
getPointedData
|
|
231
|
+
getPointedData,
|
|
232
|
+
sanitizeFilename
|
|
227
233
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import {ButtonNew, defineWidget} from "./Basic";
|
|
3
|
+
import Separator from "./Separator"
|
|
4
|
+
|
|
5
|
+
const
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
SizeChoices = {
|
|
9
|
+
"1080p": {width: 1920, height: 1080, value: "1080p"},
|
|
10
|
+
"720p": {width: 1280, height: 720, value: "720p"},
|
|
11
|
+
"Fluid": {width: null, height: null, value: "Fluid"},
|
|
12
|
+
"Custom": {value: ""}
|
|
13
|
+
}
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
ButtonChoiceWidget = defineWidget(
|
|
17
|
+
({attrs}) => {
|
|
18
|
+
|
|
19
|
+
const
|
|
20
|
+
{value, field, toggle, element, emptyMessage, chooseKey, chooseDict} = attrs,
|
|
21
|
+
choose = (!attrs.choose && chooseKey && chooseDict) ? chooseDict[chooseKey] : attrs.choose,
|
|
22
|
+
choices = choose
|
|
23
|
+
? choose.map((choice) => ({value: choice, caption: choice}))
|
|
24
|
+
: attrs.choices || {};
|
|
25
|
+
|
|
26
|
+
const
|
|
27
|
+
keys = Object.keys(choices),
|
|
28
|
+
has = keys.length,
|
|
29
|
+
clase = (attrs.class || "") + (attrs.subclass ? " " + attrs.subclass : " scaff scaff-b1");
|
|
30
|
+
|
|
31
|
+
return has || emptyMessage
|
|
32
|
+
? [
|
|
33
|
+
...attrs.label ? [m(Separator, {text: attrs.label, class: attrs.labelClass || ""})] : [],
|
|
34
|
+
m(
|
|
35
|
+
(element || "div") + ".buttonchoice.flexrow.ohidden",
|
|
36
|
+
{
|
|
37
|
+
class: clase + (attrs.icon ? " withicon fa-" + attrs.icon : ""),
|
|
38
|
+
title: attrs.title
|
|
39
|
+
},
|
|
40
|
+
m(
|
|
41
|
+
".flexrow.grows.ohidden.wrap" + (attrs.icon ? " scaff-left" : ""),
|
|
42
|
+
keys.length
|
|
43
|
+
? keys.map((choicekey) => {
|
|
44
|
+
|
|
45
|
+
const
|
|
46
|
+
choice = choices[choicekey],
|
|
47
|
+
choicevalue = attrs.raw && field ? choice : choice.value,
|
|
48
|
+
finalchoicevalue = field ? choicevalue[field] : choicevalue,
|
|
49
|
+
current = finalchoicevalue === value;
|
|
50
|
+
|
|
51
|
+
// noinspection EqualityComparisonWithCoercionJS
|
|
52
|
+
return m(ButtonNew, {
|
|
53
|
+
|
|
54
|
+
icon: choice.icon || undefined,
|
|
55
|
+
class: "grows scaff-b0 " + (attrs.buttonClass ? attrs.buttonClass + " " : "rectbutton unitheightsmall ") + (choice.class ? choice.class + " " : "") + (current ? "accent" : ""),
|
|
56
|
+
title: choice.current ? choice.titleOn || choice.title : choice.titleOff || choice.title,
|
|
57
|
+
onClick: (e) => {
|
|
58
|
+
attrs.onchange(toggle ? current ? undefined : choice : choice, choicekey, e);
|
|
59
|
+
m.redraw();
|
|
60
|
+
}
|
|
61
|
+
}, attrs.render ? attrs.render(choice) : choice.caption || choicekey);
|
|
62
|
+
})
|
|
63
|
+
: [m(".emptychoice.grows.al-center.align-self-center.unitheightsmall", attrs.emptyMessage)]
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
]
|
|
67
|
+
: [];
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export default ButtonChoiceWidget;
|
|
72
|
+
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import defineWidget from "../util/widgets.utils";
|
|
3
|
+
import {popupMessage} from "../util/widgets"
|
|
4
|
+
|
|
5
|
+
const
|
|
6
|
+
colorjoe = require("colorjoe");
|
|
7
|
+
// TODO
|
|
8
|
+
// ColorProbeButton = require("ColorProbeButton");
|
|
9
|
+
|
|
10
|
+
const
|
|
11
|
+
ColorJoe = defineWidget(
|
|
12
|
+
() => m(".colorjoe-frame.absolute"),
|
|
13
|
+
null,
|
|
14
|
+
({attrs, dom}) => {
|
|
15
|
+
|
|
16
|
+
window.SCALE = 1;
|
|
17
|
+
|
|
18
|
+
attrs.state.joe = (attrs.hsl ? colorjoe.hsl : colorjoe.rgb)(
|
|
19
|
+
dom,
|
|
20
|
+
attrs.color,
|
|
21
|
+
attrs.noalpha
|
|
22
|
+
? []
|
|
23
|
+
: [
|
|
24
|
+
// "currentColor",
|
|
25
|
+
"alpha"
|
|
26
|
+
]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
attrs.state.joe.on("change", (c) => {
|
|
30
|
+
attrs.onColor(attrs.noalpha ? c.css() : c.cssa(), c);
|
|
31
|
+
})
|
|
32
|
+
.update();
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
FAVORITES = [],
|
|
36
|
+
ColorJoeWrapper = defineWidget(
|
|
37
|
+
({attrs, state, children}) => m(".colorjoe-popper.flexcol", {
|
|
38
|
+
class: attrs.noalpha ? "no-alpha" : ""
|
|
39
|
+
}, [
|
|
40
|
+
m(ColorJoe, {...attrs, state}),
|
|
41
|
+
...children,
|
|
42
|
+
m(".flexrow.extended.w-100.scaff-top.pad-2.wrap", [
|
|
43
|
+
|
|
44
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8].map((i) => m("button.scaff.scaff-b1.marg-1.unitheightsmall.grows", {
|
|
45
|
+
class: FAVORITES[i] ? "" : "chequered",
|
|
46
|
+
style: {
|
|
47
|
+
...FAVORITES[i] && {backgroundColor: FAVORITES[i]}
|
|
48
|
+
},
|
|
49
|
+
onclick: (e) => {
|
|
50
|
+
if (e.shiftKey) {
|
|
51
|
+
FAVORITES[i] = state.joe.get()
|
|
52
|
+
.css();
|
|
53
|
+
} else {
|
|
54
|
+
if (FAVORITES[i]) state.joe.set(FAVORITES[i]);
|
|
55
|
+
}
|
|
56
|
+
if (attrs.onRedraw) attrs.onRedraw(); else m.redraw();
|
|
57
|
+
}
|
|
58
|
+
})),
|
|
59
|
+
m(".flexbreak"),
|
|
60
|
+
/* TODO ELECTRON
|
|
61
|
+
m(ColorProbeButton, {
|
|
62
|
+
class: "grows marg-1 scaff scaff-b1 unitheightsmall",
|
|
63
|
+
icon: "magic",
|
|
64
|
+
title: "Pick a color from the scene",
|
|
65
|
+
onColor: (color) => state.joe.set(color)
|
|
66
|
+
}),
|
|
67
|
+
*/
|
|
68
|
+
...attrs.onRemove ? [m("button.scaff.scaff-b1.unitheightsmall.marg-1.pad-2.pad-h.grows.fabf.transp.bg-accent.fa-trash", {
|
|
69
|
+
onclick: () => attrs.onRemove(state.joe.get())
|
|
70
|
+
})] : []
|
|
71
|
+
])
|
|
72
|
+
])
|
|
73
|
+
),
|
|
74
|
+
popupColor = (vnode) => popupMessage(
|
|
75
|
+
() => m(ColorJoeWrapper, {
|
|
76
|
+
noalpha: vnode.attrs.noalpha,
|
|
77
|
+
color: vnode.state.color,
|
|
78
|
+
hsl: vnode.attrs.hsl,
|
|
79
|
+
onColor: (parsedColor, colorObject) => {
|
|
80
|
+
vnode.state.color = parsedColor;
|
|
81
|
+
if (vnode.attrs.onchange) vnode.attrs.onchange(parsedColor, colorObject);
|
|
82
|
+
m.redraw();
|
|
83
|
+
},
|
|
84
|
+
onRemove: () => {
|
|
85
|
+
if (vnode.attrs.onchange) vnode.attrs.onchange(null, null);
|
|
86
|
+
popupMessage(null);
|
|
87
|
+
},
|
|
88
|
+
onRedraw: () => {
|
|
89
|
+
popupMessage.redraw();
|
|
90
|
+
m.redraw();
|
|
91
|
+
}
|
|
92
|
+
}, vnode.children),
|
|
93
|
+
|
|
94
|
+
() => {
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
".modal-content-popper"
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const ColorJoeWidget = defineWidget(
|
|
101
|
+
(vnode) => {
|
|
102
|
+
const {attrs, state} = vnode;
|
|
103
|
+
return [
|
|
104
|
+
m(
|
|
105
|
+
".colorjoe-cell.chequered",
|
|
106
|
+
{
|
|
107
|
+
class: (attrs.class || "") + (state.shown ? " open" : ""),
|
|
108
|
+
title: attrs.title,
|
|
109
|
+
...attrs.style && {style: attrs.style}
|
|
110
|
+
},
|
|
111
|
+
[
|
|
112
|
+
m(".inset", {
|
|
113
|
+
style: {
|
|
114
|
+
backgroundColor: state.color
|
|
115
|
+
},
|
|
116
|
+
...attrs.caption && {"data-caption": attrs.caption, class: "titled"},
|
|
117
|
+
onclick: (e) => {
|
|
118
|
+
if (attrs.onshiftclick && (e.shiftKey || e.ctrlKey)) {
|
|
119
|
+
attrs.onshiftclick();
|
|
120
|
+
} else {
|
|
121
|
+
popupColor(vnode);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
])
|
|
126
|
+
];
|
|
127
|
+
},
|
|
128
|
+
({attrs, state}) => {
|
|
129
|
+
state.original = attrs.color;
|
|
130
|
+
state.color = state.original || "rgba(0,0,0,0)";
|
|
131
|
+
},
|
|
132
|
+
null,
|
|
133
|
+
null,
|
|
134
|
+
({attrs, state}) => {
|
|
135
|
+
if (state.original !== attrs.color) {
|
|
136
|
+
state.original = attrs.color;
|
|
137
|
+
state.color = state.original || "rgba(0,0,0,0)";
|
|
138
|
+
m.redraw();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
export default ColorJoeWidget;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
PropGroup = {
|
|
5
|
+
view: ({attrs}) => attrs.items.map(({name}, index) => m(
|
|
6
|
+
"option",
|
|
7
|
+
{
|
|
8
|
+
...(attrs.state.index === index + (attrs.offset || 0)) && {selected: true}
|
|
9
|
+
},
|
|
10
|
+
name
|
|
11
|
+
))
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let
|
|
15
|
+
__timer;
|
|
16
|
+
|
|
17
|
+
function parseGroups(attrs, state) {
|
|
18
|
+
|
|
19
|
+
if (attrs.groups) {
|
|
20
|
+
|
|
21
|
+
state.groups = {};
|
|
22
|
+
state.allItems = [];
|
|
23
|
+
|
|
24
|
+
attrs.parsed = true;
|
|
25
|
+
|
|
26
|
+
const
|
|
27
|
+
groupKeys = Object.keys(attrs.groups);
|
|
28
|
+
|
|
29
|
+
groupKeys.forEach((groupKey) => {
|
|
30
|
+
state.groups[groupKey] = {
|
|
31
|
+
label: groupKey,
|
|
32
|
+
len: attrs.groups[groupKey].length,
|
|
33
|
+
items: attrs.groups[groupKey]
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const
|
|
38
|
+
groupValues = Object.values(state.groups);
|
|
39
|
+
|
|
40
|
+
groupValues
|
|
41
|
+
.forEach((group, index) => {
|
|
42
|
+
|
|
43
|
+
if (attrs.value) {
|
|
44
|
+
state.index = 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
group.offset = index ? groupValues[index - 1].offset + groupValues[index - 1].len : 0;
|
|
48
|
+
state.allItems = state.allItems.concat(group.items);
|
|
49
|
+
if (attrs.value) {
|
|
50
|
+
|
|
51
|
+
group.items.forEach((item, itemIndex) => {
|
|
52
|
+
const
|
|
53
|
+
itemValue = item.value,
|
|
54
|
+
parsedValue = attrs.parser ? attrs.parser(itemValue) : itemValue;
|
|
55
|
+
if (parsedValue === attrs.value) {
|
|
56
|
+
state.index = itemIndex + group.offset;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
} else if (attrs.items) {
|
|
62
|
+
state.index = 0;
|
|
63
|
+
for (let i = 0, l = attrs.items.length; i < l; i++) {
|
|
64
|
+
const
|
|
65
|
+
itemValue = attrs.items[i].value,
|
|
66
|
+
parsedValue = attrs.parser ? attrs.parser(itemValue) : itemValue;
|
|
67
|
+
if (parsedValue === attrs.value) {
|
|
68
|
+
state.index = i;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
state.allItems = attrs.items;
|
|
73
|
+
} else {
|
|
74
|
+
state.allItems = [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const ComboWidget = {
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Creates the Widget View
|
|
83
|
+
* @param vnode
|
|
84
|
+
* @param {SelectAttrs} vnode.attrs
|
|
85
|
+
* @param {Object} vnode.state
|
|
86
|
+
* @return {*}
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
view: ({attrs, state}) => {
|
|
92
|
+
const {groups} = state;
|
|
93
|
+
return m(
|
|
94
|
+
"select",
|
|
95
|
+
{
|
|
96
|
+
"aria-label": attrs.caption,
|
|
97
|
+
class: attrs.class,
|
|
98
|
+
oninput: (ev) => {
|
|
99
|
+
|
|
100
|
+
// el desincronismo es si se camian los items y el state no se entera
|
|
101
|
+
// esto asegura que estan synchro
|
|
102
|
+
parseGroups(attrs, state);
|
|
103
|
+
|
|
104
|
+
const
|
|
105
|
+
index = state.index = ev.target.selectedIndex,
|
|
106
|
+
item = index >= 0 ? state.allItems[index] : null;
|
|
107
|
+
|
|
108
|
+
if (attrs.onchange && item) {
|
|
109
|
+
attrs.onchange(item.value, item, index);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
m.redraw();
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
groups
|
|
116
|
+
? Object.values(groups)
|
|
117
|
+
.map((group) => m("optgroup", {label: group.label}, m(PropGroup, {
|
|
118
|
+
items: group.items,
|
|
119
|
+
offset: group.offset,
|
|
120
|
+
state
|
|
121
|
+
})))
|
|
122
|
+
: m(PropGroup, {items: (attrs.items != null ? attrs.items : []), state}));
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
oninit: ({attrs, state}) => {
|
|
126
|
+
Object.assign(state, {
|
|
127
|
+
index: attrs.index || 0,
|
|
128
|
+
initial: attrs.value
|
|
129
|
+
});
|
|
130
|
+
parseGroups(attrs, state);
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
oncreate: () => {
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
onupdate: ({attrs, state}) => {
|
|
137
|
+
|
|
138
|
+
const refresh = (attrs.value !== undefined && state.initial !== attrs.value);
|
|
139
|
+
|
|
140
|
+
if (!state.groups && !state.allItems || refresh) {
|
|
141
|
+
|
|
142
|
+
// sets index from attrs.value
|
|
143
|
+
parseGroups(attrs, state);
|
|
144
|
+
|
|
145
|
+
if (refresh) {
|
|
146
|
+
state.initial = attrs.value;
|
|
147
|
+
clearTimeout(__timer);
|
|
148
|
+
__timer = setTimeout(() => m.redraw(), 50);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export default ComboWidget;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import {defineWidget, ButtonNew} from "./Basic";
|
|
3
|
+
|
|
4
|
+
const
|
|
5
|
+
// TODO
|
|
6
|
+
FontSelectorButton = defineWidget(
|
|
7
|
+
({attrs}) => {
|
|
8
|
+
const {fontFamily, state, onchange} = attrs;
|
|
9
|
+
return m(".flexrow.grows.fontgroup", {class: attrs.class}, [
|
|
10
|
+
...fontFamily && !attrs.nodelete
|
|
11
|
+
? [
|
|
12
|
+
m(ButtonNew, {
|
|
13
|
+
class: "scaff-right unitsize",
|
|
14
|
+
icon: "trash",
|
|
15
|
+
onClick: () => {
|
|
16
|
+
onchange(undefined);
|
|
17
|
+
state.setTransState();
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
: [],
|
|
22
|
+
m(ButtonNew, {
|
|
23
|
+
class: "grows transp font-125 ohidden",
|
|
24
|
+
text: fontFamily || "default",
|
|
25
|
+
icon: "font",
|
|
26
|
+
onClick: () => state.setTransState("fontsel", (selected) => {
|
|
27
|
+
onchange(selected);
|
|
28
|
+
state.setTransState();
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
]);
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export default FontSelectorButton;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import {ButtonNew, defineWidget} from "./Basic";
|
|
3
|
+
|
|
4
|
+
const
|
|
5
|
+
PlusMinus = defineWidget(
|
|
6
|
+
({attrs}) => {
|
|
7
|
+
return m(".flexrow.wrap.grows",
|
|
8
|
+
{
|
|
9
|
+
...attrs.label && {"aria-label": attrs.label},
|
|
10
|
+
class: (attrs.label ? "witharia" : "") + " " + (attrs.class || ""),
|
|
11
|
+
title: attrs.title || ""
|
|
12
|
+
},
|
|
13
|
+
[
|
|
14
|
+
m(ButtonNew, {
|
|
15
|
+
icon: "minus",
|
|
16
|
+
class: "unitsizesmall transp",
|
|
17
|
+
title: attrs.title ? "decrease the " + attrs.title : "",
|
|
18
|
+
onClick: () => {
|
|
19
|
+
const {
|
|
20
|
+
step = 1,
|
|
21
|
+
min = 0
|
|
22
|
+
} = attrs;
|
|
23
|
+
let v = attrs.value || 0;
|
|
24
|
+
if (Number.isNaN(v)) v = 0;
|
|
25
|
+
v -= step;
|
|
26
|
+
if (v < min) v = min;
|
|
27
|
+
attrs.onchange(v);
|
|
28
|
+
m.redraw();
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
m(".currentvalue.al-center.grows.unitheightsmall", {
|
|
32
|
+
title: attrs.title
|
|
33
|
+
}, String(attrs.value || 0)),
|
|
34
|
+
m(ButtonNew, {
|
|
35
|
+
icon: "plus",
|
|
36
|
+
class: "unitsizesmall transp",
|
|
37
|
+
title: attrs.title ? "decrease the " + attrs.title : "",
|
|
38
|
+
onClick: () => {
|
|
39
|
+
const {
|
|
40
|
+
step = 1,
|
|
41
|
+
max = 0
|
|
42
|
+
} = attrs;
|
|
43
|
+
|
|
44
|
+
let v = attrs.value || 0;
|
|
45
|
+
if (max && v === max) return;
|
|
46
|
+
v += step;
|
|
47
|
+
attrs.onchange(v);
|
|
48
|
+
m.redraw();
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
export default PlusMinus;
|