@flanksource/clicky-ui 0.3.30 → 0.3.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comments/CommentCard.cjs +156 -273
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts +5 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +151 -268
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +115 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -0
- package/dist/comments/CommentCardParts.d.ts +21 -0
- package/dist/comments/CommentCardParts.d.ts.map +1 -0
- package/dist/comments/CommentCardParts.js +115 -0
- package/dist/comments/CommentCardParts.js.map +1 -0
- package/dist/comments/CommentProvider.cjs +3 -0
- package/dist/comments/CommentProvider.cjs.map +1 -1
- package/dist/comments/CommentProvider.d.ts +1 -1
- package/dist/comments/CommentProvider.d.ts.map +1 -1
- package/dist/comments/CommentProvider.js +3 -0
- package/dist/comments/CommentProvider.js.map +1 -1
- package/dist/comments/CommentSidePanel.cjs +55 -22
- package/dist/comments/CommentSidePanel.cjs.map +1 -1
- package/dist/comments/CommentSidePanel.d.ts +3 -1
- package/dist/comments/CommentSidePanel.d.ts.map +1 -1
- package/dist/comments/CommentSidePanel.js +56 -23
- package/dist/comments/CommentSidePanel.js.map +1 -1
- package/dist/comments/CommentThread.cjs +2 -0
- package/dist/comments/CommentThread.cjs.map +1 -1
- package/dist/comments/CommentThread.d.ts +2 -1
- package/dist/comments/CommentThread.d.ts.map +1 -1
- package/dist/comments/CommentThread.js +2 -0
- package/dist/comments/CommentThread.js.map +1 -1
- package/dist/comments/CommentThreadList.cjs +52 -34
- package/dist/comments/CommentThreadList.cjs.map +1 -1
- package/dist/comments/CommentThreadList.d.ts +5 -2
- package/dist/comments/CommentThreadList.d.ts.map +1 -1
- package/dist/comments/CommentThreadList.js +52 -34
- package/dist/comments/CommentThreadList.js.map +1 -1
- package/dist/comments/comment-types.cjs +16 -4
- package/dist/comments/comment-types.cjs.map +1 -1
- package/dist/comments/comment-types.d.ts +11 -1
- package/dist/comments/comment-types.d.ts.map +1 -1
- package/dist/comments/comment-types.js +16 -4
- package/dist/comments/comment-types.js.map +1 -1
- package/dist/comments/comment-utils.cjs +31 -1
- package/dist/comments/comment-utils.cjs.map +1 -1
- package/dist/comments/comment-utils.d.ts +9 -2
- package/dist/comments/comment-utils.d.ts.map +1 -1
- package/dist/comments/comment-utils.js +31 -1
- package/dist/comments/comment-utils.js.map +1 -1
- package/dist/comments.cjs +3 -0
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.js +4 -1
- package/dist/components/ComboboxMenu.cjs +4 -1
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +5 -2
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxTags.cjs +5 -1
- package/dist/components/ComboboxTags.cjs.map +1 -1
- package/dist/components/ComboboxTags.d.ts.map +1 -1
- package/dist/components/ComboboxTags.js +6 -2
- package/dist/components/ComboboxTags.js.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.cjs +24 -35
- package/dist/components/ConnectionLoggingPolicy.cjs.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.d.ts.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.js +24 -35
- package/dist/components/ConnectionLoggingPolicy.js.map +1 -1
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts +7 -0
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/filter-bar-multi.cjs +10 -1
- package/dist/components/filter-bar-multi.cjs.map +1 -1
- package/dist/components/filter-bar-multi.d.ts.map +1 -1
- package/dist/components/filter-bar-multi.js +11 -2
- package/dist/components/filter-bar-multi.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +23 -8
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +8 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +23 -8
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +9 -1
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +9 -1
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +24 -2
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +25 -3
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.cjs +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.js +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +6 -4
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +10 -1
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +6 -4
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/test-runner/status.cjs +1 -1
- package/dist/data/test-runner/status.cjs.map +1 -1
- package/dist/data/test-runner/status.js +1 -1
- package/dist/data/test-runner/status.js.map +1 -1
- package/dist/data/test-runner/types.d.ts +6 -0
- package/dist/data/test-runner/types.d.ts.map +1 -1
- package/dist/data/verification/VerificationResults.cjs +99 -0
- package/dist/data/verification/VerificationResults.cjs.map +1 -0
- package/dist/data/verification/VerificationResults.d.ts +27 -0
- package/dist/data/verification/VerificationResults.d.ts.map +1 -0
- package/dist/data/verification/VerificationResults.js +99 -0
- package/dist/data/verification/VerificationResults.js.map +1 -0
- package/dist/data/verification/adapterViews.cjs +116 -0
- package/dist/data/verification/adapterViews.cjs.map +1 -0
- package/dist/data/verification/adapterViews.d.ts +13 -0
- package/dist/data/verification/adapterViews.d.ts.map +1 -0
- package/dist/data/verification/adapterViews.js +116 -0
- package/dist/data/verification/adapterViews.js.map +1 -0
- package/dist/data/verification/adapters.cjs +26 -0
- package/dist/data/verification/adapters.cjs.map +1 -0
- package/dist/data/verification/adapters.d.ts +6 -0
- package/dist/data/verification/adapters.d.ts.map +1 -0
- package/dist/data/verification/adapters.js +26 -0
- package/dist/data/verification/adapters.js.map +1 -0
- package/dist/data/verification/index.d.ts +5 -0
- package/dist/data/verification/index.d.ts.map +1 -0
- package/dist/data/verification/verify-report.cjs +58 -0
- package/dist/data/verification/verify-report.cjs.map +1 -0
- package/dist/data/verification/verify-report.d.ts +96 -0
- package/dist/data/verification/verify-report.d.ts.map +1 -0
- package/dist/data/verification/verify-report.js +58 -0
- package/dist/data/verification/verify-report.js.map +1 -0
- package/dist/data/verification/verifyReportTests.cjs +84 -0
- package/dist/data/verification/verifyReportTests.cjs.map +1 -0
- package/dist/data/verification/verifyReportTests.d.ts +13 -0
- package/dist/data/verification/verifyReportTests.d.ts.map +1 -0
- package/dist/data/verification/verifyReportTests.js +84 -0
- package/dist/data/verification/verifyReportTests.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +10 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +10 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const Badge = require("../data/Badge.cjs");
|
|
5
|
+
const utils = require("../lib/utils.cjs");
|
|
6
|
+
const commentUtils = require("./comment-utils.cjs");
|
|
7
|
+
const UiThumbsUp = require("../icons/components/UiThumbsUp.cjs");
|
|
8
|
+
const UiThumbsDown = require("../icons/components/UiThumbsDown.cjs");
|
|
9
|
+
function RatingChip({ rating }) {
|
|
10
|
+
if (!rating) return null;
|
|
11
|
+
const positive = rating === "positive";
|
|
12
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13
|
+
Badge.Badge,
|
|
14
|
+
{
|
|
15
|
+
variant: "soft",
|
|
16
|
+
tone: positive ? "success" : "danger",
|
|
17
|
+
size: "xs",
|
|
18
|
+
icon: positive ? UiThumbsUp.UiThumbsUp : UiThumbsDown.UiThumbsDown,
|
|
19
|
+
children: positive ? "Positive rating" : "Negative rating"
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
function StatusChip({
|
|
24
|
+
comment,
|
|
25
|
+
config
|
|
26
|
+
}) {
|
|
27
|
+
const status = commentUtils.resolveStatusConfig(config, comment.status);
|
|
28
|
+
if (!status) return null;
|
|
29
|
+
const closedBy = status.stage === "closed" ? comment.closedBy : void 0;
|
|
30
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31
|
+
Badge.Badge,
|
|
32
|
+
{
|
|
33
|
+
variant: "soft",
|
|
34
|
+
tone: commentUtils.toneToBadgeTone(status.tone),
|
|
35
|
+
size: "xs",
|
|
36
|
+
...status.icon ? { icon: status.icon } : {},
|
|
37
|
+
...comment.closedAt ? { title: new Date(comment.closedAt).toLocaleString() } : {},
|
|
38
|
+
children: closedBy ? `Closed by ${closedBy.name}` : status.label
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function FacetBadges({
|
|
43
|
+
comment,
|
|
44
|
+
config,
|
|
45
|
+
compact
|
|
46
|
+
}) {
|
|
47
|
+
const chips = (config.facets ?? []).flatMap((facet) => {
|
|
48
|
+
var _a;
|
|
49
|
+
const option = commentUtils.resolveFacetOption(facet, (_a = comment.facets) == null ? void 0 : _a[facet.key]);
|
|
50
|
+
if (!option) return [];
|
|
51
|
+
return [
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
Badge.Badge,
|
|
54
|
+
{
|
|
55
|
+
variant: "soft",
|
|
56
|
+
tone: commentUtils.toneToBadgeTone(option.tone),
|
|
57
|
+
size: "xs",
|
|
58
|
+
children: compact ? option.short ?? option.label : option.label
|
|
59
|
+
},
|
|
60
|
+
facet.key
|
|
61
|
+
)
|
|
62
|
+
];
|
|
63
|
+
});
|
|
64
|
+
return chips.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: chips }) : null;
|
|
65
|
+
}
|
|
66
|
+
function ChecklistChips({
|
|
67
|
+
comment,
|
|
68
|
+
onChecklistToggle
|
|
69
|
+
}) {
|
|
70
|
+
var _a;
|
|
71
|
+
if (!((_a = comment.checklist) == null ? void 0 : _a.length)) return null;
|
|
72
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: comment.checklist.map((item, index) => {
|
|
73
|
+
const done = /done|complete|resolved/i.test(item.status);
|
|
74
|
+
const active = /progress|doing/i.test(item.status);
|
|
75
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
76
|
+
"button",
|
|
77
|
+
{
|
|
78
|
+
type: "button",
|
|
79
|
+
onClick: () => onChecklistToggle == null ? void 0 : onChecklistToggle(index),
|
|
80
|
+
disabled: !onChecklistToggle,
|
|
81
|
+
className: utils.cn(
|
|
82
|
+
"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity",
|
|
83
|
+
onChecklistToggle && "cursor-pointer hover:opacity-80",
|
|
84
|
+
done ? "bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300" : active ? "bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300" : "bg-muted text-muted-foreground"
|
|
85
|
+
),
|
|
86
|
+
children: item.label
|
|
87
|
+
},
|
|
88
|
+
index
|
|
89
|
+
);
|
|
90
|
+
}) });
|
|
91
|
+
}
|
|
92
|
+
function RefChips({ comment }) {
|
|
93
|
+
var _a;
|
|
94
|
+
if (!((_a = comment.refs) == null ? void 0 : _a.length)) return null;
|
|
95
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5", children: comment.refs.map((group, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
96
|
+
"span",
|
|
97
|
+
{
|
|
98
|
+
className: "inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground",
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
101
|
+
group.label,
|
|
102
|
+
":"
|
|
103
|
+
] }),
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: group.mono ? "font-mono" : void 0, children: group.items.join(", ") })
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
index
|
|
108
|
+
)) });
|
|
109
|
+
}
|
|
110
|
+
exports.ChecklistChips = ChecklistChips;
|
|
111
|
+
exports.FacetBadges = FacetBadges;
|
|
112
|
+
exports.RatingChip = RatingChip;
|
|
113
|
+
exports.RefChips = RefChips;
|
|
114
|
+
exports.StatusChip = StatusChip;
|
|
115
|
+
//# sourceMappingURL=CommentCardParts.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentCardParts.cjs","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport type { Comment, CommentConfig, CommentRating } from \"./comment-types\";\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy = status.stage === \"closed\" ? comment.closedBy : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":["jsx","Badge","UiThumbsUp","UiThumbsDown","resolveStatusConfig","toneToBadgeTone","resolveFacetOption","Fragment","cn","jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Comment, CommentConfig, CommentRating } from './comment-types';
|
|
2
|
+
export declare function RatingChip({ rating }: {
|
|
3
|
+
rating: CommentRating | undefined;
|
|
4
|
+
}): import("react").JSX.Element | null;
|
|
5
|
+
export declare function StatusChip({ comment, config, }: {
|
|
6
|
+
comment: Comment;
|
|
7
|
+
config: CommentConfig;
|
|
8
|
+
}): import("react").JSX.Element | null;
|
|
9
|
+
export declare function FacetBadges({ comment, config, compact, }: {
|
|
10
|
+
comment: Comment;
|
|
11
|
+
config: CommentConfig;
|
|
12
|
+
compact?: boolean;
|
|
13
|
+
}): import("react").JSX.Element | null;
|
|
14
|
+
export declare function ChecklistChips({ comment, onChecklistToggle, }: {
|
|
15
|
+
comment: Comment;
|
|
16
|
+
onChecklistToggle?: (index: number) => void;
|
|
17
|
+
}): import("react").JSX.Element | null;
|
|
18
|
+
export declare function RefChips({ comment }: {
|
|
19
|
+
comment: Comment;
|
|
20
|
+
}): import("react").JSX.Element | null;
|
|
21
|
+
//# sourceMappingURL=CommentCardParts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentCardParts.d.ts","sourceRoot":"","sources":["../../src/comments/CommentCardParts.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE7E,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,sCAa3E;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,MAAM,GACP,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB,sCAiBA;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,MAAM,EACN,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,sCAgBA;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,iBAAiB,GAClB,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C,sCA6BA;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,sCAiBzD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from "../data/Badge.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { resolveStatusConfig, toneToBadgeTone, resolveFacetOption } from "./comment-utils.js";
|
|
5
|
+
import { UiThumbsUp } from "../icons/components/UiThumbsUp.js";
|
|
6
|
+
import { UiThumbsDown } from "../icons/components/UiThumbsDown.js";
|
|
7
|
+
function RatingChip({ rating }) {
|
|
8
|
+
if (!rating) return null;
|
|
9
|
+
const positive = rating === "positive";
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
Badge,
|
|
12
|
+
{
|
|
13
|
+
variant: "soft",
|
|
14
|
+
tone: positive ? "success" : "danger",
|
|
15
|
+
size: "xs",
|
|
16
|
+
icon: positive ? UiThumbsUp : UiThumbsDown,
|
|
17
|
+
children: positive ? "Positive rating" : "Negative rating"
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function StatusChip({
|
|
22
|
+
comment,
|
|
23
|
+
config
|
|
24
|
+
}) {
|
|
25
|
+
const status = resolveStatusConfig(config, comment.status);
|
|
26
|
+
if (!status) return null;
|
|
27
|
+
const closedBy = status.stage === "closed" ? comment.closedBy : void 0;
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
Badge,
|
|
30
|
+
{
|
|
31
|
+
variant: "soft",
|
|
32
|
+
tone: toneToBadgeTone(status.tone),
|
|
33
|
+
size: "xs",
|
|
34
|
+
...status.icon ? { icon: status.icon } : {},
|
|
35
|
+
...comment.closedAt ? { title: new Date(comment.closedAt).toLocaleString() } : {},
|
|
36
|
+
children: closedBy ? `Closed by ${closedBy.name}` : status.label
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function FacetBadges({
|
|
41
|
+
comment,
|
|
42
|
+
config,
|
|
43
|
+
compact
|
|
44
|
+
}) {
|
|
45
|
+
const chips = (config.facets ?? []).flatMap((facet) => {
|
|
46
|
+
var _a;
|
|
47
|
+
const option = resolveFacetOption(facet, (_a = comment.facets) == null ? void 0 : _a[facet.key]);
|
|
48
|
+
if (!option) return [];
|
|
49
|
+
return [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Badge,
|
|
52
|
+
{
|
|
53
|
+
variant: "soft",
|
|
54
|
+
tone: toneToBadgeTone(option.tone),
|
|
55
|
+
size: "xs",
|
|
56
|
+
children: compact ? option.short ?? option.label : option.label
|
|
57
|
+
},
|
|
58
|
+
facet.key
|
|
59
|
+
)
|
|
60
|
+
];
|
|
61
|
+
});
|
|
62
|
+
return chips.length > 0 ? /* @__PURE__ */ jsx(Fragment, { children: chips }) : null;
|
|
63
|
+
}
|
|
64
|
+
function ChecklistChips({
|
|
65
|
+
comment,
|
|
66
|
+
onChecklistToggle
|
|
67
|
+
}) {
|
|
68
|
+
var _a;
|
|
69
|
+
if (!((_a = comment.checklist) == null ? void 0 : _a.length)) return null;
|
|
70
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: comment.checklist.map((item, index) => {
|
|
71
|
+
const done = /done|complete|resolved/i.test(item.status);
|
|
72
|
+
const active = /progress|doing/i.test(item.status);
|
|
73
|
+
return /* @__PURE__ */ jsx(
|
|
74
|
+
"button",
|
|
75
|
+
{
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: () => onChecklistToggle == null ? void 0 : onChecklistToggle(index),
|
|
78
|
+
disabled: !onChecklistToggle,
|
|
79
|
+
className: cn(
|
|
80
|
+
"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity",
|
|
81
|
+
onChecklistToggle && "cursor-pointer hover:opacity-80",
|
|
82
|
+
done ? "bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300" : active ? "bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300" : "bg-muted text-muted-foreground"
|
|
83
|
+
),
|
|
84
|
+
children: item.label
|
|
85
|
+
},
|
|
86
|
+
index
|
|
87
|
+
);
|
|
88
|
+
}) });
|
|
89
|
+
}
|
|
90
|
+
function RefChips({ comment }) {
|
|
91
|
+
var _a;
|
|
92
|
+
if (!((_a = comment.refs) == null ? void 0 : _a.length)) return null;
|
|
93
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: comment.refs.map((group, index) => /* @__PURE__ */ jsxs(
|
|
94
|
+
"span",
|
|
95
|
+
{
|
|
96
|
+
className: "inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground",
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
99
|
+
group.label,
|
|
100
|
+
":"
|
|
101
|
+
] }),
|
|
102
|
+
/* @__PURE__ */ jsx("span", { className: group.mono ? "font-mono" : void 0, children: group.items.join(", ") })
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
index
|
|
106
|
+
)) });
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
ChecklistChips,
|
|
110
|
+
FacetBadges,
|
|
111
|
+
RatingChip,
|
|
112
|
+
RefChips,
|
|
113
|
+
StatusChip
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=CommentCardParts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommentCardParts.js","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport type { Comment, CommentConfig, CommentRating } from \"./comment-types\";\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy = status.stage === \"closed\" ? comment.closedBy : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ function CommentProvider({
|
|
|
13
13
|
onCreate,
|
|
14
14
|
onReply,
|
|
15
15
|
onUpdateStatus,
|
|
16
|
+
onClose,
|
|
16
17
|
onUpdateRating,
|
|
17
18
|
onDelete,
|
|
18
19
|
onChecklistToggle,
|
|
@@ -113,6 +114,7 @@ function CommentProvider({
|
|
|
113
114
|
...onCreate ? { onCreate } : {},
|
|
114
115
|
...onReply ? { onReply } : {},
|
|
115
116
|
...onUpdateStatus ? { onUpdateStatus } : {},
|
|
117
|
+
...onClose ? { onClose } : {},
|
|
116
118
|
...onUpdateRating ? { onUpdateRating } : {},
|
|
117
119
|
...onDelete ? { onDelete } : {},
|
|
118
120
|
...onChecklistToggle ? { onChecklistToggle } : {},
|
|
@@ -122,6 +124,7 @@ function CommentProvider({
|
|
|
122
124
|
onCreate,
|
|
123
125
|
onReply,
|
|
124
126
|
onUpdateStatus,
|
|
127
|
+
onClose,
|
|
125
128
|
onUpdateRating,
|
|
126
129
|
onDelete,
|
|
127
130
|
onChecklistToggle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentProvider.cjs","sources":["../../src/comments/CommentProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { deriveAnchorCounts, deriveAnchorMeta } from \"./comment-utils\";\nimport {\n CommentContext,\n CommentAnchorActionsContext,\n CommentAnchorStoreContext,\n createCommentAnchorStore,\n exactAnchorResolver,\n type AnchorResolver,\n type CommentAnchorActions,\n type CommentContextValue,\n type CommentRailMode,\n type CommentScrollOptions,\n} from \"./comment-context\";\nimport {\n type Comment,\n type CommentAnchor,\n type CommentCallbacks,\n type CommentConfig,\n} from \"./comment-types\";\n\nexport type CommentProviderProps = CommentCallbacks & {\n children: ReactNode;\n /** All comments for the document; counts and metadata are derived from these. */\n comments: Comment[];\n config: CommentConfig;\n /** Strategy to map a requested anchor onto a registered one. Defaults to exact. */\n resolveAnchor?: AnchorResolver;\n /** Reports rail actions so a host can synchronize external visibility state. */\n onRailModeChange?: (mode: CommentRailMode) => void;\n /**\n * Rail mode on mount. Use \"all\" where the host already decided the rail is\n * visible, so the reader is not asked to open it a second time.\n */\n initialRailMode?: CommentRailMode;\n};\n\n/**\n * Supplies comment state to a document subtree: derived per-anchor counts and\n * metadata, rail open/focus state, and a generic anchor registry (cells call\n * `registerAnchor` so the side panel can scroll-align to them). Owns no\n * fetching — `comments` and the callbacks are controlled by the consumer.\n */\nexport function CommentProvider({\n children,\n comments,\n config,\n resolveAnchor = exactAnchorResolver,\n onRailModeChange,\n onCreate,\n onReply,\n onUpdateStatus,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n initialRailMode = \"closed\",\n}: CommentProviderProps) {\n const [railMode, setRailMode] = useState<CommentRailMode>(initialRailMode);\n const [focusedAnchor, setFocusedAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const [highlightAnchor, setHighlightAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const railModeRef = useRef<CommentRailMode>(initialRailMode);\n const onRailModeChangeRef = useRef(onRailModeChange);\n const resolveAnchorRef = useRef(resolveAnchor);\n const anchorEls = useRef<Record<string, HTMLElement>>({});\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const commentCounts = useMemo(() => deriveAnchorCounts(comments), [comments]);\n const commentMeta = useMemo(() => deriveAnchorMeta(comments), [comments]);\n const [anchorStore] = useState(createCommentAnchorStore);\n\n useLayoutEffect(() => {\n onRailModeChangeRef.current = onRailModeChange;\n resolveAnchorRef.current = resolveAnchor;\n }, [onRailModeChange, resolveAnchor]);\n\n const focusAnchor = useCallback((anchor: CommentAnchor) => {\n setFocusedAnchor(anchor);\n railModeRef.current = \"focused\";\n setRailMode(\"focused\");\n onRailModeChangeRef.current?.(\"focused\");\n }, []);\n\n const openCommentList = useCallback(() => {\n const next = railModeRef.current === \"all\" ? \"closed\" : \"all\";\n railModeRef.current = next;\n setRailMode(next);\n onRailModeChangeRef.current?.(next);\n }, []);\n\n const closeRail = useCallback(() => {\n railModeRef.current = \"closed\";\n setRailMode(\"closed\");\n onRailModeChangeRef.current?.(\"closed\");\n }, []);\n\n const registerAnchor = useCallback(\n (anchor: CommentAnchor, el: HTMLElement | null) => {\n if (!el) {\n delete anchorEls.current[anchor];\n return;\n }\n const registered = anchorEls.current[anchor];\n if (registered && registered !== el) {\n throw new Error(\n `Comment anchor \"${anchor}\" is registered by multiple elements`,\n );\n }\n anchorEls.current[anchor] = el;\n },\n [],\n );\n\n const getAnchorTop = useCallback((anchor: CommentAnchor): number | null => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return null;\n return (\n el.getBoundingClientRect().top - container.getBoundingClientRect().top\n );\n }, []);\n\n const scrollToAnchor = useCallback(\n (anchor: CommentAnchor, options: CommentScrollOptions = {}): boolean => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return false;\n const containerRect = container.getBoundingClientRect();\n const anchorRect = el.getBoundingClientRect();\n const offset = options.offset ?? 0;\n const top =\n options.block === \"center\"\n ? container.scrollTop +\n anchorRect.top -\n containerRect.top +\n anchorRect.height / 2 -\n container.clientHeight / 2 -\n offset\n : container.scrollTop + anchorRect.top - containerRect.top - offset;\n container.scrollTo({\n top: Math.max(0, top),\n behavior: options.behavior ?? \"smooth\",\n });\n return true;\n },\n [],\n );\n\n // A focused rail with no anchor selected has nothing to show.\n useEffect(() => {\n if (railMode === \"focused\" && !focusedAnchor) closeRail();\n }, [closeRail, railMode, focusedAnchor]);\n\n const callbacks = useMemo<CommentCallbacks>(\n () => ({\n ...(onCreate ? { onCreate } : {}),\n ...(onReply ? { onReply } : {}),\n ...(onUpdateStatus ? { onUpdateStatus } : {}),\n ...(onUpdateRating ? { onUpdateRating } : {}),\n ...(onDelete ? { onDelete } : {}),\n ...(onChecklistToggle ? { onChecklistToggle } : {}),\n ...(onMention ? { onMention } : {}),\n }),\n [\n onCreate,\n onReply,\n onUpdateStatus,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n ],\n );\n\n useLayoutEffect(() => {\n anchorStore.update(commentMeta, railMode, focusedAnchor, highlightAnchor);\n }, [anchorStore, commentMeta, railMode, focusedAnchor, highlightAnchor]);\n\n const [anchorActions] = useState<CommentAnchorActions>(() => ({\n focusAnchor,\n registerAnchor,\n scrollToAnchor,\n contentRef,\n }));\n\n const value = useMemo<CommentContextValue>(\n () => ({\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n contentRef,\n highlightAnchor,\n setHighlightAnchor,\n }),\n [\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n highlightAnchor,\n ],\n );\n\n return (\n <CommentAnchorStoreContext.Provider value={anchorStore}>\n <CommentAnchorActionsContext.Provider value={anchorActions}>\n <CommentContext.Provider value={value}>\n {children}\n </CommentContext.Provider>\n </CommentAnchorActionsContext.Provider>\n </CommentAnchorStoreContext.Provider>\n );\n}\n"],"names":["exactAnchorResolver","useState","useRef","useMemo","deriveAnchorCounts","deriveAnchorMeta","createCommentAnchorStore","useLayoutEffect","useCallback","useEffect","CommentAnchorStoreContext","CommentAnchorActionsContext","CommentContext"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentProvider.cjs","sources":["../../src/comments/CommentProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { deriveAnchorCounts, deriveAnchorMeta } from \"./comment-utils\";\nimport {\n CommentContext,\n CommentAnchorActionsContext,\n CommentAnchorStoreContext,\n createCommentAnchorStore,\n exactAnchorResolver,\n type AnchorResolver,\n type CommentAnchorActions,\n type CommentContextValue,\n type CommentRailMode,\n type CommentScrollOptions,\n} from \"./comment-context\";\nimport {\n type Comment,\n type CommentAnchor,\n type CommentCallbacks,\n type CommentConfig,\n} from \"./comment-types\";\n\nexport type CommentProviderProps = CommentCallbacks & {\n children: ReactNode;\n /** All comments for the document; counts and metadata are derived from these. */\n comments: Comment[];\n config: CommentConfig;\n /** Strategy to map a requested anchor onto a registered one. Defaults to exact. */\n resolveAnchor?: AnchorResolver;\n /** Reports rail actions so a host can synchronize external visibility state. */\n onRailModeChange?: (mode: CommentRailMode) => void;\n /**\n * Rail mode on mount. Use \"all\" where the host already decided the rail is\n * visible, so the reader is not asked to open it a second time.\n */\n initialRailMode?: CommentRailMode;\n};\n\n/**\n * Supplies comment state to a document subtree: derived per-anchor counts and\n * metadata, rail open/focus state, and a generic anchor registry (cells call\n * `registerAnchor` so the side panel can scroll-align to them). Owns no\n * fetching — `comments` and the callbacks are controlled by the consumer.\n */\nexport function CommentProvider({\n children,\n comments,\n config,\n resolveAnchor = exactAnchorResolver,\n onRailModeChange,\n onCreate,\n onReply,\n onUpdateStatus,\n onClose,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n initialRailMode = \"closed\",\n}: CommentProviderProps) {\n const [railMode, setRailMode] = useState<CommentRailMode>(initialRailMode);\n const [focusedAnchor, setFocusedAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const [highlightAnchor, setHighlightAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const railModeRef = useRef<CommentRailMode>(initialRailMode);\n const onRailModeChangeRef = useRef(onRailModeChange);\n const resolveAnchorRef = useRef(resolveAnchor);\n const anchorEls = useRef<Record<string, HTMLElement>>({});\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const commentCounts = useMemo(() => deriveAnchorCounts(comments), [comments]);\n const commentMeta = useMemo(() => deriveAnchorMeta(comments), [comments]);\n const [anchorStore] = useState(createCommentAnchorStore);\n\n useLayoutEffect(() => {\n onRailModeChangeRef.current = onRailModeChange;\n resolveAnchorRef.current = resolveAnchor;\n }, [onRailModeChange, resolveAnchor]);\n\n const focusAnchor = useCallback((anchor: CommentAnchor) => {\n setFocusedAnchor(anchor);\n railModeRef.current = \"focused\";\n setRailMode(\"focused\");\n onRailModeChangeRef.current?.(\"focused\");\n }, []);\n\n const openCommentList = useCallback(() => {\n const next = railModeRef.current === \"all\" ? \"closed\" : \"all\";\n railModeRef.current = next;\n setRailMode(next);\n onRailModeChangeRef.current?.(next);\n }, []);\n\n const closeRail = useCallback(() => {\n railModeRef.current = \"closed\";\n setRailMode(\"closed\");\n onRailModeChangeRef.current?.(\"closed\");\n }, []);\n\n const registerAnchor = useCallback(\n (anchor: CommentAnchor, el: HTMLElement | null) => {\n if (!el) {\n delete anchorEls.current[anchor];\n return;\n }\n const registered = anchorEls.current[anchor];\n if (registered && registered !== el) {\n throw new Error(\n `Comment anchor \"${anchor}\" is registered by multiple elements`,\n );\n }\n anchorEls.current[anchor] = el;\n },\n [],\n );\n\n const getAnchorTop = useCallback((anchor: CommentAnchor): number | null => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return null;\n return (\n el.getBoundingClientRect().top - container.getBoundingClientRect().top\n );\n }, []);\n\n const scrollToAnchor = useCallback(\n (anchor: CommentAnchor, options: CommentScrollOptions = {}): boolean => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return false;\n const containerRect = container.getBoundingClientRect();\n const anchorRect = el.getBoundingClientRect();\n const offset = options.offset ?? 0;\n const top =\n options.block === \"center\"\n ? container.scrollTop +\n anchorRect.top -\n containerRect.top +\n anchorRect.height / 2 -\n container.clientHeight / 2 -\n offset\n : container.scrollTop + anchorRect.top - containerRect.top - offset;\n container.scrollTo({\n top: Math.max(0, top),\n behavior: options.behavior ?? \"smooth\",\n });\n return true;\n },\n [],\n );\n\n // A focused rail with no anchor selected has nothing to show.\n useEffect(() => {\n if (railMode === \"focused\" && !focusedAnchor) closeRail();\n }, [closeRail, railMode, focusedAnchor]);\n\n const callbacks = useMemo<CommentCallbacks>(\n () => ({\n ...(onCreate ? { onCreate } : {}),\n ...(onReply ? { onReply } : {}),\n ...(onUpdateStatus ? { onUpdateStatus } : {}),\n ...(onClose ? { onClose } : {}),\n ...(onUpdateRating ? { onUpdateRating } : {}),\n ...(onDelete ? { onDelete } : {}),\n ...(onChecklistToggle ? { onChecklistToggle } : {}),\n ...(onMention ? { onMention } : {}),\n }),\n [\n onCreate,\n onReply,\n onUpdateStatus,\n onClose,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n ],\n );\n\n useLayoutEffect(() => {\n anchorStore.update(commentMeta, railMode, focusedAnchor, highlightAnchor);\n }, [anchorStore, commentMeta, railMode, focusedAnchor, highlightAnchor]);\n\n const [anchorActions] = useState<CommentAnchorActions>(() => ({\n focusAnchor,\n registerAnchor,\n scrollToAnchor,\n contentRef,\n }));\n\n const value = useMemo<CommentContextValue>(\n () => ({\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n contentRef,\n highlightAnchor,\n setHighlightAnchor,\n }),\n [\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n highlightAnchor,\n ],\n );\n\n return (\n <CommentAnchorStoreContext.Provider value={anchorStore}>\n <CommentAnchorActionsContext.Provider value={anchorActions}>\n <CommentContext.Provider value={value}>\n {children}\n </CommentContext.Provider>\n </CommentAnchorActionsContext.Provider>\n </CommentAnchorStoreContext.Provider>\n );\n}\n"],"names":["exactAnchorResolver","useState","useRef","useMemo","deriveAnchorCounts","deriveAnchorMeta","createCommentAnchorStore","useLayoutEffect","useCallback","useEffect","CommentAnchorStoreContext","CommentAnchorActionsContext","CommentContext"],"mappings":"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"}
|
|
@@ -22,5 +22,5 @@ export type CommentProviderProps = CommentCallbacks & {
|
|
|
22
22
|
* `registerAnchor` so the side panel can scroll-align to them). Owns no
|
|
23
23
|
* fetching — `comments` and the callbacks are controlled by the consumer.
|
|
24
24
|
*/
|
|
25
|
-
export declare function CommentProvider({ children, comments, config, resolveAnchor, onRailModeChange, onCreate, onReply, onUpdateStatus, onUpdateRating, onDelete, onChecklistToggle, onMention, initialRailMode, }: CommentProviderProps): import("react").JSX.Element;
|
|
25
|
+
export declare function CommentProvider({ children, comments, config, resolveAnchor, onRailModeChange, onCreate, onReply, onUpdateStatus, onClose, onUpdateRating, onDelete, onChecklistToggle, onMention, initialRailMode, }: CommentProviderProps): import("react").JSX.Element;
|
|
26
26
|
//# sourceMappingURL=CommentProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentProvider.d.ts","sourceRoot":"","sources":["../../src/comments/CommentProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,cAAc,EAGnB,KAAK,eAAe,EAErB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,QAAQ,EAAE,SAAS,CAAC;IACpB,iFAAiF;IACjF,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,aAAmC,EACnC,gBAAgB,EAChB,QAAQ,EACR,OAAO,EACP,cAAc,EACd,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,eAA0B,GAC3B,EAAE,oBAAoB,+
|
|
1
|
+
{"version":3,"file":"CommentProvider.d.ts","sourceRoot":"","sources":["../../src/comments/CommentProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,cAAc,EAGnB,KAAK,eAAe,EAErB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,GAAG;IACpD,QAAQ,EAAE,SAAS,CAAC;IACpB,iFAAiF;IACjF,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,cAAc,CAAC;IAC/B,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,aAAmC,EACnC,gBAAgB,EAChB,QAAQ,EACR,OAAO,EACP,cAAc,EACd,OAAO,EACP,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,eAA0B,GAC3B,EAAE,oBAAoB,+BA4LtB"}
|
|
@@ -11,6 +11,7 @@ function CommentProvider({
|
|
|
11
11
|
onCreate,
|
|
12
12
|
onReply,
|
|
13
13
|
onUpdateStatus,
|
|
14
|
+
onClose,
|
|
14
15
|
onUpdateRating,
|
|
15
16
|
onDelete,
|
|
16
17
|
onChecklistToggle,
|
|
@@ -111,6 +112,7 @@ function CommentProvider({
|
|
|
111
112
|
...onCreate ? { onCreate } : {},
|
|
112
113
|
...onReply ? { onReply } : {},
|
|
113
114
|
...onUpdateStatus ? { onUpdateStatus } : {},
|
|
115
|
+
...onClose ? { onClose } : {},
|
|
114
116
|
...onUpdateRating ? { onUpdateRating } : {},
|
|
115
117
|
...onDelete ? { onDelete } : {},
|
|
116
118
|
...onChecklistToggle ? { onChecklistToggle } : {},
|
|
@@ -120,6 +122,7 @@ function CommentProvider({
|
|
|
120
122
|
onCreate,
|
|
121
123
|
onReply,
|
|
122
124
|
onUpdateStatus,
|
|
125
|
+
onClose,
|
|
123
126
|
onUpdateRating,
|
|
124
127
|
onDelete,
|
|
125
128
|
onChecklistToggle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentProvider.js","sources":["../../src/comments/CommentProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { deriveAnchorCounts, deriveAnchorMeta } from \"./comment-utils\";\nimport {\n CommentContext,\n CommentAnchorActionsContext,\n CommentAnchorStoreContext,\n createCommentAnchorStore,\n exactAnchorResolver,\n type AnchorResolver,\n type CommentAnchorActions,\n type CommentContextValue,\n type CommentRailMode,\n type CommentScrollOptions,\n} from \"./comment-context\";\nimport {\n type Comment,\n type CommentAnchor,\n type CommentCallbacks,\n type CommentConfig,\n} from \"./comment-types\";\n\nexport type CommentProviderProps = CommentCallbacks & {\n children: ReactNode;\n /** All comments for the document; counts and metadata are derived from these. */\n comments: Comment[];\n config: CommentConfig;\n /** Strategy to map a requested anchor onto a registered one. Defaults to exact. */\n resolveAnchor?: AnchorResolver;\n /** Reports rail actions so a host can synchronize external visibility state. */\n onRailModeChange?: (mode: CommentRailMode) => void;\n /**\n * Rail mode on mount. Use \"all\" where the host already decided the rail is\n * visible, so the reader is not asked to open it a second time.\n */\n initialRailMode?: CommentRailMode;\n};\n\n/**\n * Supplies comment state to a document subtree: derived per-anchor counts and\n * metadata, rail open/focus state, and a generic anchor registry (cells call\n * `registerAnchor` so the side panel can scroll-align to them). Owns no\n * fetching — `comments` and the callbacks are controlled by the consumer.\n */\nexport function CommentProvider({\n children,\n comments,\n config,\n resolveAnchor = exactAnchorResolver,\n onRailModeChange,\n onCreate,\n onReply,\n onUpdateStatus,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n initialRailMode = \"closed\",\n}: CommentProviderProps) {\n const [railMode, setRailMode] = useState<CommentRailMode>(initialRailMode);\n const [focusedAnchor, setFocusedAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const [highlightAnchor, setHighlightAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const railModeRef = useRef<CommentRailMode>(initialRailMode);\n const onRailModeChangeRef = useRef(onRailModeChange);\n const resolveAnchorRef = useRef(resolveAnchor);\n const anchorEls = useRef<Record<string, HTMLElement>>({});\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const commentCounts = useMemo(() => deriveAnchorCounts(comments), [comments]);\n const commentMeta = useMemo(() => deriveAnchorMeta(comments), [comments]);\n const [anchorStore] = useState(createCommentAnchorStore);\n\n useLayoutEffect(() => {\n onRailModeChangeRef.current = onRailModeChange;\n resolveAnchorRef.current = resolveAnchor;\n }, [onRailModeChange, resolveAnchor]);\n\n const focusAnchor = useCallback((anchor: CommentAnchor) => {\n setFocusedAnchor(anchor);\n railModeRef.current = \"focused\";\n setRailMode(\"focused\");\n onRailModeChangeRef.current?.(\"focused\");\n }, []);\n\n const openCommentList = useCallback(() => {\n const next = railModeRef.current === \"all\" ? \"closed\" : \"all\";\n railModeRef.current = next;\n setRailMode(next);\n onRailModeChangeRef.current?.(next);\n }, []);\n\n const closeRail = useCallback(() => {\n railModeRef.current = \"closed\";\n setRailMode(\"closed\");\n onRailModeChangeRef.current?.(\"closed\");\n }, []);\n\n const registerAnchor = useCallback(\n (anchor: CommentAnchor, el: HTMLElement | null) => {\n if (!el) {\n delete anchorEls.current[anchor];\n return;\n }\n const registered = anchorEls.current[anchor];\n if (registered && registered !== el) {\n throw new Error(\n `Comment anchor \"${anchor}\" is registered by multiple elements`,\n );\n }\n anchorEls.current[anchor] = el;\n },\n [],\n );\n\n const getAnchorTop = useCallback((anchor: CommentAnchor): number | null => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return null;\n return (\n el.getBoundingClientRect().top - container.getBoundingClientRect().top\n );\n }, []);\n\n const scrollToAnchor = useCallback(\n (anchor: CommentAnchor, options: CommentScrollOptions = {}): boolean => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return false;\n const containerRect = container.getBoundingClientRect();\n const anchorRect = el.getBoundingClientRect();\n const offset = options.offset ?? 0;\n const top =\n options.block === \"center\"\n ? container.scrollTop +\n anchorRect.top -\n containerRect.top +\n anchorRect.height / 2 -\n container.clientHeight / 2 -\n offset\n : container.scrollTop + anchorRect.top - containerRect.top - offset;\n container.scrollTo({\n top: Math.max(0, top),\n behavior: options.behavior ?? \"smooth\",\n });\n return true;\n },\n [],\n );\n\n // A focused rail with no anchor selected has nothing to show.\n useEffect(() => {\n if (railMode === \"focused\" && !focusedAnchor) closeRail();\n }, [closeRail, railMode, focusedAnchor]);\n\n const callbacks = useMemo<CommentCallbacks>(\n () => ({\n ...(onCreate ? { onCreate } : {}),\n ...(onReply ? { onReply } : {}),\n ...(onUpdateStatus ? { onUpdateStatus } : {}),\n ...(onUpdateRating ? { onUpdateRating } : {}),\n ...(onDelete ? { onDelete } : {}),\n ...(onChecklistToggle ? { onChecklistToggle } : {}),\n ...(onMention ? { onMention } : {}),\n }),\n [\n onCreate,\n onReply,\n onUpdateStatus,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n ],\n );\n\n useLayoutEffect(() => {\n anchorStore.update(commentMeta, railMode, focusedAnchor, highlightAnchor);\n }, [anchorStore, commentMeta, railMode, focusedAnchor, highlightAnchor]);\n\n const [anchorActions] = useState<CommentAnchorActions>(() => ({\n focusAnchor,\n registerAnchor,\n scrollToAnchor,\n contentRef,\n }));\n\n const value = useMemo<CommentContextValue>(\n () => ({\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n contentRef,\n highlightAnchor,\n setHighlightAnchor,\n }),\n [\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n highlightAnchor,\n ],\n );\n\n return (\n <CommentAnchorStoreContext.Provider value={anchorStore}>\n <CommentAnchorActionsContext.Provider value={anchorActions}>\n <CommentContext.Provider value={value}>\n {children}\n </CommentContext.Provider>\n </CommentAnchorActionsContext.Provider>\n </CommentAnchorStoreContext.Provider>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentProvider.js","sources":["../../src/comments/CommentProvider.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport { deriveAnchorCounts, deriveAnchorMeta } from \"./comment-utils\";\nimport {\n CommentContext,\n CommentAnchorActionsContext,\n CommentAnchorStoreContext,\n createCommentAnchorStore,\n exactAnchorResolver,\n type AnchorResolver,\n type CommentAnchorActions,\n type CommentContextValue,\n type CommentRailMode,\n type CommentScrollOptions,\n} from \"./comment-context\";\nimport {\n type Comment,\n type CommentAnchor,\n type CommentCallbacks,\n type CommentConfig,\n} from \"./comment-types\";\n\nexport type CommentProviderProps = CommentCallbacks & {\n children: ReactNode;\n /** All comments for the document; counts and metadata are derived from these. */\n comments: Comment[];\n config: CommentConfig;\n /** Strategy to map a requested anchor onto a registered one. Defaults to exact. */\n resolveAnchor?: AnchorResolver;\n /** Reports rail actions so a host can synchronize external visibility state. */\n onRailModeChange?: (mode: CommentRailMode) => void;\n /**\n * Rail mode on mount. Use \"all\" where the host already decided the rail is\n * visible, so the reader is not asked to open it a second time.\n */\n initialRailMode?: CommentRailMode;\n};\n\n/**\n * Supplies comment state to a document subtree: derived per-anchor counts and\n * metadata, rail open/focus state, and a generic anchor registry (cells call\n * `registerAnchor` so the side panel can scroll-align to them). Owns no\n * fetching — `comments` and the callbacks are controlled by the consumer.\n */\nexport function CommentProvider({\n children,\n comments,\n config,\n resolveAnchor = exactAnchorResolver,\n onRailModeChange,\n onCreate,\n onReply,\n onUpdateStatus,\n onClose,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n initialRailMode = \"closed\",\n}: CommentProviderProps) {\n const [railMode, setRailMode] = useState<CommentRailMode>(initialRailMode);\n const [focusedAnchor, setFocusedAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const [highlightAnchor, setHighlightAnchor] = useState<CommentAnchor | null>(\n null,\n );\n const railModeRef = useRef<CommentRailMode>(initialRailMode);\n const onRailModeChangeRef = useRef(onRailModeChange);\n const resolveAnchorRef = useRef(resolveAnchor);\n const anchorEls = useRef<Record<string, HTMLElement>>({});\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n const commentCounts = useMemo(() => deriveAnchorCounts(comments), [comments]);\n const commentMeta = useMemo(() => deriveAnchorMeta(comments), [comments]);\n const [anchorStore] = useState(createCommentAnchorStore);\n\n useLayoutEffect(() => {\n onRailModeChangeRef.current = onRailModeChange;\n resolveAnchorRef.current = resolveAnchor;\n }, [onRailModeChange, resolveAnchor]);\n\n const focusAnchor = useCallback((anchor: CommentAnchor) => {\n setFocusedAnchor(anchor);\n railModeRef.current = \"focused\";\n setRailMode(\"focused\");\n onRailModeChangeRef.current?.(\"focused\");\n }, []);\n\n const openCommentList = useCallback(() => {\n const next = railModeRef.current === \"all\" ? \"closed\" : \"all\";\n railModeRef.current = next;\n setRailMode(next);\n onRailModeChangeRef.current?.(next);\n }, []);\n\n const closeRail = useCallback(() => {\n railModeRef.current = \"closed\";\n setRailMode(\"closed\");\n onRailModeChangeRef.current?.(\"closed\");\n }, []);\n\n const registerAnchor = useCallback(\n (anchor: CommentAnchor, el: HTMLElement | null) => {\n if (!el) {\n delete anchorEls.current[anchor];\n return;\n }\n const registered = anchorEls.current[anchor];\n if (registered && registered !== el) {\n throw new Error(\n `Comment anchor \"${anchor}\" is registered by multiple elements`,\n );\n }\n anchorEls.current[anchor] = el;\n },\n [],\n );\n\n const getAnchorTop = useCallback((anchor: CommentAnchor): number | null => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return null;\n return (\n el.getBoundingClientRect().top - container.getBoundingClientRect().top\n );\n }, []);\n\n const scrollToAnchor = useCallback(\n (anchor: CommentAnchor, options: CommentScrollOptions = {}): boolean => {\n const resolved = resolveAnchorRef.current(\n anchor,\n Object.keys(anchorEls.current),\n );\n const el = resolved ? anchorEls.current[resolved] : null;\n const container = contentRef.current;\n if (!el || !container) return false;\n const containerRect = container.getBoundingClientRect();\n const anchorRect = el.getBoundingClientRect();\n const offset = options.offset ?? 0;\n const top =\n options.block === \"center\"\n ? container.scrollTop +\n anchorRect.top -\n containerRect.top +\n anchorRect.height / 2 -\n container.clientHeight / 2 -\n offset\n : container.scrollTop + anchorRect.top - containerRect.top - offset;\n container.scrollTo({\n top: Math.max(0, top),\n behavior: options.behavior ?? \"smooth\",\n });\n return true;\n },\n [],\n );\n\n // A focused rail with no anchor selected has nothing to show.\n useEffect(() => {\n if (railMode === \"focused\" && !focusedAnchor) closeRail();\n }, [closeRail, railMode, focusedAnchor]);\n\n const callbacks = useMemo<CommentCallbacks>(\n () => ({\n ...(onCreate ? { onCreate } : {}),\n ...(onReply ? { onReply } : {}),\n ...(onUpdateStatus ? { onUpdateStatus } : {}),\n ...(onClose ? { onClose } : {}),\n ...(onUpdateRating ? { onUpdateRating } : {}),\n ...(onDelete ? { onDelete } : {}),\n ...(onChecklistToggle ? { onChecklistToggle } : {}),\n ...(onMention ? { onMention } : {}),\n }),\n [\n onCreate,\n onReply,\n onUpdateStatus,\n onClose,\n onUpdateRating,\n onDelete,\n onChecklistToggle,\n onMention,\n ],\n );\n\n useLayoutEffect(() => {\n anchorStore.update(commentMeta, railMode, focusedAnchor, highlightAnchor);\n }, [anchorStore, commentMeta, railMode, focusedAnchor, highlightAnchor]);\n\n const [anchorActions] = useState<CommentAnchorActions>(() => ({\n focusAnchor,\n registerAnchor,\n scrollToAnchor,\n contentRef,\n }));\n\n const value = useMemo<CommentContextValue>(\n () => ({\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n contentRef,\n highlightAnchor,\n setHighlightAnchor,\n }),\n [\n comments,\n config,\n callbacks,\n commentCounts,\n commentMeta,\n railMode,\n focusedAnchor,\n focusAnchor,\n openCommentList,\n closeRail,\n registerAnchor,\n getAnchorTop,\n scrollToAnchor,\n highlightAnchor,\n ],\n );\n\n return (\n <CommentAnchorStoreContext.Provider value={anchorStore}>\n <CommentAnchorActionsContext.Provider value={anchorActions}>\n <CommentContext.Provider value={value}>\n {children}\n </CommentContext.Provider>\n </CommentAnchorActionsContext.Provider>\n </CommentAnchorStoreContext.Provider>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -85,7 +85,8 @@ function AllComments({
|
|
|
85
85
|
ctx,
|
|
86
86
|
comments,
|
|
87
87
|
label,
|
|
88
|
-
emptyLabel
|
|
88
|
+
emptyLabel,
|
|
89
|
+
threadToMarkdown
|
|
89
90
|
}) {
|
|
90
91
|
const ordered = react.useMemo(() => {
|
|
91
92
|
const anchorOrder = new Map(orderedAnchors(ctx).map((a, i) => [a, i]));
|
|
@@ -141,7 +142,8 @@ function AllComments({
|
|
|
141
142
|
onMouseLeave: () => ctx.setHighlightAnchor(null),
|
|
142
143
|
onClick: (event) => activateThread(event, c.anchor ?? commentTypes.DOCUMENT_ANCHOR)
|
|
143
144
|
}),
|
|
144
|
-
...handlers
|
|
145
|
+
...handlers,
|
|
146
|
+
...threadToMarkdown ? { threadToMarkdown } : {}
|
|
145
147
|
}
|
|
146
148
|
)
|
|
147
149
|
}
|
|
@@ -152,7 +154,8 @@ function FocusedComments({
|
|
|
152
154
|
comments: visible,
|
|
153
155
|
anchor,
|
|
154
156
|
label,
|
|
155
|
-
compact
|
|
157
|
+
compact,
|
|
158
|
+
threadToMarkdown
|
|
156
159
|
}) {
|
|
157
160
|
const comments = commentUtils.selectAnchorThreads(visible, anchor);
|
|
158
161
|
const hasComments = comments.length > 0;
|
|
@@ -173,7 +176,8 @@ function FocusedComments({
|
|
|
173
176
|
autoFocusComposer: !hasComments,
|
|
174
177
|
defaultExpanded: hasComments,
|
|
175
178
|
composerPlaceholder: hasComments ? "Add another top-level comment…" : "Add a comment…",
|
|
176
|
-
...ctx.callbacks
|
|
179
|
+
...ctx.callbacks,
|
|
180
|
+
...threadToMarkdown ? { threadToMarkdown } : {}
|
|
177
181
|
}
|
|
178
182
|
)
|
|
179
183
|
] });
|
|
@@ -184,7 +188,7 @@ function CommentSidePanel(props) {
|
|
|
184
188
|
const railRef = react.useRef(null);
|
|
185
189
|
const focusedRef = react.useRef(null);
|
|
186
190
|
const [focusedOffset, setFocusedOffset] = react.useState(null);
|
|
187
|
-
const [
|
|
191
|
+
const [stage, setStage] = react.useState("active");
|
|
188
192
|
const focusedAnchor = (ctx == null ? void 0 : ctx.railMode) === "focused" ? ctx.focusedAnchor : null;
|
|
189
193
|
react.useEffect(() => {
|
|
190
194
|
if (!ctx || props.focusedAlignment !== "anchor" || !focusedAnchor) {
|
|
@@ -219,11 +223,21 @@ function CommentSidePanel(props) {
|
|
|
219
223
|
};
|
|
220
224
|
}, [ctx, focusedAnchor, props.focusedAlignment]);
|
|
221
225
|
if (!ctx) return null;
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
226
|
+
const counts = commentUtils.getRoots(ctx.comments).reduce(
|
|
227
|
+
(result, root) => {
|
|
228
|
+
const rootStage = commentUtils.resolveCommentStage(ctx.config, root.status);
|
|
229
|
+
if (rootStage) result[rootStage] += 1;
|
|
230
|
+
return result;
|
|
231
|
+
},
|
|
232
|
+
{ active: 0, resolved: 0, closed: 0 }
|
|
233
|
+
);
|
|
234
|
+
const visible = commentUtils.selectCommentThreadsByStage(ctx.comments, ctx.config, stage);
|
|
235
|
+
if (ctx.railMode === "closed" && counts.active + counts.resolved + counts.closed === 0)
|
|
236
|
+
return null;
|
|
237
|
+
function selectStage(next) {
|
|
238
|
+
setStage(next);
|
|
239
|
+
if ((ctx == null ? void 0 : ctx.railMode) !== "all") ctx == null ? void 0 : ctx.openCommentList();
|
|
240
|
+
}
|
|
227
241
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
228
242
|
"aside",
|
|
229
243
|
{
|
|
@@ -237,28 +251,45 @@ function CommentSidePanel(props) {
|
|
|
237
251
|
"data-testid": "comment-rail-header",
|
|
238
252
|
className: "sticky top-0 z-20 flex items-center gap-2 bg-background py-2",
|
|
239
253
|
children: [
|
|
240
|
-
(
|
|
254
|
+
(counts.active > 0 || ctx.railMode === "all") && /* @__PURE__ */ jsxRuntime.jsx(
|
|
241
255
|
RailToggle,
|
|
242
256
|
{
|
|
243
|
-
active: ctx.railMode === "all",
|
|
244
|
-
onClick:
|
|
257
|
+
active: ctx.railMode === "all" && stage === "active",
|
|
258
|
+
onClick: () => selectStage("active"),
|
|
245
259
|
testId: "comment-open-all",
|
|
246
|
-
children: ctx.railMode === "closed" ? `Open comments (${
|
|
260
|
+
children: ctx.railMode === "closed" ? `Open comments (${counts.active})` : ctx.railMode === "focused" ? `All comments (${counts.active})` : `Open (${counts.active})`
|
|
247
261
|
}
|
|
248
262
|
),
|
|
249
|
-
|
|
263
|
+
counts.resolved > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
250
264
|
"button",
|
|
251
265
|
{
|
|
252
266
|
type: "button",
|
|
253
|
-
"aria-pressed":
|
|
254
|
-
onClick: () =>
|
|
267
|
+
"aria-pressed": ctx.railMode === "all" && stage === "resolved",
|
|
268
|
+
onClick: () => selectStage("resolved"),
|
|
255
269
|
className: utils.cn(
|
|
256
270
|
"rounded-full border px-2 py-1 text-xs font-medium transition-colors",
|
|
257
|
-
|
|
271
|
+
ctx.railMode === "all" && stage === "resolved" ? "border-primary bg-primary text-primary-foreground" : "border-border bg-background text-muted-foreground hover:text-foreground"
|
|
258
272
|
),
|
|
259
273
|
children: [
|
|
260
274
|
"Resolved (",
|
|
261
|
-
|
|
275
|
+
counts.resolved,
|
|
276
|
+
")"
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
),
|
|
280
|
+
counts.closed > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
281
|
+
"button",
|
|
282
|
+
{
|
|
283
|
+
type: "button",
|
|
284
|
+
"aria-pressed": ctx.railMode === "all" && stage === "closed",
|
|
285
|
+
onClick: () => selectStage("closed"),
|
|
286
|
+
className: utils.cn(
|
|
287
|
+
"rounded-full border px-2 py-1 text-xs font-medium transition-colors",
|
|
288
|
+
ctx.railMode === "all" && stage === "closed" ? "border-primary bg-primary text-primary-foreground" : "border-border bg-background text-muted-foreground hover:text-foreground"
|
|
289
|
+
),
|
|
290
|
+
children: [
|
|
291
|
+
"Closed (",
|
|
292
|
+
counts.closed,
|
|
262
293
|
")"
|
|
263
294
|
]
|
|
264
295
|
}
|
|
@@ -281,7 +312,8 @@ function CommentSidePanel(props) {
|
|
|
281
312
|
ctx,
|
|
282
313
|
comments: visible,
|
|
283
314
|
label,
|
|
284
|
-
emptyLabel:
|
|
315
|
+
emptyLabel: stage === "active" ? "No open comments." : stage === "resolved" ? "No resolved comments." : "No closed comments.",
|
|
316
|
+
...props.threadToMarkdown ? { threadToMarkdown: props.threadToMarkdown } : {}
|
|
285
317
|
}
|
|
286
318
|
) : ctx.railMode === "focused" && ctx.focusedAnchor ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
287
319
|
"div",
|
|
@@ -294,10 +326,11 @@ function CommentSidePanel(props) {
|
|
|
294
326
|
FocusedComments,
|
|
295
327
|
{
|
|
296
328
|
ctx,
|
|
297
|
-
comments:
|
|
329
|
+
comments: ctx.comments,
|
|
298
330
|
anchor: ctx.focusedAnchor,
|
|
299
331
|
label: label(ctx.focusedAnchor),
|
|
300
|
-
...props.compact !== void 0 ? { compact: props.compact } : {}
|
|
332
|
+
...props.compact !== void 0 ? { compact: props.compact } : {},
|
|
333
|
+
...props.threadToMarkdown ? { threadToMarkdown: props.threadToMarkdown } : {}
|
|
301
334
|
}
|
|
302
335
|
)
|
|
303
336
|
}
|