hale-commenting-system 2.0.2 → 2.0.4

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 (58) hide show
  1. package/README.md +16 -207
  2. package/bin/detect.d.ts +1 -0
  3. package/bin/detect.js +62 -0
  4. package/bin/generators.d.ts +18 -0
  5. package/bin/generators.js +193 -0
  6. package/bin/hale-commenting.js +4 -0
  7. package/bin/index.d.ts +2 -0
  8. package/bin/index.js +61 -0
  9. package/bin/onboarding.d.ts +1 -0
  10. package/bin/onboarding.js +170 -0
  11. package/bin/postinstall.d.ts +2 -0
  12. package/bin/postinstall.js +65 -0
  13. package/bin/validators.d.ts +2 -0
  14. package/bin/validators.js +66 -0
  15. package/dist/cli/detect.d.ts +1 -0
  16. package/dist/cli/detect.js +62 -0
  17. package/dist/cli/generators.d.ts +18 -0
  18. package/dist/cli/generators.js +193 -0
  19. package/dist/cli/index.d.ts +2 -0
  20. package/dist/cli/index.js +61 -0
  21. package/dist/cli/onboarding.d.ts +1 -0
  22. package/dist/cli/onboarding.js +170 -0
  23. package/dist/cli/postinstall.d.ts +2 -0
  24. package/dist/cli/postinstall.js +65 -0
  25. package/dist/cli/validators.d.ts +2 -0
  26. package/dist/cli/validators.js +66 -0
  27. package/dist/components/CommentOverlay.d.ts +2 -0
  28. package/dist/components/CommentOverlay.js +101 -0
  29. package/dist/components/CommentPanel.d.ts +6 -0
  30. package/dist/components/CommentPanel.js +334 -0
  31. package/dist/components/CommentPin.d.ts +11 -0
  32. package/dist/components/CommentPin.js +64 -0
  33. package/dist/components/DetailsTab.d.ts +2 -0
  34. package/dist/components/DetailsTab.js +380 -0
  35. package/dist/components/FloatingWidget.d.ts +8 -0
  36. package/dist/components/FloatingWidget.js +128 -0
  37. package/dist/components/JiraTab.d.ts +2 -0
  38. package/dist/components/JiraTab.js +507 -0
  39. package/dist/contexts/CommentContext.d.ts +30 -0
  40. package/dist/contexts/CommentContext.js +891 -0
  41. package/dist/contexts/GitHubAuthContext.d.ts +13 -0
  42. package/dist/contexts/GitHubAuthContext.js +96 -0
  43. package/dist/index.d.ts +10 -97
  44. package/dist/index.js +26 -789
  45. package/dist/services/githubAdapter.d.ts +56 -0
  46. package/dist/services/githubAdapter.js +321 -0
  47. package/dist/types/index.d.ts +25 -0
  48. package/dist/types/index.js +2 -0
  49. package/dist/utils/version.d.ts +1 -0
  50. package/dist/utils/version.js +23 -0
  51. package/package.json +39 -38
  52. package/templates/webpack-middleware.js +226 -0
  53. package/cli/dist/index.js +0 -370
  54. package/cli/dist/index.js.map +0 -1
  55. package/dist/index.d.mts +0 -97
  56. package/dist/index.js.map +0 -1
  57. package/dist/index.mjs +0 -762
  58. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CommentPanel = void 0;
37
+ const React = __importStar(require("react"));
38
+ const react_router_dom_1 = require("react-router-dom");
39
+ const react_core_1 = require("@patternfly/react-core");
40
+ const react_icons_1 = require("@patternfly/react-icons");
41
+ const CommentContext_1 = require("../contexts/CommentContext");
42
+ const DetailsTab_1 = require("./DetailsTab");
43
+ const JiraTab_1 = require("./JiraTab");
44
+ const FloatingWidget_1 = require("./FloatingWidget");
45
+ const version_1 = require("../utils/version");
46
+ const CommentPanel = ({ children }) => {
47
+ const { getThreadsForRoute, selectedThreadId, setSelectedThreadId, drawerPinnedOpen, setDrawerPinnedOpen, floatingWidgetMode, setFloatingWidgetMode, addReply, updateComment, deleteComment, closeThread, reopenThread, removePin, retrySync, } = (0, CommentContext_1.useComments)();
48
+ const location = (0, react_router_dom_1.useLocation)();
49
+ const detectedVersion = (0, version_1.getVersionFromPathOrQuery)(location.pathname, location.search);
50
+ const [newCommentText, setNewCommentText] = React.useState('');
51
+ const [replyingToCommentId, setReplyingToCommentId] = React.useState(null);
52
+ const [replyTextByCommentId, setReplyTextByCommentId] = React.useState({});
53
+ const [editingCommentId, setEditingCommentId] = React.useState(null);
54
+ const [editText, setEditText] = React.useState('');
55
+ const drawerRef = React.useRef(null);
56
+ const [activeTabKey, setActiveTabKey] = React.useState('comments');
57
+ const currentThreads = getThreadsForRoute(location.pathname, detectedVersion);
58
+ const selectedThread = currentThreads.find((t) => t.id === selectedThreadId);
59
+ const isExpanded = !!selectedThreadId || drawerPinnedOpen || floatingWidgetMode;
60
+ const onExpand = () => {
61
+ drawerRef.current && drawerRef.current.focus();
62
+ };
63
+ React.useEffect(() => {
64
+ if (selectedThreadId) {
65
+ setActiveTabKey('comments');
66
+ }
67
+ }, [selectedThreadId]);
68
+ React.useEffect(() => {
69
+ if (drawerPinnedOpen && !selectedThreadId) {
70
+ setActiveTabKey('details');
71
+ }
72
+ }, [drawerPinnedOpen, selectedThreadId]);
73
+ const handleAddComment = () => {
74
+ if (newCommentText.trim() && selectedThread) {
75
+ addReply(selectedThread.id, newCommentText.trim());
76
+ setNewCommentText('');
77
+ }
78
+ };
79
+ const handleStartReply = (commentId) => {
80
+ setReplyingToCommentId(commentId);
81
+ setReplyTextByCommentId((prev) => ({ ...prev, [commentId]: prev[commentId] ?? '' }));
82
+ };
83
+ const handleCancelReply = () => {
84
+ setReplyingToCommentId(null);
85
+ };
86
+ const handleSubmitReply = (parentCommentId) => {
87
+ if (!selectedThread)
88
+ return;
89
+ const text = (replyTextByCommentId[parentCommentId] || '').trim();
90
+ if (!text)
91
+ return;
92
+ addReply(selectedThread.id, text, parentCommentId);
93
+ setReplyTextByCommentId((prev) => ({ ...prev, [parentCommentId]: '' }));
94
+ setReplyingToCommentId(null);
95
+ };
96
+ const handleStartEdit = (commentId, currentText) => {
97
+ setEditingCommentId(commentId);
98
+ setEditText(currentText);
99
+ };
100
+ const handleSaveEdit = (commentId) => {
101
+ if (editText.trim() && selectedThread) {
102
+ updateComment(selectedThread.id, commentId, editText.trim());
103
+ setEditingCommentId(null);
104
+ setEditText('');
105
+ }
106
+ };
107
+ const handleCancelEdit = () => {
108
+ setEditingCommentId(null);
109
+ setEditText('');
110
+ };
111
+ const handleDeleteComment = (commentId) => {
112
+ if (selectedThread) {
113
+ deleteComment(selectedThread.id, commentId);
114
+ }
115
+ };
116
+ const handleCloseThread = () => {
117
+ if (selectedThread) {
118
+ closeThread(selectedThread.id);
119
+ }
120
+ };
121
+ const handleReopenThread = () => {
122
+ if (selectedThread) {
123
+ reopenThread(selectedThread.id);
124
+ }
125
+ };
126
+ const handleRemovePin = () => {
127
+ if (!selectedThread)
128
+ return;
129
+ removePin(selectedThread.id);
130
+ };
131
+ const handleClose = () => {
132
+ setSelectedThreadId(null);
133
+ if (floatingWidgetMode) {
134
+ setFloatingWidgetMode(false);
135
+ }
136
+ else {
137
+ setDrawerPinnedOpen(false);
138
+ }
139
+ setEditingCommentId(null);
140
+ setEditText('');
141
+ setNewCommentText('');
142
+ setReplyingToCommentId(null);
143
+ setReplyTextByCommentId({});
144
+ };
145
+ const formatCommentDate = (isoDate) => {
146
+ const date = new Date(isoDate);
147
+ return date.toLocaleString(undefined, {
148
+ month: 'short',
149
+ day: 'numeric',
150
+ hour: '2-digit',
151
+ minute: '2-digit',
152
+ });
153
+ };
154
+ const stripMarkersForDisplay = (text) => {
155
+ return text
156
+ .replace(/<!--\s*hale-reply-to:\d+\s*-->\s*\n?/g, '')
157
+ .replace(/<!--\s*hale-reply-to-local\s*-->\s*\n?/g, '')
158
+ .trimEnd();
159
+ };
160
+ const deriveStatus = () => {
161
+ if (!selectedThread)
162
+ return 'local';
163
+ if (selectedThread.syncStatus === 'error')
164
+ return 'error';
165
+ // If we have an issue and any comment hasn't synced yet, treat as pending.
166
+ if (selectedThread.issueNumber && selectedThread.comments.some((c) => !c.githubCommentId))
167
+ return 'pending';
168
+ if (selectedThread.issueNumber)
169
+ return 'synced';
170
+ return selectedThread.syncStatus || 'local';
171
+ };
172
+ const renderSyncLabel = (status) => {
173
+ switch (status) {
174
+ case 'synced':
175
+ return (React.createElement(react_core_1.Label, { color: "green", icon: React.createElement(react_icons_1.GithubIcon, null) }, "Synced"));
176
+ case 'local':
177
+ return React.createElement(react_core_1.Label, { color: "grey" }, "Local");
178
+ case 'pending':
179
+ return React.createElement(react_core_1.Label, { color: "blue" }, "Pending\u2026");
180
+ case 'syncing':
181
+ return (React.createElement(react_core_1.Label, { color: "blue", icon: React.createElement(react_core_1.Spinner, { size: "sm" }) }, "Syncing\u2026"));
182
+ case 'error':
183
+ return React.createElement(react_core_1.Label, { color: "red" }, "Sync error");
184
+ default:
185
+ return null;
186
+ }
187
+ };
188
+ const panelContent = (React.createElement(React.Fragment, null,
189
+ React.createElement(react_core_1.Tabs, { activeKey: activeTabKey, onSelect: (_event, tabKey) => setActiveTabKey(tabKey), "aria-label": "Hale Commenting System drawer tabs" },
190
+ React.createElement(react_core_1.Tab, { eventKey: "details", title: React.createElement(react_core_1.TabTitleText, null, "Details") },
191
+ React.createElement("div", { style: { paddingTop: '1rem' } },
192
+ React.createElement(DetailsTab_1.DetailsTab, null))),
193
+ React.createElement(react_core_1.Tab, { eventKey: "jira", title: React.createElement(react_core_1.TabTitleText, null, "Jira") },
194
+ React.createElement("div", { style: { paddingTop: '1rem' } },
195
+ React.createElement(JiraTab_1.JiraTab, null))),
196
+ React.createElement(react_core_1.Tab, { eventKey: "comments", title: React.createElement(react_core_1.TabTitleText, null, "Comments") },
197
+ React.createElement("div", { style: { paddingTop: '1rem' } }, !selectedThread ? (React.createElement(react_core_1.EmptyState, { icon: react_icons_1.InfoCircleIcon, titleText: "No pin selected", headingLevel: "h3" },
198
+ React.createElement(react_core_1.EmptyStateBody, null, "Select or create a comment pin to start a thread."))) : (React.createElement(React.Fragment, null,
199
+ React.createElement(react_core_1.Card, { style: { marginBottom: '1rem' } },
200
+ React.createElement(react_core_1.CardBody, null,
201
+ React.createElement("div", { style: { display: 'grid', gap: '0.5rem' } },
202
+ React.createElement("div", { style: { fontSize: '0.875rem' } },
203
+ React.createElement("strong", null, "Location:"),
204
+ " (",
205
+ selectedThread.xPercent.toFixed(1),
206
+ "%, ",
207
+ selectedThread.yPercent.toFixed(1),
208
+ "%)"),
209
+ React.createElement("div", { style: { fontSize: '0.875rem' } },
210
+ React.createElement("strong", null, "Comments:"),
211
+ " ",
212
+ selectedThread.comments.length),
213
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem', fontSize: '0.875rem' } },
214
+ React.createElement("strong", null, "Status:"),
215
+ renderSyncLabel(deriveStatus()) ?? React.createElement(react_core_1.Label, { color: "grey" }, "Local")),
216
+ React.createElement("div", { style: { fontSize: '0.875rem' } }, selectedThread.issueNumber && selectedThread.issueUrl ? (React.createElement("a", { href: selectedThread.issueUrl, target: "_blank", rel: "noopener noreferrer", style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem' } },
217
+ React.createElement(react_icons_1.GithubIcon, null),
218
+ "Issue #",
219
+ selectedThread.issueNumber,
220
+ React.createElement(react_icons_1.ExternalLinkAltIcon, { style: { fontSize: '0.75rem' } }))) : (React.createElement("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem', color: 'var(--pf-t--global--text--color--subtle)' } },
221
+ React.createElement(react_icons_1.GithubIcon, null),
222
+ "Issue pending\u2026"))),
223
+ React.createElement("div", null)))),
224
+ selectedThread.comments.length > 0 && (React.createElement("div", { style: { marginBottom: '1.5rem' } }, (() => {
225
+ const comments = selectedThread.comments;
226
+ const byId = new Map(comments.map((c) => [c.id, c]));
227
+ const byGitHubId = new Map();
228
+ for (const c of comments) {
229
+ if (c.githubCommentId)
230
+ byGitHubId.set(c.githubCommentId, c.id);
231
+ }
232
+ const childrenByParent = new Map();
233
+ const topLevel = [];
234
+ for (const c of comments) {
235
+ const parentLocal = c.parentCommentId ||
236
+ (c.parentGitHubCommentId ? byGitHubId.get(c.parentGitHubCommentId) : undefined);
237
+ if (parentLocal && byId.has(parentLocal)) {
238
+ const list = childrenByParent.get(parentLocal) || [];
239
+ list.push(c.id);
240
+ childrenByParent.set(parentLocal, list);
241
+ }
242
+ else {
243
+ topLevel.push(c.id);
244
+ }
245
+ }
246
+ const sortByCreatedAt = (aId, bId) => {
247
+ const a = byId.get(aId);
248
+ const b = byId.get(bId);
249
+ const at = a ? Date.parse(a.createdAt) : 0;
250
+ const bt = b ? Date.parse(b.createdAt) : 0;
251
+ return at - bt;
252
+ };
253
+ topLevel.sort(sortByCreatedAt);
254
+ childrenByParent.forEach((list, parentId) => {
255
+ list.sort(sortByCreatedAt);
256
+ childrenByParent.set(parentId, list);
257
+ });
258
+ const renderNode = (id, depth, topIndex) => {
259
+ const comment = byId.get(id);
260
+ if (!comment)
261
+ return null;
262
+ const isReply = depth > 0;
263
+ const title = isReply ? 'Reply' : `Comment #${(topIndex ?? 0) + 1}`;
264
+ const children = childrenByParent.get(id) || [];
265
+ return (React.createElement("div", { key: id, style: {
266
+ marginLeft: depth * 16,
267
+ marginTop: depth > 0 ? '8px' : undefined,
268
+ marginBottom: depth > 0 ? '8px' : '1rem',
269
+ } },
270
+ React.createElement(react_core_1.Card, null,
271
+ React.createElement(react_core_1.CardBody, { style: { position: 'relative' } },
272
+ React.createElement(react_core_1.Button, { variant: "plain", icon: React.createElement(react_icons_1.TrashIcon, null), isDanger: true, "aria-label": "Delete comment", title: "Delete comment", onClick: () => handleDeleteComment(comment.id), style: { position: 'absolute', top: '12px', right: '12px' } }),
273
+ React.createElement(react_core_1.Title, { headingLevel: "h3", size: isReply ? 'lg' : 'xl', style: { paddingRight: '2.5rem' } }, title),
274
+ React.createElement("div", { style: {
275
+ marginTop: '0.25rem',
276
+ fontSize: '0.875rem',
277
+ color: 'var(--pf-t--global--text--color--subtle)',
278
+ paddingRight: '2.5rem',
279
+ } },
280
+ "@",
281
+ comment.author ?? '—',
282
+ " \u00A0 ",
283
+ formatCommentDate(comment.createdAt)),
284
+ editingCommentId === comment.id ? (React.createElement("div", { style: { marginTop: '0.5rem' } },
285
+ React.createElement(react_core_1.TextArea, { value: editText, onChange: (_event, value) => setEditText(value), "aria-label": "Edit comment", rows: 3 }),
286
+ React.createElement(react_core_1.ActionList, { style: { marginTop: '0.5rem' } },
287
+ React.createElement(react_core_1.ActionListItem, null,
288
+ React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleSaveEdit(comment.id) }, "Save")),
289
+ React.createElement(react_core_1.ActionListItem, null,
290
+ React.createElement(react_core_1.Button, { variant: "link", onClick: handleCancelEdit }, "Cancel"))))) : (React.createElement("div", null,
291
+ React.createElement("div", { style: { marginTop: '0.75rem', whiteSpace: 'pre-wrap' } }, stripMarkersForDisplay(comment.text)),
292
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '0.5rem' } },
293
+ React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleStartReply(comment.id) }, "Reply"),
294
+ React.createElement(react_core_1.Button, { variant: "link", onClick: () => handleStartEdit(comment.id, stripMarkersForDisplay(comment.text)) }, "Edit")))),
295
+ replyingToCommentId === comment.id && (React.createElement("div", { style: { marginTop: '0.75rem' } },
296
+ React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md", style: { marginBottom: '0.5rem' } }, "Reply to this comment"),
297
+ React.createElement(react_core_1.TextArea, { value: replyTextByCommentId[comment.id] || '', onChange: (_event, value) => setReplyTextByCommentId((prev) => ({ ...prev, [comment.id]: value })), placeholder: "Type your reply...", "aria-label": "Reply to comment", rows: 3 }),
298
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '0.5rem' } },
299
+ React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleSubmitReply(comment.id), isDisabled: !(replyTextByCommentId[comment.id] || '').trim() }, "Post reply"),
300
+ React.createElement(react_core_1.Button, { variant: "link", onClick: handleCancelReply }, "Cancel")))))),
301
+ children.map((childId) => renderNode(childId, depth + 1))));
302
+ };
303
+ return React.createElement(React.Fragment, null, topLevel.map((id, idx) => renderNode(id, 0, idx)));
304
+ })())),
305
+ React.createElement("div", null, selectedThread.status === 'closed' ? (React.createElement("div", { style: { marginBottom: '1rem', padding: '1rem', backgroundColor: 'var(--pf-t--global--background--color--secondary--default)', borderRadius: 'var(--pf-t--global--border--radius--medium)' } },
306
+ React.createElement(react_core_1.Title, { headingLevel: "h3", size: "md", style: { marginBottom: '0.5rem' } }, "\uD83D\uDD12 Thread Closed"),
307
+ React.createElement("p", { style: { color: 'var(--pf-t--global--text--color--subtle)', marginBottom: '1rem' } }, "This thread has been closed and locked. Reopen it to add new comments."),
308
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' } },
309
+ React.createElement(react_core_1.Button, { variant: "primary", onClick: handleReopenThread }, "Reopen Thread"),
310
+ React.createElement(react_core_1.Button, { variant: "link", isDanger: true, onClick: handleRemovePin }, "Remove pin")))) : (React.createElement(React.Fragment, null,
311
+ React.createElement(react_core_1.Title, { headingLevel: "h3", size: "md", style: { marginBottom: '0.5rem' } }, "Add comment"),
312
+ React.createElement(react_core_1.TextArea, { value: newCommentText, onChange: (_event, value) => setNewCommentText(value), placeholder: "Type your comment...", "aria-label": "New comment", rows: 4 }),
313
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '1rem' } },
314
+ React.createElement(react_core_1.Button, { variant: "primary", onClick: handleAddComment, isDisabled: !newCommentText.trim() }, "Add Comment"),
315
+ React.createElement(react_core_1.Button, { variant: "secondary", onClick: handleCloseThread }, "Close Thread"),
316
+ React.createElement(react_core_1.Button, { variant: "link", isDanger: true, onClick: handleRemovePin }, "Remove pin"))))))))))));
317
+ if (floatingWidgetMode && isExpanded) {
318
+ return (React.createElement(React.Fragment, null,
319
+ React.createElement(FloatingWidget_1.FloatingWidget, { onClose: handleClose, title: "Hale Commenting System" },
320
+ React.createElement("div", { style: { padding: '1rem' } }, panelContent)),
321
+ React.createElement("div", { style: { position: 'relative' } }, children)));
322
+ }
323
+ const drawerPanelContent = isExpanded ? (React.createElement(react_core_1.DrawerPanelContent, { isResizable: true, defaultSize: '500px', minSize: '300px' },
324
+ React.createElement(react_core_1.DrawerHead, null,
325
+ React.createElement("span", { tabIndex: isExpanded ? 0 : -1, ref: drawerRef },
326
+ React.createElement(react_core_1.Title, { headingLevel: "h2", size: "lg" }, "Hale Commenting System")),
327
+ React.createElement(react_core_1.DrawerActions, null,
328
+ React.createElement(react_core_1.DrawerCloseButton, { onClick: handleClose }))),
329
+ React.createElement(react_core_1.DrawerPanelBody, null, panelContent))) : null;
330
+ return (React.createElement(react_core_1.Drawer, { isExpanded: isExpanded, isInline: true, onExpand: onExpand },
331
+ React.createElement(react_core_1.DrawerContent, { panelContent: drawerPanelContent },
332
+ React.createElement(react_core_1.DrawerContentBody, { style: { position: 'relative' } }, children))));
333
+ };
334
+ exports.CommentPanel = CommentPanel;
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ interface CommentPinProps {
3
+ xPercent: number;
4
+ yPercent: number;
5
+ commentCount: number;
6
+ isClosed?: boolean;
7
+ isSelected: boolean;
8
+ onClick: () => void;
9
+ }
10
+ export declare const CommentPin: React.FunctionComponent<CommentPinProps>;
11
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CommentPin = void 0;
37
+ const React = __importStar(require("react"));
38
+ const react_core_1 = require("@patternfly/react-core");
39
+ const react_icons_1 = require("@patternfly/react-icons");
40
+ const CommentPin = ({ xPercent, yPercent, commentCount, isClosed = false, isSelected, onClick, }) => {
41
+ return (React.createElement(react_core_1.Button, { variant: "plain", "data-comment-pin": true, style: {
42
+ position: 'absolute',
43
+ left: `${xPercent}%`,
44
+ top: `${yPercent}%`,
45
+ transform: 'translate(-50%, -50%)',
46
+ width: '32px',
47
+ height: '32px',
48
+ borderRadius: '50%',
49
+ backgroundColor: isClosed ? 'var(--pf-t--global--icon--color--subtle)' : '#C9190B',
50
+ color: 'white',
51
+ border: isSelected ? '3px solid #0066CC' : '2px solid white',
52
+ boxShadow: isSelected
53
+ ? '0 0 0 3px rgba(0, 102, 204, 0.3), 0 2px 8px rgba(0,0,0,0.3)'
54
+ : '0 2px 8px rgba(0,0,0,0.3)',
55
+ cursor: 'pointer',
56
+ padding: 0,
57
+ display: 'flex',
58
+ alignItems: 'center',
59
+ justifyContent: 'center',
60
+ transition: 'all 0.2s ease',
61
+ pointerEvents: 'auto',
62
+ }, onClick: onClick, "aria-label": `${isClosed ? 'Closed ' : ''}comment thread with ${commentCount} comment${commentCount !== 1 ? 's' : ''}` }, commentCount === 0 ? (React.createElement(react_icons_1.CommentIcon, { style: { fontSize: '16px' } })) : commentCount === 1 ? (React.createElement(react_icons_1.CommentIcon, { style: { fontSize: '16px' } })) : (React.createElement("span", { style: { fontSize: '14px', fontWeight: 'bold' } }, commentCount))));
63
+ };
64
+ exports.CommentPin = CommentPin;
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare const DetailsTab: React.FunctionComponent;