@availity/mui-feedback 0.1.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.
- package/CHANGELOG.md +20 -0
- package/README.md +61 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +582 -0
- package/dist/index.mjs +552 -0
- package/introduction.mdx +7 -0
- package/jest.config.js +7 -0
- package/package.json +57 -0
- package/project.json +42 -0
- package/src/index.ts +1 -0
- package/src/lib/Feedback.stories.tsx +19 -0
- package/src/lib/Feedback.test.tsx +15 -0
- package/src/lib/Feedback.tsx +67 -0
- package/src/lib/FeedbackForm.test.tsx +48 -0
- package/src/lib/FeedbackForm.tsx +188 -0
- package/src/lib/FeedbackHeader.test.tsx +28 -0
- package/src/lib/FeedbackHeader.tsx +36 -0
- package/tsconfig.json +5 -0
- package/tsconfig.spec.json +10 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
// src/lib/Feedback.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Popover } from "@availity/mui-popover";
|
|
4
|
+
import { Button as Button2 } from "@availity/mui-button";
|
|
5
|
+
import { Container, styled as styled3 } from "@mui/material";
|
|
6
|
+
import { avLogMessagesApi } from "@availity/api-axios";
|
|
7
|
+
|
|
8
|
+
// src/lib/FeedbackForm.tsx
|
|
9
|
+
import { useEffect } from "react";
|
|
10
|
+
import { TextField } from "@availity/mui-textfield";
|
|
11
|
+
import { LoadingButton, Button } from "@availity/mui-button";
|
|
12
|
+
import { ToggleButtonGroup, ToggleButton } from "@availity/mui-toggle-button";
|
|
13
|
+
import { Grid, styled as styled2 } from "@mui/material";
|
|
14
|
+
import { FaceFrownIcon, FaceNeutralIcon, FaceSmileIcon } from "@availity/mui-icon";
|
|
15
|
+
|
|
16
|
+
// ../../node_modules/@availity/message-core/dist/index.mjs
|
|
17
|
+
var __defProp = Object.defineProperty;
|
|
18
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
19
|
+
var __publicField = (obj, key, value) => {
|
|
20
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __accessCheck = (obj, member, msg) => {
|
|
24
|
+
if (!member.has(obj))
|
|
25
|
+
throw TypeError("Cannot " + msg);
|
|
26
|
+
};
|
|
27
|
+
var __privateGet = (obj, member, getter) => {
|
|
28
|
+
__accessCheck(obj, member, "read from private field");
|
|
29
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
30
|
+
};
|
|
31
|
+
var __privateAdd = (obj, member, value) => {
|
|
32
|
+
if (member.has(obj))
|
|
33
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
34
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
35
|
+
};
|
|
36
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
37
|
+
__accessCheck(obj, member, "write to private field");
|
|
38
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
var _lastId;
|
|
42
|
+
var AvMessage = class {
|
|
43
|
+
constructor() {
|
|
44
|
+
__publicField(this, "subscribers", {});
|
|
45
|
+
__publicField(this, "getEventData", (event) => {
|
|
46
|
+
const isSameWindow = event.source === window;
|
|
47
|
+
if (!this.isEnabled || !event || !event.data || !event.origin || !event.source || !this.isDomain(event.origin)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let { data } = event;
|
|
51
|
+
if (typeof data === "string") {
|
|
52
|
+
try {
|
|
53
|
+
data = JSON.parse(data);
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof data === "string") {
|
|
58
|
+
event = data;
|
|
59
|
+
data = void 0;
|
|
60
|
+
} else {
|
|
61
|
+
event = data && data.event || this.DEFAULT_EVENT;
|
|
62
|
+
}
|
|
63
|
+
const metadata = { isSameWindow };
|
|
64
|
+
this.onMessage(event, data, metadata);
|
|
65
|
+
});
|
|
66
|
+
__privateAdd(this, _lastId, 0);
|
|
67
|
+
this.isEnabled = true;
|
|
68
|
+
this.DEFAULT_EVENT = "avMessage";
|
|
69
|
+
this.DOMAIN = /https?:\/\/([\w-]+\.)?availity\.(com|net)/;
|
|
70
|
+
window.addEventListener("message", this.getEventData);
|
|
71
|
+
}
|
|
72
|
+
enabled(value) {
|
|
73
|
+
if (arguments.length > 0) {
|
|
74
|
+
this.isEnabled = !!value;
|
|
75
|
+
}
|
|
76
|
+
return this.isEnabled;
|
|
77
|
+
}
|
|
78
|
+
subscribe(event, callback, options) {
|
|
79
|
+
var _a;
|
|
80
|
+
if (!this.subscribers[event]) {
|
|
81
|
+
this.subscribers[event] = [];
|
|
82
|
+
}
|
|
83
|
+
__privateSet(this, _lastId, __privateGet(this, _lastId) + 1);
|
|
84
|
+
const id = __privateGet(this, _lastId);
|
|
85
|
+
const ignoreSameWindow = (_a = options == null ? void 0 : options.ignoreSameWindow) != null ? _a : true;
|
|
86
|
+
const subscriber = { id, callback, options: { ignoreSameWindow } };
|
|
87
|
+
this.subscribers[event].push(subscriber);
|
|
88
|
+
return () => {
|
|
89
|
+
this.subscribers[event] = this.subscribers[event].filter((subscriber2) => subscriber2.id !== id);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
unsubscribe(event) {
|
|
93
|
+
delete this.subscribers[event];
|
|
94
|
+
}
|
|
95
|
+
unsubscribeAll() {
|
|
96
|
+
this.subscribers = {};
|
|
97
|
+
}
|
|
98
|
+
onMessage(event, data, metadata) {
|
|
99
|
+
const { isSameWindow } = metadata;
|
|
100
|
+
if (this.subscribers[event]) {
|
|
101
|
+
for (const subscriber of this.subscribers[event]) {
|
|
102
|
+
const { ignoreSameWindow } = subscriber.options;
|
|
103
|
+
const skip = isSameWindow && ignoreSameWindow;
|
|
104
|
+
if (!skip) {
|
|
105
|
+
subscriber.callback(data);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
isDomain(url) {
|
|
111
|
+
return !this.DOMAIN.test(this.domain()) || this.DOMAIN.test(url);
|
|
112
|
+
}
|
|
113
|
+
domain() {
|
|
114
|
+
if (window.location.origin) {
|
|
115
|
+
return window.location.origin;
|
|
116
|
+
}
|
|
117
|
+
if (window.location.hostname) {
|
|
118
|
+
return `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
|
|
119
|
+
}
|
|
120
|
+
return "*";
|
|
121
|
+
}
|
|
122
|
+
send(payload, target = window.top) {
|
|
123
|
+
if (!this.isEnabled || !payload) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const message = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
128
|
+
target.postMessage(message, this.domain());
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.warn("AvMessage.send()", error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
_lastId = /* @__PURE__ */ new WeakMap();
|
|
135
|
+
var AvMessage_default = AvMessage;
|
|
136
|
+
var src_default = new AvMessage_default();
|
|
137
|
+
|
|
138
|
+
// ../form-utils/src/lib/FieldHelpIcon.tsx
|
|
139
|
+
import { HelpCircleIcon } from "@availity/mui-icon";
|
|
140
|
+
import { IconButton } from "@availity/mui-button";
|
|
141
|
+
import { jsx } from "react/jsx-runtime";
|
|
142
|
+
var triggerFieldHelp = (id) => {
|
|
143
|
+
src_default.send({
|
|
144
|
+
event: "nav:help:field",
|
|
145
|
+
id
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
var FieldHelpIcon = ({ helpTopicId, labelId, sx, ...rest }) => {
|
|
149
|
+
return /* @__PURE__ */ jsx(IconButton, {
|
|
150
|
+
...rest,
|
|
151
|
+
color: "primary",
|
|
152
|
+
title: "Help",
|
|
153
|
+
role: "link",
|
|
154
|
+
onClick: () => triggerFieldHelp(helpTopicId),
|
|
155
|
+
"aria-describedby": labelId,
|
|
156
|
+
size: "small",
|
|
157
|
+
sx: { ...sx, padding: 0.5, fontSize: "inherit", marginTop: "-2px", opacity: 1 },
|
|
158
|
+
children: /* @__PURE__ */ jsx(HelpCircleIcon, {
|
|
159
|
+
"aria-hidden": true,
|
|
160
|
+
titleAccess: void 0
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// ../form-utils/src/lib/FormControlLabel.tsx
|
|
166
|
+
import { forwardRef } from "react";
|
|
167
|
+
import {
|
|
168
|
+
Box,
|
|
169
|
+
FormControlLabel as MuiFormControlLabel
|
|
170
|
+
} from "@mui/material";
|
|
171
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
172
|
+
var FormControlLabel = forwardRef(({ helpTopicId, id, ...rest }, ref) => {
|
|
173
|
+
const labelId = id || (rest.htmlFor ? `${rest.htmlFor}-label` : void 0);
|
|
174
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
175
|
+
children: [
|
|
176
|
+
/* @__PURE__ */ jsx2(MuiFormControlLabel, {
|
|
177
|
+
id: labelId,
|
|
178
|
+
...rest,
|
|
179
|
+
ref
|
|
180
|
+
}),
|
|
181
|
+
helpTopicId ? /* @__PURE__ */ jsx2(FieldHelpIcon, {
|
|
182
|
+
helpTopicId: "12345",
|
|
183
|
+
labelId
|
|
184
|
+
}) : null
|
|
185
|
+
]
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// ../form-utils/src/lib/FormHelperText.tsx
|
|
190
|
+
import MuiFormHelperText from "@mui/material/FormHelperText";
|
|
191
|
+
import { WarningTriangleIcon } from "@availity/mui-icon";
|
|
192
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
193
|
+
|
|
194
|
+
// ../form-utils/src/lib/FormLabel.tsx
|
|
195
|
+
import { forwardRef as forwardRef2 } from "react";
|
|
196
|
+
import { Box as Box2, FormLabel as MuiFormLabel, styled } from "@mui/material";
|
|
197
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
198
|
+
var Children = styled("span", {
|
|
199
|
+
name: "MuiFormLabel",
|
|
200
|
+
slot: "Children",
|
|
201
|
+
overridesResolver: (props, styles) => styles.children
|
|
202
|
+
})({});
|
|
203
|
+
var StyleOverrides = {
|
|
204
|
+
position: "relative !important",
|
|
205
|
+
transform: "none !important",
|
|
206
|
+
transition: "none !important",
|
|
207
|
+
animation: "none !important"
|
|
208
|
+
};
|
|
209
|
+
var FormLabel = forwardRef2((props, ref) => {
|
|
210
|
+
const { children, helpTopicId, id, sx, ...rest } = props;
|
|
211
|
+
const labelId = id || (rest.htmlFor ? `${rest.htmlFor}-label` : void 0);
|
|
212
|
+
return /* @__PURE__ */ jsxs3(Box2, {
|
|
213
|
+
display: "flex",
|
|
214
|
+
flexDirection: "row",
|
|
215
|
+
sx,
|
|
216
|
+
children: [
|
|
217
|
+
/* @__PURE__ */ jsx4(MuiFormLabel, {
|
|
218
|
+
id: labelId,
|
|
219
|
+
sx: { ...StyleOverrides },
|
|
220
|
+
...rest,
|
|
221
|
+
ref,
|
|
222
|
+
children: /* @__PURE__ */ jsx4(Children, {
|
|
223
|
+
className: "MuiFormLabel-children",
|
|
224
|
+
children
|
|
225
|
+
})
|
|
226
|
+
}),
|
|
227
|
+
helpTopicId ? /* @__PURE__ */ jsx4(FieldHelpIcon, {
|
|
228
|
+
helpTopicId,
|
|
229
|
+
labelId,
|
|
230
|
+
sx: { px: 0.5 }
|
|
231
|
+
}) : null
|
|
232
|
+
]
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// ../form-utils/src/lib/Input.tsx
|
|
237
|
+
import MuiInput from "@mui/material/OutlinedInput";
|
|
238
|
+
import InputAdornment from "@mui/material/InputAdornment";
|
|
239
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
240
|
+
var InputPropOverrides = {
|
|
241
|
+
notched: false
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// ../form-utils/src/lib/Select.tsx
|
|
245
|
+
import MuiSelect from "@mui/material/Select";
|
|
246
|
+
import Divider from "@mui/material/Divider";
|
|
247
|
+
import Stack from "@mui/material/Stack";
|
|
248
|
+
import { ExpandIcon } from "@availity/mui-icon";
|
|
249
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
250
|
+
var InnerEndAdornment = (args) => /* @__PURE__ */ jsxs4(Stack, {
|
|
251
|
+
...args,
|
|
252
|
+
direction: "row",
|
|
253
|
+
spacing: 1,
|
|
254
|
+
height: "100%",
|
|
255
|
+
paddingY: ".5rem",
|
|
256
|
+
top: "unset!important",
|
|
257
|
+
children: [
|
|
258
|
+
/* @__PURE__ */ jsx6(Divider, {
|
|
259
|
+
orientation: "vertical"
|
|
260
|
+
}),
|
|
261
|
+
/* @__PURE__ */ jsx6(ExpandIcon, {
|
|
262
|
+
sx: { position: "relative", top: "calc(50% - .5rem)" }
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
});
|
|
266
|
+
var SelectPropOverrides = {
|
|
267
|
+
IconComponent: InnerEndAdornment,
|
|
268
|
+
...InputPropOverrides
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// src/lib/FeedbackForm.tsx
|
|
272
|
+
import { avRegionsApi } from "@availity/api-axios";
|
|
273
|
+
import { useForm, Controller } from "react-hook-form";
|
|
274
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
275
|
+
var SmileButtons = styled2(ToggleButtonGroup, { name: "AvFeedbackContainer", slot: "SmileButtons" })({});
|
|
276
|
+
var SmileButton = ({ disabled, Icon, label, value, ...props }) => /* @__PURE__ */ jsx7("div", {
|
|
277
|
+
children: /* @__PURE__ */ jsx7(ToggleButton, {
|
|
278
|
+
"aria-label": value,
|
|
279
|
+
value,
|
|
280
|
+
...props,
|
|
281
|
+
disabled,
|
|
282
|
+
children: /* @__PURE__ */ jsx7(Icon, {
|
|
283
|
+
fontSize: "large"
|
|
284
|
+
})
|
|
285
|
+
})
|
|
286
|
+
});
|
|
287
|
+
var FeedbackForm = ({
|
|
288
|
+
analytics,
|
|
289
|
+
appName,
|
|
290
|
+
handleClose,
|
|
291
|
+
loading,
|
|
292
|
+
sent,
|
|
293
|
+
setLoading,
|
|
294
|
+
setSent
|
|
295
|
+
}) => {
|
|
296
|
+
var _a;
|
|
297
|
+
const {
|
|
298
|
+
control,
|
|
299
|
+
formState: { errors },
|
|
300
|
+
handleSubmit,
|
|
301
|
+
register,
|
|
302
|
+
setValue,
|
|
303
|
+
watch
|
|
304
|
+
} = useForm();
|
|
305
|
+
const onSubmit = async ({ smileField, ...values }) => {
|
|
306
|
+
setLoading(true);
|
|
307
|
+
try {
|
|
308
|
+
const response = await avRegionsApi.getCurrentRegion();
|
|
309
|
+
await analytics.info({
|
|
310
|
+
surveyId: `${appName.replace(/\s/g, "_")}_Smile_Survey`,
|
|
311
|
+
smileLocation: `${appName}`,
|
|
312
|
+
smile: `icon-${smileField}`,
|
|
313
|
+
url: window.location.href,
|
|
314
|
+
region: response.data.regions[0] && response.data.regions[0].id,
|
|
315
|
+
userAgent: window.navigator.userAgent,
|
|
316
|
+
submitTime: new Date(),
|
|
317
|
+
...values
|
|
318
|
+
});
|
|
319
|
+
setSent(true);
|
|
320
|
+
setLoading(false);
|
|
321
|
+
} catch {
|
|
322
|
+
setSent(false);
|
|
323
|
+
setLoading(false);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
if (sent) {
|
|
328
|
+
setTimeout(() => {
|
|
329
|
+
handleClose();
|
|
330
|
+
}, 2e3);
|
|
331
|
+
}
|
|
332
|
+
}, [sent]);
|
|
333
|
+
const options = [
|
|
334
|
+
{
|
|
335
|
+
Icon: FaceSmileIcon,
|
|
336
|
+
label: "What do you like?",
|
|
337
|
+
value: "smile"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
Icon: FaceNeutralIcon,
|
|
341
|
+
label: "What would you improve?",
|
|
342
|
+
value: "meh"
|
|
343
|
+
},
|
|
344
|
+
{ Icon: FaceFrownIcon, label: "What don't you like?", value: "frown" }
|
|
345
|
+
];
|
|
346
|
+
const getFeedbackLabel = () => {
|
|
347
|
+
const smile = watch("smileField");
|
|
348
|
+
const option = options.find((option2) => option2.value === smile);
|
|
349
|
+
return (option == null ? void 0 : option.label) || "What would you improve?";
|
|
350
|
+
};
|
|
351
|
+
if (!sent) {
|
|
352
|
+
return /* @__PURE__ */ jsxs5(Grid, {
|
|
353
|
+
component: "form",
|
|
354
|
+
container: true,
|
|
355
|
+
justifyContent: "center",
|
|
356
|
+
onSubmit: handleSubmit(onSubmit),
|
|
357
|
+
"aria-label": "Feedback Form",
|
|
358
|
+
"aria-describedby": "feedback-form-header",
|
|
359
|
+
children: [
|
|
360
|
+
/* @__PURE__ */ jsx7(Controller, {
|
|
361
|
+
control,
|
|
362
|
+
name: "smileField",
|
|
363
|
+
render: ({ field }) => {
|
|
364
|
+
return /* @__PURE__ */ jsx7(SmileButtons, {
|
|
365
|
+
children: options.map((props, index) => /* @__PURE__ */ jsx7(SmileButton, {
|
|
366
|
+
autoFocus: index === 0,
|
|
367
|
+
disabled: loading,
|
|
368
|
+
...props
|
|
369
|
+
}, props.value)),
|
|
370
|
+
...field,
|
|
371
|
+
"aria-labelledby": "feedback-form-header",
|
|
372
|
+
onChange: (event, value) => {
|
|
373
|
+
setValue(field.name, value);
|
|
374
|
+
},
|
|
375
|
+
size: "medium",
|
|
376
|
+
exclusive: true
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}),
|
|
380
|
+
/* @__PURE__ */ jsx7(TextField, {
|
|
381
|
+
...register("feedback", {
|
|
382
|
+
required: "This field is required",
|
|
383
|
+
maxLength: { value: 200, message: "This field must not exceed 200 characters" }
|
|
384
|
+
}),
|
|
385
|
+
fullWidth: true,
|
|
386
|
+
multiline: true,
|
|
387
|
+
minRows: 3,
|
|
388
|
+
maxRows: 3,
|
|
389
|
+
label: getFeedbackLabel(),
|
|
390
|
+
inputProps: { "aria-required": "true" },
|
|
391
|
+
InputLabelProps: {
|
|
392
|
+
component: FormLabel,
|
|
393
|
+
required: true
|
|
394
|
+
},
|
|
395
|
+
helperText: ((_a = errors.feedback) == null ? void 0 : _a.message) || "Max 200 characters",
|
|
396
|
+
error: !!errors.feedback,
|
|
397
|
+
disabled: loading
|
|
398
|
+
}),
|
|
399
|
+
/* @__PURE__ */ jsxs5(Grid, {
|
|
400
|
+
container: true,
|
|
401
|
+
direction: "row",
|
|
402
|
+
marginTop: "16px",
|
|
403
|
+
spacing: 1,
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ jsx7(Grid, {
|
|
406
|
+
item: true,
|
|
407
|
+
xs: 6,
|
|
408
|
+
children: /* @__PURE__ */ jsx7(Button, {
|
|
409
|
+
color: "secondary",
|
|
410
|
+
disabled: loading,
|
|
411
|
+
fullWidth: true,
|
|
412
|
+
onClick: handleClose,
|
|
413
|
+
children: "Cancel"
|
|
414
|
+
})
|
|
415
|
+
}),
|
|
416
|
+
/* @__PURE__ */ jsx7(Grid, {
|
|
417
|
+
item: true,
|
|
418
|
+
xs: 6,
|
|
419
|
+
children: /* @__PURE__ */ jsx7(LoadingButton, {
|
|
420
|
+
disabled: !watch("smileField"),
|
|
421
|
+
fullWidth: true,
|
|
422
|
+
loading,
|
|
423
|
+
type: "submit",
|
|
424
|
+
variant: "contained",
|
|
425
|
+
children: "Send Feedback"
|
|
426
|
+
})
|
|
427
|
+
})
|
|
428
|
+
]
|
|
429
|
+
})
|
|
430
|
+
]
|
|
431
|
+
});
|
|
432
|
+
} else {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
// src/lib/FeedbackHeader.tsx
|
|
438
|
+
import { IconButton as IconButton2 } from "@availity/mui-button";
|
|
439
|
+
import { CloseIcon } from "@availity/mui-icon";
|
|
440
|
+
|
|
441
|
+
// ../typography/src/lib/Typography.tsx
|
|
442
|
+
import { forwardRef as forwardRef3 } from "react";
|
|
443
|
+
import { Typography as MuiTypography } from "@mui/material";
|
|
444
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
445
|
+
var Typography = forwardRef3(
|
|
446
|
+
({ children, ...rest }, ref) => {
|
|
447
|
+
return /* @__PURE__ */ jsx8(MuiTypography, {
|
|
448
|
+
...rest,
|
|
449
|
+
ref,
|
|
450
|
+
children
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
// src/lib/FeedbackHeader.tsx
|
|
456
|
+
import { Grid as Grid2 } from "@mui/material";
|
|
457
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
458
|
+
var FeedbackHeader = ({ appName, handleClose, loading, sent }) => {
|
|
459
|
+
return /* @__PURE__ */ jsxs6(Grid2, {
|
|
460
|
+
alignItems: "center",
|
|
461
|
+
container: true,
|
|
462
|
+
direction: "row",
|
|
463
|
+
marginBottom: !sent ? "8px" : "0px",
|
|
464
|
+
justifyContent: "space-between",
|
|
465
|
+
flexWrap: "nowrap",
|
|
466
|
+
id: "feedback-form-header",
|
|
467
|
+
children: [
|
|
468
|
+
/* @__PURE__ */ jsx9(Grid2, {
|
|
469
|
+
item: true,
|
|
470
|
+
whiteSpace: "normal",
|
|
471
|
+
children: /* @__PURE__ */ jsx9(Typography, {
|
|
472
|
+
component: "h2",
|
|
473
|
+
variant: "h5",
|
|
474
|
+
children: sent ? "Thank you for your feedback." : `Tell us what you think about ${appName}`
|
|
475
|
+
})
|
|
476
|
+
}),
|
|
477
|
+
/* @__PURE__ */ jsx9(Grid2, {
|
|
478
|
+
item: true,
|
|
479
|
+
marginRight: "-8px",
|
|
480
|
+
children: /* @__PURE__ */ jsx9(IconButton2, {
|
|
481
|
+
disabled: loading,
|
|
482
|
+
title: "Close",
|
|
483
|
+
onClick: handleClose,
|
|
484
|
+
children: /* @__PURE__ */ jsx9(CloseIcon, {})
|
|
485
|
+
})
|
|
486
|
+
})
|
|
487
|
+
]
|
|
488
|
+
});
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
// src/lib/Feedback.tsx
|
|
492
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
493
|
+
var FeedbackContainer = styled3(Container, { name: "AvFeedbackContainer", slot: "root" })({});
|
|
494
|
+
var Feedback = ({ analytics = avLogMessagesApi, appName }) => {
|
|
495
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
496
|
+
const [sent, setSent] = useState(false);
|
|
497
|
+
const [loading, setLoading] = useState(false);
|
|
498
|
+
const handlePopoverOpen = (event) => {
|
|
499
|
+
setAnchorEl(event.currentTarget);
|
|
500
|
+
};
|
|
501
|
+
const handlePopoverClose = () => {
|
|
502
|
+
setAnchorEl(null);
|
|
503
|
+
};
|
|
504
|
+
const open = Boolean(anchorEl);
|
|
505
|
+
return /* @__PURE__ */ jsxs7(Fragment, {
|
|
506
|
+
children: [
|
|
507
|
+
/* @__PURE__ */ jsx10(Button2, {
|
|
508
|
+
onClick: handlePopoverOpen,
|
|
509
|
+
color: "secondary",
|
|
510
|
+
size: "large",
|
|
511
|
+
children: "Give Feedback"
|
|
512
|
+
}),
|
|
513
|
+
/* @__PURE__ */ jsx10(Popover, {
|
|
514
|
+
anchorEl,
|
|
515
|
+
anchorOrigin: {
|
|
516
|
+
vertical: "bottom",
|
|
517
|
+
horizontal: "right"
|
|
518
|
+
},
|
|
519
|
+
sx: { marginTop: "4px" },
|
|
520
|
+
disableRestoreFocus: true,
|
|
521
|
+
onClose: handlePopoverClose,
|
|
522
|
+
open,
|
|
523
|
+
transformOrigin: {
|
|
524
|
+
vertical: "top",
|
|
525
|
+
horizontal: "right"
|
|
526
|
+
},
|
|
527
|
+
children: /* @__PURE__ */ jsxs7(FeedbackContainer, {
|
|
528
|
+
children: [
|
|
529
|
+
/* @__PURE__ */ jsx10(FeedbackHeader, {
|
|
530
|
+
appName,
|
|
531
|
+
handleClose: handlePopoverClose,
|
|
532
|
+
loading,
|
|
533
|
+
sent
|
|
534
|
+
}),
|
|
535
|
+
/* @__PURE__ */ jsx10(FeedbackForm, {
|
|
536
|
+
analytics,
|
|
537
|
+
appName,
|
|
538
|
+
handleClose: handlePopoverClose,
|
|
539
|
+
loading,
|
|
540
|
+
sent,
|
|
541
|
+
setLoading,
|
|
542
|
+
setSent
|
|
543
|
+
})
|
|
544
|
+
]
|
|
545
|
+
})
|
|
546
|
+
})
|
|
547
|
+
]
|
|
548
|
+
});
|
|
549
|
+
};
|
|
550
|
+
export {
|
|
551
|
+
Feedback
|
|
552
|
+
};
|
package/introduction.mdx
ADDED
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@availity/mui-feedback",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Availity MUI Feedback Component - part of the @availity/element design system",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"typescript",
|
|
8
|
+
"availity",
|
|
9
|
+
"mui"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://availity.github.io/element/?path=/docs/components-feedback-introduction--docs",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Availity/element/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/Availity/element.git",
|
|
18
|
+
"directory": "packages/feedback"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "Availity Developers <AVOSS@availity.com>",
|
|
22
|
+
"browser": "./dist/index.js",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"module": "./dist/index.mjs",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
28
|
+
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"clean:nm": "rm -rf node_modules",
|
|
31
|
+
"publish": "yarn npm publish --tolerate-republish --access public",
|
|
32
|
+
"publish:canary": "yarn npm publish --access public --tag canary"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@mui/material": "^5.11.9",
|
|
36
|
+
"react": "18.2.0",
|
|
37
|
+
"react-dom": "18.2.0",
|
|
38
|
+
"tsup": "^5.12.7",
|
|
39
|
+
"typescript": "^4.6.4"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@mui/material": "^5.11.9",
|
|
43
|
+
"react": ">=16.3.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@availity/api-axios": "^8.0.3",
|
|
50
|
+
"@availity/mui-button": "^0.5.1",
|
|
51
|
+
"@availity/mui-icon": "^0.7.3",
|
|
52
|
+
"@availity/mui-popover": "^0.1.1",
|
|
53
|
+
"@availity/mui-textfield": "^0.3.3",
|
|
54
|
+
"@availity/mui-toggle-button": "^0.1.6",
|
|
55
|
+
"react-hook-form": "^7.48.2"
|
|
56
|
+
}
|
|
57
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mui-feedback",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/feedback/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"targets": {
|
|
8
|
+
"lint": {
|
|
9
|
+
"executor": "@nrwl/linter:eslint",
|
|
10
|
+
"options": {
|
|
11
|
+
"eslintConfig": ".eslintrc.json",
|
|
12
|
+
"lintFilePatterns": ["packages/feedback/**/*.{js,ts}"],
|
|
13
|
+
"silent": false,
|
|
14
|
+
"fix": false,
|
|
15
|
+
"cache": true,
|
|
16
|
+
"cacheLocation": "./node_modules/.cache/feedback/.eslintcache",
|
|
17
|
+
"maxWarnings": -1,
|
|
18
|
+
"quiet": false,
|
|
19
|
+
"noEslintrc": false,
|
|
20
|
+
"hasTypeAwareRules": true,
|
|
21
|
+
"cacheStrategy": "metadata"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"test": {
|
|
25
|
+
"executor": "@nrwl/jest:jest",
|
|
26
|
+
"outputs": ["coverage/feedback"],
|
|
27
|
+
"options": {
|
|
28
|
+
"jestConfig": "packages/feedback/jest.config.js",
|
|
29
|
+
"passWithNoTests": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"version": {
|
|
33
|
+
"executor": "@jscutlery/semver:version",
|
|
34
|
+
"options": {
|
|
35
|
+
"preset": "conventional",
|
|
36
|
+
"commitMessageFormat": "chore(${projectName}): release version ${version} [skip ci]",
|
|
37
|
+
"tagPrefix": "@availity/${projectName}@",
|
|
38
|
+
"trackDeps": true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/Feedback';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Each exported component in the package should have its own stories file
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
|
+
import { Feedback, FeedbackProps } from './Feedback';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Feedback> = {
|
|
7
|
+
title: 'Components/Feedback/Feedback',
|
|
8
|
+
component: Feedback,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
export const _Feedback: StoryObj<typeof Feedback> = {
|
|
15
|
+
render: (args: FeedbackProps) => <Feedback {...args} />,
|
|
16
|
+
args: {
|
|
17
|
+
appName: 'This App',
|
|
18
|
+
},
|
|
19
|
+
};
|