Editor Components
Editor components build settings UIs for editor.tsx and designer.tsx surfaces. They serialize via the Worker Reconciler and render as native @lumio/ui components on the host -- matching the Lumio design system automatically.
All editor components are imported from @zaflun/lumio-sdk.
EditorInput
Text or number input with optional label, placeholder, min/max, and unit suffix.
Import
import { EditorInput } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Current value |
onChange | (value: string) => void | Yes | Change handler |
label | string | No | Label text |
type | "text" | "number" | "color" | No | Input type (default: "text") |
placeholder | string | No | Placeholder text |
min | number | No | Minimum value (number type) |
max | number | No | Maximum value (number type) |
step | number | No | Step increment (number type) |
unit | string | No | Unit suffix (e.g. "px", "ms") |
id | string | No | HTML id attribute |
Example
import { EditorInput, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorInput
label="Font Size"
type="number"
value={String(config.settings?.fontSize ?? 16)}
onChange={(v) => update("fontSize", Number(v))}
min={8}
max={200}
unit="px"
placeholder="Enter value..."
/>
);
}
EditorTextarea
Multi-line text input with configurable row count.
Import
import { EditorTextarea } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Current value |
onChange | (value: string) => void | Yes | Change handler |
label | string | No | Label text |
placeholder | string | No | Placeholder text |
rows | number | No | Number of visible rows |
id | string | No | HTML id attribute |
Example
import { EditorTextarea, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorTextarea
label="Welcome Message"
value={String(config.settings?.welcome ?? "")}
onChange={(v) => update("welcome", v)}
placeholder="Enter a message..."
rows={4}
/>
);
}
EditorSelect
Dropdown select with predefined options.
Import
import { EditorSelect } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Currently selected value |
onChange | (value: string) => void | Yes | Change handler |
options | { value: string; label: string }[] | Yes | Available options |
label | string | No | Label text |
id | string | No | HTML id attribute |
Example
import { EditorSelect, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorSelect
label="Position"
value={String(config.settings?.position ?? "top-right")}
onChange={(v) => update("position", v)}
options={[
{ value: "top-left", label: "Top Left" },
{ value: "top-right", label: "Top Right" },
{ value: "bottom-left", label: "Bottom Left" },
{ value: "bottom-right", label: "Bottom Right" },
]}
/>
);
}
EditorCheckbox
Toggle checkbox with a label.
Import
import { EditorCheckbox } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
checked | boolean | Yes | Current state |
onChange | (checked: boolean) => void | Yes | Change handler |
label | string | Yes | Label text |
id | string | No | HTML id attribute |
Example
import { EditorCheckbox, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorCheckbox
label="Show timestamps"
checked={Boolean(config.settings?.showTimestamps ?? true)}
onChange={(v) => update("showTimestamps", v)}
/>
);
}
EditorSlider
Range slider for selecting a numeric value within bounds.
Import
import { EditorSlider } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | number | Yes | Current value |
onChange | (value: number) => void | Yes | Change handler |
label | string | No | Label text |
min | number | No | Minimum value |
max | number | No | Maximum value |
step | number | No | Step increment |
unit | string | No | Unit suffix (e.g. "%", "px") |
id | string | No | HTML id attribute |
Example
import { EditorSlider, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorSlider
label="Opacity"
value={Number(config.settings?.opacity ?? 100)}
onChange={(v) => update("opacity", v)}
min={0}
max={100}
step={5}
unit="%"
/>
);
}
EditorColorPicker
Color picker with hex input field.
Import
import { EditorColorPicker } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Current hex color (e.g. "#6366f1") |
onChange | (value: string) => void | Yes | Change handler |
label | string | No | Label text |
id | string | No | HTML id attribute |
Example
import { EditorColorPicker, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorColorPicker
label="Primary Color"
value={String(config.settings?.primaryColor ?? "#6366f1")}
onChange={(v) => update("primaryColor", v)}
/>
);
}
EditorFontPicker
Font family picker with optional weight and italic controls. Loads fonts from Google Fonts.
Import
import { EditorFontPicker } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Current font family name |
onChange | (family: string) => void | Yes | Family change handler |
label | string | No | Label text |
weight | string | No | Current font weight (e.g. "400", "700") |
onWeightChange | (weight: string) => void | No | Weight change handler |
italic | boolean | No | Whether italic is active |
onItalicChange | (italic: boolean) => void | No | Italic toggle handler |
Example
import { EditorFontPicker, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorFontPicker
label="Display Font"
value={String(config.settings?.fontFamily ?? "Inter")}
onChange={(v) => update("fontFamily", v)}
weight={String(config.settings?.fontWeight ?? "400")}
onWeightChange={(v) => update("fontWeight", v)}
italic={Boolean(config.settings?.fontItalic ?? false)}
onItalicChange={(v) => update("fontItalic", v)}
/>
);
}
EditorFontRow
Compact font styling row combining bold, italic, weight, size, and color controls in a single line.
Import
import { EditorFontRow } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
fontWeight | string | Yes | Current font weight (e.g. "400", "700") |
onFontWeightChange | (weight: string) => void | Yes | Weight change handler |
italic | boolean | Yes | Whether italic is active |
onItalicChange | (italic: boolean) => void | Yes | Italic toggle handler |
fontSize | number | Yes | Current font size in pixels |
onFontSizeChange | (size: number) => void | Yes | Size change handler |
fontColor | string | Yes | Current font color hex |
onFontColorChange | (color: string) => void | Yes | Color change handler |
Example
import { EditorFontRow, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorFontRow
fontWeight={String(config.settings?.fontWeight ?? "400")}
onFontWeightChange={(v) => update("fontWeight", v)}
italic={Boolean(config.settings?.fontItalic ?? false)}
onItalicChange={(v) => update("fontItalic", v)}
fontSize={Number(config.settings?.fontSize ?? 16)}
onFontSizeChange={(v) => update("fontSize", v)}
fontColor={String(config.settings?.fontColor ?? "#ffffff")}
onFontColorChange={(v) => update("fontColor", v)}
/>
);
}
EditorButton
Action button with variant support. Use for triggering actions in the editor panel (reset, test, import).
Import
import { EditorButton } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Button text |
onClick | () => void | Yes | Click handler |
variant | "default" | "primary" | "destructive" | No | Visual variant (default: "default") |
fullWidth | boolean | No | Stretch to fill container width |
disabled | boolean | No | Prevents clicks and shows disabled state |
Example
import { EditorButton, useMutation } from "@zaflun/lumio-sdk";
function Settings() {
const { mutate: resetAll } = useMutation("resetDefaults");
return (
<>
<EditorButton
label="Test Alert"
variant="primary"
onClick={() => {/* trigger test */}}
/>
<EditorButton
label="Reset to Defaults"
variant="destructive"
onClick={() => resetAll()}
/>
</>
);
}
EditorGroup
Collapsible section for organizing related settings. Renders as an accordion panel.
Import
import { EditorGroup } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Group heading text |
collapsed | boolean | No | Initial collapsed state (default: false) |
children | ReactNode | Yes | Group contents |
Example
import { EditorGroup, EditorSlider, EditorCheckbox, useLumioConfig } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
const update = (key: string, value: unknown) =>
setConfig((prev) => ({ ...prev, settings: { ...(prev.settings ?? {}), [key]: value } }));
return (
<EditorGroup label="Advanced" collapsed>
<EditorSlider
label="Animation Speed"
value={Number(config.settings?.speed ?? 300)}
onChange={(v) => update("speed", v)}
min={100}
max={2000}
unit="ms"
/>
<EditorCheckbox
label="Enable shadows"
checked={Boolean(config.settings?.shadows ?? false)}
onChange={(v) => update("shadows", v)}
/>
</EditorGroup>
);
}
EditorLabel
Section label or heading text. Use to visually separate groups of controls.
Import
import { EditorLabel } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Label text |
htmlFor | string | No | Associated input id |
required | boolean | No | Show required indicator |
Example
import { EditorLabel, EditorInput } from "@zaflun/lumio-sdk";
function Settings() {
return (
<>
<EditorLabel text="Display Settings" />
<EditorInput label="Title" value="" onChange={() => {}} id="title-input" />
</>
);
}
EditorDivider
Visual horizontal separator. Takes no props.
Import
import { EditorDivider } from "@zaflun/lumio-sdk";
Example
import { EditorDivider, EditorInput, EditorColorPicker } from "@zaflun/lumio-sdk";
function Settings() {
return (
<>
<EditorInput label="Title" value="" onChange={() => {}} />
<EditorDivider />
<EditorColorPicker label="Background" value="#000000" onChange={() => {}} />
</>
);
}
EditorInfo
Read-only informational text block. Use for help text, warnings, or descriptions.
Import
import { EditorInfo } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
content | string | Yes | Informational text to display |
Example
import { EditorInfo, EditorInput } from "@zaflun/lumio-sdk";
function Settings() {
return (
<>
<EditorInfo content="Enter the API key from your ESPN developer account. This is required for live score updates." />
<EditorInput label="API Key" value="" onChange={() => {}} placeholder="Enter API key..." />
</>
);
}
EditorChannelRow
Compact row for channel configuration: platform dropdown, channel name input, color swatch, and delete button in a single line.
Import
import { EditorChannelRow } from "@zaflun/lumio-sdk";
Props
| Prop | Type | Required | Description |
|---|---|---|---|
platform | string | Yes | Selected platform (e.g. "twitch") |
onPlatformChange | (platform: string) => void | Yes | Platform change handler |
channel | string | Yes | Channel name |
onChannelChange | (channel: string) => void | Yes | Channel name change handler |
color | string | Yes | Background color hex |
onColorChange | (color: string) => void | Yes | Color change handler |
onRemove | () => void | Yes | Remove button handler |
platforms | \{value: string, label: string\}[]? | No | Custom platform list |
Example
import { EditorChannelRow, EditorButton } from "@zaflun/lumio-sdk";
{channels.map((ch, i) => (
<EditorChannelRow
key={i}
platform={ch.platform}
onPlatformChange={(v) => updateChannel(i, "platform", v)}
channel={ch.channel}
onChannelChange={(v) => updateChannel(i, "channel", v)}
color={ch.color ?? "#000000"}
onColorChange={(v) => updateChannel(i, "color", v)}
onRemove={() => removeChannel(i)}
/>
))}
<EditorButton label="Add Channel" variant="primary" onClick={addChannel} />
Complete example
A full editor panel combining multiple editor components:
import {
Lumio,
EditorGroup,
EditorInput,
EditorSelect,
EditorCheckbox,
EditorSlider,
EditorColorPicker,
EditorFontPicker,
EditorFontRow,
EditorDivider,
EditorInfo,
EditorButton,
useLumioConfig,
useMutation,
} from "@zaflun/lumio-sdk";
function ScoreboardEditor() {
const [config, setConfig] = useLumioConfig();
const { mutate: resetScores } = useMutation("resetScores");
const update = (key: string, value: unknown) =>
setConfig((prev) => ({
...prev,
settings: { ...(prev.settings ?? {}), [key]: value },
}));
const s = config.settings ?? {};
return (
<>
<EditorInfo content="Configure how the scoreboard appears on your overlay." />
<EditorInput
label="Home Team"
value={String(s.homeTeam ?? "")}
onChange={(v) => update("homeTeam", v)}
placeholder="Team name..."
/>
<EditorInput
label="Away Team"
value={String(s.awayTeam ?? "")}
onChange={(v) => update("awayTeam", v)}
placeholder="Team name..."
/>
<EditorDivider />
<EditorSelect
label="Layout"
value={String(s.layout ?? "horizontal")}
onChange={(v) => update("layout", v)}
options={[
{ value: "horizontal", label: "Horizontal" },
{ value: "vertical", label: "Vertical" },
{ value: "compact", label: "Compact" },
]}
/>
<EditorGroup label="Appearance">
<EditorColorPicker
label="Background Color"
value={String(s.bgColor ?? "#1a1a2e")}
onChange={(v) => update("bgColor", v)}
/>
<EditorSlider
label="Opacity"
value={Number(s.opacity ?? 100)}
onChange={(v) => update("opacity", v)}
min={0}
max={100}
unit="%"
/>
<EditorFontPicker
label="Font"
value={String(s.fontFamily ?? "Inter")}
onChange={(v) => update("fontFamily", v)}
/>
<EditorFontRow
fontWeight={String(s.fontWeight ?? "700")}
onFontWeightChange={(v) => update("fontWeight", v)}
italic={Boolean(s.fontItalic ?? false)}
onItalicChange={(v) => update("fontItalic", v)}
fontSize={Number(s.fontSize ?? 24)}
onFontSizeChange={(v) => update("fontSize", v)}
fontColor={String(s.fontColor ?? "#ffffff")}
onFontColorChange={(v) => update("fontColor", v)}
/>
</EditorGroup>
<EditorGroup label="Behavior" collapsed>
<EditorCheckbox
label="Auto-hide when inactive"
checked={Boolean(s.autoHide ?? false)}
onChange={(v) => update("autoHide", v)}
/>
<EditorSlider
label="Hide delay"
value={Number(s.hideDelay ?? 30)}
onChange={(v) => update("hideDelay", v)}
min={5}
max={120}
unit="s"
/>
</EditorGroup>
<EditorDivider />
<EditorButton
label="Reset Scores"
variant="destructive"
onClick={() => resetScores()}
fullWidth
/>
</>
);
}
Lumio.render(<ScoreboardEditor />, { target: "editor" });