@collabdt/core 0.3.1 → 0.3.2

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.
Files changed (196) hide show
  1. package/dist/core/components/authentication/ForgotPassword.d.ts.map +1 -1
  2. package/dist/core/components/authentication/ForgotPassword.js +0 -1
  3. package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
  4. package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts +12 -2
  5. package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
  6. package/dist/core/components/ui/Comments/CollapsibleCommentItem.js +137 -139
  7. package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
  8. package/dist/core/components/ui/Comments/Comment.d.ts +18 -1
  9. package/dist/core/components/ui/Comments/Comment.d.ts.map +1 -1
  10. package/dist/core/components/ui/Comments/Comment.js +94 -23
  11. package/dist/core/components/ui/Comments/Comment.js.map +1 -1
  12. package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +34 -0
  13. package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -0
  14. package/dist/core/components/ui/Comments/CommentActionButtons.js +106 -0
  15. package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -0
  16. package/dist/core/components/ui/Comments/CommentInput.d.ts.map +1 -1
  17. package/dist/core/components/ui/Comments/CommentInput.js +5 -2
  18. package/dist/core/components/ui/Comments/CommentInput.js.map +1 -1
  19. package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
  20. package/dist/core/components/ui/Comments/CommentsSection.js +86 -42
  21. package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
  22. package/dist/core/components/ui/Comments/commentUtils.d.ts.map +1 -1
  23. package/dist/core/components/ui/Comments/commentUtils.js +2 -1
  24. package/dist/core/components/ui/Comments/commentUtils.js.map +1 -1
  25. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.d.ts.map +1 -1
  26. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js +0 -1
  27. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js.map +1 -1
  28. package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
  29. package/dist/core/components/ui/InfoSidebar/Container.js +16 -12
  30. package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
  31. package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
  32. package/dist/core/components/ui/Sensors/SensorInput.js +0 -1
  33. package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
  34. package/dist/core/components/ui/Sensors/SensorsSection.js +0 -2
  35. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  36. package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
  37. package/dist/core/components/ui/Sidebar.js +27 -4
  38. package/dist/core/components/ui/Sidebar.js.map +1 -1
  39. package/dist/core/components/ui/ToolbarButton.d.ts.map +1 -1
  40. package/dist/core/components/ui/ToolbarButton.js +0 -1
  41. package/dist/core/components/ui/ToolbarButton.js.map +1 -1
  42. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.d.ts.map +1 -1
  43. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js +0 -2
  44. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js.map +1 -1
  45. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.d.ts.map +1 -1
  46. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js +0 -10
  47. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js.map +1 -1
  48. package/dist/core/components/viewers/Data/files/DatatableFileAdder.d.ts.map +1 -1
  49. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js +0 -1
  50. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js.map +1 -1
  51. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.d.ts.map +1 -1
  52. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js +0 -1
  53. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js.map +1 -1
  54. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.d.ts.map +1 -1
  55. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js +0 -1
  56. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js.map +1 -1
  57. package/dist/core/components/viewers/Data/utils/filterHelper.d.ts.map +1 -1
  58. package/dist/core/components/viewers/Data/utils/filterHelper.js +0 -2
  59. package/dist/core/components/viewers/Data/utils/filterHelper.js.map +1 -1
  60. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.d.ts.map +1 -1
  61. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js +0 -3
  62. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js.map +1 -1
  63. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  64. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +1 -7
  65. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  66. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  67. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js +1 -9
  68. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  69. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.d.ts.map +1 -1
  70. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js +4 -3
  71. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js.map +1 -1
  72. package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
  73. package/dist/core/components/viewers/bim/src/ClippingPlane.js +0 -1
  74. package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
  75. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts +16 -10
  76. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts.map +1 -1
  77. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js +26 -6
  78. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
  79. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +23 -0
  80. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -0
  81. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +108 -0
  82. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -0
  83. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts +44 -0
  84. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts.map +1 -0
  85. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js +77 -0
  86. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -0
  87. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +24 -0
  88. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -0
  89. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +27 -0
  90. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -0
  91. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.d.ts.map +1 -1
  92. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js +2 -2
  93. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js.map +1 -1
  94. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
  95. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +242 -61
  96. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
  97. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.d.ts.map +1 -1
  98. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js +1 -5
  99. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js.map +1 -1
  100. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.d.ts.map +1 -1
  101. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js +0 -1
  102. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js.map +1 -1
  103. package/dist/core/components/viewers/bim/src/tools/measureBimTool.d.ts.map +1 -1
  104. package/dist/core/components/viewers/bim/src/tools/measureBimTool.js +1 -2
  105. package/dist/core/components/viewers/bim/src/tools/measureBimTool.js.map +1 -1
  106. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  107. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  108. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.d.ts.map +1 -1
  109. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js +11 -14
  110. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js.map +1 -1
  111. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.d.ts.map +1 -1
  112. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js +2 -5
  113. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js.map +1 -1
  114. package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
  115. package/dist/core/components/viewers/map/datasets/src/localDatasets.js +0 -3
  116. package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
  117. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.d.ts.map +1 -1
  118. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js +0 -11
  119. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js.map +1 -1
  120. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.d.ts.map +1 -1
  121. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js +0 -1
  122. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js.map +1 -1
  123. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
  124. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +0 -1
  125. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
  126. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.d.ts.map +1 -1
  127. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js +0 -1
  128. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js.map +1 -1
  129. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.d.ts.map +1 -1
  130. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js +174 -53
  131. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js.map +1 -1
  132. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.d.ts.map +1 -1
  133. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js +2 -1
  134. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js.map +1 -1
  135. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
  136. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +0 -3
  137. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
  138. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.d.ts.map +1 -1
  139. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js +4 -3
  140. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js.map +1 -1
  141. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  142. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js +0 -1
  143. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  144. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  145. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js +1 -5
  146. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  147. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.d.ts.map +1 -1
  148. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js +1 -3
  149. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js.map +1 -1
  150. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
  151. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +0 -1
  152. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
  153. package/dist/core/components/viewers/map/utils/flyToEach.d.ts.map +1 -1
  154. package/dist/core/components/viewers/map/utils/flyToEach.js +0 -1
  155. package/dist/core/components/viewers/map/utils/flyToEach.js.map +1 -1
  156. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.d.ts.map +1 -1
  157. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js +0 -2
  158. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js.map +1 -1
  159. package/dist/core/hooks/comments/comments.d.ts +11 -0
  160. package/dist/core/hooks/comments/comments.d.ts.map +1 -1
  161. package/dist/core/hooks/comments/comments.js +3 -1
  162. package/dist/core/hooks/comments/comments.js.map +1 -1
  163. package/dist/core/hooks/comments/createCommentHooks.d.ts +11 -0
  164. package/dist/core/hooks/comments/createCommentHooks.d.ts.map +1 -1
  165. package/dist/core/hooks/comments/createCommentHooks.js +30 -1
  166. package/dist/core/hooks/comments/createCommentHooks.js.map +1 -1
  167. package/dist/core/hooks/files/files.d.ts.map +1 -1
  168. package/dist/core/hooks/files/files.js +0 -1
  169. package/dist/core/hooks/files/files.js.map +1 -1
  170. package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts +30 -0
  171. package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts.map +1 -0
  172. package/dist/core/hooks/ui/useResizableSidebarWidth.js +75 -0
  173. package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -0
  174. package/dist/core/i18n/messages/en.json +5 -0
  175. package/dist/core/i18n/messages/es.json +6 -1
  176. package/dist/core/i18n/messages/fr.json +6 -1
  177. package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
  178. package/dist/core/store/Datasets/reducer.js +0 -2
  179. package/dist/core/store/Datasets/reducer.js.map +1 -1
  180. package/dist/core/store/Files/reducer.js +0 -1
  181. package/dist/core/store/Files/reducer.js.map +1 -1
  182. package/dist/core/store/Menus/context.d.ts.map +1 -1
  183. package/dist/core/store/Menus/context.js +4 -1
  184. package/dist/core/store/Menus/context.js.map +1 -1
  185. package/dist/core/store/Menus/reducer.d.ts +20 -0
  186. package/dist/core/store/Menus/reducer.d.ts.map +1 -1
  187. package/dist/core/store/Menus/reducer.js +21 -3
  188. package/dist/core/store/Menus/reducer.js.map +1 -1
  189. package/dist/core/utils/markerUtils.d.ts +10 -0
  190. package/dist/core/utils/markerUtils.d.ts.map +1 -1
  191. package/dist/core/utils/markerUtils.js +9 -1
  192. package/dist/core/utils/markerUtils.js.map +1 -1
  193. package/dist/core/utils/memcache.d.ts.map +1 -1
  194. package/dist/core/utils/memcache.js +0 -7
  195. package/dist/core/utils/memcache.js.map +1 -1
  196. package/package.json +4 -1
@@ -1,14 +1,34 @@
1
1
  "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
2
21
  import { jsx, jsxs } from "react/jsx-runtime";
3
22
  import * as LR from "lucide-react";
4
23
  import * as React from "react";
5
24
  import { useFile } from "../../../hooks/files/files";
6
- import { markerStyleHighlight } from "../../../utils/markerUtils";
25
+ import { commentRingShadow } from "../../../utils/markerUtils";
7
26
  import { formatTimestamp } from "../../../utils/timeUtils";
8
27
  import { Avatar } from "../Avatar";
9
28
  import { Button } from "../Button";
10
29
  import { Card } from "../Card";
11
30
  import { UserAvatar } from "../UserAvatar";
31
+ import { CommentActionButtons } from "./CommentActionButtons";
12
32
  function Comment({
13
33
  text,
14
34
  createdAt,
@@ -17,34 +37,47 @@ function Comment({
17
37
  userImageFileId,
18
38
  onRemove,
19
39
  onClose,
40
+ onSelect,
41
+ onFocus,
42
+ onReply,
43
+ onEdit,
20
44
  enableCollapse = false,
21
45
  defaultCollapsed = false,
22
46
  isPending = false,
23
- highlight = false
47
+ highlight = false,
48
+ focused = false,
49
+ showActions = false,
50
+ canReply = true,
51
+ canEdit = true,
52
+ canDelete = true,
53
+ actionLabels
24
54
  }) {
55
+ var _a, _b, _c, _d;
25
56
  const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed);
26
57
  const lastTap = React.useRef(0);
27
58
  const resolvedImageFileId = userImageFileId != null ? userImageFileId : userImage;
28
59
  const { file } = useFile(resolvedImageFileId);
29
60
  const previewSrc = file == null ? void 0 : file.url;
30
- const handlePointerDown = (e) => {
31
- if (!enableCollapse) return;
32
- e.stopPropagation();
33
- const now = performance.now();
34
- if (now - lastTap.current < 300) setIsCollapsed((v) => !v);
35
- lastTap.current = now;
61
+ React.useEffect(() => {
62
+ if (focused && enableCollapse) setIsCollapsed(false);
63
+ }, [focused, enableCollapse]);
64
+ const handleClose = () => {
65
+ if (enableCollapse) setIsCollapsed(true);
66
+ else onClose == null ? void 0 : onClose();
36
67
  };
37
68
  if (enableCollapse && isCollapsed) {
38
69
  return /* @__PURE__ */ jsx(
39
70
  "div",
40
71
  {
41
- className: `h-9 w-9 rounded-full shadow-md overflow-hidden flex-shrink-0 pointer-events-auto ${highlight ? markerStyleHighlight : ""}`,
42
- onPointerDown: handlePointerDown,
43
- onDoubleClick: (e) => {
72
+ className: "h-9 w-9 rounded-full overflow-hidden flex-shrink-0 pointer-events-auto cursor-pointer transition-transform relative",
73
+ style: { boxShadow: commentRingShadow({ highlight, focused }) },
74
+ onPointerDown: (e) => {
44
75
  e.stopPropagation();
45
- setIsCollapsed((v) => !v);
76
+ lastTap.current = performance.now();
77
+ onSelect == null ? void 0 : onSelect();
78
+ setIsCollapsed(false);
46
79
  },
47
- children: isPending ? /* @__PURE__ */ jsx("div", { className: "w-full h-full rounded-full bg-primary-light flex items-center justify-center", children: /* @__PURE__ */ jsx(LR.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) }) : /* @__PURE__ */ jsx(Avatar, { className: "h-full w-full cursor-pointer", children: /* @__PURE__ */ jsx(
80
+ children: isPending ? /* @__PURE__ */ jsx("div", { className: "w-full h-full rounded-full bg-primary-light flex items-center justify-center", children: /* @__PURE__ */ jsx(LR.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) }) : /* @__PURE__ */ jsx(Avatar, { className: "h-full w-full", children: /* @__PURE__ */ jsx(
48
81
  UserAvatar,
49
82
  {
50
83
  imageFileId: resolvedImageFileId,
@@ -60,13 +93,18 @@ function Comment({
60
93
  "div",
61
94
  {
62
95
  className: "relative inline-block group",
63
- style: { pointerEvents: "auto" },
64
- title: enableCollapse ? "Double click to collapse" : void 0,
65
- onPointerDown: handlePointerDown,
96
+ style: { pointerEvents: "auto", boxShadow: focused ? commentRingShadow({ focused }) : void 0, borderRadius: focused ? 12 : void 0, zIndex: focused ? 30 : highlight ? 20 : void 0 },
97
+ title: onFocus ? "Double click to zoom" : enableCollapse ? "Double click to collapse" : void 0,
98
+ onPointerDown: (e) => {
99
+ e.stopPropagation();
100
+ if (!enableCollapse) return;
101
+ const now = performance.now();
102
+ if (now - lastTap.current < 300) onFocus == null ? void 0 : onFocus();
103
+ lastTap.current = now;
104
+ },
66
105
  onDoubleClick: (e) => {
67
106
  e.stopPropagation();
68
- if (enableCollapse) setIsCollapsed((v) => !v);
69
- else onClose == null ? void 0 : onClose();
107
+ if (!enableCollapse) onClose == null ? void 0 : onClose();
70
108
  },
71
109
  children: /* @__PURE__ */ jsxs(Card, { className: "w-48 px-3 py-2.5 shadow-md group-hover:shadow-lg transition-shadow duration-200", children: [
72
110
  /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
@@ -82,19 +120,38 @@ function Comment({
82
120
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [
83
121
  /* @__PURE__ */ jsx("span", { className: "font-medium text-sm text-foreground leading-none truncate", children: userName }),
84
122
  /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground leading-none", children: formatTimestamp(createdAt) })
85
- ] })
123
+ ] }),
124
+ showActions && /* @__PURE__ */ jsx(
125
+ Button,
126
+ __spreadProps(__spreadValues({
127
+ type: "button",
128
+ variant: "ghost",
129
+ size: "icon",
130
+ title: (_a = actionLabels == null ? void 0 : actionLabels.close) != null ? _a : "Close",
131
+ "aria-label": (_b = actionLabels == null ? void 0 : actionLabels.close) != null ? _b : "Close",
132
+ className: "h-7 w-7 shrink-0 -mr-1 -mt-1"
133
+ }, enableCollapse ? { onPointerDown: (e) => {
134
+ e.stopPropagation();
135
+ handleClose();
136
+ } } : { onClick: (e) => {
137
+ e.stopPropagation();
138
+ handleClose();
139
+ } }), {
140
+ children: /* @__PURE__ */ jsx(LR.X, { className: "h-4 w-4" })
141
+ })
142
+ )
86
143
  ] }),
87
144
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-start gap-2", children: [
88
145
  /* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 text-sm leading-relaxed text-foreground whitespace-pre-wrap break-words", children: text }),
89
- onRemove && /* @__PURE__ */ jsx(
146
+ !showActions && onRemove && /* @__PURE__ */ jsx(
90
147
  Button,
91
148
  {
92
149
  type: "button",
93
150
  variant: "ghost",
94
151
  size: "icon",
95
- title: "Remove comment",
152
+ title: (_c = actionLabels == null ? void 0 : actionLabels.delete) != null ? _c : "Remove comment",
96
153
  className: "z-50 h-7 w-7 shrink-0",
97
- "aria-label": "Remove comment",
154
+ "aria-label": (_d = actionLabels == null ? void 0 : actionLabels.delete) != null ? _d : "Remove comment",
98
155
  onClick: (e) => {
99
156
  e.stopPropagation();
100
157
  onRemove();
@@ -102,7 +159,21 @@ function Comment({
102
159
  children: /* @__PURE__ */ jsx(LR.Trash2, { className: "h-4 w-4" })
103
160
  }
104
161
  )
105
- ] })
162
+ ] }),
163
+ showActions && (onReply || onEdit || onRemove) && /* @__PURE__ */ jsx("div", { className: "mt-2 flex justify-end border-t pt-1", children: /* @__PURE__ */ jsx(
164
+ CommentActionButtons,
165
+ {
166
+ onReply,
167
+ onEdit,
168
+ onDelete: onRemove,
169
+ canReply,
170
+ canEdit,
171
+ canDelete,
172
+ labels: actionLabels,
173
+ buttonClassName: "h-7 w-7",
174
+ activateOnPointerDown: enableCollapse
175
+ }
176
+ ) })
106
177
  ] })
107
178
  }
108
179
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/core/components/ui/Comments/Comment.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as LR from 'lucide-react'\r\nimport * as React from 'react'\r\n\r\nimport { useFile } from '../../../hooks/files/files'\r\nimport { markerStyleHighlight } from '../../../utils/markerUtils'\r\nimport { formatTimestamp } from '../../../utils/timeUtils'\r\nimport { Avatar } from '../Avatar'\r\nimport { Button } from '../Button'\r\nimport { Card } from '../Card'\r\nimport { UserAvatar } from '../UserAvatar'\r\n\r\nexport type CommentProps = {\r\n userName: string\r\n userImage: number | null\r\n userImageFileId?: number | null\r\n buildingId?: number\r\n text: string\r\n createdAt: string | Date\r\n onRemove?: () => void\r\n onClose?: () => void\r\n enableCollapse?: boolean\r\n defaultCollapsed?: boolean\r\n isPending?: boolean\r\n highlight?: boolean\r\n}\r\n\r\nexport default function Comment({\r\n text,\r\n createdAt,\r\n userName,\r\n userImage,\r\n userImageFileId,\r\n onRemove,\r\n onClose,\r\n enableCollapse = false,\r\n defaultCollapsed = false,\r\n isPending = false,\r\n highlight = false,\r\n}: CommentProps) {\r\n const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed)\r\n const lastTap = React.useRef(0)\r\n const resolvedImageFileId = userImageFileId ?? userImage\r\n const { file } = useFile(resolvedImageFileId)\r\n const previewSrc = file?.url\r\n\r\n const handlePointerDown = (e: React.PointerEvent) => {\r\n if (!enableCollapse) return\r\n e.stopPropagation()\r\n\r\n const now = performance.now()\r\n if (now - lastTap.current < 300) setIsCollapsed(v => !v)\r\n lastTap.current = now\r\n }\r\n if (enableCollapse && isCollapsed) {\r\n return (\r\n <div\r\n className={`h-9 w-9 rounded-full shadow-md overflow-hidden flex-shrink-0 pointer-events-auto ${highlight ? markerStyleHighlight : ''}`}\r\n onPointerDown={handlePointerDown}\r\n onDoubleClick={(e) => {\r\n e.stopPropagation()\r\n setIsCollapsed(v => !v)\r\n }}\r\n >\r\n {isPending ? (\r\n <div className=\"w-full h-full rounded-full bg-primary-light flex items-center justify-center\">\r\n <LR.Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <Avatar className=\"h-full w-full cursor-pointer\">\r\n <UserAvatar\r\n imageFileId={resolvedImageFileId}\r\n previewSrc={previewSrc}\r\n name={userName}\r\n className=\"h-full w-full rounded-full object-cover\"\r\n />\r\n </Avatar>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n className=\"relative inline-block group\"\r\n style={{ pointerEvents: 'auto' }}\r\n title={enableCollapse ? 'Double click to collapse' : undefined}\r\n onPointerDown={handlePointerDown}\r\n onDoubleClick={(e) => {\r\n e.stopPropagation()\r\n if (enableCollapse) setIsCollapsed(v => !v)\r\n else onClose?.()\r\n }}\r\n >\r\n <Card className=\"w-48 px-3 py-2.5 shadow-md group-hover:shadow-lg transition-shadow duration-200\">\r\n <div className=\"flex items-start gap-3\">\r\n <div className=\"h-9 w-9 rounded-full shadow-sm flex items-center justify-center select-none flex-shrink-0 bg-card\">\r\n {isPending ? (\r\n <div className=\"h-10 w-10 rounded-full bg-muted flex items-center justify-center\">\r\n <LR.Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\r\n </div>\r\n ) : (\r\n <Avatar className=\"h-10 w-10\">\r\n <UserAvatar\r\n imageFileId={resolvedImageFileId}\r\n previewSrc={previewSrc}\r\n name={userName}\r\n className=\"h-full w-full rounded-full object-cover\"\r\n />\r\n </Avatar>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\r\n <span className=\"font-medium text-sm text-foreground leading-none truncate\">\r\n {userName}\r\n </span>\r\n <span className=\"text-xs text-muted-foreground leading-none\">\r\n {formatTimestamp(createdAt)}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"mt-2 flex items-start gap-2\">\r\n <p className=\"min-w-0 flex-1 text-sm leading-relaxed text-foreground whitespace-pre-wrap break-words\">\r\n {text}\r\n </p>\r\n\r\n {onRemove && (\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n title=\"Remove comment\"\r\n className=\"z-50 h-7 w-7 shrink-0\"\r\n aria-label=\"Remove comment\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onRemove()\r\n }}\r\n >\r\n <LR.Trash2 className=\"h-4 w-4\" />\r\n </Button>\r\n )}\r\n </div>\r\n </Card>\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/core/components/ui/Comments/Comment.tsx"],"sourcesContent":["'use client'\n\n// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2025 Collab Digital Twins\n\nimport * as LR from 'lucide-react'\nimport * as React from 'react'\n\nimport { useFile } from '../../../hooks/files/files'\nimport { commentRingShadow } from '../../../utils/markerUtils'\nimport { formatTimestamp } from '../../../utils/timeUtils'\nimport { Avatar } from '../Avatar'\nimport { Button } from '../Button'\nimport { Card } from '../Card'\nimport { UserAvatar } from '../UserAvatar'\n\nimport { CommentActionButtons, type CommentActionLabels } from './CommentActionButtons'\n\nexport type CommentProps = {\n userName: string\n userImage: number | null\n userImageFileId?: number | null\n buildingId?: number\n text: string\n createdAt: string | Date\n onRemove?: () => void\n onClose?: () => void\n /** Called when the collapsed avatar is single-clicked (select the comment). */\n onSelect?: () => void\n /** Called on double-click — used to zoom/focus the comment in the viewer. */\n onFocus?: () => void\n /** Reply to the comment (in-viewer card opens the reply box in the sidebar). */\n onReply?: () => void\n /** Edit the comment (in-viewer card opens the editor in the sidebar). */\n onEdit?: () => void\n enableCollapse?: boolean\n defaultCollapsed?: boolean\n isPending?: boolean\n highlight?: boolean\n /** Double-clicked/zoomed comment: renders the thicker focus ring. */\n focused?: boolean\n /** Render the close/reply/edit/delete action row (used by the in-viewer BIM card). */\n showActions?: boolean\n canReply?: boolean\n canEdit?: boolean\n canDelete?: boolean\n actionLabels?: CommentActionLabels\n}\n\nexport default function Comment({\n text,\n createdAt,\n userName,\n userImage,\n userImageFileId,\n onRemove,\n onClose,\n onSelect,\n onFocus,\n onReply,\n onEdit,\n enableCollapse = false,\n defaultCollapsed = false,\n isPending = false,\n highlight = false,\n focused = false,\n showActions = false,\n canReply = true,\n canEdit = true,\n canDelete = true,\n actionLabels,\n}: CommentProps) {\n const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed)\n // Timestamp of the last press, shared across the puck→card transition so a quick second press\n // (double-click) zooms even though the first press already opened the card.\n const lastTap = React.useRef(0)\n const resolvedImageFileId = userImageFileId ?? userImage\n const { file } = useFile(resolvedImageFileId)\n const previewSrc = file?.url\n\n // Zooming to a comment (focus) should also open its card in the 3D scene.\n React.useEffect(() => {\n if (focused && enableCollapse) setIsCollapsed(false)\n }, [focused, enableCollapse])\n\n const handleClose = () => {\n if (enableCollapse) setIsCollapsed(true)\n else onClose?.()\n }\n\n if (enableCollapse && isCollapsed) {\n return (\n <div\n className=\"h-9 w-9 rounded-full overflow-hidden flex-shrink-0 pointer-events-auto cursor-pointer transition-transform relative\"\n style={{ boxShadow: commentRingShadow({ highlight, focused }) }}\n // Open on pointerdown, not click: the CSS2D renderer re-transforms this element every\n // frame, so a browser \"click\" (down+up on the same stable spot) often never fires in the\n // 3D scene. stopPropagation keeps the press from reaching the canvas/orbit controls.\n onPointerDown={(e) => {\n e.stopPropagation()\n lastTap.current = performance.now()\n onSelect?.()\n setIsCollapsed(false)\n }}\n >\n {isPending ? (\n <div className=\"w-full h-full rounded-full bg-primary-light flex items-center justify-center\">\n <LR.Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" />\n </div>\n ) : (\n <Avatar className=\"h-full w-full\">\n <UserAvatar\n imageFileId={resolvedImageFileId}\n previewSrc={previewSrc}\n name={userName}\n className=\"h-full w-full rounded-full object-cover\"\n />\n </Avatar>\n )}\n </div>\n )\n }\n\n return (\n <div\n className=\"relative inline-block group\"\n style={{ pointerEvents: 'auto', boxShadow: focused ? commentRingShadow({ focused }) : undefined, borderRadius: focused ? 12 : undefined, zIndex: focused ? 30 : highlight ? 20 : undefined }}\n title={onFocus ? 'Double click to zoom' : enableCollapse ? 'Double click to collapse' : undefined}\n // In the 3D card, detect a double-press here (dblclick is unreliable under the CSS2D\n // renderer) to trigger zoom. The map popup keeps the normal onDoubleClick path below.\n onPointerDown={(e) => {\n e.stopPropagation()\n if (!enableCollapse) return\n const now = performance.now()\n if (now - lastTap.current < 300) onFocus?.()\n lastTap.current = now\n }}\n onDoubleClick={(e) => {\n e.stopPropagation()\n if (!enableCollapse) onClose?.()\n }}\n >\n <Card className=\"w-48 px-3 py-2.5 shadow-md group-hover:shadow-lg transition-shadow duration-200\">\n <div className=\"flex items-start gap-3\">\n <div className=\"h-9 w-9 rounded-full shadow-sm flex items-center justify-center select-none flex-shrink-0 bg-card\">\n {isPending ? (\n <div className=\"h-10 w-10 rounded-full bg-muted flex items-center justify-center\">\n <LR.Loader2 className=\"h-5 w-5 animate-spin text-muted-foreground\" />\n </div>\n ) : (\n <Avatar className=\"h-10 w-10\">\n <UserAvatar\n imageFileId={resolvedImageFileId}\n previewSrc={previewSrc}\n name={userName}\n className=\"h-full w-full rounded-full object-cover\"\n />\n </Avatar>\n )}\n </div>\n\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n <span className=\"font-medium text-sm text-foreground leading-none truncate\">\n {userName}\n </span>\n <span className=\"text-xs text-muted-foreground leading-none\">\n {formatTimestamp(createdAt)}\n </span>\n </div>\n\n {showActions && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n title={actionLabels?.close ?? 'Close'}\n aria-label={actionLabels?.close ?? 'Close'}\n className=\"h-7 w-7 shrink-0 -mr-1 -mt-1\"\n // In the CSS2D 3D card (enableCollapse) activate on pointerdown for reliability;\n // the map popup is normal DOM, so keep click for keyboard accessibility.\n {...(enableCollapse\n ? { onPointerDown: (e: React.PointerEvent) => { e.stopPropagation(); handleClose() } }\n : { onClick: (e: React.MouseEvent) => { e.stopPropagation(); handleClose() } })}\n >\n <LR.X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n\n <div className=\"mt-2 flex items-start gap-2\">\n <p className=\"min-w-0 flex-1 text-sm leading-relaxed text-foreground whitespace-pre-wrap break-words\">\n {text}\n </p>\n\n {/* Map popup keeps the inline delete; the BIM card uses the action row below instead. */}\n {!showActions && onRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n title={actionLabels?.delete ?? 'Remove comment'}\n className=\"z-50 h-7 w-7 shrink-0\"\n aria-label={actionLabels?.delete ?? 'Remove comment'}\n onClick={(e) => {\n e.stopPropagation()\n onRemove()\n }}\n >\n <LR.Trash2 className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n\n {showActions && (onReply || onEdit || onRemove) && (\n <div className=\"mt-2 flex justify-end border-t pt-1\">\n <CommentActionButtons\n onReply={onReply}\n onEdit={onEdit}\n onDelete={onRemove}\n canReply={canReply}\n canEdit={canEdit}\n canDelete={canDelete}\n labels={actionLabels}\n buttonClassName=\"h-7 w-7\"\n activateOnPointerDown={enableCollapse}\n />\n </div>\n )}\n </Card>\n </div>\n )\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,34 @@
1
+ import * as React from 'react';
2
+ export interface CommentActionLabels {
3
+ reply?: string;
4
+ edit?: string;
5
+ delete?: string;
6
+ close?: string;
7
+ }
8
+ interface CommentActionButtonsProps {
9
+ onReply?: () => void;
10
+ onEdit?: () => void;
11
+ onDelete?: () => void;
12
+ onClose?: () => void;
13
+ canReply?: boolean;
14
+ canEdit?: boolean;
15
+ canDelete?: boolean;
16
+ labels?: CommentActionLabels;
17
+ className?: string;
18
+ /** Applied to each icon button; lets the caller size the row (sidebar h-8, 3D card h-7). */
19
+ buttonClassName?: string;
20
+ /**
21
+ * Fire on pointerdown instead of click. Needed inside the 3D comment card: the CSS2D renderer
22
+ * re-transforms the element every frame, so a browser "click" frequently never fires there.
23
+ */
24
+ activateOnPointerDown?: boolean;
25
+ }
26
+ /**
27
+ * Presentational reply/edit/delete/close row shared by the sidebar comment item and the
28
+ * in-viewer comment card. Intentionally free of i18n and permission hooks: the in-viewer
29
+ * card renders in a detached React root without the next-intl provider, so labels are
30
+ * passed in and gating is expressed by which handlers/`can*` flags the caller supplies.
31
+ */
32
+ export declare function CommentActionButtons({ onReply, onEdit, onDelete, onClose, canReply, canEdit, canDelete, labels, className, buttonClassName, activateOnPointerDown, }: CommentActionButtonsProps): React.ReactElement;
33
+ export {};
34
+ //# sourceMappingURL=CommentActionButtons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommentActionButtons.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CommentActionButtons.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,UAAU,yBAAyB;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAe,EACf,OAAc,EACd,SAAgB,EAChB,MAAM,EACN,SAAS,EACT,eAAe,EACf,qBAA6B,GAC9B,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAuEhD"}
@@ -0,0 +1,106 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+ import { jsx, jsxs } from "react/jsx-runtime";
22
+ import * as LR from "lucide-react";
23
+ import { cn } from "../../../utils/utils";
24
+ import { Button } from "../Button";
25
+ function CommentActionButtons({
26
+ onReply,
27
+ onEdit,
28
+ onDelete,
29
+ onClose,
30
+ canReply = true,
31
+ canEdit = true,
32
+ canDelete = true,
33
+ labels,
34
+ className,
35
+ buttonClassName,
36
+ activateOnPointerDown = false
37
+ }) {
38
+ var _a, _b, _c, _d, _e, _f, _g, _h;
39
+ const activate = (handler) => (e) => {
40
+ e.stopPropagation();
41
+ handler == null ? void 0 : handler();
42
+ };
43
+ const bind = (handler) => activateOnPointerDown ? { onPointerDown: activate(handler) } : { onClick: activate(handler) };
44
+ const btn = cn("h-8 w-8 p-0", buttonClassName);
45
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-0 flex-shrink-0", className), children: [
46
+ onReply && /* @__PURE__ */ jsx(
47
+ Button,
48
+ __spreadProps(__spreadValues({
49
+ type: "button",
50
+ variant: "ghost",
51
+ size: "icon",
52
+ className: btn
53
+ }, bind(onReply)), {
54
+ title: (_a = labels == null ? void 0 : labels.reply) != null ? _a : "Reply",
55
+ "aria-label": (_b = labels == null ? void 0 : labels.reply) != null ? _b : "Reply",
56
+ disabled: !canReply,
57
+ children: /* @__PURE__ */ jsx(LR.Reply, { className: "h-4 w-4" })
58
+ })
59
+ ),
60
+ onEdit && /* @__PURE__ */ jsx(
61
+ Button,
62
+ __spreadProps(__spreadValues({
63
+ type: "button",
64
+ variant: "ghost",
65
+ size: "icon",
66
+ className: btn
67
+ }, bind(onEdit)), {
68
+ title: (_c = labels == null ? void 0 : labels.edit) != null ? _c : "Edit",
69
+ "aria-label": (_d = labels == null ? void 0 : labels.edit) != null ? _d : "Edit",
70
+ disabled: !canEdit,
71
+ children: /* @__PURE__ */ jsx(LR.Pencil, { className: "h-4 w-4" })
72
+ })
73
+ ),
74
+ onDelete && /* @__PURE__ */ jsx(
75
+ Button,
76
+ __spreadProps(__spreadValues({
77
+ type: "button",
78
+ variant: "ghost",
79
+ size: "icon",
80
+ className: btn
81
+ }, bind(onDelete)), {
82
+ title: (_e = labels == null ? void 0 : labels.delete) != null ? _e : "Delete",
83
+ "aria-label": (_f = labels == null ? void 0 : labels.delete) != null ? _f : "Delete",
84
+ disabled: !canDelete,
85
+ children: /* @__PURE__ */ jsx(LR.Trash2, { className: "h-4 w-4" })
86
+ })
87
+ ),
88
+ onClose && /* @__PURE__ */ jsx(
89
+ Button,
90
+ __spreadProps(__spreadValues({
91
+ type: "button",
92
+ variant: "ghost",
93
+ size: "icon",
94
+ className: btn
95
+ }, bind(onClose)), {
96
+ title: (_g = labels == null ? void 0 : labels.close) != null ? _g : "Close",
97
+ "aria-label": (_h = labels == null ? void 0 : labels.close) != null ? _h : "Close",
98
+ children: /* @__PURE__ */ jsx(LR.X, { className: "h-4 w-4" })
99
+ })
100
+ )
101
+ ] });
102
+ }
103
+ export {
104
+ CommentActionButtons
105
+ };
106
+ //# sourceMappingURL=CommentActionButtons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/core/components/ui/Comments/CommentActionButtons.tsx"],"sourcesContent":["'use client'\n\n// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2025 Collab Digital Twins\n\nimport * as LR from 'lucide-react'\nimport * as React from 'react'\n\nimport { cn } from '../../../utils/utils'\nimport { Button } from '../Button'\n\nexport interface CommentActionLabels {\n reply?: string\n edit?: string\n delete?: string\n close?: string\n}\n\ninterface CommentActionButtonsProps {\n onReply?: () => void\n onEdit?: () => void\n onDelete?: () => void\n onClose?: () => void\n canReply?: boolean\n canEdit?: boolean\n canDelete?: boolean\n labels?: CommentActionLabels\n className?: string\n /** Applied to each icon button; lets the caller size the row (sidebar h-8, 3D card h-7). */\n buttonClassName?: string\n /**\n * Fire on pointerdown instead of click. Needed inside the 3D comment card: the CSS2D renderer\n * re-transforms the element every frame, so a browser \"click\" frequently never fires there.\n */\n activateOnPointerDown?: boolean\n}\n\n/**\n * Presentational reply/edit/delete/close row shared by the sidebar comment item and the\n * in-viewer comment card. Intentionally free of i18n and permission hooks: the in-viewer\n * card renders in a detached React root without the next-intl provider, so labels are\n * passed in and gating is expressed by which handlers/`can*` flags the caller supplies.\n */\nexport function CommentActionButtons({\n onReply,\n onEdit,\n onDelete,\n onClose,\n canReply = true,\n canEdit = true,\n canDelete = true,\n labels,\n className,\n buttonClassName,\n activateOnPointerDown = false,\n}: CommentActionButtonsProps): React.ReactElement {\n const activate = (handler?: () => void) => (e: React.MouseEvent | React.PointerEvent) => {\n e.stopPropagation()\n handler?.()\n }\n\n // Bind the action to pointerdown (3D card) or click (sidebar). Returns the right prop object.\n const bind = (handler?: () => void) =>\n activateOnPointerDown ? { onPointerDown: activate(handler) } : { onClick: activate(handler) }\n\n const btn = cn('h-8 w-8 p-0', buttonClassName)\n\n return (\n <div className={cn('flex items-center gap-0 flex-shrink-0', className)}>\n {onReply && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={btn}\n {...bind(onReply)}\n title={labels?.reply ?? 'Reply'}\n aria-label={labels?.reply ?? 'Reply'}\n disabled={!canReply}\n >\n <LR.Reply className=\"h-4 w-4\" />\n </Button>\n )}\n {onEdit && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={btn}\n {...bind(onEdit)}\n title={labels?.edit ?? 'Edit'}\n aria-label={labels?.edit ?? 'Edit'}\n disabled={!canEdit}\n >\n <LR.Pencil className=\"h-4 w-4\" />\n </Button>\n )}\n {onDelete && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={btn}\n {...bind(onDelete)}\n title={labels?.delete ?? 'Delete'}\n aria-label={labels?.delete ?? 'Delete'}\n disabled={!canDelete}\n >\n <LR.Trash2 className=\"h-4 w-4\" />\n </Button>\n )}\n {onClose && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={btn}\n {...bind(onClose)}\n title={labels?.close ?? 'Close'}\n aria-label={labels?.close ?? 'Close'}\n >\n <LR.X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoEI,SAYM,KAZN;AA/DJ,YAAY,QAAQ;AAGpB,SAAS,UAAU;AACnB,SAAS,cAAc;AAkChB,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAwB;AAC1B,GAAkD;AAvDlD;AAwDE,QAAM,WAAW,CAAC,YAAyB,CAAC,MAA6C;AACvF,MAAE,gBAAgB;AAClB;AAAA,EACF;AAGA,QAAM,OAAO,CAAC,YACZ,wBAAwB,EAAE,eAAe,SAAS,OAAO,EAAE,IAAI,EAAE,SAAS,SAAS,OAAO,EAAE;AAE9F,QAAM,MAAM,GAAG,eAAe,eAAe;AAE7C,SACE,qBAAC,SAAI,WAAW,GAAG,yCAAyC,SAAS,GAClE;AAAA,eACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW;AAAA,SACP,KAAK,OAAO,IALjB;AAAA,QAMC,QAAO,sCAAQ,UAAR,YAAiB;AAAA,QACxB,eAAY,sCAAQ,UAAR,YAAiB;AAAA,QAC7B,UAAU,CAAC;AAAA,QAEX,8BAAC,GAAG,OAAH,EAAS,WAAU,WAAU;AAAA;AAAA,IAChC;AAAA,IAED,UACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW;AAAA,SACP,KAAK,MAAM,IALhB;AAAA,QAMC,QAAO,sCAAQ,SAAR,YAAgB;AAAA,QACvB,eAAY,sCAAQ,SAAR,YAAgB;AAAA,QAC5B,UAAU,CAAC;AAAA,QAEX,8BAAC,GAAG,QAAH,EAAU,WAAU,WAAU;AAAA;AAAA,IACjC;AAAA,IAED,YACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW;AAAA,SACP,KAAK,QAAQ,IALlB;AAAA,QAMC,QAAO,sCAAQ,WAAR,YAAkB;AAAA,QACzB,eAAY,sCAAQ,WAAR,YAAkB;AAAA,QAC9B,UAAU,CAAC;AAAA,QAEX,8BAAC,GAAG,QAAH,EAAU,WAAU,WAAU;AAAA;AAAA,IACjC;AAAA,IAED,WACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAW;AAAA,SACP,KAAK,OAAO,IALjB;AAAA,QAMC,QAAO,sCAAQ,UAAR,YAAiB;AAAA,QACxB,eAAY,sCAAQ,UAAR,YAAiB;AAAA,QAE7B,8BAAC,GAAG,GAAH,EAAK,WAAU,WAAU;AAAA;AAAA,IAC5B;AAAA,KAEJ;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"CommentInput.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CommentInput.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAUpD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE7D,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,GAAG,CAAA;IACV,OAAO,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAC5E,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,GAAG,CAAC,EAAE,0BAA0B,CAAA;IAChC,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,MAAiB,EACjB,QAAQ,EACR,GAAG,EACH,MAAc,GACf,EAAE,iBAAiB,qBA0SnB"}
1
+ {"version":3,"file":"CommentInput.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CommentInput.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAUpD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE7D,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,EAAE,GAAG,CAAA;IACV,OAAO,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAC5E,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,GAAG,CAAC,EAAE,0BAA0B,CAAA;IAChC,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,MAAiB,EACjB,QAAQ,EACR,GAAG,EACH,MAAc,GACf,EAAE,iBAAiB,qBA8SnB"}
@@ -4,6 +4,7 @@ import * as LR from "lucide-react";
4
4
  import { useSession } from "next-auth/react";
5
5
  import { useTranslations } from "next-intl";
6
6
  import * as React from "react";
7
+ import { toast } from "sonner";
7
8
  import { useCreateComment } from "../../../hooks/comments/comments";
8
9
  import { AppConfigContext, MapContext, BuildingsContext, MenusContext, ToolsContext } from "../../../store";
9
10
  import { ViewerNames } from "../../../types/dbTypes";
@@ -179,6 +180,7 @@ function CommentInput({
179
180
  if (text.trim() === "") return;
180
181
  setIsPlacing(true);
181
182
  setCursor("crosshair");
183
+ toast(viewer === ViewerNames.map ? t("placeHelpTextMap") : t("placeHelpTextBim"));
182
184
  };
183
185
  const inputEl = /* @__PURE__ */ jsx(
184
186
  Input,
@@ -202,7 +204,7 @@ function CommentInput({
202
204
  children: /* @__PURE__ */ jsx(LR.Plus, { className: cn("w-4 h-4", "cursor-pointer transition-transform duration-200 active:scale-90") })
203
205
  }
204
206
  );
205
- const helpText = isPlacing ? viewer === ViewerNames.map ? t("placeHelpTextMap") : t("placeHelpTextBim") : null;
207
+ const helpText = isPlacing ? viewer === ViewerNames.map ? t("placeHelpTextMap") : t("placeHelpTextBim") : text.trim() !== "" ? t("clickPlusHint") : null;
206
208
  if (layout === "dialog") {
207
209
  if (isPlacing) return null;
208
210
  return /* @__PURE__ */ jsx(
@@ -217,7 +219,8 @@ function CommentInput({
217
219
  /* @__PURE__ */ jsxs("div", { className: "flex flex-row gap-2", children: [
218
220
  inputEl,
219
221
  submitButtonEl
220
- ] })
222
+ ] }),
223
+ helpText && /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: helpText })
221
224
  ] })
222
225
  }
223
226
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/core/components/ui/Comments/CommentInput.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as LR from 'lucide-react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as React from 'react'\r\n\r\nimport { useCreateComment } from '../../../hooks/comments/comments'\r\nimport { AppConfigContext, MapContext, BuildingsContext, MenusContext, ToolsContext } from '../../../store'\r\nimport { ViewerNames } from '../../../types/dbTypes'\r\nimport { cn } from '../../../utils/utils'\r\nimport { AddItemDialog } from '../AddItemDialog'\r\nimport { Button } from '../Button'\r\nimport { Card, CardContent, CardHeader, CardTitle } from '../Card'\r\nimport { Input } from '../Input'\r\nimport { Label } from '../Label'\r\n\r\nimport type { Comment} from '../../../types/dbTypes';\r\n\r\nexport type CommentInputLayout = 'inline' | 'card' | 'dialog'\r\n\r\nexport type BimCommentPlacementContext = {\r\n world: any\r\n raycast: (data: { camera: any; mouse: any; dom: any }) => Promise<any>\r\n buildingId?: number\r\n setCursor?: (cursor: string) => void\r\n addPendingMarker?: (position: { x: number; y: number; z: number }) => number\r\n removePendingMarker?: (id: number) => void\r\n}\r\n\r\nexport type CommentInputProps = {\r\n viewer: ViewerNames\r\n layout?: CommentInputLayout\r\n onCancel?: () => void\r\n bim?: BimCommentPlacementContext\r\n isOpen?: boolean\r\n}\r\n\r\nexport function CommentInput({\r\n viewer,\r\n layout = 'inline',\r\n onCancel,\r\n bim,\r\n isOpen = false,\r\n}: CommentInputProps) {\r\n const t = useTranslations('CommentInput')\r\n const session = useSession()\r\n\r\n const user = useSession().data?.user\r\n\r\n const organizationId = user?.organizationId\r\n const authorId = session.data?.user?.id || -1\r\n\r\n const { state: appConfigState } = React.useContext(AppConfigContext)\r\n const mapContext = React.useContext(MapContext)\r\n\r\n const { state: buildingsState } = React.useContext(BuildingsContext)\r\n const buildingId = buildingsState?.buildings?.building?.id || -1\r\n\r\n const [text, setText] = React.useState('')\r\n const [isPlacing, setIsPlacing] = React.useState(false)\r\n\r\n const inputId = React.useId()\r\n const { createComment } = useCreateComment()\r\n\r\n const setCursor = React.useCallback((cursor: string) => {\r\n if (viewer === ViewerNames.map) {\r\n const map = mapContext?.state?.map?.map\r\n if (!map) return\r\n if (map.getCanvas().style.cursor === cursor) return\r\n map.getCanvas().style.cursor = cursor\r\n return\r\n }\r\n\r\n if (viewer === ViewerNames.bim) {\r\n bim?.setCursor?.(cursor)\r\n }\r\n }, [bim, mapContext, viewer])\r\n\r\n const reset = React.useCallback(() => {\r\n setIsPlacing(false)\r\n setText('')\r\n setCursor('')\r\n }, [setCursor])\r\n\r\n const onCreateComment = async (commentData: Partial<Comment>) => {\r\n const commentResult = await createComment({ commentData })\r\n reset()\r\n }\r\n\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { state: toolsState } = React.useContext(ToolsContext)\r\n const { currentToolId } = toolsState.tools\r\n const { commentsVisibleInViewer } = menusState.menus\r\n\r\n React.useEffect(() => {\r\n const viewerToShow = currentToolId === 'bim-add-comment'\r\n ? ViewerNames.bim\r\n : currentToolId === 'map-add-comment'\r\n ? ViewerNames.map\r\n : null\r\n\r\n if (!viewerToShow) return\r\n if (commentsVisibleInViewer.includes(viewerToShow)) return\r\n\r\n menusDispatch({\r\n type: 'SHOW_COMMENTS_IN_VIEWER',\r\n payload: { viewer: viewerToShow },\r\n })\r\n }, [currentToolId, commentsVisibleInViewer, menusDispatch])\r\n\r\n React.useEffect(() => {\r\n if (!isPlacing) return\r\n\r\n if (viewer === ViewerNames.map) {\r\n const map = mapContext?.state?.map?.map\r\n if (!map) return\r\n\r\n const mouseMoveCrosshairHandler = () => {\r\n setCursor('crosshair')\r\n }\r\n\r\n const dbClickAddCommentHandler = (e: any): void => {\r\n const longitude = e?.lngLat?.lng\r\n const latitude = e?.lngLat?.lat\r\n if (typeof longitude !== 'number' || typeof latitude !== 'number') return\r\n\r\n const elevation = map.queryTerrainElevation([latitude, longitude]) || 0\r\n\r\n const newComment = {\r\n authorId: Number(user?.id),\r\n organizationId,\r\n text,\r\n visible: true,\r\n longitude,\r\n latitude,\r\n elevation,\r\n viewer: ViewerNames.map,\r\n }\r\n onCreateComment(newComment)\r\n }\r\n\r\n map.on('mousemove', mouseMoveCrosshairHandler)\r\n map.on('dblclick', dbClickAddCommentHandler)\r\n\r\n return () => {\r\n setCursor('')\r\n map.off('mousemove', mouseMoveCrosshairHandler)\r\n map.off('dblclick', dbClickAddCommentHandler)\r\n }\r\n }\r\n\r\n\r\n if (viewer === ViewerNames.bim) {\r\n const world = bim?.world\r\n const raycast = bim?.raycast\r\n if (!world || !raycast) return\r\n\r\n let disposed = false\r\n let removeListeners: (() => void) | null = null\r\n\r\n ; (async () => {\r\n const THREE = await import('three')\r\n if (disposed) return\r\n\r\n const mouse = new THREE.Vector2()\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n }\r\n\r\n const handleDblClick = async (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n\r\n const result = await raycast({\r\n camera: world.camera?.three,\r\n mouse,\r\n dom: world.renderer?.three?.domElement,\r\n })\r\n\r\n if (!result?.point) return\r\n const p = result.point\r\n\r\n // Add pending marker immediately\r\n const pendingId = bim?.addPendingMarker?.({ x: p.x, y: p.y, z: p.z })\r\n\r\n const newComment = {\r\n authorId: Number(authorId),\r\n organizationId,\r\n text,\r\n x: p.x,\r\n y: p.y,\r\n z: p.z,\r\n visible: true,\r\n buildingId,\r\n viewer,\r\n }\r\n\r\n try {\r\n await onCreateComment(newComment)\r\n } finally {\r\n // Remove pending marker after creation completes (or fails)\r\n if (pendingId) {\r\n bim?.removePendingMarker?.(pendingId)\r\n }\r\n }\r\n // BIM flow historically closes the adding UI once the comment is placed.\r\n onCancel?.()\r\n }\r\n\r\n document.addEventListener('mousemove', handleMouseMove)\r\n document.addEventListener('dblclick', handleDblClick)\r\n\r\n removeListeners = () => {\r\n document.removeEventListener('mousemove', handleMouseMove)\r\n document.removeEventListener('dblclick', handleDblClick)\r\n }\r\n })()\r\n\r\n return () => {\r\n disposed = true\r\n setCursor('')\r\n removeListeners?.()\r\n }\r\n }\r\n }, [\r\n appConfigState,\r\n bim,\r\n isPlacing,\r\n mapContext,\r\n viewer,\r\n onCancel,\r\n reset,\r\n setCursor,\r\n text,\r\n authorId,\r\n ])\r\n\r\n const onSubmit = () => {\r\n if (text.trim() === '') return\r\n setIsPlacing(true)\r\n setCursor('crosshair')\r\n }\r\n\r\n const inputEl = (\r\n <Input\r\n id={inputId}\r\n type=\"text\"\r\n value={text}\r\n onChange={e => setText(e.target.value)}\r\n placeholder={t('placeholder')}\r\n className={cn('cursor-pointer')}\r\n />\r\n )\r\n\r\n const submitButtonEl = (\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n onClick={onSubmit}\r\n className=\"cursor-pointer transition-transform duration-200 active:scale-90\"\r\n disabled={text.trim() === ''}\r\n >\r\n <LR.Plus className={cn('w-4 h-4', 'cursor-pointer transition-transform duration-200 active:scale-90')} />\r\n </Button>\r\n )\r\n\r\n const helpText =\r\n isPlacing\r\n ? (viewer === ViewerNames.map ? t('placeHelpTextMap') : t('placeHelpTextBim'))\r\n : null\r\n\r\n if (layout === 'dialog') {\r\n // When placing, return null so the map is fully interactive (component stays mounted for useEffect)\r\n if (isPlacing) return null\r\n\r\n return (\r\n <AddItemDialog\r\n open={isOpen}\r\n onOpenChange={open => !open && onCancel?.()}\r\n title={t('title')}\r\n icon={LR.MessageCircle}\r\n >\r\n <div className=\"flex flex-col gap-2 pointer-events-auto\">\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex flex-row gap-2\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n </div>\r\n </AddItemDialog>\r\n )\r\n }\r\n\r\n if (layout === 'card') {\r\n return (\r\n <Card className={cn('absolute bottom-10 left-0 bg-background shadow-md z-10 w-full')}>\r\n <CardHeader className=\"flex flex-row justify-between items-center pointer-events-auto py-0\">\r\n <CardTitle className=\"text-sm\">{t('title')}</CardTitle>\r\n {onCancel && (\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={onCancel}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <span className=\"sr-only\">{t('close')}</span>\r\n <LR.X size={18} />\r\n </Button>\r\n )}\r\n </CardHeader>\r\n <CardContent>\r\n <div className=\"flex flex-col gap-2 mt-2 pointer-events-auto\">\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex flex-row gap-2\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n {helpText && (\r\n <p className=\"text-sm text-foreground\">{helpText}</p>\r\n )}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n )\r\n }\r\n\r\n return (\r\n <div className={cn('flex flex-col gap-2 mt-2 pointer-events-auto')}>\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex items-center gap-1\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n {helpText && (\r\n <p className=\"text-sm text-foreground\">{helpText}</p>\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","_c","_d","_e"]}
1
+ {"version":3,"sources":["../../../../../src/core/components/ui/Comments/CommentInput.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as LR from 'lucide-react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as React from 'react'\r\nimport { toast } from 'sonner'\r\n\r\nimport { useCreateComment } from '../../../hooks/comments/comments'\r\nimport { AppConfigContext, MapContext, BuildingsContext, MenusContext, ToolsContext } from '../../../store'\r\nimport { ViewerNames } from '../../../types/dbTypes'\r\nimport { cn } from '../../../utils/utils'\r\nimport { AddItemDialog } from '../AddItemDialog'\r\nimport { Button } from '../Button'\r\nimport { Card, CardContent, CardHeader, CardTitle } from '../Card'\r\nimport { Input } from '../Input'\r\nimport { Label } from '../Label'\r\n\r\nimport type { Comment} from '../../../types/dbTypes';\r\n\r\nexport type CommentInputLayout = 'inline' | 'card' | 'dialog'\r\n\r\nexport type BimCommentPlacementContext = {\r\n world: any\r\n raycast: (data: { camera: any; mouse: any; dom: any }) => Promise<any>\r\n buildingId?: number\r\n setCursor?: (cursor: string) => void\r\n addPendingMarker?: (position: { x: number; y: number; z: number }) => number\r\n removePendingMarker?: (id: number) => void\r\n}\r\n\r\nexport type CommentInputProps = {\r\n viewer: ViewerNames\r\n layout?: CommentInputLayout\r\n onCancel?: () => void\r\n bim?: BimCommentPlacementContext\r\n isOpen?: boolean\r\n}\r\n\r\nexport function CommentInput({\r\n viewer,\r\n layout = 'inline',\r\n onCancel,\r\n bim,\r\n isOpen = false,\r\n}: CommentInputProps) {\r\n const t = useTranslations('CommentInput')\r\n const session = useSession()\r\n\r\n const user = useSession().data?.user\r\n\r\n const organizationId = user?.organizationId\r\n const authorId = session.data?.user?.id || -1\r\n\r\n const { state: appConfigState } = React.useContext(AppConfigContext)\r\n const mapContext = React.useContext(MapContext)\r\n\r\n const { state: buildingsState } = React.useContext(BuildingsContext)\r\n const buildingId = buildingsState?.buildings?.building?.id || -1\r\n\r\n const [text, setText] = React.useState('')\r\n const [isPlacing, setIsPlacing] = React.useState(false)\r\n\r\n const inputId = React.useId()\r\n const { createComment } = useCreateComment()\r\n\r\n const setCursor = React.useCallback((cursor: string) => {\r\n if (viewer === ViewerNames.map) {\r\n const map = mapContext?.state?.map?.map\r\n if (!map) return\r\n if (map.getCanvas().style.cursor === cursor) return\r\n map.getCanvas().style.cursor = cursor\r\n return\r\n }\r\n\r\n if (viewer === ViewerNames.bim) {\r\n bim?.setCursor?.(cursor)\r\n }\r\n }, [bim, mapContext, viewer])\r\n\r\n const reset = React.useCallback(() => {\r\n setIsPlacing(false)\r\n setText('')\r\n setCursor('')\r\n }, [setCursor])\r\n\r\n const onCreateComment = async (commentData: Partial<Comment>) => {\r\n const commentResult = await createComment({ commentData })\r\n reset()\r\n }\r\n\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { state: toolsState } = React.useContext(ToolsContext)\r\n const { currentToolId } = toolsState.tools\r\n const { commentsVisibleInViewer } = menusState.menus\r\n\r\n React.useEffect(() => {\r\n const viewerToShow = currentToolId === 'bim-add-comment'\r\n ? ViewerNames.bim\r\n : currentToolId === 'map-add-comment'\r\n ? ViewerNames.map\r\n : null\r\n\r\n if (!viewerToShow) return\r\n if (commentsVisibleInViewer.includes(viewerToShow)) return\r\n\r\n menusDispatch({\r\n type: 'SHOW_COMMENTS_IN_VIEWER',\r\n payload: { viewer: viewerToShow },\r\n })\r\n }, [currentToolId, commentsVisibleInViewer, menusDispatch])\r\n\r\n React.useEffect(() => {\r\n if (!isPlacing) return\r\n\r\n if (viewer === ViewerNames.map) {\r\n const map = mapContext?.state?.map?.map\r\n if (!map) return\r\n\r\n const mouseMoveCrosshairHandler = () => {\r\n setCursor('crosshair')\r\n }\r\n\r\n const dbClickAddCommentHandler = (e: any): void => {\r\n const longitude = e?.lngLat?.lng\r\n const latitude = e?.lngLat?.lat\r\n if (typeof longitude !== 'number' || typeof latitude !== 'number') return\r\n\r\n const elevation = map.queryTerrainElevation([latitude, longitude]) || 0\r\n\r\n const newComment = {\r\n authorId: Number(user?.id),\r\n organizationId,\r\n text,\r\n visible: true,\r\n longitude,\r\n latitude,\r\n elevation,\r\n viewer: ViewerNames.map,\r\n }\r\n onCreateComment(newComment)\r\n }\r\n\r\n map.on('mousemove', mouseMoveCrosshairHandler)\r\n map.on('dblclick', dbClickAddCommentHandler)\r\n\r\n return () => {\r\n setCursor('')\r\n map.off('mousemove', mouseMoveCrosshairHandler)\r\n map.off('dblclick', dbClickAddCommentHandler)\r\n }\r\n }\r\n\r\n\r\n if (viewer === ViewerNames.bim) {\r\n const world = bim?.world\r\n const raycast = bim?.raycast\r\n if (!world || !raycast) return\r\n\r\n let disposed = false\r\n let removeListeners: (() => void) | null = null\r\n\r\n ; (async () => {\r\n const THREE = await import('three')\r\n if (disposed) return\r\n\r\n const mouse = new THREE.Vector2()\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n }\r\n\r\n const handleDblClick = async (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n\r\n const result = await raycast({\r\n camera: world.camera?.three,\r\n mouse,\r\n dom: world.renderer?.three?.domElement,\r\n })\r\n\r\n if (!result?.point) return\r\n const p = result.point\r\n\r\n // Add pending marker immediately\r\n const pendingId = bim?.addPendingMarker?.({ x: p.x, y: p.y, z: p.z })\r\n\r\n const newComment = {\r\n authorId: Number(authorId),\r\n organizationId,\r\n text,\r\n x: p.x,\r\n y: p.y,\r\n z: p.z,\r\n visible: true,\r\n buildingId,\r\n viewer,\r\n }\r\n\r\n try {\r\n await onCreateComment(newComment)\r\n } finally {\r\n // Remove pending marker after creation completes (or fails)\r\n if (pendingId) {\r\n bim?.removePendingMarker?.(pendingId)\r\n }\r\n }\r\n // BIM flow historically closes the adding UI once the comment is placed.\r\n onCancel?.()\r\n }\r\n\r\n document.addEventListener('mousemove', handleMouseMove)\r\n document.addEventListener('dblclick', handleDblClick)\r\n\r\n removeListeners = () => {\r\n document.removeEventListener('mousemove', handleMouseMove)\r\n document.removeEventListener('dblclick', handleDblClick)\r\n }\r\n })()\r\n\r\n return () => {\r\n disposed = true\r\n setCursor('')\r\n removeListeners?.()\r\n }\r\n }\r\n }, [\r\n appConfigState,\r\n bim,\r\n isPlacing,\r\n mapContext,\r\n viewer,\r\n onCancel,\r\n reset,\r\n setCursor,\r\n text,\r\n authorId,\r\n ])\r\n\r\n const onSubmit = () => {\r\n if (text.trim() === '') return\r\n setIsPlacing(true)\r\n setCursor('crosshair')\r\n toast(viewer === ViewerNames.map ? t('placeHelpTextMap') : t('placeHelpTextBim'))\r\n }\r\n\r\n const inputEl = (\r\n <Input\r\n id={inputId}\r\n type=\"text\"\r\n value={text}\r\n onChange={e => setText(e.target.value)}\r\n placeholder={t('placeholder')}\r\n className={cn('cursor-pointer')}\r\n />\r\n )\r\n\r\n const submitButtonEl = (\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n onClick={onSubmit}\r\n className=\"cursor-pointer transition-transform duration-200 active:scale-90\"\r\n disabled={text.trim() === ''}\r\n >\r\n <LR.Plus className={cn('w-4 h-4', 'cursor-pointer transition-transform duration-200 active:scale-90')} />\r\n </Button>\r\n )\r\n\r\n const helpText =\r\n isPlacing\r\n ? (viewer === ViewerNames.map ? t('placeHelpTextMap') : t('placeHelpTextBim'))\r\n : (text.trim() !== '' ? t('clickPlusHint') : null)\r\n\r\n if (layout === 'dialog') {\r\n // When placing, return null so the map is fully interactive (component stays mounted for useEffect)\r\n if (isPlacing) return null\r\n\r\n return (\r\n <AddItemDialog\r\n open={isOpen}\r\n onOpenChange={open => !open && onCancel?.()}\r\n title={t('title')}\r\n icon={LR.MessageCircle}\r\n >\r\n <div className=\"flex flex-col gap-2 pointer-events-auto\">\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex flex-row gap-2\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n {helpText && (\r\n <p className=\"text-sm text-foreground\">{helpText}</p>\r\n )}\r\n </div>\r\n </AddItemDialog>\r\n )\r\n }\r\n\r\n if (layout === 'card') {\r\n return (\r\n <Card className={cn('absolute bottom-10 left-0 bg-background shadow-md z-10 w-full')}>\r\n <CardHeader className=\"flex flex-row justify-between items-center pointer-events-auto py-0\">\r\n <CardTitle className=\"text-sm\">{t('title')}</CardTitle>\r\n {onCancel && (\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={onCancel}\r\n className=\"opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <span className=\"sr-only\">{t('close')}</span>\r\n <LR.X size={18} />\r\n </Button>\r\n )}\r\n </CardHeader>\r\n <CardContent>\r\n <div className=\"flex flex-col gap-2 mt-2 pointer-events-auto\">\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex flex-row gap-2\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n {helpText && (\r\n <p className=\"text-sm text-foreground\">{helpText}</p>\r\n )}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n )\r\n }\r\n\r\n return (\r\n <div className={cn('flex flex-col gap-2 mt-2 pointer-events-auto')}>\r\n <Label htmlFor={inputId}>{t('label')}</Label>\r\n <div className=\"flex items-center gap-1\">\r\n {inputEl}\r\n {submitButtonEl}\r\n </div>\r\n {helpText && (\r\n <p className=\"text-sm text-foreground\">{helpText}</p>\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AA4PI,cAwCM,YAxCN;AAvPJ,YAAY,QAAQ;AACpB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,YAAY,WAAW;AACvB,SAAS,aAAa;AAEtB,SAAS,wBAAwB;AACjC,SAAS,kBAAkB,YAAY,kBAAkB,cAAc,oBAAoB;AAC3F,SAAS,mBAAmB;AAC5B,SAAS,UAAU;AACnB,SAAS,qBAAqB;AAC9B,SAAS,cAAc;AACvB,SAAS,MAAM,aAAa,YAAY,iBAAiB;AACzD,SAAS,aAAa;AACtB,SAAS,aAAa;AAuBf,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAsB;AAhDtB;AAiDE,QAAM,IAAI,gBAAgB,cAAc;AACxC,QAAM,UAAU,WAAW;AAE3B,QAAM,QAAO,gBAAW,EAAE,SAAb,mBAAmB;AAEhC,QAAM,iBAAiB,6BAAM;AAC7B,QAAM,aAAW,mBAAQ,SAAR,mBAAc,SAAd,mBAAoB,OAAM;AAE3C,QAAM,EAAE,OAAO,eAAe,IAAI,MAAM,WAAW,gBAAgB;AACnE,QAAM,aAAa,MAAM,WAAW,UAAU;AAE9C,QAAM,EAAE,OAAO,eAAe,IAAI,MAAM,WAAW,gBAAgB;AACnE,QAAM,eAAa,4DAAgB,cAAhB,mBAA2B,aAA3B,mBAAqC,OAAM;AAE9D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,EAAE;AACzC,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AAEtD,QAAM,UAAU,MAAM,MAAM;AAC5B,QAAM,EAAE,cAAc,IAAI,iBAAiB;AAE3C,QAAM,YAAY,MAAM,YAAY,CAAC,WAAmB;AArE1D,QAAAA,KAAAC,KAAAC;AAsEI,QAAI,WAAW,YAAY,KAAK;AAC9B,YAAM,OAAMD,OAAAD,MAAA,yCAAY,UAAZ,gBAAAA,IAAmB,QAAnB,gBAAAC,IAAwB;AACpC,UAAI,CAAC,IAAK;AACV,UAAI,IAAI,UAAU,EAAE,MAAM,WAAW,OAAQ;AAC7C,UAAI,UAAU,EAAE,MAAM,SAAS;AAC/B;AAAA,IACF;AAEA,QAAI,WAAW,YAAY,KAAK;AAC9B,OAAAC,MAAA,2BAAK,cAAL,gBAAAA,IAAA,UAAiB;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,KAAK,YAAY,MAAM,CAAC;AAE5B,QAAM,QAAQ,MAAM,YAAY,MAAM;AACpC,iBAAa,KAAK;AAClB,YAAQ,EAAE;AACV,cAAU,EAAE;AAAA,EACd,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,kBAAkB,OAAO,gBAAkC;AAC/D,UAAM,gBAAgB,MAAM,cAAc,EAAE,YAAY,CAAC;AACzD,UAAM;AAAA,EACR;AAEA,QAAM,EAAE,OAAO,YAAY,UAAU,cAAc,IAAI,MAAM,WAAW,YAAY;AACpF,QAAM,EAAE,OAAO,WAAW,IAAI,MAAM,WAAW,YAAY;AAC3D,QAAM,EAAE,cAAc,IAAI,WAAW;AACrC,QAAM,EAAE,wBAAwB,IAAI,WAAW;AAE/C,QAAM,UAAU,MAAM;AACpB,UAAM,eAAe,kBAAkB,oBACnC,YAAY,MACZ,kBAAkB,oBAChB,YAAY,MACZ;AAEN,QAAI,CAAC,aAAc;AACnB,QAAI,wBAAwB,SAAS,YAAY,EAAG;AAEpD,kBAAc;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,aAAa;AAAA,IAClC,CAAC;AAAA,EACH,GAAG,CAAC,eAAe,yBAAyB,aAAa,CAAC;AAE1D,QAAM,UAAU,MAAM;AAnHxB,QAAAF,KAAAC;AAoHI,QAAI,CAAC,UAAW;AAEhB,QAAI,WAAW,YAAY,KAAK;AAC9B,YAAM,OAAMA,OAAAD,MAAA,yCAAY,UAAZ,gBAAAA,IAAmB,QAAnB,gBAAAC,IAAwB;AACpC,UAAI,CAAC,IAAK;AAEV,YAAM,4BAA4B,MAAM;AACtC,kBAAU,WAAW;AAAA,MACvB;AAEA,YAAM,2BAA2B,CAAC,MAAiB;AA9HzD,YAAAD,KAAAC;AA+HQ,cAAM,aAAYD,MAAA,uBAAG,WAAH,gBAAAA,IAAW;AAC7B,cAAM,YAAWC,MAAA,uBAAG,WAAH,gBAAAA,IAAW;AAC5B,YAAI,OAAO,cAAc,YAAY,OAAO,aAAa,SAAU;AAEnE,cAAM,YAAY,IAAI,sBAAsB,CAAC,UAAU,SAAS,CAAC,KAAK;AAEtE,cAAM,aAAa;AAAA,UACjB,UAAU,OAAO,6BAAM,EAAE;AAAA,UACzB;AAAA,UACA;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,YAAY;AAAA,QACtB;AACA,wBAAgB,UAAU;AAAA,MAC5B;AAEA,UAAI,GAAG,aAAa,yBAAyB;AAC7C,UAAI,GAAG,YAAY,wBAAwB;AAE3C,aAAO,MAAM;AACX,kBAAU,EAAE;AACZ,YAAI,IAAI,aAAa,yBAAyB;AAC9C,YAAI,IAAI,YAAY,wBAAwB;AAAA,MAC9C;AAAA,IACF;AAGA,QAAI,WAAW,YAAY,KAAK;AAC9B,YAAM,QAAQ,2BAAK;AACnB,YAAM,UAAU,2BAAK;AACrB,UAAI,CAAC,SAAS,CAAC,QAAS;AAExB,UAAI,WAAW;AACf,UAAI,kBAAuC;AAEvC,OAAC,YAAY;AACb,cAAM,QAAQ,MAAM,OAAO,OAAO;AAClC,YAAI,SAAU;AAEd,cAAM,QAAQ,IAAI,MAAM,QAAQ;AAEhC,cAAM,kBAAkB,CAAC,MAAkB;AACzC,gBAAM,IAAI,EAAE;AACZ,gBAAM,IAAI,EAAE;AAAA,QACd;AAEA,cAAM,iBAAiB,OAAO,MAAkB;AAhL1D,cAAAD,KAAAC,KAAAC,KAAAC,KAAAC;AAiLY,gBAAM,IAAI,EAAE;AACZ,gBAAM,IAAI,EAAE;AAEZ,gBAAM,SAAS,MAAM,QAAQ;AAAA,YAC3B,SAAQJ,MAAA,MAAM,WAAN,gBAAAA,IAAc;AAAA,YACtB;AAAA,YACA,MAAKE,OAAAD,MAAA,MAAM,aAAN,gBAAAA,IAAgB,UAAhB,gBAAAC,IAAuB;AAAA,UAC9B,CAAC;AAED,cAAI,EAAC,iCAAQ,OAAO;AACpB,gBAAM,IAAI,OAAO;AAGjB,gBAAM,aAAYC,MAAA,2BAAK,qBAAL,gBAAAA,IAAA,UAAwB,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE;AAEnE,gBAAM,aAAa;AAAA,YACjB,UAAU,OAAO,QAAQ;AAAA,YACzB;AAAA,YACA;AAAA,YACA,GAAG,EAAE;AAAA,YACL,GAAG,EAAE;AAAA,YACL,GAAG,EAAE;AAAA,YACL,SAAS;AAAA,YACT;AAAA,YACA;AAAA,UACF;AAEA,cAAI;AACF,kBAAM,gBAAgB,UAAU;AAAA,UAClC,UAAE;AAEA,gBAAI,WAAW;AACb,eAAAC,MAAA,2BAAK,wBAAL,gBAAAA,IAAA,UAA2B;AAAA,YAC7B;AAAA,UACF;AAEA;AAAA,QACF;AAEA,iBAAS,iBAAiB,aAAa,eAAe;AACtD,iBAAS,iBAAiB,YAAY,cAAc;AAEpD,0BAAkB,MAAM;AACtB,mBAAS,oBAAoB,aAAa,eAAe;AACzD,mBAAS,oBAAoB,YAAY,cAAc;AAAA,QACzD;AAAA,MACF,GAAG;AAEL,aAAO,MAAM;AACX,mBAAW;AACX,kBAAU,EAAE;AACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM;AACrB,QAAI,KAAK,KAAK,MAAM,GAAI;AACxB,iBAAa,IAAI;AACjB,cAAU,WAAW;AACrB,UAAM,WAAW,YAAY,MAAM,EAAE,kBAAkB,IAAI,EAAE,kBAAkB,CAAC;AAAA,EAClF;AAEA,QAAM,UACJ;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,MAAK;AAAA,MACL,OAAO;AAAA,MACP,UAAU,OAAK,QAAQ,EAAE,OAAO,KAAK;AAAA,MACrC,aAAa,EAAE,aAAa;AAAA,MAC5B,WAAW,GAAG,gBAAgB;AAAA;AAAA,EAChC;AAGF,QAAM,iBACJ;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAU;AAAA,MACV,UAAU,KAAK,KAAK,MAAM;AAAA,MAE1B,8BAAC,GAAG,MAAH,EAAQ,WAAW,GAAG,WAAW,kEAAkE,GAAG;AAAA;AAAA,EACzG;AAGF,QAAM,WACJ,YACK,WAAW,YAAY,MAAM,EAAE,kBAAkB,IAAI,EAAE,kBAAkB,IACzE,KAAK,KAAK,MAAM,KAAK,EAAE,eAAe,IAAI;AAEjD,MAAI,WAAW,UAAU;AAEvB,QAAI,UAAW,QAAO;AAEtB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,cAAc,UAAQ,CAAC,SAAQ;AAAA,QAC/B,OAAO,EAAE,OAAO;AAAA,QAChB,MAAM,GAAG;AAAA,QAET,+BAAC,SAAI,WAAU,2CACb;AAAA,8BAAC,SAAM,SAAS,SAAU,YAAE,OAAO,GAAE;AAAA,UACrC,qBAAC,SAAI,WAAU,uBACZ;AAAA;AAAA,YACA;AAAA,aACH;AAAA,UACC,YACC,oBAAC,OAAE,WAAU,2BAA2B,oBAAS;AAAA,WAErD;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,MAAI,WAAW,QAAQ;AACrB,WACE,qBAAC,QAAK,WAAW,GAAG,+DAA+D,GACjF;AAAA,2BAAC,cAAW,WAAU,uEACpB;AAAA,4BAAC,aAAU,WAAU,WAAW,YAAE,OAAO,GAAE;AAAA,QAC1C,YACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS;AAAA,YACT,WAAU;AAAA,YAEV;AAAA,kCAAC,UAAK,WAAU,WAAW,YAAE,OAAO,GAAE;AAAA,cACtC,oBAAC,GAAG,GAAH,EAAK,MAAM,IAAI;AAAA;AAAA;AAAA,QAClB;AAAA,SAEJ;AAAA,MACA,oBAAC,eACC,+BAAC,SAAI,WAAU,gDACb;AAAA,4BAAC,SAAM,SAAS,SAAU,YAAE,OAAO,GAAE;AAAA,QACrC,qBAAC,SAAI,WAAU,uBACZ;AAAA;AAAA,UACA;AAAA,WACH;AAAA,QACC,YACC,oBAAC,OAAE,WAAU,2BAA2B,oBAAS;AAAA,SAErD,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,GAAG,8CAA8C,GAC/D;AAAA,wBAAC,SAAM,SAAS,SAAU,YAAE,OAAO,GAAE;AAAA,IACrC,qBAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,MACA;AAAA,OACH;AAAA,IACC,YACC,oBAAC,OAAE,WAAU,2BAA2B,oBAAS;AAAA,KAErD;AAEJ;","names":["_a","_b","_c","_d","_e"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CommentsSection.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CommentsSection.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,wBAAgB,eAAe,sBAsI9B"}
1
+ {"version":3,"file":"CommentsSection.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Comments/CommentsSection.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAiB9B,wBAAgB,eAAe,sBAwL9B"}