Skip to main content

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

PropTypeRequiredDescription
valuestringYesCurrent value
onChange(value: string) => voidYesChange handler
labelstringNoLabel text
type"text" | "number" | "color"NoInput type (default: "text")
placeholderstringNoPlaceholder text
minnumberNoMinimum value (number type)
maxnumberNoMaximum value (number type)
stepnumberNoStep increment (number type)
unitstringNoUnit suffix (e.g. "px", "ms")
idstringNoHTML 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

PropTypeRequiredDescription
valuestringYesCurrent value
onChange(value: string) => voidYesChange handler
labelstringNoLabel text
placeholderstringNoPlaceholder text
rowsnumberNoNumber of visible rows
idstringNoHTML 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

PropTypeRequiredDescription
valuestringYesCurrently selected value
onChange(value: string) => voidYesChange handler
options{ value: string; label: string }[]YesAvailable options
labelstringNoLabel text
idstringNoHTML 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

PropTypeRequiredDescription
checkedbooleanYesCurrent state
onChange(checked: boolean) => voidYesChange handler
labelstringYesLabel text
idstringNoHTML 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

PropTypeRequiredDescription
valuenumberYesCurrent value
onChange(value: number) => voidYesChange handler
labelstringNoLabel text
minnumberNoMinimum value
maxnumberNoMaximum value
stepnumberNoStep increment
unitstringNoUnit suffix (e.g. "%", "px")
idstringNoHTML 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

PropTypeRequiredDescription
valuestringYesCurrent hex color (e.g. "#6366f1")
onChange(value: string) => voidYesChange handler
labelstringNoLabel text
idstringNoHTML 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

PropTypeRequiredDescription
valuestringYesCurrent font family name
onChange(family: string) => voidYesFamily change handler
labelstringNoLabel text
weightstringNoCurrent font weight (e.g. "400", "700")
onWeightChange(weight: string) => voidNoWeight change handler
italicbooleanNoWhether italic is active
onItalicChange(italic: boolean) => voidNoItalic 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

PropTypeRequiredDescription
fontWeightstringYesCurrent font weight (e.g. "400", "700")
onFontWeightChange(weight: string) => voidYesWeight change handler
italicbooleanYesWhether italic is active
onItalicChange(italic: boolean) => voidYesItalic toggle handler
fontSizenumberYesCurrent font size in pixels
onFontSizeChange(size: number) => voidYesSize change handler
fontColorstringYesCurrent font color hex
onFontColorChange(color: string) => voidYesColor 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

PropTypeRequiredDescription
labelstringYesButton text
onClick() => voidYesClick handler
variant"default" | "primary" | "destructive"NoVisual variant (default: "default")
fullWidthbooleanNoStretch to fill container width
disabledbooleanNoPrevents 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

PropTypeRequiredDescription
labelstringYesGroup heading text
collapsedbooleanNoInitial collapsed state (default: false)
childrenReactNodeYesGroup 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

PropTypeRequiredDescription
textstringYesLabel text
htmlForstringNoAssociated input id
requiredbooleanNoShow 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

PropTypeRequiredDescription
contentstringYesInformational 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

PropTypeRequiredDescription
platformstringYesSelected platform (e.g. "twitch")
onPlatformChange(platform: string) => voidYesPlatform change handler
channelstringYesChannel name
onChannelChange(channel: string) => voidYesChannel name change handler
colorstringYesBackground color hex
onColorChange(color: string) => voidYesColor change handler
onRemove() => voidYesRemove button handler
platforms\{value: string, label: string\}[]?NoCustom 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" });