@wheelhouse/embed
v0.3.1
Published
```sh npm i @wheelhouse/embed ```
Keywords
Readme
Wheelhouse Embed Library
Installation
npm i @wheelhouse/embedPeer dependencies
Outside of the library's api and types exports, peer dependencies are required.
The host application must install compatible versions of several packages alongside @wheelhouse/embed. They are declared as peers (not bundled inside this package) so you get one shared instance of React, TanStack Query, and i18next. If the library shipped its own copies, you could end up with multiple React trees, separate QueryClient instances (broken cache and hooks), or separate i18n instances (wrong translations).
Exact semver ranges live in package.json under peerDependencies. Some peers are also marked optional there so non-React or types-only installs are not forced to pull them in; when you need a package for your integration is separate from that npm flag—use the table below.
| Package | When you need it |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| react | Any React usage: DataProvider, ListingProvider, UIProvider, hooks, or @wheelhouse/embed/react or @wheelhouse/embed/react/ui. |
| @tanstack/react-query | DataProvider, exported TanStack query/mutation hooks, or anything under ListingProvider (it assumes DataProvider above it). Not required for types-only or non-React consumers. |
| react-dom | Only when using UIProvider and components from @wheelhouse/embed/react/ui (DOM/CSS UI). Not required for DataProvider, ListingProvider, or headless hooks alone—those only need react. |
| i18next | Only when using UIProvider from @wheelhouse/embed/react/ui. Not required for DataProvider or ListingProvider alone. |
| react-i18next | Only when using UIProvider. Pairs with i18next for the UI bundle. |
Typical React app with data + UI:
npm i @wheelhouse/embed react react-dom @tanstack/react-query i18next react-i18nextUse version ranges from peerDependencies. If you use TanStack Query in your host app, use the same package and wire QueryClientProvider (or equivalent) so the app and the embed resolve one client.
Basic Usage
| Exports | Import Path | Includes CSS? | Use Case | Dependencies |
| ------------------- | ---------------------------- | ------------- | ------------------------------------------------- | ------------------------------- |
| TypeScript types | @wheelhouse/embed/types | ❌ | Type declarations only | None |
| API fetches | @wheelhouse/embed/api | ❌ | API helpers | types |
| React logic (no UI) | @wheelhouse/embed/react | ❌ | Data, hooks, state mgmt, logic, bring your own UI | types, api (core in the future) |
| React Components | @wheelhouse/embed/react/ui | ✅ | UI Components | types, api, react |
| Web Components | @wheelhouse/embed/wc | ✅ | Native web component wrappers (future) | types, api, react, react/ui |
Authentication & Data
To make secure authenticated calls to the Wheelhouse API, three things are needed:
- Integrations API key (server)
- User API key (server, per user)
- Access token (client)
Only the access token should be sent down to the client, which gets used to make calls directly to the WH API from the browser.
To exchange the two server keys for an auth token, a secure server-to-server call needs to be made. This looks something like the following.
The nonce is a random string that needs to be generated in the browser and utilized on subsequent requests with the access token.
// on your server behind an endpoint that the browser library can reach
const getAccessToken = async (nonce: string): Promise<AccessTokenResponse> => {
const response = await fetch('https://app.usewheelhouse.com/api/v1/edge_embed/token', {
method: 'POST',
headers: {
Accept: 'application/json',
'X-Integration-Api-Key': process.env.WHEELHOUSE_INTEGRATION_API_KEY,
'X-User-Api-Key': userApiKey,
'X-Embed-Api-Nonce': nonce,
},
});
if (!response.ok) {
throw new Error('Failed to get access token');
}
return response.json() as unknown as AccessTokenResponse;
};With React, it looks like the following. The DataProvider will generate the nonce, and it will utilize the returned access token to make subsequent API calls.
// fetchAccessToken is a call to your server that ends up calling something like getAccessToken above
<DataProvider getAccessToken={fetchAccessToken}>{children}</DataProvider>Expiration / Invalidated Tokens
If the token is expired or invalidated, a new one must be obtained. The library will automatically call the function provided to the getAccessToken prop in an attempt to obtain a new token.
@wheelhouse/embed/react
These components can be used to manage data access and listing state management alongside your own React components.
DataProvider
Provides access to and management of Wheelhouse API data and caching. Required for usage with React components in @wheelhouse/embed/react/ui, or your own custom components using this library's React query and mutation hooks.
The context value can be obtained importing the useDataContext hook from @wheelhouse/embed/react.
React Query and Mutation Hooks
Exports of query hooks and mutations (Tanstack Query) are made available (must be used with a DataProvider).
This library's UI components have a dependency on these, but they can also be used directly for implementing custom UI.
ListingProvider
Utilities for fetching and updating listing settings, as well as previewing changes on the pricing chart. Required for listing specific React components in @wheelhouse/embed/react/ui.
The useListingProvider hook can be used when implementing your own React UI.
See Storybook for more information and usage.
@wheelhouse/embed/react/ui
The React UI components. See Storybook for complete information and usage.
Translations
All UI text comes from the language prop on UIProvider. English (en) and German (de) are built in. To change some of the text, spread the built-in resource and override the keys you need:
import { UIProvider, en, type LanguageConfig } from '@wheelhouse/embed/react/ui';
const language: LanguageConfig = { code: 'en', resource: { ...en.resource, minimum_stays: 'Minimum Nights' } };
<UIProvider language={language}>{children}</UIProvider>;See UIProvider's "Internationalization" section in Storybook for adding a language, finding keys, plurals, and hiding help text.
Theming & Customization
Components can be restyled in exactly two ways: (1) colors and semantic values via UIProvider's themeOverrides (--wh-* CSS variables), and (2) everything else (layout, spacing, borders, state) via documented data-slot attributes targeted with ordinary CSS — no !important required, regardless of your styling stack. See UIProvider's "Styling" section and each component's own "Customization" section in Storybook for the full guide.
Pricing chart series renames
Two PricingChart series were renamed to match the Wheelhouse series catalog used by the in-app pricing chart:
| Old | New | Legend label |
| ------------------------------------ | ------------------------------- | -------------------- |
| PricingChart.RecommendedPrices | PricingChart.AskingRatePrices | Prices (Asking Rate) |
| PricingChart.CurrentSettingsPrices | PricingChart.PreviewPrices | Prices (Preview) |
The old component names still work as deprecated aliases and will be removed in the next major version. Their
CSS variables were renamed to match (--asking-rate-prices-color, --preview-prices-color); the old variable
names are still read as a fallback, so existing overrides keep working.
Neither rename changes what data a series fetches or displays — both keep the same endpoint and response field.
Several series changed only their legend label, with no change to the component name, props or data: Bookings is
now "Bookings (This Year)", BookingsLastYear is "Bookings (Last Year)", ObservedPricesLastYear is
"Prices (Last Year, Observed)", BookingBands is "Nights (Booked)" and BlockedBands is "Nights (Blocked)". The
chart header's "Booked Days" / "Blocked Days" metrics are unchanged.
Running Example Apps
export WHEELHOUSE_ACCESS_TOKEN="your_access_token_here" WHEELHOUSE_LISTING_ID="123"
npm run examples # development build
npm run examples:preview # production build
# OR
WHEELHOUSE_ACCESS_TOKEN="your_access_token" WHEELHOUSE_LISTING_ID="123" npm run examplesNote that these example apps do not hot-reload changes to the embed package, they must be rebuilt.
LLMs
For LLM context, see llms.txt.
