@revenera/swm-dm-ui
v1.0.5
Published
Dynamic Monetization UI Component Library
Downloads
975
Readme
Dynamic Monetization UI
Dynamic Monetization UI is a React component library with TypeScript support that primarily exposes ready-to-use UI pages for embedding into other applications via npm.
Under the hood, Dynamic Monetization UI uses Material UI (MUI v6) as its component library and theming foundation. For more information, see the official MUI v6 documentation: https://v6.mui.com
Dynamic Monetization UI includes a full development setup with Vite, Storybook, Jest, Husky, and i18n, enabling easy development, testing, and documentation of components.
Contents
- How to use Dynamic Monetization UI in your React application
- Dynamic Monetization UI Library development
How to use Dynamic Monetization UI in your React application
Install the package
npm install @revenera/swm-dm-uiInstall peer dependencies
If you do not already have compatible versions of the peer dependencies (such as React or MUI v6) installed in your project, install them along with the library:
npm install "react@^18.0.0 || ^19.0.0" "react-dom@^18.0.0 || ^19.0.0" @mui/material@^6.4.0 @mui/icons-material@^6.4.0 @mui/x-date-pickers@^7.23.0 @emotion/react@^11.0.0 @emotion/styled@^11.0.0 dayjs@^1.11.0 axios@^1.12.2 yup@^1.0.0 formik@^2.4.6 i18next@^25.6.0 react-i18next@^16.2.4If you already have compatible versions of some dependencies (for example, if your app already uses MUI v6), you can omit them from the install command:
Supported versions
| Package | Supported Versions | | ------------------- | ------------------ | | react | ^18.0.0 or ^19.0.0 | | react-dom | ^18.0.0 or ^19.0.0 | | @mui/material | ^6.4.0 | | @mui/icons-material | ^6.4.0 | | @mui/x-date-pickers | ^7.23.0 | | @emotion/react | ^11.0.0 | | @emotion/styled | ^11.0.0 | | dayjs | ^1.11.0 | | axios | ^1.12.2 | | yup | ^1.7.1 | | formik | 2.4.6 | | i18next | ^25.6.0 | | react-i18next | ^16.2.4 |
Basic implementation
The basic implementation provides an out-of-the-box, ready-to-use solution with:
- Default localization (for example,
en) and built-in i18n support - Default styling/theme, so pages render correctly without additional UI setup
- A complete customer journey for the selected flow (for example, Rate Tables or Instances), packaged as a single embeddable React component
DM Rate Table App
DMRateTableApp provides the complete Rate Table management experience, including:
- Rate Table list/management
- View Rate Table
- Create Rate Table
Embed it as a single component:
import React from 'react';
import { DMRateTableApp } from '@revenera/swm-dm-ui';
export default function App() {
return (
<DMRateTableApp
bearerToken="YOUR_BEARER_TOKEN"
baseApiUrl="YOUR_DM_DATA_URL"
isProducer={true}
/>
);
}DMRateTableApp supported props
| Prop | Type | Required | Description |
| -------------- | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| baseApiUrl | string | Yes | Base API URL for Dynamic Monetization (example: https://example.com/your-dynamic-monetization-api-url). |
| bearerToken | string | Yes | Bearer token used to authorize API requests. |
| isProducer | boolean | Yes | Enables producer-mode behavior where applicable. |
| locale | string | No | Locale used for i18n (default: "en"). |
| apiUrl | string | No | Relative API path for the page (default: "/rate-tables"). If an absolute URL is provided, it will be used as-is for that component. |
| i18Resources | Record<string, any> | No | Consumer provided translations, if provided it will override the default |
DM Instances App
DMInstancesApp provides the complete Instances experience, including:
- Instances list
- Instance details overview
- Instance details line items
Embed it as a single component:
import React from 'react';
import { DMInstancesApp } from '@revenera/swm-dm-ui';
export default function App() {
return <DMInstancesApp bearerToken="YOUR_BEARER_TOKEN" baseApiUrl="YOUR_DM_DATA_URL" />;
}DMInstancesApp supported props
| Prop | Type | Required | Description |
| ------------------- | -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| baseApiUrl | string | Yes | Base API URL for Dynamic Monetization (example: https://example.com/your-dynamic-monetization-api-url). |
| bearerToken | string | Yes | Bearer token used to authorize API requests. |
| instancesApiUrl | string | No | Relative API path for listing instances (default: "/instances"). |
| lineItemsApiUrlFn | (instanceId: string) => string | No | Function that returns the relative API path for an instance’s line items (default: (id) => `/instances/${id}/line-items` ). |
| overviewApiUrlFn | (instanceId: string) => string | No | Function that returns the relative API path for an instance overview/details (default: (id) => `/instances/${id}` ). |
| locale | string | No | Locale used for i18n (default: "en"). |
| i18Resources | Record<string, any> | No | Consumer provided translations, if provided it will override the default |
End Customer Instance App
DMEndCustomerInstanceApp provides an end-customer view of a single instance.
Embed it as a single component:
import React from 'react';
import { DMEndCustomerInstanceApp } from '@revenera/swm-dm-ui';
export default function App() {
return <DMEndCustomerInstanceApp bearerToken="YOUR_BEARER_TOKEN" baseApiUrl="YOUR_DM_DATA_URL" />;
}DMEndCustomerInstanceApp supported props
| Prop | Type | Required | Description |
| ----------------- | ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| baseApiUrl | string | Yes | Base API URL for Dynamic Monetization (example: https://example.com/your-dynamic-monetization-api-url). |
| bearerToken | string | Yes | Bearer token used to authorize API requests. |
| lineItemsApiUrl | (id: string) => string | No | Function that returns the relative API path for the instance’s line items (default: (id) => `/instances/${id}/line-items` ). |
| pageTitle | string | No | Optional page title override displayed by the page. |
| locale | string | No | Locale used for i18n (default: "en"). |
| i18Resources | Record<string, any> | No | Consumer provided translations, if provided it will override the default |
Customization
If you need more control over styling, routing, composition, or API endpoint configuration than the single “App” components provide, instead of embedding a full flow (DMRateTableApp, DMInstancesApp, etc.), you can embed smaller root and page-level building blocks and configure them inside your application (for example, under your own MUI theme, routes, layouts, authentication, and navigation).
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import { ThemeProvider, CssBaseline } from '@mui/material';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import {
DMTheme,
useBearerToken,
useApiConfig,
DMRateTableRoot,
DMLibraryTranslations,
DMRateTableCreate,
DMRateTableForm,
DMViewRateTables,
DMInstancesRoot,
DMViewInstances,
DMInstanceDetails,
DMEndCustomerInstanceDetails,
} from '@revenera/swm-dm-ui';
import i18n from 'i18next';
import { initReactI18next, I18nextProvider } from 'react-i18next';
import dayjs from 'dayjs';
const DATA_URL = 'YOUR_DATA_URL';
const BEARER_TOKEN = 'YOUR_BEARER_TOKEN';
i18n.use(initReactI18next).init({
resources: {
en: { translation: DMLibraryTranslations.en },
fr: { translation: DMLibraryTranslations.fr },
},
lng: 'en',
fallbackLng: 'en',
interpolation: { escapeValue: false },
});
// Example of adding a custom translation key
i18n.addResource('en', 'translation', 'dm.rateTableView.heading', 'Custom Header');
function DMShell({ children }: { children: React.ReactNode }) {
// Set the bearer token in the context so that it can be used by DM components
const { setBearerToken } = useBearerToken();
// Set the base API URL in the context so that it can be used by DM components
const { setBaseApiUrl } = useApiConfig();
setBearerToken(BEARER_TOKEN);
setBaseApiUrl(DATA_URL);
//You can replace DMTheme with your custom MUI theme that extends DMTheme
//to ensure compatibility with DM components while applying your own styling.
return (
<I18nextProvider i18n={i18n}>
<ThemeProvider theme={DMTheme}>
<CssBaseline />
<LocalizationProvider dateAdapter={AdapterDayjs}>{children}</LocalizationProvider>
</ThemeProvider>
</I18nextProvider>
);
}
export default function App() {
return (
<DMShell>
<Routes>
<Route
path="rate-table-root"
element={<DMRateTableRoot apiUrl="/rate-tables" isProducer={true} />}
/>
<Route
path="rate-table-view"
element={
<DMViewRateTables
apiUrl="rate-tables"
isProducer={true}
onCreateClick={() => alert('Create clicked!')}
onView={() => alert('View clicked!')}
onCopy={() => alert('Copy clicked!')}
/>
}
/>
<Route
path="rate-table-create"
element={
<DMRateTableCreate
apiUrl="rate-tables"
afterSaveAction={() => alert('Rate table created!')}
onCancelAction={() => alert('Cancelled')}
/>
}
/>
<Route
path="rate-table-form"
element={
<DMRateTableForm
heading="Test Heading"
isEditable={true}
initialValues={{
series: 'Test Series',
effectiveFrom: dayjs(),
version: '1.0',
items: [{ name: 'Item 1', version: '1.0', rate: 100 }],
}}
onSubmit={() => alert('Submitted!')}
onCancel={() => alert('Cancelled')}
onBack={() => alert('Back!')}
loading={false}
error=""
saving={false}
/>
}
/>
<Route
path="instances-root"
element={
<DMInstancesRoot
instancesApiUrl="/instances"
lineItemsApiUrlFn={(instanceId) => `/instances/${instanceId}/line-items`}
overviewApiUrlFn={(instanceId) => `/instances/${instanceId}`}
/>
}
/>
<Route
path="instances-view"
element={
<DMViewInstances
isProducer={true}
apiUrl="/instances"
onCreateClick={() => alert('Create instance clicked!')}
onInstanceIdClick={({ instanceId }) => alert(`Instance ${instanceId} clicked!`)}
/>
}
/>
<Route
path="instances-details"
element={
<DMInstanceDetails
onBackToList={() => alert('Back to list!')}
overviewApiUrl="/instances/instance-id-123"
lineItemsApiUrl="/instances/instance-id-123/line-items"
initialTab={0}
hasBackLink={true}
pageTitle="Instance Details"
isProducer={true}
/>
}
/>
<Route
path="end-customer-instance-details"
element={
<DMEndCustomerInstanceDetails
lineItemsApiUrl={(instanceId) => `/instances/${instanceId}/line-items`}
bearerToken={BEARER_TOKEN}
pageTitle="End Customer Instance Details"
/>
}
/>
</Routes>
</DMShell>
);
}DMProvider
DMProvider is a context provider that can be used to wrap your page component and supply the default context for DM components. It includes API configuration (base URL and bearer token), DMTheme, localization settings, and i18n translations.
import React from 'react';
import { DMRateTableRoot, DMProvider } from '@revenera/swm-dm-ui';
const DATA_URL = 'YOUR_DATA_URL';
const BEARER_TOKEN = 'YOUR_BEARER_TOKEN';
export default function App() {
return (
<DMProvider locale={'en'} baseApiUrl={DATA_URL} bearerToken={BEARER_TOKEN}>
<DMRateTableRoot apiUrl="/rate-tables" isProducer={true} />
</DMProvider>
);
}How to set base api url and pass apiUrl in components?
To handle api url effectively, base api url can be set once while loading your app (see example above), and then in individual components, only relative path can be passed (in apiUrl prop). Please check the above example demonstrating the same.
Note: If an absolute url is passed in any individual component in apiUrl prop (example: apiUrl="https://example.com/dynamicmonetization/v1/api/rate-tables"), then the absolute url will be picked entirely for that component.
Dynamic Monetization UI Library development
This repository contains the source code for the Dynamic Monetization UI component library, including tooling for local development, testing, and documentation.
Tech stack
React + TypeScript + Vite
Components are built with React and TypeScript. Vite is used for local development and library builds.Storybook
Storybook is used to develop, test, and preview components/pages in isolation.Jest + React Testing Library
Automated tests are written with React Testing Library and executed with Jest.Material UI (MUI v6)
The UI is built on top of Material UI v6 and its theming system.i18n (i18next + react-i18next)
The library supports localization via i18next and react-i18next (and ships default translation resources).Git hooks (Husky)
Husky is used to run checks automatically during development (for example, before commits/pushes).
Local setup
Clone the repository.
Install dependencies from the repository root:
npm installRun Storybook to develop and preview components/pages in the browser:
npm run storybook
Components (adding a new component)
To add a new component (for example, a button), create a new folder under src/components:
src/components/DMButton/
Recommended files:
DMButton.tsx— component implementationDMButton.styles.ts— styles/theme helpers (if applicable)DMButton.test.tsx— unit/integration tests (Jest + React Testing Library)DMButton.stories.tsx— Storybook stories
Naming convention: prefer PascalCase for component names and file names (for example,
DMButton.stories.tsx).
Testing
Run the unit/integration test suite:
npm run testRun Storybook for manual testing and visual review:
npm run storybook
