@nebularstreams/libmui 2.0.2 → 2.0.4

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 (38) hide show
  1. package/dist/libui.css +15 -1
  2. package/package.json +2 -5
  3. package/rollup.config.js +20 -0
  4. package/src/app/app.js +9 -0
  5. package/src/css/a-measures.css +5 -0
  6. package/src/css/b-root-bootstrap-ext.css +81 -0
  7. package/src/css/b-root-bootstrap.css +178 -0
  8. package/src/css/b-root-semantic-flex.css +70 -0
  9. package/src/css/b-root-semantic-size-new.css +37 -0
  10. package/src/css/b-root-semantic-size.css +55 -0
  11. package/src/css/b-root-semantic-skin.css +48 -0
  12. package/src/css/b-root-semantic.css +111 -0
  13. package/src/css/b-root.css +3 -0
  14. package/src/css/body.css +60 -0
  15. package/src/css/cardie.css +6 -0
  16. package/src/css/flex.css +46 -0
  17. package/src/css/fontawesome/brands.min.css +16 -0
  18. package/src/css/fontawesome/fontawesome-ext.css +7 -0
  19. package/src/css/fontawesome/fontawesome-solid.css +17 -0
  20. package/src/css/fontawesome/fontawesome.css +4359 -0
  21. package/src/index.js +34 -0
  22. package/src/style.js +14 -0
  23. package/src/util/fuckingconfirm.js +28 -0
  24. package/src/util/mithril-range.js +443 -0
  25. package/src/util/util.clone.js +8 -0
  26. package/src/util/util.tokenizer.js +227 -0
  27. package/src/util/widgets.core.js +314 -0
  28. package/src/util/widgets.js +72 -0
  29. package/src/util/widgets.utils.js +10 -0
  30. package/src/widgets/Basic.js +346 -0
  31. package/src/widgets/CardieWidget.js +167 -0
  32. package/src/widgets/ComboPrompt.js +112 -0
  33. package/src/widgets/InputWidget.js +238 -0
  34. package/src/widgets/NoticeWidget.js +31 -0
  35. package/src/widgets/OverflowUtils.js +449 -0
  36. package/src/widgets/RangeWidget.js +200 -0
  37. package/src/widgets/Separator.js +21 -0
  38. package/src/widgets/SwitchWidget.js +42 -0
@@ -0,0 +1,449 @@
1
+ import m from "mithril";
2
+ import defineWidget from "../util/widgets.utils";
3
+ import * as widget from "../util/widgets";
4
+ import {Icon, Notification, ButtonNew} from "./Basic"
5
+ import {OverflowMenu} from "../util/widgets.core";
6
+ import SwitchWidget from "../widgets/SwitchWidget";
7
+ import InputWidget from "../widgets/InputWidget";
8
+ import Notice from "../widgets/NoticeWidget";
9
+ import clone from "../util/util.clone"
10
+
11
+ function choose(items, config = {
12
+ icon: "circle", onSelect: () => {
13
+ }
14
+ }) {
15
+
16
+ const
17
+ {icon, title, field, onSelect, parser = (v) => v} = config,
18
+ options = items.map((item, index) => ({
19
+ icon: field && item.icon || icon,
20
+ // WARNING !!!!!
21
+ caption: parser(field ? item[field] : item, item),
22
+ // caption: idField ? item[idField] : item,
23
+ onClick: (e) => onSelect(item, e, index)
24
+ }));
25
+
26
+ if (Array.isArray(items) && !items.length) {
27
+ Notification.add("No items available");
28
+ } else {
29
+ OverflowMenu(
30
+ document.body,
31
+ {title},
32
+ options
33
+ )
34
+ .then(({action}) => action.onClick());
35
+ }
36
+ }
37
+
38
+ function promptOptions(items, onchange, options = {}) {
39
+
40
+ const
41
+ {title, field, icon, textNew, textHint, resolve} = options,
42
+ dialogOptions = Array.isArray(items)
43
+ ? items.map((item) => ({
44
+ icon,
45
+ // WARNING !!!!!
46
+ caption: field ? item[field] : item,
47
+ // caption: idField ? item[idField] : item,
48
+ onClick: (e) => onchange(item, e)
49
+ }))
50
+ : Object.keys(items)
51
+ .map((key) => ({
52
+ icon: items[key].icon || icon,
53
+ caption: items[key].caption || key,
54
+ onClick: (e) => onchange(
55
+ resolve && items[key].value !== undefined
56
+ ? items[key].value
57
+ : items[key],
58
+ e)
59
+ }));
60
+
61
+ if (Array.isArray(items) && !items.length) {
62
+ Notification.add("No items available");
63
+ } else {
64
+ OverflowMenu(
65
+ document.body,
66
+ {title},
67
+ [
68
+ ...textNew && !field
69
+ ? [
70
+ {
71
+ icon: "plus",
72
+ caption: textNew,
73
+ onClick: () => promptName(
74
+ textNew,
75
+ "",
76
+ textHint,
77
+ (value) => {
78
+ if (value) {
79
+ if (value && value.trim()) {
80
+ onchange(value);
81
+ m.redraw();
82
+ }
83
+ }
84
+ }
85
+ )
86
+ }
87
+ ]
88
+ : [],
89
+ ...dialogOptions
90
+ ]
91
+ )
92
+ .then(({action}) => action.onClick())
93
+ .finally(() => {
94
+ });
95
+ }
96
+ }
97
+
98
+ function promptName(title, value, hint, action, state = {}) {
99
+ setTimeout(() => OverflowMenu(
100
+ document.body,
101
+ {title},
102
+ [
103
+ {
104
+ type: "text",
105
+ hint,
106
+ value
107
+ }
108
+ ]
109
+ )
110
+ .then(({value: val}) => {
111
+ state.refreshKey = String(Date.now());
112
+ return action(val);
113
+ }), 100);
114
+ }
115
+
116
+ const
117
+ WHAT_DO_UPDATE_LIGHTS = 0, // 0
118
+ WHAT_DO_UPDATE_FACE = 1, // 1
119
+ WHAT_DO_UPDATE_PARTICLES = 2, // 4
120
+ WHAT_DO_UPDATE_SEGMENTATION = 3,
121
+ WHAT_DO_UPDATE_VAL_VPLANE = 4,
122
+ WHAT_DO_UPDATE_VAL_PANO = 5,
123
+ WHAT_DO_UPDATE_VAL_FREE = 6,
124
+ WHAT_DO_UPDATE_VAL_DRONE = 7,
125
+ WHAT_DO_UPDATE_VAL_TRANSITION = 8,
126
+ WHAT_DO_UPDATE_TVFX = 9,
127
+ WHAT_DO_UPDATE_VAL_FOLLOW = 10,
128
+
129
+ PROPERTIES = [
130
+ ["Lights and Fog", null, ["amblight", "l0", "l1", "l2", "l3", "fog"], WHAT_DO_UPDATE_LIGHTS],
131
+ ["Face and Accessories", null, ["facekit"], WHAT_DO_UPDATE_FACE],
132
+ ["Particle settings", null, ["particles"], WHAT_DO_UPDATE_PARTICLES],
133
+ ["Video Segmentation", "common", ["segcam", "mask", "green"], WHAT_DO_UPDATE_SEGMENTATION, true],
134
+ ["Video Effects", null, ["fxconfig"], WHAT_DO_UPDATE_TVFX],
135
+ ["Video Plane", "val", ["xvideo", "yvideo", "zvideo", "rvideo", "svideo", "video"], WHAT_DO_UPDATE_VAL_VPLANE],
136
+ ["Main Camera", "val", ["ypos", "xpos", "zoom", "yaw", "pitch", "roll", "ai"], WHAT_DO_UPDATE_VAL_PANO],
137
+ ["Drone Camera", "val", ["free"], WHAT_DO_UPDATE_VAL_FREE],
138
+ ["Followed Agent", "val", ["track"], WHAT_DO_UPDATE_VAL_FOLLOW],
139
+ ["Game Camera", "val", ["orbit", "track", "ocam"], WHAT_DO_UPDATE_VAL_DRONE, undefined, true],
140
+ ["Transition Speed", "val", ["spd"], WHAT_DO_UPDATE_VAL_TRANSITION]
141
+ ],
142
+
143
+ TitleBarWidget = defineWidget(
144
+ ({attrs}) => m("h2.marg-2.no-marg-bottom", attrs.title)
145
+ ),
146
+ EntityTemplates = defineWidget(
147
+ ({attrs}) => {
148
+
149
+ const
150
+ {type = "changes", meta, onInput, title, options} = attrs,
151
+ valid = meta.title?.trim().length && meta.description?.trim().length,
152
+ embedded = options && options.embedded;
153
+
154
+ return m(".flexcol.grows.ohidden.fadein", [
155
+ ...attrs.title ? [
156
+ m(TitleBarWidget, {
157
+ title
158
+ })] : [],
159
+ m(".flexrow.wrap.grows.pad-3.propsgroup.scrolly", [
160
+ ...attrs.notice ? [
161
+ m(Notice, {
162
+ class: "marg-1 marg-v withbottommargin font-75 col-12",
163
+ size: 1,
164
+ icon: "info-circle",
165
+ text: attrs.notice
166
+ })
167
+ ] : [],
168
+ m(
169
+ ".witharia.col-12.pad-1.pad-v",
170
+ {"aria-label": type + " name"},
171
+ m(InputWidget, {
172
+ class: "pad-2 pad-xh " + (valid ? "valid" : "invalid"),
173
+ value: meta.title,
174
+ maxlength: 64,
175
+ onchange: (newvalue) => {
176
+ meta.title = newvalue;
177
+ m.redraw();
178
+ }
179
+ })
180
+ ),
181
+ ...embedded ? []
182
+ : [
183
+ m(
184
+ ".col-12.witharia.pad-1.pad-v",
185
+ {"aria-label": "description"},
186
+ m(InputWidget, {
187
+ class: "pad-2 pad-xh " + (meta.description ? "valid" : "invalid"),
188
+ value: meta.description,
189
+ maxlength: 240,
190
+ multi: true,
191
+ alwaysmulti: true,
192
+ onchange: (newvalue) => {
193
+ meta.description = newvalue;
194
+ m.redraw();
195
+ }
196
+ })
197
+ ),
198
+ m(
199
+ ".col-8.witharia.pad-1.pad-v",
200
+ {"aria-label": "tags"},
201
+ m(InputWidget, {
202
+ class: "pad-2 pad-xh",
203
+ value: meta.tags,
204
+ maxlength: 128,
205
+ onchange: (newvalue) => {
206
+ meta.tags = newvalue.toLowerCase()
207
+ .split(" ")
208
+ .join(",")
209
+ .split(",")
210
+ .filter((tag) => tag.length)
211
+ .join(",");
212
+ }
213
+ })
214
+ ),
215
+ m(
216
+ ".col-4.witharia.pad-1.pad-v",
217
+ {"aria-label": "youtube video"},
218
+ m(InputWidget, {
219
+ class: "pad-2 pad-xh",
220
+ value: meta.ytref || "",
221
+ hint: "YouTube ID",
222
+ maxlength: 16,
223
+ onchange: (newvalue) => {
224
+ newvalue = newvalue.trim();
225
+ if (newvalue) {
226
+ if (newvalue.indexOf(" ") === -1) {
227
+ meta.ytref = newvalue.trim();
228
+ }
229
+ } else {
230
+ delete meta.ytref;
231
+ }
232
+ }
233
+ })
234
+ )
235
+ ],
236
+ m(
237
+ ".col-4.witharia.pad-1.pad-v",
238
+ {"aria-label": "content attribution"},
239
+ m(InputWidget, {
240
+ class: "pad-2 pad-xh",
241
+ value: meta.author,
242
+ hint: "author name",
243
+ maxlength: 128,
244
+ onchange: (newvalue) => {
245
+ meta.author = newvalue;
246
+ }
247
+ })
248
+ ),
249
+
250
+ m(
251
+ ".col-4.witharia.pad-1.pad-v",
252
+ {"aria-label": "license or author link"},
253
+ m(InputWidget, {
254
+ class: "pad-2 pad-xh",
255
+ hint: "https://...",
256
+ value: meta.link,
257
+ maxlength: 128,
258
+ onchange: (newvalue) => {
259
+ meta.link = newvalue;
260
+ }
261
+ })
262
+ ),
263
+ m(
264
+ ".col-4.witharia.pad-1.pad-v",
265
+ {"aria-label": "source domain"},
266
+ m(InputWidget, {
267
+ class: "pad-2 pad-xh",
268
+ value: meta.source,
269
+ hint: "example.com",
270
+ maxlength: 128,
271
+ onchange: (newvalue) => {
272
+ meta.source = newvalue;
273
+ }
274
+ })
275
+ ),
276
+
277
+ m(
278
+ ".col-12.al-right.marg-2.marg-v",
279
+ m(ButtonNew, {
280
+ class: "noshrink accentbutton unitheightsmall col-4",
281
+ text: "save " + type,
282
+ onClick: () => {
283
+
284
+ const isValid = meta.title?.trim().length && (embedded || meta.description?.trim().length);
285
+
286
+ if (isValid) {
287
+ widget.popupMessage(null);
288
+ onInput(meta);
289
+ } else {
290
+ Notification.add("Information is incomplete or invalid");
291
+ }
292
+ }
293
+ })
294
+ )
295
+ ])
296
+ ]);
297
+ }
298
+ ),
299
+ promptEntity = (meta, title, type, options = {}) => new Promise((resolve, reject) => {
300
+ widget.popupMessage(
301
+ m(EntityTemplates, {
302
+ meta,
303
+ type,
304
+ title,
305
+ options,
306
+ onInput: (newMeta) => resolve(newMeta)
307
+ }),
308
+ () => {
309
+ reject(new Error("cancelled"));
310
+ }
311
+ );
312
+ }),
313
+ PresetTemplate = defineWidget(
314
+ ({attrs}) => {
315
+
316
+ const
317
+
318
+ {parameters, preset, presetComponents, types, globalData, fetcher} = attrs,
319
+ available = [],
320
+ sourceAvailable = [],
321
+ items = types
322
+ ? PROPERTIES
323
+ : PROPERTIES.filter((cosa) => {
324
+
325
+ const
326
+ [, primaryTarget, elements, index, globalSource] = cosa,
327
+ target = primaryTarget ? preset[primaryTarget] : preset,
328
+ rootSource = globalSource ? globalData : parameters,
329
+ source = primaryTarget ? rootSource[primaryTarget] : rootSource;
330
+
331
+ let found = false;
332
+
333
+ if (elements.length) {
334
+
335
+ for (const element of elements) {
336
+ if (target && target[element] !== undefined) {
337
+ found = available[index] = true;
338
+ }
339
+ if (source[element] !== undefined) {
340
+ found = sourceAvailable[index] = true;
341
+ }
342
+ }
343
+ return found;
344
+ } else {
345
+ found = true;
346
+ sourceAvailable[index] = !!source;
347
+ available[index] = !!target;
348
+ }
349
+ return found;
350
+
351
+ });
352
+
353
+ return m(
354
+ "ul.flexrow.wrap.userdialog",
355
+ items.length
356
+ ? items.map((cosa) => {
357
+
358
+ const
359
+ [title, primaryTarget, elements, cosaIndex, globalSource, fetchLive] = cosa,
360
+ target = types ? undefined : primaryTarget ? preset[primaryTarget] : preset,
361
+ rootSource = globalSource ? globalData : parameters,
362
+ source = types ? undefined : primaryTarget ? rootSource[primaryTarget] : rootSource,
363
+ deleteCurrent = () => {
364
+ if (elements.length) {
365
+ for (const field of elements) {
366
+ delete target[field];
367
+ }
368
+ } else if (elements.length === 0 && primaryTarget) {
369
+ delete preset[primaryTarget];
370
+ }
371
+ attrs.redraw && attrs.redraw();
372
+ },
373
+ updateCurrent = () => {
374
+ if (elements.length) {
375
+ if (primaryTarget && !preset[primaryTarget]) preset[primaryTarget] = {};
376
+ const updatedTarget = primaryTarget ? preset[primaryTarget] : preset;
377
+ for (const field of elements) {
378
+ if (source[field] !== undefined) {
379
+ const finalSource = fetchLive && fetcher ? fetcher(updatedTarget[field], cosaIndex) : source[field];
380
+ updatedTarget[field] = clone(finalSource);
381
+ }
382
+ }
383
+ } else if (elements.length === 0 && primaryTarget) {
384
+ if (source !== undefined) {
385
+ const finalSource = fetchLive && fetcher ? fetcher(source, cosaIndex) : source;
386
+ preset[primaryTarget] = clone(finalSource);
387
+ }
388
+ }
389
+ attrs.redraw && attrs.redraw();
390
+ Notification.add(`updated ${title} from current scene`);
391
+ },
392
+ isAvailable = types || available[cosaIndex],
393
+ isSourceAvailable = sourceAvailable[cosaIndex];
394
+
395
+ return [
396
+ ...presetComponents ? [
397
+ m(SwitchWidget, {
398
+ title: `Include ${cosa[0]} in snapshots`,
399
+ class: "grows unitheightsmall" + (presetComponents[cosaIndex] ? " accent" : ""),
400
+ checked: !!presetComponents[cosaIndex],
401
+ onchange: (status) => {
402
+ presetComponents[cosaIndex] = !presetComponents[cosaIndex];
403
+ m.redraw();
404
+ attrs.redraw && attrs.redraw();
405
+ }
406
+ }),
407
+ m(".grows", {class: isAvailable ? "avail" : "unavail"}, title)
408
+ ] : [],
409
+ ...!attrs.types ? [
410
+ m(ButtonNew, {
411
+ class: "col-3" + (isSourceAvailable ? "avail" : "unavail"),
412
+ icon: "sync", title: `Copy ${title} from current state`,
413
+ onClick: updateCurrent
414
+ }),
415
+ m(ButtonNew, {
416
+ class: "col-3 " + (isAvailable ? "" : "disabled text-lo"),
417
+ icon: "trash", title: `Delete ${title} in preset`,
418
+ onClick: () => isAvailable && deleteCurrent()
419
+ })
420
+ ] : [],
421
+ m(".flexbreak")
422
+ ];
423
+
424
+ })
425
+ : m("h3", "Preset is Empty")
426
+ );
427
+ }
428
+ ),
429
+ promptPreset = (preset, parameters, options = {}) => new Promise((resolve, reject) => {
430
+ widget.popupMessage(
431
+ () => m(PresetTemplate, {
432
+ ...options,
433
+ preset,
434
+ parameters,
435
+ redraw: () => widget.popupMessage.redraw()
436
+ }),
437
+ () => {
438
+ reject(new Error("cancelled"));
439
+ }
440
+ );
441
+ });
442
+
443
+ export {
444
+ promptName,
445
+ promptEntity,
446
+ promptPreset,
447
+ promptOptions,
448
+ choose
449
+ };
@@ -0,0 +1,200 @@
1
+ import m from "mithril";
2
+ import MithrilRange from "../util/mithril-range";
3
+
4
+ let
5
+ __timer;
6
+
7
+ const
8
+ resetMultiplier = (state) => {
9
+ /*
10
+ if (state.curMultiplier > 1 && state.value < state.curMax * (state.curMultiplier - 1)) {
11
+ state.curMultiplier = Math.ceil(state.value / state.curMax);
12
+ m.redraw();
13
+ }
14
+ */
15
+
16
+ const
17
+ // req multiplier to show value within negative bounds
18
+ maxMultiplier = state.value > state.curMax ? Math.ceil(state.value / state.curMax) : 1,
19
+ // req multiplier to show value within positive bounds
20
+ minMultiplier = (state.curMin < 0 && state.value < state.curMin) ? Math.abs(Math.ceil(state.value / state.curMin)) : 1,
21
+ // chosen
22
+ multiplier = Math.min(Math.max(minMultiplier, maxMultiplier), state.maxMultiplier);
23
+
24
+ if (state.curMultiplier !== multiplier) {
25
+ state.curMultiplier = multiplier;
26
+ m.redraw();
27
+ }
28
+ },
29
+ increaseMultiplier = (state) => {
30
+ if (
31
+ state.value >= (state.curMax * state.curMultiplier) * 0.9
32
+ && state.maxMultiplier > 1
33
+ && state.curMultiplier <= state.maxMultiplier - 1
34
+ ) {
35
+ state.curMultiplier++;
36
+ return true;
37
+ }
38
+ if (state.curMin < 0) return increaseMinMultiplier(state);
39
+ },
40
+ increaseMinMultiplier = (state) => {
41
+ if (state.value <= (state.curMin * state.curMultiplier) * 0.9
42
+ && state.maxMultiplier > 1
43
+ && state.curMultiplier <= state.maxMultiplier - 1
44
+ ) {
45
+ state.curMultiplier++;
46
+ return true;
47
+ }
48
+ },
49
+ RangeSlider = {
50
+
51
+ oninit: ({attrs, state}) => {
52
+ Object.assign(state, {
53
+ value: attrs.value || 0,
54
+ initial: attrs.value || 0,
55
+ curMax: attrs.max,
56
+ curMin: attrs.min,
57
+ curMultiplier: 1,
58
+ maxMultiplier: attrs.multiplier || 1,
59
+ id: "I" + Date.now()
60
+ });
61
+ // adjust initial multiplier
62
+ if (state.maxMultiplier > 1) {
63
+ if (state.value > attrs.max) {
64
+ state.curMultiplier = Math.ceil(state.value / attrs.max);
65
+ } else if (attrs.min < 0 && state.value < attrs.min) {
66
+ state.curMultiplier = Math.abs(Math.ceil(state.value / attrs.min));
67
+ }
68
+ }
69
+ },
70
+ onupdate: ({attrs, state}) => {
71
+ const
72
+ attrsMultiplier = attrs.multiplier || 1,
73
+ attrsValue = attrs.value || 0;
74
+
75
+ if (state.curMax !== attrs.max || state.maxMultiplier !== attrsMultiplier) {
76
+
77
+ Object.assign(state, {
78
+ curMax: attrs.max,
79
+ curMin: attrs.min,
80
+ maxMultiplier: attrsMultiplier,
81
+ value: attrs.value,
82
+ initial: attrsValue
83
+ });
84
+ if (!increaseMultiplier(state)) {
85
+ clearTimeout(state.timer);
86
+ state.timer = setTimeout(resetMultiplier, 1000, state);
87
+ }
88
+
89
+ m.redraw();
90
+
91
+ } else if (state.initial !== attrsValue) {
92
+
93
+ Object.assign(state, {
94
+ value: attrsValue,
95
+ initial: attrsValue
96
+ });
97
+
98
+ clearTimeout(__timer);
99
+ __timer = setTimeout(() => m.redraw(), 50);
100
+
101
+ /*
102
+ if (!increaseMultiplier(state)) {
103
+ state.timer = setTimeout(resetMultiplier, 1000, state);
104
+ clearTimeout(state.timer);
105
+ }
106
+ */
107
+ }
108
+ },
109
+ view: ({attrs, state}) => m(
110
+ ".range.flexcol.control.relative" + (attrs.multiplier > 1 ? ".withmultiplier" : ""),
111
+ {
112
+ ...attrs.class && {class: attrs.class},
113
+ title: attrs.hint || "Click, then use arrows to finetune value if needed"
114
+ },
115
+ [
116
+ ...attrs.title ? [m("label", {class: "rangelabel", htmlFor: state.id}, attrs.title)] : [],
117
+ m(MithrilRange, {
118
+ onchange: (value) => {
119
+
120
+ state.value = value;
121
+
122
+ const increased = increaseMultiplier(state);
123
+
124
+ if (!increased && state.curMultiplier > 1) {
125
+ clearTimeout(state.timer);
126
+ state.timer = setTimeout(resetMultiplier, 1000, state);
127
+ }
128
+
129
+ if (attrs.onchange) {
130
+ attrs.onchange(value);
131
+ } else {
132
+ m.redraw();
133
+ }
134
+ },
135
+ ondrag: (value) => {
136
+ if (value !== state.value) {
137
+ state.value = value;
138
+ if (attrs.ondrag) attrs.ondrag(value);
139
+ return true;
140
+ }
141
+ return false;
142
+ },
143
+ value: state.value || 0,
144
+ min: (attrs.min || 0) * state.curMultiplier,
145
+ max: (state.curMax * state.curMultiplier) || 100,
146
+ step: attrs.step || 1,
147
+ relative: attrs.relative,
148
+ factor: attrs.factor
149
+ }, [
150
+ m(".currentval", attrs.parser
151
+ ? attrs.parser(state.value, attrs.step < 1)
152
+ : state.value
153
+ ? attrs.step < 1
154
+ ? state.value.toFixed(2)
155
+ : ("" + Math.floor(state.value)) : "")
156
+ ])
157
+ /*
158
+ m(".datalist.flexrow", [
159
+ m("div", attrs.getLabel(0)),
160
+ m(".ismax", attrs.getLabel(attrs.max || 100))
161
+ ])
162
+ */
163
+ ]
164
+ )
165
+ },
166
+ RangeWidget = {
167
+ view: ({attrs, state}) => m(RangeSlider, {
168
+ value: attrs.value || 0,
169
+ min: attrs.min || 0,
170
+ max: attrs.max || 100,
171
+ step: attrs.step || 0.1,
172
+ class: (attrs.disabled ? "disabled " : "") + (attrs.class || ""),
173
+ title: attrs.title,
174
+ multiplier: attrs.multiplier,
175
+ hint: attrs.hint,
176
+ parser: attrs.parser,
177
+ relative: attrs.relative,
178
+ factor: attrs.factor,
179
+
180
+ // values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
181
+ getLabel: (value) => (value ? "" + value : "default"),
182
+ ondrag: (value) => {
183
+ state.changed = true;
184
+ state.value = value;
185
+ if (attrs.onchange) attrs.onchange(value, true);
186
+ return true;
187
+ },
188
+ onchange: (value) => {
189
+ if (attrs.auto0) {
190
+ value = 0;
191
+ } else if (attrs.autoValue) value = attrs.autoValue;
192
+ state.changed = true;
193
+ state.value = value;
194
+ if (attrs.onchange) attrs.onchange(value, false);
195
+ return true;
196
+ }
197
+ })
198
+ };
199
+
200
+ export default RangeWidget;
@@ -0,0 +1,21 @@
1
+ import m from "mithril";
2
+ import defineWidget from "../util/widgets.utils";
3
+
4
+
5
+ const
6
+
7
+ Separator = defineWidget(
8
+ ({ attrs, children }) => m(
9
+ ".separator",
10
+ {
11
+ class: attrs.class || "mini",
12
+ ...attrs.onClick && { onclick: attrs.onClick }
13
+ },
14
+ [
15
+ m("span.grows", attrs.text),
16
+ ...(children || [])
17
+ ]
18
+ )
19
+ );
20
+
21
+ export default Separator;