Input-Komponenten
Input-Komponenten ermöglichen es, eigene Visualisierungen für Variablen (Merkmale) zu erstellen. Sie können für jeden Variablentyp benutzerdefinierte Eingabe-Widgets registrieren, die Administratoren dann im Backend auswählen können.
Grundstruktur
Input-Komponenten werden im ui.inputs Objekt nach Variablentyp gruppiert registriert:
// In Plugin.tsx
export default {
// ...
ui: {
inputs: {
number: [ /* Visualisierungen für Zahlen */ ],
color: [ /* Visualisierungen für Farben */ ],
list: [ /* Visualisierungen für Listen */ ],
// weitere Typen...
}
}
}
Eine einzelne Input-Komponenten-Registrierung:
import type { VariableVisualisation } from "k3-plugin-api";
import { MySliderInput } from "./MySliderInput";
const sliderVisualisation: VariableVisualisation = {
key: "vendor.slider",
label: "Slider",
description: "Numerische Eingabe als Schieberegler",
component: MySliderInput
};
VariableVisualisation
Jede Input-Komponente ist eine VariableVisualisation mit:
- key: Eindeutiger Schlüssel (z.B. "vendor.slider")
- label: Anzeigename im Admin-UI
- description: Beschreibung (String oder LocalizedString)
- component: Die React-Komponente für die Eingabe
Variablentypen
Folgende Variablentypen können erweitert werden:
import { VariableType } from "k3-plugin-api";
// Verfügbare Typen:
VariableType.List // "list" - Auswahllisten
VariableType.Color // "color" - Farbauswahl
VariableType.Number // "number" - Numerische Eingabe
VariableType.Text // "text" - Texteingabe
VariableType.Boolean // "boolean" - Ja/Nein
VariableType.Image // "image" - Bildupload
VariableType.Upload // "upload" - Dateiupload
VariableType.Components // "components" - Produktkomponenten
VariableType.Information // "information" - Info-Anzeige
Component Props
Jede Input-Komponente erhält K3VariableComponentProps:
interface K3VariableComponentProps {
/** Die Variable, für die diese Komponente gerendert wird */
variable: {
id: string | number;
label: string;
type: VariableTypes;
settings?: {
template?: string; // Key der gewählten Visualisierung
templateOptions?: {
min?: number;
max?: number;
digits?: number;
[key: string]: unknown;
};
};
};
/** Aktuelle Auswahl */
selection?: {
id: string | number;
data?: {
inputValue?: number; // Für number-Variablen
[key: string]: unknown;
};
};
/** Verfügbare Werte */
values?: Array<{
id: string | number;
label: string;
value?: string | boolean | null; // hex color, boolean, etc.
}>;
/** Callback zum Setzen der Auswahl */
onChange: (
valueId: string | number,
metadata?: { inputValue?: number }
) => void;
/** Wenn true, ist die Variable gesperrt */
disabled?: boolean;
}
Beispiel: Slider für Number
import { K3VariableComponentProps } from "k3-plugin-api";
export const MySliderInput: React.FC<K3VariableComponentProps> = ({
variable,
selection,
values,
onChange,
disabled
}) => {
// Für number-Variablen gibt es typischerweise einen einzigen Wert
const value = values?.[0];
const currentValue = selection?.data?.inputValue ?? 0;
const min = variable.settings?.templateOptions?.min ?? 0;
const max = variable.settings?.templateOptions?.max ?? 100;
const step = 1 / Math.pow(10, variable.settings?.templateOptions?.digits ?? 0);
const handleChange = (newValue: number) => {
if (value?.id) {
onChange(value.id, { inputValue: newValue });
}
};
return (
<div className="slider-input">
<label>{variable.label}</label>
<input
type="range"
min={min}
max={max}
step={step}
value={currentValue}
onChange={(e) => handleChange(parseFloat(e.target.value))}
disabled={disabled}
/>
<span className="slider-value">{currentValue}</span>
</div>
);
};
Beispiel: Custom Color Picker
import { K3VariableComponentProps } from "k3-plugin-api";
import { useState } from "react";
export const MyColorPicker: React.FC<K3VariableComponentProps> = ({
variable,
selection,
values,
onChange,
disabled
}) => {
const [hexInput, setHexInput] = useState("");
return (
<div className="color-picker">
<label>{variable.label}</label>
{/* Farb-Swatches */}
<div className="color-swatches">
{values?.map((val) => (
<button
key={val.id}
className={`swatch ${selection?.id === val.id ? "active" : ""}`}
style={{ backgroundColor: val.value as string }}
onClick={() => onChange(val.id)}
disabled={disabled}
>
{val.label}
</button>
))}
</div>
{/* HEX-Eingabe */}
<div className="hex-input">
<label>HEX:</label>
<input
type="text"
value={hexInput}
onChange={(e) => setHexInput(e.target.value)}
placeholder="#FF0000"
disabled={disabled}
/>
</div>
</div>
);
};
Beispiel: Custom List mit Bildern
import { K3VariableComponentProps } from "k3-plugin-api";
export const MyImageList: React.FC<K3VariableComponentProps> = ({
variable,
selection,
values,
onChange,
disabled
}) => {
return (
<div className="image-list">
<h3>{variable.label}</h3>
<div className="image-grid">
{values?.map((val) => (
<div
key={val.id}
className={`image-card ${selection?.id === val.id ? "selected" : ""}`}
onClick={() => !disabled && onChange(val.id)}
>
<img src={val.thumbnail} alt={val.label} />
<span className="image-label">{val.label}</span>
</div>
))}
</div>
</div>
);
};
onChange für verschiedene Typen
List, Color, Boolean, Image, Upload, Components
Einfach die Value-ID übergeben:
onChange(valueId);
Number
Value-ID mit inputValue metadata übergeben:
onChange(valueId, { inputValue: numericValue });
Text
Value-ID mit inputText metadata übergeben (siehe K3-Interna):
onChange(valueId, { inputText: textValue });
Template-Optionen nutzen
Admins können im Backend Template-Optionen konfigurieren. Greifen Sie in der Komponente darauf zu:
const options = variable.settings?.templateOptions;
const showLabels = options?.showLabels ?? true;
const columns = options?.columns ?? 3;
const customValue = options?.myCustomOption;
Lokalisierte Beschreibungen
import type { LocalizedString } from "k3-plugin-api";
{
key: "vendor.slider",
label: "Slider",
description: {
de: "Numerische Eingabe als Schieberegler",
en: "Numeric input as slider",
fr: "Entrée numérique comme curseur",
nl: "Numerieke invoer als schuifregelaar"
} as LocalizedString,
component: MySliderInput
}
Alle Typen in einem Plugin
import type { VariableVisualisation } from "k3-plugin-api";
import { VariableType } from "k3-plugin-api";
// Verschiedene Input-Komponenten definieren
import { MyImageList } from "./MyImageList";
import { MyColorPicker } from "./MyColorPicker";
import { MySliderInput } from "./MySliderInput";
import { MySpinButton } from "./MySpinButton";
import { MyToggle } from "./MyToggle";
import { MyRichText } from "./MyRichText";
// Im Plugin registrieren:
export default {
// ...
ui: {
inputs: {
list: [
{
key: "vendor.imageList",
label: "Bild-Liste",
description: "Listenauswahl mit Bildern",
component: MyImageList
}
],
color: [
{
key: "vendor.colorPicker",
label: "Erweiterter Farbwähler",
description: "Farbwähler mit HEX-Eingabe",
component: MyColorPicker
}
],
number: [
{
key: "vendor.slider",
label: "Slider",
description: "Schieberegler für Zahlen",
component: MySliderInput
},
{
key: "vendor.spinButton",
label: "Spin-Button",
description: "Plus/Minus Buttons",
component: MySpinButton
}
],
boolean: [
{
key: "vendor.toggle",
label: "Toggle Switch",
description: "iOS-Style Toggle",
component: MyToggle
}
],
text: [
{
key: "vendor.richText",
label: "Rich Text Editor",
description: "Formatierte Texteingabe",
component: MyRichText
}
]
}
}
};
Verwendung im Backend
Nach der Plugin-Installation können Administratoren:
- In den Merkmal-Einstellungen unter "Darstellung" die neue Visualisierung auswählen
- Der Key der Visualisierung wird in
variable.settings.templategespeichert - Optional Template-Optionen konfigurieren
Best Practices
1. Disabled-State respektieren
Wenn disabled={true}, sollte die Komponente keine Interaktion erlauben:
<input disabled={disabled} />
<button onClick={handleClick} disabled={disabled} />
2. Fehlerbehandlung
Prüfen Sie auf fehlende oder ungültige Daten:
if (!values || values.length === 0) {
return <div>Keine Werte verfügbar</div>;
}
3. Barrierefreiheit
Nutzen Sie semantisches HTML und ARIA-Attribute:
<input
type="range"
aria-label={variable.label}
aria-valuemin={min}
aria-valuemax={max}
aria-valuenow={currentValue}
/>
4. Performance
Memoizen Sie teure Berechnungen:
const sortedValues = useMemo(
() => values?.sort((a, b) => a.label.localeCompare(b.label)),
[values]
);
5. TypeScript verwenden
Nutzen Sie die bereitgestellten Typen:
import type {
K3VariableComponentProps,
VariableVisualisation
} from "k3-plugin-api";
export const MyInput: React.FC<K3VariableComponentProps> = (props) => {
// TypeScript kennt jetzt alle Props
};
Debugging
Loggen Sie Props während der Entwicklung:
export const MyInput: React.FC<K3VariableComponentProps> = (props) => {
console.log("Variable:", props.variable);
console.log("Selection:", props.selection);
console.log("Values:", props.values);
return <div>...</div>;
};
Vollständiges Beispiel
Siehe das k3-sample-plugin Repository für vollständige, funktionierende Beispiele aller Input-Typen.