@munichremarkets/interactive-factsheet
v9.1.0
Published
Downloads
609
Readme
Munich Re Markets Interactive Factsheet Widget
This package provides the Interactive Factsheet widget by Munich Re Markets for integration into your website.
Installation
If you use NPM as a package manager, run
npm install --save @munichremarkets/interactive-factsheet
And if you use Yarn:
yarn add @munichremarkets/interactive-factsheet
Integration
The Interactive Factsheet widget provides a (plain JavaScript) rendering API in the form of the renderInteractiveFactsheet
function
that is used to display the widget on the page and pass data to the widget.
Importing from NPM
The Interactive Factsheet package contains JavaScript (ES5) code in the ECMAScript module format, so you need to use a bundler that supports this format, such as Webpack or Rollup. Using ES6-style imports, your code might look like this:
import { renderInteractiveFactsheet } from '@munichremarkets/interactive-factsheet';
TypeScript declaration files (.d.ts
) are also included in the package, providing typings and enhanced IDE support for
the rendering API.
Rendering the widget
In order to render the widget, you need to invoke the renderInteractiveFactsheet
rendering function that is made available as
described above. The following data needs to be provided when invoking the rendering function:
- A target DOM element (typically a
<div>
element) into which the widget should be rendered - A configuration object providing data to the widget, see section "Configuring the widget" below
For example, a call to the rendering function might look like this (ES6):
const target = document.getElementById('widget-target');
renderInteractiveFactsheet(target, {
/* configuration data, see below */
});
Please make sure to invoke the rendering function after the DOM has been loaded, e.g. by putting the call into
a <script>
tag at the end of the <body>
or into a DOMContentLoaded
event handler.
Note
You need to make sure that the process.env
object is available at runtime and contains a NODE_ENV
property defining the current environment, see
the Node.js documentation. Note that it is not enough to just replace
process.env.NODE_ENV
, but you need to replace process.env
as a whole. Depending on your bundler, you can use these tools:
- For Webpack, use the DefinePlugin:
new webpack.DefinePlugin({
'process.env': JSON.stringify({ NODE_ENV: process.env.NODE_ENV }),
});
- For Vite, use the define config option:
defineConfig({
// ...
define: {
'process.env': JSON.stringify({ NODE_ENV: process.env.NODE_ENV }),
},
});
Warning: Do not use JSON.stringify(process.env)
as this may leak other environment variables into your bundle.
Unmounting the widget
The rendering function returns a cleanup function that can be used to unmount the widget like this:
const target = document.getElementById('widget-target');
const unmountWidget = renderInteractiveFactsheet(target, {
/* configuration data, see below */
});
/* use `unmountWidget` e.g. in an event listener */
Configuring the widget
The configuration object passed to renderInteractiveFactsheet
can contain the following properties (example values):
{
// Whether to include widget-scoped Bootstrap 4.x CSS into the page
// Optional, default: false
// Set this to `true` if you are not already using Bootstrap on your website
includeBootstrap4Css: true,
// Base URL of index data backend
// Optional, default: 'https://data.munichremarkets.com/indexdata'
// May optionally end in '/'
backendBaseUrl: 'https://some-url',
// Locale to use for localized texts
// Mandatory
// Currently available locales: Locale.DeDe, Locale.EnUs
locale: Locale.DeDe,
// Configuration object for configuring the Matomo tracking of the widget
// Optional
internalTrackingConfiguration: {
// Site ID to be used for Matomo tracking if enabled (see `trackingEnabled` option)
// Mandatory
trackingSiteId: '1',
// Whether Matomo tracking is enabled
// Optional, default: false
// If set to false, no requests will be sent to Matomo
trackingEnabled: true,
},
// Configuration object for configuring whether and how tracking events should be provided to the host website
// Optional - if not specified, no data is provided to your website
externalTrackingConfiguration: {
// Size of the batches of events to emit at once
// Optional, default: 10
eventQueueSize: 10,
// Function to be invoked for each batch of events
// Also invoked on the window event 'beforeunload' with all events still in the queue
// For the structure of each event, see example events below
// Optional - if not specified, no events are emitted
onTrackEvents: events => console.log(events),
},
// A token provided in JWT (JSON Web Token) format (see https://jwt.io).
// The token is required for rendering the widget and permits access to the index data backend.
// Mandatory
jwt: '<some-token>',
// Custom texts per locale
// Optional - if not specified, default texts are used
textOverrides: {
'widgets.interactiveFactsheet.title': {
// Texts can be provided in any supported locale (see `locale` option)
[Locale.DeDe]: 'Auswahl der Anlagestrategie – Gothaer GarantieRente Index',
[Locale.EnUs]: 'Choose your strategy - Gothaer GuaranteePension Index',
},
},
// URL or data-URL of a company logo in the print view
// Optional - if not specified, no logo is rendered in the print view
companyLogoUrl:
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICAgIDx0ZXh0IHg9IjAiIHk9IjQwIiBmaWxsPSJ3aGl0ZSI+SnVzdCBhbiBleGFtcGxlPC90ZXh0Pgo8L3N2Zz4=',
// Defines which mode of the widget is displayed
// Mandatory
// Currently available modes: 'interactiveFactsheet', 'indexManager', 'oneIndex'
mode: 'interactiveFactsheet',
// Array of indices to show
// Mandatory if the interactiveFactsheet or indexManager mode is selected
// Note that there is no upper bound on the number of indices, but there needs to be at least one.
indices: [
{
// UUID of index
// Mandatory
// Must be one of the UUIDs returned by the index data backend
uuid: '0b7ac102-a355-448e-b0c1-fd11b41efb2a',
// URL or data-URL of an image
// Mandatory
imageUrl:
'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICAgIDx0ZXh0Pkp1c3QgYW4gZXhhbXBsZTwvdGV4dD4NCjwvc3ZnPg==',
},
],
// Array of preselected indices
// It is possible to select up to two indices
// Mandatory if the indexManager mode is selected
selectedIndices: [
{
// Uuid of the index
// Mandatory
// Must be included in indices
uuid: '0b7ac102-a355-448e-b0c1-fd11b41efb2a',
// Share of the index, from 0 to 1
// Mandatory
// The sum of all shares must add up to 1
share: 1,
},
],
// Whether to disallow the combination of multiple indices
// Optional, default: false, only available if interactiveFactsheet mode is selected
// When `true`, only one of the given indices can be selected
disableIndexCombination: true,
// Callback to be invoked when the widget's workflow is finished and selection is confirmed
// Mandatory if the indexManager mode is selected
// Arguments:
// * `items` (mandatory): list of indices contained in the new strategy like this:
// [
// {
// // UUID of the index
// uuid: '0b7ac102-a355-448e-b0c1-fd11b41efb2a',
//
// // Share of the index within the strategy, from 0 to 1
// // The sum of all shares must add up to 1
// share: 0.4
// },
//
// {
// uuid: '8c5e7108-c595-4645-a6f4-8b36b6695585',
// share: 0.6
// }
// ]
onConfirmSelection: indicesWithShares => console.log(indicesWithShares),
// Uuid of the index to be displayed in the oneIndex mode
// Mandatory if mode the oneIndex mode is selected
indexUuid: '0b7ac102-a355-448e-b0c1-fd11b41efb2a',
}
The following things should be considered in order to ensure that the widget works as intended.
Note: Providing data that does not adhere to the documented API of the widget may lead to unexpected behavior or the widget not working altogether.
Text override mechanism
Some texts that are displayed by the widget can be overridden by providing the textOverrides
option in the
configuration object. It expects an object in the form of
{
'some.overridable.key': {
[Locale.DeDe]: 'Some German text',
[Locale.EnUs]: 'Some English text (US)',
[Locale.EnGb]: 'Some English text (GB)',
},
'some.other.key': { /* ... */ }
}
where some.overridable.key
is a localization key specified by the widget.
Note: The override mechanism is entirely optional. If it is omitted, default texts are used instead.
Semantic markup
Some texts can contain basic semantic HTML markup that is sanitized before displaying. The following tags are allowed
and will be displayed as bold, italic, underlined, etc.: strong
, b
, em
, i
, u
, br
, p
.
Note: HTML tags cannot contain attributes. If provided anyway, they are removed during sanitization (
e.g. <em class="some-classname">some text</em>
will be converted to <em>some text</em>
).
Interpolation
In some cases, texts might need to include dynamic values (e.g. monetary values or percentages). Such values can be
referenced in the text using {{someVariable}}
, where someVariable
is a predefined name specific to the respective
text key and will be replaced with the actual value during runtime.
Empty default text
In some cases default texts might be empty, which will cause the enclosing markup element (e.g. an information icon with accompanying text label) to purposefully not be displayed in the widget. This is a mechanism to remove markup elements entirely when the text that they usually display is missing. In these cases, a text override can be supplied to make the element visible again.
Mandatory and optional fields in the configuration
- When using TypeScript, your IDE should automatically indicate which fields are mandatory/optional via the provided typings.
- When using plain JavaScript, please refer to the section above regarding mandatory/optional fields.
Providing enumeration values in the configuration
Enumerations can be directly imported from the widget library. This works with both plain JavaScript and TypeScript. For
instance, the Locale
enumeration can be used like this:
import { renderInteractiveFactsheet, Locale } from '@munichremarkets/interactive-factsheet';
const target = document.getElementById('widget-target');
renderInteractiveFactsheet(target, { locale: Locale.En_US, ... });
Although other ways of providing an enumeration value are technically possible (e.g. numerical or string values), it is considered improper usage and may stop working at any point.
Recommendations
- Do not use a side navigation besides the widget.
- Do not implement the widget in modals.
- The respective widget should take as much height as it needs.
- Provide at least 1440px width for the widgets.
- Don't include much content above and below the widget.
Due to the scrolling behavior of the widget, it is recommended that you allow the widget to take the full height of the page with possible exceptions being a header and a footer. The widget assumes that a sticky header may be present on mobile viewports but not on desktop viewports. This distinction comes into play when the widget automatically scrolls to the top because this means scrolling to the top of the page on mobile viewports but to the top of the widget for desktop viewports.
Styling
Framework
The Interactive Factsheet widget uses version 4.x of the Bootstrap framework for styling. When integrating the widget into your website, you need to do different things depending on whether your website uses Bootstrap, too:
Case 1: Your website uses Bootstrap
In this case, Bootstrap CSS rules are already present on your website and all the Bootstrap theme colors defined by your website will automatically be used by the widget. Note that the supported range of Bootstrap versions is from 4.2 to 4.6 (inclusive).
Case 2: Your website does not use Bootstrap
In this case, you are required to set the includeBootstrap4Css
flag to true
when invoking the widget rendering
function, so that the Bootstrap 4.x CSS rules shipped with the widget are included on your page. Those CSS rules will
not affect the appearance of elements outside the widget because they are scoped to the .sri-widget
CSS class that is
assigned to a DOM element the widget is rendered into.
Adaptation of styling
By default, the styling of the widget automatically adapts to the styling of your website to a certain extent. However, you can still customize the appearance if necessary.
Automatic styling
Fonts
Since the widget does not define its own font, any font you define in the DOM tree above the widget will automatically be used within the widget.
Note: If your website uses external web fonts, e.g. from Google Fonts, you need to set crossorigin
or
crossorigin="anonymous"
on the corresponding <link>
tag. Otherwise, those web fonts cannot be used in certain parts
of the print views produced by the widget, and you will see a fallback font instead.
Example:
<link href="https://fonts.googleapis.com/css2?family=Roboto" rel="stylesheet" crossorigin />
Spacings
Font sizes and most of the spacings are defined in units of rem
(root em
), so these sizes will automatically be set
relative to the font size of your website's <body>
element.
Width
The widget will automatically fill the full width of its parent element.
Theming
Primary theming API: Overriding Bootstrap theme colors & CSS variables
Regardless of whether you are providing a custom-themed Bootstrap or not, certain colors (SRI colors) need to be
customized. The minimal set of CSS variables that should be overridden are element
, and the shades
of primary
and secondary
:
primary-[50-900]
secondary-[50-900]
element-[0-23]
element-other
The element-*
colors are used within indicators and charts (funds, categories, ...). The element-other
color is used
specifically for those instances where it's necessary to display an "Other" category in an indicator or chart.
By default, all additional colors are derived from those colors so overriding them should already provide a good baseline for theming.
To make sure that your settings for these variables take precedence over the defaults defined by the widget, use the CSS
selector .sri-widget.sri-external
like this:
.sri-widget.sri-external {
--primary-500: red;
}
Case 1: Your website uses Bootstrap
Bootstrap theme colors: Bootstrap components used throughout the Munich Re Markets widgets will be styled correctly,
CSS variables for those customized colors are expected to be available on :root
. This should require no further
action.
Case 2: Your website does not use Bootstrap
Bootstrap theme colors: The CSS variables referring to the Bootstrap theme colors need to be overridden:
--primary
--secondary
--success
--danger
--warning
--info
--light
--dark
To make sure that your settings for these variables take precedence over the defaults defined by the widget, use the CSS
selector .sri-widget.sri-external
like this:
.sri-widget.sri-external {
--primary: red;
}
Note:
- Bootstrap internally uses SCSS variables, which are only present at build time. Since you will use the Bootstrap CSS
rules shipped with the widget if you don't provide your own, components provided by Bootstrap will not be themed
properly by just overriding the CSS variables. Also, classes like
.text-primary
,.bg-primary
etc. will use wrong color values. In those cases the according CSS classes have to be overridden individually (see next section). - Any style overrides except changing Bootstrap theme colors may stop working at any point and hence need to be thoroughly tested on every upgrade.
Secondary theming API: Overriding CSS classes
You can override each style of the application via CSS classes individually. Therefore, it is important to know the basic markup of the widget, which looks like this:
<!-- Passed into the rendering function by your website -->
<div>
<!-- Created by the rendering function -->
<div>
<div class="sri-widget sri-external">
<div class="sri-interactive-factsheet">
<!-- Widget content -->
</div>
</div>
</div>
</div>
If you want to style an element within the main content of the widget, prefix all CSS rules
with .sri-widget.sri-external
to ensure that your CSS rule is more specific than the ones shipped with the widget and
hence overrides the latter. For example, to style a button (.sri-btn
), use a CSS rule like this:
.sri-widget.sri-external .sri-btn {
/* ... */
}
If you use other widgets on the same page and need to scope a rule specifically to the Interactive Factsheet widget, additionally include the widget-specific class like this:
.sri-widget.sri-external.sri-interactive-factsheet .sri-btn {
/* ... */
}
There is one special case: Some elements need to be rendered directly into the <body>
of your website to ensure that
they cover other elements, e.g. modal dialogs and tooltips. For these elements, the markup looks like this:
<div class="sri-widget sri-external sri-interactive-factsheet sri-modal">
<!-- Modal content -->
</div>
In this case, you can override styles within the modal using CSS rules like this:
.sri-widget.sri-external.sri-interactive-factsheet.sri-modal .sri-btn {
/* ... */
}
Notes:
- Use
!important
for rules originating from Bootstrap. This is because Bootstrap already declares all rules as!important
, so your rules need to be!important
, too, in order to override the Bootstrap rules. - Any style overrides except changing Bootstrap theme colors may stop working at any point and hence need to be thoroughly tested on every upgrade.
Recommendations for mobile viewports
Viewports in the "Extra small" (xs
) and "Small" (sm
) ranges of the responsive breakpoints defined by Bootstrap, i.e.
narrower than 768px
, are considered "mobile" viewports and larger ones are considered "desktop" viewports.
Although the Interactive Factsheet widget is generally responsive across all breakpoints, there are significant changes in layout between mobile and desktop viewports. Hence it is recommended to test your website in both variants.
Browser support
The following browsers are supported:
- Chrome (latest version)
- Firefox (latest version)
- Safari on macOS and iOS (latest two major versions)