API
Platform API
Various APIs provided by the platform for all widgets, such as:
- Themes;
- Reserved props (List of possibly shared props);
- Widget props.
Themes
Themes are objects describing custom application styles, provided to all widgets.
Implementation/usage is described in the theme-serving documentation section.
- Multiple objects could be provided.
- Theme is dynamic.
- Changing themes lead to CSS styles change.
- Themes are provided through the customization backend.
- All widgets get the active theme through the
styled-componentscontext. - Theme-derived styles usage is recommended, but not mandatory in the widgets.
Branding
- All the branding elements - custom icons, images, fonts, and other assets.
- Branding resides on the customization backend.
- Currently, only fonts are implemented through the theming API.
Platform Meta Props
- Props indicating the current state of the platform that is important for widgets.
- Includes info on the current active dashboard, other available widgets metadata.
- Typings available through
@invent/shared-typespackage.
interface IPlatformMeta {
storeWidgetsById: Record<string, IWidgetMetadata<Record<string, unknown>>>;
platformWidgetsById: Record<string, IPlatformWidget>;
currentDashboardId?: string;
currentDashboard: IDashboard | undefined;
}
State sharing
- Widgets can read and write to the special section of app state.
useShareValue,useSelectSharedValue,useDeleteSharedValuehooks are provided for every widget through props, typing could be found in@invent/shared-types.
import React from "react";
import { UseSelectSharedValueT, ISharedState } from "@invent/shared-types";
import { path } from "ramda";
/* Lens function. It "focuses" key in `ISharedState` object. */
function profileSelector(state: ISharedState) {
return path<UserProfileT | undefined>(["userProfile"], state);
}
const MyComponent = ({ useSelectSharedValue }: PropsType) => {
const userProfile = useSelectSharedValue(profileSelector);
return <div>{userProfile.name}</div>;
};
import React, { useEffect } from "react";
import { v4 } from "uuid";
const ShareRandomValueComponent = ({ useShareValue }: PropsType) => {
const shareValue = useShareValue();
useEffect(() => {
const randomValue = v4();
/*
This value could be accessed with function like:
function randomValueSelector (state: ISharedState){
return path<UserProfileT>(['randomValue'], state);
}
const randomSharedValue = useSelectSharedValue(randomValueSelector);
*/
shareValue(["randomValue"], randomValue);
}, []);
return <div>{randomValue}</div>;
};
- The dashboard-bound scope is auto-created in this section when some dashboard becomes active, it can be used to connect widget instances on the same board.
Http client
- Platform provides a default HTTP client for widgets.
- It takes care of credentials, tokens, etc.
- Potentially, different clients/communication bindings could be provided.
- Widgets can use custom ways of making requests if developers find it suitable.
Remote module rendering inside widgets
platformMeta,remoteModuleandgenerateWidgetDataprops, if used together, can make it possible to easily render any other known widget (to the host app) inside your widget.remoteModuleprop provides a React component that the Platform uses to render remotesgenerateWidgetData- accepts widget metadata (specific, or selected fromplatformMeta), and generates an object consumable by<RemoteModule/>.- also described at Module Federation.
Widget instance ID on the specific dashboard
dashboardWidgetInstanceIdidentifies widget instance inside the specific dashboard, and could be used for state sharing across this dashboard, or other means.
Use React Query Data
useQueryDataprop is a hook, that internally subscribes to the react-query cache, and returns an updated query state object if it was changed. It should be provided with a query key argument, which works like path-based selectors in Redux.react-querycaches data with long query key-based hashes which contain all the query parameters, but withuseQueryDatawe can read updates while only providing a partial key, thus avoiding the need to gather all the query parameters to read it in some other micro frontends.
import { useQuery } from "react-query";
import { path } from "ramda";
import type { ISharedState } from "@invent/shared-types";
function userProfileSelector(state: ISharedState) {
return path<IUserProfile | undefined>(["userProfile"], state);
}
const GetUserProfile = ({
apiUrl,
httpClient,
useShareValue,
useSelectSharedValue,
}: PropsType) => {
const shareValue = useShareValue();
const userProfile = useSelectSharedValue(userProfileSelector);
const profileEndpoint = `${apiUrl}/profile`;
const { data: profileData } = useQuery<IUserProfile>(
[profileEndpoint, userProfile],
async () => {
if (apiUrl && !userProfile) {
return await httpClient(profileEndpoint, { traceId: projectId });
}
}
);
useEffect(() => {
shareValue(["userProfile"], data);
}, [data]);
return <div>{data.name}</div>;
};
Platform Widget Props
Platform widgets have some specific props for control application state.
type PlatformWidgetComponentProps = {
handleSignin: VoidFinction;
handleSignout: VoidFinction;
};