@availity/feedback 0.0.0-t325224b2 → 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.
@@ -0,0 +1,306 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Button, ModalBody, ModalHeader, ModalFooter, FormGroup } from 'reactstrap';
4
+ import { avLogMessagesApiV2, avRegionsApi } from '@availity/api-axios';
5
+ import { Form, Field } from '@availity/form';
6
+ import { SelectField } from '@availity/select';
7
+ import * as yup from 'yup';
8
+
9
+ import SmileField from './SmileField';
10
+
11
+ yup.addMethod(yup.string, 'isRequired', function format(isRequired, msg) {
12
+ return this.test({
13
+ name: 'dateRange',
14
+ exclusive: true,
15
+ message: msg || 'This field is required.',
16
+ test(value) {
17
+ if (isRequired) {
18
+ return value !== undefined;
19
+ }
20
+ return true;
21
+ },
22
+ });
23
+ });
24
+
25
+ const fieldStyles = { resize: 'none' };
26
+ const inlineStyles = { display: 'inline-block', margin: 0 };
27
+
28
+ const FeedbackForm = ({
29
+ name,
30
+ onClose,
31
+ faceOptions,
32
+ aboutOptions = [],
33
+ aboutLabel = 'This is about',
34
+ onFeedbackSent,
35
+ prompt,
36
+ additionalComments = false,
37
+ staticFields,
38
+ analytics = avLogMessagesApiV2,
39
+ modalHeaderProps,
40
+ showSupport = false,
41
+ setSupportIsActive,
42
+ autoFocusFeedbackButton,
43
+ modal = true,
44
+ ...formProps
45
+ }) => {
46
+ const [active, setActive] = useState(null);
47
+ const [sent, setSent] = useState(null);
48
+ const [loading, setLoading] = useState(null);
49
+ const ref = useRef();
50
+
51
+ const sendFeedback = async ({ smileField, ...values }) => {
52
+ setLoading(true);
53
+ const response = await avRegionsApi.getCurrentRegion();
54
+
55
+ await analytics.info({
56
+ surveyId: `${name.replaceAll(/\s/g, '_')}_Smile_Survey`,
57
+ smileLocation: `${name}`,
58
+ smile: `icon-${smileField.icon}`,
59
+ url: window.location.href,
60
+ region: response.data.regions[0] && response.data.regions[0].id,
61
+ userAgent: window.navigator.userAgent,
62
+ submitTime: new Date(),
63
+ ...values, // Spread the form values onto the logger
64
+ ...staticFields, // Spread the static key value pairs onto the logger
65
+ });
66
+
67
+ setSent(values);
68
+ setLoading(false);
69
+ };
70
+
71
+ // Close the Modal once sent after 2 seconds
72
+ useEffect(() => {
73
+ if (sent) {
74
+ setTimeout(() => {
75
+ if (onClose) {
76
+ onClose(); // Mostly for Screen Reader use but a nice to have for all
77
+ }
78
+ if (onFeedbackSent) {
79
+ for (const key of Object.keys(sent)) {
80
+ if (sent[key] === undefined) {
81
+ delete sent[key];
82
+ }
83
+ }
84
+
85
+ onFeedbackSent({
86
+ active: active.icon,
87
+ ...sent,
88
+ });
89
+ }
90
+ }, 2000);
91
+ }
92
+ // eslint-disable-next-line react-hooks/exhaustive-deps
93
+ }, [sent]);
94
+
95
+ return sent ? (
96
+ <ModalHeader
97
+ role="status"
98
+ id="feedback-form-header"
99
+ tabIndex="0"
100
+ className="d-flex justify-content-center"
101
+ {...modalHeaderProps}
102
+ >
103
+ Thank you for your feedback.
104
+ </ModalHeader>
105
+ ) : (
106
+ <>
107
+ <ModalHeader
108
+ id="feedback-form-header"
109
+ role="heading"
110
+ aria-level="2"
111
+ className="h5"
112
+ tag="div"
113
+ {...modalHeaderProps}
114
+ >
115
+ {prompt || `Tell us what you think about ${name}`}
116
+ </ModalHeader>
117
+ <Form
118
+ innerRef={ref}
119
+ aria-label="Feedback Form"
120
+ aria-describedby="feedback-form-header"
121
+ role="form"
122
+ onKeyDown={({ key }) => key === 'Escape' && onClose()}
123
+ data-testid="feedback-form"
124
+ initialValues={{
125
+ 'face-options': undefined,
126
+ additionalFeedback: undefined,
127
+ feedback: undefined,
128
+ feedbackApp: undefined,
129
+ smileField: undefined,
130
+ }}
131
+ validationSchema={yup.object().shape({
132
+ feedback: yup.string().max(200, 'Feedback cannot exceed 200 characters.').required('This field is required.'),
133
+ additionalFeedback: yup.string().max(200, 'Additional Feedback cannot exceed 200 characters.'),
134
+ smileField: yup
135
+ .object()
136
+ .shape({
137
+ icon: yup.string().required(),
138
+ description: yup.string(),
139
+ label: yup.string(),
140
+ })
141
+ .required('This field is required.'),
142
+ feedbackApp: yup.string().isRequired(aboutOptions.length > 0, 'This field is required.'),
143
+ })}
144
+ {...formProps}
145
+ onSubmit={(values) => sendFeedback(values)}
146
+ >
147
+ <ModalBody>
148
+ <FormGroup
149
+ size="lg"
150
+ id="face-options"
151
+ role="group"
152
+ aria-labelledby="feedback-form-header"
153
+ data-testid="face-options"
154
+ className="d-flex flex-row justify-content-between"
155
+ >
156
+ <SmileField
157
+ options={faceOptions}
158
+ name="smileField"
159
+ onChange={(option) => setActive(option)}
160
+ onClose={onClose}
161
+ autoFocusFeedbackButton={autoFocusFeedbackButton}
162
+ modal={modal}
163
+ />
164
+ </FormGroup>
165
+
166
+ {active ? (
167
+ <>
168
+ {aboutOptions.length > 0 && (
169
+ <SelectField
170
+ name="feedbackApp"
171
+ id="about-options"
172
+ data-testid="about-options"
173
+ label={aboutLabel}
174
+ options={aboutOptions}
175
+ />
176
+ )}
177
+
178
+ <Field
179
+ type="textarea"
180
+ name="feedback"
181
+ label={(active && active.label) || 'Feedback? Requests? Defects?'}
182
+ style={fieldStyles}
183
+ rows="2"
184
+ />
185
+ {additionalComments && (
186
+ <Field
187
+ type="textarea"
188
+ name="additionalFeedback"
189
+ label="Additional Comments... (Optional)"
190
+ style={fieldStyles}
191
+ rows="2"
192
+ />
193
+ )}
194
+ </>
195
+ ) : null}
196
+ </ModalBody>
197
+
198
+ <ModalFooter>
199
+ {showSupport ? (
200
+ <>
201
+ <span className="d-none d-md-block" style={inlineStyles}>
202
+ Need Help?
203
+ </span>
204
+ <Button
205
+ className="pl-0"
206
+ onClick={() => setSupportIsActive(true)}
207
+ color="link"
208
+ type="button"
209
+ onKeyDown={({ key }) => key === 'Enter' && setSupportIsActive(true)}
210
+ >
211
+ Open a support ticket
212
+ </Button>
213
+ </>
214
+ ) : null}
215
+
216
+ {onClose ? (
217
+ <Button
218
+ type="button"
219
+ onClick={onClose}
220
+ color="secondary"
221
+ onKeyDown={({ key, shiftKey }) => {
222
+ if (key === 'Enter') {
223
+ onClose();
224
+ }
225
+ if (key === 'Tab' && !active && !shiftKey && !modal) {
226
+ onClose();
227
+ }
228
+ }}
229
+ >
230
+ Close
231
+ </Button>
232
+ ) : null}
233
+
234
+ <Button
235
+ onKeyDown={({ key, shiftKey }) => {
236
+ if (key === 'Enter') {
237
+ ref.current.submitForm();
238
+ }
239
+ if (key === 'Tab' && !shiftKey && !modal) {
240
+ onClose();
241
+ }
242
+ }}
243
+ type="submit"
244
+ color="primary"
245
+ disabled={Boolean(!active || loading)}
246
+ >
247
+ Send Feedback
248
+ </Button>
249
+ </ModalFooter>
250
+ </Form>
251
+ </>
252
+ );
253
+ };
254
+
255
+ FeedbackForm.propTypes = {
256
+ /** The name of the application this feedback is for. It is used in the API request to indicate where the feedback came from. */
257
+ name: PropTypes.string.isRequired,
258
+ /** Callback for when the feedback is submitted. It is called with the feedback object. */
259
+ onFeedbackSent: PropTypes.func,
260
+ /** Array of Objects containing icon (String), description (String), and label (String) properties.
261
+ * Allows you to override the smiley face options which appear.
262
+ * Default: Smiley Face, Meh Face, and Frowny Face.
263
+ * Previous placeholder property removed as of v6.0.0. Use label instead. */
264
+ faceOptions: PropTypes.arrayOf(
265
+ PropTypes.shape({
266
+ icon: PropTypes.string,
267
+ description: PropTypes.string,
268
+ label: PropTypes.string,
269
+ })
270
+ ),
271
+ /** Array of Objects containing value (String,Number) and label (String) properties.
272
+ * Allows a dropdown displaying the options provided to let the user indicate what the feedback is about. */
273
+ aboutOptions: PropTypes.arrayOf(
274
+ PropTypes.shape({
275
+ name: PropTypes.string,
276
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
277
+ })
278
+ ),
279
+ /** Label text for the dropdown created via the aboutOptions prop. Default: "This is about".
280
+ *Previously aboutPlaceholder. All placeholders replaced with labels starting v6.0.0. */
281
+ aboutLabel: PropTypes.node,
282
+ /** When provided, a "Close" button is rendered and onClose is excuted when it's clicked. */
283
+ onClose: PropTypes.func,
284
+ /** Text that prompts the user to provider feedback. Default: "Tell us what you think about ${appName}.". */
285
+ prompt: PropTypes.string,
286
+ /** If true, shows an optional comments field below. */
287
+ additionalComments: PropTypes.bool,
288
+ /** Static (non-user-entered) key/value pairs to be sent in feedback submission. */
289
+ staticFields: PropTypes.object,
290
+ /** Props to be spread onto the <ModalHeader /> rendered inside of the <FeedbackForm />. See ModalHeader
291
+ *For accessibility use className instead of tag to adjust size and style of header. */
292
+ modalHeaderProps: PropTypes.shape({ ...ModalHeader.propTypes }),
293
+ /** Override the analytics instance that is passed in. Default avLogMessagesApiV2 */
294
+ analytics: PropTypes.shape({
295
+ info: PropTypes.func.isRequired,
296
+ }),
297
+ /** Toggle whether or not to show the "Open a Support ticket" link in the FeedbackForm */
298
+ showSupport: PropTypes.bool,
299
+ setSupportIsActive: PropTypes.func,
300
+ /** Default: true. When set to false, the first feedback button is not focused.
301
+ * This is to avoid issues with focus causing other elements to close (e.g. dropdowns) */
302
+ autoFocusFeedbackButton: PropTypes.bool,
303
+ modal: PropTypes.bool,
304
+ };
305
+
306
+ export default FeedbackForm;
@@ -0,0 +1,9 @@
1
+ export interface FeedbackModalProps {
2
+ isOpen: boolean;
3
+ toggle: Function;
4
+ zIndex?: number | string;
5
+ }
6
+
7
+ declare const FeedbackModal: React.FC<FeedbackModalProps>;
8
+
9
+ export default FeedbackModal;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Modal } from 'reactstrap';
4
+
5
+ import FeedbackForm from './FeedbackForm';
6
+ import SupportModal from './SupportModal';
7
+
8
+ const FeedbackModal = ({ isOpen, toggle, zIndex, showSupport, supportZIndex, feedbackToggle, ...formOptions }) => {
9
+ const [supportIsActive, setSupportIsActive] = React.useState(false);
10
+
11
+ return supportIsActive ? (
12
+ <SupportModal
13
+ supportIsActive={supportIsActive}
14
+ setSupportIsActive={setSupportIsActive}
15
+ zIndex={supportZIndex}
16
+ toggle={toggle}
17
+ feedbackToggle={feedbackToggle}
18
+ />
19
+ ) : (
20
+ <Modal
21
+ fade
22
+ id="feedbackModal"
23
+ data-testid="feedbackModal"
24
+ size="lg"
25
+ aria-labelledby="feedback-form-header"
26
+ isOpen={isOpen && !supportIsActive}
27
+ toggle={toggle}
28
+ zIndex={zIndex}
29
+ >
30
+ <FeedbackForm
31
+ onClose={toggle}
32
+ showSupport={showSupport}
33
+ setSupportIsActive={setSupportIsActive}
34
+ {...formOptions}
35
+ />
36
+ </Modal>
37
+ );
38
+ };
39
+
40
+ FeedbackModal.propTypes = {
41
+ isOpen: PropTypes.bool.isRequired,
42
+ toggle: PropTypes.func.isRequired,
43
+ showSupport: PropTypes.bool,
44
+ zIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
45
+ supportZIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
46
+ feedbackToggle: PropTypes.func,
47
+ };
48
+
49
+ export default FeedbackModal;
@@ -0,0 +1,76 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useField, useFormikContext } from 'formik';
4
+
5
+ import FeedbackButton from './FeedbackButton';
6
+
7
+ const btnStyles = { flex: 1, margin: '0 2% 0 2%' };
8
+ const defaultOptions = [
9
+ {
10
+ icon: 'smile',
11
+ description: 'Smiley face',
12
+ label: 'What do you like?',
13
+ },
14
+ {
15
+ icon: 'meh',
16
+ description: 'Meh face',
17
+ label: 'What would you improve?',
18
+ },
19
+ {
20
+ icon: 'frown',
21
+ description: 'Frowny face',
22
+ label: "What don't you like?",
23
+ },
24
+ ];
25
+
26
+ const SmileField = ({ name, options = defaultOptions, onChange, autoFocusFeedbackButton = true, onClose, modal }) => {
27
+ const [{ value }] = useField(name);
28
+ const { setFieldValue } = useFormikContext();
29
+
30
+ return options.map((option, i) => (
31
+ <FeedbackButton
32
+ autoFocus={i === 0 && autoFocusFeedbackButton}
33
+ onKeyDown={(e) => {
34
+ if (e.shiftKey && e.keyCode === 9 && i === 0 && !modal) {
35
+ onClose();
36
+ }
37
+ if (e.keyCode === 13) {
38
+ setFieldValue(name, option);
39
+ if (onChange) {
40
+ onChange(option);
41
+ }
42
+ }
43
+ }}
44
+ style={btnStyles}
45
+ key={option.icon}
46
+ icon={option.icon}
47
+ iconSize="2x"
48
+ value={option}
49
+ active={value && value.icon}
50
+ onClick={() => {
51
+ setFieldValue(name, option);
52
+ if (onChange) {
53
+ onChange(option);
54
+ }
55
+ }}
56
+ >
57
+ {option.description}
58
+ </FeedbackButton>
59
+ ));
60
+ };
61
+
62
+ SmileField.propTypes = {
63
+ name: PropTypes.string.isRequired,
64
+ options: PropTypes.arrayOf(
65
+ PropTypes.shape({
66
+ icon: PropTypes.string,
67
+ description: PropTypes.string,
68
+ label: PropTypes.string,
69
+ })
70
+ ),
71
+ onChange: PropTypes.func,
72
+ autoFocusFeedbackButton: PropTypes.bool,
73
+ modal: PropTypes.bool,
74
+ };
75
+
76
+ export default SmileField;
@@ -0,0 +1,37 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { DropdownMenu } from 'reactstrap';
4
+ import BlockUi from '@availity/block-ui';
5
+
6
+ import SupportForm from './SupportForm';
7
+
8
+ const dropdownStyles = { width: '550px', maxWidth: '90vw', padding: 0 };
9
+
10
+ const SupportDropdown = ({ setSupportIsActive, feedbackToggle }) => {
11
+ const [blocking, setBlocking] = useState(false);
12
+
13
+ return (
14
+ <DropdownMenu
15
+ right
16
+ style={dropdownStyles}
17
+ positionFixed="false"
18
+ role="dialog"
19
+ aria-labelledby="support-form-header"
20
+ >
21
+ <BlockUi tag="div" keepInView blocking={blocking}>
22
+ <SupportForm
23
+ setSupportIsActive={setSupportIsActive}
24
+ setBlocking={setBlocking}
25
+ feedbackToggle={feedbackToggle}
26
+ />
27
+ </BlockUi>
28
+ </DropdownMenu>
29
+ );
30
+ };
31
+
32
+ SupportDropdown.propTypes = {
33
+ setSupportIsActive: PropTypes.func,
34
+ feedbackToggle: PropTypes.func,
35
+ };
36
+
37
+ export default SupportDropdown;
@@ -0,0 +1,149 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Button, ModalBody, ModalHeader, ModalFooter } from 'reactstrap';
4
+ import { Form } from '@availity/form';
5
+ import { AvOrganizationSelect } from '@availity/select';
6
+ import * as yup from 'yup';
7
+ import nativeForm from '@availity/native-form';
8
+ import { avOrganizationsApi, avWebQLApi } from '@availity/api-axios';
9
+ import '@availity/yup';
10
+
11
+ const SUPPORT_PERMISSION_ID = '7205';
12
+
13
+ const ORG_VALIDATION_MESSAGE = 'Please select an organization from the dropdown.';
14
+
15
+ const getToken = () => document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*=\s*([^;]*).*$)|^.*$/, '$1');
16
+
17
+ const openSupport = async (values, setBlocking, setSupportIsActive, feedbackToggle) => {
18
+ setBlocking(true);
19
+ const orgsResp = await avOrganizationsApi.getOrganizations(SUPPORT_PERMISSION_ID);
20
+ let salesforceResponse;
21
+ if (orgsResp.data.organizations.some((org) => org.id === values.organization.id)) {
22
+ salesforceResponse = await avWebQLApi.create({
23
+ query: `
24
+ query salesforceUser($organizationId: ID!) {
25
+ salesforceUser(organizationId: $organizationId) {
26
+ id
27
+ accountId
28
+ newCommunity
29
+ }
30
+ }
31
+ `,
32
+ variables: {
33
+ organizationId: values.organization.id,
34
+ },
35
+ });
36
+ }
37
+
38
+ let href = 'mailto:support@availity.com';
39
+ const target = '_top';
40
+
41
+ if (!salesforceResponse || !salesforceResponse.data) {
42
+ window.open(href, target);
43
+ }
44
+
45
+ const salesforceData = salesforceResponse.data.data.salesforceUser;
46
+ const ssoId = 'BJx3fqX3BH';
47
+ const newCommutySsoId = 'E-t_s_JQ0P';
48
+
49
+ if (salesforceData) {
50
+ const attributes = {
51
+ orgGenKey: values.organization.customerId,
52
+ organizationName: values.organization.name,
53
+ partyId: values.organization.id,
54
+ payerId: 'AVAILITY',
55
+ X_Client_ID: '5430d59f-c5cc-4be7-be5a-34472ec30fe9',
56
+ X_XSRF_TOKEN: getToken(),
57
+ };
58
+
59
+ if (salesforceData.id && salesforceData.accountId) {
60
+ attributes.avSalesForceContactId = salesforceData.id;
61
+ attributes.avSalesForceContactAccId = salesforceData.accountId;
62
+ }
63
+
64
+ href = `/ms/api/availity/internal/spc/magneto/sso/v1/saml/${salesforceData.newCommunity ? newCommutySsoId : ssoId}`;
65
+
66
+ await nativeForm(ssoId, attributes, { action: href, target: '_blank' }, 'saml');
67
+ setBlocking(false);
68
+ } else {
69
+ window.open(href, target);
70
+ }
71
+ setSupportIsActive(false);
72
+ feedbackToggle(false);
73
+ };
74
+
75
+ function orgSelectTest(msg) {
76
+ const orgSelectSchema = yup.object().shape({
77
+ id: yup.string().isRequired(true, ORG_VALIDATION_MESSAGE),
78
+ name: yup.string().isRequired(true, ORG_VALIDATION_MESSAGE),
79
+ });
80
+
81
+ return this.test({
82
+ name: 'orgSelectTest',
83
+ exclusive: true,
84
+ message: msg || 'This field is invalid.',
85
+ async test(componentValue) {
86
+ if (!componentValue) return true;
87
+
88
+ const valid = await orgSelectSchema.isValid(componentValue);
89
+ return valid;
90
+ },
91
+ });
92
+ }
93
+
94
+ yup.addMethod(yup.object, 'orgSelectTest', orgSelectTest);
95
+
96
+ const SupportForm = ({ setSupportIsActive, setBlocking, feedbackToggle }) => (
97
+ <>
98
+ <ModalHeader id="support-form-header" role="heading" aria-level="2" className="h5" tag="div">
99
+ Open Support Ticket
100
+ </ModalHeader>
101
+ <Form
102
+ aria-label="Support Form"
103
+ aria-describedby="support-form-header"
104
+ role="form"
105
+ data-testid="support-form"
106
+ initialValues={{
107
+ organization: undefined,
108
+ }}
109
+ validationSchema={yup.object({
110
+ organization: yup
111
+ .object()
112
+ .orgSelectTest(ORG_VALIDATION_MESSAGE)
113
+ .isRequired(ORG_VALIDATION_MESSAGE)
114
+ .typeError(ORG_VALIDATION_MESSAGE),
115
+ })}
116
+ onSubmit={(values) => openSupport(values, setBlocking, setSupportIsActive, feedbackToggle)}
117
+ >
118
+ <ModalBody>
119
+ <AvOrganizationSelect
120
+ name="organization"
121
+ label="Select an Organization"
122
+ data-testid="org-dropdown"
123
+ getResult={(data) => data.organizations}
124
+ />
125
+ </ModalBody>
126
+ <ModalFooter>
127
+ <Button
128
+ onClick={() => setSupportIsActive(false)}
129
+ color="secondary"
130
+ type="button"
131
+ onKeyDown={({ keyCode }) => keyCode === 13 && setSupportIsActive(false)}
132
+ >
133
+ Close
134
+ </Button>
135
+ <Button data-testid="submit-btn" type="submit" color="primary">
136
+ Continue
137
+ </Button>
138
+ </ModalFooter>
139
+ </Form>
140
+ </>
141
+ );
142
+
143
+ SupportForm.propTypes = {
144
+ setSupportIsActive: PropTypes.func,
145
+ setBlocking: PropTypes.func,
146
+ feedbackToggle: PropTypes.func,
147
+ };
148
+
149
+ export default SupportForm;
@@ -0,0 +1,40 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Modal } from 'reactstrap';
4
+ import BlockUi from '@availity/block-ui';
5
+
6
+ import SupportForm from './SupportForm';
7
+
8
+ const SupportModal = ({ supportIsActive, toggle, supportZIndex, setSupportIsActive, feedbackToggle }) => {
9
+ const [blocking, setBlocking] = useState(false);
10
+
11
+ return (
12
+ <Modal
13
+ fade
14
+ id="supportModal"
15
+ data-testid="supportModal"
16
+ aria-labelledby="support-form-header"
17
+ isOpen={supportIsActive}
18
+ toggle={toggle}
19
+ zIndex={supportZIndex}
20
+ >
21
+ <BlockUi tag="div" blocking={blocking}>
22
+ <SupportForm
23
+ setSupportIsActive={setSupportIsActive}
24
+ setBlocking={setBlocking}
25
+ feedbackToggle={feedbackToggle}
26
+ />
27
+ </BlockUi>
28
+ </Modal>
29
+ );
30
+ };
31
+
32
+ SupportModal.propTypes = {
33
+ supportIsActive: PropTypes.bool.isRequired,
34
+ toggle: PropTypes.func.isRequired,
35
+ supportZIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
36
+ setSupportIsActive: PropTypes.func,
37
+ feedbackToggle: PropTypes.func,
38
+ };
39
+
40
+ export default SupportModal;
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["."],
4
+ "exclude": ["dist", "build", "node_modules"]
5
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "types": ["jest", "node", "@testing-library/jest-dom"],
7
+ "allowJs": true
8
+ },
9
+ "include": ["**/*.test.js", "**/*.test.ts", "**/*.test.tsx", "**/*.d.ts"]
10
+ }