@nebularstreams/libmui 3.0.8 → 3.1.0
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 +2 -2
- package/readme.md +554 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebularstreams/libmui",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "3.0
|
|
3
|
+
"description": "Lightweight, high-performance Mithril widget library for modern websites and JavaScript applications.",
|
|
4
|
+
"version": "3.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"scripts": {
|
package/readme.md
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# LibMui
|
|
2
|
+
|
|
3
|
+
LibMui is a lightweight, high-performance widget library for modern websites and JavaScript applications. It is built on [Mithril](https://mithril.js.org/) and provides responsive controls, selectors, dialogs, color tools, file pickers, parameter editors, and reusable layout components.
|
|
4
|
+
|
|
5
|
+
The package ships its widget styles and Font Awesome icon definitions with the JavaScript entry point, so importing LibMui also loads its visual system.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @nebularstreams/libmui mithril
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import m from "mithril";
|
|
15
|
+
import {
|
|
16
|
+
ButtonNew,
|
|
17
|
+
InputWidget,
|
|
18
|
+
RangeWidget,
|
|
19
|
+
SwitchWidget
|
|
20
|
+
} from "@nebularstreams/libmui";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
LibMui widgets are Mithril components. Render them with `m(Component, attrs, children)` and keep application values in your own state.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import m from "mithril";
|
|
29
|
+
import {
|
|
30
|
+
ButtonNew,
|
|
31
|
+
InputWidget,
|
|
32
|
+
RangeWidget,
|
|
33
|
+
SwitchWidget
|
|
34
|
+
} from "@nebularstreams/libmui";
|
|
35
|
+
|
|
36
|
+
const state = {
|
|
37
|
+
name: "Nebular",
|
|
38
|
+
volume: 0.5,
|
|
39
|
+
enabled: true
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const Demo = {
|
|
43
|
+
view: () => m("main.pad-3", [
|
|
44
|
+
m(InputWidget, {
|
|
45
|
+
label: "Display name",
|
|
46
|
+
value: state.name,
|
|
47
|
+
hint: "Enter a name",
|
|
48
|
+
onchange: value => state.name = value
|
|
49
|
+
}),
|
|
50
|
+
|
|
51
|
+
m(RangeWidget, {
|
|
52
|
+
title: "Volume",
|
|
53
|
+
value: state.volume,
|
|
54
|
+
min: 0,
|
|
55
|
+
max: 1,
|
|
56
|
+
step: 0.01,
|
|
57
|
+
onchange: value => state.volume = value
|
|
58
|
+
}),
|
|
59
|
+
|
|
60
|
+
m(SwitchWidget, {
|
|
61
|
+
text: "Enabled",
|
|
62
|
+
checked: state.enabled,
|
|
63
|
+
onchange: checked => state.enabled = checked
|
|
64
|
+
}),
|
|
65
|
+
|
|
66
|
+
m(ButtonNew, {
|
|
67
|
+
icon: "check",
|
|
68
|
+
text: "Save",
|
|
69
|
+
onClick: () => saveSettings(state)
|
|
70
|
+
})
|
|
71
|
+
])
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
m.mount(document.body, Demo);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> `Button` uses an `onclick` callback, while the newer `ButtonNew` uses `onClick`.
|
|
78
|
+
|
|
79
|
+
## Buttons and icons
|
|
80
|
+
|
|
81
|
+
### `Icon`
|
|
82
|
+
|
|
83
|
+
Renders a Font Awesome icon.
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
m(Icon, {
|
|
87
|
+
icon: "gear",
|
|
88
|
+
size: 2,
|
|
89
|
+
icontitle: "Settings",
|
|
90
|
+
onclick: openSettings
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
| Attribute | Description |
|
|
95
|
+
|-------------|---------------------------------------------------------------------|
|
|
96
|
+
| `icon` | Font Awesome icon name without the `fa-` prefix. Defaults to `cog`. |
|
|
97
|
+
| `pack` | Icon pack class. Defaults to `fas`. |
|
|
98
|
+
| `size` | Font Awesome size multiplier. |
|
|
99
|
+
| `icontitle` | Native tooltip text. |
|
|
100
|
+
| `iconClass` | Additional classes for the icon element. |
|
|
101
|
+
| `onclick` | Optional icon click handler. |
|
|
102
|
+
|
|
103
|
+
### `ButtonNew`
|
|
104
|
+
|
|
105
|
+
Renders a button, link, or download action. Promise-returning handlers automatically apply a busy state and expose rejected errors through `data-error`.
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
m(ButtonNew, {
|
|
109
|
+
icon: "cloud-upload-alt",
|
|
110
|
+
text: "Publish",
|
|
111
|
+
title: "Publish changes",
|
|
112
|
+
class: "accentbutton",
|
|
113
|
+
onClick: () => publishProject()
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Important attributes are `icon`, `text`, `title`, `class`, `textClass`, `right`, `onClick`, `link`, `target`, and `download`. When `link` or `download` is present, the widget renders an anchor instead of a button.
|
|
118
|
+
|
|
119
|
+
`Button` offers the same basic presentation but uses `onclick`.
|
|
120
|
+
|
|
121
|
+
### `ButtonChoiceWidget`
|
|
122
|
+
|
|
123
|
+
Displays a set of choices as a row of buttons.
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
m(ButtonChoiceWidget, {
|
|
127
|
+
label: "Quality",
|
|
128
|
+
value: state.quality,
|
|
129
|
+
choices: {
|
|
130
|
+
low: {value: "low", caption: "Low"},
|
|
131
|
+
high: {value: "high", caption: "High", icon: "star"}
|
|
132
|
+
},
|
|
133
|
+
onchange: choice => state.quality = choice.value
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use `choose: ["one", "two"]` for a simple list. Use `choices` for captions, icons, classes, and distinct values. Set `toggle` to allow the active choice to be cleared, `field` to compare a property of each choice, or `render(choice)` for custom button content.
|
|
138
|
+
|
|
139
|
+
## Text and numeric input
|
|
140
|
+
|
|
141
|
+
### `InputWidget`
|
|
142
|
+
|
|
143
|
+
Provides single-line, multiline, numeric, validated, read-only, and editable-static inputs.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
m(InputWidget, {
|
|
147
|
+
label: "Retries",
|
|
148
|
+
type: "number",
|
|
149
|
+
value: state.retries,
|
|
150
|
+
min: 0,
|
|
151
|
+
max: 10,
|
|
152
|
+
step: 1,
|
|
153
|
+
onchange: value => state.retries = value
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
| Attribute | Description |
|
|
158
|
+
|-------------------------------------|-------------------------------------------------------------------------------|
|
|
159
|
+
| `value` | Current controlled value. |
|
|
160
|
+
| `onchange(value, event, multiline)` | Called when the value is committed. |
|
|
161
|
+
| `oninput(value, event)` | Optional live-input callback. |
|
|
162
|
+
| `type` | Native input type. Use `number` for parsed numeric values. |
|
|
163
|
+
| `float` | Parses numeric input with `parseFloat` instead of `parseInt`. |
|
|
164
|
+
| `hint` | Placeholder text. |
|
|
165
|
+
| `label` | Accessible label applied to the container. |
|
|
166
|
+
| `multi` | Adds a control for switching between input and textarea. |
|
|
167
|
+
| `alwaysmulti` | Always renders a textarea. |
|
|
168
|
+
| `validator(value)` | Returns whether the current value is valid. |
|
|
169
|
+
| `readonly` | Prevents editing. |
|
|
170
|
+
| `maxlength`, `min`, `max`, `step` | Native input constraints. |
|
|
171
|
+
| `action`, `actions` | One or more `ButtonNew` configurations shown beside the input. |
|
|
172
|
+
| `onenter(value, event)` | Called when Enter is pressed. |
|
|
173
|
+
| `staticField` | Displays a static value until the user activates it. |
|
|
174
|
+
| `draginc` | Enables vertical drag adjustment by this increment on a static numeric field. |
|
|
175
|
+
|
|
176
|
+
### `RangeWidget`
|
|
177
|
+
|
|
178
|
+
Renders an accessible slider with a live value display.
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
m(RangeWidget, {
|
|
182
|
+
title: "Opacity",
|
|
183
|
+
value: state.opacity,
|
|
184
|
+
min: 0,
|
|
185
|
+
max: 1,
|
|
186
|
+
step: 0.01,
|
|
187
|
+
parser: value => `${Math.round(value * 100)}%`,
|
|
188
|
+
onchange: (value, dragging) => state.opacity = value
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Use `multiplier` to let the range expand beyond its initial limits, `relative` for relative movement, and `factor` to scale interaction. The second `onchange` argument indicates whether the slider is being dragged.
|
|
193
|
+
|
|
194
|
+
### `PlusMinus`
|
|
195
|
+
|
|
196
|
+
Provides decrement and increment buttons around a displayed value.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
m(PlusMinus, {
|
|
200
|
+
title: "Copies",
|
|
201
|
+
value: state.copies,
|
|
202
|
+
min: 1,
|
|
203
|
+
max: 20,
|
|
204
|
+
step: 1,
|
|
205
|
+
onchange: value => state.copies = value
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Customize the display with `parser(value)` and the buttons with `iconMinus`, `iconPlus`, and `buttonClass`.
|
|
210
|
+
|
|
211
|
+
### `SwitchWidget`
|
|
212
|
+
|
|
213
|
+
Displays a controlled toggle.
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
m(SwitchWidget, {
|
|
217
|
+
text: "Show guides",
|
|
218
|
+
subline: "Display alignment helpers",
|
|
219
|
+
checked: state.guides,
|
|
220
|
+
right: true,
|
|
221
|
+
onchange: checked => state.guides = checked
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Selection widgets
|
|
226
|
+
|
|
227
|
+
### `ComboWidget`
|
|
228
|
+
|
|
229
|
+
Renders a native select from `{name, value}` items.
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
m(ComboWidget, {
|
|
233
|
+
caption: "Renderer",
|
|
234
|
+
value: state.renderer,
|
|
235
|
+
items: [
|
|
236
|
+
{name: "WebGL", value: "webgl"},
|
|
237
|
+
{name: "WebGPU", value: "webgpu"}
|
|
238
|
+
],
|
|
239
|
+
onchange: (value, item, index) => state.renderer = value
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Pass `groups` instead of `items` to create named option groups. `parser(value)` can normalize values before matching the controlled selection.
|
|
244
|
+
|
|
245
|
+
### `ComboPrompt`
|
|
246
|
+
|
|
247
|
+
Shows the current choice as a compact button and opens a modal choice menu.
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
m(ComboPrompt, {
|
|
251
|
+
label: "Theme",
|
|
252
|
+
value: state.theme,
|
|
253
|
+
items: themes,
|
|
254
|
+
field: "name",
|
|
255
|
+
emptyText: "Choose a theme",
|
|
256
|
+
onchange: value => state.theme = value
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Useful attributes include `items`, `field`, `itemsText`, `icon`, `emptyIcon`, `emptyText`, `locked`, `nodelete`, `confirm`, `textNew`, and `textHint`. Shift-clicking the main button clears the value.
|
|
261
|
+
|
|
262
|
+
### `SmileysButton`
|
|
263
|
+
|
|
264
|
+
Opens LibMui's application-level icon and emoji selector. The selected entry is returned through `onchange`.
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
m(SmileysButton, {
|
|
268
|
+
icon: state.markerIcon,
|
|
269
|
+
icons: availableIcons,
|
|
270
|
+
onchange: icon => state.markerIcon = icon
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The current `icon` may contain an `icon` field for a Font Awesome symbol, a `glyph` field for an emoji, or both. This widget uses `MainState` to open the `emoji` application panel, so that panel must be registered by the host application.
|
|
275
|
+
|
|
276
|
+
### `Selector`
|
|
277
|
+
|
|
278
|
+
Builds a toolbar that switches between complete Mithril components.
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
const panels = [
|
|
282
|
+
{text: "General", icon: "sliders-h", widget: GeneralPanel},
|
|
283
|
+
{text: "Advanced", icon: "cogs", widget: AdvancedPanel}
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
m(Selector, {
|
|
287
|
+
title: "Settings",
|
|
288
|
+
items: panels,
|
|
289
|
+
selected: 0,
|
|
290
|
+
toggle: true,
|
|
291
|
+
closeButton: true,
|
|
292
|
+
onSelected: (item, params, changed) => {
|
|
293
|
+
if (changed) console.log("Selected", item);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Each item accepts `text`, `icon`, `title`, `class`, `widget`, `attrs`, and `children`. Widget `attrs` may be an object or a function receiving the selector's own attributes. Pass a shared `state` object when another component needs to call `state.setItem(index, ...params)`.
|
|
299
|
+
|
|
300
|
+
## Layout and status
|
|
301
|
+
|
|
302
|
+
### `CardieWidget`
|
|
303
|
+
|
|
304
|
+
Creates a collapsible card whose body can be supplied as children or through `expandedView(attrs, state)`.
|
|
305
|
+
|
|
306
|
+
```js
|
|
307
|
+
m(CardieWidget, {
|
|
308
|
+
cardid: "settings-audio",
|
|
309
|
+
title: "Audio settings",
|
|
310
|
+
collapsed: true,
|
|
311
|
+
expandedView: () => m(AudioSettings)
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Cards sharing the prefix before the first `-` in `cardid` behave like an accordion. Use `nofold` for a permanently expanded card, `action` and `collapsedAction` for title actions, and `alwaysView` for content that remains outside the folding body.
|
|
316
|
+
|
|
317
|
+
### `TitleBarWidget`
|
|
318
|
+
|
|
319
|
+
Creates an application or panel title bar with optional back navigation, logo, editable title, actions, and overflow menu.
|
|
320
|
+
|
|
321
|
+
```js
|
|
322
|
+
m(TitleBarWidget, {
|
|
323
|
+
title: "Project settings",
|
|
324
|
+
onClick: goBack,
|
|
325
|
+
action: {icon: "save", title: "Save", onClick: save},
|
|
326
|
+
overflow: {
|
|
327
|
+
items: [
|
|
328
|
+
{caption: "Duplicate", icon: "copy", onClick: duplicate},
|
|
329
|
+
{caption: "Delete", icon: "trash", onClick: remove}
|
|
330
|
+
]
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### `Separator`
|
|
336
|
+
|
|
337
|
+
Renders a labelled section divider and optional child actions.
|
|
338
|
+
|
|
339
|
+
```js
|
|
340
|
+
m(Separator, {text: "Appearance"});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### `NoticeWidget`
|
|
344
|
+
|
|
345
|
+
Renders inline informational content with an optional icon, click handler, and child content.
|
|
346
|
+
|
|
347
|
+
```js
|
|
348
|
+
m(NoticeWidget, {
|
|
349
|
+
icon: "info-circle",
|
|
350
|
+
text: "Changes are saved automatically."
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Empty states
|
|
355
|
+
|
|
356
|
+
`Empty` renders a centered icon, message, and optional children. `EmptyButton` adds a primary action, while `CoolerEmpty` supports a header and one or more action definitions.
|
|
357
|
+
|
|
358
|
+
```js
|
|
359
|
+
m(CoolerEmpty, {
|
|
360
|
+
icon: "folder-open",
|
|
361
|
+
header: "No projects",
|
|
362
|
+
message: "Create your first project to begin.",
|
|
363
|
+
action: {caption: "Create project", onclick: createProject}
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Color widgets
|
|
368
|
+
|
|
369
|
+
### `ColorJoeWidget`
|
|
370
|
+
|
|
371
|
+
Displays a color swatch that opens an RGB or HSL picker in a modal.
|
|
372
|
+
|
|
373
|
+
```js
|
|
374
|
+
m(ColorJoeWidget, {
|
|
375
|
+
caption: "Background",
|
|
376
|
+
color: state.color,
|
|
377
|
+
onchange: (cssColor, colorObject) => state.color = cssColor
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Set `hsl` for an HSL picker, `noalpha` to remove alpha controls, and `onshiftclick` to provide an alternate swatch action. Passing `null` from the picker indicates removal.
|
|
382
|
+
|
|
383
|
+
### `ColorJoePack`
|
|
384
|
+
|
|
385
|
+
Edits an array of RGB(A) or HSL(A) colors and supports up to eight entries by default.
|
|
386
|
+
|
|
387
|
+
```js
|
|
388
|
+
m(ColorJoePack, {
|
|
389
|
+
colors: state.palette,
|
|
390
|
+
max: 8,
|
|
391
|
+
onchange: colors => state.palette = colors
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Click a swatch to edit it, Shift-click one to remove it, click **+** to add a color, or Shift-click **+** to clear the collection.
|
|
396
|
+
|
|
397
|
+
## File and image widgets
|
|
398
|
+
|
|
399
|
+
### `FileSelectButton`
|
|
400
|
+
|
|
401
|
+
```js
|
|
402
|
+
m(FileSelectButton, {
|
|
403
|
+
text: "Choose JSON",
|
|
404
|
+
icon: "upload",
|
|
405
|
+
accept: "application/json",
|
|
406
|
+
onFile: file => importFile(file)
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Image helpers
|
|
411
|
+
|
|
412
|
+
- `ImageSelectButton` returns selected files through `onImageFiles(files)`.
|
|
413
|
+
- `ImageProcessButton` loads the selected image and passes an `HTMLImageElement` to `onImage(image)`.
|
|
414
|
+
- `ImageDataButton` reads the image as a data URL and calls `onImageUrl({name, url})`.
|
|
415
|
+
- `MediaSelectButton` opens LibMui's configured media-selection application state.
|
|
416
|
+
- `processImage(file)` provides the image-loading behavior as a standalone promise.
|
|
417
|
+
|
|
418
|
+
All image buttons accept the presentation attributes `class`, `icon`, `iconClass`, `text`, `textClass`, and `accept`. Processing buttons also support `onError(error)`.
|
|
419
|
+
|
|
420
|
+
## Notifications and dialogs
|
|
421
|
+
|
|
422
|
+
Add these containers once near the root of the document when using notifications, prompts, color pickers, or modal utilities:
|
|
423
|
+
|
|
424
|
+
```html
|
|
425
|
+
|
|
426
|
+
<div id="notification-container"></div>
|
|
427
|
+
<div id="modal-container" style="display: none"></div>
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Notifications
|
|
431
|
+
|
|
432
|
+
```js
|
|
433
|
+
Notification.add("Saved", "success");
|
|
434
|
+
Notification.add("Could not connect", "error");
|
|
435
|
+
Notification.clear();
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Notifications are queued and dismissed automatically. Supported semantic types include `info`, `success`, and `error`; clicking the current notification advances the queue.
|
|
439
|
+
|
|
440
|
+
### Confirmations
|
|
441
|
+
|
|
442
|
+
```js
|
|
443
|
+
const result = await ConfirmPromise(
|
|
444
|
+
"Delete project?",
|
|
445
|
+
"This action cannot be undone.",
|
|
446
|
+
["CANCEL", "DELETE"],
|
|
447
|
+
true
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
if (result.name === "DELETE") deleteProject();
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
`ConfirmPromise` resolves to `{idx, name}`. The lowercase `confirmPromise` export provides the library's alternative confirmation helper. `popupMessage(content, cancelable, contentClass)` can render custom Mithril content in the modal container, while `clearModal()` closes the active modal.
|
|
454
|
+
|
|
455
|
+
### `OverflowMenu`
|
|
456
|
+
|
|
457
|
+
```js
|
|
458
|
+
const {action} = await OverflowMenu(
|
|
459
|
+
document.body,
|
|
460
|
+
{title: "Project actions"},
|
|
461
|
+
[
|
|
462
|
+
{caption: "Duplicate", icon: "copy"},
|
|
463
|
+
{caption: "Archive", icon: "archive"}
|
|
464
|
+
]
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
console.log(action.caption);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Tickers and collections
|
|
471
|
+
|
|
472
|
+
`GenericButtonTicker` renders a compact collection of selectable buttons with add, edit, update, rename, and delete behavior. `CoolGenericTicker` switches large collections to previous/next navigation. `ThematicWrapper` provides their themed frame.
|
|
473
|
+
|
|
474
|
+
```js
|
|
475
|
+
m(GenericButtonTicker, {
|
|
476
|
+
items: state.presets,
|
|
477
|
+
current: state.currentPreset,
|
|
478
|
+
emptyText: "No presets",
|
|
479
|
+
addText: "Add preset",
|
|
480
|
+
onSelect: (item, index) => state.currentPreset = index,
|
|
481
|
+
onAdd: () => addPreset(),
|
|
482
|
+
onDelete: index => deletePreset(index)
|
|
483
|
+
});
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
`CoolContentTicker` is the application-integrated variant. It expects a `layer` containing `items` and a `global.storyWrapper` implementing LibMui's ticker state methods.
|
|
487
|
+
|
|
488
|
+
## Metadata-driven forms
|
|
489
|
+
|
|
490
|
+
`ParameterTable` and `TemplatedInputWidget` generate complete control panels from metadata and a mutable parameter object. They are intended for applications with many dynamic properties, presets, or schema-defined editors.
|
|
491
|
+
|
|
492
|
+
```js
|
|
493
|
+
const parameters = {
|
|
494
|
+
title: "Scene one",
|
|
495
|
+
visible: true,
|
|
496
|
+
opacity: 0.8
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
const meta = {
|
|
500
|
+
title: {type: "text", title: "Title"},
|
|
501
|
+
visible: {type: "boolean", title: "Visible"},
|
|
502
|
+
opacity: {type: "number", title: "Opacity", min: 0, max: 1, step: 0.01}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
m(ParameterTable, {
|
|
506
|
+
meta,
|
|
507
|
+
parameters,
|
|
508
|
+
onchange: (changeCode, target, key) => {
|
|
509
|
+
console.log("Changed", key, target[key]);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
Related widgets include:
|
|
515
|
+
|
|
516
|
+
- `ParameterCardie` — groups generated parameter controls in a collapsible card.
|
|
517
|
+
- `MultiToggleWidget` — edits a keyed set of toggle values.
|
|
518
|
+
- `RangeToggleWidget` — edits a keyed set of numeric range values.
|
|
519
|
+
- `TemplatedInputWidget` — combines a value editor with presets and optional property controls.
|
|
520
|
+
|
|
521
|
+
Metadata forms support standard strings, numbers, booleans, ranges, choices, colors, JSON, nested groups, separators, custom widgets, and injected asset or code editors. For application-specific editors, pass `AssetButton` or `CodeMirror` through the table attributes.
|
|
522
|
+
|
|
523
|
+
## Application routing
|
|
524
|
+
|
|
525
|
+
`startApp(target, appMetadata)` starts a Mithril router on an element ID:
|
|
526
|
+
|
|
527
|
+
```js
|
|
528
|
+
startApp("app", {
|
|
529
|
+
default: "/home",
|
|
530
|
+
routes: {
|
|
531
|
+
"/home": HomePage,
|
|
532
|
+
"/settings": SettingsPage
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
## Public exports
|
|
538
|
+
|
|
539
|
+
The package exports the following public widgets:
|
|
540
|
+
|
|
541
|
+
- Foundations: `Button`, `ButtonNew`, `Icon`, `Empty`, `Selector`, `Notification`
|
|
542
|
+
- Inputs: `InputWidget`, `RangeWidget`, `PlusMinus`, `SwitchWidget`
|
|
543
|
+
- Choices: `ButtonChoiceWidget`, `ComboWidget`, `ComboPrompt`, `SmileysButton`
|
|
544
|
+
- Layout: `CardieWidget`, `Separator`, `TitleBarWidget`, `NoticeWidget`, `EmptyButton`, `CoolerEmpty`
|
|
545
|
+
- Colors: `ColorJoeWidget`, `ColorJoePack`
|
|
546
|
+
- Files: `FileSelectButton`, `ImageSelectButton`, `ImageProcessButton`, `ImageDataButton`, `MediaSelectButton`
|
|
547
|
+
- Collections: `GenericButtonTicker`, `CoolGenericTicker`, `CoolContentTicker`, `ThematicWrapper`
|
|
548
|
+
- Dynamic forms: `TemplatedInputWidget`, `ParameterTable`, `ParameterCardie`, `MultiToggleWidget`, `RangeToggleWidget`
|
|
549
|
+
|
|
550
|
+
LibMui also exports modal, cloning, tokenization, file-path, routing, application-state, and widget-definition utilities. These support the widgets but are outside this widget-focused guide.
|
|
551
|
+
|
|
552
|
+
## Browser support
|
|
553
|
+
|
|
554
|
+
LibMui is an ES module intended for modern browsers. Widgets that read local files require the FileReader API, while image processing also uses the browser `Image` API. The core rendering dependency is Mithril 2.x.
|