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