@servicetitan/docs-uikit 28.2.0 → 28.3.1

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.
@@ -9,7 +9,7 @@ each with its own set of feature flags and client-side IDs that authorize connec
9
9
 
10
10
  LaunchDarkly's SDKs require applications to create a separate client connection to the LaunchDarkly backend for each project.
11
11
  However, if applications and MFEs create multiple, independent connections to the same LaunchDarkly project, it can degrade performance
12
- and cause the uikit to behave inconsistently. It also harms performance to teardown and recreate connections each time an
12
+ and cause the UI to behave inconsistently. It also harms performance to teardown and recreate connections each time an
13
13
  MFE is unloaded and reloaded.
14
14
 
15
15
  To prevent these issues **@servicetitan/launchdarkly-service** implements a coordinated approach for creating
@@ -29,7 +29,8 @@ Instead of using **LDProvider**, **withLDProvider** or **withAsyncLDProvider** f
29
29
  ### LDProvider
30
30
 
31
31
  `LDProvider` provides LaunchDarkly feature flags within hosts and MFEs.
32
- It ensures that hosts and MFEs share one client connection to each LaunchDarkly project (as identified by the client-side ID).
32
+ It ensures that hosts and MFEs share one client connection to each LaunchDarkly project (as identified by the client-side ID)
33
+ and automatically [provides a store](#use-flags-in-mobx-store) that allows flag values to be used in MobX stores.
33
34
 
34
35
  #### Props
35
36
 
@@ -47,11 +48,9 @@ This is typically only a problem when different code paths call `LDProvider` wit
47
48
  If that isn't practical, you can use [`getContext`](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html#getContext) and [`identify`](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html#identify) to fetch and amend the active context.
48
49
  :::
49
50
 
50
- :::caution
51
- When `waitForInitialization` is set to false, the UI could render immediately, with no flags,
52
- and the LaunchDarkly SDK won't automatically re-render components when the flags become available.
53
- If this is a problem, you can [subscribe to flag changes](https://docs.launchdarkly.com/sdk/features/flag-changes)
54
- and manually trigger updates.
51
+ :::note
52
+ When `waitForInitialization` is set to false, `LDProvider` renders children immediately, possibly with no flag values,
53
+ then automatically re-renders when the flags become available.
55
54
  :::
56
55
 
57
56
  #### Examples
@@ -140,3 +139,198 @@ export const HostApp: FC = () => {
140
139
  );
141
140
  };
142
141
  ```
142
+
143
+ ### FeatureFlagStore
144
+
145
+ `LDProvider` automatically provides a `FeatureFlagStore` that allows you to access
146
+ feature flags in MobX stores.
147
+ To use [@inject](./react-ioc#inject) where needed.
148
+
149
+ #### Props
150
+
151
+ | Name | Type | Description |
152
+ | :------ | :---------- | :------------------------------ |
153
+ | `flags` | `LDFlagSet` | The LaunchDarkly feature flags. |
154
+
155
+ #### Example
156
+
157
+ ```tsx
158
+ import { FeatureFlagStore } from '@servicetitan/launchdarkly-service';
159
+
160
+ class ConsumerStore {
161
+ constructor(@inject(FeatureFlagStore) private readonly featureFlagStore: FeatureFlagStore) {
162
+ // this.featureFlagStore.flags contains feature flags
163
+ }
164
+ }
165
+ ```
166
+
167
+ ### WithFeatureFlag
168
+
169
+ `WithFeatureFlag` conditionally renders content depending on the value of a feature flag.
170
+
171
+ #### Props
172
+
173
+ | Name | Type | Description |
174
+ | :-------- | :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
175
+ | `flagKey` | `string` | The feature flag's key. To type check `flagKey`, pass a type argument that defines the flag set (see [below](#type-check-flag-key)) |
176
+ | `on` | `React.ComponentType` | (Optional) Component to render when the flag is turned on. Defaults to `children` prop. |
177
+ | `off` | `React.ComponentType` | (Optional) Component to render when the flag is turned off. Defaults to `null`. |
178
+ | `value` | `LDFlagValue` | (Optional) Flag value that indicates the flag is turned on. Defaults to treating any truthy value as "on". |
179
+
180
+ #### Examples
181
+
182
+ Render children when flag is turned on:
183
+
184
+ ```tsx
185
+ <WithFeatureFlag flagKey={flagKey}>
186
+ <Text>Flag is ON</Text>
187
+ </WithFeatureFlag>
188
+ ```
189
+
190
+ Render children when flag has specific value:
191
+
192
+ ```tsx
193
+ <WithFeatureFlag flagKey={flagKey} value={false}>
194
+ <Text>Flag is false</Text>
195
+ </WithFeatureFlag>
196
+ ```
197
+
198
+ Render children when flag is on, and render other component when flag is turned off:
199
+
200
+ ```tsx
201
+ <WithFeatureFlag flagKey={flagKey} off={ComponentV1}>
202
+ <ComponentV2 />
203
+ </WithFeatureFlag>
204
+ ```
205
+
206
+ Render component when flag is on, and render other component when flag is turned off:
207
+
208
+ ```tsx
209
+ <WithFeatureFlag flagKey={flagKey} on={ComponentV2} off={ComponentV1} />
210
+
211
+ <WithFeatureFlag flagKey={flagKey} on={() => 'Flag is ON'} off={() => 'Flag is OFF'} />
212
+ ```
213
+
214
+ ## Examples
215
+
216
+ ### Using flag values in React component
217
+
218
+ Use the `useFlags` hook from the LaunchDarkly React SDK to access flags in React components. E.g.,
219
+
220
+ ```tsx
221
+ import { useFlags } from 'launchdarkly-react-client-sdk';
222
+
223
+ export const Component: FC = () => {
224
+ const { enableRedesign } = useFlags();
225
+ return enableRedesign ? <NewDesign /> : <OldDesign />;
226
+ };
227
+ ```
228
+
229
+ Or, use this package's [WithFeatureFlag](#withfeatureflag) helper:
230
+
231
+ ```tsx
232
+ import { WithFeatureFlag } from '@servicetitan/launchdarkly-service';
233
+
234
+ export const Component: FC = () => (
235
+ <WithFeatureFlag flagKey="enableRedesign" on={NewDesign} off={OldDesign} />
236
+ );
237
+ ```
238
+
239
+ ### Using flag values in MobX store {#use-flags-in-mobx-store}
240
+
241
+ To use flag values in MobX stores, inject the [FeatureFlagStore](#featureflagstore) provided by `LDProvider`.
242
+ For example,
243
+
244
+ ```tsx
245
+ import { FeatureFlagStore } from '@servicetitan/launchdarkly-service';
246
+
247
+ @injectable()
248
+ export class DataStore extends Store {
249
+ constructor(@inject(FeatureFlagStore) private readonly featureFlagStore: FeatureFlagStore) {
250
+ // Use this.featureFlagStore.flags to access feature flags
251
+ if (this.featureFlagStore.flags.enableDataV2) {
252
+ this.initializeDataV2();
253
+ } else {
254
+ this.initializeData();
255
+ }
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### Type checking WithFeatureFlag key {#type-check-flag-key}
261
+
262
+ To type check the `flagKey` passed to `WithFeatureFlag`, pass a type argument that defines the flag set.
263
+ For example,
264
+
265
+ ```tsx title='fleet-flag-set.ts'
266
+ export interface FleetFlagSet {
267
+ enablePermissions: boolean;
268
+ enableBreadcrumbPage: boolean;
269
+ enableAlertsRedesign: boolean;
270
+ }
271
+ ```
272
+
273
+ ```tsx
274
+ <WithFeatureFlag<FleetFlagSet> flagKey={flagKey} /> // Enforces that flagKey is in FleetFlagSet
275
+ ```
276
+
277
+ Or, create a custom wrapper that does this automatically. For example,
278
+
279
+ ```tsx title='with-fleet-feature-flag.tsx'
280
+ import { WithFeatureFlag, WithFeatureFlagProps } from '@servicetitan/launchdarkly-service';
281
+ import { FleetFlagSet } from './fleet-flag-set';
282
+
283
+ export const WithFleetFeatureFlag = <T extends keyof FleetFlagSet>(
284
+ props: WithFeatureFlagProps<FleetFlagSet, T>
285
+ ) => <WithFeatureFlag<FleetFlagSet, T> {...props} />;
286
+ ```
287
+
288
+ ```tsx
289
+ <WithFleetFeatureFlag flagKey={flagKey} /> // Enforces that flagKey is in FleetFlagSet
290
+ ```
291
+
292
+ ### Type checking WithFeatureFlag value
293
+
294
+ To type check the `value` passed to `WithFeatureFlag`, use the `createFlagKeys` helper.
295
+ It returns an object with keys that enable type checking against the passed `value`. For example,
296
+
297
+ ```tsx title='fleet-flag-set.ts'
298
+ import { createFlagKeys } from '@servicetitan/launchdarkly-service';
299
+
300
+ export interface FleetFlagSet {
301
+ enablePermissions: boolean;
302
+ enableBreadcrumbPage: boolean;
303
+ enableAlertsRedesign: boolean;
304
+ triStateFlag: 0 | 1 | 2; // flag has non-boolean value
305
+ }
306
+
307
+ export const FleetFlagKeys = createFlagKeys<FleetFlagSet>( // generates type-aware keys
308
+ 'enablePermissions',
309
+ 'enableBreadcrumbPage',
310
+ 'enableAlertsRedesign',
311
+ 'triStateFlag'
312
+ );
313
+ ```
314
+
315
+ ```tsx
316
+ // Use generated key to enforce that value is correct type, in this case, 0, 1 or 2
317
+ <WithFeatureFlag flagKey={FleetFlagKeys.triStateFlag} value={2} />
318
+
319
+ // Use generated key to type check value passed to custom wrapper
320
+ <WithFleetFeatureFlag flagKey={FleetFlagKeys.triStateFlag} value={2} />
321
+ ```
322
+
323
+ ### Type checking FeatureFlagStore
324
+
325
+ To type check `FeatureFlagStore` keys, pass a type argument that defines the flag set.
326
+ For example,
327
+
328
+ ```tsx title='consumer-store.ts'
329
+ class ConsumerStore {
330
+ constructor(
331
+ @inject(FeatureFlagStore)
332
+ // Establishes that type of this.featureFlagStore.flags is FleetFlagSet
333
+ private readonly featureFlagStore: FeatureFlagStore<FleetFlagSet>
334
+ ) {}
335
+ }
336
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-uikit",
3
- "version": "28.2.0",
3
+ "version": "28.3.1",
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": "df48bdf4994bce3971c7e4f099eeb11ebb4945e6"
19
+ "gitHead": "475386c1ac1891c3e585a2ce694472ad3a1353e8"
20
20
  }