elseware-ui 2.36.9 → 2.37.1
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/dist/index.css +240 -3
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +487 -3
- package/dist/index.d.ts +487 -3
- package/dist/index.js +1600 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1576 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20196,26 +20196,40 @@ var Drawer = ({
|
|
|
20196
20196
|
side = "left",
|
|
20197
20197
|
handleClose,
|
|
20198
20198
|
styles,
|
|
20199
|
+
backdropStyles,
|
|
20199
20200
|
showBackdrop = true,
|
|
20200
|
-
closeOnBackdropClick = true
|
|
20201
|
+
closeOnBackdropClick = true,
|
|
20202
|
+
offsetTop = "0px",
|
|
20203
|
+
offsetBottom = "0px"
|
|
20201
20204
|
}) => {
|
|
20202
20205
|
const isHorizontal = side === "left" || side === "right";
|
|
20203
20206
|
const isMobile = useIsMobile_default();
|
|
20207
|
+
const hasOffset = offsetTop !== "0px" || offsetBottom !== "0px";
|
|
20208
|
+
const drawerStyle = isHorizontal ? {
|
|
20209
|
+
top: offsetTop,
|
|
20210
|
+
bottom: offsetBottom,
|
|
20211
|
+
height: hasOffset ? `calc(100vh - ${offsetTop} - ${offsetBottom})` : void 0
|
|
20212
|
+
} : void 0;
|
|
20204
20213
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20205
20214
|
isMobile && showBackdrop && /* @__PURE__ */ jsxRuntime.jsx(TransitionFade_default, { visibility, leaveDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20206
20215
|
"div",
|
|
20207
20216
|
{
|
|
20208
|
-
className:
|
|
20217
|
+
className: classNames17__default.default(
|
|
20218
|
+
"fixed inset-0 bg-black/50 z-40",
|
|
20219
|
+
backdropStyles
|
|
20220
|
+
),
|
|
20209
20221
|
onClick: closeOnBackdropClick ? handleClose : void 0
|
|
20210
20222
|
}
|
|
20211
20223
|
) }),
|
|
20212
20224
|
/* @__PURE__ */ jsxRuntime.jsx(TransitionSlide_default, { visibility, side, leaveDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20213
20225
|
"div",
|
|
20214
20226
|
{
|
|
20227
|
+
style: drawerStyle,
|
|
20215
20228
|
className: classNames17__default.default(
|
|
20216
20229
|
"fixed shadow-lg z-50",
|
|
20217
20230
|
{
|
|
20218
|
-
"h-full w-[300px] top-0": isHorizontal,
|
|
20231
|
+
"h-full w-[300px] top-0": isHorizontal && !hasOffset,
|
|
20232
|
+
"w-[300px]": isHorizontal && hasOffset,
|
|
20219
20233
|
"w-full h-[300px] left-0": !isHorizontal,
|
|
20220
20234
|
"left-0": side === "left",
|
|
20221
20235
|
"right-0": side === "right",
|
|
@@ -22976,6 +22990,1563 @@ var TopNav = ({
|
|
|
22976
22990
|
};
|
|
22977
22991
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: items.map(renderNode) });
|
|
22978
22992
|
};
|
|
22993
|
+
function ReviewForm({
|
|
22994
|
+
initialValues,
|
|
22995
|
+
placeholder = "Write your review...",
|
|
22996
|
+
submitLabel = "Submit",
|
|
22997
|
+
cancelLabel = "Cancel",
|
|
22998
|
+
loading = false,
|
|
22999
|
+
disabled = false,
|
|
23000
|
+
autoFocus = false,
|
|
23001
|
+
config,
|
|
23002
|
+
onSubmit,
|
|
23003
|
+
onCancel
|
|
23004
|
+
}) {
|
|
23005
|
+
const [content, setContent] = React2.useState(initialValues?.content ?? "");
|
|
23006
|
+
const [rating, setRating] = React2.useState(initialValues?.rating ?? 0);
|
|
23007
|
+
const [isRecommended, setIsRecommended] = React2.useState(
|
|
23008
|
+
initialValues?.isRecommended ?? true
|
|
23009
|
+
);
|
|
23010
|
+
const [error, setError] = React2.useState("");
|
|
23011
|
+
const contentLength = content.trim().length;
|
|
23012
|
+
const ratingItems = React2.useMemo(() => {
|
|
23013
|
+
return Array.from(
|
|
23014
|
+
{
|
|
23015
|
+
length: config.maxRating
|
|
23016
|
+
},
|
|
23017
|
+
(_, index) => index + 1
|
|
23018
|
+
);
|
|
23019
|
+
}, [config.maxRating]);
|
|
23020
|
+
React2.useEffect(() => {
|
|
23021
|
+
setContent(initialValues?.content ?? "");
|
|
23022
|
+
setRating(initialValues?.rating ?? 0);
|
|
23023
|
+
setIsRecommended(initialValues?.isRecommended ?? true);
|
|
23024
|
+
setError("");
|
|
23025
|
+
}, [
|
|
23026
|
+
initialValues?.content,
|
|
23027
|
+
initialValues?.rating,
|
|
23028
|
+
initialValues?.isRecommended
|
|
23029
|
+
]);
|
|
23030
|
+
function validate() {
|
|
23031
|
+
const trimmedContent = content.trim();
|
|
23032
|
+
if (trimmedContent.length < config.minContentLength) {
|
|
23033
|
+
return `Review must be at least ${config.minContentLength} characters.`;
|
|
23034
|
+
}
|
|
23035
|
+
if (trimmedContent.length > config.maxContentLength) {
|
|
23036
|
+
return `Review cannot be more than ${config.maxContentLength} characters.`;
|
|
23037
|
+
}
|
|
23038
|
+
if (rating < config.minRating) {
|
|
23039
|
+
return "Please select a rating.";
|
|
23040
|
+
}
|
|
23041
|
+
return "";
|
|
23042
|
+
}
|
|
23043
|
+
async function handleSubmit() {
|
|
23044
|
+
const nextError = validate();
|
|
23045
|
+
if (nextError) {
|
|
23046
|
+
setError(nextError);
|
|
23047
|
+
return;
|
|
23048
|
+
}
|
|
23049
|
+
const values = {
|
|
23050
|
+
content: content.trim(),
|
|
23051
|
+
rating,
|
|
23052
|
+
isRecommended: config.allowRecommendation ? isRecommended : void 0
|
|
23053
|
+
};
|
|
23054
|
+
await onSubmit(values);
|
|
23055
|
+
}
|
|
23056
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
23057
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23058
|
+
"textarea",
|
|
23059
|
+
{
|
|
23060
|
+
value: content,
|
|
23061
|
+
disabled: disabled || loading,
|
|
23062
|
+
autoFocus,
|
|
23063
|
+
placeholder,
|
|
23064
|
+
maxLength: config.maxContentLength,
|
|
23065
|
+
onChange: (event) => {
|
|
23066
|
+
setContent(event.target.value);
|
|
23067
|
+
setError("");
|
|
23068
|
+
},
|
|
23069
|
+
className: "min-h-[120px] w-full resize-none rounded-xl border border-gray-300 bg-white px-4 py-3 text-sm text-gray-900 outline-none transition-colors placeholder:text-gray-400 focus:border-blue-500 disabled:cursor-not-allowed disabled:opacity-60 dark:border-neutral-700 dark:bg-neutral-900 dark:text-gray-100 dark:placeholder:text-gray-500"
|
|
23070
|
+
}
|
|
23071
|
+
),
|
|
23072
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
23073
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
23074
|
+
contentLength,
|
|
23075
|
+
"/",
|
|
23076
|
+
config.maxContentLength
|
|
23077
|
+
] }),
|
|
23078
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: error })
|
|
23079
|
+
] }),
|
|
23080
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
23081
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Rating" }),
|
|
23082
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: ratingItems.map((item) => {
|
|
23083
|
+
const active = item <= rating;
|
|
23084
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23085
|
+
"button",
|
|
23086
|
+
{
|
|
23087
|
+
type: "button",
|
|
23088
|
+
disabled: disabled || loading,
|
|
23089
|
+
onClick: () => {
|
|
23090
|
+
setRating(item);
|
|
23091
|
+
setError("");
|
|
23092
|
+
},
|
|
23093
|
+
className: `
|
|
23094
|
+
text-2xl leading-none transition-transform disabled:cursor-not-allowed disabled:opacity-60
|
|
23095
|
+
${active ? "text-yellow-400" : "text-gray-300 dark:text-neutral-700"}
|
|
23096
|
+
hover:scale-110
|
|
23097
|
+
`,
|
|
23098
|
+
"aria-label": `Rate ${item} out of ${config.maxRating}`,
|
|
23099
|
+
children: "\u2605"
|
|
23100
|
+
},
|
|
23101
|
+
item
|
|
23102
|
+
);
|
|
23103
|
+
}) })
|
|
23104
|
+
] }),
|
|
23105
|
+
config.allowRecommendation && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
23106
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Do you recommend this?" }),
|
|
23107
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
|
|
23108
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
|
|
23109
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23110
|
+
"input",
|
|
23111
|
+
{
|
|
23112
|
+
type: "radio",
|
|
23113
|
+
checked: isRecommended,
|
|
23114
|
+
disabled: disabled || loading,
|
|
23115
|
+
onChange: () => setIsRecommended(true)
|
|
23116
|
+
}
|
|
23117
|
+
),
|
|
23118
|
+
"Yes"
|
|
23119
|
+
] }),
|
|
23120
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
|
|
23121
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23122
|
+
"input",
|
|
23123
|
+
{
|
|
23124
|
+
type: "radio",
|
|
23125
|
+
checked: !isRecommended,
|
|
23126
|
+
disabled: disabled || loading,
|
|
23127
|
+
onChange: () => setIsRecommended(false)
|
|
23128
|
+
}
|
|
23129
|
+
),
|
|
23130
|
+
"No"
|
|
23131
|
+
] })
|
|
23132
|
+
] })
|
|
23133
|
+
] }),
|
|
23134
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
23135
|
+
onCancel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23136
|
+
Button_default,
|
|
23137
|
+
{
|
|
23138
|
+
text: cancelLabel,
|
|
23139
|
+
variant: "secondary",
|
|
23140
|
+
appearance: "ghost",
|
|
23141
|
+
disabled: loading,
|
|
23142
|
+
onClick: onCancel
|
|
23143
|
+
}
|
|
23144
|
+
),
|
|
23145
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23146
|
+
Button_default,
|
|
23147
|
+
{
|
|
23148
|
+
text: submitLabel,
|
|
23149
|
+
variant: "primary",
|
|
23150
|
+
loading,
|
|
23151
|
+
disabled: disabled || !content.trim() || rating < config.minRating,
|
|
23152
|
+
onClick: handleSubmit
|
|
23153
|
+
}
|
|
23154
|
+
)
|
|
23155
|
+
] })
|
|
23156
|
+
] });
|
|
23157
|
+
}
|
|
23158
|
+
var ReviewForm_default = ReviewForm;
|
|
23159
|
+
function ReviewComposer({
|
|
23160
|
+
currentUser,
|
|
23161
|
+
placeholder = "Write your review...",
|
|
23162
|
+
submitLabel = "Post Review",
|
|
23163
|
+
loading = false,
|
|
23164
|
+
disabled = false,
|
|
23165
|
+
config,
|
|
23166
|
+
onLoginClick,
|
|
23167
|
+
onSubmit
|
|
23168
|
+
}) {
|
|
23169
|
+
if (!currentUser) {
|
|
23170
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
|
|
23171
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: "Please login to post your review." }),
|
|
23172
|
+
onLoginClick && /* @__PURE__ */ jsxRuntime.jsx(Button_default, { text: "Login", variant: "primary", onClick: onLoginClick })
|
|
23173
|
+
] }) });
|
|
23174
|
+
}
|
|
23175
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
|
|
23176
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: currentUser.avatar, size: "md" }),
|
|
23177
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23178
|
+
ReviewForm_default,
|
|
23179
|
+
{
|
|
23180
|
+
placeholder,
|
|
23181
|
+
submitLabel,
|
|
23182
|
+
loading,
|
|
23183
|
+
disabled,
|
|
23184
|
+
config,
|
|
23185
|
+
onSubmit
|
|
23186
|
+
}
|
|
23187
|
+
) })
|
|
23188
|
+
] }) });
|
|
23189
|
+
}
|
|
23190
|
+
var ReviewComposer_default = ReviewComposer;
|
|
23191
|
+
|
|
23192
|
+
// src/compositions/review-thread/utils/formatReviewDate.ts
|
|
23193
|
+
function formatReviewDate(date, format = "relative") {
|
|
23194
|
+
if (!date) {
|
|
23195
|
+
return "";
|
|
23196
|
+
}
|
|
23197
|
+
const target = new Date(date);
|
|
23198
|
+
if (Number.isNaN(target.getTime())) {
|
|
23199
|
+
return "";
|
|
23200
|
+
}
|
|
23201
|
+
if (format === "absolute") {
|
|
23202
|
+
return target.toLocaleString();
|
|
23203
|
+
}
|
|
23204
|
+
const now = /* @__PURE__ */ new Date();
|
|
23205
|
+
const seconds = Math.floor((now.getTime() - target.getTime()) / 1e3);
|
|
23206
|
+
if (seconds < 60) {
|
|
23207
|
+
return "Just now";
|
|
23208
|
+
}
|
|
23209
|
+
const intervals = [
|
|
23210
|
+
{
|
|
23211
|
+
label: "year",
|
|
23212
|
+
seconds: 31536e3
|
|
23213
|
+
},
|
|
23214
|
+
{
|
|
23215
|
+
label: "month",
|
|
23216
|
+
seconds: 2592e3
|
|
23217
|
+
},
|
|
23218
|
+
{
|
|
23219
|
+
label: "day",
|
|
23220
|
+
seconds: 86400
|
|
23221
|
+
},
|
|
23222
|
+
{
|
|
23223
|
+
label: "hour",
|
|
23224
|
+
seconds: 3600
|
|
23225
|
+
},
|
|
23226
|
+
{
|
|
23227
|
+
label: "minute",
|
|
23228
|
+
seconds: 60
|
|
23229
|
+
}
|
|
23230
|
+
];
|
|
23231
|
+
for (const interval of intervals) {
|
|
23232
|
+
const count = Math.floor(seconds / interval.seconds);
|
|
23233
|
+
if (count >= 1) {
|
|
23234
|
+
return `${count} ${interval.label}${count > 1 ? "s" : ""} ago`;
|
|
23235
|
+
}
|
|
23236
|
+
}
|
|
23237
|
+
return "Just now";
|
|
23238
|
+
}
|
|
23239
|
+
|
|
23240
|
+
// src/compositions/review-thread/utils/reviewState.ts
|
|
23241
|
+
function prependReview(reviews, review) {
|
|
23242
|
+
return [review, ...reviews.filter((item) => item.id !== review.id)];
|
|
23243
|
+
}
|
|
23244
|
+
function appendReview(reviews, review) {
|
|
23245
|
+
return [...reviews.filter((item) => item.id !== review.id), review];
|
|
23246
|
+
}
|
|
23247
|
+
function updateReview(reviews, reviewId, updater) {
|
|
23248
|
+
return reviews.map(
|
|
23249
|
+
(review) => review.id === reviewId ? updater(review) : review
|
|
23250
|
+
);
|
|
23251
|
+
}
|
|
23252
|
+
function replaceReview(reviews, nextReview) {
|
|
23253
|
+
return updateReview(reviews, nextReview.id, () => nextReview);
|
|
23254
|
+
}
|
|
23255
|
+
function removeReview(reviews, reviewId) {
|
|
23256
|
+
return reviews.filter((review) => review.id !== reviewId);
|
|
23257
|
+
}
|
|
23258
|
+
function findReview(reviews, reviewId) {
|
|
23259
|
+
return reviews.find((review) => review.id === reviewId);
|
|
23260
|
+
}
|
|
23261
|
+
function upsertReview(reviews, review) {
|
|
23262
|
+
const exists = reviews.some((item) => item.id === review.id);
|
|
23263
|
+
if (!exists) {
|
|
23264
|
+
return prependReview(reviews, review);
|
|
23265
|
+
}
|
|
23266
|
+
return replaceReview(reviews, review);
|
|
23267
|
+
}
|
|
23268
|
+
|
|
23269
|
+
// src/compositions/review-thread/utils/reviewReplyState.ts
|
|
23270
|
+
function addReviewReply(review, reply, maxReplies = 1) {
|
|
23271
|
+
const replies = review.replies ?? [];
|
|
23272
|
+
return {
|
|
23273
|
+
...review,
|
|
23274
|
+
replies: [reply, ...replies.filter((item) => item.id !== reply.id)].slice(
|
|
23275
|
+
0,
|
|
23276
|
+
maxReplies
|
|
23277
|
+
)
|
|
23278
|
+
};
|
|
23279
|
+
}
|
|
23280
|
+
function updateReviewReply(review, replyId, updater) {
|
|
23281
|
+
return {
|
|
23282
|
+
...review,
|
|
23283
|
+
replies: (review.replies ?? []).map(
|
|
23284
|
+
(reply) => reply.id === replyId ? updater(reply) : reply
|
|
23285
|
+
)
|
|
23286
|
+
};
|
|
23287
|
+
}
|
|
23288
|
+
function replaceReviewReply(review, nextReply) {
|
|
23289
|
+
return updateReviewReply(review, nextReply.id, () => nextReply);
|
|
23290
|
+
}
|
|
23291
|
+
function removeReviewReply(review, replyId) {
|
|
23292
|
+
return {
|
|
23293
|
+
...review,
|
|
23294
|
+
replies: (review.replies ?? []).filter((reply) => reply.id !== replyId)
|
|
23295
|
+
};
|
|
23296
|
+
}
|
|
23297
|
+
function hasReviewReply(review, replyId) {
|
|
23298
|
+
return (review.replies ?? []).some((reply) => reply.id === replyId);
|
|
23299
|
+
}
|
|
23300
|
+
|
|
23301
|
+
// src/compositions/review-thread/utils/reviewPermissions.ts
|
|
23302
|
+
function canEditReview(review) {
|
|
23303
|
+
return review.permissions?.canEdit ?? false;
|
|
23304
|
+
}
|
|
23305
|
+
function canDeleteReview(review) {
|
|
23306
|
+
return review.permissions?.canDelete ?? false;
|
|
23307
|
+
}
|
|
23308
|
+
function canReportReview(review) {
|
|
23309
|
+
return review.permissions?.canReport ?? false;
|
|
23310
|
+
}
|
|
23311
|
+
function canReplyToReview(review) {
|
|
23312
|
+
return review.permissions?.canReply ?? false;
|
|
23313
|
+
}
|
|
23314
|
+
function canEditReviewReply(reply) {
|
|
23315
|
+
return reply.permissions?.canEdit ?? false;
|
|
23316
|
+
}
|
|
23317
|
+
function canDeleteReviewReply(reply) {
|
|
23318
|
+
return reply.permissions?.canDelete ?? false;
|
|
23319
|
+
}
|
|
23320
|
+
function canReportReviewReply(reply) {
|
|
23321
|
+
return reply.permissions?.canReport ?? false;
|
|
23322
|
+
}
|
|
23323
|
+
|
|
23324
|
+
// src/compositions/review-thread/utils/normalizeReview.ts
|
|
23325
|
+
function normalizeReviewAuthor(author) {
|
|
23326
|
+
if (!author) {
|
|
23327
|
+
return null;
|
|
23328
|
+
}
|
|
23329
|
+
return {
|
|
23330
|
+
id: String(author.id ?? author._id ?? ""),
|
|
23331
|
+
username: author.username,
|
|
23332
|
+
avatar: author.avatar,
|
|
23333
|
+
firstName: author.firstName,
|
|
23334
|
+
lastName: author.lastName,
|
|
23335
|
+
role: author.role
|
|
23336
|
+
};
|
|
23337
|
+
}
|
|
23338
|
+
function normalizeReviewReply(raw, fallback) {
|
|
23339
|
+
return {
|
|
23340
|
+
id: String(raw.id ?? raw._id ?? ""),
|
|
23341
|
+
targetId: String(raw.targetId ?? fallback.targetId),
|
|
23342
|
+
reviewId: String(raw.reviewId ?? fallback.reviewId),
|
|
23343
|
+
content: String(raw.content ?? raw.replyText ?? raw.responseText ?? ""),
|
|
23344
|
+
createdAt: String(raw.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()),
|
|
23345
|
+
updatedAt: raw.updatedAt,
|
|
23346
|
+
edited: raw.edited ?? false,
|
|
23347
|
+
author: normalizeReviewAuthor(raw.author ?? raw.repliedBy ?? null),
|
|
23348
|
+
authorLabel: raw.authorLabel,
|
|
23349
|
+
permissions: raw.permissions
|
|
23350
|
+
};
|
|
23351
|
+
}
|
|
23352
|
+
function normalizeReview(raw, fallbackTargetId = "") {
|
|
23353
|
+
const id = String(raw.id ?? raw._id ?? "");
|
|
23354
|
+
const targetId = String(
|
|
23355
|
+
raw.targetId ?? raw.gameSlug ?? raw.productSlug ?? raw.courseId ?? fallbackTargetId
|
|
23356
|
+
);
|
|
23357
|
+
const replies = raw.replies ? raw.replies.map(
|
|
23358
|
+
(reply) => normalizeReviewReply(reply, {
|
|
23359
|
+
targetId,
|
|
23360
|
+
reviewId: id
|
|
23361
|
+
})
|
|
23362
|
+
) : raw.ownerReply ? [
|
|
23363
|
+
normalizeReviewReply(raw.ownerReply, {
|
|
23364
|
+
targetId,
|
|
23365
|
+
reviewId: id
|
|
23366
|
+
})
|
|
23367
|
+
] : [];
|
|
23368
|
+
return {
|
|
23369
|
+
id,
|
|
23370
|
+
targetId,
|
|
23371
|
+
content: String(raw.content ?? raw.reviewText ?? ""),
|
|
23372
|
+
rating: Number(raw.rating ?? 0),
|
|
23373
|
+
isRecommended: raw.isRecommended,
|
|
23374
|
+
createdAt: String(raw.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()),
|
|
23375
|
+
updatedAt: raw.updatedAt,
|
|
23376
|
+
edited: raw.edited ?? false,
|
|
23377
|
+
author: normalizeReviewAuthor(raw.author ?? raw.reviewedBy ?? null),
|
|
23378
|
+
replies,
|
|
23379
|
+
permissions: raw.permissions
|
|
23380
|
+
};
|
|
23381
|
+
}
|
|
23382
|
+
function ReviewHeader({ review, config }) {
|
|
23383
|
+
const author = review.author;
|
|
23384
|
+
const displayName = author?.firstName || author?.lastName ? `${author?.firstName ?? ""} ${author?.lastName ?? ""}`.trim() : author?.username ?? "Unknown";
|
|
23385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
23386
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: author?.avatar, size: "sm" }),
|
|
23387
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
23388
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
23389
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold text-gray-900 dark:text-gray-100", children: displayName }),
|
|
23390
|
+
author?.username && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
|
|
23391
|
+
"@",
|
|
23392
|
+
author.username
|
|
23393
|
+
] }),
|
|
23394
|
+
author?.role && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600 dark:bg-neutral-800 dark:text-gray-300", children: author.role })
|
|
23395
|
+
] }),
|
|
23396
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
23397
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatReviewDate(review.createdAt, config.dateFormat) }),
|
|
23398
|
+
review.edited && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "(edited)" })
|
|
23399
|
+
] })
|
|
23400
|
+
] })
|
|
23401
|
+
] });
|
|
23402
|
+
}
|
|
23403
|
+
var ReviewHeader_default = ReviewHeader;
|
|
23404
|
+
function ReviewContent({ review }) {
|
|
23405
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-gray-700 dark:text-gray-300", children: review.content });
|
|
23406
|
+
}
|
|
23407
|
+
var ReviewContent_default = ReviewContent;
|
|
23408
|
+
function ReviewRating({ rating, maxRating }) {
|
|
23409
|
+
const items = Array.from(
|
|
23410
|
+
{
|
|
23411
|
+
length: maxRating
|
|
23412
|
+
},
|
|
23413
|
+
(_, index) => index + 1
|
|
23414
|
+
);
|
|
23415
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23416
|
+
"div",
|
|
23417
|
+
{
|
|
23418
|
+
className: "inline-flex items-center gap-0.5",
|
|
23419
|
+
"aria-label": `${rating} out of ${maxRating}`,
|
|
23420
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23421
|
+
"span",
|
|
23422
|
+
{
|
|
23423
|
+
className: item <= rating ? "text-sm text-yellow-400" : "text-sm text-gray-300 dark:text-neutral-700",
|
|
23424
|
+
children: "\u2605"
|
|
23425
|
+
},
|
|
23426
|
+
item
|
|
23427
|
+
))
|
|
23428
|
+
}
|
|
23429
|
+
);
|
|
23430
|
+
}
|
|
23431
|
+
var ReviewRating_default = ReviewRating;
|
|
23432
|
+
function ReviewRecommendation({ isRecommended }) {
|
|
23433
|
+
if (typeof isRecommended !== "boolean") {
|
|
23434
|
+
return null;
|
|
23435
|
+
}
|
|
23436
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23437
|
+
"span",
|
|
23438
|
+
{
|
|
23439
|
+
className: `
|
|
23440
|
+
inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
|
|
23441
|
+
${isRecommended ? "bg-green-500/10 text-green-500" : "bg-red-500/10 text-red-500"}
|
|
23442
|
+
`,
|
|
23443
|
+
children: [
|
|
23444
|
+
isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(bi.BiCheckCircle, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(bi.BiXCircle, { size: 16 }),
|
|
23445
|
+
isRecommended ? "Recommended" : "Not Recommended"
|
|
23446
|
+
]
|
|
23447
|
+
}
|
|
23448
|
+
);
|
|
23449
|
+
}
|
|
23450
|
+
var ReviewRecommendation_default = ReviewRecommendation;
|
|
23451
|
+
function MyReviewPanel({
|
|
23452
|
+
currentUser,
|
|
23453
|
+
myReview,
|
|
23454
|
+
loading = false,
|
|
23455
|
+
disabled = false,
|
|
23456
|
+
config,
|
|
23457
|
+
components,
|
|
23458
|
+
onLoginClick,
|
|
23459
|
+
onCreateReview,
|
|
23460
|
+
onUpdateReview,
|
|
23461
|
+
onEditReview,
|
|
23462
|
+
onDeleteReview
|
|
23463
|
+
}) {
|
|
23464
|
+
const [editing, setEditing] = React2.useState(false);
|
|
23465
|
+
const ComposerComponent = components?.Composer ?? ReviewComposer_default;
|
|
23466
|
+
const FormComponent = components?.Form ?? ReviewForm_default;
|
|
23467
|
+
const HeaderComponent = components?.Header ?? ReviewHeader_default;
|
|
23468
|
+
const ContentComponent = components?.Content ?? ReviewContent_default;
|
|
23469
|
+
const RatingComponent = components?.Rating ?? ReviewRating_default;
|
|
23470
|
+
const RecommendationComponent = components?.Recommendation ?? ReviewRecommendation_default;
|
|
23471
|
+
async function handleCreateReview(values) {
|
|
23472
|
+
await onCreateReview(values);
|
|
23473
|
+
}
|
|
23474
|
+
async function handleUpdateReview(values) {
|
|
23475
|
+
if (!myReview) {
|
|
23476
|
+
return;
|
|
23477
|
+
}
|
|
23478
|
+
await onUpdateReview(myReview, values);
|
|
23479
|
+
setEditing(false);
|
|
23480
|
+
}
|
|
23481
|
+
function handleEdit() {
|
|
23482
|
+
if (!myReview) {
|
|
23483
|
+
return;
|
|
23484
|
+
}
|
|
23485
|
+
if (onEditReview) {
|
|
23486
|
+
onEditReview(myReview);
|
|
23487
|
+
return;
|
|
23488
|
+
}
|
|
23489
|
+
setEditing(true);
|
|
23490
|
+
}
|
|
23491
|
+
function handleDelete() {
|
|
23492
|
+
if (!myReview) {
|
|
23493
|
+
return;
|
|
23494
|
+
}
|
|
23495
|
+
onDeleteReview?.(myReview);
|
|
23496
|
+
}
|
|
23497
|
+
if (!config.showMyReviewPanel) {
|
|
23498
|
+
return null;
|
|
23499
|
+
}
|
|
23500
|
+
if (!myReview) {
|
|
23501
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
23502
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: "My Review" }),
|
|
23503
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23504
|
+
ComposerComponent,
|
|
23505
|
+
{
|
|
23506
|
+
currentUser,
|
|
23507
|
+
placeholder: "Write your review...",
|
|
23508
|
+
submitLabel: "Post Review",
|
|
23509
|
+
loading,
|
|
23510
|
+
disabled,
|
|
23511
|
+
config,
|
|
23512
|
+
onLoginClick,
|
|
23513
|
+
onSubmit: handleCreateReview
|
|
23514
|
+
}
|
|
23515
|
+
)
|
|
23516
|
+
] });
|
|
23517
|
+
}
|
|
23518
|
+
if (editing) {
|
|
23519
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
23520
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: "Update My Review" }),
|
|
23521
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23522
|
+
FormComponent,
|
|
23523
|
+
{
|
|
23524
|
+
initialValues: {
|
|
23525
|
+
content: myReview.content,
|
|
23526
|
+
rating: myReview.rating,
|
|
23527
|
+
isRecommended: myReview.isRecommended
|
|
23528
|
+
},
|
|
23529
|
+
placeholder: "Update your review...",
|
|
23530
|
+
submitLabel: "Update Review",
|
|
23531
|
+
loading,
|
|
23532
|
+
disabled,
|
|
23533
|
+
autoFocus: true,
|
|
23534
|
+
config,
|
|
23535
|
+
onSubmit: handleUpdateReview,
|
|
23536
|
+
onCancel: () => setEditing(false)
|
|
23537
|
+
}
|
|
23538
|
+
) })
|
|
23539
|
+
] });
|
|
23540
|
+
}
|
|
23541
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
23542
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: "My Review" }),
|
|
23543
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
23544
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
23545
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderComponent, { review: myReview, config }),
|
|
23546
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
23547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23548
|
+
Button_default,
|
|
23549
|
+
{
|
|
23550
|
+
text: "Edit",
|
|
23551
|
+
variant: "secondary",
|
|
23552
|
+
appearance: "ghost",
|
|
23553
|
+
disabled: disabled || loading,
|
|
23554
|
+
onClick: handleEdit
|
|
23555
|
+
}
|
|
23556
|
+
),
|
|
23557
|
+
onDeleteReview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23558
|
+
Button_default,
|
|
23559
|
+
{
|
|
23560
|
+
text: "Delete",
|
|
23561
|
+
variant: "danger",
|
|
23562
|
+
appearance: "ghost",
|
|
23563
|
+
disabled: disabled || loading,
|
|
23564
|
+
onClick: handleDelete
|
|
23565
|
+
}
|
|
23566
|
+
)
|
|
23567
|
+
] })
|
|
23568
|
+
] }),
|
|
23569
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentComponent, { review: myReview }),
|
|
23570
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
23571
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23572
|
+
RatingComponent,
|
|
23573
|
+
{
|
|
23574
|
+
rating: myReview.rating,
|
|
23575
|
+
maxRating: config.maxRating
|
|
23576
|
+
}
|
|
23577
|
+
),
|
|
23578
|
+
config.allowRecommendation && /* @__PURE__ */ jsxRuntime.jsx(RecommendationComponent, { isRecommended: myReview.isRecommended })
|
|
23579
|
+
] })
|
|
23580
|
+
] }) })
|
|
23581
|
+
] });
|
|
23582
|
+
}
|
|
23583
|
+
var MyReviewPanel_default = MyReviewPanel;
|
|
23584
|
+
function ReviewMenuItem({
|
|
23585
|
+
icon,
|
|
23586
|
+
name,
|
|
23587
|
+
badge,
|
|
23588
|
+
to,
|
|
23589
|
+
navigate,
|
|
23590
|
+
className,
|
|
23591
|
+
onClick,
|
|
23592
|
+
style
|
|
23593
|
+
}) {
|
|
23594
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23595
|
+
MenuItem,
|
|
23596
|
+
{
|
|
23597
|
+
icon,
|
|
23598
|
+
name,
|
|
23599
|
+
badge,
|
|
23600
|
+
to,
|
|
23601
|
+
navigate,
|
|
23602
|
+
onClick,
|
|
23603
|
+
style,
|
|
23604
|
+
className
|
|
23605
|
+
}
|
|
23606
|
+
);
|
|
23607
|
+
}
|
|
23608
|
+
function ReviewMenu({
|
|
23609
|
+
open,
|
|
23610
|
+
setOpen,
|
|
23611
|
+
canEdit,
|
|
23612
|
+
canDelete,
|
|
23613
|
+
canReport,
|
|
23614
|
+
canReply,
|
|
23615
|
+
onEdit,
|
|
23616
|
+
onDelete,
|
|
23617
|
+
onReport,
|
|
23618
|
+
onReply
|
|
23619
|
+
}) {
|
|
23620
|
+
const ref = React2.useRef(null);
|
|
23621
|
+
useClickOutside(ref, () => setOpen(false));
|
|
23622
|
+
const items = [];
|
|
23623
|
+
if (canEdit) {
|
|
23624
|
+
items.push({
|
|
23625
|
+
type: "item",
|
|
23626
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiEdit, {}),
|
|
23627
|
+
name: "Edit Review",
|
|
23628
|
+
component: ReviewMenuItem,
|
|
23629
|
+
onClick: () => {
|
|
23630
|
+
setOpen(false);
|
|
23631
|
+
onEdit?.();
|
|
23632
|
+
},
|
|
23633
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23634
|
+
});
|
|
23635
|
+
}
|
|
23636
|
+
if (canDelete) {
|
|
23637
|
+
items.push({
|
|
23638
|
+
type: "item",
|
|
23639
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiTrash, {}),
|
|
23640
|
+
name: "Delete Review",
|
|
23641
|
+
component: ReviewMenuItem,
|
|
23642
|
+
onClick: () => {
|
|
23643
|
+
setOpen(false);
|
|
23644
|
+
onDelete?.();
|
|
23645
|
+
},
|
|
23646
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm text-red-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23647
|
+
});
|
|
23648
|
+
}
|
|
23649
|
+
if (canReport) {
|
|
23650
|
+
items.push({
|
|
23651
|
+
type: "item",
|
|
23652
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiFlag, {}),
|
|
23653
|
+
name: "Report Review",
|
|
23654
|
+
component: ReviewMenuItem,
|
|
23655
|
+
onClick: () => {
|
|
23656
|
+
setOpen(false);
|
|
23657
|
+
onReport?.();
|
|
23658
|
+
},
|
|
23659
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23660
|
+
});
|
|
23661
|
+
}
|
|
23662
|
+
if (canReply) {
|
|
23663
|
+
items.push({
|
|
23664
|
+
type: "item",
|
|
23665
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiReply, {}),
|
|
23666
|
+
name: "Reply as Owner",
|
|
23667
|
+
component: ReviewMenuItem,
|
|
23668
|
+
onClick: () => {
|
|
23669
|
+
setOpen(false);
|
|
23670
|
+
onReply?.();
|
|
23671
|
+
},
|
|
23672
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23673
|
+
});
|
|
23674
|
+
}
|
|
23675
|
+
if (!items.length) {
|
|
23676
|
+
return null;
|
|
23677
|
+
}
|
|
23678
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: "relative", children: [
|
|
23679
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23680
|
+
"button",
|
|
23681
|
+
{
|
|
23682
|
+
type: "button",
|
|
23683
|
+
onClick: () => setOpen(!open),
|
|
23684
|
+
className: "text-gray-500 transition-colors hover:text-gray-900 dark:hover:text-gray-100",
|
|
23685
|
+
"aria-label": "Review options",
|
|
23686
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(bi.BiDotsVerticalRounded, { size: 20 })
|
|
23687
|
+
}
|
|
23688
|
+
),
|
|
23689
|
+
/* @__PURE__ */ jsxRuntime.jsx(Transition.TransitionDropdown, { visibility: open, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-full z-50 mt-2 min-w-[190px] overflow-hidden rounded-xl border border-gray-200 bg-white shadow-xl dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsx(Menu, { items }) }) })
|
|
23690
|
+
] });
|
|
23691
|
+
}
|
|
23692
|
+
var ReviewMenu_default = ReviewMenu;
|
|
23693
|
+
function ReviewActions({ canReply, onReply }) {
|
|
23694
|
+
if (!canReply) {
|
|
23695
|
+
return null;
|
|
23696
|
+
}
|
|
23697
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4 text-sm text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23698
|
+
"button",
|
|
23699
|
+
{
|
|
23700
|
+
type: "button",
|
|
23701
|
+
onClick: onReply,
|
|
23702
|
+
className: "inline-flex items-center gap-1 font-medium transition-colors hover:text-gray-900 dark:hover:text-gray-100",
|
|
23703
|
+
children: [
|
|
23704
|
+
/* @__PURE__ */ jsxRuntime.jsx(bi.BiReply, { size: 18 }),
|
|
23705
|
+
"Reply as Owner"
|
|
23706
|
+
]
|
|
23707
|
+
}
|
|
23708
|
+
) });
|
|
23709
|
+
}
|
|
23710
|
+
var ReviewActions_default = ReviewActions;
|
|
23711
|
+
function ReviewReplyHeader({ reply, config }) {
|
|
23712
|
+
const author = reply.author;
|
|
23713
|
+
const displayName = author?.firstName || author?.lastName ? `${author?.firstName ?? ""} ${author?.lastName ?? ""}`.trim() : author?.username ?? "Unknown";
|
|
23714
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
23715
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: author?.avatar, size: "sm" }),
|
|
23716
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
23717
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
23718
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-semibold text-gray-900 dark:text-gray-100", children: displayName }),
|
|
23719
|
+
(reply.authorLabel || author?.role) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-blue-500/10 px-2 py-0.5 text-xs font-medium text-blue-500", children: reply.authorLabel ?? author?.role }),
|
|
23720
|
+
author?.username && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
|
|
23721
|
+
"@",
|
|
23722
|
+
author.username
|
|
23723
|
+
] })
|
|
23724
|
+
] }),
|
|
23725
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs text-gray-500 dark:text-gray-400", children: [
|
|
23726
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatReviewDate(reply.createdAt, config.dateFormat) }),
|
|
23727
|
+
reply.edited && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "(edited)" })
|
|
23728
|
+
] })
|
|
23729
|
+
] })
|
|
23730
|
+
] });
|
|
23731
|
+
}
|
|
23732
|
+
var ReviewReplyHeader_default = ReviewReplyHeader;
|
|
23733
|
+
function ReviewReplyContent({ reply }) {
|
|
23734
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-gray-700 dark:text-gray-300", children: reply.content });
|
|
23735
|
+
}
|
|
23736
|
+
var ReviewReplyContent_default = ReviewReplyContent;
|
|
23737
|
+
function ReviewReplyMenuItem({
|
|
23738
|
+
icon,
|
|
23739
|
+
name,
|
|
23740
|
+
badge,
|
|
23741
|
+
to,
|
|
23742
|
+
navigate,
|
|
23743
|
+
className,
|
|
23744
|
+
onClick,
|
|
23745
|
+
style
|
|
23746
|
+
}) {
|
|
23747
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23748
|
+
MenuItem,
|
|
23749
|
+
{
|
|
23750
|
+
icon,
|
|
23751
|
+
name,
|
|
23752
|
+
badge,
|
|
23753
|
+
to,
|
|
23754
|
+
navigate,
|
|
23755
|
+
onClick,
|
|
23756
|
+
style,
|
|
23757
|
+
className
|
|
23758
|
+
}
|
|
23759
|
+
);
|
|
23760
|
+
}
|
|
23761
|
+
function ReviewReplyMenu({
|
|
23762
|
+
open,
|
|
23763
|
+
setOpen,
|
|
23764
|
+
canEdit,
|
|
23765
|
+
canDelete,
|
|
23766
|
+
canReport,
|
|
23767
|
+
onEdit,
|
|
23768
|
+
onDelete,
|
|
23769
|
+
onReport
|
|
23770
|
+
}) {
|
|
23771
|
+
const ref = React2.useRef(null);
|
|
23772
|
+
useClickOutside(ref, () => setOpen(false));
|
|
23773
|
+
const items = [];
|
|
23774
|
+
if (canEdit) {
|
|
23775
|
+
items.push({
|
|
23776
|
+
type: "item",
|
|
23777
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiEdit, {}),
|
|
23778
|
+
name: "Edit Reply",
|
|
23779
|
+
component: ReviewReplyMenuItem,
|
|
23780
|
+
onClick: () => {
|
|
23781
|
+
setOpen(false);
|
|
23782
|
+
onEdit?.();
|
|
23783
|
+
},
|
|
23784
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23785
|
+
});
|
|
23786
|
+
}
|
|
23787
|
+
if (canDelete) {
|
|
23788
|
+
items.push({
|
|
23789
|
+
type: "item",
|
|
23790
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiTrash, {}),
|
|
23791
|
+
name: "Delete Reply",
|
|
23792
|
+
component: ReviewReplyMenuItem,
|
|
23793
|
+
onClick: () => {
|
|
23794
|
+
setOpen(false);
|
|
23795
|
+
onDelete?.();
|
|
23796
|
+
},
|
|
23797
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm text-red-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23798
|
+
});
|
|
23799
|
+
}
|
|
23800
|
+
if (canReport) {
|
|
23801
|
+
items.push({
|
|
23802
|
+
type: "item",
|
|
23803
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(bi.BiFlag, {}),
|
|
23804
|
+
name: "Report Reply",
|
|
23805
|
+
component: ReviewReplyMenuItem,
|
|
23806
|
+
onClick: () => {
|
|
23807
|
+
setOpen(false);
|
|
23808
|
+
onReport?.();
|
|
23809
|
+
},
|
|
23810
|
+
className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
|
|
23811
|
+
});
|
|
23812
|
+
}
|
|
23813
|
+
if (!items.length) {
|
|
23814
|
+
return null;
|
|
23815
|
+
}
|
|
23816
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: "relative", children: [
|
|
23817
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23818
|
+
"button",
|
|
23819
|
+
{
|
|
23820
|
+
type: "button",
|
|
23821
|
+
onClick: () => setOpen(!open),
|
|
23822
|
+
className: "text-gray-500 transition-colors hover:text-gray-900 dark:hover:text-gray-100",
|
|
23823
|
+
"aria-label": "Review reply options",
|
|
23824
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(bi.BiDotsVerticalRounded, { size: 18 })
|
|
23825
|
+
}
|
|
23826
|
+
),
|
|
23827
|
+
/* @__PURE__ */ jsxRuntime.jsx(Transition.TransitionDropdown, { visibility: open, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-full z-50 mt-2 min-w-[180px] overflow-hidden rounded-xl border border-gray-200 bg-white shadow-xl dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsx(Menu, { items }) }) })
|
|
23828
|
+
] });
|
|
23829
|
+
}
|
|
23830
|
+
var ReviewReplyMenu_default = ReviewReplyMenu;
|
|
23831
|
+
function ReviewReplyItem({
|
|
23832
|
+
reply,
|
|
23833
|
+
parentReview,
|
|
23834
|
+
config,
|
|
23835
|
+
components,
|
|
23836
|
+
onEditReviewReply,
|
|
23837
|
+
onDeleteReviewReply,
|
|
23838
|
+
onReportReviewReply
|
|
23839
|
+
}) {
|
|
23840
|
+
const [menuOpen, setMenuOpen] = React2.useState(false);
|
|
23841
|
+
const HeaderComponent = components?.ReplyHeader ?? ReviewReplyHeader_default;
|
|
23842
|
+
const ContentComponent = components?.ReplyContent ?? ReviewReplyContent_default;
|
|
23843
|
+
const MenuComponent = components?.ReplyMenu ?? ReviewReplyMenu_default;
|
|
23844
|
+
const canEdit = canEditReviewReply(reply);
|
|
23845
|
+
const canDelete = canDeleteReviewReply(reply);
|
|
23846
|
+
const canReport = canReportReviewReply(reply);
|
|
23847
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-gray-50 p-4 dark:border-neutral-800 dark:bg-neutral-950", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
23848
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
23849
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23850
|
+
HeaderComponent,
|
|
23851
|
+
{
|
|
23852
|
+
reply,
|
|
23853
|
+
parentReview,
|
|
23854
|
+
config
|
|
23855
|
+
}
|
|
23856
|
+
),
|
|
23857
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23858
|
+
MenuComponent,
|
|
23859
|
+
{
|
|
23860
|
+
reply,
|
|
23861
|
+
parentReview,
|
|
23862
|
+
open: menuOpen,
|
|
23863
|
+
setOpen: setMenuOpen,
|
|
23864
|
+
canEdit,
|
|
23865
|
+
canDelete,
|
|
23866
|
+
canReport,
|
|
23867
|
+
onEdit: () => onEditReviewReply?.(reply, parentReview),
|
|
23868
|
+
onDelete: () => onDeleteReviewReply?.(reply, parentReview),
|
|
23869
|
+
onReport: () => onReportReviewReply?.(reply, parentReview)
|
|
23870
|
+
}
|
|
23871
|
+
)
|
|
23872
|
+
] }),
|
|
23873
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentComponent, { reply, parentReview })
|
|
23874
|
+
] }) });
|
|
23875
|
+
}
|
|
23876
|
+
var ReviewReplyItem_default = ReviewReplyItem;
|
|
23877
|
+
function ReviewReplyList({
|
|
23878
|
+
review,
|
|
23879
|
+
replies,
|
|
23880
|
+
config,
|
|
23881
|
+
components,
|
|
23882
|
+
onEditReviewReply,
|
|
23883
|
+
onDeleteReviewReply,
|
|
23884
|
+
onReportReviewReply
|
|
23885
|
+
}) {
|
|
23886
|
+
const ReplyItemComponent = components?.ReplyItem ?? ReviewReplyItem_default;
|
|
23887
|
+
if (!config.allowReplies || !replies.length) {
|
|
23888
|
+
return null;
|
|
23889
|
+
}
|
|
23890
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-6 border-l border-gray-200 pl-4 dark:border-neutral-800", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-3", children: replies.map((reply) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23891
|
+
ReplyItemComponent,
|
|
23892
|
+
{
|
|
23893
|
+
reply,
|
|
23894
|
+
parentReview: review,
|
|
23895
|
+
config,
|
|
23896
|
+
components,
|
|
23897
|
+
onEditReviewReply,
|
|
23898
|
+
onDeleteReviewReply,
|
|
23899
|
+
onReportReviewReply
|
|
23900
|
+
},
|
|
23901
|
+
reply.id
|
|
23902
|
+
)) }) });
|
|
23903
|
+
}
|
|
23904
|
+
var ReviewReplyList_default = ReviewReplyList;
|
|
23905
|
+
function ReviewItem({
|
|
23906
|
+
review,
|
|
23907
|
+
config,
|
|
23908
|
+
components,
|
|
23909
|
+
onEditReview,
|
|
23910
|
+
onDeleteReview,
|
|
23911
|
+
onReportReview,
|
|
23912
|
+
onReplyToReview,
|
|
23913
|
+
onEditReviewReply,
|
|
23914
|
+
onDeleteReviewReply,
|
|
23915
|
+
onReportReviewReply
|
|
23916
|
+
}) {
|
|
23917
|
+
const [menuOpen, setMenuOpen] = React2.useState(false);
|
|
23918
|
+
const HeaderComponent = components?.Header ?? ReviewHeader_default;
|
|
23919
|
+
const ContentComponent = components?.Content ?? ReviewContent_default;
|
|
23920
|
+
const RatingComponent = components?.Rating ?? ReviewRating_default;
|
|
23921
|
+
const RecommendationComponent = components?.Recommendation ?? ReviewRecommendation_default;
|
|
23922
|
+
const MenuComponent = components?.Menu ?? ReviewMenu_default;
|
|
23923
|
+
const ActionsComponent = components?.Actions ?? ReviewActions_default;
|
|
23924
|
+
const ReplyListComponent = components?.ReplyList ?? ReviewReplyList_default;
|
|
23925
|
+
const replies = review.replies ?? [];
|
|
23926
|
+
const canEdit = canEditReview(review);
|
|
23927
|
+
const canDelete = canDeleteReview(review);
|
|
23928
|
+
const canReport = canReportReview(review);
|
|
23929
|
+
const canReply = config.allowReplies && canReplyToReview(review) && replies.length < config.maxRepliesPerReview;
|
|
23930
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
23931
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
23932
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderComponent, { review, config }),
|
|
23933
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23934
|
+
MenuComponent,
|
|
23935
|
+
{
|
|
23936
|
+
review,
|
|
23937
|
+
open: menuOpen,
|
|
23938
|
+
setOpen: setMenuOpen,
|
|
23939
|
+
canEdit,
|
|
23940
|
+
canDelete,
|
|
23941
|
+
canReport,
|
|
23942
|
+
canReply,
|
|
23943
|
+
onEdit: () => onEditReview?.(review),
|
|
23944
|
+
onDelete: () => onDeleteReview?.(review),
|
|
23945
|
+
onReport: () => onReportReview?.(review),
|
|
23946
|
+
onReply: () => onReplyToReview?.(review)
|
|
23947
|
+
}
|
|
23948
|
+
)
|
|
23949
|
+
] }),
|
|
23950
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentComponent, { review }),
|
|
23951
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
23952
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23953
|
+
RatingComponent,
|
|
23954
|
+
{
|
|
23955
|
+
rating: review.rating,
|
|
23956
|
+
maxRating: config.maxRating
|
|
23957
|
+
}
|
|
23958
|
+
),
|
|
23959
|
+
config.allowRecommendation && /* @__PURE__ */ jsxRuntime.jsx(RecommendationComponent, { isRecommended: review.isRecommended })
|
|
23960
|
+
] }),
|
|
23961
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23962
|
+
ActionsComponent,
|
|
23963
|
+
{
|
|
23964
|
+
review,
|
|
23965
|
+
canReply,
|
|
23966
|
+
onReply: () => onReplyToReview?.(review)
|
|
23967
|
+
}
|
|
23968
|
+
),
|
|
23969
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23970
|
+
ReplyListComponent,
|
|
23971
|
+
{
|
|
23972
|
+
review,
|
|
23973
|
+
replies,
|
|
23974
|
+
config,
|
|
23975
|
+
components,
|
|
23976
|
+
onEditReviewReply,
|
|
23977
|
+
onDeleteReviewReply,
|
|
23978
|
+
onReportReviewReply
|
|
23979
|
+
}
|
|
23980
|
+
)
|
|
23981
|
+
] }) });
|
|
23982
|
+
}
|
|
23983
|
+
var ReviewItem_default = ReviewItem;
|
|
23984
|
+
function ReviewEmptyState({
|
|
23985
|
+
title = "No reviews yet",
|
|
23986
|
+
text = "There are no reviews to show."
|
|
23987
|
+
}) {
|
|
23988
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-dashed border-gray-300 bg-white p-8 text-center dark:border-neutral-800 dark:bg-neutral-900", children: [
|
|
23989
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: title }),
|
|
23990
|
+
text && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: text })
|
|
23991
|
+
] });
|
|
23992
|
+
}
|
|
23993
|
+
var ReviewEmptyState_default = ReviewEmptyState;
|
|
23994
|
+
function ReviewList({
|
|
23995
|
+
reviews,
|
|
23996
|
+
config,
|
|
23997
|
+
components,
|
|
23998
|
+
onEditReview,
|
|
23999
|
+
onDeleteReview,
|
|
24000
|
+
onReportReview,
|
|
24001
|
+
onReplyToReview,
|
|
24002
|
+
onEditReviewReply,
|
|
24003
|
+
onDeleteReviewReply,
|
|
24004
|
+
onReportReviewReply
|
|
24005
|
+
}) {
|
|
24006
|
+
const ItemComponent = components?.Item ?? ReviewItem_default;
|
|
24007
|
+
const EmptyStateComponent = components?.EmptyState ?? ReviewEmptyState_default;
|
|
24008
|
+
if (!reviews.length) {
|
|
24009
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EmptyStateComponent, { title: config.emptyTitle, text: config.emptyText });
|
|
24010
|
+
}
|
|
24011
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-5", children: reviews.map((review) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
24012
|
+
ItemComponent,
|
|
24013
|
+
{
|
|
24014
|
+
review,
|
|
24015
|
+
config,
|
|
24016
|
+
components,
|
|
24017
|
+
onEditReview,
|
|
24018
|
+
onDeleteReview,
|
|
24019
|
+
onReportReview,
|
|
24020
|
+
onReplyToReview,
|
|
24021
|
+
onEditReviewReply,
|
|
24022
|
+
onDeleteReviewReply,
|
|
24023
|
+
onReportReviewReply
|
|
24024
|
+
},
|
|
24025
|
+
review.id
|
|
24026
|
+
)) });
|
|
24027
|
+
}
|
|
24028
|
+
var ReviewList_default = ReviewList;
|
|
24029
|
+
|
|
24030
|
+
// src/compositions/review-thread/constants/review-thread.constants.ts
|
|
24031
|
+
var DEFAULT_REVIEW_THREAD_CONFIG = {
|
|
24032
|
+
reviewsPerPage: 10,
|
|
24033
|
+
dateFormat: "relative",
|
|
24034
|
+
minRating: 1,
|
|
24035
|
+
maxRating: 5,
|
|
24036
|
+
minContentLength: 8,
|
|
24037
|
+
maxContentLength: 2e3,
|
|
24038
|
+
allowRecommendation: true,
|
|
24039
|
+
showMyReviewPanel: true,
|
|
24040
|
+
showMyReviewInList: true,
|
|
24041
|
+
allowReplies: true,
|
|
24042
|
+
maxRepliesPerReview: 1,
|
|
24043
|
+
ownerReplyLabel: "Owner",
|
|
24044
|
+
emptyTitle: "No reviews yet",
|
|
24045
|
+
emptyText: "There are no reviews to show."
|
|
24046
|
+
};
|
|
24047
|
+
function isReviewEntity(value) {
|
|
24048
|
+
return Boolean(value && "rating" in value);
|
|
24049
|
+
}
|
|
24050
|
+
function updateReviewEverywhere(review, updater) {
|
|
24051
|
+
return updater(review);
|
|
24052
|
+
}
|
|
24053
|
+
function useReviewThreadState({
|
|
24054
|
+
targetId,
|
|
24055
|
+
dataSource,
|
|
24056
|
+
config,
|
|
24057
|
+
shouldLoadMyReview = true,
|
|
24058
|
+
loading = false,
|
|
24059
|
+
updatedReview,
|
|
24060
|
+
deletedReview,
|
|
24061
|
+
updatedReviewReply,
|
|
24062
|
+
deletedReviewReply,
|
|
24063
|
+
onReviewCreated,
|
|
24064
|
+
onReviewUpdated,
|
|
24065
|
+
onReviewDeleted
|
|
24066
|
+
}) {
|
|
24067
|
+
const [reviews, setReviews] = React2.useState([]);
|
|
24068
|
+
const [myReview, setMyReview] = React2.useState(null);
|
|
24069
|
+
const [isLoadingReviews, setIsLoadingReviews] = React2.useState(true);
|
|
24070
|
+
const [isLoadingMyReview, setIsLoadingMyReview] = React2.useState(
|
|
24071
|
+
Boolean(dataSource.getMyReview && shouldLoadMyReview)
|
|
24072
|
+
);
|
|
24073
|
+
const [isCreatingReview, setIsCreatingReview] = React2.useState(false);
|
|
24074
|
+
const [isUpdatingReview, setIsUpdatingReview] = React2.useState(false);
|
|
24075
|
+
const [isDeletingReview, setIsDeletingReview] = React2.useState(false);
|
|
24076
|
+
const [isCreatingReviewReply, setIsCreatingReviewReply] = React2.useState(false);
|
|
24077
|
+
const [isUpdatingReviewReply, setIsUpdatingReviewReply] = React2.useState(false);
|
|
24078
|
+
const [isDeletingReviewReply, setIsDeletingReviewReply] = React2.useState(false);
|
|
24079
|
+
const [reviewsError, setReviewsError] = React2.useState(null);
|
|
24080
|
+
const [myReviewError, setMyReviewError] = React2.useState(null);
|
|
24081
|
+
const error = reviewsError ?? myReviewError;
|
|
24082
|
+
const visibleReviews = React2.useMemo(() => {
|
|
24083
|
+
if (config.showMyReviewInList || !myReview) {
|
|
24084
|
+
return reviews;
|
|
24085
|
+
}
|
|
24086
|
+
return reviews.filter((review) => review.id !== myReview.id);
|
|
24087
|
+
}, [config.showMyReviewInList, myReview, reviews]);
|
|
24088
|
+
const applyReview = React2.useCallback((review) => {
|
|
24089
|
+
setReviews((prev) => upsertReview(prev, review));
|
|
24090
|
+
setMyReview((prev) => {
|
|
24091
|
+
if (!prev || prev.id !== review.id) {
|
|
24092
|
+
return prev;
|
|
24093
|
+
}
|
|
24094
|
+
return review;
|
|
24095
|
+
});
|
|
24096
|
+
}, []);
|
|
24097
|
+
const applyReviewUpdater = React2.useCallback(
|
|
24098
|
+
(reviewId, updater) => {
|
|
24099
|
+
setReviews((prev) => updateReview(prev, reviewId, updater));
|
|
24100
|
+
setMyReview((prev) => {
|
|
24101
|
+
if (!prev || prev.id !== reviewId) {
|
|
24102
|
+
return prev;
|
|
24103
|
+
}
|
|
24104
|
+
return updateReviewEverywhere(prev, updater);
|
|
24105
|
+
});
|
|
24106
|
+
},
|
|
24107
|
+
[]
|
|
24108
|
+
);
|
|
24109
|
+
const removeReviewById = React2.useCallback((reviewId) => {
|
|
24110
|
+
setReviews((prev) => removeReview(prev, reviewId));
|
|
24111
|
+
setMyReview((prev) => {
|
|
24112
|
+
if (!prev || prev.id !== reviewId) {
|
|
24113
|
+
return prev;
|
|
24114
|
+
}
|
|
24115
|
+
return null;
|
|
24116
|
+
});
|
|
24117
|
+
}, []);
|
|
24118
|
+
const loadReviews = React2.useCallback(async () => {
|
|
24119
|
+
try {
|
|
24120
|
+
setIsLoadingReviews(true);
|
|
24121
|
+
setReviewsError(null);
|
|
24122
|
+
const result = await dataSource.getReviews({
|
|
24123
|
+
limit: config.reviewsPerPage
|
|
24124
|
+
});
|
|
24125
|
+
setReviews(result.items);
|
|
24126
|
+
} catch (error2) {
|
|
24127
|
+
setReviewsError(error2);
|
|
24128
|
+
} finally {
|
|
24129
|
+
setIsLoadingReviews(false);
|
|
24130
|
+
}
|
|
24131
|
+
}, [config.reviewsPerPage, dataSource, targetId]);
|
|
24132
|
+
const loadMyReview = React2.useCallback(async () => {
|
|
24133
|
+
if (!dataSource.getMyReview || !shouldLoadMyReview) {
|
|
24134
|
+
setMyReview(null);
|
|
24135
|
+
setIsLoadingMyReview(false);
|
|
24136
|
+
setMyReviewError(null);
|
|
24137
|
+
return;
|
|
24138
|
+
}
|
|
24139
|
+
try {
|
|
24140
|
+
setIsLoadingMyReview(true);
|
|
24141
|
+
setMyReviewError(null);
|
|
24142
|
+
const result = await dataSource.getMyReview();
|
|
24143
|
+
setMyReview(result);
|
|
24144
|
+
} catch (error2) {
|
|
24145
|
+
setMyReview(null);
|
|
24146
|
+
setMyReviewError(error2);
|
|
24147
|
+
} finally {
|
|
24148
|
+
setIsLoadingMyReview(false);
|
|
24149
|
+
}
|
|
24150
|
+
}, [dataSource, shouldLoadMyReview, targetId]);
|
|
24151
|
+
const reload = React2.useCallback(async () => {
|
|
24152
|
+
await Promise.all([loadReviews(), loadMyReview()]);
|
|
24153
|
+
}, [loadReviews, loadMyReview]);
|
|
24154
|
+
const createReview = React2.useCallback(
|
|
24155
|
+
async (values) => {
|
|
24156
|
+
try {
|
|
24157
|
+
setIsCreatingReview(true);
|
|
24158
|
+
const review = await dataSource.createReview({
|
|
24159
|
+
content: values.content,
|
|
24160
|
+
rating: values.rating,
|
|
24161
|
+
isRecommended: values.isRecommended
|
|
24162
|
+
});
|
|
24163
|
+
setMyReview(review);
|
|
24164
|
+
setReviews((prev) => prependReview(prev, review));
|
|
24165
|
+
onReviewCreated?.(review);
|
|
24166
|
+
return review;
|
|
24167
|
+
} finally {
|
|
24168
|
+
setIsCreatingReview(false);
|
|
24169
|
+
}
|
|
24170
|
+
},
|
|
24171
|
+
[dataSource, onReviewCreated]
|
|
24172
|
+
);
|
|
24173
|
+
const updateReview2 = React2.useCallback(
|
|
24174
|
+
async (review, values) => {
|
|
24175
|
+
try {
|
|
24176
|
+
setIsUpdatingReview(true);
|
|
24177
|
+
const updated = await dataSource.updateReview({
|
|
24178
|
+
id: review.id,
|
|
24179
|
+
content: values.content,
|
|
24180
|
+
rating: values.rating,
|
|
24181
|
+
isRecommended: values.isRecommended
|
|
24182
|
+
});
|
|
24183
|
+
setMyReview((prev) => {
|
|
24184
|
+
if (!prev || prev.id !== updated.id) {
|
|
24185
|
+
return prev;
|
|
24186
|
+
}
|
|
24187
|
+
return updated;
|
|
24188
|
+
});
|
|
24189
|
+
setReviews((prev) => upsertReview(prev, updated));
|
|
24190
|
+
onReviewUpdated?.(updated);
|
|
24191
|
+
return updated;
|
|
24192
|
+
} finally {
|
|
24193
|
+
setIsUpdatingReview(false);
|
|
24194
|
+
}
|
|
24195
|
+
},
|
|
24196
|
+
[dataSource, onReviewUpdated]
|
|
24197
|
+
);
|
|
24198
|
+
const deleteReview = React2.useCallback(
|
|
24199
|
+
async (review) => {
|
|
24200
|
+
try {
|
|
24201
|
+
setIsDeletingReview(true);
|
|
24202
|
+
await dataSource.deleteReview(review.id);
|
|
24203
|
+
removeReviewById(review.id);
|
|
24204
|
+
onReviewDeleted?.(review);
|
|
24205
|
+
} finally {
|
|
24206
|
+
setIsDeletingReview(false);
|
|
24207
|
+
}
|
|
24208
|
+
},
|
|
24209
|
+
[dataSource, onReviewDeleted, removeReviewById]
|
|
24210
|
+
);
|
|
24211
|
+
const createReviewReply = React2.useCallback(
|
|
24212
|
+
async (input) => {
|
|
24213
|
+
if (!dataSource.createReviewReply) {
|
|
24214
|
+
throw new Error("createReviewReply is not implemented by dataSource.");
|
|
24215
|
+
}
|
|
24216
|
+
try {
|
|
24217
|
+
setIsCreatingReviewReply(true);
|
|
24218
|
+
const result = await dataSource.createReviewReply(input);
|
|
24219
|
+
if (isReviewEntity(result)) {
|
|
24220
|
+
applyReview(result);
|
|
24221
|
+
} else {
|
|
24222
|
+
applyReviewUpdater(
|
|
24223
|
+
input.reviewId,
|
|
24224
|
+
(review) => addReviewReply(review, result, config.maxRepliesPerReview)
|
|
24225
|
+
);
|
|
24226
|
+
}
|
|
24227
|
+
return result;
|
|
24228
|
+
} finally {
|
|
24229
|
+
setIsCreatingReviewReply(false);
|
|
24230
|
+
}
|
|
24231
|
+
},
|
|
24232
|
+
[applyReview, applyReviewUpdater, config.maxRepliesPerReview, dataSource]
|
|
24233
|
+
);
|
|
24234
|
+
const updateReviewReply2 = React2.useCallback(
|
|
24235
|
+
async (input) => {
|
|
24236
|
+
if (!dataSource.updateReviewReply) {
|
|
24237
|
+
throw new Error("updateReviewReply is not implemented by dataSource.");
|
|
24238
|
+
}
|
|
24239
|
+
try {
|
|
24240
|
+
setIsUpdatingReviewReply(true);
|
|
24241
|
+
const result = await dataSource.updateReviewReply(input);
|
|
24242
|
+
if (isReviewEntity(result)) {
|
|
24243
|
+
applyReview(result);
|
|
24244
|
+
} else {
|
|
24245
|
+
applyReviewUpdater(
|
|
24246
|
+
input.reviewId,
|
|
24247
|
+
(review) => replaceReviewReply(review, result)
|
|
24248
|
+
);
|
|
24249
|
+
}
|
|
24250
|
+
return result;
|
|
24251
|
+
} finally {
|
|
24252
|
+
setIsUpdatingReviewReply(false);
|
|
24253
|
+
}
|
|
24254
|
+
},
|
|
24255
|
+
[applyReview, applyReviewUpdater, dataSource]
|
|
24256
|
+
);
|
|
24257
|
+
const deleteReviewReply = React2.useCallback(
|
|
24258
|
+
async (reviewId, replyId) => {
|
|
24259
|
+
if (!dataSource.deleteReviewReply) {
|
|
24260
|
+
throw new Error("deleteReviewReply is not implemented by dataSource.");
|
|
24261
|
+
}
|
|
24262
|
+
try {
|
|
24263
|
+
setIsDeletingReviewReply(true);
|
|
24264
|
+
const result = await dataSource.deleteReviewReply(reviewId, replyId);
|
|
24265
|
+
if (isReviewEntity(result)) {
|
|
24266
|
+
applyReview(result);
|
|
24267
|
+
} else {
|
|
24268
|
+
applyReviewUpdater(
|
|
24269
|
+
reviewId,
|
|
24270
|
+
(review) => removeReviewReply(review, replyId)
|
|
24271
|
+
);
|
|
24272
|
+
}
|
|
24273
|
+
return result;
|
|
24274
|
+
} finally {
|
|
24275
|
+
setIsDeletingReviewReply(false);
|
|
24276
|
+
}
|
|
24277
|
+
},
|
|
24278
|
+
[applyReview, applyReviewUpdater, dataSource]
|
|
24279
|
+
);
|
|
24280
|
+
React2.useEffect(() => {
|
|
24281
|
+
let cancelled = false;
|
|
24282
|
+
async function run() {
|
|
24283
|
+
try {
|
|
24284
|
+
setIsLoadingReviews(true);
|
|
24285
|
+
setReviewsError(null);
|
|
24286
|
+
const result = await dataSource.getReviews({
|
|
24287
|
+
limit: config.reviewsPerPage
|
|
24288
|
+
});
|
|
24289
|
+
if (!cancelled) {
|
|
24290
|
+
setReviews(result.items);
|
|
24291
|
+
}
|
|
24292
|
+
} catch (error2) {
|
|
24293
|
+
if (!cancelled) {
|
|
24294
|
+
setReviewsError(error2);
|
|
24295
|
+
}
|
|
24296
|
+
} finally {
|
|
24297
|
+
if (!cancelled) {
|
|
24298
|
+
setIsLoadingReviews(false);
|
|
24299
|
+
}
|
|
24300
|
+
}
|
|
24301
|
+
}
|
|
24302
|
+
void run();
|
|
24303
|
+
return () => {
|
|
24304
|
+
cancelled = true;
|
|
24305
|
+
};
|
|
24306
|
+
}, [config.reviewsPerPage, dataSource, targetId]);
|
|
24307
|
+
React2.useEffect(() => {
|
|
24308
|
+
let cancelled = false;
|
|
24309
|
+
async function run() {
|
|
24310
|
+
if (!dataSource.getMyReview || !shouldLoadMyReview) {
|
|
24311
|
+
setMyReview(null);
|
|
24312
|
+
setMyReviewError(null);
|
|
24313
|
+
setIsLoadingMyReview(false);
|
|
24314
|
+
return;
|
|
24315
|
+
}
|
|
24316
|
+
try {
|
|
24317
|
+
setIsLoadingMyReview(true);
|
|
24318
|
+
setMyReviewError(null);
|
|
24319
|
+
const result = await dataSource.getMyReview();
|
|
24320
|
+
if (!cancelled) {
|
|
24321
|
+
setMyReview(result);
|
|
24322
|
+
}
|
|
24323
|
+
} catch (error2) {
|
|
24324
|
+
if (!cancelled) {
|
|
24325
|
+
setMyReview(null);
|
|
24326
|
+
setMyReviewError(error2);
|
|
24327
|
+
}
|
|
24328
|
+
} finally {
|
|
24329
|
+
if (!cancelled) {
|
|
24330
|
+
setIsLoadingMyReview(false);
|
|
24331
|
+
}
|
|
24332
|
+
}
|
|
24333
|
+
}
|
|
24334
|
+
void run();
|
|
24335
|
+
return () => {
|
|
24336
|
+
cancelled = true;
|
|
24337
|
+
};
|
|
24338
|
+
}, [dataSource, shouldLoadMyReview, targetId]);
|
|
24339
|
+
React2.useEffect(() => {
|
|
24340
|
+
if (!updatedReview) {
|
|
24341
|
+
return;
|
|
24342
|
+
}
|
|
24343
|
+
applyReview(updatedReview);
|
|
24344
|
+
}, [applyReview, updatedReview]);
|
|
24345
|
+
React2.useEffect(() => {
|
|
24346
|
+
if (!deletedReview) {
|
|
24347
|
+
return;
|
|
24348
|
+
}
|
|
24349
|
+
removeReviewById(deletedReview.id);
|
|
24350
|
+
}, [deletedReview, removeReviewById]);
|
|
24351
|
+
React2.useEffect(() => {
|
|
24352
|
+
if (!updatedReviewReply) {
|
|
24353
|
+
return;
|
|
24354
|
+
}
|
|
24355
|
+
if (updatedReviewReply.review) {
|
|
24356
|
+
applyReview(updatedReviewReply.review);
|
|
24357
|
+
return;
|
|
24358
|
+
}
|
|
24359
|
+
if (!updatedReviewReply.reply) {
|
|
24360
|
+
return;
|
|
24361
|
+
}
|
|
24362
|
+
applyReviewUpdater(updatedReviewReply.reviewId, (review) => {
|
|
24363
|
+
if (hasReviewReply(review, updatedReviewReply.reply.id)) {
|
|
24364
|
+
return replaceReviewReply(review, updatedReviewReply.reply);
|
|
24365
|
+
}
|
|
24366
|
+
return addReviewReply(
|
|
24367
|
+
review,
|
|
24368
|
+
updatedReviewReply.reply,
|
|
24369
|
+
config.maxRepliesPerReview
|
|
24370
|
+
);
|
|
24371
|
+
});
|
|
24372
|
+
}, [
|
|
24373
|
+
applyReview,
|
|
24374
|
+
applyReviewUpdater,
|
|
24375
|
+
config.maxRepliesPerReview,
|
|
24376
|
+
updatedReviewReply
|
|
24377
|
+
]);
|
|
24378
|
+
React2.useEffect(() => {
|
|
24379
|
+
if (!deletedReviewReply) {
|
|
24380
|
+
return;
|
|
24381
|
+
}
|
|
24382
|
+
if (deletedReviewReply.review) {
|
|
24383
|
+
applyReview(deletedReviewReply.review);
|
|
24384
|
+
return;
|
|
24385
|
+
}
|
|
24386
|
+
applyReviewUpdater(
|
|
24387
|
+
deletedReviewReply.reviewId,
|
|
24388
|
+
(review) => removeReviewReply(review, deletedReviewReply.replyId)
|
|
24389
|
+
);
|
|
24390
|
+
}, [applyReview, applyReviewUpdater, deletedReviewReply]);
|
|
24391
|
+
return {
|
|
24392
|
+
reviews,
|
|
24393
|
+
visibleReviews,
|
|
24394
|
+
myReview,
|
|
24395
|
+
isLoadingReviews,
|
|
24396
|
+
isLoadingMyReview,
|
|
24397
|
+
isInitialLoading: loading || isLoadingReviews || isLoadingMyReview,
|
|
24398
|
+
isCreatingReview,
|
|
24399
|
+
isUpdatingReview,
|
|
24400
|
+
isDeletingReview,
|
|
24401
|
+
isCreatingReviewReply,
|
|
24402
|
+
isUpdatingReviewReply,
|
|
24403
|
+
isDeletingReviewReply,
|
|
24404
|
+
reviewsError,
|
|
24405
|
+
myReviewError,
|
|
24406
|
+
error,
|
|
24407
|
+
setReviews,
|
|
24408
|
+
setMyReview,
|
|
24409
|
+
loadReviews,
|
|
24410
|
+
loadMyReview,
|
|
24411
|
+
reload,
|
|
24412
|
+
createReview,
|
|
24413
|
+
updateReview: updateReview2,
|
|
24414
|
+
deleteReview,
|
|
24415
|
+
createReviewReply,
|
|
24416
|
+
updateReviewReply: updateReviewReply2,
|
|
24417
|
+
deleteReviewReply,
|
|
24418
|
+
applyReview,
|
|
24419
|
+
removeReviewById
|
|
24420
|
+
};
|
|
24421
|
+
}
|
|
24422
|
+
function ReviewThread({
|
|
24423
|
+
targetId,
|
|
24424
|
+
currentUser,
|
|
24425
|
+
dataSource,
|
|
24426
|
+
loading = false,
|
|
24427
|
+
disabled = false,
|
|
24428
|
+
config,
|
|
24429
|
+
components,
|
|
24430
|
+
updatedReview,
|
|
24431
|
+
deletedReview,
|
|
24432
|
+
updatedReviewReply,
|
|
24433
|
+
deletedReviewReply,
|
|
24434
|
+
onLoginClick,
|
|
24435
|
+
onEditReview,
|
|
24436
|
+
onDeleteReview,
|
|
24437
|
+
onReportReview,
|
|
24438
|
+
onReplyToReview,
|
|
24439
|
+
onEditReviewReply,
|
|
24440
|
+
onDeleteReviewReply,
|
|
24441
|
+
onReportReviewReply,
|
|
24442
|
+
onReviewCreated,
|
|
24443
|
+
onReviewUpdated,
|
|
24444
|
+
onReviewDeleted
|
|
24445
|
+
}) {
|
|
24446
|
+
const resolvedConfig = {
|
|
24447
|
+
...DEFAULT_REVIEW_THREAD_CONFIG,
|
|
24448
|
+
...config
|
|
24449
|
+
};
|
|
24450
|
+
const reviewState = useReviewThreadState({
|
|
24451
|
+
targetId,
|
|
24452
|
+
dataSource,
|
|
24453
|
+
config: resolvedConfig,
|
|
24454
|
+
shouldLoadMyReview: Boolean(currentUser),
|
|
24455
|
+
loading,
|
|
24456
|
+
updatedReview,
|
|
24457
|
+
deletedReview,
|
|
24458
|
+
updatedReviewReply,
|
|
24459
|
+
deletedReviewReply,
|
|
24460
|
+
onReviewCreated,
|
|
24461
|
+
onReviewUpdated,
|
|
24462
|
+
onReviewDeleted
|
|
24463
|
+
});
|
|
24464
|
+
function handleEditReview(review) {
|
|
24465
|
+
onEditReview?.(review);
|
|
24466
|
+
}
|
|
24467
|
+
function handleDeleteReview(review) {
|
|
24468
|
+
if (onDeleteReview) {
|
|
24469
|
+
onDeleteReview(review);
|
|
24470
|
+
return;
|
|
24471
|
+
}
|
|
24472
|
+
void reviewState.deleteReview(review);
|
|
24473
|
+
}
|
|
24474
|
+
function handleReportReview(review) {
|
|
24475
|
+
onReportReview?.(review);
|
|
24476
|
+
}
|
|
24477
|
+
function handleReplyToReview(review) {
|
|
24478
|
+
onReplyToReview?.(review);
|
|
24479
|
+
}
|
|
24480
|
+
function handleEditReviewReply(reply, parentReview) {
|
|
24481
|
+
onEditReviewReply?.(reply, parentReview);
|
|
24482
|
+
}
|
|
24483
|
+
function handleDeleteReviewReply(reply, parentReview) {
|
|
24484
|
+
onDeleteReviewReply?.(reply, parentReview);
|
|
24485
|
+
}
|
|
24486
|
+
function handleReportReviewReply(reply, parentReview) {
|
|
24487
|
+
onReportReviewReply?.(reply, parentReview);
|
|
24488
|
+
}
|
|
24489
|
+
if (reviewState.isInitialLoading) {
|
|
24490
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
24491
|
+
resolvedConfig.showMyReviewPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-40 animate-pulse rounded-xl bg-gray-100 dark:bg-neutral-900" }),
|
|
24492
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-36 animate-pulse rounded-xl bg-gray-100 dark:bg-neutral-900" }),
|
|
24493
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-36 animate-pulse rounded-xl bg-gray-100 dark:bg-neutral-900" })
|
|
24494
|
+
] });
|
|
24495
|
+
}
|
|
24496
|
+
if (reviewState.error && !reviewState.reviews.length) {
|
|
24497
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-red-200 bg-red-50 p-5 dark:border-red-500/20 dark:bg-red-500/10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
24498
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
24499
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-red-700 dark:text-red-400", children: "Failed to load reviews" }),
|
|
24500
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-red-600/80 dark:text-red-300/80", children: "Something went wrong while loading the review thread." })
|
|
24501
|
+
] }),
|
|
24502
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
24503
|
+
Button_default,
|
|
24504
|
+
{
|
|
24505
|
+
text: "Retry",
|
|
24506
|
+
variant: "danger",
|
|
24507
|
+
appearance: "ghost",
|
|
24508
|
+
onClick: () => {
|
|
24509
|
+
void reviewState.reload();
|
|
24510
|
+
}
|
|
24511
|
+
}
|
|
24512
|
+
) })
|
|
24513
|
+
] }) });
|
|
24514
|
+
}
|
|
24515
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-8", children: [
|
|
24516
|
+
resolvedConfig.showMyReviewPanel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
24517
|
+
MyReviewPanel_default,
|
|
24518
|
+
{
|
|
24519
|
+
currentUser,
|
|
24520
|
+
myReview: reviewState.myReview,
|
|
24521
|
+
loading: reviewState.isCreatingReview || reviewState.isUpdatingReview || reviewState.isDeletingReview,
|
|
24522
|
+
disabled,
|
|
24523
|
+
config: resolvedConfig,
|
|
24524
|
+
components,
|
|
24525
|
+
onLoginClick,
|
|
24526
|
+
onCreateReview: reviewState.createReview,
|
|
24527
|
+
onUpdateReview: reviewState.updateReview,
|
|
24528
|
+
onEditReview: handleEditReview,
|
|
24529
|
+
onDeleteReview: handleDeleteReview
|
|
24530
|
+
}
|
|
24531
|
+
),
|
|
24532
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
24533
|
+
ReviewList_default,
|
|
24534
|
+
{
|
|
24535
|
+
reviews: reviewState.visibleReviews,
|
|
24536
|
+
config: resolvedConfig,
|
|
24537
|
+
components,
|
|
24538
|
+
onEditReview: handleEditReview,
|
|
24539
|
+
onDeleteReview: handleDeleteReview,
|
|
24540
|
+
onReportReview: handleReportReview,
|
|
24541
|
+
onReplyToReview: handleReplyToReview,
|
|
24542
|
+
onEditReviewReply: handleEditReviewReply,
|
|
24543
|
+
onDeleteReviewReply: handleDeleteReviewReply,
|
|
24544
|
+
onReportReviewReply: handleReportReviewReply
|
|
24545
|
+
}
|
|
24546
|
+
)
|
|
24547
|
+
] });
|
|
24548
|
+
}
|
|
24549
|
+
var ReviewThread_default = ReviewThread;
|
|
22979
24550
|
function GenericLayout({
|
|
22980
24551
|
children,
|
|
22981
24552
|
styles,
|
|
@@ -23158,6 +24729,7 @@ exports.ConfiguratorError = ConfiguratorError;
|
|
|
23158
24729
|
exports.Content = Content;
|
|
23159
24730
|
exports.ContentArea = ContentArea_default;
|
|
23160
24731
|
exports.DEFAULT_CHART_THEME = DEFAULT_CHART_THEME;
|
|
24732
|
+
exports.DEFAULT_REVIEW_THREAD_CONFIG = DEFAULT_REVIEW_THREAD_CONFIG;
|
|
23161
24733
|
exports.DataView = DataView;
|
|
23162
24734
|
exports.DataViewTable = DataViewTable_default;
|
|
23163
24735
|
exports.DateSelector = DateSelector_default;
|
|
@@ -23235,6 +24807,7 @@ exports.ProgressBarRating = ProgressBarRating_default;
|
|
|
23235
24807
|
exports.Quote = Quote;
|
|
23236
24808
|
exports.Radio = Radio_default;
|
|
23237
24809
|
exports.RealtimeChartDataSource = RealtimeChartDataSource;
|
|
24810
|
+
exports.ReviewThread = ReviewThread_default;
|
|
23238
24811
|
exports.RouteTab = RouteTab_default;
|
|
23239
24812
|
exports.RouteTabs = RouteTabs_default;
|
|
23240
24813
|
exports.ScatterPlot = ScatterPlot;
|
|
@@ -23285,9 +24858,18 @@ exports.WorldMap = WorldMap;
|
|
|
23285
24858
|
exports.WorldMapCountryTable = WorldMapCountryTable;
|
|
23286
24859
|
exports.YoutubeVideoPlayer = YoutubeVideo_default;
|
|
23287
24860
|
exports.addReplyToCache = addReplyToCache;
|
|
24861
|
+
exports.addReviewReply = addReviewReply;
|
|
24862
|
+
exports.appendReview = appendReview;
|
|
23288
24863
|
exports.applyReactionState = applyReactionState;
|
|
23289
24864
|
exports.assertAbsoluteURL = assertAbsoluteURL;
|
|
23290
24865
|
exports.buildURL = buildURL;
|
|
24866
|
+
exports.canDeleteReview = canDeleteReview;
|
|
24867
|
+
exports.canDeleteReviewReply = canDeleteReviewReply;
|
|
24868
|
+
exports.canEditReview = canEditReview;
|
|
24869
|
+
exports.canEditReviewReply = canEditReviewReply;
|
|
24870
|
+
exports.canReplyToReview = canReplyToReview;
|
|
24871
|
+
exports.canReportReview = canReportReview;
|
|
24872
|
+
exports.canReportReviewReply = canReportReviewReply;
|
|
23291
24873
|
exports.chartReducer = chartReducer;
|
|
23292
24874
|
exports.cn = cn;
|
|
23293
24875
|
exports.createConfigurator = createConfigurator;
|
|
@@ -23299,9 +24881,11 @@ exports.createURLResolver = createURLResolver;
|
|
|
23299
24881
|
exports.decrementReplyCount = decrementReplyCount;
|
|
23300
24882
|
exports.enumValues = enumValues;
|
|
23301
24883
|
exports.euiToast = euiToast;
|
|
24884
|
+
exports.findReview = findReview;
|
|
23302
24885
|
exports.formatChartValue = formatChartValue;
|
|
23303
24886
|
exports.formatCommentDate = formatCommentDate;
|
|
23304
24887
|
exports.formatConfigError = formatConfigError;
|
|
24888
|
+
exports.formatReviewDate = formatReviewDate;
|
|
23305
24889
|
exports.getAllowedOrigins = getAllowedOrigins;
|
|
23306
24890
|
exports.getBrowserHref = getBrowserHref;
|
|
23307
24891
|
exports.getBrowserOrigin = getBrowserOrigin;
|
|
@@ -23311,6 +24895,7 @@ exports.getLayout = getLayout;
|
|
|
23311
24895
|
exports.getOptimisticDislikeState = getOptimisticDislikeState;
|
|
23312
24896
|
exports.getOptimisticLikeState = getOptimisticLikeState;
|
|
23313
24897
|
exports.getSafeRedirect = getSafeRedirect;
|
|
24898
|
+
exports.hasReviewReply = hasReviewReply;
|
|
23314
24899
|
exports.incrementReplyCount = incrementReplyCount;
|
|
23315
24900
|
exports.isMatch = isMatch;
|
|
23316
24901
|
exports.isRenderFn = isRenderFn;
|
|
@@ -23318,13 +24903,21 @@ exports.limitRealtimePoints = limitRealtimePoints;
|
|
|
23318
24903
|
exports.normalize = normalize;
|
|
23319
24904
|
exports.normalizeChartData = normalizeChartData;
|
|
23320
24905
|
exports.normalizeChartDataPoint = normalizeChartDataPoint;
|
|
24906
|
+
exports.normalizeReview = normalizeReview;
|
|
24907
|
+
exports.normalizeReviewAuthor = normalizeReviewAuthor;
|
|
24908
|
+
exports.normalizeReviewReply = normalizeReviewReply;
|
|
23321
24909
|
exports.parseJson = parseJson;
|
|
23322
24910
|
exports.parseJsonRecord = parseJsonRecord;
|
|
23323
24911
|
exports.parseUrlMap = parseUrlMap;
|
|
24912
|
+
exports.prependReview = prependReview;
|
|
23324
24913
|
exports.registerLayout = registerLayout;
|
|
23325
24914
|
exports.removeComment = removeComment;
|
|
23326
24915
|
exports.removeCommentTreeFromCache = removeCommentTreeFromCache;
|
|
24916
|
+
exports.removeReview = removeReview;
|
|
24917
|
+
exports.removeReviewReply = removeReviewReply;
|
|
23327
24918
|
exports.replaceRealtimePoints = replaceRealtimePoints;
|
|
24919
|
+
exports.replaceReview = replaceReview;
|
|
24920
|
+
exports.replaceReviewReply = replaceReviewReply;
|
|
23328
24921
|
exports.resolveAppearanceStyles = resolveAppearanceStyles;
|
|
23329
24922
|
exports.resolveChartColor = resolveChartColor;
|
|
23330
24923
|
exports.resolveChartColors = resolveChartColors;
|
|
@@ -23333,6 +24926,9 @@ exports.sendToast = sendToast;
|
|
|
23333
24926
|
exports.toConfiguratorError = toConfiguratorError;
|
|
23334
24927
|
exports.updateComment = updateComment;
|
|
23335
24928
|
exports.updateReplyCacheComment = updateReplyCacheComment;
|
|
24929
|
+
exports.updateReview = updateReview;
|
|
24930
|
+
exports.updateReviewReply = updateReviewReply;
|
|
24931
|
+
exports.upsertReview = upsertReview;
|
|
23336
24932
|
exports.useChartContext = useChartContext;
|
|
23337
24933
|
exports.useChartData = useChartData;
|
|
23338
24934
|
exports.useChartPolling = useChartPolling;
|
|
@@ -23346,6 +24942,7 @@ exports.useDrawer = useDrawer_default;
|
|
|
23346
24942
|
exports.useEUIConfig = useEUIConfig;
|
|
23347
24943
|
exports.useIsMobile = useIsMobile_default;
|
|
23348
24944
|
exports.useModal = useModal_default;
|
|
24945
|
+
exports.useReviewThreadState = useReviewThreadState;
|
|
23349
24946
|
exports.useTheme = useTheme_default;
|
|
23350
24947
|
//# sourceMappingURL=index.js.map
|
|
23351
24948
|
//# sourceMappingURL=index.js.map
|