@lumiastream/lumia-types 3.9.3 → 3.9.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.
- package/dist/custom-code/custom-actions.md +78 -14
- package/dist/custom-overlays/custom-overlays-cheatsheet.md +21 -6
- package/dist/custom-overlays/custom-overlays-documentation.md +35 -3
- package/dist/custom-overlays/custom-overlays.d.ts +21 -3
- package/dist/custom-overlays/gpt-instructions.md +1 -1
- package/dist/custom-overlays.d.ts +21 -3
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ Let's get started:
|
|
|
25
25
|
**System bases** (built into Lumia):
|
|
26
26
|
`delay, lumia, overlay, api, commandRunner, inputEvents`
|
|
27
27
|
|
|
28
|
-
> Note: `lumia` and `overlay
|
|
28
|
+
> Note: the canonical system bases are `lumia` and `overlay`. The older spellings `lumiaActions` and `overlayActions` still run but are **deprecated** — prefer `lumia` / `overlay`. The input base is `inputEvents` (plural).
|
|
29
29
|
|
|
30
30
|
**Integration bases** — every connected integration is also a valid base. These include (and more are added over time):
|
|
31
31
|
`twitch, youtube, facebook, tiktok, kick, discord, obs, slobs, meld, spotify, youtubemusic, nowplaying, vlc, voicemod, streamerbot, vtubestudio, midi, osc, artnet, mqtt, serial, websocket, broadlink, hue, lifx, nanoleaf, govee, wled, wiz, tplink, tuya, yeelight, elgato, streamdeck, touchportal, loupedeck, homeassistant, switchbot` plus any installed plugin (use the plugin's id as the base).
|
|
@@ -36,7 +36,27 @@ Let's get started:
|
|
|
36
36
|
|
|
37
37
|
`variables`: allows you to send in different variables for each action. But do note that the variables that are already on the command/alert will also be spread on to this variables object. Variables are not required
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
To pause between actions, insert a dedicated **delay step**: an entry whose `type` is `"delay"` with the milliseconds in `delay` (e.g. `{ type: "delay", delay: 1000 }`). It can carry any `base` and runs in order with the rest of the list. (An inline `delay` on a non-delay action is **not** applied by the runner — use a delay step.)
|
|
40
|
+
|
|
41
|
+
#### Where actions live: the unified `actions` lane
|
|
42
|
+
|
|
43
|
+
Inside a Lumia **command** or **alert**, every action — whatever its `base` (a `lumia` system action, an `overlay` action, a `twitch` action, an integration, a plugin) — lives together in one ordered list on the command:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"actions": {
|
|
48
|
+
"before": [{ "base": "lumia", "type": "tts", "value": { "message": "Hi" } }],
|
|
49
|
+
"after": [{ "base": "twitch", "type": "clip", "value": { "title": "Clutch!", "duration": 30 } }],
|
|
50
|
+
"waitForActions": true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- **`before`** runs before the command/alert's main effect (its light / overlay reaction); **`after`** runs after it.
|
|
56
|
+
- **`waitForActions`** (optional): when `true`, each action is awaited so the list runs in strict order before the command continues; when omitted or `false`, the list fires without waiting.
|
|
57
|
+
- Every entry is one action object of the shape `{ base, type, value?, delay?, args? }` — the same object you pass to the custom-code `actions()` helper. `delay` holds the milliseconds for a `type: "delay"` step; `args` carries the extra payload used by imported Streamer.bot actions.
|
|
58
|
+
|
|
59
|
+
This unified `actions` lane is the current model, and the one the AI action creator and the Streamer.bot / Mix It Up importers target. It **replaces** the older per-source command fields (`lumiaActions`, `overlayActions`, `api`, `commandRunner`, `inputEvents`) and the per-integration lanes (`command.<integration>.before/after` — e.g. `command.wavelink`, `command.streamfog`, whose entries have no `base`), all of which are **deprecated** — within the unified lane the source is simply each entry's `base`.
|
|
40
60
|
|
|
41
61
|
### Passing an array of actions
|
|
42
62
|
|
|
@@ -63,9 +83,11 @@ These are the built-in `type` values for each system base.
|
|
|
63
83
|
|
|
64
84
|
**`base: "commandRunner"`** — `app/file, shell command, delay`
|
|
65
85
|
|
|
66
|
-
**`base: "inputEvents"`** — `keyboard, mouse, delay`
|
|
86
|
+
**`base: "inputEvents"`** — `keyboard, mouse, delay`. The key/mouse data is **flat on the action**, not under `value`:
|
|
87
|
+
> - `keyboard`: `{ base: "inputEvents", type: "keyboard", keyboardValue: { value: "ctrl+j", valueType: "combination" } }` — `valueType` is `combination` (a hotkey like `ctrl+shift+f5`) or `input` (type the literal `value` as text); optional `longPress`, `cpm`.
|
|
88
|
+
> - `mouse`: `{ base: "inputEvents", type: "mouse", mouseValue: { x: 0, y: 100, clickEvent: "left", moveType: "set" } }` — `clickEvent` is `left` / `right` / `none`; optional `x1`, `y1`, `doubleClick`, `mouseSpeed`.
|
|
67
89
|
|
|
68
|
-
|
|
90
|
+
**delay step** — an entry with `type: "delay"` pauses the list; put the milliseconds in `delay` (e.g. `{ type: "delay", delay: 1000 }`). `duration` is accepted in place of `delay`, and the step runs under any `base`.
|
|
69
91
|
|
|
70
92
|
> Tip: most of the `lumia` and `overlay` actions already have dedicated helper functions (`tts`, `chatbot`, `overlaySetTextContent`, etc.) in `helper-functions.md`. Reach for `actions()` mainly when you need an integration action that does not have a helper yet.
|
|
71
93
|
|
|
@@ -460,6 +482,8 @@ async function() {
|
|
|
460
482
|
}
|
|
461
483
|
```
|
|
462
484
|
|
|
485
|
+
> MIDI device targeting: `port` (the device's port number) is the simplest selector and is required. On a multi-device setup — where ports can shift between sessions — also pass the optional `deviceId` and/or `deviceName`; Lumia resolves the target by `deviceId`, then `deviceName`, then `port`. `type` is `note-on`, `note-off`, or `delay` (a `delay` entry just waits its `delay` ms).
|
|
486
|
+
|
|
463
487
|
#### Twitch (`base: "twitch"`)
|
|
464
488
|
|
|
465
489
|
Twitch actions take a `value` object. Most string inputs — usernames, message ids, comma-separated option lists — go in `value.message`. Each action needs the matching Twitch permission to be granted on your connection.
|
|
@@ -569,7 +593,23 @@ async function() {
|
|
|
569
593
|
}
|
|
570
594
|
```
|
|
571
595
|
|
|
572
|
-
|
|
596
|
+
Common direct request-types (flat fields, verified against real setups):
|
|
597
|
+
|
|
598
|
+
| `request-type` | fields |
|
|
599
|
+
| --- | --- |
|
|
600
|
+
| `SetCurrentProgramScene` | `{ sceneName }` |
|
|
601
|
+
| `SetSceneItemEnabled` | `{ sceneName, inputName, sceneItemEnabled }` — Lumia resolves `inputName` → the scene-item id |
|
|
602
|
+
| `SetSourceFilterEnabled` | `{ sourceName, filterName, filterEnabled }` |
|
|
603
|
+
| `SaveSourceScreenshot` | `{ sourceName, imageFormat, imageFilePath }` |
|
|
604
|
+
| `StartStream` / `StopStream` / `StartRecord` / `StopRecord` | no extra fields |
|
|
605
|
+
|
|
606
|
+
Convenience source types let you set a source's content without hand-building `inputSettings`, but they only work if you **also** pass `lumiaOrigin: "SetInputSettings"` — Lumia rewrites the request into a real `SetInputSettings` call using it. Without `lumiaOrigin` the alias is sent verbatim and OBS rejects it. The aliases: `SetSourceText` (`{ inputName, text }`), `SetGenericUrlSource` / `SetSourceUrl` (`{ inputName, url }`), `SetGenericFileSource` / `SetImageFileSource` / `SetMediaFileSource` (`{ inputName, file }`):
|
|
607
|
+
|
|
608
|
+
```js
|
|
609
|
+
{ base: "obs", "request-type": "SetMediaFileSource", lumiaOrigin: "SetInputSettings", inputName: "Replay", file: "{{get_latest_file_from_folder=G:/Replays}}" }
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
For custom code it's usually simpler to skip the alias and call `sendRawObsJson({ "request-type": "SetInputSettings", inputName: "Replay", inputSettings: { local_file: "..." } })` directly. All other request-types match the OBS v5 API exactly.
|
|
573
613
|
|
|
574
614
|
#### Streamlabs Desktop (`base: "slobs"`)
|
|
575
615
|
|
|
@@ -657,20 +697,20 @@ These read their fields **flat** on the action object (no `value` wrapper).
|
|
|
657
697
|
|
|
658
698
|
```js
|
|
659
699
|
async function() {
|
|
660
|
-
// MQTT: publish to a topic
|
|
661
|
-
await actions([{ base: "mqtt", type: "send", host: "192.168.1.50", topic: "home/light", value: "ON" }]);
|
|
700
|
+
// MQTT: publish to a topic. host is the broker URL — mqtt://<host>:<port>
|
|
701
|
+
await actions([{ base: "mqtt", type: "send", host: "mqtt://192.168.1.50:1883", topic: "home/light", value: "ON" }]);
|
|
662
702
|
|
|
663
|
-
// WebSocket: send to one connection by its id
|
|
703
|
+
// WebSocket: send to one configured connection by its id
|
|
664
704
|
await actions([{ base: "websocket", type: "data", device: "<websocketId>", value: "hello" }]);
|
|
665
705
|
|
|
666
|
-
// Serial: write raw data to a port (
|
|
706
|
+
// Serial: write raw data to a port (COM3 on Windows, /dev/tty.* on macOS)
|
|
667
707
|
await actions([{ base: "serial", type: "write", port: "COM3", value: "L1\n" }]);
|
|
668
708
|
|
|
669
|
-
// Art-Net: set DMX channels on a universe (
|
|
670
|
-
await actions([{ base: "artnet", type: "artnet", universe: 0, values: [{ channel: 1, value: 255 }, { channel: 2, value: 128 }] }]);
|
|
709
|
+
// Art-Net: set DMX channels on a universe (channel 1-512, value 0-255). universe is a string
|
|
710
|
+
await actions([{ base: "artnet", type: "artnet", universe: "0", values: [{ channel: 1, value: 255 }, { channel: 2, value: 128 }] }]);
|
|
671
711
|
|
|
672
|
-
// Broadlink: send a learned IR/RF code by its library id
|
|
673
|
-
await actions([{ base: "broadlink", type: "ir", device: "<deviceId>", value: "
|
|
712
|
+
// Broadlink: send a learned IR/RF code by its library id to a device
|
|
713
|
+
await actions([{ base: "broadlink", type: "ir", device: "<deviceId>", value: "<codeId>" }]);
|
|
674
714
|
done();
|
|
675
715
|
}
|
|
676
716
|
```
|
|
@@ -682,11 +722,35 @@ All take a `value` object.
|
|
|
682
722
|
| base | type | `value` | notes |
|
|
683
723
|
| --- | --- | --- | --- |
|
|
684
724
|
| `switchbot` | `turnOn` / `turnOff` / `toggle` | `{ deviceId: "<id>" }` | |
|
|
725
|
+
| `wavelink` | `FILTER_SET` | `{ filterId: "<uuid>", isEnabled: true, inputId: "Wave Link Mic In 1" }` | enable/disable an input's filter; `filterId: "ALL_EFFECTS"` targets every effect on that input |
|
|
685
726
|
| `wavelink` | `SET_INPUT_VOLUME` | `{ inputId: "<id>", volume: 50, mixerID: "com.elgato.mix.local" }` | volume 0–100; mixer `local`/`stream`/`all` |
|
|
686
727
|
| `wavelink` | `MUTE_INPUT` | `{ inputId: "<id>", muted: true, mixerID: "com.elgato.mix.local" }` | |
|
|
687
728
|
| `wavelink` | `SET_OUTPUT_VOLUME` / `MUTE_OUTPUT` | `{ volume: 50, mixerID: "com.elgato.mix.local" }` | |
|
|
688
729
|
| `wavelink3` | same types as `wavelink` | same shapes | Wave Link 3.0 uses base `wavelink3`; some legacy filter/mic types are unsupported on v3 |
|
|
689
|
-
| `camerahub` | `SET_WEBCAM_PROPERTY` | `{ propertyID: "Brightness", propertyValue: 60 }` |
|
|
730
|
+
| `camerahub` | `SET_WEBCAM_PROPERTY` | `{ propertyID: "Brightness", propertyValue: 60 }` | all camerahub types share one property-bag `value` (`deviceID, propertyID, propertyValue, intensity, isEnabled, …`) — set only the fields the type uses. Also `SELECT_DEVICE`, `SET_NVIDIA_VIDEO_EFFECT`, `SET_LUT_EFFECT` (`intensity`), `SET_PROMPTER_PROPERTY` |
|
|
690
731
|
| `streamfog` | `activateLens` | `{ lensId: "<id or name>", duration: 10 }` | `lensId: "random"` picks one; also `activateOutfit` (`{ outfit, duration }`) and `disableLens` (`{}`) |
|
|
691
732
|
|
|
733
|
+
#### Plugin actions (`base: "<pluginId>"`)
|
|
734
|
+
|
|
735
|
+
Every installed plugin is also a valid base — use the plugin's id as the `base`, plus the plugin's own action `type` and a `value` object of that plugin's fields. The exact `type` and `value` come from the plugin's manifest, so the reliable way to discover them is to add the action once in the editor and read it back; the shape is always `{ base: "<pluginId>", type: "<action type>", value: { ...plugin fields } }`. Verified examples:
|
|
736
|
+
|
|
737
|
+
```js
|
|
738
|
+
async function() {
|
|
739
|
+
// Tapo smart plug — target is the device IP, or "IP|deviceId"
|
|
740
|
+
await actions([{ base: "tapo_plugin", type: "tapo_turn_on", value: { target: "192.168.50.169" } }]);
|
|
741
|
+
|
|
742
|
+
// Steam — look up a game
|
|
743
|
+
await actions([{ base: "steam", type: "fetch_game", value: { game: "Sonic" } }]);
|
|
744
|
+
|
|
745
|
+
// ClickUp — create a task (assigneeId is comma-separated)
|
|
746
|
+
await actions([{ base: "clickup", type: "create_task", value: { name: "{{message}}", assigneeId: "14928785,14928776" } }]);
|
|
747
|
+
|
|
748
|
+
// ElevenLabs TTS
|
|
749
|
+
await actions([{ base: "elevenlabs_tts", type: "speak", value: { message: "{{message}}", voiceId: "hpp4J3VqNfWAUOO0d1Us", modelId: "eleven_multilingual_v2", volume: 100 } }]);
|
|
750
|
+
done();
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
A plugin action is silently skipped unless its plugin is installed, connected, and enabled.
|
|
755
|
+
|
|
692
756
|
This documentation can get extremely broad for every integration, so if you get stuck please visit our [**Discord**](https://discord.gg/R8rCaKb) to ask us any questions.
|
|
@@ -110,12 +110,27 @@ Include these two helper aliases in your embeddings so the model can quickly map
|
|
|
110
110
|
"min": { "type": "number" },
|
|
111
111
|
"max": { "type": "number" },
|
|
112
112
|
"visibleIf": {
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
"oneOf": [
|
|
114
|
+
{
|
|
115
|
+
"type": "object",
|
|
116
|
+
"required": ["key", "equals"],
|
|
117
|
+
"properties": {
|
|
118
|
+
"key": { "type": "string" },
|
|
119
|
+
"equals": {}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"type": "array",
|
|
124
|
+
"items": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"required": ["key", "equals"],
|
|
127
|
+
"properties": {
|
|
128
|
+
"key": { "type": "string" },
|
|
129
|
+
"equals": {}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
]
|
|
119
134
|
},
|
|
120
135
|
"hidden": { "type": "boolean" }
|
|
121
136
|
},
|
|
@@ -399,7 +399,7 @@ A field object can now contain these properties:
|
|
|
399
399
|
| **`value`** | ❌ | Default value that appears the first time the user opens the overlay (also pre populates `Overlay.data`). Omit it to leave the field blank/unchecked on first load. | `"value": 18` |
|
|
400
400
|
| **`options`** | ☑️\* | Key value map of selectable choices. Required **only** for `dropdown`, `multiselect` and `slider`; ignored for other types. For `slider`, `options` supports `step`, `min`, `max`, `prefix`, `suffix`. | `"options": { "step": 5, "min": 0, "max": 100 }` |
|
|
401
401
|
| **`order`** | ❌ | **Display order priority**. Fields with lower numbers appear first. Fields without `order` appear after ordered fields, sorted alphabetically by key. | `"order": 1` |
|
|
402
|
-
| **`visibleIf`** | ❌ | **Conditional render rule**. Field is shown **only if** `Overlay.data[visibleIf.key]` strictly equals one of the values in `visibleIf.equals`.
|
|
402
|
+
| **`visibleIf`** | ❌ | **Conditional render rule**. Field is shown **only if** `Overlay.data[visibleIf.key]` strictly equals one of the values in `visibleIf.equals`. Pass an **array of rules** to require that **every** rule matches (AND across keys). | `"visibleIf": [{ "key": "targetKey", "equals": ["yes", "maybe"] }, { "key": "mode", "equals": "advanced" }]` |
|
|
403
403
|
| **`hidden`** | ❌ | **Hard-hide rule.** When set to `true`, the field is **never displayed** in the Configs sidebar, preventing end users from altering it. The value still flows into `Overlay.data`, so the overlay can rely on it internally.<br>Useful for locking event subscriptions or other advanced settings. | `"hidden": true` |
|
|
404
404
|
|
|
405
405
|
Additional properties for text fields (`type: "input"` and `type: "textarea"`):
|
|
@@ -761,10 +761,13 @@ In this example, the fields would appear in this order:
|
|
|
761
761
|
### Visible If Conditional Fields
|
|
762
762
|
|
|
763
763
|
The `visibleIf` field is a conditional statement that determines whether a field should be visible or not based on a condition.
|
|
764
|
-
The `visibleIf` field
|
|
764
|
+
The `visibleIf` field can be **either**:
|
|
765
|
+
|
|
766
|
+
- a single rule object with two keys, `key` and `equals`, or
|
|
767
|
+
- an **array of rule objects**, in which case the field is shown only when **every** rule matches (logical AND). Use the array form to gate a field on more than one key at once.
|
|
765
768
|
|
|
766
769
|
The `key` key is a string that represents the name of the field whose value should be used in the conditional statement.
|
|
767
|
-
The `equals` key is a string, number, boolean, or an array that represents the value of the field
|
|
770
|
+
The `equals` key is a string, number, boolean, or an array that represents the value(s) of that field that make the condition match. When `equals` is an array, the rule matches if the field's value is one of the listed values (and for `multiselect` fields, if any selected value is in the list).
|
|
768
771
|
|
|
769
772
|
#### Single Primitive Equals Example
|
|
770
773
|
|
|
@@ -804,6 +807,35 @@ The `equals` key is a string, number, boolean, or an array that represents the v
|
|
|
804
807
|
}
|
|
805
808
|
```
|
|
806
809
|
|
|
810
|
+
#### Multiple Keys (Array of Rules) Example
|
|
811
|
+
|
|
812
|
+
Pass an array of rule objects to require that **every** rule matches before the
|
|
813
|
+
field shows. Here `subcolor` only appears when **both** `color` and `alerts`
|
|
814
|
+
are set to one of `red`, `blue`, or `green`:
|
|
815
|
+
|
|
816
|
+
```json
|
|
817
|
+
{
|
|
818
|
+
"color": {
|
|
819
|
+
"type": "input",
|
|
820
|
+
"label": "Colors"
|
|
821
|
+
},
|
|
822
|
+
"subcolor": {
|
|
823
|
+
"type": "input",
|
|
824
|
+
"label": "Subcolors",
|
|
825
|
+
"visibleIf": [
|
|
826
|
+
{
|
|
827
|
+
"key": "color",
|
|
828
|
+
"equals": ["red", "blue", "green"]
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
"key": "alerts",
|
|
832
|
+
"equals": ["red", "blue", "green"]
|
|
833
|
+
}
|
|
834
|
+
]
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
```
|
|
838
|
+
|
|
807
839
|
---
|
|
808
840
|
|
|
809
841
|
## 📊 Data Tab
|
|
@@ -53,7 +53,7 @@ export enum ConfigsFieldType {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* A single conditional render rule for a config field.
|
|
57
57
|
* The field is shown only when `Overlay.data[key]` strictly equals one of `equals`
|
|
58
58
|
* (scalar) or intersects with `equals` (when either side is an array).
|
|
59
59
|
*
|
|
@@ -68,6 +68,23 @@ export interface ConfigVisibleIf {
|
|
|
68
68
|
equals: string | number | boolean | Array<string | number | boolean>;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Conditional render rule, or a list of rules. When an array is supplied, the
|
|
73
|
+
* field is shown only when **every** rule matches (logical AND), letting you
|
|
74
|
+
* gate a field on several keys at once.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // single key
|
|
78
|
+
* { key: 'mode', equals: 'advanced' }
|
|
79
|
+
* @example
|
|
80
|
+
* // multiple keys — all must match
|
|
81
|
+
* [
|
|
82
|
+
* { key: 'color', equals: ['red', 'blue', 'green'] },
|
|
83
|
+
* { key: 'alerts', equals: ['red', 'blue', 'green'] },
|
|
84
|
+
* ]
|
|
85
|
+
*/
|
|
86
|
+
export type ConfigVisibleIfRule = ConfigVisibleIf | ConfigVisibleIf[];
|
|
87
|
+
|
|
71
88
|
/** Properties common to every config field, regardless of `type`. */
|
|
72
89
|
export interface BaseConfigField {
|
|
73
90
|
/** Human-readable name shown next to the control in the Configs sidebar. */
|
|
@@ -79,9 +96,10 @@ export interface BaseConfigField {
|
|
|
79
96
|
order?: number;
|
|
80
97
|
/**
|
|
81
98
|
* Conditional render rule. When set, the field renders only when
|
|
82
|
-
* `Overlay.data[visibleIf.key]` matches `visibleIf.equals`.
|
|
99
|
+
* `Overlay.data[visibleIf.key]` matches `visibleIf.equals`. Pass an array of
|
|
100
|
+
* rules to require that **every** rule matches (logical AND across keys).
|
|
83
101
|
*/
|
|
84
|
-
visibleIf?:
|
|
102
|
+
visibleIf?: ConfigVisibleIfRule;
|
|
85
103
|
/**
|
|
86
104
|
* Hard-hide rule. When `true`, the field is never displayed in the Configs
|
|
87
105
|
* sidebar, but its `value` still flows into `Overlay.data` for internal use.
|
|
@@ -35,7 +35,7 @@ Source of truth (in order): this file > `gpt-instructions-extended.md` (long-for
|
|
|
35
35
|
- **HTML**: body content only. Stable IDs/classes. No inline `<script>` or `<style>`.
|
|
36
36
|
- **CSS**: stylesheet only. Unquoted CSS variables for colors/sizes/numbers. Quoted only where CSS requires a string (`font-family: "{{font}}";`).
|
|
37
37
|
- **JS**: top-level JS. Use `Overlay.data` for Data values. Use `textContent`/`createElement`/`appendChild` for any chat, alert, or user-generated text — never `innerHTML` with user input. `fetch` is allowed.
|
|
38
|
-
- **Configs**: field types: `input`, `textarea`, `number`, `checkbox`, `dropdown`, `multiselect`, `colorpicker`, `fontpicker`, `slider`, `imageupload`, `soundupload`, `videoupload`, `actionbutton`. Required: `type`, `label`. Use `value` for defaults. `dropdown`/`multiselect` need `options`. `slider` needs `options.min`/`max` (usually `step`/`prefix`/`suffix`). `imageupload`/`soundupload`/`videoupload` accept an `accept` MIME hint. `actionbutton` has no `value` — bind it via `Overlay.on('configAction', ({ key }) => …)`. Use `order` to control sidebar order. Use `visibleIf` for conditional fields. Keys must be machine-friendly (no spaces).
|
|
38
|
+
- **Configs**: field types: `input`, `textarea`, `number`, `checkbox`, `dropdown`, `multiselect`, `colorpicker`, `fontpicker`, `slider`, `imageupload`, `soundupload`, `videoupload`, `actionbutton`. Required: `type`, `label`. Use `value` for defaults. `dropdown`/`multiselect` need `options`. `slider` needs `options.min`/`max` (usually `step`/`prefix`/`suffix`). `imageupload`/`soundupload`/`videoupload` accept an `accept` MIME hint. `actionbutton` has no `value` — bind it via `Overlay.on('configAction', ({ key }) => …)`. Use `order` to control sidebar order. Use `visibleIf` for conditional fields — either a single `{ key, equals }` rule or an array of rules (the field shows only when every rule matches). Keys must be machine-friendly (no spaces).
|
|
39
39
|
- **Data**: every Configs key must have a matching Data key with a matching default. Data can hold internal values that aren't in Configs (rare).
|
|
40
40
|
|
|
41
41
|
## Variables
|
|
@@ -53,7 +53,7 @@ export enum ConfigsFieldType {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* A single conditional render rule for a config field.
|
|
57
57
|
* The field is shown only when `Overlay.data[key]` strictly equals one of `equals`
|
|
58
58
|
* (scalar) or intersects with `equals` (when either side is an array).
|
|
59
59
|
*
|
|
@@ -68,6 +68,23 @@ export interface ConfigVisibleIf {
|
|
|
68
68
|
equals: string | number | boolean | Array<string | number | boolean>;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Conditional render rule, or a list of rules. When an array is supplied, the
|
|
73
|
+
* field is shown only when **every** rule matches (logical AND), letting you
|
|
74
|
+
* gate a field on several keys at once.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // single key
|
|
78
|
+
* { key: 'mode', equals: 'advanced' }
|
|
79
|
+
* @example
|
|
80
|
+
* // multiple keys — all must match
|
|
81
|
+
* [
|
|
82
|
+
* { key: 'color', equals: ['red', 'blue', 'green'] },
|
|
83
|
+
* { key: 'alerts', equals: ['red', 'blue', 'green'] },
|
|
84
|
+
* ]
|
|
85
|
+
*/
|
|
86
|
+
export type ConfigVisibleIfRule = ConfigVisibleIf | ConfigVisibleIf[];
|
|
87
|
+
|
|
71
88
|
/** Properties common to every config field, regardless of `type`. */
|
|
72
89
|
export interface BaseConfigField {
|
|
73
90
|
/** Human-readable name shown next to the control in the Configs sidebar. */
|
|
@@ -79,9 +96,10 @@ export interface BaseConfigField {
|
|
|
79
96
|
order?: number;
|
|
80
97
|
/**
|
|
81
98
|
* Conditional render rule. When set, the field renders only when
|
|
82
|
-
* `Overlay.data[visibleIf.key]` matches `visibleIf.equals`.
|
|
99
|
+
* `Overlay.data[visibleIf.key]` matches `visibleIf.equals`. Pass an array of
|
|
100
|
+
* rules to require that **every** rule matches (logical AND across keys).
|
|
83
101
|
*/
|
|
84
|
-
visibleIf?:
|
|
102
|
+
visibleIf?: ConfigVisibleIfRule;
|
|
85
103
|
/**
|
|
86
104
|
* Hard-hide rule. When `true`, the field is never displayed in the Configs
|
|
87
105
|
* sidebar, but its `value` still flows into `Overlay.data` for internal use.
|