@dxos/plugin-thread 0.6.13-main.548ca8d → 0.6.13-staging.1e988a3

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 (92) hide show
  1. package/dist/lib/browser/{ThreadArticle-GBPIH47W.mjs → ThreadArticle-O64ZECMF.mjs} +3 -3
  2. package/dist/lib/browser/{ThreadMain-PGF7W5EV.mjs → ThreadMain-ZDCRC6RG.mjs} +3 -3
  3. package/dist/lib/browser/chunk-5IBJO53M.mjs +21 -0
  4. package/dist/lib/browser/chunk-5IBJO53M.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-JFQZ5W2I.mjs → chunk-GKPZHUT3.mjs} +2 -2
  6. package/dist/lib/browser/{chunk-JFQZ5W2I.mjs.map → chunk-GKPZHUT3.mjs.map} +1 -1
  7. package/dist/lib/browser/{chunk-O4YRHIZC.mjs → chunk-P7ZE5N5M.mjs} +11 -13
  8. package/dist/lib/browser/chunk-P7ZE5N5M.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +393 -411
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/meta.mjs +1 -1
  13. package/dist/lib/browser/types.mjs +2 -2
  14. package/dist/lib/node/{ThreadArticle-GH5UBWFU.cjs → ThreadArticle-DO56JXBU.cjs} +7 -7
  15. package/dist/lib/node/{ThreadMain-CO6I3DNX.cjs → ThreadMain-XJX75GHG.cjs} +7 -7
  16. package/dist/lib/node/{chunk-FDYRG7HE.cjs → chunk-5PZNPPQF.cjs} +63 -65
  17. package/dist/lib/node/chunk-5PZNPPQF.cjs.map +7 -0
  18. package/dist/lib/node/{chunk-JIJ7Z6NO.cjs → chunk-BWBONZGU.cjs} +22 -7
  19. package/dist/lib/node/chunk-BWBONZGU.cjs.map +7 -0
  20. package/dist/lib/node/{chunk-FOZUQZF4.cjs → chunk-D5GOVXHS.cjs} +6 -6
  21. package/dist/lib/node/{chunk-FOZUQZF4.cjs.map → chunk-D5GOVXHS.cjs.map} +1 -1
  22. package/dist/lib/node/index.cjs +428 -442
  23. package/dist/lib/node/index.cjs.map +4 -4
  24. package/dist/lib/node/meta.cjs +4 -4
  25. package/dist/lib/node/meta.cjs.map +1 -1
  26. package/dist/lib/node/meta.json +1 -1
  27. package/dist/lib/node/types.cjs +3 -3
  28. package/dist/lib/node/types.cjs.map +1 -1
  29. package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
  30. package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
  31. package/dist/types/src/components/CommentContainer.d.ts +1 -1
  32. package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
  33. package/dist/types/src/components/CommentsContainer.d.ts +5 -1
  34. package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
  35. package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
  36. package/dist/types/src/components/index.d.ts +2 -3
  37. package/dist/types/src/components/index.d.ts.map +1 -1
  38. package/dist/types/src/components/testing.d.ts +0 -2
  39. package/dist/types/src/components/testing.d.ts.map +1 -1
  40. package/dist/types/src/meta.d.ts +9 -3
  41. package/dist/types/src/meta.d.ts.map +1 -1
  42. package/dist/types/src/types.d.ts +1 -6
  43. package/dist/types/src/types.d.ts.map +1 -1
  44. package/dist/types/src/types.test.d.ts +2 -0
  45. package/dist/types/src/types.test.d.ts.map +1 -0
  46. package/package.json +37 -40
  47. package/src/ThreadPlugin.tsx +310 -120
  48. package/src/components/ChatContainer.tsx +8 -7
  49. package/src/components/CommentContainer.tsx +19 -18
  50. package/src/components/Comments.stories.tsx +2 -2
  51. package/src/components/CommentsContainer.tsx +31 -18
  52. package/src/components/MessageContainer.tsx +1 -2
  53. package/src/components/index.ts +2 -3
  54. package/src/meta.tsx +20 -0
  55. package/src/types.test.ts +13 -0
  56. package/src/types.ts +3 -8
  57. package/dist/lib/browser/chunk-5G3KL6TC.mjs +0 -16
  58. package/dist/lib/browser/chunk-5G3KL6TC.mjs.map +0 -7
  59. package/dist/lib/browser/chunk-O4YRHIZC.mjs.map +0 -7
  60. package/dist/lib/node/chunk-FDYRG7HE.cjs.map +0 -7
  61. package/dist/lib/node/chunk-JIJ7Z6NO.cjs.map +0 -7
  62. package/dist/lib/node-esm/ThreadArticle-ZTYD52TR.mjs +0 -19
  63. package/dist/lib/node-esm/ThreadArticle-ZTYD52TR.mjs.map +0 -7
  64. package/dist/lib/node-esm/ThreadMain-LEHGOF7R.mjs +0 -27
  65. package/dist/lib/node-esm/ThreadMain-LEHGOF7R.mjs.map +0 -7
  66. package/dist/lib/node-esm/chunk-DC5ZA6H5.mjs +0 -18
  67. package/dist/lib/node-esm/chunk-DC5ZA6H5.mjs.map +0 -7
  68. package/dist/lib/node-esm/chunk-XOVJ65DG.mjs +0 -413
  69. package/dist/lib/node-esm/chunk-XOVJ65DG.mjs.map +0 -7
  70. package/dist/lib/node-esm/chunk-ZXIPFXSA.mjs +0 -21
  71. package/dist/lib/node-esm/chunk-ZXIPFXSA.mjs.map +0 -7
  72. package/dist/lib/node-esm/index.mjs +0 -1121
  73. package/dist/lib/node-esm/index.mjs.map +0 -7
  74. package/dist/lib/node-esm/meta.json +0 -1
  75. package/dist/lib/node-esm/meta.mjs +0 -12
  76. package/dist/lib/node-esm/meta.mjs.map +0 -7
  77. package/dist/lib/node-esm/types.mjs +0 -9
  78. package/dist/lib/node-esm/types.mjs.map +0 -7
  79. package/dist/types/src/components/ThreadComplementary.d.ts +0 -10
  80. package/dist/types/src/components/ThreadComplementary.d.ts.map +0 -1
  81. package/dist/types/src/extensions/index.d.ts +0 -2
  82. package/dist/types/src/extensions/index.d.ts.map +0 -1
  83. package/dist/types/src/extensions/threads.d.ts +0 -9
  84. package/dist/types/src/extensions/threads.d.ts.map +0 -1
  85. package/src/components/ThreadComplementary.tsx +0 -113
  86. package/src/extensions/index.ts +0 -5
  87. package/src/extensions/threads.ts +0 -117
  88. package/src/meta.ts +0 -15
  89. /package/dist/lib/browser/{ThreadArticle-GBPIH47W.mjs.map → ThreadArticle-O64ZECMF.mjs.map} +0 -0
  90. /package/dist/lib/browser/{ThreadMain-PGF7W5EV.mjs.map → ThreadMain-ZDCRC6RG.mjs.map} +0 -0
  91. /package/dist/lib/node/{ThreadArticle-GH5UBWFU.cjs.map → ThreadArticle-DO56JXBU.cjs.map} +0 -0
  92. /package/dist/lib/node/{ThreadMain-CO6I3DNX.cjs.map → ThreadMain-XJX75GHG.cjs.map} +0 -0
@@ -28,68 +28,73 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
- ThreadAction: () => import_chunk_FOZUQZF4.ThreadAction,
31
+ ThreadAction: () => import_chunk_D5GOVXHS.ThreadAction,
32
32
  ThreadPlugin: () => ThreadPlugin,
33
33
  default: () => src_default,
34
- useAnalyticsCallback: () => import_chunk_FDYRG7HE.useAnalyticsCallback,
35
- useOnEditAnalytics: () => import_chunk_FDYRG7HE.useOnEditAnalytics,
36
- useStatus: () => import_chunk_FDYRG7HE.useStatus
34
+ useAnalyticsCallback: () => import_chunk_5PZNPPQF.useAnalyticsCallback,
35
+ useOnEditAnalytics: () => import_chunk_5PZNPPQF.useOnEditAnalytics,
36
+ useStatus: () => import_chunk_5PZNPPQF.useStatus
37
37
  });
38
38
  module.exports = __toCommonJS(node_exports);
39
- var import_chunk_FOZUQZF4 = require("./chunk-FOZUQZF4.cjs");
40
- var import_chunk_FDYRG7HE = require("./chunk-FDYRG7HE.cjs");
41
- var import_chunk_JIJ7Z6NO = require("./chunk-JIJ7Z6NO.cjs");
42
- var import_react = __toESM(require("react"));
39
+ var import_chunk_D5GOVXHS = require("./chunk-D5GOVXHS.cjs");
40
+ var import_chunk_5PZNPPQF = require("./chunk-5PZNPPQF.cjs");
41
+ var import_chunk_BWBONZGU = require("./chunk-BWBONZGU.cjs");
42
+ var import_react = require("@phosphor-icons/react");
43
+ var import_signals_core = require("@preact/signals-core");
44
+ var import_react2 = __toESM(require("react"));
43
45
  var import_app_framework = require("@dxos/app-framework");
44
46
  var import_echo_schema = require("@dxos/echo-schema");
47
+ var import_echo_schema2 = require("@dxos/echo-schema");
45
48
  var import_local_storage = require("@dxos/local-storage");
46
- var import_log = require("@dxos/log");
49
+ var import_plugin_attention = require("@dxos/plugin-attention");
47
50
  var import_plugin_client = require("@dxos/plugin-client");
48
51
  var import_plugin_graph = require("@dxos/plugin-graph");
52
+ var import_types = require("@dxos/plugin-markdown/types");
49
53
  var import_meta = require("@dxos/plugin-observability/meta");
50
54
  var import_plugin_space = require("@dxos/plugin-space");
51
- var import_types = require("@dxos/plugin-space/types");
52
- var import_echo = require("@dxos/react-client/echo");
53
- var import_react_ui_thread = require("@dxos/react-ui-thread");
54
- var import_react2 = __toESM(require("react"));
55
- var import_react3 = require("@phosphor-icons/react");
56
- var import_react4 = __toESM(require("react"));
57
- var import_echo_schema2 = require("@dxos/echo-schema");
58
55
  var import_types2 = require("@dxos/plugin-space/types");
59
- var import_echo2 = require("@dxos/react-client/echo");
60
- var import_halo = require("@dxos/react-client/halo");
56
+ var import_echo = require("@dxos/react-client/echo");
61
57
  var import_react_ui = require("@dxos/react-ui");
58
+ var import_react_ui_attention = require("@dxos/react-ui-attention");
62
59
  var import_react_ui_editor = require("@dxos/react-ui-editor");
63
- var import_react_ui_theme = require("@dxos/react-ui-theme");
64
- var import_react_ui_thread2 = require("@dxos/react-ui-thread");
60
+ var import_react_ui_thread = require("@dxos/react-ui-thread");
65
61
  var import_util = require("@dxos/util");
62
+ var import_react3 = __toESM(require("react"));
63
+ var import_react4 = __toESM(require("react"));
64
+ var import_plugin_settings = require("@dxos/plugin-settings");
65
+ var import_react_ui2 = require("@dxos/react-ui");
66
66
  var import_react5 = require("@phosphor-icons/react");
67
67
  var import_react6 = __toESM(require("react"));
68
- var import_echo3 = require("@dxos/react-client/echo");
69
- var import_react_ui2 = require("@dxos/react-ui");
70
- var import_react_ui_theme2 = require("@dxos/react-ui-theme");
71
- var import_react7 = __toESM(require("react"));
72
- var import_app_framework2 = require("@dxos/app-framework");
73
- var import_echo4 = require("@dxos/react-client/echo");
68
+ var import_echo_schema3 = require("@dxos/echo-schema");
69
+ var import_types3 = require("@dxos/plugin-space/types");
70
+ var import_echo2 = require("@dxos/react-client/echo");
71
+ var import_halo = require("@dxos/react-client/halo");
74
72
  var import_react_ui3 = require("@dxos/react-ui");
75
- var import_react_ui_attention = require("@dxos/react-ui-attention");
73
+ var import_react_ui_editor2 = require("@dxos/react-ui-editor");
74
+ var import_react_ui_theme = require("@dxos/react-ui-theme");
75
+ var import_react_ui_thread2 = require("@dxos/react-ui-thread");
76
76
  var import_util2 = require("@dxos/util");
77
+ var import_react7 = require("@phosphor-icons/react");
77
78
  var import_react8 = __toESM(require("react"));
78
- var import_plugin_settings = require("@dxos/plugin-settings");
79
79
  var import_react_ui4 = require("@dxos/react-ui");
80
- var import_view = require("@codemirror/view");
81
- var import_signals_core = require("@preact/signals-core");
82
- var import_types3 = require("@dxos/plugin-space/types");
83
- var import_echo5 = require("@dxos/react-client/echo");
84
- var import_react_ui_editor2 = require("@dxos/react-ui-editor");
85
- var import_util3 = require("@dxos/util");
80
+ var import_react_ui_deck = require("@dxos/react-ui-deck");
81
+ var import_react_ui_theme2 = require("@dxos/react-ui-theme");
82
+ var ThreadSettings = ({ settings }) => {
83
+ const { t } = (0, import_react_ui2.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
84
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(import_plugin_settings.SettingsValue, {
85
+ label: t("settings standalone label")
86
+ }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui2.Input.Switch, {
87
+ checked: settings.standalone,
88
+ onCheckedChange: (checked) => settings.standalone = !!checked
89
+ })));
90
+ };
86
91
  var sizeClass = (0, import_react_ui_theme.getSize)(4);
87
92
  var ToggleResolvedButton = ({ isResolved, onResolve }) => {
88
- const { t } = (0, import_react_ui.useTranslation)(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
93
+ const { t } = (0, import_react_ui3.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
89
94
  const label = t(isResolved ? "mark as unresolved label" : "mark as resolved label");
90
- return /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Root, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Trigger, {
95
+ return /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Trigger, {
91
96
  asChild: true
92
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Button, {
97
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Button, {
93
98
  variant: "ghost",
94
99
  "data-testid": "thread.toggle-resolved",
95
100
  onClick: onResolve,
@@ -97,23 +102,23 @@ var ToggleResolvedButton = ({ isResolved, onResolve }) => {
97
102
  "min-bs-0 p-1",
98
103
  !isResolved && import_react_ui_theme.hoverableControlItem
99
104
  ]
100
- }, /* @__PURE__ */ import_react4.default.createElement("span", {
105
+ }, /* @__PURE__ */ import_react6.default.createElement("span", {
101
106
  className: "sr-only"
102
- }, label), isResolved ? /* @__PURE__ */ import_react4.default.createElement(import_react3.CheckCircle, {
107
+ }, label), isResolved ? /* @__PURE__ */ import_react6.default.createElement(import_react5.CheckCircle, {
103
108
  className: sizeClass,
104
109
  weight: "fill"
105
- }) : /* @__PURE__ */ import_react4.default.createElement(import_react3.CheckCircle, {
110
+ }) : /* @__PURE__ */ import_react6.default.createElement(import_react5.CheckCircle, {
106
111
  className: sizeClass
107
- }))), /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Portal, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Content, {
112
+ }))), /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Portal, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Content, {
108
113
  classNames: "z-[21]"
109
- }, label, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Arrow, null))));
114
+ }, label, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Arrow, null))));
110
115
  };
111
116
  var DeleteThreadButton = ({ onDelete }) => {
112
- const { t } = (0, import_react_ui.useTranslation)(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
117
+ const { t } = (0, import_react_ui3.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
113
118
  const label = t("delete thread label");
114
- return /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Root, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Trigger, {
119
+ return /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Trigger, {
115
120
  asChild: true
116
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Button, {
121
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Button, {
117
122
  variant: "ghost",
118
123
  "data-testid": "thread.delete",
119
124
  onClick: onDelete,
@@ -121,49 +126,55 @@ var DeleteThreadButton = ({ onDelete }) => {
121
126
  "min-bs-0 p-1",
122
127
  import_react_ui_theme.hoverableControlItem
123
128
  ]
124
- }, /* @__PURE__ */ import_react4.default.createElement("span", {
129
+ }, /* @__PURE__ */ import_react6.default.createElement("span", {
125
130
  className: "sr-only"
126
- }, label), /* @__PURE__ */ import_react4.default.createElement(import_react3.X, {
131
+ }, label), /* @__PURE__ */ import_react6.default.createElement(import_react5.X, {
127
132
  className: sizeClass
128
- }))), /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Portal, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Content, {
133
+ }))), /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Portal, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Content, {
129
134
  classNames: "z-[21]"
130
- }, label, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Arrow, null))));
135
+ }, label, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Arrow, null))));
131
136
  };
132
- var CommentContainer = ({ thread, detached, context, current, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
137
+ var CommentContainer = ({ thread, detached, context, current, autoFocusTextbox, onAttend, onThreadDelete, onMessageDelete, onResolve, onComment }) => {
133
138
  const identity = (0, import_halo.useIdentity)();
134
139
  const space = (0, import_echo2.getSpace)(thread);
135
140
  const members = (0, import_echo2.useMembers)(space?.key);
136
- const activity = (0, import_chunk_FDYRG7HE.useStatus)(space, (0, import_echo2.fullyQualifiedId)(thread));
137
- const { t } = (0, import_react_ui.useTranslation)(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
138
- const threadScrollRef = (0, import_react4.useRef)(null);
139
- const { themeMode } = (0, import_react_ui.useThemeContext)();
140
- const textboxMetadata = (0, import_chunk_FDYRG7HE.getMessageMetadata)((0, import_echo2.fullyQualifiedId)(thread), identity);
141
- const [_count, _setCount] = (0, import_react4.useState)(0);
141
+ const activity = (0, import_chunk_5PZNPPQF.useStatus)(space, thread.id);
142
+ const { t } = (0, import_react_ui3.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
143
+ const threadScrollRef = (0, import_react6.useRef)(null);
144
+ const [autoFocus, setAutoFocus] = (0, import_react6.useState)(!!autoFocusTextbox);
145
+ const { themeMode } = (0, import_react_ui3.useThemeContext)();
146
+ const textboxMetadata = (0, import_chunk_5PZNPPQF.getMessageMetadata)(thread.id, identity);
147
+ const [_count, _setCount] = (0, import_react6.useState)(0);
142
148
  const rerenderEditor = () => _setCount((count) => count + 1);
143
- const messageRef = (0, import_react4.useRef)("");
144
- const extensions = (0, import_react4.useMemo)(() => [
145
- (0, import_react_ui_editor.createBasicExtensions)({
149
+ const messageRef = (0, import_react6.useRef)("");
150
+ const extensions = (0, import_react6.useMemo)(() => [
151
+ (0, import_react_ui_editor2.createBasicExtensions)({
146
152
  placeholder: t("message placeholder")
147
153
  }),
148
- (0, import_react_ui_editor.createThemeExtensions)({
154
+ (0, import_react_ui_editor2.createThemeExtensions)({
149
155
  themeMode
150
156
  }),
151
- (0, import_react_ui_editor.listener)({
157
+ (0, import_react_ui_editor2.listener)({
152
158
  onChange: (text) => messageRef.current = text
153
159
  }),
154
- import_chunk_FDYRG7HE.command
160
+ import_chunk_5PZNPPQF.command
155
161
  ], [
156
162
  _count
157
163
  ]);
164
+ (0, import_react6.useEffect)(() => {
165
+ setAutoFocus(!!autoFocusTextbox);
166
+ }, [
167
+ autoFocusTextbox
168
+ ]);
158
169
  const scrollToEnd = (behavior) => setTimeout(() => threadScrollRef.current?.scrollIntoView({
159
170
  behavior,
160
171
  block: "end"
161
172
  }), 10);
162
- const handleCreate = (0, import_react4.useCallback)(() => {
173
+ const handleCreate = (0, import_react6.useCallback)(() => {
163
174
  if (!messageRef.current) {
164
175
  return false;
165
176
  }
166
- thread.messages.push((0, import_echo_schema2.create)(import_types2.MessageType, {
177
+ thread.messages.push((0, import_echo_schema3.create)(import_types3.MessageType, {
167
178
  sender: {
168
179
  identityKey: identity.identityKey.toHex()
169
180
  },
@@ -173,6 +184,7 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
173
184
  }));
174
185
  onComment?.(thread);
175
186
  messageRef.current = "";
187
+ setAutoFocus(true);
176
188
  scrollToEnd("instant");
177
189
  rerenderEditor();
178
190
  return true;
@@ -180,51 +192,64 @@ var CommentContainer = ({ thread, detached, context, current, onAttend, onThread
180
192
  thread,
181
193
  identity
182
194
  ]);
183
- return /* @__PURE__ */ import_react4.default.createElement(import_react_ui_thread2.Thread, {
195
+ const handleDeleteMessage = (id) => onMessageDelete?.(id);
196
+ return /* @__PURE__ */ import_react6.default.createElement(import_react_ui_thread2.Thread, {
184
197
  onClickCapture: onAttend,
185
198
  onFocusCapture: onAttend,
186
199
  current,
187
- id: (0, import_echo2.fullyQualifiedId)(thread)
188
- }, /* @__PURE__ */ import_react4.default.createElement("div", {
200
+ id: thread.id
201
+ }, /* @__PURE__ */ import_react6.default.createElement("div", {
189
202
  role: "none",
190
203
  className: (0, import_react_ui_theme.mx)("col-span-2 grid grid-cols-[var(--rail-size)_1fr_min-content]", import_react_ui_theme.hoverableControls, import_react_ui_theme.hoverableFocusedWithinControls)
191
- }, detached ? /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Root, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Trigger, {
204
+ }, detached ? /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Root, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Trigger, {
192
205
  asChild: true
193
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui_thread2.ThreadHeading, {
206
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui_thread2.ThreadHeading, {
194
207
  detached: true
195
- }, thread.name ?? t("thread title placeholder"))), /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Portal, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Content, {
208
+ }, thread.name ?? t("thread title placeholder"))), /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Portal, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Content, {
196
209
  classNames: "z-[21]",
197
210
  side: "top"
198
- }, t("detached thread label"), /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tooltip.Arrow, null)))) : /* @__PURE__ */ import_react4.default.createElement(import_react_ui_thread2.ThreadHeading, null, thread.name ?? t("thread title placeholder")), /* @__PURE__ */ import_react4.default.createElement("div", {
211
+ }, t("detached thread label"), /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tooltip.Arrow, null)))) : /* @__PURE__ */ import_react6.default.createElement(import_react_ui_thread2.ThreadHeading, null, thread.name ?? t("thread title placeholder")), /* @__PURE__ */ import_react6.default.createElement("div", {
199
212
  className: "flex flex-row items-center pli-1"
200
- }, thread.status === "staged" && /* @__PURE__ */ import_react4.default.createElement(import_react_ui.Tag, {
213
+ }, thread.status === "staged" && /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Tag, {
201
214
  palette: "neutral"
202
- }, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */ import_react4.default.createElement(ToggleResolvedButton, {
215
+ }, t("draft button")), onResolve && !(thread?.status === "staged") && /* @__PURE__ */ import_react6.default.createElement(ToggleResolvedButton, {
203
216
  isResolved: thread?.status === "resolved",
204
217
  onResolve
205
- }), onThreadDelete && /* @__PURE__ */ import_react4.default.createElement(DeleteThreadButton, {
218
+ }), onThreadDelete && /* @__PURE__ */ import_react6.default.createElement(DeleteThreadButton, {
206
219
  onDelete: onThreadDelete
207
- }))), thread.messages.filter(import_util.nonNullable).map((message) => /* @__PURE__ */ import_react4.default.createElement(import_chunk_FDYRG7HE.MessageContainer, {
220
+ }))), thread.messages.filter(import_util2.nonNullable).map((message) => /* @__PURE__ */ import_react6.default.createElement(import_chunk_5PZNPPQF.MessageContainer, {
208
221
  key: message.id,
209
222
  message,
210
223
  members,
211
- onDelete: (id) => onMessageDelete?.(id)
212
- })), /* @__PURE__ */ import_react4.default.createElement(import_react_ui_thread2.MessageTextbox, {
224
+ onDelete: handleDeleteMessage
225
+ })), /* @__PURE__ */ import_react6.default.createElement(import_react_ui_thread2.MessageTextbox, {
213
226
  extensions,
227
+ autoFocus,
214
228
  onSend: handleCreate,
215
229
  ...textboxMetadata
216
- }), /* @__PURE__ */ import_react4.default.createElement(import_react_ui_thread2.ThreadFooter, {
230
+ }), /* @__PURE__ */ import_react6.default.createElement(import_react_ui_thread2.ThreadFooter, {
217
231
  activity
218
- }, t("activity message")), /* @__PURE__ */ import_react4.default.createElement("div", {
232
+ }, t("activity message")), /* @__PURE__ */ import_react6.default.createElement("div", {
219
233
  role: "none",
220
234
  className: "bs-px -mbs-px",
221
235
  ref: threadScrollRef
222
236
  }));
223
237
  };
224
- var CommentsContainer = ({ threads: threads2, detached = [], currentId, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
225
- const { t } = (0, import_react_ui2.useTranslation)(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
226
- const filteredThreads = showResolvedThreads ? threads2 : threads2.filter((thread) => !(thread?.status === "resolved"));
227
- (0, import_react6.useEffect)(() => {
238
+ var CommentsHeading = ({ attendableId }) => {
239
+ const { t } = (0, import_react_ui4.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
240
+ return /* @__PURE__ */ import_react8.default.createElement("div", {
241
+ role: "none",
242
+ className: "flex items-center"
243
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui_deck.PlankHeading.Button, {
244
+ attendableId
245
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react7.Quotes, import_react_ui_deck.plankHeadingIconProps)), /* @__PURE__ */ import_react8.default.createElement(import_react_ui_deck.PlankHeading.Label, {
246
+ attendableId
247
+ }, t("comments heading")));
248
+ };
249
+ var CommentsContainer = ({ threads, detached = [], currentId, autoFocusCurrentTextbox, showResolvedThreads, onThreadAttend, onThreadDelete, onMessageDelete, onThreadToggleResolved, ...props }) => {
250
+ const { t } = (0, import_react_ui4.useTranslation)(import_chunk_BWBONZGU.THREAD_PLUGIN);
251
+ const filteredThreads = showResolvedThreads ? threads : threads.filter((thread) => !(thread?.status === "resolved"));
252
+ (0, import_react8.useEffect)(() => {
228
253
  if (currentId) {
229
254
  document.getElementById(currentId)?.scrollIntoView({
230
255
  behavior: "smooth",
@@ -234,241 +259,46 @@ var CommentsContainer = ({ threads: threads2, detached = [], currentId, showReso
234
259
  }, [
235
260
  currentId
236
261
  ]);
237
- return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => {
238
- const threadId = (0, import_echo3.fullyQualifiedId)(thread);
239
- return /* @__PURE__ */ import_react6.default.createElement(CommentContainer, {
240
- key: threadId,
241
- thread,
242
- current: currentId === threadId,
243
- detached: detached.includes(threadId),
244
- ...onThreadAttend && {
245
- onAttend: () => onThreadAttend(thread)
246
- },
247
- ...onThreadDelete && {
248
- onThreadDelete: () => onThreadDelete(thread)
249
- },
250
- ...onMessageDelete && {
251
- onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
252
- },
253
- ...onThreadToggleResolved && {
254
- onResolve: () => onThreadToggleResolved(thread)
255
- },
256
- ...props
257
- });
258
- }) : /* @__PURE__ */ import_react6.default.createElement("div", {
262
+ return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, filteredThreads.length > 0 ? filteredThreads.map((thread) => /* @__PURE__ */ import_react8.default.createElement(CommentContainer, {
263
+ key: thread.id,
264
+ thread,
265
+ current: currentId === thread.id,
266
+ detached: detached.includes(thread.id),
267
+ autoFocusTextbox: autoFocusCurrentTextbox && currentId === thread.id,
268
+ ...onThreadAttend && {
269
+ onAttend: () => onThreadAttend(thread)
270
+ },
271
+ ...onThreadDelete && {
272
+ onThreadDelete: () => onThreadDelete(thread)
273
+ },
274
+ ...onMessageDelete && {
275
+ onMessageDelete: (messageId) => onMessageDelete(thread, messageId)
276
+ },
277
+ ...onThreadToggleResolved && {
278
+ onResolve: () => onThreadToggleResolved(thread)
279
+ },
280
+ ...props
281
+ })) : /* @__PURE__ */ import_react8.default.createElement("div", {
259
282
  role: "alert",
260
283
  className: (0, import_react_ui_theme2.mx)(import_react_ui_theme2.descriptionText, "place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-4 m-4")
261
- }, /* @__PURE__ */ import_react6.default.createElement("h2", {
284
+ }, /* @__PURE__ */ import_react8.default.createElement("h2", {
262
285
  className: "mbe-2 font-medium text-baseText"
263
- }, t("no comments title")), /* @__PURE__ */ import_react6.default.createElement("p", null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui2.Trans, {
286
+ }, t("no comments title")), /* @__PURE__ */ import_react8.default.createElement("p", null, /* @__PURE__ */ import_react8.default.createElement(import_react_ui4.Trans, {
264
287
  t,
265
288
  i18nKey: "no comments message",
266
289
  components: {
267
- commentIcon: /* @__PURE__ */ import_react6.default.createElement(import_react5.ChatText, {
290
+ commentIcon: /* @__PURE__ */ import_react8.default.createElement(import_react7.ChatText, {
268
291
  className: "inline-block"
269
292
  })
270
293
  }
271
294
  }))));
272
295
  };
273
- var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
274
- var ThreadComplementary = ({ role, subject, drafts, current, showResolvedThreads }) => {
275
- const dispatch = (0, import_app_framework2.useIntentDispatcher)();
276
- const threadsIntegrators = (0, import_app_framework2.useResolvePlugins)(providesThreadsConfig);
277
- const threadProvides = (0, import_react7.useMemo)(() => threadsIntegrators.map((p) => p.provides.thread), [
278
- threadsIntegrators
279
- ]);
280
- const createSort = (0, import_react7.useMemo)(() => threadProvides.find((p) => p.predicate(subject))?.createSort, [
281
- threadProvides,
282
- subject
283
- ]);
284
- const sort = (0, import_react7.useMemo)(() => createSort?.(subject), [
285
- createSort,
286
- subject
287
- ]);
288
- const threads2 = (0, import_react7.useMemo)(() => {
289
- return subject.threads.concat(drafts ?? []).filter(import_util2.nonNullable);
290
- }, [
291
- JSON.stringify(subject.threads),
292
- JSON.stringify(drafts)
293
- ]);
294
- const detachedIds = (0, import_react7.useMemo)(() => {
295
- return threads2.filter(({ anchor }) => !anchor).map((thread) => (0, import_echo4.fullyQualifiedId)(thread));
296
- }, [
297
- threads2
298
- ]);
299
- (0, import_react7.useEffect)(() => {
300
- if (!sort) {
301
- return;
302
- }
303
- threads2.sort((a, b) => sort(a?.anchor, b?.anchor));
304
- }, [
305
- sort,
306
- threads2
307
- ]);
308
- const attended = (0, import_react_ui_attention.useAttended)();
309
- const qualifiedSubjectId = (0, import_echo4.fullyQualifiedId)(subject);
310
- return /* @__PURE__ */ import_react7.default.createElement("div", {
311
- role: "none",
312
- className: "contents"
313
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui3.ScrollArea.Root, {
314
- classNames: "row-span-2"
315
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui3.ScrollArea.Viewport, null, /* @__PURE__ */ import_react7.default.createElement(CommentsContainer, {
316
- threads: threads2,
317
- detached: detachedIds,
318
- currentId: attended.includes(qualifiedSubjectId) ? current : void 0,
319
- showResolvedThreads,
320
- onThreadAttend: (thread) => {
321
- const threadId = (0, import_echo4.fullyQualifiedId)(thread);
322
- if (current !== threadId) {
323
- current = threadId;
324
- void dispatch?.([
325
- {
326
- action: import_app_framework2.LayoutAction.SCROLL_INTO_VIEW,
327
- data: {
328
- id: (0, import_echo4.fullyQualifiedId)(subject),
329
- thread: threadId,
330
- cursor: thread.anchor
331
- }
332
- }
333
- ]);
334
- }
335
- },
336
- onThreadDelete: (thread) => {
337
- return dispatch({
338
- plugin: import_chunk_JIJ7Z6NO.THREAD_PLUGIN,
339
- action: import_chunk_FOZUQZF4.ThreadAction.DELETE,
340
- data: {
341
- subject,
342
- thread
343
- }
344
- });
345
- },
346
- onMessageDelete: (thread, messageId) => dispatch({
347
- plugin: import_chunk_JIJ7Z6NO.THREAD_PLUGIN,
348
- action: import_chunk_FOZUQZF4.ThreadAction.DELETE_MESSAGE,
349
- data: {
350
- subject,
351
- thread,
352
- messageId
353
- }
354
- }),
355
- onThreadToggleResolved: (thread) => dispatch({
356
- plugin: import_chunk_JIJ7Z6NO.THREAD_PLUGIN,
357
- action: import_chunk_FOZUQZF4.ThreadAction.TOGGLE_RESOLVED,
358
- data: {
359
- thread
360
- }
361
- }),
362
- onComment: (thread) => {
363
- void dispatch({
364
- action: import_chunk_FOZUQZF4.ThreadAction.ON_MESSAGE_ADD,
365
- data: {
366
- thread,
367
- subject
368
- }
369
- });
370
- }
371
- }), /* @__PURE__ */ import_react7.default.createElement("div", {
372
- role: "none",
373
- className: "bs-10"
374
- }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui3.ScrollArea.Scrollbar, null, /* @__PURE__ */ import_react7.default.createElement(import_react_ui3.ScrollArea.Thumb, null)))));
375
- };
376
- var ThreadSettings = ({ settings }) => {
377
- const { t } = (0, import_react_ui4.useTranslation)(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
378
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(import_plugin_settings.SettingsValue, {
379
- label: t("settings standalone label")
380
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui4.Input.Switch, {
381
- checked: settings.standalone,
382
- onCheckedChange: (checked) => settings.standalone = !!checked
383
- })));
384
- };
385
- var ThreadMain = import_react2.default.lazy(() => import("./ThreadMain-CO6I3DNX.cjs"));
386
- var ThreadArticle = import_react2.default.lazy(() => import("./ThreadArticle-GH5UBWFU.cjs"));
387
- var getName = (doc, anchor) => {
388
- if (doc.content) {
389
- const [start, end] = anchor.split(":");
390
- return (0, import_echo5.getTextInRange)((0, import_echo5.createDocAccessor)(doc.content, [
391
- "content"
392
- ]), start, end);
393
- }
394
- };
395
- var threads = (state, doc, dispatch) => {
396
- const space = doc && (0, import_echo5.getSpace)(doc);
397
- if (!doc || !space || !dispatch) {
398
- return [
399
- (0, import_react_ui_editor2.comments)()
400
- ];
401
- }
402
- const threads2 = (0, import_signals_core.computed)(() => [
403
- ...doc.threads.filter(import_util3.nonNullable),
404
- ...state.drafts[(0, import_echo5.fullyQualifiedId)(doc)] ?? []
405
- ].filter((thread) => !(thread?.status === "resolved")));
406
- return [
407
- import_view.EditorView.updateListener.of((update) => {
408
- if (update.docChanged) {
409
- doc.threads.forEach((thread) => {
410
- if (thread?.anchor) {
411
- const name = getName(doc, thread.anchor);
412
- if (name && name !== thread.name) {
413
- thread.name = name;
414
- }
415
- }
416
- });
417
- }
418
- }),
419
- (0, import_react_ui_editor2.createExternalCommentSync)((0, import_echo5.fullyQualifiedId)(doc), (sink) => (0, import_signals_core.effect)(() => sink()), () => threads2.value.filter((thread) => thread?.anchor).map((thread) => ({
420
- id: (0, import_echo5.fullyQualifiedId)(thread),
421
- cursor: thread.anchor
422
- }))),
423
- (0, import_react_ui_editor2.comments)({
424
- id: (0, import_echo5.fullyQualifiedId)(doc),
425
- onCreate: ({ cursor }) => {
426
- const name = getName(doc, cursor);
427
- void dispatch({
428
- action: import_chunk_FOZUQZF4.ThreadAction.CREATE,
429
- data: {
430
- cursor,
431
- name,
432
- subject: doc
433
- }
434
- });
435
- },
436
- onDelete: ({ id }) => {
437
- const draft = state.drafts[(0, import_echo5.fullyQualifiedId)(doc)];
438
- if (draft) {
439
- const index = draft.findIndex((thread2) => (0, import_echo5.fullyQualifiedId)(thread2) === id);
440
- if (index !== -1) {
441
- draft.splice(index, 1);
442
- }
443
- }
444
- const thread = doc.threads.find((thread2) => thread2?.id === id);
445
- if (thread) {
446
- thread.anchor = void 0;
447
- }
448
- },
449
- onUpdate: ({ id, cursor }) => {
450
- const thread = state.drafts[(0, import_echo5.fullyQualifiedId)(doc)]?.find((thread2) => (0, import_echo5.fullyQualifiedId)(thread2) === id) ?? doc.threads.find((thread2) => thread2?.id === id);
451
- if (thread instanceof import_types3.ThreadType && thread.anchor) {
452
- thread.name = getName(doc, thread.anchor);
453
- thread.anchor = cursor;
454
- }
455
- },
456
- onSelect: ({ selection: { current, closest } }) => {
457
- void dispatch({
458
- action: import_chunk_FOZUQZF4.ThreadAction.SELECT,
459
- data: {
460
- current: current ?? closest,
461
- skipOpen: true
462
- }
463
- });
464
- }
465
- })
466
- ];
467
- };
296
+ var ThreadMain = import_react3.default.lazy(() => import("./ThreadMain-XJX75GHG.cjs"));
297
+ var ThreadArticle = import_react3.default.lazy(() => import("./ThreadArticle-DO56JXBU.cjs"));
468
298
  var translations_default = [
469
299
  {
470
300
  "en-US": {
471
- [import_chunk_JIJ7Z6NO.THREAD_PLUGIN]: {
301
+ [import_chunk_BWBONZGU.THREAD_PLUGIN]: {
472
302
  "plugin name": "Threads",
473
303
  "channel name placeholder": "New channel",
474
304
  "channel title label": "Title",
@@ -499,16 +329,16 @@ var translations_default = [
499
329
  }
500
330
  }
501
331
  ];
502
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-thread/src/ThreadPlugin.tsx";
503
332
  var initialViewState = {
504
333
  showResolvedThreads: false
505
334
  };
335
+ var providesThreadsConfig = (plugin) => "thread" in plugin.provides ? plugin : void 0;
506
336
  var ThreadPlugin = () => {
507
- const settings = new import_local_storage.LocalStorageStore(import_chunk_JIJ7Z6NO.THREAD_PLUGIN);
508
- const state = (0, import_echo_schema.create)({
509
- drafts: {}
337
+ const settings = new import_local_storage.LocalStorageStore(import_chunk_BWBONZGU.THREAD_PLUGIN);
338
+ const state = (0, import_echo_schema2.create)({
339
+ staging: {}
510
340
  });
511
- const viewStore = (0, import_echo_schema.create)({});
341
+ const viewStore = (0, import_echo_schema2.create)({});
512
342
  const getViewState = (subjectId) => {
513
343
  if (!viewStore[subjectId]) {
514
344
  viewStore[subjectId] = {
@@ -517,11 +347,13 @@ var ThreadPlugin = () => {
517
347
  }
518
348
  return viewStore[subjectId];
519
349
  };
350
+ let attentionPlugin;
520
351
  let navigationPlugin;
521
352
  let intentPlugin;
353
+ let dispatch;
522
354
  const unsubscribeCallbacks = [];
523
355
  return {
524
- meta: import_chunk_JIJ7Z6NO.meta_default,
356
+ meta: import_chunk_BWBONZGU.meta_default,
525
357
  ready: async (plugins) => {
526
358
  settings.prop({
527
359
  key: "standalone",
@@ -529,8 +361,36 @@ var ThreadPlugin = () => {
529
361
  allowUndefined: true
530
362
  })
531
363
  });
364
+ attentionPlugin = (0, import_app_framework.resolvePlugin)(plugins, import_plugin_attention.parseAttentionPlugin);
532
365
  navigationPlugin = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseNavigationPlugin);
533
366
  intentPlugin = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseIntentPlugin);
367
+ dispatch = intentPlugin?.provides.intent.dispatch;
368
+ const graphPlugin = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseGraphPlugin);
369
+ const client = (0, import_app_framework.resolvePlugin)(plugins, import_plugin_client.parseClientPlugin)?.provides.client;
370
+ if (!client) {
371
+ return;
372
+ }
373
+ const channelsQuery = client.spaces.query(import_echo.Filter.schema(import_types2.ChannelType));
374
+ const queryUnsubscribe = channelsQuery.subscribe();
375
+ const unsubscribe = (0, import_signals_core.effect)(() => {
376
+ const attention = attentionPlugin?.provides.attention;
377
+ if (!attention?.attended) {
378
+ return;
379
+ }
380
+ const firstAttendedNodeWithComments = Array.from(attention.attended).map((id) => graphPlugin?.provides.graph.findNode(id)).find((node) => node?.data instanceof import_types.DocumentType && (node.data.threads?.length ?? 0) > 0);
381
+ if (firstAttendedNodeWithComments) {
382
+ void intentPlugin?.provides.intent.dispatch({
383
+ action: import_app_framework.NavigationAction.OPEN,
384
+ data: {
385
+ activeParts: {
386
+ complementary: `${firstAttendedNodeWithComments.id}${import_app_framework.SLUG_PATH_SEPARATOR}comments`
387
+ }
388
+ }
389
+ });
390
+ }
391
+ });
392
+ unsubscribeCallbacks.push(queryUnsubscribe);
393
+ unsubscribeCallbacks.push(unsubscribe);
534
394
  },
535
395
  unload: async () => {
536
396
  unsubscribeCallbacks.forEach((unsubscribe) => unsubscribe());
@@ -539,26 +399,27 @@ var ThreadPlugin = () => {
539
399
  settings: settings.values,
540
400
  metadata: {
541
401
  records: {
542
- [import_types.ChannelType.typename]: {
402
+ [import_types2.ChannelType.typename]: {
543
403
  placeholder: [
544
404
  "channel title placeholder",
545
405
  {
546
- ns: import_chunk_JIJ7Z6NO.THREAD_PLUGIN
406
+ ns: import_chunk_BWBONZGU.THREAD_PLUGIN
547
407
  }
548
408
  ],
549
- icon: "ph--chat--regular",
409
+ icon: (props) => /* @__PURE__ */ import_react2.default.createElement(import_react.Chat, props),
410
+ iconSymbol: "ph--chat--regular",
550
411
  // TODO(wittjosiah): Move out of metadata.
551
412
  loadReferences: (channel) => (0, import_echo.loadObjectReferences)(channel, (channel2) => channel2.threads)
552
413
  },
553
- [import_types.ThreadType.typename]: {
414
+ [import_types2.ThreadType.typename]: {
554
415
  // TODO(wittjosiah): Move out of metadata.
555
416
  loadReferences: (thread) => (0, import_echo.loadObjectReferences)(thread, (thread2) => thread2.messages)
556
417
  },
557
- [import_types.MessageType.typename]: {
418
+ [import_types2.MessageType.typename]: {
558
419
  // TODO(wittjosiah): Move out of metadata.
559
420
  loadReferences: (message) => []
560
421
  },
561
- [import_chunk_JIJ7Z6NO.THREAD_ITEM]: {
422
+ [import_chunk_BWBONZGU.THREAD_ITEM]: {
562
423
  parse: (item, type) => {
563
424
  switch (type) {
564
425
  case "node":
@@ -585,56 +446,49 @@ var ThreadPlugin = () => {
585
446
  ],
586
447
  echo: {
587
448
  schema: [
588
- import_types.ChannelType,
589
- import_types.ThreadType,
590
- import_types.MessageType
449
+ import_types2.ChannelType,
450
+ import_types2.ThreadType,
451
+ import_types2.MessageType
591
452
  ]
592
453
  },
593
454
  graph: {
594
455
  builder: (plugins) => {
595
456
  const client = (0, import_app_framework.resolvePlugin)(plugins, import_plugin_client.parseClientPlugin)?.provides.client;
596
- const dispatch = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseIntentPlugin)?.provides.intent.dispatch;
457
+ const dispatch2 = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseIntentPlugin)?.provides.intent.dispatch;
597
458
  const metadataResolver = (0, import_app_framework.resolvePlugin)(plugins, import_app_framework.parseMetadataResolverPlugin)?.provides.metadata.resolver;
598
- if (!client || !dispatch || !metadataResolver) {
459
+ if (!client || !dispatch2 || !metadataResolver) {
599
460
  return [];
600
461
  }
601
462
  return [
602
463
  (0, import_plugin_graph.createExtension)({
603
- id: `${import_chunk_JIJ7Z6NO.THREAD_PLUGIN}/comments-for-subject`,
464
+ id: `${import_chunk_BWBONZGU.THREAD_PLUGIN}/comments-for-subject`,
604
465
  resolver: ({ id }) => {
605
466
  if (!id.endsWith("~comments")) {
606
467
  return;
607
468
  }
608
- const [subjectId] = id.split("~");
609
- const [spaceId, objectId] = (0, import_echo.parseFullyQualifiedId)(subjectId);
469
+ const docId = id.split("~").at(0);
470
+ const [spaceId, objectId] = docId?.split(":") ?? [];
610
471
  const space = client.spaces.get().find((space2) => space2.id === spaceId);
611
- const object = (0, import_plugin_graph.toSignal)((onChange) => {
612
- const timeout = setTimeout(async () => {
613
- await space?.db.loadObjectById(objectId);
614
- onChange();
615
- });
616
- return () => clearTimeout(timeout);
617
- }, () => space?.db.getObjectById(objectId), subjectId);
618
- if (!object || !subjectId) {
472
+ const doc = space?.db.getObjectById(objectId);
473
+ if (!doc || !docId) {
619
474
  return;
620
475
  }
621
- const meta = metadataResolver((0, import_echo_schema.getTypename)(object) ?? "");
622
- const label = meta.label?.(object) || object.name || meta.placeholder || [
476
+ const docMeta = metadataResolver((0, import_echo_schema.getTypename)(doc) ?? "");
477
+ const label = docMeta.label?.(doc) || doc.name || docMeta.placeholder || [
623
478
  "unnamed object threads label",
624
479
  {
625
- ns: import_chunk_JIJ7Z6NO.THREAD_PLUGIN
480
+ ns: import_chunk_BWBONZGU.THREAD_PLUGIN
626
481
  }
627
482
  ];
628
- const viewState = getViewState(subjectId);
483
+ const viewState = getViewState(docId);
629
484
  return {
630
485
  id,
631
486
  type: "orphan-comments-for-subject",
632
- data: null,
487
+ data: doc,
633
488
  properties: {
634
- icon: "ph--chat-text--regular",
489
+ icon: import_chunk_BWBONZGU.meta_default.iconComponent,
635
490
  label,
636
- showResolvedThreads: viewState.showResolvedThreads,
637
- object
491
+ showResolvedThreads: viewState.showResolvedThreads
638
492
  }
639
493
  };
640
494
  },
@@ -648,7 +502,7 @@ var ThreadPlugin = () => {
648
502
  const toggle = () => {
649
503
  const newToggleState = !viewState.showResolvedThreads;
650
504
  viewState.showResolvedThreads = newToggleState;
651
- void dispatch({
505
+ void dispatch2({
652
506
  action: import_meta.ObservabilityAction.SEND_EVENT,
653
507
  data: {
654
508
  name: "threads.toggle-show-resolved",
@@ -662,26 +516,25 @@ var ThreadPlugin = () => {
662
516
  };
663
517
  return [
664
518
  {
665
- id: `${import_chunk_JIJ7Z6NO.THREAD_PLUGIN}/toggle-show-resolved/${node.id}`,
519
+ id: `${import_chunk_BWBONZGU.THREAD_PLUGIN}/toggle-show-resolved/${node.id}`,
666
520
  data: toggle,
667
521
  properties: {
668
522
  label: [
669
523
  "toggle show resolved",
670
524
  {
671
- ns: import_chunk_JIJ7Z6NO.THREAD_PLUGIN
525
+ ns: import_chunk_BWBONZGU.THREAD_PLUGIN
672
526
  }
673
527
  ],
674
528
  menuItemType: "toggle",
675
529
  isChecked: viewState.showResolvedThreads,
676
- testId: "threadPlugin.toggleShowResolved",
677
- icon: viewState.showResolvedThreads ? "ph--eye-slash--regular" : "ph--eye--regular"
530
+ testId: "threadPlugin.toggleShowResolved"
678
531
  }
679
532
  }
680
533
  ];
681
534
  }
682
535
  }),
683
536
  (0, import_plugin_graph.createExtension)({
684
- id: import_chunk_FOZUQZF4.ThreadAction.CREATE,
537
+ id: import_chunk_D5GOVXHS.ThreadAction.CREATE,
685
538
  filter: (node) => !!settings.values.standalone && (0, import_plugin_graph.isActionGroup)(node) && node.id.startsWith(import_plugin_space.SpaceAction.ADD_OBJECT),
686
539
  actions: ({ node }) => {
687
540
  const id = node.id.split("/").at(-1);
@@ -694,12 +547,12 @@ var ThreadPlugin = () => {
694
547
  }
695
548
  return [
696
549
  {
697
- id: `${import_chunk_JIJ7Z6NO.THREAD_PLUGIN}/create/${node.id}`,
550
+ id: `${import_chunk_BWBONZGU.THREAD_PLUGIN}/create/${node.id}`,
698
551
  data: async () => {
699
- await dispatch([
552
+ await dispatch2([
700
553
  {
701
- plugin: import_chunk_JIJ7Z6NO.THREAD_PLUGIN,
702
- action: import_chunk_FOZUQZF4.ThreadAction.CREATE
554
+ plugin: import_chunk_BWBONZGU.THREAD_PLUGIN,
555
+ action: import_chunk_D5GOVXHS.ThreadAction.CREATE
703
556
  },
704
557
  {
705
558
  action: import_plugin_space.SpaceAction.ADD_OBJECT,
@@ -716,10 +569,11 @@ var ThreadPlugin = () => {
716
569
  label: [
717
570
  "create channel label",
718
571
  {
719
- ns: import_chunk_JIJ7Z6NO.THREAD_PLUGIN
572
+ ns: import_chunk_BWBONZGU.THREAD_PLUGIN
720
573
  }
721
574
  ],
722
- icon: "ph--chat--regular",
575
+ icon: (props) => /* @__PURE__ */ import_react2.default.createElement(import_react.Chat, props),
576
+ iconSymbol: "ph--chat--regular",
723
577
  testId: "threadPlugin.createObject"
724
578
  }
725
579
  }
@@ -733,18 +587,21 @@ var ThreadPlugin = () => {
733
587
  component: ({ data, role }) => {
734
588
  switch (role) {
735
589
  case "main": {
736
- return data.active instanceof import_types.ChannelType && data.active.threads[0] ? /* @__PURE__ */ import_react.default.createElement(ThreadMain, {
590
+ return data.active instanceof import_types2.ChannelType && data.active.threads[0] ? /* @__PURE__ */ import_react2.default.createElement(ThreadMain, {
737
591
  thread: data.active.threads[0]
738
592
  }) : null;
739
593
  }
740
594
  case "settings": {
741
- return data.plugin === import_chunk_JIJ7Z6NO.meta_default.id ? /* @__PURE__ */ import_react.default.createElement(ThreadSettings, {
595
+ return data.plugin === import_chunk_BWBONZGU.meta_default.id ? /* @__PURE__ */ import_react2.default.createElement(ThreadSettings, {
742
596
  settings: settings.values
743
597
  }) : null;
744
598
  }
745
- case "article": {
599
+ case "article":
600
+ case "complementary": {
746
601
  const location = navigationPlugin?.provides.location;
747
- if (data.object instanceof import_types.ChannelType && data.object.threads[0]) {
602
+ const threadsIntegrators = (0, import_app_framework.useResolvePlugins)(providesThreadsConfig);
603
+ const threadProvides = threadsIntegrators.map((p) => p.provides.thread);
604
+ if (data.object instanceof import_types2.ChannelType && data.object.threads[0]) {
748
605
  const channel = data.object;
749
606
  if ((0, import_app_framework.isLayoutParts)(location?.active) && location.active.main) {
750
607
  const layoutEntries = location.active.main;
@@ -752,37 +609,102 @@ var ThreadPlugin = () => {
752
609
  if (currentPosition > 0) {
753
610
  const objectToTheLeft = layoutEntries[currentPosition - 1];
754
611
  const context = (0, import_echo.getSpace)(data.object)?.db.getObjectById(objectToTheLeft.id);
755
- return /* @__PURE__ */ import_react.default.createElement(ThreadArticle, {
612
+ return /* @__PURE__ */ import_react2.default.createElement(ThreadArticle, {
756
613
  thread: data.object.threads[0],
757
614
  context
758
615
  });
759
616
  }
760
617
  }
761
- return /* @__PURE__ */ import_react.default.createElement(ThreadArticle, {
618
+ return /* @__PURE__ */ import_react2.default.createElement(ThreadArticle, {
762
619
  thread: data.object.threads[0]
763
620
  });
764
621
  }
765
- if (data.subject instanceof import_types.ThreadType) {
766
- return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_chunk_FDYRG7HE.ChatHeading, {
622
+ if (data.subject instanceof import_types2.ThreadType) {
623
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_chunk_5PZNPPQF.ChatHeading, {
767
624
  attendableId: data.subject.id
768
- }), /* @__PURE__ */ import_react.default.createElement(import_chunk_FDYRG7HE.ChatContainer, {
625
+ }), /* @__PURE__ */ import_react2.default.createElement(import_chunk_5PZNPPQF.ChatContainer, {
769
626
  thread: data.subject
770
627
  }));
771
628
  }
772
- break;
773
- }
774
- case "complementary--comments": {
775
629
  if (data.subject && typeof data.subject === "object" && "threads" in data.subject && Array.isArray(data.subject.threads)) {
776
- const { showResolvedThreads } = getViewState((0, import_echo.fullyQualifiedId)(data.subject));
777
- return /* @__PURE__ */ import_react.default.createElement(ThreadComplementary, {
778
- role,
779
- subject: data.subject,
780
- drafts: state.drafts[(0, import_echo.fullyQualifiedId)(data.subject)],
781
- current: state.current,
782
- showResolvedThreads
783
- });
630
+ const threads = data.subject.threads.concat(state.staging[(0, import_echo.fullyQualifiedId)(data.subject)]).filter(import_util.nonNullable);
631
+ const createSort = threadProvides.find((p) => p.predicate(data.subject))?.createSort;
632
+ if (createSort) {
633
+ const sort = createSort(data.subject);
634
+ threads.sort((a, b) => sort(a.anchor, b.anchor));
635
+ }
636
+ const detached = data.subject.threads.filter(import_util.nonNullable).filter(({ anchor }) => !anchor).map((thread) => thread.id);
637
+ const qualifiedSubjectId = (0, import_echo.fullyQualifiedId)(data.subject);
638
+ const attention = attentionPlugin?.provides.attention?.attended ?? /* @__PURE__ */ new Set([
639
+ qualifiedSubjectId
640
+ ]);
641
+ const attendableAttrs = (0, import_react_ui_attention.createAttendableAttributes)(qualifiedSubjectId);
642
+ const { showResolvedThreads } = getViewState(qualifiedSubjectId);
643
+ return /* @__PURE__ */ import_react2.default.createElement("div", {
644
+ role: "none",
645
+ className: "contents group/attention",
646
+ ...attendableAttrs
647
+ }, role === "complementary" && /* @__PURE__ */ import_react2.default.createElement(CommentsHeading, {
648
+ attendableId: qualifiedSubjectId
649
+ }), /* @__PURE__ */ import_react2.default.createElement(import_react_ui.ScrollArea.Root, {
650
+ classNames: "row-span-2"
651
+ }, /* @__PURE__ */ import_react2.default.createElement(import_react_ui.ScrollArea.Viewport, null, /* @__PURE__ */ import_react2.default.createElement(CommentsContainer, {
652
+ threads,
653
+ detached,
654
+ currentId: attention.has(qualifiedSubjectId) ? state.current : void 0,
655
+ autoFocusCurrentTextbox: state.focus,
656
+ showResolvedThreads,
657
+ onThreadAttend: (thread) => {
658
+ if (state.current !== thread.id) {
659
+ state.current = thread.id;
660
+ void dispatch?.({
661
+ action: import_app_framework.LayoutAction.SCROLL_INTO_VIEW,
662
+ data: {
663
+ id: (0, import_echo.fullyQualifiedId)(data.subject),
664
+ thread: (0, import_echo.fullyQualifiedId)(thread),
665
+ cursor: thread.anchor
666
+ }
667
+ });
668
+ }
669
+ },
670
+ onThreadDelete: (thread) => dispatch?.({
671
+ plugin: import_chunk_BWBONZGU.THREAD_PLUGIN,
672
+ action: import_chunk_D5GOVXHS.ThreadAction.DELETE,
673
+ data: {
674
+ subject: data.subject,
675
+ thread
676
+ }
677
+ }),
678
+ onMessageDelete: (thread, messageId) => dispatch?.({
679
+ plugin: import_chunk_BWBONZGU.THREAD_PLUGIN,
680
+ action: import_chunk_D5GOVXHS.ThreadAction.DELETE_MESSAGE,
681
+ data: {
682
+ subject: data.subject,
683
+ thread,
684
+ messageId
685
+ }
686
+ }),
687
+ onThreadToggleResolved: (thread) => dispatch?.({
688
+ plugin: import_chunk_BWBONZGU.THREAD_PLUGIN,
689
+ action: import_chunk_D5GOVXHS.ThreadAction.TOGGLE_RESOLVED,
690
+ data: {
691
+ thread
692
+ }
693
+ }),
694
+ onComment: (thread) => {
695
+ void intentPlugin?.provides.intent.dispatch({
696
+ action: import_chunk_D5GOVXHS.ThreadAction.ON_MESSAGE_ADD,
697
+ data: {
698
+ thread,
699
+ subject: data.subject
700
+ }
701
+ });
702
+ }
703
+ }), /* @__PURE__ */ import_react2.default.createElement("div", {
704
+ role: "none",
705
+ className: "bs-10"
706
+ }), /* @__PURE__ */ import_react2.default.createElement(import_react_ui.ScrollArea.Scrollbar, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui.ScrollArea.Thumb, null)))));
784
707
  }
785
- break;
786
708
  }
787
709
  }
788
710
  return null;
@@ -791,65 +713,59 @@ var ThreadPlugin = () => {
791
713
  intent: {
792
714
  resolver: async (intent) => {
793
715
  switch (intent.action) {
794
- case import_chunk_FOZUQZF4.ThreadAction.CREATE: {
716
+ case import_chunk_D5GOVXHS.ThreadAction.CREATE: {
795
717
  if (intent.data && intent.data.cursor !== void 0) {
796
718
  const { cursor, name, subject } = intent.data;
797
- if (subject?.threads === void 0) {
798
- try {
799
- subject.threads = [];
800
- } catch (err) {
801
- import_log.log.error("Subject does not support threads array", subject?.typename, {
802
- F: __dxlog_file,
803
- L: 327,
804
- S: void 0,
805
- C: (f, a) => f(...a)
806
- });
807
- return;
808
- }
809
- }
810
719
  const subjectId = (0, import_echo.fullyQualifiedId)(subject);
811
- const thread = (0, import_echo_schema.create)(import_types.ThreadType, {
720
+ const thread = (0, import_echo_schema2.create)(import_types2.ThreadType, {
812
721
  name,
813
722
  anchor: cursor,
814
723
  messages: [],
815
724
  status: "staged"
816
725
  });
817
- const draft = state.drafts[subjectId];
818
- if (draft) {
819
- draft.push(thread);
726
+ const stagingArea = state.staging[subjectId];
727
+ if (stagingArea) {
728
+ stagingArea.push(thread);
820
729
  } else {
821
- state.drafts[subjectId] = [
730
+ state.staging[subjectId] = [
822
731
  thread
823
732
  ];
824
733
  }
825
734
  return {
826
735
  data: thread,
827
736
  intents: [
828
- [
829
- {
830
- action: import_chunk_FOZUQZF4.ThreadAction.SELECT,
831
- data: {
832
- current: (0, import_echo.fullyQualifiedId)(thread)
833
- }
834
- }
835
- ],
836
737
  [
837
738
  {
838
739
  action: import_app_framework.NavigationAction.OPEN,
839
740
  data: {
840
741
  activeParts: {
841
- complementary: "comments"
742
+ complementary: `${subjectId}${import_app_framework.SLUG_PATH_SEPARATOR}comments${import_app_framework.SLUG_COLLECTION_INDICATOR}`
842
743
  }
843
744
  }
745
+ },
746
+ {
747
+ action: import_chunk_D5GOVXHS.ThreadAction.SELECT,
748
+ data: {
749
+ current: thread.id,
750
+ focus: true
751
+ }
752
+ },
753
+ {
754
+ action: import_app_framework.LayoutAction.SET_LAYOUT,
755
+ data: {
756
+ element: "complementary",
757
+ subject: subjectId,
758
+ state: true
759
+ }
844
760
  }
845
761
  ]
846
762
  ]
847
763
  };
848
764
  } else {
849
765
  return {
850
- data: (0, import_echo_schema.create)(import_types.ChannelType, {
766
+ data: (0, import_echo_schema2.create)(import_types2.ChannelType, {
851
767
  threads: [
852
- (0, import_echo_schema.create)(import_types.ThreadType, {
768
+ (0, import_echo_schema2.create)(import_types2.ThreadType, {
853
769
  messages: []
854
770
  })
855
771
  ]
@@ -857,27 +773,16 @@ var ThreadPlugin = () => {
857
773
  };
858
774
  }
859
775
  }
860
- case import_chunk_FOZUQZF4.ThreadAction.SELECT: {
776
+ case import_chunk_D5GOVXHS.ThreadAction.SELECT: {
777
+ state.focus = intent.data?.current === state.current ? state.focus : intent.data?.focus;
861
778
  state.current = intent.data?.current;
862
779
  return {
863
- data: true,
864
- intents: !intent.data?.skipOpen ? [
865
- [
866
- {
867
- action: import_app_framework.NavigationAction.OPEN,
868
- data: {
869
- activeParts: {
870
- complementary: "comments"
871
- }
872
- }
873
- }
874
- ]
875
- ] : []
780
+ data: true
876
781
  };
877
782
  }
878
- case import_chunk_FOZUQZF4.ThreadAction.TOGGLE_RESOLVED: {
783
+ case import_chunk_D5GOVXHS.ThreadAction.TOGGLE_RESOLVED: {
879
784
  const { thread } = intent.data ?? {};
880
- if (!(thread instanceof import_types.ThreadType)) {
785
+ if (!(thread instanceof import_types2.ThreadType)) {
881
786
  return;
882
787
  }
883
788
  if (thread.status === "active" || thread.status === void 0) {
@@ -888,7 +793,6 @@ var ThreadPlugin = () => {
888
793
  const space = (0, import_echo.getSpace)(thread);
889
794
  const spaceId = space?.id;
890
795
  return {
891
- data: true,
892
796
  intents: [
893
797
  [
894
798
  {
@@ -905,20 +809,18 @@ var ThreadPlugin = () => {
905
809
  ]
906
810
  };
907
811
  }
908
- case import_chunk_FOZUQZF4.ThreadAction.DELETE: {
812
+ case import_chunk_D5GOVXHS.ThreadAction.DELETE: {
909
813
  const { subject, thread } = intent.data ?? {};
910
- if (!(thread instanceof import_types.ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
814
+ if (!(subject instanceof import_types.DocumentType) || !(thread instanceof import_types2.ThreadType)) {
911
815
  return;
912
816
  }
913
817
  const subjectId = (0, import_echo.fullyQualifiedId)(subject);
914
- const draft = state.drafts[subjectId];
915
- if (draft) {
916
- const index = draft.findIndex((t) => t.id === thread.id);
818
+ const stagingArea = state.staging[subjectId];
819
+ if (stagingArea) {
820
+ const index = stagingArea.findIndex((t) => t.id === thread.id);
917
821
  if (index !== -1) {
918
- draft.splice(index, 1);
919
- return {
920
- data: true
921
- };
822
+ stagingArea.splice(index, 1);
823
+ return;
922
824
  }
923
825
  }
924
826
  const space = (0, import_echo.getSpace)(thread);
@@ -934,7 +836,7 @@ var ThreadPlugin = () => {
934
836
  space.db.remove(thread);
935
837
  return {
936
838
  undoable: {
937
- message: translations_default[0]["en-US"][import_chunk_JIJ7Z6NO.THREAD_PLUGIN]["thread deleted label"],
839
+ message: translations_default[0]["en-US"][import_chunk_BWBONZGU.THREAD_PLUGIN]["thread deleted label"],
938
840
  data: {
939
841
  cursor
940
842
  }
@@ -977,9 +879,9 @@ var ThreadPlugin = () => {
977
879
  }
978
880
  break;
979
881
  }
980
- case import_chunk_FOZUQZF4.ThreadAction.ON_MESSAGE_ADD: {
882
+ case import_chunk_D5GOVXHS.ThreadAction.ON_MESSAGE_ADD: {
981
883
  const { thread, subject } = intent.data ?? {};
982
- if (!(thread instanceof import_types.ThreadType) || !(subject && typeof subject === "object" && "threads" in subject && Array.isArray(subject.threads))) {
884
+ if (!(thread instanceof import_types2.ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
983
885
  return;
984
886
  }
985
887
  const subjectId = (0, import_echo.fullyQualifiedId)(subject);
@@ -989,12 +891,12 @@ var ThreadPlugin = () => {
989
891
  threadId: thread.id,
990
892
  spaceId: space?.id
991
893
  };
992
- if (state.drafts[subjectId]?.find((t) => t === thread)) {
894
+ if (state.staging[subjectId]?.find((t) => t === thread)) {
993
895
  thread.status = "active";
994
896
  subject.threads ? subject.threads.push(thread) : subject.threads = [
995
897
  thread
996
898
  ];
997
- state.drafts[subjectId] = state.drafts[subjectId]?.filter(({ id }) => id !== thread.id);
899
+ state.staging[subjectId] = state.staging[subjectId]?.filter((t) => t.id !== thread.id);
998
900
  intents.push({
999
901
  action: import_meta.ObservabilityAction.SEND_EVENT,
1000
902
  data: {
@@ -1020,10 +922,10 @@ var ThreadPlugin = () => {
1020
922
  ]
1021
923
  };
1022
924
  }
1023
- case import_chunk_FOZUQZF4.ThreadAction.DELETE_MESSAGE: {
925
+ case import_chunk_D5GOVXHS.ThreadAction.DELETE_MESSAGE: {
1024
926
  const { subject, thread, messageId } = intent.data ?? {};
1025
927
  const space = (0, import_echo.getSpace)(subject);
1026
- if (!(thread instanceof import_types.ThreadType) || !(subject && typeof subject === "object" && "threads" in subject)) {
928
+ if (!(subject instanceof import_types.DocumentType) || !(thread instanceof import_types2.ThreadType) || !space) {
1027
929
  return;
1028
930
  }
1029
931
  if (!intent.undo) {
@@ -1037,7 +939,7 @@ var ThreadPlugin = () => {
1037
939
  intents: [
1038
940
  [
1039
941
  {
1040
- action: import_chunk_FOZUQZF4.ThreadAction.DELETE,
942
+ action: import_chunk_D5GOVXHS.ThreadAction.DELETE,
1041
943
  data: {
1042
944
  subject,
1043
945
  thread
@@ -1051,7 +953,7 @@ var ThreadPlugin = () => {
1051
953
  }
1052
954
  return {
1053
955
  undoable: {
1054
- message: translations_default[0]["en-US"][import_chunk_JIJ7Z6NO.THREAD_PLUGIN]["message deleted label"],
956
+ message: translations_default[0]["en-US"][import_chunk_BWBONZGU.THREAD_PLUGIN]["message deleted label"],
1055
957
  data: {
1056
958
  message,
1057
959
  messageIndex
@@ -1065,7 +967,7 @@ var ThreadPlugin = () => {
1065
967
  name: "threads.message.delete",
1066
968
  properties: {
1067
969
  threadId: thread.id,
1068
- spaceId: space?.id
970
+ spaceId: space.id
1069
971
  }
1070
972
  }
1071
973
  }
@@ -1075,7 +977,7 @@ var ThreadPlugin = () => {
1075
977
  } else if (intent.undo) {
1076
978
  const message = intent.data?.message;
1077
979
  const messageIndex = intent.data?.messageIndex;
1078
- if (!(message instanceof import_types.MessageType) || !(typeof messageIndex === "number")) {
980
+ if (!(message instanceof import_types2.MessageType) || !(typeof messageIndex === "number")) {
1079
981
  return;
1080
982
  }
1081
983
  thread.messages.splice(messageIndex, 0, message);
@@ -1089,7 +991,7 @@ var ThreadPlugin = () => {
1089
991
  name: "threads.message.undo-delete",
1090
992
  properties: {
1091
993
  threadId: thread.id,
1092
- spaceId: space?.id
994
+ spaceId: space.id
1093
995
  }
1094
996
  }
1095
997
  }
@@ -1102,8 +1004,92 @@ var ThreadPlugin = () => {
1102
1004
  }
1103
1005
  },
1104
1006
  markdown: {
1007
+ // TODO(burdon): Factor out extension factory into separate file (for simplicity).
1105
1008
  extensions: ({ document: doc }) => {
1106
- return threads(state, doc, intentPlugin?.provides.intent.dispatch);
1009
+ const space = doc && (0, import_echo.getSpace)(doc);
1010
+ if (!doc || !space) {
1011
+ return [
1012
+ (0, import_react_ui_editor.comments)()
1013
+ ];
1014
+ }
1015
+ const threads = (0, import_signals_core.computed)(() => [
1016
+ ...doc.threads.filter(import_util.nonNullable),
1017
+ ...state.staging[(0, import_echo.fullyQualifiedId)(doc)] ?? []
1018
+ ].filter((thread) => !(thread?.status === "resolved")));
1019
+ return [
1020
+ (0, import_react_ui_editor.listener)({
1021
+ onChange: () => {
1022
+ doc.threads.forEach((thread) => {
1023
+ if (thread?.anchor) {
1024
+ const [start, end] = thread.anchor.split(":");
1025
+ const name = doc.content && (0, import_echo.getTextInRange)((0, import_echo.createDocAccessor)(doc.content, [
1026
+ "content"
1027
+ ]), start, end);
1028
+ if (name && name !== thread.name) {
1029
+ thread.name = name;
1030
+ }
1031
+ }
1032
+ });
1033
+ }
1034
+ }),
1035
+ (0, import_react_ui_editor.createExternalCommentSync)(doc.id, (sink) => (0, import_signals_core.effect)(() => sink()), () => threads.value.filter((thread) => thread?.anchor).map((thread) => ({
1036
+ id: thread.id,
1037
+ cursor: thread.anchor
1038
+ }))),
1039
+ (0, import_react_ui_editor.comments)({
1040
+ id: doc.id,
1041
+ onCreate: ({ cursor }) => {
1042
+ const [start, end] = cursor.split(":");
1043
+ const name = doc.content && (0, import_echo.getTextInRange)((0, import_echo.createDocAccessor)(doc.content, [
1044
+ "content"
1045
+ ]), start, end);
1046
+ void intentPlugin?.provides.intent.dispatch({
1047
+ action: import_chunk_D5GOVXHS.ThreadAction.CREATE,
1048
+ data: {
1049
+ cursor,
1050
+ name,
1051
+ subject: doc
1052
+ }
1053
+ });
1054
+ },
1055
+ onDelete: ({ id }) => {
1056
+ const stagingArea = state.staging[(0, import_echo.fullyQualifiedId)(doc)];
1057
+ if (stagingArea) {
1058
+ const index = stagingArea.findIndex((thread2) => thread2.id === id);
1059
+ if (index !== -1) {
1060
+ stagingArea.splice(index, 1);
1061
+ }
1062
+ }
1063
+ const thread = doc.threads.find((thread2) => thread2?.id === id);
1064
+ if (thread) {
1065
+ thread.anchor = void 0;
1066
+ }
1067
+ },
1068
+ onUpdate: ({ id, cursor }) => {
1069
+ const thread = state.staging[(0, import_echo.fullyQualifiedId)(doc)]?.find((thread2) => thread2.id === id) ?? doc.threads.find((thread2) => thread2?.id === id);
1070
+ if (thread instanceof import_types2.ThreadType && thread.anchor) {
1071
+ const [start, end] = thread.anchor.split(":");
1072
+ thread.name = doc.content && (0, import_echo.getTextInRange)((0, import_echo.createDocAccessor)(doc.content, [
1073
+ "content"
1074
+ ]), start, end);
1075
+ thread.anchor = cursor;
1076
+ }
1077
+ },
1078
+ onSelect: ({ selection: { current, closest } }) => {
1079
+ const dispatch2 = intentPlugin?.provides.intent.dispatch;
1080
+ if (dispatch2) {
1081
+ void dispatch2([
1082
+ {
1083
+ action: import_chunk_D5GOVXHS.ThreadAction.SELECT,
1084
+ data: {
1085
+ current: current ?? closest
1086
+ }
1087
+ }
1088
+ ]);
1089
+ }
1090
+ }
1091
+ })
1092
+ ];
1107
1093
  }
1108
1094
  }
1109
1095
  }