API-Referenz

Props von TreatmentConsultant

PropTypStandardwertBeschreibung
configDeepPartial<TreatmentConsultantConfig>{}Überschreibungen, die mit den Standardwerten zusammengeführt werden. Siehe Konfiguration
styleClassPassthroughstring | string[][]Zusätzliche Klassen für das Wurzelelement des Widgets
licenseKeystringundefinedÜberschreibt den Schlüssel des Plugins für diese Instanz. Siehe Lizenzierung

Events von TreatmentConsultant

EventPayloadWird ausgelöst, wenn
changeConsultationSelectionssich eine Auswahl ändert
completeConsultationSelectionsdie Kundin oder der Kunde den Ergebnisschritt erreicht

createHairTreatments()

Eine Factory für ein Vue-Plugin. Nach der Installation stellt sie jeder TreatmentConsultant-Instanz in der App eine Standard-config bereit. Die config-Props auf Instanzebene werden darüber zusammengeführt.

ts
function createHairTreatments(
  config?: DeepPartial<TreatmentConsultantConfig> & { licenseKey?: string }
): Plugin

pages.docs.apiReference.createHairTreatments.licenseKeyField

Die config des Plugins wird einmalig bei der Installation des Plugins zusammengeführt. Um die Konfiguration zur Laufzeit zu ändern, etwa beim Sprachwechsel, übergeben Sie sie stattdessen über die config-Prop der Komponente, die sich bei jeder Wertänderung aktualisiert. Siehe Sprache wechseln.

TextConfig

Alle für Nutzer sichtbaren Texte, gruppiert nach dem Ort, an dem sie angezeigt werden.

ts
interface TextConfig {
  header: {
    /** Brand/salon name shown in the built-in header. Empty string hides it. */
    brand: string
    /** Persistent title shown alongside the brand, e.g. "Colour Consultation" */
    title: string
  }
  navigation: {
    steps: string[]
    back: string
    next: string
    viewResults: string
    backToResults: string
  }
  progress: {
    /** Format string for the step counter. Use {step}, {total}, {label} as placeholders. */
    stepFormat: string
  }
  steps: {
    hairType: string
    naturalColour: string
    greyCoverage: string
    greyCoverageSubtitle: string
    desiredColour: string
    desiredColourSkipSublabel: string
    treatments: string
    treatmentsSubtitle: string
    applicationType: string
    applicationTypeSubtitle: string
    cut: string
    cutSubtitle: string
  }
  /** Hero content above each selection step, keyed by step name. */
  explainers: {
    hairType: ExplainerContent
    naturalColour: ExplainerContent
    desiredColour: ExplainerContent
    applicationType: ExplainerContent
    cut: ExplainerContent
    treatments: ExplainerContent
  }
  results: {
    title: string
    colourSection: string
    treatmentsSection: string
    processesRequired: string
    noColour: { label: string; note: string }
    noTreatment: { label: string; note: string }
    compatOk: string
    compatWarning: string
    suitability: Record<Suitability, { icon: string; label: string }>
  }
  summary: {
    hairType: string
    naturalColour: string
    greyCoverage: string
    /** Shown when the grey coverage question was skipped */
    noGreyCoverage: string
    dreamColour: string
    treatments: string
    noTreatment: string
    applicationType: string
    cut: string
    /** Shown when no cut was chosen */
    noCut: string
  }
  cta: {
    disclaimer: string
    bookLabel: string
    bookHref: string
    resetLabel: string
  }
  /** Small strings that don't belong to a single step or option. */
  labels: {
    /** The built-in "no cut today" choice on the cut step */
    cutSkipLabel: string
    cutSkipSublabel: string
    /** Shown on an option that isn't offered for the chosen hair type */
    hairTypeExcludedNote: string
    /** Shown on a treatment that conflicts with one already picked. Use {treatment} as a placeholder. */
    treatmentConflictFormat: string
    /** The extra "all shades" tab in the full shade catalogue */
    allShadesTab: string
  }
  /** Virtual try-on screen (behaviour.experimentalTryOn). */
  tryOn: {
    /** Accessible label for the try-on button in the header, shown on every step */
    triggerLabel: string
    /** The larger try-on button on the Dream Colour step */
    dreamColourCtaLabel: string
    title: string
    useCameraLabel: string
    uploadPhotoLabel: string
    loadingLabel: string
    unsupportedMessage: string
    cameraDeniedMessage: string
    closeLabel: string
    turnCameraOffLabel: string
    /** Colour strength slider */
    opacityLabel: string
    /** Edge softness slider */
    blurLabel: string
  }
  /** Colour advice on the results screen, keyed natural colour, then dream colour. */
  recommendations: Record<NaturalColourId, Partial<Record<DesiredColourId, RecommendationText>>>
  /** Used for any combination missing from recommendations */
  recommendationFallback: RecommendationText
  /** Added to the details when the hair type is curly or coily */
  texturedHairNote: string
  /** Added when the natural and dream shades are the same. Use {shade} as a placeholder. */
  sameShadeNoteFormat: string
  /** Per-option wording, keyed by list, then option id. See OptionTextConfig. */
  options?: OptionTextConfig
}

interface ExplainerContent {
  title: string
  body: string
  /** Falls back to the default hero image when omitted */
  image?: string
}

interface RecommendationText {
  method: string
  notes: string
  details: string[]
}

Wie Sie diese Texte übersetzen oder ein fertiges Sprachpaket verwenden, erfahren Sie unter Sprachen.

OptionTextConfig

Die Struktur von text.options: übersetzbare Bezeichnungen für jede Option, geordnet nach Liste und dann nach Options-ID. Jedes Feld überschreibt das entsprechende Feld der Option mit dieser ID. Wie das angewendet wird, erfahren Sie unter Optionsbezeichnungen.

ts
interface OptionTextConfig {
  hairTypes?: Partial<Record<HairTypeId, LabelOptionText>>
  naturalColours?: Partial<Record<NaturalColourId, LabelOptionText>>
  desiredColours?: Partial<Record<DesiredColourId, LabelOptionText>>
  /** Keyed by DesiredShadeOption.id */
  shades?: Record<string, LabelOptionText>
  /** Keyed by NaturalShadeOption.id */
  naturalShades?: Record<string, LabelOptionText>
  greyCoverageOptions?: Partial<Record<GreyCoverageId, DescribedOptionText>>
  treatments?: Partial<Record<TreatmentId, TreatmentOptionText>>
  applicationTypes?: Partial<Record<ApplicationTypeId, WarnableOptionText>>
  cuts?: Partial<Record<CutId, WarnableOptionText>>
}

interface LabelOptionText {
  label?: string
}

interface DescribedOptionText extends LabelOptionText {
  description?: string
}

interface TreatmentOptionText extends DescribedOptionText {
  /** Replaces the treatment's notes as a whole list */
  notes?: string[]
}

interface WarnableOptionText extends DescribedOptionText {
  /** Merged per hair type and per field over the option's own warnings */
  warnings?: Partial<Record<HairTypeId, Partial<{ note: string; detail: string }>>>
}

Sprachpakete

Fertige Übersetzungen, ein Subpath-Export pro Sprache. Jedes ist ein DeepPartial<TextConfig>, der alle Texte im Widget abdeckt. Wie Sie sie verwenden, erfahren Sie unter Integrierte Sprachpakete.

ts
// srcdev-hair-treatments/locales/fr
export const fr: DeepPartial<TextConfig>

// srcdev-hair-treatments/locales/de
export const de: DeepPartial<TextConfig>

// srcdev-hair-treatments/locales/en-US
export const enUS: DeepPartial<TextConfig>

Optionstypen

Die Strukturen hinter den einzelnen Options-Arrays in TreatmentConsultantConfig.

ts
type HairTypeId = "straight" | "wavy" | "curly" | "coily"

interface HairTypeOption {
  id: HairTypeId
  label: string
  pattern: string
  image?: string
}

type NaturalColourId =
  | "light-blonde" | "dark-blonde" | "light-brown" | "dark-brown"
  | "red" | "black" | "grey-white"

interface ColourOption {
  id: NaturalColourId
  label: string
  colour: string
  image?: string
  textDark?: boolean
}

type DesiredColourId =
  | "none" | "blonde" | "brown" | "red" | "black" | "grey-silver" | "vivid" | "balayage"

interface DesiredColourOption {
  id: DesiredColourId
  label: string
  colour?: string
  image?: string
  textDark?: boolean
}

type ApplicationTypeId = "all-over" | "balayage" | "highlights" | "lowlights" | "t-section"

interface ApplicationTypeOption {
  id: ApplicationTypeId
  label: string
  description?: string
  icon: string
}

type GreyCoverageId = "none" | "some" | "significant" | "predominantly-grey"

interface GreyCoverageOption {
  id: GreyCoverageId
  label: string
  description?: string
}

/** Individual named shade within a broad category — Premium-only "granular" catalog mode. */
interface DesiredShadeOption {
  id: string
  label: string
  desiredColourId: DesiredColourId
  colour?: string
  image?: string
  image2x?: string
}

interface NaturalShadeOption {
  id: string
  label: string
  naturalColourId: NaturalColourId
  colour?: string
  image?: string
  image2x?: string
}

type CutId = "none" | "trim" | "restyle" | "layers" | "fringe"

interface CutOption {
  id: CutId
  label: string
  description?: string
  icon: string
  excludedByHairTypes?: HairTypeId[]
  warnForHairTypes?: HairTypeId[]
  warnings?: Partial<Record<HairTypeId, { note: string; detail: string }>>
}

type TreatmentId =
  | "none" | "keratin-smoothing" | "brazilian-blowout" | "perm" | "relaxer"
  | "japanese-straightening" | "deep-conditioning" | "bond-repair" | "gloss"
  | "scalp-treatment" | "blowdry"

interface Treatment {
  id: TreatmentId
  label: string
  icon: string
  description?: string
  notes: string[]
  /** Show a colour-compatibility badge on the results screen */
  compatibility?: boolean
  /** "ok" = compatible same-day; "warning" = not same-day as colour */
  colourCompatibility?: "ok" | "warning"
  excludes?: TreatmentId[]
  /** Set to false to hide this treatment from the treatments step */
  display?: boolean
}

ConsultationSelections

Die Payload-Struktur für die Events change und complete.

ts
interface ConsultationSelections {
  hairType: HairTypeId | null
  naturalColour: NaturalColourId | null
  /** Picked shade id in "granular" naturalColourMode; null in basic mode or before picking */
  naturalShade: string | null
  greyCoverage: GreyCoverageId | null
  desiredColour: DesiredColourId | null
  /** Picked shade id in "granular" dreamColourMode; null in basic mode or before picking */
  desiredShade: string | null
  applicationType: ApplicationTypeId | null
  cut: CutId | null
  treatments: TreatmentId[]
}

Suitability

ts
type Suitability = "great" | "possible" | "difficult" | "not-recommended"

Slots

header

Wird oberhalb des Schrittinhalts innerhalb des Wurzelelements des Widgets gerendert. Standardmäßig zeigt er den integrierten Header (text.header.brand / .title plus eine aktuelle Fortschrittsanzeige). Nutzen Sie diesen Slot, um ihn vollständig durch eigenes Markup zu ersetzen. Da es ein Scoped Slot ist, bleibt ein eigener Schrittzähler automatisch synchron:

Slot-PropTypBeschreibung
displayStepnumberAktueller Schritt, ab 1 gezählt, bereinigt um übersprungene/ausgeblendete Schritte
totalStepsnumberGesamtzahl der Schritte (6 oder 7, abhängig von behaviour.showTreatmentsStep)
displayStepLabelstringBezeichnung des aktuellen Schritts aus text.navigation.steps
progressLabelstringDer formatierte Text hinter der integrierten Fortschrittsanzeige (text.progress.stepFormat)
vue
<TreatmentConsultant>
  <template #header="{ displayStep, totalSteps, displayStepLabel }">
    <header class="my-consultation-header">
      <img class="my-logo" src="/my-logo.svg" alt="My Salon" />
      <span>Step {{ displayStep }} of {{ totalSteps }} — {{ displayStepLabel }}</span>
    </header>
  </template>
</TreatmentConsultant>

In jedem Auswahlschritt zeigt der Hero-Bereich die Schrittbezeichnung zusätzlich über seinem Bild an. Ein eigener Header, der ebenfalls einen Fortschrittstext anzeigt, zeigt ihn daher doppelt.