@dxos/plugin-thread 0.6.12-staging.e11e696 → 0.6.13-main.548ca8d

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 (71) hide show
  1. package/dist/lib/browser/{ThreadArticle-4VU752F4.mjs → ThreadArticle-GBPIH47W.mjs} +3 -3
  2. package/dist/lib/browser/{ThreadMain-ML3P4XSD.mjs → ThreadMain-PGF7W5EV.mjs} +3 -3
  3. package/dist/lib/browser/{chunk-7NUYW5IW.mjs → chunk-5G3KL6TC.mjs} +4 -6
  4. package/dist/lib/browser/chunk-5G3KL6TC.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-GJRBBPXI.mjs → chunk-JFQZ5W2I.mjs} +2 -2
  6. package/dist/lib/browser/{chunk-GJRBBPXI.mjs.map → chunk-JFQZ5W2I.mjs.map} +1 -1
  7. package/dist/lib/browser/{chunk-XF5QKI75.mjs → chunk-O4YRHIZC.mjs} +2 -2
  8. package/dist/lib/browser/index.mjs +234 -215
  9. package/dist/lib/browser/index.mjs.map +4 -4
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/meta.mjs +1 -1
  12. package/dist/lib/browser/types.mjs +2 -2
  13. package/dist/lib/node/{ThreadArticle-ERUHPHVT.cjs → ThreadArticle-GH5UBWFU.cjs} +7 -7
  14. package/dist/lib/node/{ThreadMain-6DN7FDNB.cjs → ThreadMain-CO6I3DNX.cjs} +7 -7
  15. package/dist/lib/node/{chunk-PZVUW4W2.cjs → chunk-FDYRG7HE.cjs} +9 -9
  16. package/dist/lib/node/{chunk-FXD3DYMO.cjs → chunk-FOZUQZF4.cjs} +6 -6
  17. package/dist/lib/node/{chunk-FXD3DYMO.cjs.map → chunk-FOZUQZF4.cjs.map} +1 -1
  18. package/dist/lib/node/{chunk-6EVXCSDS.cjs → chunk-JIJ7Z6NO.cjs} +6 -8
  19. package/dist/lib/node/chunk-JIJ7Z6NO.cjs.map +7 -0
  20. package/dist/lib/node/index.cjs +272 -255
  21. package/dist/lib/node/index.cjs.map +4 -4
  22. package/dist/lib/node/meta.cjs +4 -4
  23. package/dist/lib/node/meta.cjs.map +1 -1
  24. package/dist/lib/node/meta.json +1 -1
  25. package/dist/lib/node/types.cjs +3 -3
  26. package/dist/lib/node/types.cjs.map +1 -1
  27. package/dist/lib/node-esm/{ThreadArticle-NKI5F4W5.mjs → ThreadArticle-ZTYD52TR.mjs} +3 -3
  28. package/dist/lib/node-esm/{ThreadMain-2A3VQLCW.mjs → ThreadMain-LEHGOF7R.mjs} +3 -3
  29. package/dist/lib/node-esm/{chunk-Y475KZTX.mjs → chunk-DC5ZA6H5.mjs} +4 -6
  30. package/dist/lib/node-esm/chunk-DC5ZA6H5.mjs.map +7 -0
  31. package/dist/lib/node-esm/{chunk-A44C4MTQ.mjs → chunk-XOVJ65DG.mjs} +2 -2
  32. package/dist/lib/node-esm/{chunk-YO46JGAE.mjs → chunk-ZXIPFXSA.mjs} +2 -2
  33. package/dist/lib/node-esm/{chunk-YO46JGAE.mjs.map → chunk-ZXIPFXSA.mjs.map} +1 -1
  34. package/dist/lib/node-esm/index.mjs +234 -215
  35. package/dist/lib/node-esm/index.mjs.map +4 -4
  36. package/dist/lib/node-esm/meta.json +1 -1
  37. package/dist/lib/node-esm/meta.mjs +1 -1
  38. package/dist/lib/node-esm/types.mjs +2 -2
  39. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  40. package/dist/types/src/components/ThreadComplementary.d.ts +2 -2
  41. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  42. package/dist/types/src/components/index.d.ts +3 -2
  43. package/dist/types/src/components/index.d.ts.map +1 -1
  44. package/dist/types/src/extensions/index.d.ts +2 -0
  45. package/dist/types/src/extensions/index.d.ts.map +1 -0
  46. package/dist/types/src/extensions/threads.d.ts +9 -0
  47. package/dist/types/src/extensions/threads.d.ts.map +1 -0
  48. package/dist/types/src/meta.d.ts +3 -6
  49. package/dist/types/src/meta.d.ts.map +1 -1
  50. package/dist/types/src/types.d.ts +5 -0
  51. package/dist/types/src/types.d.ts.map +1 -1
  52. package/package.json +28 -28
  53. package/src/ThreadPlugin.tsx +68 -146
  54. package/src/components/ThreadComplementary.tsx +4 -4
  55. package/src/components/index.ts +3 -2
  56. package/src/extensions/index.ts +5 -0
  57. package/src/extensions/threads.ts +117 -0
  58. package/src/{meta.tsx → meta.ts} +3 -4
  59. package/src/types.ts +7 -2
  60. package/dist/lib/browser/chunk-7NUYW5IW.mjs.map +0 -7
  61. package/dist/lib/node/chunk-6EVXCSDS.cjs.map +0 -7
  62. package/dist/lib/node-esm/chunk-Y475KZTX.mjs.map +0 -7
  63. /package/dist/lib/browser/{ThreadArticle-4VU752F4.mjs.map → ThreadArticle-GBPIH47W.mjs.map} +0 -0
  64. /package/dist/lib/browser/{ThreadMain-ML3P4XSD.mjs.map → ThreadMain-PGF7W5EV.mjs.map} +0 -0
  65. /package/dist/lib/browser/{chunk-XF5QKI75.mjs.map → chunk-O4YRHIZC.mjs.map} +0 -0
  66. /package/dist/lib/node/{ThreadArticle-ERUHPHVT.cjs.map → ThreadArticle-GH5UBWFU.cjs.map} +0 -0
  67. /package/dist/lib/node/{ThreadMain-6DN7FDNB.cjs.map → ThreadMain-CO6I3DNX.cjs.map} +0 -0
  68. /package/dist/lib/node/{chunk-PZVUW4W2.cjs.map → chunk-FDYRG7HE.cjs.map} +0 -0
  69. /package/dist/lib/node-esm/{ThreadArticle-NKI5F4W5.mjs.map → ThreadArticle-ZTYD52TR.mjs.map} +0 -0
  70. /package/dist/lib/node-esm/{ThreadMain-2A3VQLCW.mjs.map → ThreadMain-LEHGOF7R.mjs.map} +0 -0
  71. /package/dist/lib/node-esm/{chunk-A44C4MTQ.mjs.map → chunk-XOVJ65DG.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ThreadAction
3
- } from "./chunk-GJRBBPXI.mjs";
3
+ } from "./chunk-JFQZ5W2I.mjs";
4
4
  import {
5
5
  ChatContainer,
6
6
  ChatHeading,
@@ -10,67 +10,49 @@ import {
10
10
  useAnalyticsCallback,
11
11
  useOnEditAnalytics,
12
12
  useStatus
13
- } from "./chunk-XF5QKI75.mjs";
13
+ } from "./chunk-O4YRHIZC.mjs";
14
14
  import {
15
15
  THREAD_ITEM,
16
16
  THREAD_PLUGIN,
17
17
  meta_default
18
- } from "./chunk-7NUYW5IW.mjs";
18
+ } from "./chunk-5G3KL6TC.mjs";
19
19
 
20
20
  // packages/plugins/plugin-thread/src/ThreadPlugin.tsx
21
- import { computed, effect } from "@preact/signals-core";
22
21
  import React6 from "react";
23
- import { LayoutAction as LayoutAction2, NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, isLayoutParts, parseMetadataResolverPlugin } from "@dxos/app-framework";
24
- import { getTypename } from "@dxos/echo-schema";
25
- import { create as create2 } from "@dxos/echo-schema";
22
+ import { NavigationAction, isLayoutParts, parseIntentPlugin, parseNavigationPlugin, parseMetadataResolverPlugin, resolvePlugin } from "@dxos/app-framework";
23
+ import { create as create2, getTypename } from "@dxos/echo-schema";
26
24
  import { LocalStorageStore } from "@dxos/local-storage";
27
25
  import { log } from "@dxos/log";
28
26
  import { parseClientPlugin } from "@dxos/plugin-client";
29
27
  import { createExtension, isActionGroup, toSignal } from "@dxos/plugin-graph";
30
28
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
31
29
  import { SpaceAction } from "@dxos/plugin-space";
32
- import { ThreadType, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
33
- import { getSpace as getSpace2, getTextInRange, createDocAccessor, fullyQualifiedId as fullyQualifiedId4, loadObjectReferences } from "@dxos/react-client/echo";
34
- import { comments, createExternalCommentSync, listener as listener2 } from "@dxos/react-ui-editor";
30
+ import { ThreadType as ThreadType2, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
31
+ import { getSpace as getSpace3, fullyQualifiedId as fullyQualifiedId5, loadObjectReferences, parseFullyQualifiedId } from "@dxos/react-client/echo";
35
32
  import { translations as threadTranslations } from "@dxos/react-ui-thread";
36
- import { nonNullable as nonNullable3 } from "@dxos/util";
37
33
 
38
34
  // packages/plugins/plugin-thread/src/components/index.ts
39
- import React4 from "react";
40
-
41
- // packages/plugins/plugin-thread/src/components/ThreadSettings.tsx
42
- import React from "react";
43
- import { SettingsValue } from "@dxos/plugin-settings";
44
- import { Input, useTranslation } from "@dxos/react-ui";
45
- var ThreadSettings = ({ settings }) => {
46
- const { t } = useTranslation(THREAD_PLUGIN);
47
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(SettingsValue, {
48
- label: t("settings standalone label")
49
- }, /* @__PURE__ */ React.createElement(Input.Switch, {
50
- checked: settings.standalone,
51
- onCheckedChange: (checked) => settings.standalone = !!checked
52
- })));
53
- };
35
+ import React5 from "react";
54
36
 
55
37
  // packages/plugins/plugin-thread/src/components/CommentContainer.tsx
56
38
  import { CheckCircle, X } from "@phosphor-icons/react";
57
- import React2, { useCallback, useMemo, useRef, useState } from "react";
39
+ import React, { useCallback, useMemo, useRef, useState } from "react";
58
40
  import { create } from "@dxos/echo-schema";
59
41
  import { MessageType } from "@dxos/plugin-space/types";
60
42
  import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
61
43
  import { useIdentity } from "@dxos/react-client/halo";
62
- import { Button, Tag, Tooltip, useThemeContext, useTranslation as useTranslation2 } from "@dxos/react-ui";
44
+ import { Button, Tag, Tooltip, useThemeContext, useTranslation } from "@dxos/react-ui";
63
45
  import { createBasicExtensions, createThemeExtensions, listener } from "@dxos/react-ui-editor";
64
46
  import { getSize, hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from "@dxos/react-ui-theme";
65
47
  import { MessageTextbox, Thread, ThreadFooter, ThreadHeading } from "@dxos/react-ui-thread";
66
48
  import { nonNullable } from "@dxos/util";
67
49
  var sizeClass = getSize(4);
68
50
  var ToggleResolvedButton = ({ isResolved, onResolve }) => {
69
- const { t } = useTranslation2(THREAD_PLUGIN);
51
+ const { t } = useTranslation(THREAD_PLUGIN);
70
52
  const label = t(isResolved ? "mark as unresolved label" : "mark as resolved label");
71
- return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
53
+ return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
72
54
  asChild: true
73
- }, /* @__PURE__ */ React2.createElement(Button, {
55
+ }, /* @__PURE__ */ React.createElement(Button, {
74
56
  variant: "ghost",
75
57
  "data-testid": "thread.toggle-resolved",
76
58
  onClick: onResolve,
@@ -78,23 +60,23 @@ var ToggleResolvedButton = ({ isResolved, onResolve }) => {
78
60
  "min-bs-0 p-1",
79
61
  !isResolved && hoverableControlItem
80
62
  ]
81
- }, /* @__PURE__ */ React2.createElement("span", {
63
+ }, /* @__PURE__ */ React.createElement("span", {
82
64
  className: "sr-only"
83
- }, label), isResolved ? /* @__PURE__ */ React2.createElement(CheckCircle, {
65
+ }, label), isResolved ? /* @__PURE__ */ React.createElement(CheckCircle, {
84
66
  className: sizeClass,
85
67
  weight: "fill"
86
- }) : /* @__PURE__ */ React2.createElement(CheckCircle, {
68
+ }) : /* @__PURE__ */ React.createElement(CheckCircle, {
87
69
  className: sizeClass
88
- }))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, {
70
+ }))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
89
71
  classNames: "z-[21]"
90
- }, label, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
72
+ }, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
91
73
  };
92
74
  var DeleteThreadButton = ({ onDelete }) => {
93
- const { t } = useTranslation2(THREAD_PLUGIN);
75
+ const { t } = useTranslation(THREAD_PLUGIN);
94
76
  const label = t("delete thread label");
95
- return /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
77
+ return /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
96
78
  asChild: true
97
- }, /* @__PURE__ */ React2.createElement(Button, {
79
+ }, /* @__PURE__ */ React.createElement(Button, {
98
80
  variant: "ghost",
99
81
  "data-testid": "thread.delete",
100
82
  onClick: onDelete,
@@ -102,20 +84,20 @@ var DeleteThreadButton = ({ onDelete }) => {
102
84
  "min-bs-0 p-1",
103
85
  hoverableControlItem
104
86
  ]
105
- }, /* @__PURE__ */ React2.createElement("span", {
87
+ }, /* @__PURE__ */ React.createElement("span", {
106
88
  className: "sr-only"
107
- }, label), /* @__PURE__ */ React2.createElement(X, {
89
+ }, label), /* @__PURE__ */ React.createElement(X, {
108
90
  className: sizeClass
109
- }))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, {
91
+ }))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
110
92
  classNames: "z-[21]"
111
- }, label, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
93
+ }, label, /* @__PURE__ */ React.createElement(Tooltip.Arrow, null))));
112
94
  };
113
95
  var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
114
96
  const identity = useIdentity();
115
97
  const space = getSpace(thread);
116
98
  const members = useMembers(space?.key);
117
99
  const activity = useStatus(space, fullyQualifiedId(thread));
118
- const { t } = useTranslation2(THREAD_PLUGIN);
100
+ const { t } = useTranslation(THREAD_PLUGIN);
119
101
  const threadScrollRef = useRef(null);
120
102
  const { themeMode } = useThemeContext();
121
103
  const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);
@@ -161,42 +143,42 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
161
143
  thread,
162
144
  identity
163
145
  ]);
164
- return /* @__PURE__ */ React2.createElement(Thread, {
146
+ return /* @__PURE__ */ React.createElement(Thread, {
165
147
  onClickCapture: onAttend,
166
148
  onFocusCapture: onAttend,
167
149
  current,
168
150
  id: fullyQualifiedId(thread)
169
- }, /* @__PURE__ */ React2.createElement("div", {
151
+ }, /* @__PURE__ */ React.createElement("div", {
170
152
  role: "none",
171
153
  className: mx("col-span-2 grid grid-cols-[var(--rail-size)_1fr_min-content]", hoverableControls, hoverableFocusedWithinControls)
172
- }, detached ? /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
154
+ }, detached ? /* @__PURE__ */ React.createElement(Tooltip.Root, null, /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
173
155
  asChild: true
174
- }, /* @__PURE__ */ React2.createElement(ThreadHeading, {
156
+ }, /* @__PURE__ */ React.createElement(ThreadHeading, {
175
157
  detached: true
176
- }, thread.name ?? t("thread title placeholder"))), /* @__PURE__ */ React2.createElement(Tooltip.Portal, null, /* @__PURE__ */ React2.createElement(Tooltip.Content, {
158
+ }, thread.name ?? t("thread title placeholder"))), /* @__PURE__ */ React.createElement(Tooltip.Portal, null, /* @__PURE__ */ React.createElement(Tooltip.Content, {
177
159
  classNames: "z-[21]",
178
160
  side: "top"
179
- }, t("detached thread label"), /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null)))) : /* @__PURE__ */ React2.createElement(ThreadHeading, null, thread.name ?? t("thread title placeholder")), /* @__PURE__ */ React2.createElement("div", {
161
+ }, t("detached thread label"), /* @__PURE__ */ React.createElement(Tooltip.Arrow, null)))) : /* @__PURE__ */ React.createElement(ThreadHeading, null, thread.name ?? t("thread title placeholder")), /* @__PURE__ */ React.createElement("div", {
180
162
  className: "flex flex-row items-center pli-1"
181
- }, thread.status === "staged" && /* @__PURE__ */ React2.createElement(Tag, {
163
+ }, thread.status === "staged" && /* @__PURE__ */ React.createElement(Tag, {
182
164
  palette: "neutral"
183
- }, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */ React2.createElement(ToggleResolvedButton, {
165
+ }, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */ React.createElement(ToggleResolvedButton, {
184
166
  isResolved: thread?.status === "resolved",
185
167
  onResolve
186
- }), onThreadDelete && /* @__PURE__ */ React2.createElement(DeleteThreadButton, {
168
+ }), onThreadDelete && /* @__PURE__ */ React.createElement(DeleteThreadButton, {
187
169
  onDelete: onThreadDelete
188
- }))), thread.messages.filter(nonNullable).map((message) => /* @__PURE__ */ React2.createElement(MessageContainer, {
170
+ }))), thread.messages.filter(nonNullable).map((message) => /* @__PURE__ */ React.createElement(MessageContainer, {
189
171
  key: message.id,
190
172
  message,
191
173
  members,
192
174
  onDelete: (id) => onMessageDelete?.(id)
193
- })), /* @__PURE__ */ React2.createElement(MessageTextbox, {
175
+ })), /* @__PURE__ */ React.createElement(MessageTextbox, {
194
176
  extensions,
195
177
  onSend: handleCreate,
196
178
  ...textboxMetadata
197
- }), /* @__PURE__ */ React2.createElement(ThreadFooter, {
179
+ }), /* @__PURE__ */ React.createElement(ThreadFooter, {
198
180
  activity
199
- }, t("activity message")), /* @__PURE__ */ React2.createElement("div", {
181
+ }, t("activity message")), /* @__PURE__ */ React.createElement("div", {
200
182
  role: "none",
201
183
  className: "bs-px -mbs-px",
202
184
  ref: threadScrollRef
@@ -205,13 +187,13 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
205
187
 
206
188
  // packages/plugins/plugin-thread/src/components/CommentsContainer.tsx
207
189
  import { ChatText } from "@phosphor-icons/react";
208
- import React3, { useEffect } from "react";
190
+ import React2, { useEffect } from "react";
209
191
  import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
210
- import { useTranslation as useTranslation3, Trans } from "@dxos/react-ui";
192
+ import { useTranslation as useTranslation2, Trans } from "@dxos/react-ui";
211
193
  import { descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
212
- var CommentsContainer = ({ threads, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
213
- const { t } = useTranslation3(THREAD_PLUGIN);
214
- const filteredThreads = showResolvedThreads ? threads : threads.filter((thread) => !(thread?.status === "resolved"));
194
+ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
195
+ const { t } = useTranslation2(THREAD_PLUGIN);
196
+ const filteredThreads = showResolvedThreads ? threads2 : threads2.filter((thread) => !(thread?.status === "resolved"));
215
197
  useEffect(() => {
216
198
  if (currentId) {
217
199
  document.getElementById(currentId)?.scrollIntoView({
@@ -222,9 +204,9 @@ var CommentsContainer = ({ threads, detached = [], currentId, showResolvedThread
222
204
  }, [
223
205
  currentId
224
206
  ]);
225
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
207
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
226
208
  const threadId = fullyQualifiedId2(thread);
227
- return /* @__PURE__ */ React3.createElement(CommentContainer, {
209
+ return /* @__PURE__ */ React2.createElement(CommentContainer, {
228
210
  key: threadId,
229
211
  thread,
230
212
  current: currentId === threadId,
@@ -243,35 +225,31 @@ var CommentsContainer = ({ threads, detached = [], currentId, showResolvedThread
243
225
  },
244
226
  ...props
245
227
  });
246
- }) : /* @__PURE__ */ React3.createElement("div", {
228
+ }) : /* @__PURE__ */ React2.createElement("div", {
247
229
  role: "alert",
248
230
  className: mx2(descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
249
- }, /* @__PURE__ */ React3.createElement("h2", {
231
+ }, /* @__PURE__ */ React2.createElement("h2", {
250
232
  className: "mbe-2 font-medium text-baseText"
251
- }, t("no comments title")), /* @__PURE__ */ React3.createElement("p", null, /* @__PURE__ */ React3.createElement(Trans, {
233
+ }, t("no comments title")), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement(Trans, {
252
234
  t,
253
235
  i18nKey: "no comments message",
254
236
  components: {
255
- commentIcon: /* @__PURE__ */ React3.createElement(ChatText, {
237
+ commentIcon: /* @__PURE__ */ React2.createElement(ChatText, {
256
238
  className: "inline-block"
257
239
  })
258
240
  }
259
241
  }))));
260
242
  };
261
243
 
262
- // packages/plugins/plugin-thread/src/components/index.ts
263
- var ThreadMain = React4.lazy(() => import("./ThreadMain-ML3P4XSD.mjs"));
264
- var ThreadArticle = React4.lazy(() => import("./ThreadArticle-4VU752F4.mjs"));
265
-
266
244
  // packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
267
- import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
245
+ import React3, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
268
246
  import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
269
247
  import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
270
248
  import { ScrollArea } from "@dxos/react-ui";
271
249
  import { useAttended } from "@dxos/react-ui-attention";
272
250
  import { nonNullable as nonNullable2 } from "@dxos/util";
273
251
  var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
274
- var ThreadComplementary = ({ role, subject, stagedThreads, current, showResolvedThreads }) => {
252
+ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
275
253
  const dispatch = useIntentDispatcher();
276
254
  const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
277
255
  const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
@@ -285,35 +263,35 @@ var ThreadComplementary = ({ role, subject, stagedThreads, current, showResolved
285
263
  createSort,
286
264
  subject
287
265
  ]);
288
- const threads = useMemo2(() => {
289
- return subject.threads.concat(stagedThreads ?? []).filter(nonNullable2);
266
+ const threads2 = useMemo2(() => {
267
+ return subject.threads.concat(drafts ?? []).filter(nonNullable2);
290
268
  }, [
291
269
  JSON.stringify(subject.threads),
292
- JSON.stringify(stagedThreads)
270
+ JSON.stringify(drafts)
293
271
  ]);
294
272
  const detachedIds = useMemo2(() => {
295
- return threads.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
273
+ return threads2.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
296
274
  }, [
297
- threads
275
+ threads2
298
276
  ]);
299
277
  useEffect2(() => {
300
278
  if (!sort) {
301
279
  return;
302
280
  }
303
- threads.sort((a, b) => sort(a?.anchor, b?.anchor));
281
+ threads2.sort((a, b) => sort(a?.anchor, b?.anchor));
304
282
  }, [
305
283
  sort,
306
- threads
284
+ threads2
307
285
  ]);
308
286
  const attended = useAttended();
309
287
  const qualifiedSubjectId = fullyQualifiedId3(subject);
310
- return /* @__PURE__ */ React5.createElement("div", {
288
+ return /* @__PURE__ */ React3.createElement("div", {
311
289
  role: "none",
312
290
  className: "contents"
313
- }, /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
291
+ }, /* @__PURE__ */ React3.createElement(ScrollArea.Root, {
314
292
  classNames: "row-span-2"
315
- }, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
316
- threads,
293
+ }, /* @__PURE__ */ React3.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React3.createElement(CommentsContainer, {
294
+ threads: threads2,
317
295
  detached: detachedIds,
318
296
  currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
319
297
  showResolvedThreads,
@@ -368,10 +346,117 @@ var ThreadComplementary = ({ role, subject, stagedThreads, current, showResolved
368
346
  }
369
347
  });
370
348
  }
371
- }), /* @__PURE__ */ React5.createElement("div", {
349
+ }), /* @__PURE__ */ React3.createElement("div", {
372
350
  role: "none",
373
351
  className: "bs-10"
374
- }), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
352
+ }), /* @__PURE__ */ React3.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React3.createElement(ScrollArea.Thumb, null)))));
353
+ };
354
+
355
+ // packages/plugins/plugin-thread/src/components/ThreadSettings.tsx
356
+ import React4 from "react";
357
+ import { SettingsValue } from "@dxos/plugin-settings";
358
+ import { Input, useTranslation as useTranslation3 } from "@dxos/react-ui";
359
+ var ThreadSettings = ({ settings }) => {
360
+ const { t } = useTranslation3(THREAD_PLUGIN);
361
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(SettingsValue, {
362
+ label: t("settings standalone label")
363
+ }, /* @__PURE__ */ React4.createElement(Input.Switch, {
364
+ checked: settings.standalone,
365
+ onCheckedChange: (checked) => settings.standalone = !!checked
366
+ })));
367
+ };
368
+
369
+ // packages/plugins/plugin-thread/src/components/index.ts
370
+ var ThreadMain = React5.lazy(() => import("./ThreadMain-PGF7W5EV.mjs"));
371
+ var ThreadArticle = React5.lazy(() => import("./ThreadArticle-GBPIH47W.mjs"));
372
+
373
+ // packages/plugins/plugin-thread/src/extensions/threads.ts
374
+ import { EditorView } from "@codemirror/view";
375
+ import { computed, effect } from "@preact/signals-core";
376
+ import { ThreadType } from "@dxos/plugin-space/types";
377
+ import { getSpace as getSpace2, getTextInRange, createDocAccessor, fullyQualifiedId as fullyQualifiedId4 } from "@dxos/react-client/echo";
378
+ import { comments, createExternalCommentSync } from "@dxos/react-ui-editor";
379
+ import { nonNullable as nonNullable3 } from "@dxos/util";
380
+ var getName = (doc, anchor) => {
381
+ if (doc.content) {
382
+ const [start, end] = anchor.split(":");
383
+ return getTextInRange(createDocAccessor(doc.content, [
384
+ "content"
385
+ ]), start, end);
386
+ }
387
+ };
388
+ var threads = (state, doc, dispatch) => {
389
+ const space = doc && getSpace2(doc);
390
+ if (!doc || !space || !dispatch) {
391
+ return [
392
+ comments()
393
+ ];
394
+ }
395
+ const threads2 = computed(() => [
396
+ ...doc.threads.filter(nonNullable3),
397
+ ...state.drafts[fullyQualifiedId4(doc)] ?? []
398
+ ].filter((thread) => !(thread?.status === "resolved")));
399
+ return [
400
+ EditorView.updateListener.of((update) => {
401
+ if (update.docChanged) {
402
+ doc.threads.forEach((thread) => {
403
+ if (thread?.anchor) {
404
+ const name = getName(doc, thread.anchor);
405
+ if (name && name !== thread.name) {
406
+ thread.name = name;
407
+ }
408
+ }
409
+ });
410
+ }
411
+ }),
412
+ createExternalCommentSync(fullyQualifiedId4(doc), (sink) => effect(() => sink()), () => threads2.value.filter((thread) => thread?.anchor).map((thread) => ({
413
+ id: fullyQualifiedId4(thread),
414
+ cursor: thread.anchor
415
+ }))),
416
+ comments({
417
+ id: fullyQualifiedId4(doc),
418
+ onCreate: ({ cursor }) => {
419
+ const name = getName(doc, cursor);
420
+ void dispatch({
421
+ action: ThreadAction.CREATE,
422
+ data: {
423
+ cursor,
424
+ name,
425
+ subject: doc
426
+ }
427
+ });
428
+ },
429
+ onDelete: ({ id }) => {
430
+ const draft = state.drafts[fullyQualifiedId4(doc)];
431
+ if (draft) {
432
+ const index = draft.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
433
+ if (index !== -1) {
434
+ draft.splice(index, 1);
435
+ }
436
+ }
437
+ const thread = doc.threads.find((thread2) => thread2?.id === id);
438
+ if (thread) {
439
+ thread.anchor = void 0;
440
+ }
441
+ },
442
+ onUpdate: ({ id, cursor }) => {
443
+ const thread = state.drafts[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
444
+ if (thread instanceof ThreadType && thread.anchor) {
445
+ thread.name = getName(doc, thread.anchor);
446
+ thread.anchor = cursor;
447
+ }
448
+ },
449
+ onSelect: ({ selection: { current, closest } }) => {
450
+ void dispatch({
451
+ action: ThreadAction.SELECT,
452
+ data: {
453
+ current: current ?? closest,
454
+ skipOpen: true
455
+ }
456
+ });
457
+ }
458
+ })
459
+ ];
375
460
  };
376
461
 
377
462
  // packages/plugins/plugin-thread/src/translations.ts
@@ -418,7 +503,7 @@ var initialViewState = {
418
503
  var ThreadPlugin = () => {
419
504
  const settings = new LocalStorageStore(THREAD_PLUGIN);
420
505
  const state = create2({
421
- staging: {}
506
+ drafts: {}
422
507
  });
423
508
  const viewStore = create2({});
424
509
  const getViewState = (subjectId) => {
@@ -462,7 +547,7 @@ var ThreadPlugin = () => {
462
547
  // TODO(wittjosiah): Move out of metadata.
463
548
  loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
464
549
  },
465
- [ThreadType.typename]: {
550
+ [ThreadType2.typename]: {
466
551
  // TODO(wittjosiah): Move out of metadata.
467
552
  loadReferences: (thread) => loadObjectReferences(thread, (thread2) => thread2.messages)
468
553
  },
@@ -498,7 +583,7 @@ var ThreadPlugin = () => {
498
583
  echo: {
499
584
  schema: [
500
585
  ChannelType,
501
- ThreadType,
586
+ ThreadType2,
502
587
  MessageType2
503
588
  ]
504
589
  },
@@ -517,8 +602,8 @@ var ThreadPlugin = () => {
517
602
  if (!id.endsWith("~comments")) {
518
603
  return;
519
604
  }
520
- const subjectId = id.split("~").at(0);
521
- const [spaceId, objectId] = subjectId?.split(":") ?? [];
605
+ const [subjectId] = id.split("~");
606
+ const [spaceId, objectId] = parseFullyQualifiedId(subjectId);
522
607
  const space = client.spaces.get().find((space2) => space2.id === spaceId);
523
608
  const object = toSignal((onChange) => {
524
609
  const timeout = setTimeout(async () => {
@@ -654,8 +739,7 @@ var ThreadPlugin = () => {
654
739
  settings: settings.values
655
740
  }) : null;
656
741
  }
657
- case "article":
658
- case "complementary": {
742
+ case "article": {
659
743
  const location = navigationPlugin?.provides.location;
660
744
  if (data.object instanceof ChannelType && data.object.threads[0]) {
661
745
  const channel = data.object;
@@ -664,7 +748,7 @@ var ThreadPlugin = () => {
664
748
  const currentPosition = layoutEntries.findIndex((entry) => channel.id === entry.id);
665
749
  if (currentPosition > 0) {
666
750
  const objectToTheLeft = layoutEntries[currentPosition - 1];
667
- const context = getSpace2(data.object)?.db.getObjectById(objectToTheLeft.id);
751
+ const context = getSpace3(data.object)?.db.getObjectById(objectToTheLeft.id);
668
752
  return /* @__PURE__ */ React6.createElement(ThreadArticle, {
669
753
  thread: data.object.threads[0],
670
754
  context
@@ -675,23 +759,27 @@ var ThreadPlugin = () => {
675
759
  thread: data.object.threads[0]
676
760
  });
677
761
  }
678
- if (data.subject instanceof ThreadType) {
762
+ if (data.subject instanceof ThreadType2) {
679
763
  return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(ChatHeading, {
680
764
  attendableId: data.subject.id
681
765
  }), /* @__PURE__ */ React6.createElement(ChatContainer, {
682
766
  thread: data.subject
683
767
  }));
684
768
  }
769
+ break;
770
+ }
771
+ case "complementary--comments": {
685
772
  if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads)) {
686
- const { showResolvedThreads } = getViewState(fullyQualifiedId4(data.subject));
773
+ const { showResolvedThreads } = getViewState(fullyQualifiedId5(data.subject));
687
774
  return /* @__PURE__ */ React6.createElement(ThreadComplementary, {
688
775
  role,
689
776
  subject: data.subject,
690
- stagedThreads: state.staging[fullyQualifiedId4(data.subject)],
777
+ drafts: state.drafts[fullyQualifiedId5(data.subject)],
691
778
  current: state.current,
692
779
  showResolvedThreads
693
780
  });
694
781
  }
782
+ break;
695
783
  }
696
784
  }
697
785
  return null;
@@ -706,28 +794,28 @@ var ThreadPlugin = () => {
706
794
  if (subject?.threads === void 0) {
707
795
  try {
708
796
  subject.threads = [];
709
- } catch (e) {
797
+ } catch (err) {
710
798
  log.error("Subject does not support threads array", subject?.typename, {
711
799
  F: __dxlog_file,
712
- L: 331,
800
+ L: 327,
713
801
  S: void 0,
714
802
  C: (f, a) => f(...a)
715
803
  });
716
804
  return;
717
805
  }
718
806
  }
719
- const subjectId = fullyQualifiedId4(subject);
720
- const thread = create2(ThreadType, {
807
+ const subjectId = fullyQualifiedId5(subject);
808
+ const thread = create2(ThreadType2, {
721
809
  name,
722
810
  anchor: cursor,
723
811
  messages: [],
724
812
  status: "staged"
725
813
  });
726
- const stagingArea = state.staging[subjectId];
727
- if (stagingArea) {
728
- stagingArea.push(thread);
814
+ const draft = state.drafts[subjectId];
815
+ if (draft) {
816
+ draft.push(thread);
729
817
  } else {
730
- state.staging[subjectId] = [
818
+ state.drafts[subjectId] = [
731
819
  thread
732
820
  ];
733
821
  }
@@ -738,15 +826,17 @@ var ThreadPlugin = () => {
738
826
  {
739
827
  action: ThreadAction.SELECT,
740
828
  data: {
741
- current: fullyQualifiedId4(thread)
829
+ current: fullyQualifiedId5(thread)
742
830
  }
743
- },
831
+ }
832
+ ],
833
+ [
744
834
  {
745
- action: LayoutAction2.SET_LAYOUT,
835
+ action: NavigationAction.OPEN,
746
836
  data: {
747
- element: "complementary",
748
- subject: subjectId,
749
- state: true
837
+ activeParts: {
838
+ complementary: "comments"
839
+ }
750
840
  }
751
841
  }
752
842
  ]
@@ -756,7 +846,7 @@ var ThreadPlugin = () => {
756
846
  return {
757
847
  data: create2(ChannelType, {
758
848
  threads: [
759
- create2(ThreadType, {
849
+ create2(ThreadType2, {
760
850
  messages: []
761
851
  })
762
852
  ]
@@ -767,12 +857,24 @@ var ThreadPlugin = () => {
767
857
  case ThreadAction.SELECT: {
768
858
  state.current = intent.data?.current;
769
859
  return {
770
- data: true
860
+ data: true,
861
+ intents: !intent.data?.skipOpen ? [
862
+ [
863
+ {
864
+ action: NavigationAction.OPEN,
865
+ data: {
866
+ activeParts: {
867
+ complementary: "comments"
868
+ }
869
+ }
870
+ }
871
+ ]
872
+ ] : []
771
873
  };
772
874
  }
773
875
  case ThreadAction.TOGGLE_RESOLVED: {
774
876
  const { thread } = intent.data ?? {};
775
- if (!(thread instanceof ThreadType)) {
877
+ if (!(thread instanceof ThreadType2)) {
776
878
  return;
777
879
  }
778
880
  if (thread.status === "active" || thread.status === void 0) {
@@ -780,9 +882,10 @@ var ThreadPlugin = () => {
780
882
  } else if (thread.status === "resolved") {
781
883
  thread.status = "active";
782
884
  }
783
- const space = getSpace2(thread);
885
+ const space = getSpace3(thread);
784
886
  const spaceId = space?.id;
785
887
  return {
888
+ data: true,
786
889
  intents: [
787
890
  [
788
891
  {
@@ -801,21 +904,21 @@ var ThreadPlugin = () => {
801
904
  }
802
905
  case ThreadAction.DELETE: {
803
906
  const { subject, thread } = intent.data ?? {};
804
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
907
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
805
908
  return;
806
909
  }
807
- const subjectId = fullyQualifiedId4(subject);
808
- const stagingArea = state.staging[subjectId];
809
- if (stagingArea) {
810
- const index = stagingArea.findIndex((t) => t.id === thread.id);
910
+ const subjectId = fullyQualifiedId5(subject);
911
+ const draft = state.drafts[subjectId];
912
+ if (draft) {
913
+ const index = draft.findIndex((t) => t.id === thread.id);
811
914
  if (index !== -1) {
812
- stagingArea.splice(index, 1);
915
+ draft.splice(index, 1);
813
916
  return {
814
917
  data: true
815
918
  };
816
919
  }
817
920
  }
818
- const space = getSpace2(thread);
921
+ const space = getSpace3(thread);
819
922
  if (!space || !subject.threads) {
820
923
  return;
821
924
  }
@@ -873,22 +976,22 @@ var ThreadPlugin = () => {
873
976
  }
874
977
  case ThreadAction.ON_MESSAGE_ADD: {
875
978
  const { thread, subject } = intent.data ?? {};
876
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
979
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
877
980
  return;
878
981
  }
879
- const subjectId = fullyQualifiedId4(subject);
880
- const space = getSpace2(subject);
982
+ const subjectId = fullyQualifiedId5(subject);
983
+ const space = getSpace3(subject);
881
984
  const intents = [];
882
985
  const analyticsProperties = {
883
986
  threadId: thread.id,
884
987
  spaceId: space?.id
885
988
  };
886
- if (state.staging[subjectId]?.find((t) => t === thread)) {
989
+ if (state.drafts[subjectId]?.find((t) => t === thread)) {
887
990
  thread.status = "active";
888
991
  subject.threads ? subject.threads.push(thread) : subject.threads = [
889
992
  thread
890
993
  ];
891
- state.staging[subjectId] = state.staging[subjectId]?.filter((t) => t.id !== thread.id);
994
+ state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
892
995
  intents.push({
893
996
  action: ObservabilityAction.SEND_EVENT,
894
997
  data: {
@@ -916,8 +1019,8 @@ var ThreadPlugin = () => {
916
1019
  }
917
1020
  case ThreadAction.DELETE_MESSAGE: {
918
1021
  const { subject, thread, messageId } = intent.data ?? {};
919
- const space = getSpace2(subject);
920
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
1022
+ const space = getSpace3(subject);
1023
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
921
1024
  return;
922
1025
  }
923
1026
  if (!intent.undo) {
@@ -996,92 +1099,8 @@ var ThreadPlugin = () => {
996
1099
  }
997
1100
  },
998
1101
  markdown: {
999
- // TODO(burdon): Factor out extension factory into separate file (for simplicity).
1000
1102
  extensions: ({ document: doc }) => {
1001
- const space = doc && getSpace2(doc);
1002
- if (!doc || !space) {
1003
- return [
1004
- comments()
1005
- ];
1006
- }
1007
- const threads = computed(() => [
1008
- ...doc.threads.filter(nonNullable3),
1009
- ...state.staging[fullyQualifiedId4(doc)] ?? []
1010
- ].filter((thread) => !(thread?.status === "resolved")));
1011
- return [
1012
- listener2({
1013
- onChange: () => {
1014
- doc.threads.forEach((thread) => {
1015
- if (thread?.anchor) {
1016
- const [start, end] = thread.anchor.split(":");
1017
- const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1018
- "content"
1019
- ]), start, end);
1020
- if (name && name !== thread.name) {
1021
- thread.name = name;
1022
- }
1023
- }
1024
- });
1025
- }
1026
- }),
1027
- createExternalCommentSync(fullyQualifiedId4(doc), (sink) => effect(() => sink()), () => threads.value.filter((thread) => thread?.anchor).map((thread) => ({
1028
- id: fullyQualifiedId4(thread),
1029
- cursor: thread.anchor
1030
- }))),
1031
- comments({
1032
- id: fullyQualifiedId4(doc),
1033
- onCreate: ({ cursor }) => {
1034
- const [start, end] = cursor.split(":");
1035
- const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1036
- "content"
1037
- ]), start, end);
1038
- void intentPlugin?.provides.intent.dispatch({
1039
- action: ThreadAction.CREATE,
1040
- data: {
1041
- cursor,
1042
- name,
1043
- subject: doc
1044
- }
1045
- });
1046
- },
1047
- onDelete: ({ id }) => {
1048
- const stagingArea = state.staging[fullyQualifiedId4(doc)];
1049
- if (stagingArea) {
1050
- const index = stagingArea.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
1051
- if (index !== -1) {
1052
- stagingArea.splice(index, 1);
1053
- }
1054
- }
1055
- const thread = doc.threads.find((thread2) => thread2?.id === id);
1056
- if (thread) {
1057
- thread.anchor = void 0;
1058
- }
1059
- },
1060
- onUpdate: ({ id, cursor }) => {
1061
- const thread = state.staging[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
1062
- if (thread instanceof ThreadType && thread.anchor) {
1063
- const [start, end] = thread.anchor.split(":");
1064
- thread.name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1065
- "content"
1066
- ]), start, end);
1067
- thread.anchor = cursor;
1068
- }
1069
- },
1070
- onSelect: ({ selection: { current, closest } }) => {
1071
- const dispatch = intentPlugin?.provides.intent.dispatch;
1072
- if (dispatch) {
1073
- void dispatch([
1074
- {
1075
- action: ThreadAction.SELECT,
1076
- data: {
1077
- current: current ?? closest
1078
- }
1079
- }
1080
- ]);
1081
- }
1082
- }
1083
- })
1084
- ];
1103
+ return threads(state, doc, intentPlugin?.provides.intent.dispatch);
1085
1104
  }
1086
1105
  }
1087
1106
  }