@servicetitan/docs-uikit 30.1.1 → 30.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,12 +34,12 @@ and automatically [provides a store](#use-flags-in-mobx-store) that allows flag
34
34
 
35
35
  #### Props
36
36
 
37
- | Name | Type | Description |
38
- | :---------------------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
- | `clientSideID` | `string` | The client-side ID that authorizes the client to connect to a particular LaunchDarkly project. The [getValueForEnvironment](./web-components#getvalueforenvironment) helper provides a convenient way to map Monolith environments to the corresponding client-side ID. |
40
- | `projectName` | `string` | The name of the LaunchDarkly project, for logs and error messages. |
41
- | `context` | `object` | (Optional) Context for targeting rules. Defaults to anonymous user. Use LaunchDarkly's [`identify`](https://docs.launchdarkly.com/sdk/features/identify) method to change the context after initialization. |
42
- | `waitForInitialization` | `boolean` | (Optional) Whether or not to wait until flags values are available before rendering children. Defaults to `true` |
37
+ | Name | Type | Description |
38
+ | :---------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | `clientSideID` | `string` | The client-side ID that authorizes the client to connect to a particular LaunchDarkly project. The [getValueForEnvironment](./web-components/get-value-for-environment) helper provides a convenient way to map Monolith environments to the corresponding client-side ID. |
40
+ | `projectName` | `string` | The name of the LaunchDarkly project, for logs and error messages. |
41
+ | `context` | `object` | (Optional) Context for targeting rules. Defaults to anonymous user. Use LaunchDarkly's [`identify`](https://docs.launchdarkly.com/sdk/features/identify) method to change the context after initialization. |
42
+ | `waitForInitialization` | `boolean` | (Optional) Whether or not to wait until flags values are available before rendering children. Defaults to `true` |
43
43
 
44
44
  :::caution
45
45
  When a `context` is provided, only the initial value takes affect. Subsequent calls with the same client-side ID reuse the client that was created with the initial context.
@@ -10,7 +10,7 @@ Use EventBus to exchange messages (aka events) between a host and MFEs, or betwe
10
10
  ### Providing EventBus
11
11
 
12
12
  To use EventBus, provide an instance via `EVENT_BUS_TOKEN`.
13
- [Loader](#loader) automatically passes the EventBus through to MFEs.
13
+ [Loader](../web-components#loader) automatically passes the EventBus through to MFEs.
14
14
  For example,
15
15
 
16
16
  ```tsx
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: getValueForEnvironment
3
+ ---
4
+
5
+ `getValueForEnvironment` detects the host environment and returns a corresponding value.
6
+
7
+ ```ts
8
+ function getValueForEnvironment(
9
+ values: Record<string, string>,
10
+ defaultEnvironment: keyof typeof values = 'qa',
11
+ hostname: string = window.location.hostname
12
+ );
13
+ ```
14
+
15
+ :::caution
16
+ When no value is provided for the detected environment, `getValueForEnvironment` returns `undefined`.
17
+ :::
18
+
19
+ ### Parameters
20
+
21
+ | Name | Type | Description |
22
+ | :------------------- | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ |
23
+ | `values` | `Record<string, string>` | Object that maps each environment to a value (see below). |
24
+ | `defaultEnvironment` | `keyof typeof values` | The environment to use when the current environment is not recognized or is not included in `values`. Defaults to `"qa"`. |
25
+ | `hostname` | `string` | The hostname of the current environment. Defaults to `window.location.hostname` |
26
+
27
+ The recognized environments are:
28
+
29
+ | Environment | Description |
30
+ | :---------------- | :--------------------------------------------------------------------------- |
31
+ | **dev** | Development environment (i.e., `localhost`, `127.0.0.1`) |
32
+ | **go** | Production environment |
33
+ | **qa** | QA environment |
34
+ | **next** | Next environment |
35
+ | **stage** | Staging environment |
36
+ | **test** | Unit test environment (i.e., `process.env.NODE_ENV === 'test'`) |
37
+ | `<string>` | Custom environment that matches against hostname `<string>.servicetitan.com` |
38
+ | `<string>.st.dev` | Custom environment that matches against hostname `<string>.st.dev` |
39
+
40
+ ### Custom environments
41
+
42
+ Custom environments are for applications and services that run separately from the Monolith.
43
+ For example, to associate **prod** with `my-service.servicetitan.com` and **stage** with `my-service-stage.st.dev`:
44
+
45
+ ```json
46
+ {
47
+ "my-service": "prod", // Matches my-service.servicetitan.com
48
+ "stage.st.dev": "stage" // Matches *stage.st.dev
49
+ }
50
+ ```
51
+
52
+ ### Examples
53
+
54
+ Determine LaunchDarkly client-side ID for TitanAdvisor project.
55
+
56
+ ```tsx
57
+ function useTitanAdvisorClientSideID() {
58
+ // Environment won't change and is safe to memoize
59
+ return useMemo(() => {
60
+ return getValueForEnvironment({
61
+ dev: '669fe6e5cc97eb103be7a620',
62
+ go: '669fe5bff00a0c0fa60b25e4',
63
+ next: '669fe5bff00a0c0fa60b25e4', // same a 'go' but could also be 'qa'
64
+ qa: '669fe6d6f00a0c0fa60b2721',
65
+ stage: '669fe65979abf310b860236e',
66
+ });
67
+ }, []);
68
+ }
69
+ ```
70
+
71
+ :::info
72
+ Note that because the environment is fixed for the life the application, it is safe to memoize the return value.
73
+ :::
74
+
75
+ :::caution
76
+ Do not call `getValueForEnvironment` globally, outside a React component or hook. That usage assumes that all the information needed to determine the environment is available immediately when the Javascript runtime loads and before the application is initialized. While that might work, it might also change in the future.
77
+ :::
@@ -2,6 +2,9 @@
2
2
  title: Web Components
3
3
  ---
4
4
 
5
+ import Tabs from '@theme/Tabs';
6
+ import TabItem from '@theme/TabItem';
7
+
5
8
  #### [CHANGELOG (@servicetitan/web-components)](https://github.com/servicetitan/uikit/blob/master/packages/web-components/CHANGELOG.md)
6
9
 
7
10
  `@servicetitan/web-components` is used to build, register, and load Microfrontends (MFEs) into host applications.
@@ -13,19 +16,10 @@ The `Loader` component is used to load an MFE into a host application. See [Micr
13
16
  ### Usage
14
17
 
15
18
  ```tsx
16
- ...
17
-
18
19
  import { Loader } from '@servicetitan/web-components';
19
20
 
20
- ...
21
-
22
- export const Foo: React.FC = () => {
23
- ...
24
- return (
25
- ...
26
- <Loader src="https://unpkg.servicetitan.com/{package_name}@{semver_range}" />
27
- ...
28
- );
21
+ export const Foo = () => {
22
+ return <Loader src="https://unpkg.servicetitan.com/{package_name}@{semver_range}" />;
29
23
  };
30
24
  ```
31
25
 
@@ -33,8 +27,8 @@ export const Foo: React.FC = () => {
33
27
 
34
28
  | Name | Description |
35
29
  | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
36
- | `src` | path to an MFE root folder |
37
- | `fallbackSrc` | optional alternative path to an MFE root folder (if request for src returns error) |
30
+ | `src` | url for the MFE's package |
31
+ | `fallbackSrc` | optional alternative url for the MFE's package (if request for src returns error) |
38
32
  | `data` | additional data passed to an MFE as an object, where values are serializable, and preferably memoized ([see below](#passing-data-from-host-to-mfe)) |
39
33
  | `basename` | prefix for all MFE URLs, you should inject it by the `BASENAME_TOKEN` and pass to the appropriate router property |
40
34
  | `loadingFallback` | optional ReactNode to render when the MFE is loading |
@@ -60,7 +54,7 @@ When an MFE is loaded, `Loader` fetches the version and bundle data from the `sr
60
54
 
61
55
  Use `data` to pass data from your host application to the MFE. The data should be an object where keys are strings and the values are any serializable data.
62
56
 
63
- To avoid performance issues with re-rendering and re-serializing the value, we recommend memoizing the `data` object passed to `<Loader>`.
57
+ To avoid performance issues with re-rendering and re-serializing the value, we recommend memoizing the `data` object passed to `Loader`.
64
58
 
65
59
  **Reminder:** Don't casually share data between the host and MFEs. When possible, MFEs should load the data they need instead of relying on the host to pass it.
66
60
 
@@ -116,115 +110,165 @@ export const MFEApp = (props: MyType) => {
116
110
  // RESULTS IN A STRING, NOT A DATE OBJECT
117
111
  ```
118
112
 
119
- As of version v22.12.0 of `@servicetitan/web-components`, if data passed into the `data` prop of `<Loader>` changes during runtime, the data will re-render within your MFE component where appropriate. Previous versions would re-mounting the entire MFE application when data changed.
113
+ As of version v22.12.0 of `@servicetitan/web-components`, if data passed into the `data` prop of `Loader` changes during runtime, the data will re-render within your MFE component where appropriate. Previous versions would re-mounting the entire MFE application when data changed.
120
114
 
121
- ## useMFEDataContext
115
+ ### Using EventBus to exchanges messages
122
116
 
123
- Data can be also be accessed within the MFE using the `useMFEDataContext` hook. You must provide the type of the data you expect to receive.
117
+ Use [EventBus](./event-bus) to exchange messages between the host and MFEs.
118
+ When an EventBus is provided via `EVENT_BUS_TOKEN`, `Loader` automatically passes it through to MFEs.
119
+ For example,
120
+
121
+ <Tabs
122
+ defaultValue="host"
123
+ values={[
124
+ { label: 'Host', value: 'host' },
125
+ { label: 'MFE', value: 'mfe'},
126
+ { label: 'Types', value: 'types' },
127
+ ]}
128
+ >
129
+ <TabItem value="types">
124
130
 
125
131
  ```tsx
126
- import { useMFEDataContext } from '@servicetitan/web-components';
127
- ...
128
- interface MFEAppData {
129
- bar: string;
132
+ import { EventBus, typedEventBusToken } from '@servicetitan/web-components';
133
+
134
+ export enum Events {
135
+ example = 'example:event',
130
136
  }
131
137
 
132
- export const MFEApp = () => {
133
- const { bar } = useMFEDataContext<MFEAppData>();
134
- };
138
+ export interface ExampleEvents {
139
+ [Events.example]: undefined;
140
+ }
141
+
142
+ export type ExampleEventBus = EventBus<ExampleEvents>;
143
+
144
+ export const EXAMPLE_EVENT_BUS_TOKEN = typedEventBusToken<ExampleEvents>();
135
145
  ```
136
146
 
137
- ## useMFEMetadataContext
147
+ </TabItem>
148
+ <TabItem value="host">
138
149
 
139
- Some metadata is also provided to MFEs, and is accessible through the `useMFEMetadataContext` hook.
150
+ ```tsx
151
+ import { provide, useDependencies } from '@servicetitan/react-ioc';
152
+ import { EVENT_BUS_TOKEN, EventBus, Loader } from '@servicetitan/web-components';
153
+ import { FC, useCallback, useEffect } from 'react';
154
+ import { Events, EXAMPLE_EVENT_BUS_TOKEN } from './types';
155
+
156
+ const mfeUrl = 'https://unpkg.servicetitan.com/@servicetitan/examples';
157
+
158
+ export const App: FC = provide({
159
+ singletons: [{ provide: EVENT_BUS_TOKEN, useValue: new EventBus() }],
160
+ })(() => {
161
+ const [eventBus] = useDependencies(EXAMPLE_EVENT_BUS_TOKEN);
162
+ const handleExampleEvent = useCallback(() => {
163
+ /* Handle event */
164
+ }, []);
165
+
166
+ useEffect(() => {
167
+ eventBus.on(Events.example, handleExampleEvent);
168
+ return () => {
169
+ eventBus.off(Events.example, handleExampleEvent);
170
+ };
171
+ }, [eventBus, handleExampleEvent]);
172
+
173
+ // Loader passes provided EventBus through to MFE
174
+ return <Loader src={mfeUrl} />;
175
+ });
176
+ ```
177
+
178
+ </TabItem>
179
+ <TabItem value="mfe">
140
180
 
141
181
  ```tsx
142
- import { useMFEMetadataContext } from '@servicetitan/web-components';
143
- ...
144
- export const MFEApp = () => {
145
- const { shadowRoot, portalShadowRoot } = useMFEMetadataContext();
182
+ import { Button } from '@servicetitan/anvil2';
183
+ import { useDependencies } from '@servicetitan/react-ioc';
184
+ import { useCallback } from 'react';
185
+ import { Events, EXAMPLE_EVENT_BUS_TOKEN } from './types';
186
+
187
+ export const App = () => {
188
+ // Loader passes through provided EventBus
189
+ const [eventBus] = useDependencies(EXAMPLE_EVENT_BUS_TOKEN);
190
+
191
+ const handleClick = useCallback(() => {
192
+ eventBus.emit(Events.example);
193
+ }, [eventBus]);
194
+
195
+ return <Button onClick={handleClick}>Click me</Button>;
146
196
  };
147
197
  ```
148
198
 
149
- The following metadata about an MFE is available from `useMFEMetadataContext` hook.
199
+ </TabItem>
200
+ </Tabs>
150
201
 
151
- | Name | Type | Description |
152
- | :----------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------------ |
153
- | `shadowRoot` | ShadowRoot | ShadowRoot root node of which the MFE is rendered within |
154
- | `portalShadowRoot` | ShadowRoot | ShadowRoot root node of the "portal" tied to the MFE, which is used to render elements in a div directly under the body element |
202
+ See [typedEventBusToken](./event-bus#typedeventbustoken) for a detailed explanation
203
+ of the types used in these examples.
155
204
 
156
- ## getValueForEnvironment
205
+ #### Using legacy ref parameter
157
206
 
158
- `getValueForEnvironment` detects the host environment and returns a corresponding value.
207
+ For backward compatibility, when no `EVENT_BUS_TOKEN` is provided, `Loader`
208
+ creates a private EventBus and returns it via the `ref` parameter.
209
+ This old approach should not be used in new code.
159
210
 
160
- ```ts
161
- function getValueForEnvironment(
162
- values: Record<string, string>,
163
- defaultEnvironment: keyof typeof values = 'qa',
164
- hostname: string = window.location.hostname
165
- );
166
- ```
211
+ ```tsx
212
+ import { FC, useCallback, useEffect, useState } from 'react';
213
+ import { Loader } from '@servicetitan/web-components';
214
+ import { Events, ExampleEventBus } from './types';
167
215
 
168
- :::caution
169
- When no value is provided for the detected environment, `getValueForEnvironment` returns `undefined`.
170
- :::
216
+ const mfeUrl = 'https://unpkg.servicetitan.com/@servicetitan/examples';
171
217
 
172
- ### Parameters
218
+ export const Component: FC = () => {
219
+ const [eventBus, setEventBus] = useState<ExampleEventBus | null>(null);
220
+ const handleExampleEvent = useCallback(() => {
221
+ /* Handle event */
222
+ }, []);
173
223
 
174
- | Name | Type | Description |
175
- | :------------------- | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ |
176
- | `values` | `Record<string, string>` | Object that maps each environment to a value (see below). |
177
- | `defaultEnvironment` | `keyof typeof values` | The environment to use when the current environment is not recognized or is not included in `values`. Defaults to `"qa"`. |
178
- | `hostname` | `string` | The hostname of the current environment. Defaults to `window.location.hostname` |
224
+ useEffect(() => {
225
+ eventBus?.on(Events.example, handleExampleEvent);
226
+ return () => {
227
+ eventBus?.off(Events.example, handleExampleEvent);
228
+ };
229
+ }, [eventBus, handleExampleEvent]);
179
230
 
180
- The recognized environments are:
231
+ // Loader provides private EventBus and returns it via "ref"
232
+ return <Loader ref={ref => setEventBus(ref)} src={mfeUrl} />;
233
+ };
234
+ ```
181
235
 
182
- | Environment | Description |
183
- | :---------------- | :--------------------------------------------------------------------------- |
184
- | **dev** | Development environment (i.e., `localhost`, `127.0.0.1`) |
185
- | **go** | Production environment |
186
- | **qa** | QA environment |
187
- | **next** | Next environment |
188
- | **stage** | Staging environment |
189
- | **test** | Unit test environment (i.e., `process.env.NODE_ENV === 'test'`) |
190
- | `<string>` | Custom environment that matches against hostname `<string>.servicetitan.com` |
191
- | `<string>.st.dev` | Custom environment that matches against hostname `<string>.st.dev` |
236
+ :::caution
237
+ Note, if an `EVENT_BUS_TOKEN` is provided, `Loader` returns the provide value in `ref`
238
+ and doesn't create a private EventBus.
239
+ :::
192
240
 
193
- ### Custom environments
241
+ ## useMFEDataContext
194
242
 
195
- Custom environments are for applications and services that run separately from the Monolith.
196
- For example, to associate **prod** with `my-service.servicetitan.com` and **stage** with `my-service-stage.st.dev`:
243
+ Data can be also be accessed within the MFE using the `useMFEDataContext` hook. You must provide the type of the data you expect to receive.
197
244
 
198
- ```json
199
- {
200
- "my-service": "prod", // Matches my-service.servicetitan.com
201
- "stage.st.dev": "stage" // Matches *stage.st.dev
245
+ ```tsx
246
+ import { useMFEDataContext } from '@servicetitan/web-components';
247
+ ...
248
+ interface MFEAppData {
249
+ bar: string;
202
250
  }
251
+
252
+ export const MFEApp = () => {
253
+ const { bar } = useMFEDataContext<MFEAppData>();
254
+ };
203
255
  ```
204
256
 
205
- ### Examples
257
+ ## useMFEMetadataContext
206
258
 
207
- Determine LaunchDarkly client-side ID for TitanAdvisor project.
259
+ Some metadata is also provided to MFEs, and is accessible through the `useMFEMetadataContext` hook.
208
260
 
209
261
  ```tsx
210
- function useTitanAdvisorClientSideID() {
211
- // Environment won't change and is safe to memoize
212
- return useMemo(() => {
213
- return getValueForEnvironment({
214
- dev: '669fe6e5cc97eb103be7a620',
215
- go: '669fe5bff00a0c0fa60b25e4',
216
- next: '669fe5bff00a0c0fa60b25e4', // same a 'go' but could also be 'qa'
217
- qa: '669fe6d6f00a0c0fa60b2721',
218
- stage: '669fe65979abf310b860236e',
219
- });
220
- }, []);
221
- }
262
+ import { useMFEMetadataContext } from '@servicetitan/web-components';
263
+ ...
264
+ export const MFEApp = () => {
265
+ const { shadowRoot, portalShadowRoot } = useMFEMetadataContext();
266
+ };
222
267
  ```
223
268
 
224
- :::info
225
- Note that because the environment is fixed for the life the application, it is safe to memoize the return value.
226
- :::
269
+ The following metadata about an MFE is available from `useMFEMetadataContext` hook.
227
270
 
228
- :::caution
229
- Do not call `getValueForEnvironment` globally, outside a React component or hook. That usage assumes that all the information needed to determine the environment is available immediately when the Javascript runtime loads and before the application is initialized. While that might work, it might also change in the future.
230
- :::
271
+ | Name | Type | Description |
272
+ | :----------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------------ |
273
+ | `shadowRoot` | ShadowRoot | ShadowRoot root node of which the MFE is rendered within |
274
+ | `portalShadowRoot` | ShadowRoot | ShadowRoot root node of the "portal" tied to the MFE, which is used to render elements in a div directly under the body element |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-uikit",
3
- "version": "30.1.1",
3
+ "version": "30.1.2",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,5 +16,5 @@
16
16
  "cli": {
17
17
  "webpack": false
18
18
  },
19
- "gitHead": "02382f349ee120e1b30d9676484481f93059c054"
19
+ "gitHead": "76e26006c94d59038b9719ede1fa416d84d4a2c3"
20
20
  }