@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,346 @@
1
+ import m from "mithril";
2
+
3
+ export function defineWidget(view, oninit, oncreate, onremove, onupdate) {
4
+ return {
5
+ ...view && {view},
6
+ ...oninit && {oninit},
7
+ ...oncreate && {oncreate},
8
+ ...onupdate && {onupdate},
9
+ ...onremove && {onremove}
10
+ }
11
+ }
12
+
13
+
14
+ // ------------------------------------------------------------------------
15
+
16
+ function getAttrs(attrs, parentAttrs, panelInitialParams) {
17
+ const data = ((typeof attrs === "function") ? attrs(parentAttrs) : attrs) || {};
18
+ if (panelInitialParams) data.initialParams = panelInitialParams;
19
+ return data;
20
+ }
21
+
22
+ const
23
+
24
+ isCurrent = ({currentIndex}, index) => currentIndex === index,
25
+
26
+ Icon = {
27
+ view: ({attrs}) => m(
28
+ `i.icon.${attrs.pack || "fas"}.fa-${attrs.icon || "cog"}${attrs.size ? ".fa-" + attrs.size + "x" : ""}`,
29
+ {
30
+ title: attrs.icontitle || undefined,
31
+ role: "presentation",
32
+ onclick: attrs.onclick || null, ...attrs.iconClass && {class: attrs.iconClass}
33
+ }
34
+ )
35
+ },
36
+
37
+ Button = {
38
+ view: ({attrs, state, children}) => m((attrs.download || attrs.link) ? "a.button" : "button", {
39
+ ...attrs.link && {href: attrs.link},
40
+ ...attrs.download && {download: attrs.download},
41
+ ...attrs.target && {target: attrs.target},
42
+ "aria-label": attrs["aria-label"] || attrs.title || attrs.text,
43
+ title: attrs.title || attrs["aria-label"],
44
+ class: (attrs.class || "") + (state.busy ? " busy" : ""),
45
+ ...state.error && {"data-error": state.error.message},
46
+ ...attrs.onclick && {
47
+ onclick: (event) => {
48
+ clearTimeout(state.debounce);
49
+ state.debounce = setTimeout(() => {
50
+ const result = attrs.onclick(event, attrs);
51
+ if (result && result.then && result.catch) {
52
+ state.busy = true;
53
+ m.redraw();
54
+ result
55
+ .then(() => {
56
+ state.busy = false;
57
+ m.redraw();
58
+ })
59
+ .catch((error) => {
60
+ state.busy = false;
61
+ state.error = error;
62
+ m.redraw();
63
+ });
64
+ }
65
+ }, 25);
66
+ }
67
+ }
68
+ }, [
69
+ ...(attrs.icon && !attrs.right) ? [m(Icon, attrs)] : [],
70
+ ...attrs.text ? [m("span.pad-1.pad-h", {class: attrs.textClass || null}, attrs.text)] : [],
71
+ ...(attrs.icon && attrs.right) ? [m(Icon, attrs)] : [],
72
+ ...children
73
+ ])
74
+ },
75
+
76
+ ButtonNew = {
77
+ view: ({attrs, state, children}) => m((attrs.download || attrs.link) ? "a.button" : "button", {
78
+ ...attrs.link && {href: attrs.link},
79
+ ...attrs.download && {rel: "nofollow", download: attrs.download},
80
+ ...attrs.target && {target: attrs.target},
81
+ "aria-label": attrs["aria-label"] || attrs.title || attrs.text,
82
+ title: attrs.title || attrs["aria-label"],
83
+ class: (attrs.class || "") + (state.busy ? " busy" : ""),
84
+ ...state.error && {"data-error": state.error.message},
85
+ ...attrs.onClick && {
86
+ onclick: (event) => {
87
+ clearTimeout(state.debounce);
88
+ state.debounce = setTimeout(() => {
89
+ const result = attrs.onClick(event, attrs);
90
+ if (result && result.then && result.catch) {
91
+ state.busy = true;
92
+ m.redraw();
93
+ result
94
+ .then(() => {
95
+ state.busy = false;
96
+ m.redraw();
97
+ })
98
+ .catch((error) => {
99
+ state.busy = false;
100
+ state.error = error;
101
+ m.redraw();
102
+ });
103
+ }
104
+ }, 25);
105
+ }
106
+ }
107
+ }, [
108
+ ...(attrs.icon && !attrs.right) ? [m(Icon, attrs)] : [],
109
+ ...attrs.text ? [m("span.pad-1.pad-h", {class: attrs.textClass || null}, attrs.text)] : [],
110
+ ...(attrs.icon && attrs.right) ? [m(Icon, attrs)] : [],
111
+ ...children
112
+ ])
113
+ },
114
+
115
+ Empty = {
116
+
117
+ view: ({attrs, children}) => m(
118
+ ".flexcol.flexcenter.al-center.grows.emptywidget",
119
+ {
120
+ ...attrs.class && {class: attrs.class},
121
+ ...attrs.key && {key: attrs.key},
122
+ role: "presentation"
123
+ },
124
+ [
125
+ m(Icon, attrs),
126
+ ...attrs.message
127
+ ? [
128
+ m(".marg-2.marg-v",
129
+ {
130
+ role: "status",
131
+ class: attrs.size > 4 ? "font-150" : "font-100",
132
+ "aria-label": attrs.message
133
+ },
134
+ attrs.message.split("\n")
135
+ .map((str, idx, all) => all.length === 1 ? str : m("p.msg" + idx, str))
136
+ )
137
+ ]
138
+ : [],
139
+ ...children
140
+ ? [m(".flexcol.additional", children)]
141
+ : []
142
+ ]
143
+ )
144
+ },
145
+
146
+ setItem = (attrs, state, index, params) => {
147
+
148
+
149
+ const
150
+ lastIndex = state.currentIndex,
151
+ lastParams = state.currentParams;
152
+
153
+ if (index === -1) {
154
+ Object.assign(state, {
155
+ current: null,
156
+ currentIndex: -1,
157
+ currentParams: []
158
+ });
159
+ } else {
160
+ Object.assign(state, {
161
+ current: attrs.items[index] || null,
162
+ currentIndex: state.current ? index : -1,
163
+ currentParams: params || []
164
+ });
165
+ }
166
+
167
+ if (attrs.onSelected) attrs.onSelected(state.current, state.currentParams, state.currentIndex !== lastIndex, lastParams);
168
+
169
+ m.redraw();
170
+ },
171
+
172
+ Selector = {
173
+
174
+ oninit: ({attrs, state}) => {
175
+
176
+ state = attrs.state || state;
177
+ state.setItem = (index, ...params) => setItem(attrs, attrs.state || state, index, params);
178
+
179
+ const
180
+ hasState = !isNaN(state.currentIndex),
181
+ selected = hasState ? state.currentIndex : attrs.selected,
182
+ currentIndex = (attrs.items && attrs.items.length)
183
+ ? (selected !== undefined && attrs.items[selected])
184
+ ? selected
185
+ : attrs.noinitial ? -1 : 0
186
+ : -1,
187
+ current = currentIndex !== -1 ? attrs.items[currentIndex] : null;
188
+
189
+ Object.assign(state, {currentIndex, current});
190
+
191
+ },
192
+
193
+ onupdate: ({attrs, state}) => {
194
+ (attrs.state || state).setItem = (index, ...params) => setItem(attrs, attrs.state || state, index, params);
195
+ },
196
+
197
+ view: ({attrs, state}) => {
198
+
199
+ state = attrs.state || state;
200
+ const {current} = state;
201
+
202
+ return m(
203
+ (attrs.element || "widget") + ".selector" + (attrs.horizontal ? ".flexrow" : ".flexcol") + (attrs.className ? "." + attrs.className : ""),
204
+ {
205
+ ...attrs.key && {key: attrs.key},
206
+ class: (state.current ? "hascurrent" : "empty") + (attrs.class ? " " + attrs.class : "")
207
+ },
208
+ [
209
+ ...((!attrs.hideonly || (attrs.items.length > 1)) && (!attrs.hidesel))
210
+ ? [
211
+ /** navigation bar */
212
+ m(
213
+ "nav.toolbar.fullwidth" + (attrs.horizontal ? ".flexcol" : ".flexrow"),
214
+ {
215
+ "aria-label": attrs["aria-label"] || attrs.title || "selector",
216
+ class: attrs.toolbarClass
217
+ },
218
+ attrs.items.map((item, index) => m(Button, {
219
+ class: (item.class ? item.class + " " : "") + (isCurrent(state, index) ? "accent" : "nel"),
220
+ icon: item.icon || null,
221
+ ...item.title && {title: item.title},
222
+ ...item["aria-label"] && {"aria-label": item["aria-label"]},
223
+ ...item.text && {text: item.text},
224
+ onclick: () => {
225
+ const t = Date.now();
226
+ if (t - state.clickts < 200) return;
227
+ state.clickts = Date.now();
228
+ state.bodyHidden = false;
229
+ state.setItem(index);
230
+ }
231
+ }))
232
+ )]
233
+ : [],
234
+ ...current
235
+ ? [
236
+ ...(attrs.toggle && !state.bodyHidden)
237
+ ? [
238
+ m(ButtonNew, {
239
+ class: "selectornotch " + (state.bodyHidden ? "bodyhidden" : "bodyshown"),
240
+ icon: state.bodyHidden ? "caret-up" : "caret-down",
241
+ title: state.bodyHidden ? "expand panel" : "contract panel",
242
+ onClick: () => {
243
+ state.bodyHidden = !state.bodyHidden;
244
+ m.redraw();
245
+ }
246
+ })
247
+ ] : [],
248
+ ...(!attrs.toggle || !state.bodyHidden)
249
+ ? [
250
+ /** body */
251
+ m(".grows.flexcol.ohidden", {class: attrs.bodyClass, role: "presentation"}, [
252
+ m(
253
+ current.widget,
254
+ getAttrs(current.attrs, attrs, state.currentParams),
255
+ current.children
256
+ )
257
+ ])
258
+ ]
259
+ : [],
260
+ ...attrs.closeButton
261
+ ? [
262
+ m(Button, {
263
+ class: "closebutton absolute toright",
264
+ icon: "times",
265
+ onclick: () => {
266
+ state.setItem(-1);
267
+ },
268
+ "aria-label": "close item"
269
+ })] : []
270
+ ]
271
+ : m(Empty, attrs)
272
+ ]
273
+ );
274
+ }
275
+ };
276
+
277
+ const ICONS = {
278
+ info: "info",
279
+ error: "exclamation-triangle",
280
+ success: "check"
281
+ };
282
+
283
+ function Notifications(TOAST_SHORT = 5000, altContainer) {
284
+
285
+ let
286
+ mNotifications = [],
287
+ mTimer;
288
+
289
+ function render(container, n) {
290
+ m.render(
291
+ container, m(
292
+ Button, {
293
+ class: "notification " + n.type,
294
+ text: n.text,
295
+ icon: ICONS[n.type] || "info",
296
+ size: 1,
297
+ role: "status",
298
+ // eslint-disable-next-line no-use-before-define
299
+ onclick: next
300
+ }
301
+ )
302
+ );
303
+ }
304
+
305
+ function next() {
306
+
307
+ const
308
+ container = altContainer || document.getElementById("notification-container");
309
+
310
+ if (mNotifications.length) {
311
+ const n = mNotifications.splice(0, 1)[0];
312
+ render(container, n);
313
+ clearTimeout(mTimer);
314
+ mTimer = setTimeout(next, n.timer || TOAST_SHORT);
315
+ } else {
316
+ m.render(container, "");
317
+ mTimer = null;
318
+ }
319
+ }
320
+
321
+ return {
322
+ add: (text, type) => {
323
+ mNotifications.push({
324
+ text,
325
+ type
326
+ });
327
+ if (!mTimer) next();
328
+ },
329
+ clear: () => {
330
+ mNotifications = [];
331
+ next();
332
+ }
333
+
334
+ };
335
+ }
336
+
337
+ const Notification = new Notifications();
338
+
339
+ export {
340
+ Empty,
341
+ Icon,
342
+ Selector,
343
+ Button,
344
+ ButtonNew,
345
+ Notification
346
+ }
@@ -0,0 +1,167 @@
1
+ import m from "mithril";
2
+ import {ButtonNew, defineWidget} from "./Basic";
3
+
4
+ const
5
+ globalState = {},
6
+ CARDIE_CLOSED = 0;
7
+
8
+ function setCardStatus(cardid, expanded = CARDIE_CLOSED) {
9
+ if (cardid) {
10
+ const [uniq, subname] = cardid.split("-");
11
+ if (expanded && uniq && subname) {
12
+ Object.keys(globalState)
13
+ .forEach((key) => {
14
+ if (key.startsWith(uniq + "-")) {
15
+ globalState[key] = CARDIE_CLOSED;
16
+ }
17
+ });
18
+ }
19
+ globalState[cardid] = expanded;
20
+ }
21
+ }
22
+
23
+ const CardieWidget = defineWidget(
24
+ ({attrs, state, children}) => {
25
+
26
+ const
27
+
28
+ {
29
+ nofold,
30
+ cardid,
31
+ size,
32
+ title,
33
+ action,
34
+ collapsedAction,
35
+ collapsedClass,
36
+ expandedClass,
37
+ cols,
38
+ element,
39
+ busy,
40
+ expandedView,
41
+ collapsedView,
42
+ titleWidget: titWidget,
43
+ titleAttrs,
44
+ titleClass,
45
+ bodyClass,
46
+ titleExpanded,
47
+ titleCollapsed
48
+ } = attrs,
49
+
50
+ collapsed = nofold
51
+ ? false
52
+ : cardid
53
+ ? !globalState[cardid]
54
+ : !!state.collapsed,
55
+
56
+ items = (!collapsed)
57
+ ? (
58
+ expandedView
59
+ ? expandedView(attrs, state)
60
+ : (children || [])
61
+ )
62
+ : collapsedView ? collapsedView(attrs, state) : [],
63
+
64
+ titleWidget = titWidget
65
+ ? m(titWidget, titleAttrs || {})
66
+ : title ? m("span.ellipsis.ohidden.unfold", title) : undefined,
67
+
68
+ buttonClass = busy
69
+ ? "fa-sync"
70
+ : `fa-caret-down ${collapsed ? "iscollapsed" : "isexpanded"}`;
71
+
72
+ return items.length || !attrs.skipEmpty
73
+ ? m(
74
+ (element || "ul"),
75
+ {
76
+ class: "cardie ohidden noshrink "
77
+ + (cols ? "flexcol " : "flexrow wrap ")
78
+ + (attrs.class ? " " + attrs.class : "")
79
+ + (nofold
80
+ ? " expanded"
81
+ : ` ${collapsed ? "collapsed " + (collapsedClass || "") : "expanded " + (expandedClass || "")}`)
82
+ + (size ? " marg-" + size : " marg-2")
83
+ + (titWidget ? " withwidget" : "")
84
+ + (busy ? " busycard" : "")
85
+ },
86
+ [
87
+
88
+ ...titleWidget
89
+ ? [
90
+ m(
91
+ ".title.grows.fabf.flexrow.pointer.unfold",
92
+ nofold
93
+ ? {
94
+ class: titleClass || "pad-2"
95
+ }
96
+ : {
97
+ class: `${titleClass || "pad-2"} ${buttonClass || ""}`,
98
+
99
+ title: collapsed
100
+ ? (titleCollapsed || "Click to expand the options")
101
+ : (titleExpanded || titleCollapsed || "Click to collapse the options"),
102
+
103
+ onclick: (e) => {
104
+
105
+ if (e.target.classList.contains("unfold")) {
106
+ if (e.shiftKey && attrs.onShiftOpen) {
107
+ attrs.onShiftOpen();
108
+ } else if (attrs.cardid) {
109
+ setCardStatus(cardid, collapsed); // !state
110
+ } else {
111
+ state.collapsed = !state.collapsed;
112
+ }
113
+
114
+ m.redraw();
115
+ }
116
+ }
117
+ },
118
+ action && (nofold || !collapsed)
119
+ ? [
120
+ m(ButtonNew, action),
121
+ titleWidget
122
+ ]
123
+ : collapsedAction && collapsed
124
+ ? [
125
+ m(ButtonNew, collapsedAction),
126
+ titleWidget
127
+ ]
128
+ : titleWidget
129
+ )
130
+ ]
131
+ : [],
132
+
133
+ ...items.length
134
+ ? [
135
+ m(".flexbreak"),
136
+ m(
137
+ ".cardiebody.fadein-filter.grows",
138
+ {
139
+ class: (cols ? "flexcol " : "flexrow wrap") + " " + (bodyClass || "")
140
+ },
141
+ ...items
142
+ )
143
+ ] : [],
144
+
145
+ ...(attrs.alwaysView
146
+ ? [attrs.alwaysView({attrs, state})]
147
+ : [])
148
+
149
+ ]
150
+ ) : [];
151
+ },
152
+ ({attrs, state}) => {
153
+ if (!attrs.cardid) {
154
+ state.collapsed = attrs.nofold
155
+ ? false
156
+ : attrs.cardid
157
+ ? !globalState[attrs.cardid]
158
+ : !!attrs.collapsed;
159
+ }
160
+ },
161
+ undefined,
162
+ undefined,
163
+ undefined,
164
+ {setCardStatus}
165
+ );
166
+
167
+ export default CardieWidget;
@@ -0,0 +1,112 @@
1
+ import m from "mithril";
2
+ import defineWidget from "../util/widgets.utils";
3
+ import {confirm} from "../util/fuckingconfirm";
4
+ import {ButtonNew} from "./Basic"
5
+ import {promptOptions} from "./OverflowUtils";
6
+
7
+ function storyOverflow(attrs) {
8
+
9
+ const
10
+ {
11
+ title,
12
+ items: maybeFunctionItems,
13
+ itemsKey,
14
+ itemsText,
15
+ field,
16
+ onchange,
17
+ textNew,
18
+ textHint,
19
+ resolve,
20
+ icon
21
+ } = attrs,
22
+ source = typeof maybeFunctionItems === "function" ? maybeFunctionItems() : maybeFunctionItems,
23
+ items = itemsKey ? typeof itemsKey === "function" ? itemsKey() : source[itemsKey] : source;
24
+
25
+ return promptOptions(items, onchange, {title, field, icon, textNew, textHint, resolve});
26
+ }
27
+
28
+ const
29
+ ComboPrompt = defineWidget(
30
+ ({attrs}) => m(
31
+ ".flexcol.combocontainer.grows", {
32
+ class: (attrs.outerClass || "") + " " + (attrs.label ? "witharia" : ""),
33
+ ...attrs.label && {"aria-label": attrs.label},
34
+ title: attrs.hint
35
+ }, [
36
+
37
+ m(
38
+ ".flexrow.combowidget.bg-inputs",
39
+ {
40
+ class: (attrs.value ? "yesvalue " : "novalue ") + (attrs.class || "")
41
+ },
42
+ [
43
+ m(ButtonNew, {
44
+ class: "transp combovalue grows flexrow " + (attrs.buttonClass || "") + (attrs.innerLabel ? " witharia" : ""),
45
+ textClass: "grows " + attrs.textClass,
46
+ iconClass: "noshrink",
47
+ ...attrs.innerLabel && {"aria-label": attrs.innerLabel},
48
+ onClick: (e) => {
49
+ if (e.shiftKey) {
50
+ attrs.onchange(undefined, e);
51
+ } else if (!attrs.locked) {
52
+ storyOverflow(attrs);
53
+ }
54
+ },
55
+ ...attrs.value
56
+ ? {
57
+ icon: attrs.value?.icon || attrs.icon,
58
+ text: attrs.field || attrs.fieldTitle
59
+ ? attrs.value[attrs.fieldTitle || attrs.field]
60
+ : attrs.itemsText
61
+ ? attrs.itemsText[attrs.value] || attrs.value
62
+ : attrs.value
63
+ }
64
+ : {
65
+ icon: attrs.emptyIcon || (attrs.emptyText ? "" : "plus"),
66
+ text: attrs.emptyText || ""
67
+ }
68
+ }),
69
+ attrs.value && !attrs.nodelete
70
+ ? [
71
+ m(
72
+ ButtonNew,
73
+ {
74
+ class: "clrcombo pad-2 pad-h transp " + (attrs.closeClass || "scaff-left"),
75
+ onClick: (e) => {
76
+
77
+ const {field} = attrs;
78
+ if (attrs.confirm && !e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey) {
79
+ const msg = attrs.confirm();
80
+ if (msg) {
81
+ confirm(msg, () => {
82
+ attrs.onchange(field ? undefined : "", e);
83
+ });
84
+ } else {
85
+ attrs.onchange(field ? undefined : "", e);
86
+ }
87
+ } else {
88
+ attrs.onchange(field ? undefined : "", e);
89
+ }
90
+ m.redraw();
91
+ /*
92
+ if (attrs.confirm && !e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey) {
93
+ confirm(attrs.confirm, () => {
94
+ attrs.onchange(attrs.field ? undefined : "", e);
95
+ });
96
+ } else {
97
+ attrs.onchange(attrs.field ? undefined : "", e);
98
+ }
99
+ m.redraw();
100
+ */
101
+ },
102
+ icon: attrs.removeIcon || "times",
103
+ title: attrs.removeHint || "remove this item"
104
+ }
105
+ )
106
+ ]
107
+ : []
108
+ ]
109
+ )])
110
+ );
111
+
112
+ export default ComboPrompt;