@servicetitan/mpa-components 0.5.0 → 1.0.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 (61) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/lib/components/settings/company-details/index.d.ts +5 -0
  3. package/lib/components/settings/company-details/index.d.ts.map +1 -1
  4. package/lib/components/settings/company-details/index.js +4 -3
  5. package/lib/components/settings/company-details/index.js.map +1 -1
  6. package/lib/components/settings/company-email-footer/index.d.ts +3 -0
  7. package/lib/components/settings/company-email-footer/index.d.ts.map +1 -1
  8. package/lib/components/settings/company-email-footer/index.js +2 -2
  9. package/lib/components/settings/company-email-footer/index.js.map +1 -1
  10. package/lib/components/settings/company-email-reply-to/index.d.ts +3 -0
  11. package/lib/components/settings/company-email-reply-to/index.d.ts.map +1 -1
  12. package/lib/components/settings/company-email-reply-to/index.js +2 -2
  13. package/lib/components/settings/company-email-reply-to/index.js.map +1 -1
  14. package/lib/components/settings/company-email-sender/custom-domain-sender.d.ts +3 -0
  15. package/lib/components/settings/company-email-sender/custom-domain-sender.d.ts.map +1 -1
  16. package/lib/components/settings/company-email-sender/custom-domain-sender.js +2 -2
  17. package/lib/components/settings/company-email-sender/custom-domain-sender.js.map +1 -1
  18. package/lib/components/settings/company-email-sender/simple-sender.d.ts +3 -0
  19. package/lib/components/settings/company-email-sender/simple-sender.d.ts.map +1 -1
  20. package/lib/components/settings/company-email-sender/simple-sender.js +2 -2
  21. package/lib/components/settings/company-email-sender/simple-sender.js.map +1 -1
  22. package/lib/components/settings/company-trades-picker/index.d.ts +7 -2
  23. package/lib/components/settings/company-trades-picker/index.d.ts.map +1 -1
  24. package/lib/components/settings/company-trades-picker/index.js +4 -4
  25. package/lib/components/settings/company-trades-picker/index.js.map +1 -1
  26. package/lib/components/settings/double-opt-in/index.d.ts +3 -0
  27. package/lib/components/settings/double-opt-in/index.d.ts.map +1 -1
  28. package/lib/components/settings/double-opt-in/index.js +2 -2
  29. package/lib/components/settings/double-opt-in/index.js.map +1 -1
  30. package/lib/components/settings/form-errors-list/index.d.ts +1 -0
  31. package/lib/components/settings/form-errors-list/index.d.ts.map +1 -1
  32. package/lib/components/settings/form-errors-list/index.js +3 -2
  33. package/lib/components/settings/form-errors-list/index.js.map +1 -1
  34. package/lib/components/settings/logo-picker/index.d.ts +1 -0
  35. package/lib/components/settings/logo-picker/index.d.ts.map +1 -1
  36. package/lib/components/settings/logo-picker/index.js +2 -2
  37. package/lib/components/settings/logo-picker/index.js.map +1 -1
  38. package/lib/components/settings/opt-out-message/index.d.ts +3 -0
  39. package/lib/components/settings/opt-out-message/index.d.ts.map +1 -1
  40. package/lib/components/settings/opt-out-message/index.js +2 -2
  41. package/lib/components/settings/opt-out-message/index.js.map +1 -1
  42. package/lib/components/settings/result-definitions-modal/row.js +3 -3
  43. package/lib/components/settings/result-definitions-modal/row.js.map +1 -1
  44. package/lib/components/settings/settings-section/index.d.ts +3 -1
  45. package/lib/components/settings/settings-section/index.d.ts.map +1 -1
  46. package/lib/components/settings/settings-section/index.js +1 -1
  47. package/lib/components/settings/settings-section/index.js.map +1 -1
  48. package/package.json +7 -6
  49. package/src/components/settings/company-details/index.tsx +15 -4
  50. package/src/components/settings/company-email-footer/index.tsx +6 -2
  51. package/src/components/settings/company-email-reply-to/index.tsx +32 -26
  52. package/src/components/settings/company-email-sender/custom-domain-sender.tsx +6 -2
  53. package/src/components/settings/company-email-sender/simple-sender.tsx +6 -2
  54. package/src/components/settings/company-trades-picker/index.tsx +17 -7
  55. package/src/components/settings/double-opt-in/index.tsx +116 -110
  56. package/src/components/settings/form-errors-list/index.tsx +31 -27
  57. package/src/components/settings/logo-picker/index.tsx +12 -8
  58. package/src/components/settings/opt-out-message/index.tsx +6 -3
  59. package/src/components/settings/result-definitions-modal/row.tsx +3 -3
  60. package/src/components/settings/settings-section/index.tsx +12 -7
  61. package/tsconfig.tsbuildinfo +1 -1
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react';
3
3
  import classnames from 'classnames';
4
4
 
5
5
  import { CheckboxFieldState, InputFieldState, TextAreaFieldState } from '@servicetitan/form';
6
- import { Form, Text, ToggleSwitch, Button } from '@servicetitan/design-system';
6
+ import { Form, Text, ToggleSwitch, Button, LayoutProps } from '@servicetitan/design-system';
7
7
  import { useConfirm } from '@servicetitan/confirm';
8
8
 
9
9
  import { SettingsSection } from '../settings-section';
@@ -23,121 +23,127 @@ export interface DoubleOptInPropsFormState {
23
23
  }
24
24
  export interface DoubleOptInProps {
25
25
  formState: DoubleOptInPropsFormState;
26
+ layout?: LayoutProps['type'];
27
+ className?: string;
26
28
  onHandleClickEnable?(checkd: boolean): void;
27
29
  }
28
30
 
29
- export const DoubleOptIn: FC<DoubleOptInProps> = observer(({ onHandleClickEnable, formState }) => {
30
- const { emailSubject, emailHeader, emailBody, emailButtonText, enabled } = formState;
31
- const [isPreviewOpen, setIsPreviewOpen] = useState(false);
32
- const openPreview = useCallback(() => setIsPreviewOpen(true), [setIsPreviewOpen]);
33
- const closePreview = useCallback(() => setIsPreviewOpen(false), [setIsPreviewOpen]);
31
+ export const DoubleOptIn: FC<DoubleOptInProps> = observer(
32
+ ({ onHandleClickEnable, formState, layout, className }) => {
33
+ const { emailSubject, emailHeader, emailBody, emailButtonText, enabled } = formState;
34
+ const [isPreviewOpen, setIsPreviewOpen] = useState(false);
35
+ const openPreview = useCallback(() => setIsPreviewOpen(true), [setIsPreviewOpen]);
36
+ const closePreview = useCallback(() => setIsPreviewOpen(false), [setIsPreviewOpen]);
34
37
 
35
- const handleClickEnable = useCallback(
36
- (_0: any, checked: boolean) => {
37
- onHandleClickEnable?.(checked);
38
- enabled.onChange(checked);
39
- },
40
- [enabled, onHandleClickEnable]
41
- );
38
+ const handleClickEnable = useCallback(
39
+ (_0: any, checked: boolean) => {
40
+ onHandleClickEnable?.(checked);
41
+ enabled.onChange(checked);
42
+ },
43
+ [enabled, onHandleClickEnable]
44
+ );
42
45
 
43
- const [Confirm, handleConfirmed] = useConfirm(handleClickEnable);
46
+ const [Confirm, handleConfirmed] = useConfirm(handleClickEnable);
44
47
 
45
- return (
46
- <SettingsSection
47
- qaPrefix="qa-double-opt-in"
48
- title="Double Opt-In"
49
- text={
50
- <Fragment>
51
- <div>
52
- Double opt-in ensures that your emails will go to SPAM at a much lower rate.
53
- The opt-in confirmation happens after a job has been completed.
54
- </div>
55
- <ToggleSwitch
56
- label="Enable"
57
- onChange={handleConfirmed}
58
- checked={enabled.value}
59
- className="m-t-2 qa-double-opt-in-enable"
48
+ return (
49
+ <SettingsSection
50
+ layout={layout}
51
+ className={className}
52
+ qaPrefix="qa-double-opt-in"
53
+ title="Double Opt-In"
54
+ text={
55
+ <Fragment>
56
+ <div>
57
+ Double opt-in ensures that your emails will go to SPAM at a much lower
58
+ rate. The opt-in confirmation happens after a job has been completed.
59
+ </div>
60
+ <ToggleSwitch
61
+ label="Enable"
62
+ onChange={handleConfirmed}
63
+ checked={enabled.value}
64
+ className="m-t-2 qa-double-opt-in-enable"
65
+ />
66
+ </Fragment>
67
+ }
68
+ >
69
+ <Text bold className="m-b-2">
70
+ Double Opt-In Email Content
71
+ </Text>
72
+ <Form className="m-b-0-i">
73
+ <Form.Input
74
+ className="m-b-2-i qa-double-opt-in-subject-line"
75
+ value={emailSubject.value}
76
+ onChange={emailSubject.onChangeHandler}
77
+ error={emailSubject.hasError}
78
+ label="Subject Line"
79
+ fluid
80
+ disabled={!enabled.value}
60
81
  />
61
- </Fragment>
62
- }
63
- >
64
- <Text bold className="m-b-2">
65
- Double Opt-In Email Content
66
- </Text>
67
- <Form className="m-b-0-i">
68
- <Form.Input
69
- className="m-b-2-i qa-double-opt-in-subject-line"
70
- value={emailSubject.value}
71
- onChange={emailSubject.onChangeHandler}
72
- error={emailSubject.hasError}
73
- label="Subject Line"
74
- fluid
75
- disabled={!enabled.value}
76
- />
77
- <Form.Input
78
- className="m-b-2-i qa-double-opt-in-header"
79
- value={emailHeader.value}
80
- onChange={emailHeader.onChangeHandler}
81
- error={emailHeader.hasError}
82
- label="Header"
83
- fluid
84
- disabled={!enabled.value}
85
- />
86
- <Form.TextArea
87
- className="m-b-2-i qa-double-opt-in-body-copy"
88
- label="Body Copy"
89
- value={emailBody.value}
90
- onChange={emailBody.onChangeHandler}
91
- error={emailBody.hasError}
92
- rows={2}
93
- disabled={!enabled.value}
82
+ <Form.Input
83
+ className="m-b-2-i qa-double-opt-in-header"
84
+ value={emailHeader.value}
85
+ onChange={emailHeader.onChangeHandler}
86
+ error={emailHeader.hasError}
87
+ label="Header"
88
+ fluid
89
+ disabled={!enabled.value}
90
+ />
91
+ <Form.TextArea
92
+ className="m-b-2-i qa-double-opt-in-body-copy"
93
+ label="Body Copy"
94
+ value={emailBody.value}
95
+ onChange={emailBody.onChangeHandler}
96
+ error={emailBody.hasError}
97
+ rows={2}
98
+ disabled={!enabled.value}
99
+ />
100
+ <Form.Input
101
+ className={classnames(
102
+ Styles.buttonInput,
103
+ 'm-b-2-i qa-double-opt-in-button-text'
104
+ )}
105
+ value={emailButtonText.value}
106
+ onChange={emailButtonText.onChangeHandler}
107
+ error={emailButtonText.hasError}
108
+ label="Button Text"
109
+ disabled={!enabled.value}
110
+ />
111
+ <Form.Field
112
+ className="m-b-3-i"
113
+ label={
114
+ <Fragment>
115
+ Footer&nbsp;
116
+ <Text inline size={2} subdued>
117
+ (automatically added)
118
+ </Text>
119
+ </Fragment>
120
+ }
121
+ >
122
+ <Text>{footerText}</Text>
123
+ </Form.Field>
124
+ <Button
125
+ className="qa-double-opt-in-preview-email"
126
+ primary
127
+ onClick={openPreview}
128
+ outline
129
+ small
130
+ disabled={!enabled.value}
131
+ >
132
+ Preview Email
133
+ </Button>
134
+ </Form>
135
+ <Confirm
136
+ title="Disable Double Opt-In"
137
+ message="Disabling double opt-in could potentially lead to worse email performance and higher spam rates. Are you sure?"
138
+ when={enabled.value}
94
139
  />
95
- <Form.Input
96
- className={classnames(
97
- Styles.buttonInput,
98
- 'm-b-2-i qa-double-opt-in-button-text'
99
- )}
100
- value={emailButtonText.value}
101
- onChange={emailButtonText.onChangeHandler}
102
- error={emailButtonText.hasError}
103
- label="Button Text"
104
- disabled={!enabled.value}
140
+ <OptInEmailPreview
141
+ {...formState}
142
+ open={isPreviewOpen}
143
+ footerText={footerText}
144
+ onClose={closePreview}
105
145
  />
106
- <Form.Field
107
- className="m-b-3-i"
108
- label={
109
- <Fragment>
110
- Footer&nbsp;
111
- <Text inline size={2} subdued>
112
- (automatically added)
113
- </Text>
114
- </Fragment>
115
- }
116
- >
117
- <Text>{footerText}</Text>
118
- </Form.Field>
119
- <Button
120
- className="qa-double-opt-in-preview-email"
121
- primary
122
- onClick={openPreview}
123
- outline
124
- small
125
- disabled={!enabled.value}
126
- >
127
- Preview Email
128
- </Button>
129
- </Form>
130
- <Confirm
131
- title="Disable Double Opt-In"
132
- message="Disabling double opt-in could potentially lead to worse email performance and higher spam rates. Are you sure?"
133
- when={enabled.value}
134
- />
135
- <OptInEmailPreview
136
- {...formState}
137
- open={isPreviewOpen}
138
- footerText={footerText}
139
- onClose={closePreview}
140
- />
141
- </SettingsSection>
142
- );
143
- });
146
+ </SettingsSection>
147
+ );
148
+ }
149
+ );
@@ -3,37 +3,41 @@ import { observer } from 'mobx-react';
3
3
  import { ComposibleValidatable, FormState, ValidatableMapOrArray } from 'formstate';
4
4
 
5
5
  import { Banner } from '@servicetitan/design-system';
6
+ import classNames from 'classnames';
6
7
 
7
8
  export interface FormErrorsListProps<T extends ValidatableMapOrArray = ValidatableMapOrArray> {
9
+ className?: string;
8
10
  form: FormState<T>;
9
11
  }
10
12
 
11
- export const FormErrorsList: FC<FormErrorsListProps> = observer(({ form }: FormErrorsListProps) => {
12
- const getErrors = () => {
13
- return Object.entries(form.$).map(
14
- ([key, field]: [key: string, field: ComposibleValidatable<unknown>]) => {
15
- return field.hasError ? (
16
- <li key={key} className="qa-settings-email-error-list-item">
17
- {field.error}
18
- </li>
19
- ) : null;
20
- }
21
- );
22
- };
13
+ export const FormErrorsList: FC<FormErrorsListProps> = observer(
14
+ ({ form, className }: FormErrorsListProps) => {
15
+ const getErrors = () => {
16
+ return Object.entries(form.$).map(
17
+ ([key, field]: [key: string, field: ComposibleValidatable<unknown>]) => {
18
+ return field.hasError ? (
19
+ <li key={key} className="qa-settings-email-error-list-item">
20
+ {field.error}
21
+ </li>
22
+ ) : null;
23
+ }
24
+ );
25
+ };
23
26
 
24
- if (!form.hasError) {
25
- return null;
26
- }
27
+ if (!form.hasError) {
28
+ return null;
29
+ }
27
30
 
28
- return (
29
- <Banner
30
- status="critical"
31
- title="Missing Fields"
32
- icon
33
- className="m-b-2 qa-settings-email-error"
34
- >
35
- <p>Please complete all required fields:</p>
36
- <ul className="qa-settings-email-error-list">{getErrors()}</ul>
37
- </Banner>
38
- );
39
- });
31
+ return (
32
+ <Banner
33
+ status="critical"
34
+ title="Missing Fields"
35
+ icon
36
+ className={classNames('m-b-2 qa-settings-email-error', className)}
37
+ >
38
+ <p>Please complete all required fields:</p>
39
+ <ul className="qa-settings-email-error-list">{getErrors()}</ul>
40
+ </Banner>
41
+ );
42
+ }
43
+ );
@@ -40,6 +40,7 @@ export interface LogoPickerProps {
40
40
  maxSize?: number;
41
41
  minDimensions?: { width: number; height: number };
42
42
  tips?: ReactNode;
43
+ deletable?: boolean;
43
44
 
44
45
  deleteImage(): void;
45
46
  downloadImage?(): void;
@@ -61,6 +62,7 @@ export const LogoPicker: FC<LogoPickerProps> = observer(
61
62
  onBadImage,
62
63
  onFileChange,
63
64
  setError,
65
+ deletable = true,
64
66
  tips = DEFAULT_LOGO_TIPS,
65
67
  }) => {
66
68
  const [recommendLargerImage, setRecommendLargerImage] = useState(false);
@@ -222,14 +224,16 @@ export const LogoPicker: FC<LogoPickerProps> = observer(
222
224
  </a>
223
225
  )}
224
226
  </Tooltip>
225
- <Tooltip el="div" text="Delete">
226
- <Button
227
- className="qa-settings-logo-delete shadow-1-i bg-white-i"
228
- onClick={deleteImage}
229
- iconName="delete"
230
- outline
231
- />
232
- </Tooltip>
227
+ {deletable && (
228
+ <Tooltip el="div" text="Delete">
229
+ <Button
230
+ className="qa-settings-logo-delete shadow-1-i bg-white-i"
231
+ onClick={deleteImage}
232
+ iconName="delete"
233
+ outline
234
+ />
235
+ </Tooltip>
236
+ )}
233
237
  </ButtonGroup>
234
238
  </div>
235
239
  </Card.Section>
@@ -3,7 +3,7 @@ import { FC, Fragment, useCallback, useState } from 'react';
3
3
  import classnames from 'classnames';
4
4
 
5
5
  import { CheckboxFieldState, InputFieldState, TextAreaFieldState } from '@servicetitan/form';
6
- import { Button, Form, Stack, Text, ToggleSwitch } from '@servicetitan/design-system';
6
+ import { Button, Form, LayoutProps, Stack, Text, ToggleSwitch } from '@servicetitan/design-system';
7
7
  import { useConfirm } from '@servicetitan/confirm';
8
8
 
9
9
  import { SettingsSection } from '../settings-section';
@@ -22,11 +22,13 @@ export interface OptOutMessageState {
22
22
  }
23
23
  export interface OptOutMessageProps {
24
24
  formState: OptOutMessageState;
25
+ layout?: LayoutProps['type'];
26
+ className?: string;
25
27
  onHandleClickEnable?(checked: boolean): void;
26
28
  }
27
29
 
28
30
  export const OptOutMessage: FC<OptOutMessageProps> = observer(
29
- ({ onHandleClickEnable, formState }) => {
31
+ ({ onHandleClickEnable, formState, layout, className }) => {
30
32
  const {
31
33
  subjectLine,
32
34
  header,
@@ -50,7 +52,8 @@ export const OptOutMessage: FC<OptOutMessageProps> = observer(
50
52
 
51
53
  return (
52
54
  <SettingsSection
53
- className={Styles.outOutMessage}
55
+ layout={layout}
56
+ className={classnames(Styles.outOutMessage, className)}
54
57
  qaPrefix="qa-opt-out-message"
55
58
  title="Opt-Out Message"
56
59
  text={
@@ -1,7 +1,7 @@
1
1
  import { FC } from 'react';
2
2
 
3
3
  import { Grid, Text, Tag } from '@servicetitan/design-system';
4
- import tokens from '@servicetitan/tokens';
4
+ import { core as tokens } from '@servicetitan/tokens';
5
5
 
6
6
  export enum RiskType {
7
7
  Medium,
@@ -11,8 +11,8 @@ export enum RiskType {
11
11
 
12
12
  const riskTypeToColor = new Map<RiskType, string>([
13
13
  [RiskType.Medium, 'warning'],
14
- [RiskType.High, tokens.colorRed500],
15
- [RiskType.VeryHigh, tokens.colorRed600],
14
+ [RiskType.High, tokens.default.tokens.colorRed500],
15
+ [RiskType.VeryHigh, tokens.default.tokens.colorRed600],
16
16
  ]);
17
17
 
18
18
  const riskTypeToText = new Map<RiskType, string>([
@@ -2,23 +2,28 @@ import classNames from 'classnames';
2
2
  import { ReactNode, FC } from 'react';
3
3
  import { observer } from 'mobx-react';
4
4
 
5
- import { Text, Card, Layout } from '@servicetitan/design-system';
5
+ import { Text, Card, Layout, LayoutProps } from '@servicetitan/design-system';
6
6
 
7
7
  export interface SectionProps {
8
- title: string;
8
+ title: ReactNode;
9
9
  text?: JSX.Element | string;
10
10
  children: ReactNode;
11
11
  qaPrefix?: string;
12
12
  className?: string;
13
+ layout?: LayoutProps['type'];
13
14
  }
14
15
 
15
16
  export const SettingsSection: FC<SectionProps> = observer(
16
- ({ title, text, children, qaPrefix, className = '' }: SectionProps) => (
17
- <Layout type="support" direction="left" className={classNames(qaPrefix, className)}>
17
+ ({ title, text, children, qaPrefix, className = '', layout = 'support' }: SectionProps) => (
18
+ <Layout type={layout} direction="left" className={classNames(qaPrefix, className)}>
18
19
  <Layout.Section>
19
- <Text size={3} bold className={`${qaPrefix}-title`}>
20
- {title}
21
- </Text>
20
+ {typeof title === 'string' ? (
21
+ <Text size={3} bold className={`${qaPrefix}-title`}>
22
+ {title}
23
+ </Text>
24
+ ) : (
25
+ title
26
+ )}
22
27
  {text && (
23
28
  <Text size={2} subdued className={`${qaPrefix}-text`}>
24
29
  {text}