@burdenoff/microfe-bigconsole 2026.805.2 → 2026.805.3

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 (134) hide show
  1. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
  2. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  3. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
  4. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  5. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
  6. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  7. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +90 -89
  8. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  9. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
  10. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  11. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
  12. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  13. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
  14. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  19. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
  20. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  21. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
  22. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
  23. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
  24. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  25. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +181 -190
  26. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  27. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
  28. package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
  29. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  30. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
  31. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  32. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
  33. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  34. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
  35. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
  37. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  38. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
  39. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  40. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
  41. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  42. package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
  43. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  44. package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
  45. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  46. package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
  47. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  48. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
  49. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  50. package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
  51. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  52. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +222 -215
  53. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  54. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
  55. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  56. package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
  57. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  58. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
  59. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  60. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
  61. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  62. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
  63. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  64. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
  65. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  66. package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
  67. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  68. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
  69. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  70. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
  71. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  72. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
  73. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  74. package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
  75. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  76. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
  77. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  78. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
  79. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  80. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
  81. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
  82. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
  83. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  84. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
  85. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  86. package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
  87. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  88. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
  89. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  90. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
  91. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  92. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
  93. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  94. package/dist/bigconsole/pages/DashboardBuilderPage.js +181 -176
  95. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  96. package/dist/bigconsole/pages/DashboardViewPage.js +196 -192
  97. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  98. package/dist/bigconsole/pages/DashboardsPage.js +223 -219
  99. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  100. package/dist/bigconsole/pages/DataParsersPage.js +167 -170
  101. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  102. package/dist/bigconsole/pages/DataSinkBuilderPage.js +204 -189
  103. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  104. package/dist/bigconsole/pages/DataSinkViewPage.js +175 -169
  105. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  106. package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
  107. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  108. package/dist/bigconsole/pages/InsightsPage.js +238 -208
  109. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  110. package/dist/bigconsole/pages/ParserBuilderPage.js +464 -412
  111. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  112. package/dist/bigconsole/pages/ParserViewPage.js +92 -90
  113. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  114. package/dist/bigconsole/pages/PipelineBuilderPage.js +221 -194
  115. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  116. package/dist/bigconsole/pages/PipelineViewPage.js +181 -184
  117. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  118. package/dist/bigconsole/pages/PipelinesPage.js +128 -127
  119. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  120. package/dist/bigconsole/pages/SettingsPage.js +177 -172
  121. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  122. package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
  123. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  124. package/dist/bigconsole/pages/WorkflowViewPage.js +199 -193
  125. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  126. package/dist/bigconsole/pages/WorkflowsPage.js +129 -128
  127. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  128. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
  129. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  130. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
  131. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  132. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
  133. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  134. package/package.json +2 -1
@@ -1,200 +1,213 @@
1
1
  import e from "../../../hooks/useWidgetComments.js";
2
2
  import { useCallback as t, useState as n } from "react";
3
3
  import { Check as r, CornerDownRight as i, Loader2 as a, MessageSquare as o, RotateCcw as s, Send as c, Trash2 as l, X as u } from "lucide-react";
4
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
4
+ import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
5
6
  //#region src/bigconsole/components/widgets/comments/WidgetComments.tsx
6
- function p(e) {
7
- return `User ${e.slice(0, 6)}`;
7
+ function m(e, t) {
8
+ return e("bigconsole.widget.comments.authorLabel", "User {{id}}", { id: t.slice(0, 6) });
8
9
  }
9
- function m(e) {
10
+ function h(e) {
10
11
  let t = new Date(e);
11
12
  return Number.isNaN(t.getTime()) ? "" : new Intl.DateTimeFormat(void 0, {
12
13
  dateStyle: "medium",
13
14
  timeStyle: "short"
14
15
  }).format(t);
15
16
  }
16
- var h = ({ comment: e, isReply: t, busy: n, onResolve: a, onDelete: o, onReply: c }) => {
17
- let u = !!e.resolvedAt, h = e.content.text ?? e.content.markdown ?? "";
18
- return /* @__PURE__ */ d("div", {
17
+ var g = ({ comment: e, isReply: t, busy: n, onResolve: a, onDelete: o, onReply: c }) => {
18
+ let { t: u } = d(), g = !!e.resolvedAt, _ = e.content.text ?? e.content.markdown ?? "";
19
+ return /* @__PURE__ */ f("div", {
19
20
  className: t ? "pl-6" : "",
20
- children: /* @__PURE__ */ f("div", {
21
+ children: /* @__PURE__ */ p("div", {
21
22
  className: "rounded-md border border-border-default bg-bg-surface p-2.5",
22
23
  children: [
23
- /* @__PURE__ */ f("div", {
24
+ /* @__PURE__ */ p("div", {
24
25
  className: "flex items-center justify-between gap-2",
25
- children: [/* @__PURE__ */ d("span", {
26
+ children: [/* @__PURE__ */ f("span", {
26
27
  className: "text-xs font-medium text-text-primary",
27
- children: p(e.authorId)
28
- }), /* @__PURE__ */ d("span", {
28
+ children: m(u, e.authorId)
29
+ }), /* @__PURE__ */ f("span", {
29
30
  className: "text-[10px] text-text-tertiary tabular-nums",
30
- children: m(e.createdAt)
31
+ children: h(e.createdAt)
31
32
  })]
32
33
  }),
33
- /* @__PURE__ */ d("p", {
34
+ /* @__PURE__ */ f("p", {
34
35
  className: "mt-1 whitespace-pre-wrap break-words text-sm text-text-secondary",
35
- children: h
36
+ children: _
36
37
  }),
37
- /* @__PURE__ */ f("div", {
38
+ /* @__PURE__ */ p("div", {
38
39
  className: "mt-1.5 flex items-center gap-2",
39
40
  children: [
40
- u && /* @__PURE__ */ f("span", {
41
+ g && /* @__PURE__ */ p("span", {
41
42
  className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-medium bg-status-success-bg text-status-success-text",
42
- children: [/* @__PURE__ */ d(r, { className: "h-3 w-3" }), " Resolved"]
43
+ children: [
44
+ /* @__PURE__ */ f(r, { className: "h-3 w-3" }),
45
+ " ",
46
+ u("bigconsole.widget.comments.resolvedBadge", "Resolved")
47
+ ]
43
48
  }),
44
- c && /* @__PURE__ */ f("button", {
49
+ c && /* @__PURE__ */ p("button", {
45
50
  type: "button",
46
51
  disabled: n,
47
52
  onClick: () => c(e.id),
48
53
  className: "inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50",
49
- children: [/* @__PURE__ */ d(i, { className: "h-3 w-3" }), " Reply"]
54
+ children: [
55
+ /* @__PURE__ */ f(i, { className: "h-3 w-3" }),
56
+ " ",
57
+ u("bigconsole.widget.comments.reply", "Reply")
58
+ ]
50
59
  }),
51
- /* @__PURE__ */ f("button", {
60
+ /* @__PURE__ */ p("button", {
52
61
  type: "button",
53
62
  disabled: n,
54
- onClick: () => a(e.id, !u),
63
+ onClick: () => a(e.id, !g),
55
64
  className: "inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50",
56
- children: [d(u ? s : r, { className: "h-3 w-3" }), u ? "Reopen" : "Resolve"]
65
+ children: [f(g ? s : r, { className: "h-3 w-3" }), g ? u("bigconsole.widget.comments.reopen", "Reopen") : u("bigconsole.widget.comments.resolve", "Resolve")]
57
66
  }),
58
- /* @__PURE__ */ f("button", {
67
+ /* @__PURE__ */ p("button", {
59
68
  type: "button",
60
69
  disabled: n,
61
70
  onClick: () => o(e.id),
62
71
  className: "inline-flex items-center gap-1 text-[11px] text-status-error-text hover:opacity-80 disabled:opacity-50",
63
- children: [/* @__PURE__ */ d(l, { className: "h-3 w-3" }), " Delete"]
72
+ children: [
73
+ /* @__PURE__ */ f(l, { className: "h-3 w-3" }),
74
+ " ",
75
+ u("bigconsole.widget.comments.delete", "Delete")
76
+ ]
64
77
  })
65
78
  ]
66
79
  })
67
80
  ]
68
81
  })
69
82
  });
70
- }, g = ({ placeholder: e, busy: t, autoFocus: r, onSubmit: i, onCancel: o }) => {
71
- let [s, l] = n(""), p = async () => {
72
- let e = s.trim();
73
- e && await i(e) !== !1 && l("");
83
+ }, _ = ({ placeholder: e, busy: t, autoFocus: r, onSubmit: i, onCancel: o }) => {
84
+ let { t: s } = d(), [l, m] = n(""), h = async () => {
85
+ let e = l.trim();
86
+ e && await i(e) !== !1 && m("");
74
87
  };
75
- return /* @__PURE__ */ f("div", {
88
+ return /* @__PURE__ */ p("div", {
76
89
  className: "flex items-end gap-2",
77
- children: [/* @__PURE__ */ d("textarea", {
90
+ children: [/* @__PURE__ */ f("textarea", {
78
91
  autoFocus: r,
79
- value: s,
80
- onChange: (e) => l(e.target.value),
92
+ value: l,
93
+ onChange: (e) => m(e.target.value),
81
94
  onKeyDown: (e) => {
82
- (e.metaKey || e.ctrlKey) && e.key === "Enter" && (e.preventDefault(), p());
95
+ (e.metaKey || e.ctrlKey) && e.key === "Enter" && (e.preventDefault(), h());
83
96
  },
84
97
  rows: 2,
85
98
  placeholder: e,
86
99
  className: "flex-1 resize-none rounded-md border border-border-default bg-bg-surface px-2.5 py-1.5 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
87
- }), /* @__PURE__ */ f("div", {
100
+ }), /* @__PURE__ */ p("div", {
88
101
  className: "flex flex-col gap-1",
89
- children: [/* @__PURE__ */ d("button", {
102
+ children: [/* @__PURE__ */ f("button", {
90
103
  type: "button",
91
- disabled: t || !s.trim(),
92
- onClick: () => void p(),
93
- title: "Post (⌘/Ctrl + Enter)",
104
+ disabled: t || !l.trim(),
105
+ onClick: () => void h(),
106
+ title: s("bigconsole.widget.comments.postTitle", "Post (⌘/Ctrl + Enter)"),
94
107
  className: "inline-flex items-center justify-center rounded-md bg-action-primary-bg p-1.5 text-action-primary-text hover:opacity-90 disabled:opacity-50",
95
- children: t ? /* @__PURE__ */ d(a, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ d(c, { className: "h-4 w-4" })
96
- }), o && /* @__PURE__ */ d("button", {
108
+ children: t ? /* @__PURE__ */ f(a, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ f(c, { className: "h-4 w-4" })
109
+ }), o && /* @__PURE__ */ f("button", {
97
110
  type: "button",
98
111
  onClick: o,
99
112
  className: "inline-flex items-center justify-center rounded-md border border-border-default p-1.5 text-text-tertiary hover:text-text-primary",
100
- title: "Cancel reply",
101
- children: /* @__PURE__ */ d(u, { className: "h-4 w-4" })
113
+ title: s("bigconsole.widget.comments.cancelReplyTitle", "Cancel reply"),
114
+ children: /* @__PURE__ */ f(u, { className: "h-4 w-4" })
102
115
  })]
103
116
  })]
104
117
  });
105
- }, _ = ({ widgetId: r, onClose: i }) => {
106
- let { threads: s, count: c, loading: l, error: p, mutating: m, addComment: _, resolveComment: v, deleteComment: y } = e(r), [b, x] = n(null), S = t(async (e, t) => {
107
- let n = await _(e, t);
108
- return n && t && x(null), n;
109
- }, [_]);
110
- return /* @__PURE__ */ f("div", {
118
+ }, v = ({ widgetId: r, onClose: i }) => {
119
+ let { t: s } = d(), { threads: c, count: l, loading: m, error: h, mutating: v, addComment: y, resolveComment: b, deleteComment: x } = e(r), [S, C] = n(null), w = t(async (e, t) => {
120
+ let n = await y(e, t);
121
+ return n && t && C(null), n;
122
+ }, [y]);
123
+ return /* @__PURE__ */ p("div", {
111
124
  className: "absolute inset-0 z-40 flex flex-col bg-bg-surface/98 backdrop-blur-sm",
112
125
  role: "dialog",
113
- "aria-label": "Widget comments",
126
+ "aria-label": s("bigconsole.widget.comments.dialogAriaLabel", "Widget comments"),
114
127
  tabIndex: -1,
115
128
  onClick: (e) => e.stopPropagation(),
116
129
  onKeyDown: (e) => {
117
130
  e.key === "Escape" && (e.stopPropagation(), i());
118
131
  },
119
132
  children: [
120
- /* @__PURE__ */ f("div", {
133
+ /* @__PURE__ */ p("div", {
121
134
  className: "flex items-center justify-between border-b border-border-default px-3 py-2",
122
- children: [/* @__PURE__ */ f("div", {
135
+ children: [/* @__PURE__ */ p("div", {
123
136
  className: "flex items-center gap-2 text-sm font-medium text-text-primary",
124
137
  children: [
125
- /* @__PURE__ */ d(o, { className: "h-4 w-4 text-text-secondary" }),
126
- "Comments",
127
- /* @__PURE__ */ d("span", {
138
+ /* @__PURE__ */ f(o, { className: "h-4 w-4 text-text-secondary" }),
139
+ s("bigconsole.widget.comments.title", "Comments"),
140
+ /* @__PURE__ */ f("span", {
128
141
  className: "rounded-full bg-bg-sunken px-1.5 py-0.5 text-[10px] text-text-secondary tabular-nums",
129
- children: c
142
+ children: l
130
143
  })
131
144
  ]
132
- }), /* @__PURE__ */ d("button", {
145
+ }), /* @__PURE__ */ f("button", {
133
146
  type: "button",
134
147
  onClick: i,
135
- "aria-label": "Close comments",
148
+ "aria-label": s("bigconsole.widget.comments.closeAriaLabel", "Close comments"),
136
149
  className: "rounded-md p-1 text-text-tertiary hover:bg-bg-sunken hover:text-text-primary",
137
- children: /* @__PURE__ */ d(u, { className: "h-4 w-4" })
150
+ children: /* @__PURE__ */ f(u, { className: "h-4 w-4" })
138
151
  })]
139
152
  }),
140
- /* @__PURE__ */ f("div", {
153
+ /* @__PURE__ */ p("div", {
141
154
  className: "flex-1 space-y-3 overflow-auto p-3",
142
155
  children: [
143
- l && s.length === 0 && /* @__PURE__ */ d("div", {
156
+ m && c.length === 0 && /* @__PURE__ */ f("div", {
144
157
  className: "flex items-center justify-center py-8 text-text-tertiary",
145
- children: /* @__PURE__ */ d(a, { className: "h-5 w-5 animate-spin" })
158
+ children: /* @__PURE__ */ f(a, { className: "h-5 w-5 animate-spin" })
146
159
  }),
147
- p && !l && /* @__PURE__ */ d("p", {
160
+ h && !m && /* @__PURE__ */ f("p", {
148
161
  className: "rounded-md bg-status-error-bg px-2.5 py-2 text-xs text-status-error-text",
149
- children: "Couldn’t load comments."
162
+ children: s("bigconsole.widget.comments.loadError", "Couldn’t load comments.")
150
163
  }),
151
- !l && !p && s.length === 0 && /* @__PURE__ */ d("p", {
164
+ !m && !h && c.length === 0 && /* @__PURE__ */ f("p", {
152
165
  className: "py-8 text-center text-sm text-text-tertiary",
153
- children: "No comments yet. Start the conversation."
166
+ children: s("bigconsole.widget.comments.empty", "No comments yet. Start the conversation.")
154
167
  }),
155
- s.map(({ comment: e, replies: t }) => /* @__PURE__ */ f("div", {
168
+ c.map(({ comment: e, replies: t }) => /* @__PURE__ */ p("div", {
156
169
  className: "space-y-2",
157
170
  children: [
158
- /* @__PURE__ */ d(h, {
171
+ /* @__PURE__ */ f(g, {
159
172
  comment: e,
160
- busy: m,
161
- onResolve: (e, t) => void v(e, t),
162
- onDelete: (e) => void y(e),
163
- onReply: (e) => x((t) => t === e ? null : e)
173
+ busy: v,
174
+ onResolve: (e, t) => void b(e, t),
175
+ onDelete: (e) => void x(e),
176
+ onReply: (e) => C((t) => t === e ? null : e)
164
177
  }),
165
- t.map((e) => /* @__PURE__ */ d(h, {
178
+ t.map((e) => /* @__PURE__ */ f(g, {
166
179
  comment: e,
167
180
  isReply: !0,
168
- busy: m,
169
- onResolve: (e, t) => void v(e, t),
170
- onDelete: (e) => void y(e)
181
+ busy: v,
182
+ onResolve: (e, t) => void b(e, t),
183
+ onDelete: (e) => void x(e)
171
184
  }, e.id)),
172
- b === e.id && /* @__PURE__ */ d("div", {
185
+ S === e.id && /* @__PURE__ */ f("div", {
173
186
  className: "pl-6",
174
- children: /* @__PURE__ */ d(g, {
175
- placeholder: "Write a reply…",
176
- busy: m,
187
+ children: /* @__PURE__ */ f(_, {
188
+ placeholder: s("bigconsole.widget.comments.replyPlaceholder", "Write a reply…"),
189
+ busy: v,
177
190
  autoFocus: !0,
178
- onSubmit: (t) => S(t, e.id),
179
- onCancel: () => x(null)
191
+ onSubmit: (t) => w(t, e.id),
192
+ onCancel: () => C(null)
180
193
  })
181
194
  })
182
195
  ]
183
196
  }, e.id))
184
197
  ]
185
198
  }),
186
- /* @__PURE__ */ d("div", {
199
+ /* @__PURE__ */ f("div", {
187
200
  className: "border-t border-border-default p-3",
188
- children: /* @__PURE__ */ d(g, {
189
- placeholder: "Add a comment…",
190
- busy: m,
191
- onSubmit: (e) => S(e)
201
+ children: /* @__PURE__ */ f(_, {
202
+ placeholder: s("bigconsole.widget.comments.addPlaceholder", "Add a comment…"),
203
+ busy: v,
204
+ onSubmit: (e) => w(e)
192
205
  })
193
206
  })
194
207
  ]
195
208
  });
196
209
  };
197
210
  //#endregion
198
- export { _ as WidgetComments };
211
+ export { v as WidgetComments };
199
212
 
200
213
  //# sourceMappingURL=WidgetComments.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetComments.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/comments/WidgetComments.tsx"],"sourcesContent":["/**\n * WidgetComments\n *\n * Collaborative comment thread for a single widget, rendered as a slide-over\n * panel inside the widget container. Supports posting top-level comments and\n * threaded replies, resolving/reopening, and (soft) deleting. Data flows through\n * useWidgetComments → the federated EntityComment API.\n */\n\nimport { type FC, useState, useCallback } from 'react';\nimport { MessageSquare, Send, Check, RotateCcw, Trash2, X, CornerDownRight, Loader2 } from 'lucide-react';\nimport { useWidgetComments, type WidgetCommentThread } from '../../../hooks/useWidgetComments';\nimport type { EntityCommentFieldsFragment } from '../../../../generated/wspace-operations';\n\nexport interface WidgetCommentsProps {\n widgetId: string;\n /** Close the panel. */\n onClose: () => void;\n}\n\nfunction authorLabel(authorId: string): string {\n // We only have an opaque actor id here; show a short, stable handle.\n return `User ${authorId.slice(0, 6)}`;\n}\n\nfunction formatWhen(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(d);\n}\n\ninterface CommentItemProps {\n comment: EntityCommentFieldsFragment;\n isReply?: boolean;\n busy: boolean;\n onResolve: (id: string, resolved: boolean) => void;\n onDelete: (id: string) => void;\n onReply?: (id: string) => void;\n}\n\nconst CommentItem: FC<CommentItemProps> = ({ comment, isReply, busy, onResolve, onDelete, onReply }) => {\n const resolved = !!comment.resolvedAt;\n const body = comment.content.text ?? comment.content.markdown ?? '';\n return (\n <div className={isReply ? 'pl-6' : ''}>\n <div className=\"rounded-md border border-border-default bg-bg-surface p-2.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-text-primary\">{authorLabel(comment.authorId)}</span>\n <span className=\"text-[10px] text-text-tertiary tabular-nums\">{formatWhen(comment.createdAt)}</span>\n </div>\n <p className=\"mt-1 whitespace-pre-wrap break-words text-sm text-text-secondary\">{body}</p>\n <div className=\"mt-1.5 flex items-center gap-2\">\n {resolved && (\n <span className=\"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-medium bg-status-success-bg text-status-success-text\">\n <Check className=\"h-3 w-3\" /> Resolved\n </span>\n )}\n {onReply && (\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onReply(comment.id)}\n className=\"inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50\"\n >\n <CornerDownRight className=\"h-3 w-3\" /> Reply\n </button>\n )}\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onResolve(comment.id, !resolved)}\n className=\"inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50\"\n >\n {resolved ? <RotateCcw className=\"h-3 w-3\" /> : <Check className=\"h-3 w-3\" />}\n {resolved ? 'Reopen' : 'Resolve'}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onDelete(comment.id)}\n className=\"inline-flex items-center gap-1 text-[11px] text-status-error-text hover:opacity-80 disabled:opacity-50\"\n >\n <Trash2 className=\"h-3 w-3\" /> Delete\n </button>\n </div>\n </div>\n </div>\n );\n};\n\ninterface ComposerProps {\n placeholder: string;\n busy: boolean;\n autoFocus?: boolean;\n /** Returns false when the post failed — the draft is kept so it isn't lost. */\n onSubmit: (text: string) => boolean | void | Promise<boolean | void>;\n onCancel?: () => void;\n}\n\nconst Composer: FC<ComposerProps> = ({ placeholder, busy, autoFocus, onSubmit, onCancel }) => {\n const [text, setText] = useState('');\n const submit = async () => {\n const v = text.trim();\n if (!v) return;\n // Only clear once the post succeeds; on failure the user keeps their draft.\n const ok = await onSubmit(v);\n if (ok !== false) setText('');\n };\n return (\n <div className=\"flex items-end gap-2\">\n <textarea\n autoFocus={autoFocus}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n void submit();\n }\n }}\n rows={2}\n placeholder={placeholder}\n className=\"flex-1 resize-none rounded-md border border-border-default bg-bg-surface px-2.5 py-1.5 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n disabled={busy || !text.trim()}\n onClick={() => void submit()}\n title=\"Post (⌘/Ctrl + Enter)\"\n className=\"inline-flex items-center justify-center rounded-md bg-action-primary-bg p-1.5 text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Send className=\"h-4 w-4\" />}\n </button>\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"inline-flex items-center justify-center rounded-md border border-border-default p-1.5 text-text-tertiary hover:text-text-primary\"\n title=\"Cancel reply\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport const WidgetComments: FC<WidgetCommentsProps> = ({ widgetId, onClose }) => {\n const { threads, count, loading, error, mutating, addComment, resolveComment, deleteComment } =\n useWidgetComments(widgetId);\n const [replyTo, setReplyTo] = useState<string | null>(null);\n\n const handleAdd = useCallback(\n async (text: string, parentId?: string): Promise<boolean> => {\n const ok = await addComment(text, parentId);\n if (ok && parentId) setReplyTo(null);\n return ok;\n },\n [addComment]\n );\n\n return (\n <div\n className=\"absolute inset-0 z-40 flex flex-col bg-bg-surface/98 backdrop-blur-sm\"\n role=\"dialog\"\n aria-label=\"Widget comments\"\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n }\n }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-default px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-text-primary\">\n <MessageSquare className=\"h-4 w-4 text-text-secondary\" />\n Comments\n <span className=\"rounded-full bg-bg-sunken px-1.5 py-0.5 text-[10px] text-text-secondary tabular-nums\">\n {count}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close comments\"\n className=\"rounded-md p-1 text-text-tertiary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Thread list */}\n <div className=\"flex-1 space-y-3 overflow-auto p-3\">\n {loading && threads.length === 0 && (\n <div className=\"flex items-center justify-center py-8 text-text-tertiary\">\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n </div>\n )}\n {error && !loading && (\n <p className=\"rounded-md bg-status-error-bg px-2.5 py-2 text-xs text-status-error-text\">\n Couldn’t load comments.\n </p>\n )}\n {!loading && !error && threads.length === 0 && (\n <p className=\"py-8 text-center text-sm text-text-tertiary\">No comments yet. Start the conversation.</p>\n )}\n {threads.map(({ comment, replies }: WidgetCommentThread) => (\n <div key={comment.id} className=\"space-y-2\">\n <CommentItem\n comment={comment}\n busy={mutating}\n onResolve={(id, r) => void resolveComment(id, r)}\n onDelete={(id) => void deleteComment(id)}\n onReply={(id) => setReplyTo((cur) => (cur === id ? null : id))}\n />\n {replies.map((reply) => (\n <CommentItem\n key={reply.id}\n comment={reply}\n isReply\n busy={mutating}\n onResolve={(id, r) => void resolveComment(id, r)}\n onDelete={(id) => void deleteComment(id)}\n />\n ))}\n {replyTo === comment.id && (\n <div className=\"pl-6\">\n <Composer\n placeholder=\"Write a reply…\"\n busy={mutating}\n autoFocus\n onSubmit={(text) => handleAdd(text, comment.id)}\n onCancel={() => setReplyTo(null)}\n />\n </div>\n )}\n </div>\n ))}\n </div>\n\n {/* New top-level comment */}\n <div className=\"border-t border-border-default p-3\">\n <Composer placeholder=\"Add a comment…\" busy={mutating} onSubmit={(text) => handleAdd(text)} />\n </div>\n </div>\n );\n};\n\nexport default WidgetComments;\n"],"mappings":"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"}
1
+ {"version":3,"file":"WidgetComments.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/comments/WidgetComments.tsx"],"sourcesContent":["/**\n * WidgetComments\n *\n * Collaborative comment thread for a single widget, rendered as a slide-over\n * panel inside the widget container. Supports posting top-level comments and\n * threaded replies, resolving/reopening, and (soft) deleting. Data flows through\n * useWidgetComments → the federated EntityComment API.\n */\n\nimport { type FC, useState, useCallback } from 'react';\nimport { MessageSquare, Send, Check, RotateCcw, Trash2, X, CornerDownRight, Loader2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useWidgetComments, type WidgetCommentThread } from '../../../hooks/useWidgetComments';\nimport type { EntityCommentFieldsFragment } from '../../../../generated/wspace-operations';\n\nexport interface WidgetCommentsProps {\n widgetId: string;\n /** Close the panel. */\n onClose: () => void;\n}\n\nfunction authorLabel(\n t: (\n key: string,\n fallbackOrParams?: string | Record<string, string | number>,\n params?: Record<string, string | number>\n ) => string,\n authorId: string\n): string {\n // We only have an opaque actor id here; show a short, stable handle.\n return t('bigconsole.widget.comments.authorLabel', 'User {{id}}', { id: authorId.slice(0, 6) });\n}\n\nfunction formatWhen(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(d);\n}\n\ninterface CommentItemProps {\n comment: EntityCommentFieldsFragment;\n isReply?: boolean;\n busy: boolean;\n onResolve: (id: string, resolved: boolean) => void;\n onDelete: (id: string) => void;\n onReply?: (id: string) => void;\n}\n\nconst CommentItem: FC<CommentItemProps> = ({ comment, isReply, busy, onResolve, onDelete, onReply }) => {\n const { t } = useI18n();\n const resolved = !!comment.resolvedAt;\n const body = comment.content.text ?? comment.content.markdown ?? '';\n return (\n <div className={isReply ? 'pl-6' : ''}>\n <div className=\"rounded-md border border-border-default bg-bg-surface p-2.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium text-text-primary\">{authorLabel(t, comment.authorId)}</span>\n <span className=\"text-[10px] text-text-tertiary tabular-nums\">{formatWhen(comment.createdAt)}</span>\n </div>\n <p className=\"mt-1 whitespace-pre-wrap break-words text-sm text-text-secondary\">{body}</p>\n <div className=\"mt-1.5 flex items-center gap-2\">\n {resolved && (\n <span className=\"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-medium bg-status-success-bg text-status-success-text\">\n <Check className=\"h-3 w-3\" /> {t('bigconsole.widget.comments.resolvedBadge', 'Resolved')}\n </span>\n )}\n {onReply && (\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onReply(comment.id)}\n className=\"inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50\"\n >\n <CornerDownRight className=\"h-3 w-3\" /> {t('bigconsole.widget.comments.reply', 'Reply')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onResolve(comment.id, !resolved)}\n className=\"inline-flex items-center gap-1 text-[11px] text-text-tertiary hover:text-text-primary disabled:opacity-50\"\n >\n {resolved ? <RotateCcw className=\"h-3 w-3\" /> : <Check className=\"h-3 w-3\" />}\n {resolved\n ? t('bigconsole.widget.comments.reopen', 'Reopen')\n : t('bigconsole.widget.comments.resolve', 'Resolve')}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => onDelete(comment.id)}\n className=\"inline-flex items-center gap-1 text-[11px] text-status-error-text hover:opacity-80 disabled:opacity-50\"\n >\n <Trash2 className=\"h-3 w-3\" /> {t('bigconsole.widget.comments.delete', 'Delete')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\ninterface ComposerProps {\n placeholder: string;\n busy: boolean;\n autoFocus?: boolean;\n /** Returns false when the post failed — the draft is kept so it isn't lost. */\n onSubmit: (text: string) => boolean | void | Promise<boolean | void>;\n onCancel?: () => void;\n}\n\nconst Composer: FC<ComposerProps> = ({ placeholder, busy, autoFocus, onSubmit, onCancel }) => {\n const { t } = useI18n();\n const [text, setText] = useState('');\n const submit = async () => {\n const v = text.trim();\n if (!v) return;\n // Only clear once the post succeeds; on failure the user keeps their draft.\n const ok = await onSubmit(v);\n if (ok !== false) setText('');\n };\n return (\n <div className=\"flex items-end gap-2\">\n <textarea\n autoFocus={autoFocus}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n void submit();\n }\n }}\n rows={2}\n placeholder={placeholder}\n className=\"flex-1 resize-none rounded-md border border-border-default bg-bg-surface px-2.5 py-1.5 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n disabled={busy || !text.trim()}\n onClick={() => void submit()}\n title={t('bigconsole.widget.comments.postTitle', 'Post (⌘/Ctrl + Enter)')}\n className=\"inline-flex items-center justify-center rounded-md bg-action-primary-bg p-1.5 text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Send className=\"h-4 w-4\" />}\n </button>\n {onCancel && (\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"inline-flex items-center justify-center rounded-md border border-border-default p-1.5 text-text-tertiary hover:text-text-primary\"\n title={t('bigconsole.widget.comments.cancelReplyTitle', 'Cancel reply')}\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport const WidgetComments: FC<WidgetCommentsProps> = ({ widgetId, onClose }) => {\n const { t } = useI18n();\n const { threads, count, loading, error, mutating, addComment, resolveComment, deleteComment } =\n useWidgetComments(widgetId);\n const [replyTo, setReplyTo] = useState<string | null>(null);\n\n const handleAdd = useCallback(\n async (text: string, parentId?: string): Promise<boolean> => {\n const ok = await addComment(text, parentId);\n if (ok && parentId) setReplyTo(null);\n return ok;\n },\n [addComment]\n );\n\n return (\n <div\n className=\"absolute inset-0 z-40 flex flex-col bg-bg-surface/98 backdrop-blur-sm\"\n role=\"dialog\"\n aria-label={t('bigconsole.widget.comments.dialogAriaLabel', 'Widget comments')}\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n }\n }}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-border-default px-3 py-2\">\n <div className=\"flex items-center gap-2 text-sm font-medium text-text-primary\">\n <MessageSquare className=\"h-4 w-4 text-text-secondary\" />\n {t('bigconsole.widget.comments.title', 'Comments')}\n <span className=\"rounded-full bg-bg-sunken px-1.5 py-0.5 text-[10px] text-text-secondary tabular-nums\">\n {count}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t('bigconsole.widget.comments.closeAriaLabel', 'Close comments')}\n className=\"rounded-md p-1 text-text-tertiary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n {/* Thread list */}\n <div className=\"flex-1 space-y-3 overflow-auto p-3\">\n {loading && threads.length === 0 && (\n <div className=\"flex items-center justify-center py-8 text-text-tertiary\">\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n </div>\n )}\n {error && !loading && (\n <p className=\"rounded-md bg-status-error-bg px-2.5 py-2 text-xs text-status-error-text\">\n {t('bigconsole.widget.comments.loadError', 'Couldn’t load comments.')}\n </p>\n )}\n {!loading && !error && threads.length === 0 && (\n <p className=\"py-8 text-center text-sm text-text-tertiary\">\n {t('bigconsole.widget.comments.empty', 'No comments yet. Start the conversation.')}\n </p>\n )}\n {threads.map(({ comment, replies }: WidgetCommentThread) => (\n <div key={comment.id} className=\"space-y-2\">\n <CommentItem\n comment={comment}\n busy={mutating}\n onResolve={(id, r) => void resolveComment(id, r)}\n onDelete={(id) => void deleteComment(id)}\n onReply={(id) => setReplyTo((cur) => (cur === id ? null : id))}\n />\n {replies.map((reply) => (\n <CommentItem\n key={reply.id}\n comment={reply}\n isReply\n busy={mutating}\n onResolve={(id, r) => void resolveComment(id, r)}\n onDelete={(id) => void deleteComment(id)}\n />\n ))}\n {replyTo === comment.id && (\n <div className=\"pl-6\">\n <Composer\n placeholder={t('bigconsole.widget.comments.replyPlaceholder', 'Write a reply…')}\n busy={mutating}\n autoFocus\n onSubmit={(text) => handleAdd(text, comment.id)}\n onCancel={() => setReplyTo(null)}\n />\n </div>\n )}\n </div>\n ))}\n </div>\n\n {/* New top-level comment */}\n <div className=\"border-t border-border-default p-3\">\n <Composer\n placeholder={t('bigconsole.widget.comments.addPlaceholder', 'Add a comment…')}\n busy={mutating}\n onSubmit={(text) => handleAdd(text)}\n />\n </div>\n </div>\n );\n};\n\nexport default WidgetComments;\n"],"mappings":"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"}