@dxos/plugin-thread 0.6.12-main.15a606f → 0.6.12-main.2d19bf1

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 (74) 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 +185 -196
  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 +207 -220
  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 +185 -196
  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/CommentContainer.d.ts +1 -1
  41. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  42. package/dist/types/src/components/CommentsContainer.d.ts +1 -5
  43. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  44. package/dist/types/src/components/ThreadComplementary.d.ts +2 -3
  45. package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
  46. package/dist/types/src/extensions/index.d.ts +2 -0
  47. package/dist/types/src/extensions/index.d.ts.map +1 -0
  48. package/dist/types/src/extensions/threads.d.ts +9 -0
  49. package/dist/types/src/extensions/threads.d.ts.map +1 -0
  50. package/dist/types/src/meta.d.ts +3 -6
  51. package/dist/types/src/meta.d.ts.map +1 -1
  52. package/dist/types/src/types.d.ts +5 -0
  53. package/dist/types/src/types.d.ts.map +1 -1
  54. package/package.json +31 -31
  55. package/src/ThreadPlugin.tsx +58 -142
  56. package/src/components/CommentContainer.tsx +8 -12
  57. package/src/components/CommentsContainer.tsx +1 -18
  58. package/src/components/ThreadComplementary.tsx +9 -16
  59. package/src/extensions/index.ts +5 -0
  60. package/src/extensions/threads.ts +117 -0
  61. package/src/{meta.tsx → meta.ts} +3 -4
  62. package/src/types.ts +7 -2
  63. package/dist/lib/browser/chunk-7NUYW5IW.mjs.map +0 -7
  64. package/dist/lib/node/chunk-6EVXCSDS.cjs.map +0 -7
  65. package/dist/lib/node-esm/chunk-Y475KZTX.mjs.map +0 -7
  66. /package/dist/lib/browser/{ThreadArticle-4VU752F4.mjs.map → ThreadArticle-GBPIH47W.mjs.map} +0 -0
  67. /package/dist/lib/browser/{ThreadMain-ML3P4XSD.mjs.map → ThreadMain-PGF7W5EV.mjs.map} +0 -0
  68. /package/dist/lib/browser/{chunk-XF5QKI75.mjs.map → chunk-O4YRHIZC.mjs.map} +0 -0
  69. /package/dist/lib/node/{ThreadArticle-ERUHPHVT.cjs.map → ThreadArticle-GH5UBWFU.cjs.map} +0 -0
  70. /package/dist/lib/node/{ThreadMain-6DN7FDNB.cjs.map → ThreadMain-CO6I3DNX.cjs.map} +0 -0
  71. /package/dist/lib/node/{chunk-PZVUW4W2.cjs.map → chunk-FDYRG7HE.cjs.map} +0 -0
  72. /package/dist/lib/node-esm/{ThreadArticle-NKI5F4W5.mjs.map → ThreadArticle-ZTYD52TR.mjs.map} +0 -0
  73. /package/dist/lib/node-esm/{ThreadMain-2A3VQLCW.mjs.map → ThreadMain-LEHGOF7R.mjs.map} +0 -0
  74. /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,17 +10,16 @@ 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";
22
+ import { NavigationAction, parseIntentPlugin, parseNavigationPlugin, resolvePlugin, isLayoutParts, parseMetadataResolverPlugin } from "@dxos/app-framework";
24
23
  import { getTypename } from "@dxos/echo-schema";
25
24
  import { create as create2 } from "@dxos/echo-schema";
26
25
  import { LocalStorageStore } from "@dxos/local-storage";
@@ -29,11 +28,9 @@ import { parseClientPlugin } from "@dxos/plugin-client";
29
28
  import { createExtension, isActionGroup, toSignal } from "@dxos/plugin-graph";
30
29
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
31
30
  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";
31
+ import { ThreadType as ThreadType2, MessageType as MessageType2, ChannelType } from "@dxos/plugin-space/types";
32
+ import { getSpace as getSpace3, fullyQualifiedId as fullyQualifiedId5, loadObjectReferences } from "@dxos/react-client/echo";
35
33
  import { translations as threadTranslations } from "@dxos/react-ui-thread";
36
- import { nonNullable as nonNullable3 } from "@dxos/util";
37
34
 
38
35
  // packages/plugins/plugin-thread/src/components/index.ts
39
36
  import React4 from "react";
@@ -54,7 +51,7 @@ var ThreadSettings = ({ settings }) => {
54
51
 
55
52
  // packages/plugins/plugin-thread/src/components/CommentContainer.tsx
56
53
  import { CheckCircle, X } from "@phosphor-icons/react";
57
- import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
54
+ import React2, { useCallback, useMemo, useRef, useState } from "react";
58
55
  import { create } from "@dxos/echo-schema";
59
56
  import { MessageType } from "@dxos/plugin-space/types";
60
57
  import { fullyQualifiedId, getSpace, useMembers } from "@dxos/react-client/echo";
@@ -110,14 +107,13 @@ var DeleteThreadButton = ({ onDelete }) => {
110
107
  classNames: "z-[21]"
111
108
  }, label, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null))));
112
109
  };
113
- var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
110
+ var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
114
111
  const identity = useIdentity();
115
112
  const space = getSpace(thread);
116
113
  const members = useMembers(space?.key);
117
114
  const activity = useStatus(space, fullyQualifiedId(thread));
118
115
  const { t } = useTranslation2(THREAD_PLUGIN);
119
116
  const threadScrollRef = useRef(null);
120
- const [autoFocus, setAutoFocus] = useState(!!autoFocusTextbox);
121
117
  const { themeMode } = useThemeContext();
122
118
  const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);
123
119
  const [_count, _setCount] = useState(0);
@@ -137,11 +133,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
137
133
  ], [
138
134
  _count
139
135
  ]);
140
- useEffect(() => {
141
- setAutoFocus(!!autoFocusTextbox);
142
- }, [
143
- autoFocusTextbox
144
- ]);
145
136
  const scrollToEnd = (behavior) => setTimeout(() => threadScrollRef.current?.scrollIntoView({
146
137
  behavior,
147
138
  block: "end"
@@ -160,7 +151,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
160
151
  }));
161
152
  onComment?.(thread);
162
153
  messageRef.current = "";
163
- setAutoFocus(true);
164
154
  scrollToEnd("instant");
165
155
  rerenderEditor();
166
156
  return true;
@@ -199,7 +189,6 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
199
189
  onDelete: (id) => onMessageDelete?.(id)
200
190
  })), /* @__PURE__ */ React2.createElement(MessageTextbox, {
201
191
  extensions,
202
- autoFocus,
203
192
  onSend: handleCreate,
204
193
  ...textboxMetadata
205
194
  }), /* @__PURE__ */ React2.createElement(ThreadFooter, {
@@ -213,29 +202,14 @@ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox,
213
202
 
214
203
  // packages/plugins/plugin-thread/src/components/CommentsContainer.tsx
215
204
  import { ChatText } from "@phosphor-icons/react";
216
- import React3, { useEffect as useEffect2 } from "react";
205
+ import React3, { useEffect } from "react";
217
206
  import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
218
- import { useTranslation as useTranslation3, Icon, Trans } from "@dxos/react-ui";
219
- import { PlankHeading } from "@dxos/react-ui-deck";
207
+ import { useTranslation as useTranslation3, Trans } from "@dxos/react-ui";
220
208
  import { descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
221
- var CommentsHeading = ({ attendableId }) => {
209
+ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
222
210
  const { t } = useTranslation3(THREAD_PLUGIN);
223
- return /* @__PURE__ */ React3.createElement("div", {
224
- role: "none",
225
- className: "flex items-center"
226
- }, /* @__PURE__ */ React3.createElement(PlankHeading.Button, {
227
- attendableId
228
- }, /* @__PURE__ */ React3.createElement(Icon, {
229
- icon: "ph--quotes--regular",
230
- size: 5
231
- })), /* @__PURE__ */ React3.createElement(PlankHeading.Label, {
232
- attendableId
233
- }, t("comments heading")));
234
- };
235
- var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTextbox, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
236
- const { t } = useTranslation3(THREAD_PLUGIN);
237
- const filteredThreads = showResolvedThreads ? threads : threads.filter((thread) => !(thread?.status === "resolved"));
238
- useEffect2(() => {
211
+ const filteredThreads = showResolvedThreads ? threads2 : threads2.filter((thread) => !(thread?.status === "resolved"));
212
+ useEffect(() => {
239
213
  if (currentId) {
240
214
  document.getElementById(currentId)?.scrollIntoView({
241
215
  behavior: "smooth",
@@ -252,7 +226,6 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
252
226
  thread,
253
227
  current: currentId === threadId,
254
228
  detached: detached.includes(threadId),
255
- autoFocusTextbox: autoFocusCurrentTextbox && currentId === threadId,
256
229
  ...onThreadAttend && {
257
230
  onAttend: () => onThreadAttend(thread)
258
231
  },
@@ -284,18 +257,18 @@ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTe
284
257
  };
285
258
 
286
259
  // packages/plugins/plugin-thread/src/components/index.ts
287
- var ThreadMain = React4.lazy(() => import("./ThreadMain-ML3P4XSD.mjs"));
288
- var ThreadArticle = React4.lazy(() => import("./ThreadArticle-4VU752F4.mjs"));
260
+ var ThreadMain = React4.lazy(() => import("./ThreadMain-PGF7W5EV.mjs"));
261
+ var ThreadArticle = React4.lazy(() => import("./ThreadArticle-GBPIH47W.mjs"));
289
262
 
290
263
  // packages/plugins/plugin-thread/src/components/ThreadComplementary.tsx
291
- import React5, { useEffect as useEffect3, useMemo as useMemo2 } from "react";
264
+ import React5, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
292
265
  import { LayoutAction, useIntentDispatcher, useResolvePlugins } from "@dxos/app-framework";
293
266
  import { fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
294
267
  import { ScrollArea } from "@dxos/react-ui";
295
- import { createAttendableAttributes, useAttentionContext } from "@dxos/react-ui-attention";
268
+ import { useAttended } from "@dxos/react-ui-attention";
296
269
  import { nonNullable as nonNullable2 } from "@dxos/util";
297
270
  var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
298
- var ThreadComplementary = ({ role, subject, stagedThreads, current, focus, showResolvedThreads }) => {
271
+ var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
299
272
  const dispatch = useIntentDispatcher();
300
273
  const threadsIntegrators = useResolvePlugins(providesThreadsConfig);
301
274
  const threadProvides = useMemo2(() => threadsIntegrators.map((p) => p.provides.thread), [
@@ -309,42 +282,37 @@ var ThreadComplementary = ({ role, subject, stagedThreads, current, focus, showR
309
282
  createSort,
310
283
  subject
311
284
  ]);
312
- const threads = useMemo2(() => {
313
- return subject.threads.concat(stagedThreads ?? []).filter(nonNullable2);
285
+ const threads2 = useMemo2(() => {
286
+ return subject.threads.concat(drafts ?? []).filter(nonNullable2);
314
287
  }, [
315
288
  JSON.stringify(subject.threads),
316
- JSON.stringify(stagedThreads)
289
+ JSON.stringify(drafts)
317
290
  ]);
318
291
  const detachedIds = useMemo2(() => {
319
- return threads.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
292
+ return threads2.filter(({ anchor }) => !anchor).map((thread) => fullyQualifiedId3(thread));
320
293
  }, [
321
- threads
294
+ threads2
322
295
  ]);
323
- useEffect3(() => {
296
+ useEffect2(() => {
324
297
  if (!sort) {
325
298
  return;
326
299
  }
327
- threads.sort((a, b) => sort(a?.anchor, b?.anchor));
300
+ threads2.sort((a, b) => sort(a?.anchor, b?.anchor));
328
301
  }, [
329
302
  sort,
330
- threads
303
+ threads2
331
304
  ]);
332
- const { attended } = useAttentionContext("Thread Complementary");
305
+ const attended = useAttended();
333
306
  const qualifiedSubjectId = fullyQualifiedId3(subject);
334
- const attendableAttrs = createAttendableAttributes(qualifiedSubjectId);
335
307
  return /* @__PURE__ */ React5.createElement("div", {
336
308
  role: "none",
337
- className: "contents group/attention",
338
- ...attendableAttrs
339
- }, role === "complementary" && /* @__PURE__ */ React5.createElement(CommentsHeading, {
340
- attendableId: qualifiedSubjectId
341
- }), /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
309
+ className: "contents"
310
+ }, /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
342
311
  classNames: "row-span-2"
343
312
  }, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React5.createElement(CommentsContainer, {
344
- threads,
313
+ threads: threads2,
345
314
  detached: detachedIds,
346
- currentId: attended.has(qualifiedSubjectId) ? current : void 0,
347
- autoFocusCurrentTextbox: focus,
315
+ currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
348
316
  showResolvedThreads,
349
317
  onThreadAttend: (thread) => {
350
318
  const threadId = fullyQualifiedId3(thread);
@@ -403,6 +371,95 @@ var ThreadComplementary = ({ role, subject, stagedThreads, current, focus, showR
403
371
  }), /* @__PURE__ */ React5.createElement(ScrollArea.Scrollbar, null, /* @__PURE__ */ React5.createElement(ScrollArea.Thumb, null)))));
404
372
  };
405
373
 
374
+ // packages/plugins/plugin-thread/src/extensions/threads.ts
375
+ import { EditorView } from "@codemirror/view";
376
+ import { computed, effect } from "@preact/signals-core";
377
+ import { ThreadType } from "@dxos/plugin-space/types";
378
+ import { getSpace as getSpace2, getTextInRange, createDocAccessor, fullyQualifiedId as fullyQualifiedId4 } from "@dxos/react-client/echo";
379
+ import { comments, createExternalCommentSync } from "@dxos/react-ui-editor";
380
+ import { nonNullable as nonNullable3 } from "@dxos/util";
381
+ var getName = (doc, anchor) => {
382
+ if (doc.content) {
383
+ const [start, end] = anchor.split(":");
384
+ return getTextInRange(createDocAccessor(doc.content, [
385
+ "content"
386
+ ]), start, end);
387
+ }
388
+ };
389
+ var threads = (state, doc, dispatch) => {
390
+ const space = doc && getSpace2(doc);
391
+ if (!doc || !space || !dispatch) {
392
+ return [
393
+ comments()
394
+ ];
395
+ }
396
+ const threads2 = computed(() => [
397
+ ...doc.threads.filter(nonNullable3),
398
+ ...state.drafts[fullyQualifiedId4(doc)] ?? []
399
+ ].filter((thread) => !(thread?.status === "resolved")));
400
+ return [
401
+ EditorView.updateListener.of((update) => {
402
+ if (update.docChanged) {
403
+ doc.threads.forEach((thread) => {
404
+ if (thread?.anchor) {
405
+ const name = getName(doc, thread.anchor);
406
+ if (name && name !== thread.name) {
407
+ thread.name = name;
408
+ }
409
+ }
410
+ });
411
+ }
412
+ }),
413
+ createExternalCommentSync(fullyQualifiedId4(doc), (sink) => effect(() => sink()), () => threads2.value.filter((thread) => thread?.anchor).map((thread) => ({
414
+ id: fullyQualifiedId4(thread),
415
+ cursor: thread.anchor
416
+ }))),
417
+ comments({
418
+ id: fullyQualifiedId4(doc),
419
+ onCreate: ({ cursor }) => {
420
+ const name = getName(doc, cursor);
421
+ void dispatch({
422
+ action: ThreadAction.CREATE,
423
+ data: {
424
+ cursor,
425
+ name,
426
+ subject: doc
427
+ }
428
+ });
429
+ },
430
+ onDelete: ({ id }) => {
431
+ const draft = state.drafts[fullyQualifiedId4(doc)];
432
+ if (draft) {
433
+ const index = draft.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
434
+ if (index !== -1) {
435
+ draft.splice(index, 1);
436
+ }
437
+ }
438
+ const thread = doc.threads.find((thread2) => thread2?.id === id);
439
+ if (thread) {
440
+ thread.anchor = void 0;
441
+ }
442
+ },
443
+ onUpdate: ({ id, cursor }) => {
444
+ const thread = state.drafts[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
445
+ if (thread instanceof ThreadType && thread.anchor) {
446
+ thread.name = getName(doc, thread.anchor);
447
+ thread.anchor = cursor;
448
+ }
449
+ },
450
+ onSelect: ({ selection: { current, closest } }) => {
451
+ void dispatch({
452
+ action: ThreadAction.SELECT,
453
+ data: {
454
+ current: current ?? closest,
455
+ skipOpen: true
456
+ }
457
+ });
458
+ }
459
+ })
460
+ ];
461
+ };
462
+
406
463
  // packages/plugins/plugin-thread/src/translations.ts
407
464
  var translations_default = [
408
465
  {
@@ -447,7 +504,7 @@ var initialViewState = {
447
504
  var ThreadPlugin = () => {
448
505
  const settings = new LocalStorageStore(THREAD_PLUGIN);
449
506
  const state = create2({
450
- staging: {}
507
+ drafts: {}
451
508
  });
452
509
  const viewStore = create2({});
453
510
  const getViewState = (subjectId) => {
@@ -491,7 +548,7 @@ var ThreadPlugin = () => {
491
548
  // TODO(wittjosiah): Move out of metadata.
492
549
  loadReferences: (channel) => loadObjectReferences(channel, (channel2) => channel2.threads)
493
550
  },
494
- [ThreadType.typename]: {
551
+ [ThreadType2.typename]: {
495
552
  // TODO(wittjosiah): Move out of metadata.
496
553
  loadReferences: (thread) => loadObjectReferences(thread, (thread2) => thread2.messages)
497
554
  },
@@ -527,7 +584,7 @@ var ThreadPlugin = () => {
527
584
  echo: {
528
585
  schema: [
529
586
  ChannelType,
530
- ThreadType,
587
+ ThreadType2,
531
588
  MessageType2
532
589
  ]
533
590
  },
@@ -555,7 +612,7 @@ var ThreadPlugin = () => {
555
612
  onChange();
556
613
  });
557
614
  return () => clearTimeout(timeout);
558
- }, () => space?.db.getObjectById(objectId));
615
+ }, () => space?.db.getObjectById(objectId), subjectId);
559
616
  if (!object || !subjectId) {
560
617
  return;
561
618
  }
@@ -570,11 +627,12 @@ var ThreadPlugin = () => {
570
627
  return {
571
628
  id,
572
629
  type: "orphan-comments-for-subject",
573
- data: object,
630
+ data: null,
574
631
  properties: {
575
- icon: meta.icon,
632
+ icon: "ph--chat-text--regular",
576
633
  label,
577
- showResolvedThreads: viewState.showResolvedThreads
634
+ showResolvedThreads: viewState.showResolvedThreads,
635
+ object
578
636
  }
579
637
  };
580
638
  },
@@ -682,8 +740,7 @@ var ThreadPlugin = () => {
682
740
  settings: settings.values
683
741
  }) : null;
684
742
  }
685
- case "article":
686
- case "complementary": {
743
+ case "article": {
687
744
  const location = navigationPlugin?.provides.location;
688
745
  if (data.object instanceof ChannelType && data.object.threads[0]) {
689
746
  const channel = data.object;
@@ -692,7 +749,7 @@ var ThreadPlugin = () => {
692
749
  const currentPosition = layoutEntries.findIndex((entry) => channel.id === entry.id);
693
750
  if (currentPosition > 0) {
694
751
  const objectToTheLeft = layoutEntries[currentPosition - 1];
695
- const context = getSpace2(data.object)?.db.getObjectById(objectToTheLeft.id);
752
+ const context = getSpace3(data.object)?.db.getObjectById(objectToTheLeft.id);
696
753
  return /* @__PURE__ */ React6.createElement(ThreadArticle, {
697
754
  thread: data.object.threads[0],
698
755
  context
@@ -703,24 +760,27 @@ var ThreadPlugin = () => {
703
760
  thread: data.object.threads[0]
704
761
  });
705
762
  }
706
- if (data.subject instanceof ThreadType) {
763
+ if (data.subject instanceof ThreadType2) {
707
764
  return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(ChatHeading, {
708
765
  attendableId: data.subject.id
709
766
  }), /* @__PURE__ */ React6.createElement(ChatContainer, {
710
767
  thread: data.subject
711
768
  }));
712
769
  }
770
+ break;
771
+ }
772
+ case "complementary--comments": {
713
773
  if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads)) {
714
- const { showResolvedThreads } = getViewState(fullyQualifiedId4(data.subject));
774
+ const { showResolvedThreads } = getViewState(fullyQualifiedId5(data.subject));
715
775
  return /* @__PURE__ */ React6.createElement(ThreadComplementary, {
716
776
  role,
717
777
  subject: data.subject,
718
- stagedThreads: state.staging[fullyQualifiedId4(data.subject)],
778
+ drafts: state.drafts[fullyQualifiedId5(data.subject)],
719
779
  current: state.current,
720
- focus: true,
721
780
  showResolvedThreads
722
781
  });
723
782
  }
783
+ break;
724
784
  }
725
785
  }
726
786
  return null;
@@ -735,28 +795,28 @@ var ThreadPlugin = () => {
735
795
  if (subject?.threads === void 0) {
736
796
  try {
737
797
  subject.threads = [];
738
- } catch (e) {
798
+ } catch (err) {
739
799
  log.error("Subject does not support threads array", subject?.typename, {
740
800
  F: __dxlog_file,
741
- L: 331,
801
+ L: 322,
742
802
  S: void 0,
743
803
  C: (f, a) => f(...a)
744
804
  });
745
805
  return;
746
806
  }
747
807
  }
748
- const subjectId = fullyQualifiedId4(subject);
749
- const thread = create2(ThreadType, {
808
+ const subjectId = fullyQualifiedId5(subject);
809
+ const thread = create2(ThreadType2, {
750
810
  name,
751
811
  anchor: cursor,
752
812
  messages: [],
753
813
  status: "staged"
754
814
  });
755
- const stagingArea = state.staging[subjectId];
756
- if (stagingArea) {
757
- stagingArea.push(thread);
815
+ const draft = state.drafts[subjectId];
816
+ if (draft) {
817
+ draft.push(thread);
758
818
  } else {
759
- state.staging[subjectId] = [
819
+ state.drafts[subjectId] = [
760
820
  thread
761
821
  ];
762
822
  }
@@ -767,16 +827,17 @@ var ThreadPlugin = () => {
767
827
  {
768
828
  action: ThreadAction.SELECT,
769
829
  data: {
770
- current: fullyQualifiedId4(thread),
771
- focus: true
830
+ current: fullyQualifiedId5(thread)
772
831
  }
773
- },
832
+ }
833
+ ],
834
+ [
774
835
  {
775
- action: LayoutAction2.SET_LAYOUT,
836
+ action: NavigationAction.OPEN,
776
837
  data: {
777
- element: "complementary",
778
- subject: subjectId,
779
- state: true
838
+ activeParts: {
839
+ complementary: "comments"
840
+ }
780
841
  }
781
842
  }
782
843
  ]
@@ -786,7 +847,7 @@ var ThreadPlugin = () => {
786
847
  return {
787
848
  data: create2(ChannelType, {
788
849
  threads: [
789
- create2(ThreadType, {
850
+ create2(ThreadType2, {
790
851
  messages: []
791
852
  })
792
853
  ]
@@ -795,15 +856,26 @@ var ThreadPlugin = () => {
795
856
  }
796
857
  }
797
858
  case ThreadAction.SELECT: {
798
- state.focus = intent.data?.current === state.current ? state.focus : intent.data?.focus;
799
859
  state.current = intent.data?.current;
800
860
  return {
801
- data: true
861
+ data: true,
862
+ intents: !intent.data?.skipOpen ? [
863
+ [
864
+ {
865
+ action: NavigationAction.OPEN,
866
+ data: {
867
+ activeParts: {
868
+ complementary: "comments"
869
+ }
870
+ }
871
+ }
872
+ ]
873
+ ] : []
802
874
  };
803
875
  }
804
876
  case ThreadAction.TOGGLE_RESOLVED: {
805
877
  const { thread } = intent.data ?? {};
806
- if (!(thread instanceof ThreadType)) {
878
+ if (!(thread instanceof ThreadType2)) {
807
879
  return;
808
880
  }
809
881
  if (thread.status === "active" || thread.status === void 0) {
@@ -811,9 +883,10 @@ var ThreadPlugin = () => {
811
883
  } else if (thread.status === "resolved") {
812
884
  thread.status = "active";
813
885
  }
814
- const space = getSpace2(thread);
886
+ const space = getSpace3(thread);
815
887
  const spaceId = space?.id;
816
888
  return {
889
+ data: true,
817
890
  intents: [
818
891
  [
819
892
  {
@@ -832,21 +905,21 @@ var ThreadPlugin = () => {
832
905
  }
833
906
  case ThreadAction.DELETE: {
834
907
  const { subject, thread } = intent.data ?? {};
835
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
908
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
836
909
  return;
837
910
  }
838
- const subjectId = fullyQualifiedId4(subject);
839
- const stagingArea = state.staging[subjectId];
840
- if (stagingArea) {
841
- const index = stagingArea.findIndex((t) => t.id === thread.id);
911
+ const subjectId = fullyQualifiedId5(subject);
912
+ const draft = state.drafts[subjectId];
913
+ if (draft) {
914
+ const index = draft.findIndex((t) => t.id === thread.id);
842
915
  if (index !== -1) {
843
- stagingArea.splice(index, 1);
916
+ draft.splice(index, 1);
844
917
  return {
845
918
  data: true
846
919
  };
847
920
  }
848
921
  }
849
- const space = getSpace2(thread);
922
+ const space = getSpace3(thread);
850
923
  if (!space || !subject.threads) {
851
924
  return;
852
925
  }
@@ -904,22 +977,22 @@ var ThreadPlugin = () => {
904
977
  }
905
978
  case ThreadAction.ON_MESSAGE_ADD: {
906
979
  const { thread, subject } = intent.data ?? {};
907
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
980
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
908
981
  return;
909
982
  }
910
- const subjectId = fullyQualifiedId4(subject);
911
- const space = getSpace2(subject);
983
+ const subjectId = fullyQualifiedId5(subject);
984
+ const space = getSpace3(subject);
912
985
  const intents = [];
913
986
  const analyticsProperties = {
914
987
  threadId: thread.id,
915
988
  spaceId: space?.id
916
989
  };
917
- if (state.staging[subjectId]?.find((t) => t === thread)) {
990
+ if (state.drafts[subjectId]?.find((t) => t === thread)) {
918
991
  thread.status = "active";
919
992
  subject.threads ? subject.threads.push(thread) : subject.threads = [
920
993
  thread
921
994
  ];
922
- state.staging[subjectId] = state.staging[subjectId]?.filter((t) => t.id !== thread.id);
995
+ state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
923
996
  intents.push({
924
997
  action: ObservabilityAction.SEND_EVENT,
925
998
  data: {
@@ -947,8 +1020,8 @@ var ThreadPlugin = () => {
947
1020
  }
948
1021
  case ThreadAction.DELETE_MESSAGE: {
949
1022
  const { subject, thread, messageId } = intent.data ?? {};
950
- const space = getSpace2(subject);
951
- if (!(thread instanceof ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
1023
+ const space = getSpace3(subject);
1024
+ if (!(thread instanceof ThreadType2) || !(subject && typeof subject === "object" && "threads" in subject)) {
952
1025
  return;
953
1026
  }
954
1027
  if (!intent.undo) {
@@ -1027,92 +1100,8 @@ var ThreadPlugin = () => {
1027
1100
  }
1028
1101
  },
1029
1102
  markdown: {
1030
- // TODO(burdon): Factor out extension factory into separate file (for simplicity).
1031
1103
  extensions: ({ document: doc }) => {
1032
- const space = doc && getSpace2(doc);
1033
- if (!doc || !space) {
1034
- return [
1035
- comments()
1036
- ];
1037
- }
1038
- const threads = computed(() => [
1039
- ...doc.threads.filter(nonNullable3),
1040
- ...state.staging[fullyQualifiedId4(doc)] ?? []
1041
- ].filter((thread) => !(thread?.status === "resolved")));
1042
- return [
1043
- listener2({
1044
- onChange: () => {
1045
- doc.threads.forEach((thread) => {
1046
- if (thread?.anchor) {
1047
- const [start, end] = thread.anchor.split(":");
1048
- const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1049
- "content"
1050
- ]), start, end);
1051
- if (name && name !== thread.name) {
1052
- thread.name = name;
1053
- }
1054
- }
1055
- });
1056
- }
1057
- }),
1058
- createExternalCommentSync(doc.id, (sink) => effect(() => sink()), () => threads.value.filter((thread) => thread?.anchor).map((thread) => ({
1059
- id: fullyQualifiedId4(thread),
1060
- cursor: thread.anchor
1061
- }))),
1062
- comments({
1063
- id: doc.id,
1064
- onCreate: ({ cursor }) => {
1065
- const [start, end] = cursor.split(":");
1066
- const name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1067
- "content"
1068
- ]), start, end);
1069
- void intentPlugin?.provides.intent.dispatch({
1070
- action: ThreadAction.CREATE,
1071
- data: {
1072
- cursor,
1073
- name,
1074
- subject: doc
1075
- }
1076
- });
1077
- },
1078
- onDelete: ({ id }) => {
1079
- const stagingArea = state.staging[fullyQualifiedId4(doc)];
1080
- if (stagingArea) {
1081
- const index = stagingArea.findIndex((thread2) => fullyQualifiedId4(thread2) === id);
1082
- if (index !== -1) {
1083
- stagingArea.splice(index, 1);
1084
- }
1085
- }
1086
- const thread = doc.threads.find((thread2) => thread2?.id === id);
1087
- if (thread) {
1088
- thread.anchor = void 0;
1089
- }
1090
- },
1091
- onUpdate: ({ id, cursor }) => {
1092
- const thread = state.staging[fullyQualifiedId4(doc)]?.find((thread2) => fullyQualifiedId4(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
1093
- if (thread instanceof ThreadType && thread.anchor) {
1094
- const [start, end] = thread.anchor.split(":");
1095
- thread.name = doc.content && getTextInRange(createDocAccessor(doc.content, [
1096
- "content"
1097
- ]), start, end);
1098
- thread.anchor = cursor;
1099
- }
1100
- },
1101
- onSelect: ({ selection: { current, closest } }) => {
1102
- const dispatch = intentPlugin?.provides.intent.dispatch;
1103
- if (dispatch) {
1104
- void dispatch([
1105
- {
1106
- action: ThreadAction.SELECT,
1107
- data: {
1108
- current: current ?? closest
1109
- }
1110
- }
1111
- ]);
1112
- }
1113
- }
1114
- })
1115
- ];
1104
+ return threads(state, doc, intentPlugin?.provides.intent.dispatch);
1116
1105
  }
1117
1106
  }
1118
1107
  }