@servicetitan/docs-anvil-uikit-contrib 32.4.1 → 32.5.0

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.
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: IntlProvider
3
+ ---
4
+
5
+ Applications must be wrapped with the `<IntlProvider>` component in order to access internationalization features throughout the application.
6
+
7
+ `locale` and `timeZone` may be passed to the provider via the `config` prop. `locale` defaults to `en-US` and `timeZone` defaults to the user's local time zone if not provided.
8
+
9
+ The config object must be wrapped with `useMemo` to avoid unnecessary re-renders.
10
+
11
+ ```tsx
12
+ import { IntlConfig, IntlProvider } from '@servicetitan/intl';
13
+
14
+ const locale = 'en-US';
15
+ const timeZone = 'America/Los_Angeles';
16
+ const intlConfig: IntlConfig = useMemo(() => ({ locale, timeZone }), [locale, timeZone]);
17
+ return (
18
+ <IntlProvider config={intlConfig}>
19
+ <App />
20
+ </IntlProvider>
21
+ );
22
+ ```
@@ -0,0 +1,23 @@
1
+ ---
2
+ title: IntlStoreProvider
3
+ ---
4
+
5
+ Applications may be wrapped with the `<IntlStoreProvider>` component in order to provide access to internationalization features in MobX stores.
6
+
7
+ `<IntlStoreProvider>` must be a child of `<IntlProvider>`, and should be placed as high in the component tree as possible to ensure all stores have access to the `IntlStore`.
8
+
9
+ ```tsx
10
+ import { IntlProvider } from '@servicetitan/intl';
11
+ import { IntlStoreProvider } from '@servicetitan/intl/mobx';
12
+
13
+ const locale = 'en-US';
14
+ const timeZone = 'America/Los_Angeles';
15
+ const intlConfig: IntlConfig = useMemo(() => ({ locale, timeZone }), [locale, timeZone]);
16
+ return (
17
+ <IntlProvider config={intlConfig}>
18
+ <IntlStoreProvider>
19
+ <App />
20
+ </IntlStoreProvider>
21
+ </IntlProvider>
22
+ );
23
+ ```
@@ -0,0 +1,38 @@
1
+ ---
2
+ title: IntlStore
3
+ ---
4
+
5
+ The `IntlStore` is a dependency injected store that provides access to internationalization functionality in MobX stores in situations where formatting within React components is not possible.
6
+
7
+ :::note
8
+ It is preferred to use the [`useIntl` hook](./use-intl.mdx) instead of directly accessing the `IntlStore`, as it is preferred to do formatting in the "view" layer of your application vs the "data" layer.
9
+ :::
10
+
11
+ ## Overview
12
+
13
+ The `IntlStore` is an injectable store that maintains an [`intl`](https://formatjs.github.io/docs/react-intl/api#intlshape) object with the same formatting functions and locale information available through the [`useIntl`](./use-intl.mdx) hook. It extends the standard `react-intl` functionality with custom ServiceTitan formatters. The `IntlStore` is provided by a combination of [`IntlProvider`](./intl-provider.mdx) and [`IntlStoreProvider`](./intl-store-provider.mdx), and is updated when `IntlProvider`'s props change.
14
+
15
+ ## Basic Usage
16
+
17
+ ```tsx
18
+ import { inject, injectable } from '@servicetitan/react-ioc';
19
+ import { IntlStore } from '@servicetitan/intl/mobx';
20
+
21
+ @injectable()
22
+ export class UserService {
23
+ constructor(@inject(IntlStore) private intlStore: IntlStore) {}
24
+
25
+ formatUserData(user: User) {
26
+ const intl = this.intlStore.intl;
27
+
28
+ return {
29
+ joinDate: intl.formatDate(user.joinDate, { format: 'long' }),
30
+ balance: intl.formatNumber(user.balance, { style: 'currency', currency: 'USD' })
31
+ };
32
+ }
33
+ }
34
+ ```
35
+
36
+ ## Available Functions
37
+
38
+ See [`useIntl`](./use-intl.mdx#available-functions) for a list of functions and properties available in the `intl` object.
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: useIntl
3
+ ---
4
+
5
+ The `useIntl` hook is the primary way to access direct internationalization functions in your React components. It provides access to all formatting functions and locale information needed for internationalization.
6
+
7
+ :::note
8
+ If using [`react-intl` Formatted components](https://formatjs.github.io/docs/react-intl/components)--such as those described in [Dates and Time](../dates.mdx), [Numbers and Currency](../numbers.mdx), and [Plurals](../plurals.mdx) documentation--you do not need to use the `useIntl` hook directly.
9
+ :::
10
+
11
+ ## Overview
12
+
13
+ The `useIntl` hook extends the standard [`react-intl` `useIntl`](https://formatjs.github.io/docs/react-intl/api/#useintl-hook) hook with additional custom formatters specific to ServiceTitan applications. It returns an `intl` object that contains all the formatting functions and locale information.
14
+
15
+ ## Basic Usage
16
+
17
+ ```tsx
18
+ import { useIntl } from '@servicetitan/intl';
19
+
20
+ function MyComponent() {
21
+ const intl = useIntl();
22
+
23
+ return (
24
+ <div>
25
+ <p>Current locale: {intl.locale}</p>
26
+ <p>Current timezone: {intl.timeZone}</p>
27
+ <p>Formatted date: {intl.formatDate(new Date(), { format: 'short' })}</p>
28
+ <p>Formatted currency: {intl.formatNumber(1234.56, { style: 'currency', currency: 'USD' })}</p>
29
+ </div>
30
+ );
31
+ }
32
+ ```
33
+
34
+ ## Available Functions
35
+
36
+ The [`intl`](https://formatjs.github.io/docs/react-intl/api#intlshape) object returned by `useIntl` provides access to [all standard `Format.js` formatting functions](https://formatjs.github.io/docs/react-intl/api#intlshape), plus custom ServiceTitan formatters:
37
+
38
+ ### Standard Formatting Functions
39
+
40
+ - [`formatDate()`](../dates.mdx) - Format dates and times
41
+ - [`formatDisplayName()`](https://formatjs.github.io/docs/react-intl/api/#formatdisplayname) - Format display names for locales, currencies, etc.
42
+ - [`formatList()`](https://formatjs.github.io/docs/react-intl/api/#formatlist) - Format lists of items
43
+ - [`formatMessage()`](https://formatjs.github.io/docs/react-intl/api/#formatmessage) - Format messages with interpolation (note: translating messages is not yet configured within ServiceTitan)
44
+ - [`formatNumber()`](../numbers.mdx) - Format numbers and currency
45
+ - [`formatPlural()`](https://formatjs.github.io/docs/react-intl/api/#formatplural) - Handle pluralization
46
+ - [`formatRelativeTime()`](https://formatjs.github.io/docs/react-intl/api/#formatrelativetime) - Format relative time (e.g., "2 hours ago")
47
+ - [`formatTime()`](https://formatjs.github.io/docs/react-intl/api/#formattime) - Format time values
48
+
49
+ ### Custom ServiceTitan Formatters
50
+
51
+ - [`formatPluralMessage()`](../plurals.mdx#formatpluralmessage) - Provide a number and messages associated with plural forms, and receive the appropriate message for the current locale and plural form
52
+
53
+ ### Locale Information
54
+
55
+ - `locale` - Current locale (e.g., 'en-US')
56
+ - `timeZone` - Current time zone
57
+ - `messages` - Available messages for the current locale (note: translating messages is not yet configured within ServiceTitan)
58
+
59
+ ## See Also
60
+
61
+ For detailed information about specific formatting functions and their options, refer to the Format.js documentation:
62
+
63
+ - [useIntl Hook Documentation](https://formatjs.github.io/docs/react-intl/api/#useintl-hook) which our `useIntl` is a wrapper around
64
+ - [Format.JS Imperative API](https://formatjs.github.io/docs/react-intl/api/) contains all of the formatting functions available on the `intl` object
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: Dates and Times
3
+ ---
4
+
5
+ import Tabs from '@theme/Tabs';
6
+
7
+ Dates and times can be formatted either by using the [`FormattedDate`](#formatteddate) component from `react-intl`, or via the [`formatDate`](#formatdate) function as part of the `intl` object, which can be retrieved via the [`useIntl`](./API/use-intl.mdx) hook or through the [`IntlStore`](./API/intlstore.mdx) store.
8
+
9
+ ## Available Formats
10
+
11
+ The following standard ServiceTitan formats are available to use as part of date/time formatting. The formats follow the "Dates and time" section of the ["Style Guide - General guidelines"](https://servicetitan.atlassian.net/wiki/spaces/DTW/pages/262701057/Style+Guide+-+General+guidelines#Dates-and-time).
12
+
13
+ - `short` results in `09/02/25`
14
+ - `long` results in `September 2, 2025`
15
+ - `timeShort` results in `4:00 PM`
16
+ - `timeMedium` results in `4:00:00 PM`
17
+
18
+ ## Usage
19
+
20
+ ### FormattedDate
21
+
22
+ ```tsx
23
+ import { FormattedDate } from 'react-intl';
24
+ ...
25
+ <FormattedDate value={new Date()} format="short" />
26
+ // Results in 09/02/25
27
+ <FormattedDate value={new Date()} format="long" />
28
+ // Results in September 2, 2025
29
+ <FormattedDate value={new Date()} format="timeShort" />
30
+ // Results in 4:00 PM
31
+ <FormattedDate value={new Date()} format="timeMedium" />
32
+ // Results in 4:00:00 PM
33
+ ```
34
+
35
+ ### formatDate
36
+
37
+ <Tabs
38
+ defaultValue="hooks"
39
+ values={[
40
+ { label: 'React hooks', value: 'hooks' },
41
+ { label: 'Store', value: 'store' },
42
+ ]}
43
+ >
44
+ <TabItem value="hooks">
45
+
46
+ ```tsx
47
+ import { useIntl } from '@servicetitan/intl';
48
+ ...
49
+ const intl = useIntl();
50
+ ...
51
+ intl.formatDate(new Date(), { format: 'short' });
52
+ // Results in 09/02/25
53
+ intl.formatDate(new Date(), { format: 'long' });
54
+ // Results in September 2, 2025
55
+ intl.formatDate(new Date(), { format: 'timeShort' });
56
+ // Results in 4:00 PM
57
+ intl.formatDate(new Date(), { format: 'timeMedium' });
58
+ // Results in 4:00:00 PM
59
+ ```
60
+
61
+ </TabItem>
62
+ <TabItem value="store">
63
+
64
+ ```tsx
65
+ import { IntlStore } from '@servicetitan/intl/mobx';
66
+ ...
67
+ @injectable()
68
+ class MyStore {
69
+ constructor(@inject(IntlStore) private readonly intlStore: IntlStore) {}
70
+ ...
71
+ this.intlStore.intl.formatDate(new Date(), { format: 'short' });
72
+ // Results in 09/02/25
73
+ this.intlStore.intl.formatDate(new Date(), { format: 'long' });
74
+ // Results in September 2, 2025
75
+ this.intlStore.intl.formatDate(new Date(), { format: 'timeShort' });
76
+ // Results in 4:00 PM
77
+ this.intlStore.intl.formatDate(new Date(), { format: 'timeMedium' });
78
+ // Results in 4:00:00 PM
79
+ ...
80
+ }
81
+ ```
82
+
83
+ </TabItem>
84
+ </Tabs>
85
+
86
+ ### Further customization
87
+
88
+ If you need to customize the formatting further, `FormattedDate` and `formatDate` accept the same options as the native `Intl.DateTimeFormat` API. See [`Intl.DateTimeFormat` for more information about those options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat), and see Format.js [`FormattedDate` documentation](https://formatjs.github.io/docs/react-intl/components/#formatteddate) or [`formatDate` documentation](https://formatjs.github.io/docs/react-intl/api/#formatdate) for more information on how to use them.
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Intl (Internationalization)
3
+ ---
4
+
5
+ `@servicetitan/intl` is a solution for helping setup internationalization in React and MobX projects that is a light wrapper around [`Format.js`](https://formatjs.github.io/) and [`react-intl`](https://formatjs.github.io/docs/react-intl/). This library creates an internationalization API with a provided *locale* and *timeZone*, and provides that API to `react-intl` to be used within React context, as well as a store to be used within MobX.
6
+
7
+ ## Setup
8
+
9
+ This project should be installed as one of your project's `dependencies`:
10
+
11
+ ```bash
12
+ npm install @servicetitan/intl
13
+ ```
14
+
15
+ This library has `peerDependencies` for:
16
+ - `"@servicetitan/react-ioc": ">=22.0.0"`
17
+ - `"react-intl": ">=7.1.11"`
18
+
19
+ ### IntlProvider
20
+
21
+ Wrap your application in the `<IntlProvider>` component, providing `locale` and `timeZone` through the `config` prop:
22
+
23
+ ```tsx
24
+ import { IntlProvider } from '@servicetitan/intl';
25
+
26
+ const locale = 'en-US';
27
+ const timeZone = 'America/Los_Angeles';
28
+ const intlConfig: IntlConfig = useMemo(() => ({ locale, timeZone }), [locale, timeZone]);
29
+ return (
30
+ <IntlProvider config={intlConfig}>
31
+ <App />
32
+ </IntlProvider>
33
+ );
34
+ ```
35
+
36
+ ## Features
37
+
38
+ `Format.js` and `react-intl` provide many components and utilities for handling internationalization, including caching and wrapping most of the [native `Intl` formatters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). The following APIs are are particularly useful to us at this stage:
39
+
40
+ - [Formatting dates and time](./dates.mdx)
41
+ - [Formatting numbers and currency](./numbers.mdx)
42
+ - [Plurals](./plurals.mdx)
43
+
44
+ :::note
45
+ Translating messages is not yet supported, as we currently have no need for it. But using `@servicetitan/intl` ensures the framework is in place for when we do begin translating messages.
46
+ :::
47
+
48
+ ## React Hooks vs Store
49
+
50
+ We recommend using the hooks API to access the internationalization API for most cases, as it is preferred to do formatting in the "view" layer of your application vs the "data" layer.
51
+
52
+ ```tsx
53
+ import { useIntl } from '@servicetitan/intl';
54
+
55
+ function MyComponent() {
56
+ const intl = useIntl();
57
+
58
+ return (
59
+ <div>
60
+ <p>Formatted date: {intl.formatDate(new Date(), { format: 'short' })}</p>
61
+ <p>Formatted currency: {intl.formatNumber(1234.56, { style: 'currency', currency: 'USD' })}</p>
62
+ </div>
63
+ );
64
+ }
65
+ ```
66
+
67
+ However, if you have the need to access the internationalization API in MobX stores, you must use an additional wrapper component, [`<IntlStoreProvider>`](./API/intl-store-provider.mdx), and you can use the provided `IntlStore` to access the same functionality.
68
+
69
+ ```tsx
70
+ import { inject, injectable } from '@servicetitan/react-ioc';
71
+ import { IntlStore } from '@servicetitan/intl/mobx';
72
+
73
+ @injectable()
74
+ export class UserService {
75
+ constructor(@inject(IntlStore) private intlStore: IntlStore) {}
76
+
77
+ formatUserData(user: User) {
78
+ const intl = this.intlStore.intl;
79
+
80
+ return {
81
+ joinDate: intl.formatDate(user.joinDate, { format: 'long' }),
82
+ balance: intl.formatNumber(user.balance, { style: 'currency', currency: 'USD' })
83
+ };
84
+ }
85
+ }
86
+ ```
@@ -0,0 +1,64 @@
1
+ ---
2
+ title: Numbers and Currency
3
+ ---
4
+
5
+ import Tabs from '@theme/Tabs';
6
+
7
+ Numbers and currency can be formatted either by using the `FormattedNumber` component from `react-intl`, or via the `formatNumber()` function as part of the `intl` object, which can be retrieved via the [`useIntl()`](./API/use-intl.mdx) hook or through the [`IntlStore`](./API/intlstore.mdx) store.
8
+
9
+ ## Usage
10
+
11
+ ### FormattedNumber
12
+
13
+ ```tsx
14
+ import { FormattedNumber } from 'react-intl';
15
+ ...
16
+ <FormattedNumber value={1234.56} style="currency" currency="USD" />
17
+ <FormattedNumber value={0.75} style="percent" />
18
+ <FormattedNumber value={1234.567} maximumFractionDigits={2} />
19
+ ```
20
+
21
+ ### formatNumber
22
+
23
+ <Tabs
24
+ defaultValue="hooks"
25
+ values={[
26
+ { label: 'React hooks', value: 'hooks' },
27
+ { label: 'Store', value: 'store' },
28
+ ]}
29
+ >
30
+ <TabItem value="hooks">
31
+
32
+ ```tsx
33
+ import { useIntl } from '@servicetitan/intl';
34
+ ...
35
+ const intl = useIntl();
36
+ ...
37
+ intl.formatNumber(1234.56, { style: 'currency', currency: 'USD' });
38
+ intl.formatNumber(0.75, { style: 'percent' });
39
+ intl.formatNumber(1234.567, { maximumFractionDigits: 2 });
40
+ ```
41
+
42
+ </TabItem>
43
+ <TabItem value="store">
44
+
45
+ ```tsx
46
+ import { IntlStore } from '@servicetitan/intl/mobx';
47
+ ...
48
+ @injectable()
49
+ class MyStore {
50
+ constructor(@inject(IntlStore) private readonly intlStore: IntlStore) {}
51
+ ...
52
+ this.intlStore.intl.formatNumber(1234.56, { style: 'currency', currency: 'USD' });
53
+ this.intlStore.intl.formatNumber(0.75, { style: 'percent' });
54
+ this.intlStore.intl.formatNumber(1234.567, { maximumFractionDigits: 2 });
55
+ ...
56
+ }
57
+ ```
58
+
59
+ </TabItem>
60
+ </Tabs>
61
+
62
+ ### Further customization
63
+
64
+ If you need to customize the formatting further, `FormattedNumber` and `formatNumber` accept the same options as the native `Intl.NumberFormat` API. See [`Intl.NumberFormat` for more information about those options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat), and see Format.js [`FormattedNumber` documentation](https://formatjs.github.io/docs/react-intl/components/#formattednumber) or [`formatNumber` documentation](https://formatjs.github.io/docs/react-intl/api/#formatnumber) for more information on how to use them.
@@ -0,0 +1,75 @@
1
+ ---
2
+ title: Plurals
3
+ ---
4
+
5
+ import Tabs from '@theme/Tabs';
6
+
7
+ Plurals can be formatted by using the `FormattedPlural` component from `react-intl`, or via the `formatPluralMessage()` function as part of the `intl` object, which can be retrieved via the [`useIntl()`](./API/use-intl.mdx) hook or through the [`IntlStore`](./API/intlstore.mdx) store.
8
+
9
+ [`FormattedPlural`](#formattedplural) and [`formatPluralMessage()`](#formatpluralmessage) are only meant to be used with one language. Since ServiceTitan currently only supports English, and [English only uses "one" and "other" forms](https://www.unicode.org/cldr/charts/42/supplemental/language_plural_rules.html#en), those will be the only forms you will use at this time.
10
+
11
+ :::note
12
+ When ServiceTitan eventually supports multiple languages, the library will be updated to support `FormattedMessage` and `formatMessage`.
13
+ :::
14
+
15
+ ## Usage
16
+
17
+ ### FormattedPlural
18
+
19
+ See Format.js [FormattedPlural documentation](https://formatjs.github.io/docs/react-intl/components/#formattedplural) for more information.
20
+
21
+ ```tsx
22
+ import { FormattedPlural } from 'react-intl';
23
+ ...
24
+ <FormattedPlural value={5} one="item" other="items" />
25
+ ```
26
+
27
+ ### formatPluralMessage
28
+
29
+ `formatPluralMessage` is a custom formatter which accepts a number value, an object of messages keyed by plural forms, and [`Intl.PluralRules` options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules/PluralRules#options). It returns the message corresponding to the plural form of the value for the current locale.
30
+
31
+ | Name | Type | Description |
32
+ | :--------- | :-------------------- | :--------------------------------------------------- |
33
+ | `value` | `number` | The number value to determine the plural form. |
34
+ | `messages` | `PluralMessages` | An object containing messages keyed by plural forms. |
35
+ | `options?` | `FormatPluralOptions` | [Options to customize the pluralization behavior](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules/PluralRules#options). Defaults to using "cardinal".
36
+
37
+ <Tabs
38
+ defaultValue="hooks"
39
+ values={[
40
+ { label: 'React hooks', value: 'hooks' },
41
+ { label: 'Store', value: 'store' },
42
+ ]}
43
+ >
44
+ <TabItem value="hooks">
45
+
46
+ ```tsx
47
+ import { useIntl } from '@servicetitan/intl';
48
+ ...
49
+ const intl = useIntl();
50
+ ...
51
+ intl.formatPluralMessage(1, { one: 'item', other: 'items' });
52
+ // Results in "item"
53
+ intl.formatPluralMessage(3, { one: 'item', other: 'items' });
54
+ // Results in "items"
55
+ ```
56
+
57
+ </TabItem>
58
+ <TabItem value="store">
59
+
60
+ ```tsx
61
+ import { IntlStore } from '@servicetitan/intl/mobx';
62
+ ...
63
+ @injectable()
64
+ class MyStore {
65
+ constructor(@inject(IntlStore) private readonly intlStore: IntlStore) {}
66
+ ...
67
+ this.intlStore.intl.formatPluralMessage(1, { one: 'item', other: 'items' });
68
+ // Results in "item"
69
+ this.intlStore.intl.formatPluralMessage(3, { one: 'item', other: 'items' });
70
+ // Results in "items"
71
+ }
72
+ ```
73
+
74
+ </TabItem>
75
+ </Tabs>
@@ -4,7 +4,7 @@ title: TanStack Query MobX Integration
4
4
 
5
5
  import {
6
6
  AppExample, HasInitialDataExample, NoInitialDataExample, PageExample, StaleTime0Example, StaleTime10MinutesExample
7
- } from '@servicetitan/tanstack-query-mobx/dist/demo';
7
+ } from '@servicetitan/tanstack-query-mobx/demo';
8
8
 
9
9
  import { CodeDemo } from '@site/src/components/code-demo';
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/docs-anvil-uikit-contrib",
3
- "version": "32.4.1",
3
+ "version": "32.5.0",
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": "5bc4f3c9c8a181df124fdc614964757e5490ea9b"
19
+ "gitHead": "25988db91418cf6ff9018760bd03ef6c3d7ef8ec"
20
20
  }