@servicetitan/marketing-ui 1.14.0 → 1.17.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.
Files changed (163) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/dist/components/ads/ads-stat.js +13 -18
  3. package/dist/components/ads/ads-stat.js.map +1 -1
  4. package/dist/components/charts/funnel-chart/components/funnel-chart.js +15 -41
  5. package/dist/components/charts/funnel-chart/components/funnel-chart.js.map +1 -1
  6. package/dist/components/charts/funnel-chart/components/funnel-svg.js +9 -16
  7. package/dist/components/charts/funnel-chart/components/funnel-svg.js.map +1 -1
  8. package/dist/components/charts/funnel-chart/funnel-chart.stories.js +11 -14
  9. package/dist/components/charts/funnel-chart/funnel-chart.stories.js.map +1 -1
  10. package/dist/components/charts/funnel-chart/index.js +2 -16
  11. package/dist/components/charts/funnel-chart/index.js.map +1 -1
  12. package/dist/components/charts/funnel-chart/utils/const.js +2 -5
  13. package/dist/components/charts/funnel-chart/utils/const.js.map +1 -1
  14. package/dist/components/charts/funnel-chart/utils/interface.js +1 -2
  15. package/dist/components/charts/line-chart/components/body.js +26 -51
  16. package/dist/components/charts/line-chart/components/body.js.map +1 -1
  17. package/dist/components/charts/line-chart/components/container.js +12 -15
  18. package/dist/components/charts/line-chart/components/container.js.map +1 -1
  19. package/dist/components/charts/line-chart/components/hover-popover.js +20 -45
  20. package/dist/components/charts/line-chart/components/hover-popover.js.map +1 -1
  21. package/dist/components/charts/line-chart/components/sidebar.js +9 -35
  22. package/dist/components/charts/line-chart/components/sidebar.js.map +1 -1
  23. package/dist/components/charts/line-chart/components/stuff.js +13 -41
  24. package/dist/components/charts/line-chart/components/stuff.js.map +1 -1
  25. package/dist/components/charts/line-chart/components/svg-bars.js +14 -17
  26. package/dist/components/charts/line-chart/components/svg-bars.js.map +1 -1
  27. package/dist/components/charts/line-chart/components/svg-body.js +15 -41
  28. package/dist/components/charts/line-chart/components/svg-body.js.map +1 -1
  29. package/dist/components/charts/line-chart/components/svg-lines.js +11 -33
  30. package/dist/components/charts/line-chart/components/svg-lines.js.map +1 -1
  31. package/dist/components/charts/line-chart/index.js +2 -14
  32. package/dist/components/charts/line-chart/index.js.map +1 -1
  33. package/dist/components/charts/line-chart/line-chart.stories.js +19 -27
  34. package/dist/components/charts/line-chart/line-chart.stories.js.map +1 -1
  35. package/dist/components/charts/line-chart/stores/line-chart.store.js +20 -23
  36. package/dist/components/charts/line-chart/stores/line-chart.store.js.map +1 -1
  37. package/dist/components/charts/line-chart/stores/svg.store.js +10 -13
  38. package/dist/components/charts/line-chart/stores/svg.store.js.map +1 -1
  39. package/dist/components/charts/line-chart/utils/const.js +2 -6
  40. package/dist/components/charts/line-chart/utils/const.js.map +1 -1
  41. package/dist/components/charts/line-chart/utils/formatters.js +7 -11
  42. package/dist/components/charts/line-chart/utils/formatters.js.map +1 -1
  43. package/dist/components/charts/line-chart/utils/interfaces.js +1 -2
  44. package/dist/components/charts/line-chart/utils/internal-interfaces.js +1 -2
  45. package/dist/components/charts/line-chart/utils/key.js +1 -5
  46. package/dist/components/charts/line-chart/utils/key.js.map +1 -1
  47. package/dist/components/charts/line-chart/utils/labels.js +19 -26
  48. package/dist/components/charts/line-chart/utils/labels.js.map +1 -1
  49. package/dist/components/charts/pie-chart/components/pie-chart.js +12 -38
  50. package/dist/components/charts/pie-chart/components/pie-chart.js.map +1 -1
  51. package/dist/components/charts/pie-chart/components/pie.js +20 -27
  52. package/dist/components/charts/pie-chart/components/pie.js.map +1 -1
  53. package/dist/components/charts/pie-chart/index.js +1 -5
  54. package/dist/components/charts/pie-chart/index.js.map +1 -1
  55. package/dist/components/charts/pie-chart/pie-chart.stories.js +11 -18
  56. package/dist/components/charts/pie-chart/pie-chart.stories.js.map +1 -1
  57. package/dist/components/charts/pie-chart/utils/const.js +4 -8
  58. package/dist/components/charts/pie-chart/utils/const.js.map +1 -1
  59. package/dist/components/charts/pie-chart/utils/interface.js +1 -2
  60. package/dist/components/image-cropper/image-cropper.js +17 -23
  61. package/dist/components/image-cropper/image-cropper.js.map +1 -1
  62. package/dist/components/image-cropper/image-cropper.stories.js +10 -14
  63. package/dist/components/image-cropper/image-cropper.stories.js.map +1 -1
  64. package/dist/components/stat/stat-card.js +15 -42
  65. package/dist/components/stat/stat-card.js.map +1 -1
  66. package/dist/components/stat/stat-cards.stories.js +10 -13
  67. package/dist/components/stat/stat-cards.stories.js.map +1 -1
  68. package/dist/components/stat/stat-extended-card.js +9 -35
  69. package/dist/components/stat/stat-extended-card.js.map +1 -1
  70. package/dist/components/stat/stat-extended-card.stories.js +8 -11
  71. package/dist/components/stat/stat-extended-card.stories.js.map +1 -1
  72. package/dist/components/ui/action-button/action-button.d.ts +14 -0
  73. package/dist/components/ui/action-button/action-button.d.ts.map +1 -0
  74. package/dist/components/ui/action-button/action-button.js +32 -0
  75. package/dist/components/ui/action-button/action-button.js.map +1 -0
  76. package/dist/components/ui/action-button/action-button.module.less +51 -0
  77. package/dist/components/ui/action-button/action-button.stories.d.ts +10 -0
  78. package/dist/components/ui/action-button/action-button.stories.d.ts.map +1 -0
  79. package/dist/components/ui/action-button/action-button.stories.js +11 -0
  80. package/dist/components/ui/action-button/action-button.stories.js.map +1 -0
  81. package/dist/components/ui/action-button/index.d.ts +2 -0
  82. package/dist/components/ui/action-button/index.d.ts.map +1 -0
  83. package/dist/components/ui/action-button/index.js +2 -0
  84. package/dist/components/ui/action-button/index.js.map +1 -0
  85. package/dist/components/ui/centered-spinner.js +5 -12
  86. package/dist/components/ui/centered-spinner.js.map +1 -1
  87. package/dist/components/ui/centered-spinner.stories.js +8 -11
  88. package/dist/components/ui/centered-spinner.stories.js.map +1 -1
  89. package/dist/components/ui/date-range-picker/date-range-picker.js +11 -36
  90. package/dist/components/ui/date-range-picker/date-range-picker.js.map +1 -1
  91. package/dist/components/ui/date-range-picker/date-range-picker.stories.js +9 -12
  92. package/dist/components/ui/date-range-picker/date-range-picker.stories.js.map +1 -1
  93. package/dist/components/ui/disabled-button.js +4 -8
  94. package/dist/components/ui/disabled-button.js.map +1 -1
  95. package/dist/components/ui/line-text/index.js +1 -13
  96. package/dist/components/ui/line-text/index.js.map +1 -1
  97. package/dist/components/ui/line-text/line-text-body.stories.js +7 -10
  98. package/dist/components/ui/line-text/line-text-body.stories.js.map +1 -1
  99. package/dist/components/ui/line-text/line-text-head.stories.js +7 -10
  100. package/dist/components/ui/line-text/line-text-head.stories.js.map +1 -1
  101. package/dist/components/ui/line-text/line-text.js +15 -42
  102. package/dist/components/ui/line-text/line-text.js.map +1 -1
  103. package/dist/components/ui/title-popover/index.d.ts +2 -0
  104. package/dist/components/ui/title-popover/index.d.ts.map +1 -0
  105. package/dist/components/ui/title-popover/index.js +2 -0
  106. package/dist/components/ui/title-popover/index.js.map +1 -0
  107. package/dist/components/ui/title-popover/title-popover.d.ts +17 -0
  108. package/dist/components/ui/title-popover/title-popover.d.ts.map +1 -0
  109. package/dist/components/ui/title-popover/title-popover.js +96 -0
  110. package/dist/components/ui/title-popover/title-popover.js.map +1 -0
  111. package/dist/components/ui/title-popover/title-popover.module.less +10 -0
  112. package/dist/components/ui/title-popover/title-popover.stories.d.ts +11 -0
  113. package/dist/components/ui/title-popover/title-popover.stories.d.ts.map +1 -0
  114. package/dist/components/ui/title-popover/title-popover.stories.js +17 -0
  115. package/dist/components/ui/title-popover/title-popover.stories.js.map +1 -0
  116. package/dist/index.d.ts +3 -0
  117. package/dist/index.d.ts.map +1 -1
  118. package/dist/index.js +15 -24
  119. package/dist/index.js.map +1 -1
  120. package/dist/utils/ads-texts.d.ts +1 -1
  121. package/dist/utils/ads-texts.d.ts.map +1 -1
  122. package/dist/utils/ads-texts.js +3 -5
  123. package/dist/utils/ads-texts.js.map +1 -1
  124. package/dist/utils/date/__mocks__/date-mock.js +1 -5
  125. package/dist/utils/date/__mocks__/date-mock.js.map +1 -1
  126. package/dist/utils/date/date-range-picker-options.js +7 -12
  127. package/dist/utils/date/date-range-picker-options.js.map +1 -1
  128. package/dist/utils/date/date-range-picker-state.js +6 -10
  129. package/dist/utils/date/date-range-picker-state.js.map +1 -1
  130. package/dist/utils/date/date-tenant.js +1 -5
  131. package/dist/utils/date/date-tenant.js.map +1 -1
  132. package/dist/utils/date/date.js +3 -9
  133. package/dist/utils/date/date.js.map +1 -1
  134. package/dist/utils/date/index.js +4 -16
  135. package/dist/utils/date/index.js.map +1 -1
  136. package/dist/utils/format-big-numbers.js +1 -5
  137. package/dist/utils/format-big-numbers.js.map +1 -1
  138. package/dist/utils/formatters.js +13 -41
  139. package/dist/utils/formatters.js.map +1 -1
  140. package/dist/utils/helpers.js +2 -7
  141. package/dist/utils/helpers.js.map +1 -1
  142. package/dist/utils/string-case.js +2 -7
  143. package/dist/utils/string-case.js.map +1 -1
  144. package/dist/utils/use-client-rect.js +7 -11
  145. package/dist/utils/use-client-rect.js.map +1 -1
  146. package/dist/utils/use-target-range-store.d.ts +7 -0
  147. package/dist/utils/use-target-range-store.d.ts.map +1 -0
  148. package/dist/utils/use-target-range-store.js +9 -0
  149. package/dist/utils/use-target-range-store.js.map +1 -0
  150. package/package.json +2 -2
  151. package/src/components/ui/action-button/action-button.module.less +51 -0
  152. package/src/components/ui/action-button/action-button.module.less.d.ts +9 -0
  153. package/src/components/ui/action-button/action-button.stories.tsx +19 -0
  154. package/src/components/ui/action-button/action-button.tsx +82 -0
  155. package/src/components/ui/action-button/index.tsx +1 -0
  156. package/src/components/ui/title-popover/index.tsx +1 -0
  157. package/src/components/ui/title-popover/title-popover.module.less +10 -0
  158. package/src/components/ui/title-popover/title-popover.module.less.d.ts +3 -0
  159. package/src/components/ui/title-popover/title-popover.stories.tsx +28 -0
  160. package/src/components/ui/title-popover/title-popover.tsx +86 -0
  161. package/src/index.ts +3 -0
  162. package/src/utils/ads-texts.tsx +4 -1
  163. package/src/utils/use-target-range-store.ts +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/marketing-ui",
3
- "version": "1.14.0",
3
+ "version": "1.17.0",
4
4
  "description": "Marketing UI component and utils",
5
5
  "repository": {
6
6
  "type": "git",
@@ -51,5 +51,5 @@
51
51
  "less": true,
52
52
  "webpack": false
53
53
  },
54
- "gitHead": "b878482bbfa5abbf3a7b63f0685a9088d55a5d17"
54
+ "gitHead": "7f16e97f49ef5de21150d63a93b7abbe8396b89e"
55
55
  }
@@ -0,0 +1,51 @@
1
+ @import (reference) '@servicetitan/tokens/dist/tokens.less';
2
+
3
+ .action-button {
4
+ color: @color-neutral-80;
5
+ padding: @spacing-half @spacing-2;
6
+ box-sizing: border-box;
7
+ border: none;
8
+ background-color: transparent;
9
+ width: 100%;
10
+ display: flex;
11
+ align-items: center;
12
+
13
+ &.active {
14
+ background-color: @color-neutral-60;
15
+ }
16
+
17
+ &.disabled {
18
+ cursor: default;
19
+ color: @color-blue-grey-400;
20
+
21
+ .text {
22
+ color: @color-blue-grey-400;
23
+ }
24
+ }
25
+
26
+ &.primary,
27
+ &.negative {
28
+ &:focus {
29
+ outline: none;
30
+ }
31
+
32
+ &:hover,
33
+ &.focus-visible:focus {
34
+ color: @color-white;
35
+
36
+ .text {
37
+ color: @color-white;
38
+ }
39
+ }
40
+ }
41
+
42
+ &.primary:hover,
43
+ &.primary.focus-visible:focus {
44
+ background-color: @color-blue-400;
45
+ }
46
+
47
+ &.negative:hover,
48
+ &.negative.focus-visible:focus {
49
+ background-color: @color-red-400;
50
+ }
51
+ }
@@ -0,0 +1,9 @@
1
+ export const __esModule: true;
2
+ export const actionButton: string;
3
+ export const active: string;
4
+ export const disabled: string;
5
+ export const text: string;
6
+ export const primary: string;
7
+ export const negative: string;
8
+ export const focusVisible: string;
9
+
@@ -0,0 +1,19 @@
1
+ import { ReactElement } from 'react';
2
+ import { ActionButton } from './action-button';
3
+
4
+ export default {
5
+ title: 'Marketing UI/ui/ActionButton',
6
+ component: ActionButton,
7
+ parameters: {},
8
+ };
9
+
10
+ const w = (style: { width?: string; height?: string }, cb: () => ReactElement) => () =>
11
+ <div style={style}>{cb()}</div>;
12
+
13
+ export const actionButtonHoverPrimary = w({}, () => (
14
+ <ActionButton hover="primary">Button</ActionButton>
15
+ ));
16
+
17
+ export const actionButtonHoverNegative = w({}, () => (
18
+ <ActionButton hover="negative">Button</ActionButton>
19
+ ));
@@ -0,0 +1,82 @@
1
+ import { ReactNode, FC, useRef } from 'react';
2
+ import classnames from 'classnames';
3
+ import {
4
+ Icon,
5
+ BodyText,
6
+ IconNameType,
7
+ Tooltip,
8
+ useFocusVisible,
9
+ } from '@servicetitan/design-system';
10
+ import * as Styles from './action-button.module.less';
11
+
12
+ export interface ActionButtonProps {
13
+ children: ReactNode;
14
+ iconName?: IconNameType;
15
+ hover?: 'primary' | 'negative' | 'none';
16
+ disabled?: boolean;
17
+ tooltip?: string;
18
+ qaPrefix?: string;
19
+ active?: boolean;
20
+ onClick?(): void;
21
+ }
22
+
23
+ export const ActionButton: FC<ActionButtonProps> = ({
24
+ onClick,
25
+ disabled,
26
+ children,
27
+ iconName,
28
+ hover,
29
+ qaPrefix,
30
+ active,
31
+ tooltip,
32
+ }) => {
33
+ const buttonRef = useRef<HTMLButtonElement>(null);
34
+ const { isFocusVisible, focusFunction, blurFunction } = useFocusVisible(buttonRef);
35
+
36
+ const handleClick = () => {
37
+ if (disabled) {
38
+ return;
39
+ }
40
+
41
+ if (onClick) {
42
+ onClick();
43
+ }
44
+ };
45
+
46
+ const getButton = () => {
47
+ const classes = classnames(Styles.actionButton, qaPrefix, {
48
+ [Styles.primary]: hover === 'primary' && !disabled,
49
+ [Styles.negative]: hover === 'negative' && !disabled,
50
+ [Styles.active]: active && !disabled,
51
+ [Styles.disabled]: disabled,
52
+ [Styles.focusVisible]: isFocusVisible,
53
+ });
54
+
55
+ return (
56
+ <button
57
+ type="button"
58
+ ref={buttonRef}
59
+ className={classes}
60
+ onClick={handleClick}
61
+ disabled={disabled}
62
+ onFocus={focusFunction}
63
+ onBlur={blurFunction}
64
+ >
65
+ {iconName && <Icon name={iconName} size="20px" className="m-r-1" />}
66
+ <BodyText className={classnames(Styles.text, `${qaPrefix}-text`)}>
67
+ {children}
68
+ </BodyText>
69
+ </button>
70
+ );
71
+ };
72
+
73
+ if (!tooltip) {
74
+ return getButton();
75
+ }
76
+
77
+ return (
78
+ <Tooltip text={tooltip} direction="l" el="div" className={`${qaPrefix}-tooltip`}>
79
+ {getButton()}
80
+ </Tooltip>
81
+ );
82
+ };
@@ -0,0 +1 @@
1
+ export * from './action-button';
@@ -0,0 +1 @@
1
+ export * from './title-popover';
@@ -0,0 +1,10 @@
1
+ @import (reference) '@servicetitan/tokens/dist/tokens.less';
2
+
3
+ .popover {
4
+ padding: @spacing-0;
5
+
6
+ :global(.Popover__content) {
7
+ padding: @spacing-half @spacing-0;
8
+ overflow: visible;
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ export const __esModule: true;
2
+ export const popover: string;
3
+
@@ -0,0 +1,28 @@
1
+ import { ReactElement, useState } from 'react';
2
+ import { ActionButton } from '../action-button/action-button';
3
+ import { TitlePopover } from './title-popover';
4
+
5
+ export default {
6
+ title: 'Marketing UI/ui/TitlePopover',
7
+ component: TitlePopover,
8
+ parameters: {},
9
+ };
10
+
11
+ const w = (style: { width?: string; height?: string }, cb: () => ReactElement) => () =>
12
+ <div style={style}>{cb()}</div>;
13
+
14
+ export const titlePopover = w({}, () => <TitlePopover text="Title text">Content</TitlePopover>);
15
+ export const titlePopoverToggle = w({}, () => {
16
+ const [isActive, setIsActive] = useState(true);
17
+ const title = isActive ? 'Entities' : 'Archived Entities';
18
+ return (
19
+ <TitlePopover text={title}>
20
+ <ActionButton hover="primary" active={isActive} onClick={() => setIsActive(true)}>
21
+ Entities
22
+ </ActionButton>
23
+ <ActionButton hover="primary" active={!isActive} onClick={() => setIsActive(false)}>
24
+ Archived Entities
25
+ </ActionButton>
26
+ </TitlePopover>
27
+ );
28
+ });
@@ -0,0 +1,86 @@
1
+ import classNames from 'classnames';
2
+ import { observer } from 'mobx-react';
3
+ import { createRef, Component } from 'react';
4
+ import { observable, action, makeObservable } from 'mobx';
5
+ import { Popover, Stack, BodyText, Icon } from '@servicetitan/design-system';
6
+ import * as Styles from './title-popover.module.less';
7
+
8
+ interface TitlePopoverProps {
9
+ text?: string;
10
+ }
11
+
12
+ @observer
13
+ export class TitlePopover extends Component<TitlePopoverProps> {
14
+ @observable isOpen = false;
15
+
16
+ wrapElem = createRef<HTMLDivElement>();
17
+
18
+ constructor(props: TitlePopoverProps) {
19
+ super(props);
20
+ makeObservable(this);
21
+ }
22
+
23
+ @action
24
+ toggle = () => {
25
+ this.isOpen = !this.isOpen;
26
+ };
27
+
28
+ @action
29
+ close = () => {
30
+ this.isOpen = false;
31
+ };
32
+
33
+ @action
34
+ handleClick = (event: MouseEvent) => {
35
+ if (!this.wrapElem.current) {
36
+ return;
37
+ }
38
+
39
+ const isClickedInside = this.wrapElem.current.contains(event.target as Node);
40
+
41
+ if (!isClickedInside) {
42
+ this.close();
43
+ }
44
+ };
45
+
46
+ componentDidMount() {
47
+ window.addEventListener('click', this.handleClick);
48
+ }
49
+
50
+ componentWillUnmount() {
51
+ window.removeEventListener('click', this.handleClick);
52
+ }
53
+
54
+ render() {
55
+ const { text, children } = this.props;
56
+
57
+ return (
58
+ <div ref={this.wrapElem} className="qa-title-popover">
59
+ <Popover
60
+ className={classNames(Styles.popover, 'qa-title-popover')}
61
+ width="xs"
62
+ open={this.isOpen}
63
+ direction="br"
64
+ trigger={
65
+ <Stack
66
+ alignItems="center"
67
+ className="qa-title-popover-button cursor-pointer"
68
+ onClick={this.toggle}
69
+ >
70
+ <BodyText size="large" className="qa-title-popover-text">
71
+ {text}
72
+ </BodyText>
73
+ <Icon
74
+ name="expand_more"
75
+ size={20}
76
+ className="m-l-1 qa-title-popover-icon"
77
+ />
78
+ </Stack>
79
+ }
80
+ >
81
+ {children}
82
+ </Popover>
83
+ </div>
84
+ );
85
+ }
86
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  export * from './components/stat/stat-card';
2
2
  export * from './components/stat/stat-extended-card';
3
3
  export * from './components/ads/ads-stat';
4
+ export * from './components/ui/action-button';
4
5
  export * from './components/ui/centered-spinner';
5
6
  export * from './components/ui/line-text';
7
+ export * from './components/ui/title-popover';
6
8
  export * from './components/image-cropper/image-cropper';
7
9
 
8
10
  export * from './utils/ads-texts';
@@ -11,3 +13,4 @@ export * from './utils/string-case';
11
13
  export * from './utils/use-client-rect';
12
14
  export * from './utils/helpers';
13
15
  export * from './utils/format-big-numbers';
16
+ export * from './utils/use-target-range-store';
@@ -29,6 +29,7 @@ export type AdsStatType =
29
29
  | 'averageJobValue'
30
30
  | 'roi'
31
31
  | 'bookingRate'
32
+ | 'callBookingRate'
32
33
  | 'opportunityRate'
33
34
  | 'newCustomerLeads'
34
35
  | 'newCustomerLeadRate'
@@ -49,7 +50,8 @@ export const adsStatDescriptions: Record<AdsStatType, string> = {
49
50
  leads: 'Phone Calls that are longer than 60 seconds and not dismissed, plus online bookings and manual jobs',
50
51
  ranJobs:
51
52
  'A booking where a truck was dispatched. On the marketing dashboard, we show Ran Jobs that have marketing attribution',
52
- ranRate: 'The percentage of leads that turned into Ran Jobs',
53
+ ranRate:
54
+ 'The percentage of Booked Jobs that turned into Ran Jobs. This is a measure of how many booked jobs are not cancelled or left unfulfilled',
53
55
  bookedJobs: 'Leads that were booked/scheduled for a job',
54
56
  completedJobs: 'Scheduled jobs that were actually completed',
55
57
  soldJobs:
@@ -79,6 +81,7 @@ export const adsStatDescriptions: Record<AdsStatType, string> = {
79
81
  averageJobValue: 'The average income generated across all your jobs',
80
82
  roi: 'The number of dollars generated from each dollar of marketing spend. For example, and ROI of 5x means that every $1 spent on marketing leads to $5 of revenue',
81
83
  bookingRate: 'The percentage of leads that resulted in Booked Job',
84
+ callBookingRate: 'The percentage of lead calls that resulted in Booked Jobs',
82
85
  opportunityRate: 'The percentage of Ran Jobs that resulted in an Opportunity',
83
86
  newCustomerLeads:
84
87
  'Leads that came from someone not already part of your database, ie. you have never ran a job for them before',
@@ -0,0 +1,17 @@
1
+ import { useLocalStore } from 'mobx-react';
2
+ import { action } from 'mobx';
3
+
4
+ export type OptionalRange = Range | undefined;
5
+
6
+ export interface TargetRangeStore {
7
+ targetRange: OptionalRange;
8
+ setTargetRange: (range: OptionalRange) => void;
9
+ }
10
+
11
+ export const useTargetRangeStore = () =>
12
+ useLocalStore<TargetRangeStore>(() => ({
13
+ targetRange: undefined,
14
+ setTargetRange: action(function (this: TargetRangeStore, range: OptionalRange) {
15
+ this.targetRange = range;
16
+ }),
17
+ }));