elseware-ui 2.31.4 → 2.31.6

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.mjs CHANGED
@@ -22,7 +22,7 @@ import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
22
22
  import { MdUpload, MdOutlineDone, MdOutlineRemoveCircleOutline } from 'react-icons/md';
23
23
  import '@mdxeditor/editor/style.css';
24
24
  import { MDXEditor, headingsPlugin, linkPlugin, listsPlugin, imagePlugin, tablePlugin, linkDialogPlugin, thematicBreakPlugin, quotePlugin, toolbarPlugin, UndoRedo, Separator, BlockTypeSelect, BoldItalicUnderlineToggles, StrikeThroughSupSubToggles, ListsToggle, CreateLink, InsertImage, InsertTable, InsertThematicBreak, markdownShortcutPlugin, frontmatterPlugin, codeBlockPlugin, codeMirrorPlugin } from '@mdxeditor/editor';
25
- import { BiDotsVerticalRounded, BiEdit, BiTrash, BiFlag, BiSolidLike, BiLike, BiSolidDislike, BiDislike, BiChevronDown, BiChevronUp } from 'react-icons/bi';
25
+ import { BiChevronDown, BiChevronUp, BiSolidLike, BiLike, BiSolidDislike, BiDislike, BiDotsVerticalRounded, BiEdit, BiTrash, BiFlag } from 'react-icons/bi';
26
26
 
27
27
  // node_modules/clsx/dist/clsx.mjs
28
28
  function r(e) {
@@ -17522,15 +17522,16 @@ function CommentComposer({
17522
17522
  }
17523
17523
  var CommentComposer_default = CommentComposer;
17524
17524
  function CommentActions({
17525
- likes = 0,
17526
- dislikes = 0,
17527
- liked = false,
17528
- disliked = false,
17529
- canReply = true,
17525
+ comment,
17530
17526
  onLike,
17531
17527
  onDislike,
17532
17528
  onReply
17533
17529
  }) {
17530
+ const likes = comment.likes ?? 0;
17531
+ const dislikes = comment.dislikes ?? 0;
17532
+ const liked = comment.liked ?? false;
17533
+ const disliked = comment.disliked ?? false;
17534
+ const canReply = comment.permissions?.canReply ?? true;
17534
17535
  return /* @__PURE__ */ jsxs(
17535
17536
  "div",
17536
17537
  {
@@ -17583,14 +17584,8 @@ function CommentActions({
17583
17584
  );
17584
17585
  }
17585
17586
  var CommentActions_default = CommentActions;
17586
- function CommentContent({ content }) {
17587
- return /* @__PURE__ */ jsx(
17588
- "div",
17589
- {
17590
- className: "\n text-sm\n leading-relaxed\n whitespace-pre-wrap\n break-words\n text-gray-700\n dark:text-gray-300\n ",
17591
- children: content
17592
- }
17593
- );
17587
+ function CommentContent({ comment }) {
17588
+ return /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap break-words text-sm text-gray-700 dark:text-gray-300", children: comment.content });
17594
17589
  }
17595
17590
  var CommentContent_default = CommentContent;
17596
17591
 
@@ -17629,31 +17624,29 @@ function formatCommentDate(date) {
17629
17624
  }
17630
17625
  return "Just now";
17631
17626
  }
17632
- function CommentHeader({
17633
- avatar,
17634
- username,
17635
- firstName,
17636
- lastName,
17637
- createdAt,
17638
- edited
17639
- }) {
17640
- const displayName = firstName || lastName ? `${firstName ?? ""} ${lastName ?? ""}`.trim() : username;
17627
+ function CommentHeader({ comment }) {
17628
+ const author = comment.author;
17629
+ const displayName = author?.firstName || author?.lastName ? `${author?.firstName ?? ""} ${author?.lastName ?? ""}`.trim() : author?.username ?? "Unknown";
17641
17630
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
17642
- /* @__PURE__ */ jsx(Avatar, { src: avatar, size: "sm" }),
17631
+ /* @__PURE__ */ jsx(Avatar, { src: author?.avatar, size: "sm" }),
17643
17632
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap min-w-0", children: [
17644
17633
  /* @__PURE__ */ jsx("span", { className: "font-semibold text-sm text-gray-900 dark:text-gray-100", children: displayName }),
17645
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
17646
- "@",
17647
- username
17634
+ author?.username && /* @__PURE__ */ jsxs(Fragment, { children: [
17635
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
17636
+ "@",
17637
+ author.username
17638
+ ] }),
17639
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "\xB7" })
17648
17640
  ] }),
17649
- /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "\xB7" }),
17650
- /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: formatCommentDate(createdAt) }),
17651
- edited && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: "(edited)" })
17641
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: formatCommentDate(comment.createdAt) }),
17642
+ comment.edited && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: "(edited)" })
17652
17643
  ] })
17653
17644
  ] });
17654
17645
  }
17655
17646
  var CommentHeader_default = CommentHeader;
17656
17647
  function CommentMenu({
17648
+ open,
17649
+ setOpen,
17657
17650
  canEdit,
17658
17651
  canDelete,
17659
17652
  canReport,
@@ -17661,7 +17654,6 @@ function CommentMenu({
17661
17654
  onDelete,
17662
17655
  onReport
17663
17656
  }) {
17664
- const [open, setOpen] = useState(false);
17665
17657
  const ref = useRef(null);
17666
17658
  useEffect(() => {
17667
17659
  function handleOutsideClick(event) {
@@ -17671,7 +17663,7 @@ function CommentMenu({
17671
17663
  }
17672
17664
  document.addEventListener("mousedown", handleOutsideClick);
17673
17665
  return () => document.removeEventListener("mousedown", handleOutsideClick);
17674
- }, []);
17666
+ }, [setOpen]);
17675
17667
  const hasActions = canEdit || canDelete || canReport;
17676
17668
  if (!hasActions) {
17677
17669
  return null;
@@ -17681,7 +17673,7 @@ function CommentMenu({
17681
17673
  "button",
17682
17674
  {
17683
17675
  type: "button",
17684
- onClick: () => setOpen((prev) => !prev),
17676
+ onClick: () => setOpen(!open),
17685
17677
  className: "\n text-gray-500\n hover:text-gray-900\n dark:hover:text-gray-100\n transition-colors\n ",
17686
17678
  children: /* @__PURE__ */ jsx(BiDotsVerticalRounded, { size: 18 })
17687
17679
  }
@@ -17790,6 +17782,7 @@ var COMMENT_INDENTATION = 24;
17790
17782
  function CommentItem({
17791
17783
  comment,
17792
17784
  depth = 0,
17785
+ components,
17793
17786
  onLike,
17794
17787
  onDislike,
17795
17788
  onReply,
@@ -17800,10 +17793,19 @@ function CommentItem({
17800
17793
  const [collapsed, setCollapsed] = useState(false);
17801
17794
  const [isReplying, setIsReplying] = useState(false);
17802
17795
  const resolvedDepth = Math.min(depth, MAX_COMMENT_DEPTH);
17796
+ const {
17797
+ Header: HeaderComponent = CommentHeader_default,
17798
+ Content: ContentComponent = CommentContent_default,
17799
+ Actions: ActionsComponent = CommentActions_default,
17800
+ Menu: MenuComponent = CommentMenu_default,
17801
+ ReplyComposer: ReplyComposerComponent = ReplyComposer_default,
17802
+ RepliesToggle: RepliesToggleComponent = CommentRepliesToggle_default
17803
+ } = components ?? {};
17803
17804
  async function handleReply(content) {
17804
17805
  await onReply?.(comment, content);
17805
17806
  setIsReplying(false);
17806
17807
  }
17808
+ const [menuOpen, setMenuOpen] = useState(false);
17807
17809
  return /* @__PURE__ */ jsxs(
17808
17810
  "div",
17809
17811
  {
@@ -17814,20 +17816,13 @@ function CommentItem({
17814
17816
  children: [
17815
17817
  /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-3 min-w-0", children: [
17816
17818
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
17819
+ /* @__PURE__ */ jsx(HeaderComponent, { comment }),
17817
17820
  /* @__PURE__ */ jsx(
17818
- CommentHeader_default,
17819
- {
17820
- avatar: comment.author?.avatar,
17821
- username: comment.author?.username ?? "unknown",
17822
- firstName: comment.author?.firstName,
17823
- lastName: comment.author?.lastName,
17824
- createdAt: comment.createdAt,
17825
- edited: comment.edited
17826
- }
17827
- ),
17828
- /* @__PURE__ */ jsx(
17829
- CommentMenu_default,
17821
+ MenuComponent,
17830
17822
  {
17823
+ comment,
17824
+ open: menuOpen,
17825
+ setOpen: setMenuOpen,
17831
17826
  canEdit: comment.permissions?.canEdit,
17832
17827
  canDelete: comment.permissions?.canDelete,
17833
17828
  canReport: comment.permissions?.canReport,
@@ -17837,22 +17832,18 @@ function CommentItem({
17837
17832
  }
17838
17833
  )
17839
17834
  ] }),
17840
- /* @__PURE__ */ jsx(CommentContent_default, { content: comment.content }),
17835
+ /* @__PURE__ */ jsx(ContentComponent, { comment }),
17841
17836
  /* @__PURE__ */ jsx(
17842
- CommentActions_default,
17837
+ ActionsComponent,
17843
17838
  {
17844
- likes: comment.likes,
17845
- dislikes: comment.dislikes,
17846
- liked: comment.liked,
17847
- disliked: comment.disliked,
17848
- canReply: comment.permissions?.canReply,
17839
+ comment,
17849
17840
  onLike: () => onLike?.(comment),
17850
17841
  onDislike: () => onDislike?.(comment),
17851
17842
  onReply: () => setIsReplying((prev) => !prev)
17852
17843
  }
17853
17844
  ),
17854
17845
  isReplying && /* @__PURE__ */ jsx(
17855
- ReplyComposer_default,
17846
+ ReplyComposerComponent,
17856
17847
  {
17857
17848
  avatar: comment.author?.avatar,
17858
17849
  username: comment.author?.username,
@@ -17860,7 +17851,7 @@ function CommentItem({
17860
17851
  }
17861
17852
  ),
17862
17853
  !!comment.replies?.length && /* @__PURE__ */ jsx(
17863
- CommentRepliesToggle_default,
17854
+ RepliesToggleComponent,
17864
17855
  {
17865
17856
  collapsed,
17866
17857
  repliesCount: comment.replies.length,
@@ -17880,6 +17871,7 @@ function CommentItem({
17880
17871
  {
17881
17872
  comments: comment.replies,
17882
17873
  depth: depth + 1,
17874
+ components,
17883
17875
  onLike,
17884
17876
  onDislike,
17885
17877
  onReply,
@@ -17898,6 +17890,7 @@ var CommentItem_default = CommentItem;
17898
17890
  function CommentList({
17899
17891
  comments,
17900
17892
  depth = 0,
17893
+ components,
17901
17894
  onLike,
17902
17895
  onDislike,
17903
17896
  onReply,
@@ -17913,6 +17906,7 @@ function CommentList({
17913
17906
  {
17914
17907
  comment,
17915
17908
  depth,
17909
+ components,
17916
17910
  onLike,
17917
17911
  onDislike,
17918
17912
  onReply,
@@ -17981,12 +17975,14 @@ function CommentThread({
17981
17975
  currentUser,
17982
17976
  dataSource,
17983
17977
  loading = false,
17978
+ components,
17984
17979
  onEdit,
17985
17980
  onDelete,
17986
17981
  onReport
17987
17982
  }) {
17988
17983
  const [comments, setComments] = useState([]);
17989
17984
  const [isLoadingComments, setIsLoadingComments] = useState(true);
17985
+ const ComposerComponent = components?.ReplyComposer ?? CommentComposer_default;
17990
17986
  useEffect(() => {
17991
17987
  async function loadComments() {
17992
17988
  try {
@@ -18013,35 +18009,55 @@ function CommentThread({
18013
18009
  setComments((prev) => insertReply(prev, parentComment.id, reply));
18014
18010
  }
18015
18011
  async function handleLike(comment) {
18016
- const result = await dataSource.toggleLike(comment.id);
18012
+ const optimistic = {
18013
+ liked: !comment.liked,
18014
+ disliked: false,
18015
+ likes: comment.liked ? Math.max(comment.likes - 1, 0) : comment.likes + 1,
18016
+ dislikes: comment.disliked ? Math.max(comment.dislikes - 1, 0) : comment.dislikes
18017
+ };
18017
18018
  setComments(
18018
18019
  (prev) => updateComment(prev, comment.id, (item) => ({
18019
18020
  ...item,
18020
- likes: result.likes,
18021
- dislikes: result.dislikes,
18022
- liked: result.liked,
18023
- disliked: result.disliked
18021
+ likes: optimistic.likes,
18022
+ dislikes: optimistic.dislikes,
18023
+ liked: optimistic.liked,
18024
+ disliked: optimistic.disliked
18024
18025
  }))
18025
18026
  );
18027
+ try {
18028
+ await dataSource.toggleLike(comment.id);
18029
+ } catch {
18030
+ setComments((prev) => updateComment(prev, comment.id, () => comment));
18031
+ }
18026
18032
  }
18027
18033
  async function handleDislike(comment) {
18028
- const result = await dataSource.toggleDislike(comment.id);
18034
+ const optimistic = {
18035
+ liked: false,
18036
+ disliked: !comment.disliked,
18037
+ likes: comment.liked ? Math.max(comment.likes - 1, 0) : comment.likes,
18038
+ dislikes: comment.disliked ? Math.max(comment.dislikes - 1, 0) : comment.dislikes + 1
18039
+ };
18029
18040
  setComments(
18030
18041
  (prev) => updateComment(prev, comment.id, (item) => ({
18031
18042
  ...item,
18032
- likes: result.likes,
18033
- dislikes: result.dislikes,
18034
- liked: result.liked,
18035
- disliked: result.disliked
18043
+ likes: optimistic.likes,
18044
+ dislikes: optimistic.dislikes,
18045
+ liked: optimistic.liked,
18046
+ disliked: optimistic.disliked
18036
18047
  }))
18037
18048
  );
18049
+ try {
18050
+ await dataSource.toggleDislike(comment.id);
18051
+ } catch {
18052
+ setComments((prev) => updateComment(prev, comment.id, () => comment));
18053
+ }
18038
18054
  }
18039
18055
  if (loading || isLoadingComments) {
18040
18056
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6", children: "Loading comments..." });
18041
18057
  }
18042
18058
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
18043
18059
  /* @__PURE__ */ jsx(
18044
- CommentComposer_default,
18060
+ ComposerComponent,
18045
18061
  {
18046
18062
  avatar: currentUser.avatar,
18047
18063
  onSubmit: handleCreateComment
@@ -18051,6 +18067,7 @@ function CommentThread({
18051
18067
  CommentList_default,
18052
18068
  {
18053
18069
  comments,
18070
+ components,
18054
18071
  onLike: handleLike,
18055
18072
  onDislike: handleDislike,
18056
18073
  onReply: handleReply,