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