Globals


Instance Methods

App()

Application root: mounts the router behind the app-wide providers (tracking, tab management) and disables the context menu in production.

Router()

History-API router variant - use when the deploy path is known (basename from VITE_BASE_URL). Mirrors HashRouter.jsx: content + screensaver providers around the routes, pages guarded by the ErrorBoundary. App.jsx picks one of the two.

Router()

Hash-based router variant - works regardless of the deploy path, so it's the default (see App.jsx). Content + screensaver providers around the routes, pages guarded by the ErrorBoundary; the Screensaver and RotateOverlay overlays stay mounted as siblings so their fades work in both directions. RotateOverlay needs router context too (useLocation, useConfig via useSearchParams - see services/orientation.js).

Pages()

Route table of the exhibit: "/" is the app selection, each presentation mode has its own path (with an optional :viewId slide segment), and GeneralPageTracking reports every route change.

RadHeader(props: Object)

Page header shown on every RadEnablement slide (title/subline from content.header); the story icon on the right follows whichever story the current view belongs to.

Parameters

  • props (Object)
    • props.viewId (string) — Currently shown view id.

useTracking(): Object

React hook to access tracking functions (page views, events, session reset). Must be used within a <TrackingProvider>.

Returns

  • Object

Other

CacheableVideo

Drop-in replacement for <video src="..."> that's cacheable by the service worker. Renders "Loading video..." until the fetch has completed.

Parameters

  • src (string) — URL of the video file to fetch and play.
  • playing (boolean, optional) — When given, drives playback: true plays, false pauses and rewinds. Lets an always-mounted but hidden video (e.g. the screensaver behind opacity: 0) stop decoding while it's not visible.
  • props (*) — Passed through to the underlying <video> element (autoPlay, loop, muted, playsInline, ...).

ComponentRenderer

Renders a single content block of a view. Looks the block's type up in the element registry (elements/registry.js) and reshapes the raw block into the component's props via the element's own adapter. Unknown types render a debug hint in dev mode and nothing in production.

Parameters

  • props (Object)
    • props.block (Object) — A content block from a view's elements array, e.g. { type: "headline", text: "..." }.
    • props.selectedTargetViewId (string | null) — Currently armed target view (story-hub selection), passed through to selectWidget.
    • props.onSelectTarget (function) — Arms/clears the target view selection.
    • props.onNavigate (function) — Navigates to a view id (used by buttonList/buttonGrid).

RotateOverlay

Full-screen "please rotate the display" overlay. Stays mounted at all times (like Screensaver.jsx) so the opacity transition plays in both directions; visibility is toggled via CSS class rather than conditional rendering.

Shown whenever the current route/kiosk (useRequiredOrientation, services/orientation.js) expects a different orientation than the one the device is physically held in (useOrientation, hooks/orientation.jsx) - a route with no requirement (null) never shows it.

Screensaver

Full-screen overlay shown while the app is idle (see useScreensaver). Stays mounted at all times so the opacity transition plays both when fading in and when fading out; visibility is toggled via CSS class. Dismissing it needs no handler here - any interaction is already picked up by the global listeners in useIdle and flips isIdle back to false.

The video shown depends on defaultMode (config-schema.js): each presentation mode's own content file (see PRESENTATION_MODES in presentationModes.js, loaded per-route by ContentProvider) defines its own screensaver under "screensavers", keyed by that mode's key. In multi-app/ navbar mode (defaultMode "all") or for an unrecognized defaultMode value, no entry matches and no video is shown.

SlideNavigation

Fixed bottom navigation of the slide pages, with three modes:

  • closed: menu button + prev/next arrows (hidden entirely while the view has no adjacency, e.g. before content has loaded)
  • menu: full-width bar with Home / Screensaver / Apps / Slides / close
  • slides: same bar plus the full-screen SlidesOverlay

Parameters

  • props (Object)
    • props.prevViewId (string | null) — Target of the "back" arrow, disables it when null.
    • props.nextViewId (string | null) — Target of the "next" arrow, disables it when null.
    • props.homeViewId (string) — View the menu's Home button navigates to.
    • props.currentViewId (string) — Currently shown view (highlighted in the slides overlay).
    • props.onNavigate (function) — Navigates within the current app, keeping config params.

SlidePage

Shared skeleton of the slide-based presentation pages (ValueAdvisoryServices, RadEnablement): viewId routing, slide navigation, element-bucket layout and the content error/redirect states. The pages themselves only supply their constants, their CSS (via classPrefix) and an optional header.

Parameters

  • basePath (string) — route prefix, e.g. "/rad-enablement"
  • startViewId (string) — view shown at the bare route, e.g. "rad-intro"
  • storyHubViewId (string) — hub view (see getAdjacentRootViews), also the menu's Home target
  • classPrefix (string) — CSS class prefix, e.g. "rad" -> "rad-page", "rad-slide-content"
  • renderHeader (function, optional) — optional per-page header, returning a React node

SlidesOverlay

Full-screen overlay listing every slide of the loaded content file as a clickable thumbnail (from the view's optional thumbnail field, with a text placeholder as fallback), grouped by story. A toggle switch selects "All Slides" or a single story; it opens on the current view's story. Rendered by SlideNavigation in its "slides" mode.

Parameters

  • props (Object)
    • props.currentViewId (string) — View to highlight and to derive the initial story tab from.
    • props.onSelectSlide (function) — Called with the clicked slide's view id.

Avatar

Round avatar image, used for the portrait next to a Quote.

Parameters

  • props (Object)
    • props.src (string) — Image URL.
    • props.alt (string) — Alt text.

BodyText

Plain paragraph of body-sized text ("bodyText" element type) - an intro or description paragraph below a headline. Distinct from disclaimer (small, absolutely bottom-pinned legal print) and from headline (display-sized).

Parameters

  • props (Object)
    • props.text (string) — Paragraph text.

ButtonGrid

Grid of logo tiles ("buttonGrid" element type), e.g. partner institutions. Like ButtonList, clicking reports the target view id to the page instead of navigating directly.

Parameters

  • props (Object)
    • props.items (Array.<{content: {logo: string}, targetViewId: string}>) — One entry per tile.
    • props.onNavigate (function) — Called with the clicked tile's target view id.

ButtonList

Vertical list of navigation buttons ("buttonList" element type). Buttons don't navigate themselves - they report the chosen view id to the page.

Parameters

  • props (Object)
    • props.items (Array.<{content: {label: string}, targetViewId: string, icon: string}>) — One entry per button.
    • props.onNavigate (function) — Called with the clicked item's target view id.

Card

Simple text card with optional headline, body and footer line. Used as the detail popup of a Circle in the CircleInfographic.

Parameters

  • props (Object)
    • props.headline (string, optional) — Card headline.
    • props.text (string, optional) — Card body text.
    • props.underline (string, optional) — Small footer line below the body.

CardGrid

Stat tiles plus an optional highlight card ("cardGrid" element type), e.g. "20% perceived time savings" alongside a customer statement.

Parameters

  • props (Object)
    • props.stats (Array.<{value: string, label: string}>) — Stat tiles (value + caption).
    • props.highlight (Object | null) — Optional emphasized card.

ChartGrid

One or two chart/diagram images side by side, each with an optional caption above it ("chartGrid" element type). Portrait: stacks to 1 column.

Parameters

  • props (Object)
    • props.items (Array.<{title: (string|null), image: string}>) — 1-2 chart entries.

CircleChain

N labeled circles overlapping in a horizontal row ("circleChain" element type), brand-gradient colored left to right.

Parameters

  • props (Object)
    • props.items (Array.<{text: string}>) — Circles, left to right.

Circle

One selectable circle of the CircleInfographic. Toggles its detail Card on tap and closes on tap-outside.

Parameters

  • props (Object)
    • props.text (string) — Label inside the circle.
    • props.color ("black" | "blue" | "white" | "orange") — Color/position variant class.
    • props.card (Object) — Detail card content.
    • props.icons (Array.<{small: string, big: string}>) — Orbiting IconBubbles definitions.
    • props.handleCircleSelect (function) — Notifies the parent to blur the other circles.
    • props.close (function) — Notifies the parent to lift the blur again.

CircleInfographic

Interactive four-circle service infographic ("circleInfographic" element type): tapping a circle opens its detail Card and blurs the rest. Expects exactly four entries; render order is fixed to match the layout.

Parameters

  • props (Object)
    • props.circle (Array.<{text: string, icons: Array.<{small: string, big: string}>, card: {headline: (string|null), text: (string|null), underline: (string|null)}}>) — The four circle definitions.
    • props.headline (string) — Label shown in the center of the ring.

Disclaimer

Small-print legal/disclaimer line of a slide ("disclaimer" element type).

Parameters

  • props (Object)
    • props.text (string) — Disclaimer text.

Headline

Semantic heading with app-wide typography classes. Renders the content JSON's "headline" (level 2) and "subheadline" (level 3) element types, and is used directly for page headers.

Parameters

  • props (Object)
    • props.text (string) — Heading text.
    • props.level (number, optional, default: 1) — Heading level 1-6, controls both tag (h1-h6) and size class.
    • props.color ("white" | "orange", optional, default: "\"white\"") — Color variant class.

IconBubbles

Decorative pair of icon bubbles (one big, one small) orbiting a Circle in the CircleInfographic.

Parameters

  • props (Object)
    • props.big (string) — Icon URL for the big bubble.
    • props.small (string) — Icon URL for the small bubble.

IconWheel

N icon nodes with text labels evenly spaced around a decorative ring ("iconWheel" element type) - unlike CircleInfographic/SelectWidget, purely decorative and non-interactive.

Parameters

  • props (Object)
    • props.items (Array.<{icon: string, label: string}>) — Ring nodes.

ImageCard

Card with an image and/or caption text. Rendered by ImageCardGrid.

Parameters

  • props (Object)
    • props.image (string, optional) — Image URL.
    • props.text (string, optional) — Caption text.

ImageCardGrid

Grid of ImageCards ("imageCardGrid" element type), e.g. product screenshots with captions.

Parameters

  • props (Object)
    • props.items (Array.<{image: (string|null), text: (string|null)}>) — One entry per card.

InstitutionBadge

Country flag + institution logo pair ("institutionBadge" element type), shown on the "Discover real-world impact" slides.

Parameters

  • props (Object)
    • props.flag (string) — Flag image URL.
    • props.logo (string) — Institution logo URL.

ProcessFlow

N flat step images (photo/mockup with title+bullets already baked in) connected by arrows ("processFlow" element type).

Parameters

  • props (Object)
    • props.items (Array.<{image: string}>) — Steps, left to right.

Quote

Single quote row: avatar plus headline and quote text. Rendered by QuoteList.

Parameters

  • props (Object)
    • props.item (Object) — Quote content.

QuoteList

Stack of customer quotes ("quoteList" element type).

Parameters

  • props (Object)
    • props.items (Array.<{content: {headline: string, icon: string, text: string}}>) — One entry per quote.

SelectWidget

Circular story picker ("selectWidget" element type): options are spread evenly around a ring; selecting one shows its title in the center and arms the page's "next" navigation (it does not navigate by itself).

Parameters

  • props (Object)
    • props.options (Array.<{id: string, text: string, icon: string}>, optional) — Selectable options; id is a view id.
    • props.orientation ("portrait" | "landscape", optional, default: "\"portrait\"") — Ring/item sizing preset (from the content JSON).
    • props.selectedId (string | null) — Currently selected option id.
    • props.onSelect (function) — Called with the tapped option's id.

StepTracker

Horizontal dot progress indicator ("stepTracker" element type): one circle per step, connected by a line, the current step filled solid.

Parameters

  • props (Object)
    • props.total (number) — Total number of steps.
    • props.current (number) — Current step, 1-based.

StoryTitle

Full-bleed story opener ("storyTitle" element type): big title over an optional background artwork.

Parameters

  • props (Object)
    • props.title (string) — Story title text.
    • props.background (string, optional) — Background image URL.

TextMediaWidget

Media block with an accompanying text box ("textMediaWidget" element type). Shows an image or a (service-worker-cacheable) video, plus optional text.

Parameters

  • props (Object)
    • props.image (string | null) — Image URL; mutually exclusive with video in practice.
    • props.video (string | null) — Video URL, played via CacheableVideo.
    • props.text (string | null) — Text shown below the media.

useIdle

Parameters

  • idleTime (number) — Time in ms of inactivity after which isIdle becomes true.

Returns

  • Objecttrigger is the event type that ended the last idle period ("init" on first mount), and is reset to null once idle again - useful for debugging what woke the app up. forceIdle shows the idle state immediately, without waiting for the timeout.

useOrientation

Returns

  • "landscape" | "portrait" — The current viewport orientation, kept in sync live as the device is rotated/resized.

AppSelectionPage

Landing screen at "/": one tile per presentation mode (see PRESENTATION_MODES). Also the target of the idle session reset and of the menu's "Apps" button.

RadEnablementPage

"RadEnablement Services" presentation app - the shared SlidePage plus a persistent RadHeader (content: public/data/rad-content.json).

ValueAdvisoryServicesPage

"Value Advisory Services" presentation app - the shared SlidePage plus a persistent per-story icon badge (content: public/data/vas-content.json).

VasHeader

Persistent per-story icon badge shown top-right on every VAS slide of a story except its own storyTitle cover (which already fills the screen). Unlike RAD, VAS views author their own headline text per view (there is no app/story-wide title to repeat) - only the story icon is a constant, from stories..header.icon in vas-content.json.

Parameters

  • props (Object)
    • props.viewId (string) — Currently shown view id.

ValuePartnershipPage

"Value Partnership" presentation app - placeholder page until its content exists. Only functional element is the fixed "Apps" button back to "/".

CONFIG_SCHEMA: Array.<{key: string, source: string, name: string, type: string, default: *, min: number, description: string}>

Declares every kiosk/device config value the app understands. Values come from URL params (source "param", read live by useConfig in config.jsx and kept alive across navigation), each with type, default and a German description shown in admin/debug contexts.

useConfig

React hook that resolves every entry in CONFIG_SCHEMA (config-schema.js) against the current URL search params / import.meta.env and returns them as a flat, typed { key: value } object.

Returns

  • Object — Config values keyed by their CONFIG_SCHEMA key.

ContentContext

Context carrying { content, views, stories, error, getView, getAdjacentRootViews } - consume via useContent.

useContent

React hook to access the loaded content object. Returns {} until the content.json fetch in ContentProvider has resolved.

RETRY_DELAY_MS

Resolves the content file for the current route, fetches it (once per file - already-fetched files are served from an in-memory cache so switching between apps doesn't refetch) and makes it available to all descendants via ContentContext. On fetch failure, content stays {}, the failure is exposed as error (pages show a visible message instead of a blank screen) and the fetch is retried until it succeeds.

useRequiredOrientation

Returns

  • "landscape" | "portrait" | null — The orientation the current route (optionally overridden by deviceType) expects, or null if the route has no orientation requirement.

PRESENTATION_MODES: Array.<{key: string, label: string, path: string, contentFile: (string|null), orientation: ('landscape'|'portrait')}>

Single source of truth for the 3 presentation modes/sales apps. key doubles as the valid defaultMode config value (config-schema.js) and as the route path segment (see Routes.jsx, AppSelection.jsx). contentFile is the JSON this mode's route loads via ContentProvider (services/content.jsx); null means the page doesn't fetch any content (yet). orientation is the physical device orientation this app's kiosk layout is built for - read by useRequiredOrientation (services/orientation.js) to decide when to show the RotateOverlay; the deviceType config value (config-schema.js) can override it per kiosk.

ScreensaverProvider

Tracks idle state and exposes it via ScreensaverContext.

useScreensaver

React hook to access { isIdle, trigger, screensaverFadeDuration, showNow }. Must be used within a <ScreensaverProvider>.

TabProvider

Provides openTab/closeTab (see useTabs) to the component tree, tracking open external tabs/windows per URL.

useTabs

React hook to access openTab/closeTab. Must be used within a <TabProvider>.

GeneralPageTracking

Invisible helper mounted next to the routes (see Routes.jsx): keeps document.title in sync with the current route and, when VITE_MATOMO_ENABLE_ROUTER_PAGE_TRACKING is "true", reports every route change as a Matomo pageview.

parseConfigValue

Parses and validates a single raw config value against its schema definition.

Parameters

  • rawValue (string | null | undefined) — The raw value as read from searchParams.get(...) or import.meta.env[...]. Always a string when set.
  • definition (Object) — The matching entry from CONFIG_SCHEMA.
    • definition.type ("boolean" | "number" | "string") — How to interpret rawValue.
    • definition.default (*) — Value to use when rawValue is missing/invalid.
    • definition.min (number, optional) — Only for type "number": reject values below this.
    • definition.max (number, optional) — Only for type "number": reject values above this.
    • definition.key (string) — Config key name, used only for warning messages.

Returns

  • * — The parsed value, or definition.default if rawValue was empty or failed validation.

Navigates with a native View Transition cross-fade. react-router's own viewTransition navigate option only works with the data router (createHashRouter/RouterProvider) - this app uses the plain declarative /, so the native API is driven manually. flushSync forces the DOM update to happen synchronously inside the callback, which the API requires.

Callers are responsible for keeping the current query string alive (kiosk/device config, see config-schema.js) by including it in path.