@dxos/plugin-thread 0.7.5-main.499c70c → 0.7.5-main.5ae2ba8
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.
- package/dist/lib/browser/ThreadContainer-6OP5AG2W.mjs +19 -0
- package/dist/lib/browser/ThreadContainer-6OP5AG2W.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ENERBDYI.mjs → chunk-636QDHE3.mjs} +3 -3
- package/dist/lib/browser/chunk-636QDHE3.mjs.map +7 -0
- package/dist/lib/browser/chunk-BNEWNQBO.mjs +71 -0
- package/dist/lib/browser/chunk-BNEWNQBO.mjs.map +7 -0
- package/dist/lib/browser/chunk-NAO3LZMZ.mjs +16 -0
- package/dist/lib/browser/chunk-NAO3LZMZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-OD2IZKRP.mjs → chunk-UPKU23DA.mjs} +29 -105
- package/dist/lib/browser/chunk-UPKU23DA.mjs.map +7 -0
- package/dist/lib/browser/chunk-VOMIDDNO.mjs +15 -0
- package/dist/lib/browser/chunk-VOMIDDNO.mjs.map +7 -0
- package/dist/lib/browser/{chunk-6KTMQPL4.mjs → chunk-YK3ICB7G.mjs} +5 -3
- package/dist/lib/browser/chunk-YK3ICB7G.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +150 -942
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-FAFQ54NP.mjs +287 -0
- package/dist/lib/browser/intent-resolver-FAFQ54NP.mjs.map +7 -0
- package/dist/lib/browser/markdown-RPYOUBVR.mjs +112 -0
- package/dist/lib/browser/markdown-RPYOUBVR.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-surface-Y4MUSICN.mjs +433 -0
- package/dist/lib/browser/react-surface-Y4MUSICN.mjs.map +7 -0
- package/dist/lib/browser/settings-WQTE5AEZ.mjs +22 -0
- package/dist/lib/browser/settings-WQTE5AEZ.mjs.map +7 -0
- package/dist/lib/browser/state-GNFUURIC.mjs +33 -0
- package/dist/lib/browser/state-GNFUURIC.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +6 -4
- package/dist/lib/node/{ThreadArticle-ZCNMFBAO.cjs → ThreadContainer-LTKKLPXX.cjs} +14 -13
- package/dist/lib/node/ThreadContainer-LTKKLPXX.cjs.map +7 -0
- package/dist/lib/node/chunk-AWSTZ2KN.cjs +93 -0
- package/dist/lib/node/chunk-AWSTZ2KN.cjs.map +7 -0
- package/dist/lib/node/{ThreadMain-5AYGCXXP.cjs → chunk-BHFHFTHO.cjs} +21 -23
- package/dist/lib/node/chunk-BHFHFTHO.cjs.map +7 -0
- package/dist/lib/node/{chunk-VW2P26MZ.cjs → chunk-CMEMMYDL.cjs} +11 -8
- package/dist/lib/node/chunk-CMEMMYDL.cjs.map +7 -0
- package/dist/lib/node/{chunk-IC2NICNC.cjs → chunk-F735VMTN.cjs} +7 -7
- package/dist/lib/node/chunk-F735VMTN.cjs.map +7 -0
- package/dist/lib/node/{meta.cjs → chunk-FPWNZ6TB.cjs} +13 -10
- package/dist/lib/node/chunk-FPWNZ6TB.cjs.map +7 -0
- package/dist/lib/node/{chunk-2CB5AVBL.cjs → chunk-RQR5Z23G.cjs} +74 -151
- package/dist/lib/node/chunk-RQR5Z23G.cjs.map +7 -0
- package/dist/lib/node/index.cjs +149 -935
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/intent-resolver-DVBEXJ33.cjs +299 -0
- package/dist/lib/node/intent-resolver-DVBEXJ33.cjs.map +7 -0
- package/dist/lib/node/markdown-ELRGISXE.cjs +122 -0
- package/dist/lib/node/markdown-ELRGISXE.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/react-surface-7HLTN5XS.cjs +435 -0
- package/dist/lib/node/react-surface-7HLTN5XS.cjs.map +7 -0
- package/dist/lib/node/settings-7VQYARM5.cjs +36 -0
- package/dist/lib/node/settings-7VQYARM5.cjs.map +7 -0
- package/dist/lib/node/state-TQWEZ6B3.cjs +49 -0
- package/dist/lib/node/state-TQWEZ6B3.cjs.map +7 -0
- package/dist/lib/node/types.cjs +6 -4
- package/dist/lib/node/types.cjs.map +2 -2
- package/dist/lib/node-esm/ThreadContainer-SV74JFRH.mjs +20 -0
- package/dist/lib/node-esm/ThreadContainer-SV74JFRH.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-RMYATBXM.mjs → chunk-33NDMQQQ.mjs} +5 -3
- package/dist/lib/node-esm/chunk-33NDMQQQ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-AQ74G3GY.mjs → chunk-CISLDOH7.mjs} +29 -105
- package/dist/lib/node-esm/chunk-CISLDOH7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-7QRGG25F.mjs → chunk-FXUATCLW.mjs} +3 -3
- package/dist/lib/node-esm/chunk-FXUATCLW.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HLWJTUWZ.mjs +73 -0
- package/dist/lib/node-esm/chunk-HLWJTUWZ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-PJPVEO7E.mjs +17 -0
- package/dist/lib/node-esm/chunk-PJPVEO7E.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ZJITX3TO.mjs +17 -0
- package/dist/lib/node-esm/chunk-ZJITX3TO.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +150 -942
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/intent-resolver-DHVLBNCC.mjs +288 -0
- package/dist/lib/node-esm/intent-resolver-DHVLBNCC.mjs.map +7 -0
- package/dist/lib/node-esm/markdown-23OB7EZG.mjs +113 -0
- package/dist/lib/node-esm/markdown-23OB7EZG.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/react-surface-AZHTTR6J.mjs +434 -0
- package/dist/lib/node-esm/react-surface-AZHTTR6J.mjs.map +7 -0
- package/dist/lib/node-esm/settings-SGMM7UDT.mjs +23 -0
- package/dist/lib/node-esm/settings-SGMM7UDT.mjs.map +7 -0
- package/dist/lib/node-esm/state-7MLR27YG.mjs +34 -0
- package/dist/lib/node-esm/state-7MLR27YG.mjs.map +7 -0
- package/dist/lib/node-esm/types.mjs +6 -4
- package/dist/types/src/ThreadPlugin.d.ts +1 -3
- package/dist/types/src/ThreadPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +15 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +10 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/markdown.d.ts +4 -0
- package/dist/types/src/capabilities/markdown.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +7 -0
- package/dist/types/src/capabilities/state.d.ts.map +1 -0
- package/dist/types/src/components/Chat.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatContainer.d.ts +2 -3
- package/dist/types/src/components/ChatContainer.d.ts.map +1 -1
- package/dist/types/src/components/CommentContainer.d.ts +1 -2
- package/dist/types/src/components/CommentContainer.d.ts.map +1 -1
- package/dist/types/src/components/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/components/CommentsContainer.d.ts +2 -8
- package/dist/types/src/components/CommentsContainer.d.ts.map +1 -1
- package/dist/types/src/components/MessageContainer.d.ts +1 -2
- package/dist/types/src/components/MessageContainer.d.ts.map +1 -1
- package/dist/types/src/components/ThreadComplementary.d.ts +2 -7
- package/dist/types/src/components/ThreadComplementary.d.ts.map +1 -1
- package/dist/types/src/components/ThreadContainer.d.ts +7 -0
- package/dist/types/src/components/ThreadContainer.d.ts.map +1 -0
- package/dist/types/src/components/ThreadSettings.d.ts +1 -2
- package/dist/types/src/components/ThreadSettings.d.ts.map +1 -1
- package/dist/types/src/components/command-extension.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +3 -15
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +12 -12
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/components/types.d.ts +5 -5
- package/dist/types/src/components/types.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +1 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -3
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +12 -18
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +31 -38
- package/src/ThreadPlugin.tsx +106 -475
- package/src/capabilities/capabilities.ts +19 -0
- package/src/capabilities/index.ts +13 -0
- package/src/capabilities/intent-resolver.ts +239 -0
- package/src/capabilities/markdown.ts +18 -0
- package/src/capabilities/react-surface.tsx +61 -0
- package/src/capabilities/settings.ts +14 -0
- package/src/capabilities/state.ts +25 -0
- package/src/components/Chat.stories.tsx +22 -24
- package/src/components/ChatContainer.tsx +2 -2
- package/src/components/CommentContainer.tsx +18 -32
- package/src/components/Comments.stories.tsx +8 -2
- package/src/components/CommentsContainer.tsx +1 -17
- package/src/components/MessageContainer.tsx +6 -19
- package/src/components/ThreadComplementary.tsx +118 -51
- package/src/components/ThreadContainer.tsx +22 -0
- package/src/components/ThreadSettings.tsx +5 -11
- package/src/components/command-extension.ts +2 -5
- package/src/components/index.ts +1 -2
- package/src/components/types.ts +5 -5
- package/src/index.ts +1 -5
- package/src/meta.ts +1 -1
- package/src/translations.ts +3 -1
- package/src/types.ts +6 -29
- package/dist/lib/browser/ThreadArticle-EWLTNU6Z.mjs +0 -18
- package/dist/lib/browser/ThreadArticle-EWLTNU6Z.mjs.map +0 -7
- package/dist/lib/browser/ThreadMain-ABEDFWHC.mjs +0 -26
- package/dist/lib/browser/ThreadMain-ABEDFWHC.mjs.map +0 -7
- package/dist/lib/browser/chunk-6KTMQPL4.mjs.map +0 -7
- package/dist/lib/browser/chunk-ENERBDYI.mjs.map +0 -7
- package/dist/lib/browser/chunk-OD2IZKRP.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -11
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/lib/node/ThreadArticle-ZCNMFBAO.cjs.map +0 -7
- package/dist/lib/node/ThreadMain-5AYGCXXP.cjs.map +0 -7
- package/dist/lib/node/chunk-2CB5AVBL.cjs.map +0 -7
- package/dist/lib/node/chunk-IC2NICNC.cjs.map +0 -7
- package/dist/lib/node/chunk-VW2P26MZ.cjs.map +0 -7
- package/dist/lib/node/meta.cjs.map +0 -7
- package/dist/lib/node-esm/ThreadArticle-F37HYTOU.mjs +0 -19
- package/dist/lib/node-esm/ThreadArticle-F37HYTOU.mjs.map +0 -7
- package/dist/lib/node-esm/ThreadMain-OL6ZHNZY.mjs +0 -27
- package/dist/lib/node-esm/ThreadMain-OL6ZHNZY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-7QRGG25F.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AQ74G3GY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RMYATBXM.mjs.map +0 -7
- package/dist/lib/node-esm/meta.mjs +0 -12
- package/dist/lib/node-esm/meta.mjs.map +0 -7
- package/dist/types/src/components/ThreadArticle.d.ts +0 -5
- package/dist/types/src/components/ThreadArticle.d.ts.map +0 -1
- package/dist/types/src/components/ThreadMain.d.ts +0 -7
- package/dist/types/src/components/ThreadMain.d.ts.map +0 -1
- package/src/components/ThreadArticle.tsx +0 -18
- package/src/components/ThreadMain.tsx +0 -27
|
@@ -26,45 +26,36 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
29
|
+
var chunk_RQR5Z23G_exports = {};
|
|
30
|
+
__export(chunk_RQR5Z23G_exports, {
|
|
31
31
|
ChatContainer: () => ChatContainer,
|
|
32
32
|
MessageContainer: () => MessageContainer,
|
|
33
33
|
command: () => command,
|
|
34
|
-
getMessageMetadata: () => getMessageMetadata
|
|
35
|
-
useAnalyticsCallback: () => useAnalyticsCallback,
|
|
36
|
-
useOnEditAnalytics: () => useOnEditAnalytics,
|
|
37
|
-
useStatus: () => useStatus
|
|
34
|
+
getMessageMetadata: () => getMessageMetadata
|
|
38
35
|
});
|
|
39
|
-
module.exports = __toCommonJS(
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var import_app_framework = require("@dxos/app-framework");
|
|
44
|
-
var import_types = require("@dxos/plugin-observability/types");
|
|
45
|
-
var import_echo = require("@dxos/react-client/echo");
|
|
46
|
-
var import_react_ui = require("@dxos/react-ui");
|
|
47
|
-
var import_react3 = __toESM(require("react"));
|
|
36
|
+
module.exports = __toCommonJS(chunk_RQR5Z23G_exports);
|
|
37
|
+
var import_chunk_AWSTZ2KN = require("./chunk-AWSTZ2KN.cjs");
|
|
38
|
+
var import_chunk_F735VMTN = require("./chunk-F735VMTN.cjs");
|
|
39
|
+
var import_react = __toESM(require("react"));
|
|
48
40
|
var import_echo_schema = require("@dxos/echo-schema");
|
|
49
41
|
var import_live_object = require("@dxos/live-object");
|
|
50
|
-
var
|
|
51
|
-
var
|
|
42
|
+
var import_types = require("@dxos/plugin-space/types");
|
|
43
|
+
var import_echo = require("@dxos/react-client/echo");
|
|
52
44
|
var import_halo = require("@dxos/react-client/halo");
|
|
53
|
-
var
|
|
45
|
+
var import_react_ui = require("@dxos/react-ui");
|
|
54
46
|
var import_react_ui_editor = require("@dxos/react-ui-editor");
|
|
55
47
|
var import_react_ui_stack = require("@dxos/react-ui-stack");
|
|
56
48
|
var import_react_ui_theme = require("@dxos/react-ui-theme");
|
|
57
49
|
var import_react_ui_thread = require("@dxos/react-ui-thread");
|
|
58
50
|
var import_view = require("@codemirror/view");
|
|
59
|
-
var
|
|
60
|
-
var
|
|
61
|
-
var
|
|
51
|
+
var import_react2 = require("@phosphor-icons/react");
|
|
52
|
+
var import_react3 = __toESM(require("react"));
|
|
53
|
+
var import_app_framework = require("@dxos/app-framework");
|
|
62
54
|
var import_live_object2 = require("@dxos/live-object");
|
|
63
55
|
var import_react_client = require("@dxos/react-client");
|
|
64
56
|
var import_halo2 = require("@dxos/react-client/halo");
|
|
65
|
-
var
|
|
57
|
+
var import_react_ui2 = require("@dxos/react-ui");
|
|
66
58
|
var import_react_ui_editor2 = require("@dxos/react-ui-editor");
|
|
67
|
-
var import_react_ui_mosaic = require("@dxos/react-ui-mosaic");
|
|
68
59
|
var import_react_ui_theme2 = require("@dxos/react-ui-theme");
|
|
69
60
|
var import_react_ui_thread2 = require("@dxos/react-ui-thread");
|
|
70
61
|
var import_language = require("@codemirror/language");
|
|
@@ -72,61 +63,6 @@ var import_react_ui_editor3 = require("@dxos/react-ui-editor");
|
|
|
72
63
|
var import_react_ui_theme3 = require("@dxos/react-ui-theme");
|
|
73
64
|
var import_display_name = require("@dxos/display-name");
|
|
74
65
|
var import_util = require("@dxos/util");
|
|
75
|
-
var useStatus = (space, channel) => {
|
|
76
|
-
const [processing, setProcessing] = (0, import_react.useState)(false);
|
|
77
|
-
(0, import_react.useEffect)(() => {
|
|
78
|
-
if (!space || !channel) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const unsubscribe = space.listen(`status/${channel}`, (status) => {
|
|
82
|
-
const { event } = status.payload ?? {};
|
|
83
|
-
setProcessing(event === "processing");
|
|
84
|
-
});
|
|
85
|
-
const t = setInterval(() => {
|
|
86
|
-
setProcessing((prev) => {
|
|
87
|
-
if (typeof prev?.ts === "number" && Date.now() - prev.ts > 3e4) {
|
|
88
|
-
return void 0;
|
|
89
|
-
} else {
|
|
90
|
-
return prev;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}, 1e3);
|
|
94
|
-
return () => {
|
|
95
|
-
unsubscribe();
|
|
96
|
-
clearInterval(t);
|
|
97
|
-
};
|
|
98
|
-
}, [
|
|
99
|
-
space,
|
|
100
|
-
channel
|
|
101
|
-
]);
|
|
102
|
-
return processing;
|
|
103
|
-
};
|
|
104
|
-
var useAnalyticsCallback = (spaceId, name, meta) => {
|
|
105
|
-
const { dispatchPromise: dispatch } = (0, import_app_framework.useIntentDispatcher)();
|
|
106
|
-
return (0, import_react2.useCallback)((dynamicMeta) => {
|
|
107
|
-
void dispatch((0, import_app_framework.createIntent)(import_types.ObservabilityAction.SendEvent, {
|
|
108
|
-
name,
|
|
109
|
-
properties: {
|
|
110
|
-
...meta,
|
|
111
|
-
...dynamicMeta,
|
|
112
|
-
spaceId
|
|
113
|
-
}
|
|
114
|
-
}));
|
|
115
|
-
}, [
|
|
116
|
-
dispatch,
|
|
117
|
-
name,
|
|
118
|
-
meta,
|
|
119
|
-
spaceId
|
|
120
|
-
]);
|
|
121
|
-
};
|
|
122
|
-
var useOnEditAnalytics = (message, editing) => {
|
|
123
|
-
const space = (0, import_echo.getSpace)(message);
|
|
124
|
-
const onEditAnalytics = useAnalyticsCallback(space?.id, "threads.comment-edited", {
|
|
125
|
-
messageId: message.id,
|
|
126
|
-
messageLength: message.text.length
|
|
127
|
-
});
|
|
128
|
-
(0, import_react_ui.useOnTransition)(editing, true, false, onEditAnalytics);
|
|
129
|
-
};
|
|
130
66
|
var parser = import_language.StreamLanguage.define({
|
|
131
67
|
startState: () => ({
|
|
132
68
|
count: 0
|
|
@@ -146,9 +82,7 @@ var parser = import_language.StreamLanguage.define({
|
|
|
146
82
|
var styles = import_language.HighlightStyle.define([
|
|
147
83
|
{
|
|
148
84
|
tag: import_react_ui_editor3.tags.tagName,
|
|
149
|
-
class: (0, import_react_ui_theme3.mx)(
|
|
150
|
-
palette: "cyan"
|
|
151
|
-
}), "text-baseText font-medium")
|
|
85
|
+
class: (0, import_react_ui_theme3.mx)("dx-tag dx-tag--indigo text-baseText font-medium")
|
|
152
86
|
}
|
|
153
87
|
]);
|
|
154
88
|
var command = [
|
|
@@ -175,80 +109,75 @@ var MessageContainer = ({ message, members, onDelete }) => {
|
|
|
175
109
|
const senderIdentity = members.find((member) => message.sender.identityKey && import_react_client.PublicKey.equals(member.identity.identityKey, message.sender.identityKey))?.identity;
|
|
176
110
|
const messageMetadata = getMessageMetadata(message.id, senderIdentity);
|
|
177
111
|
const userIsAuthor = (0, import_halo2.useIdentity)()?.identityKey.toHex() === messageMetadata.authorId;
|
|
178
|
-
const [editing, setEditing] = (0,
|
|
179
|
-
const handleDelete = (0,
|
|
112
|
+
const [editing, setEditing] = (0, import_react3.useState)(false);
|
|
113
|
+
const handleDelete = (0, import_react3.useCallback)(() => onDelete?.(message.id), [
|
|
180
114
|
message,
|
|
181
115
|
onDelete
|
|
182
116
|
]);
|
|
183
|
-
const { t } = (0,
|
|
117
|
+
const { t } = (0, import_react_ui2.useTranslation)(import_chunk_F735VMTN.THREAD_PLUGIN);
|
|
184
118
|
const editLabel = t(editing ? "save message label" : "edit message label");
|
|
185
119
|
const deleteLabel = t("delete message label");
|
|
186
|
-
return /* @__PURE__ */
|
|
120
|
+
return /* @__PURE__ */ import_react3.default.createElement(import_react_ui_thread2.MessageRoot, {
|
|
187
121
|
...messageMetadata,
|
|
188
122
|
classNames: [
|
|
189
123
|
import_react_ui_theme2.hoverableControls,
|
|
190
124
|
import_react_ui_theme2.hoverableFocusedWithinControls
|
|
191
125
|
]
|
|
192
|
-
}, /* @__PURE__ */
|
|
126
|
+
}, /* @__PURE__ */ import_react3.default.createElement(import_react_ui_thread2.MessageHeading, {
|
|
193
127
|
authorName: messageMetadata.authorName,
|
|
194
128
|
timestamp: messageMetadata.timestamp
|
|
195
|
-
}, /* @__PURE__ */
|
|
129
|
+
}, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.ButtonGroup, {
|
|
196
130
|
classNames: "mie-1"
|
|
197
|
-
}, userIsAuthor && /* @__PURE__ */
|
|
131
|
+
}, userIsAuthor && /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Root, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Trigger, {
|
|
198
132
|
asChild: true
|
|
199
|
-
}, /* @__PURE__ */
|
|
133
|
+
}, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Button, {
|
|
200
134
|
variant: "ghost",
|
|
201
135
|
"data-testid": editing ? "thread.message.save" : "thread.message.edit",
|
|
202
136
|
classNames: messageControlClassNames,
|
|
203
137
|
onClick: () => setEditing((editing2) => !editing2)
|
|
204
|
-
}, /* @__PURE__ */
|
|
138
|
+
}, /* @__PURE__ */ import_react3.default.createElement("span", {
|
|
205
139
|
className: "sr-only"
|
|
206
|
-
}, editLabel), editing ? /* @__PURE__ */
|
|
140
|
+
}, editLabel), editing ? /* @__PURE__ */ import_react3.default.createElement(import_react2.Check, {
|
|
207
141
|
className: (0, import_react_ui_theme2.getSize)(4)
|
|
208
|
-
}) : /* @__PURE__ */
|
|
142
|
+
}) : /* @__PURE__ */ import_react3.default.createElement(import_react2.PencilSimple, {
|
|
209
143
|
className: (0, import_react_ui_theme2.getSize)(4)
|
|
210
|
-
}))), /* @__PURE__ */
|
|
144
|
+
}))), /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Portal, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Content, null, editLabel, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Arrow, null)))), onDelete && /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Root, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Trigger, {
|
|
211
145
|
asChild: true
|
|
212
|
-
}, /* @__PURE__ */
|
|
146
|
+
}, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Button, {
|
|
213
147
|
variant: "ghost",
|
|
214
148
|
"data-testid": "thread.message.delete",
|
|
215
149
|
classNames: messageControlClassNames,
|
|
216
150
|
onClick: () => handleDelete()
|
|
217
|
-
}, /* @__PURE__ */
|
|
151
|
+
}, /* @__PURE__ */ import_react3.default.createElement("span", {
|
|
218
152
|
className: "sr-only"
|
|
219
|
-
}, deleteLabel), /* @__PURE__ */
|
|
153
|
+
}, deleteLabel), /* @__PURE__ */ import_react3.default.createElement(import_react2.X, {
|
|
220
154
|
className: (0, import_react_ui_theme2.getSize)(4)
|
|
221
|
-
}))), /* @__PURE__ */
|
|
155
|
+
}))), /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Portal, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Content, null, deleteLabel, /* @__PURE__ */ import_react3.default.createElement(import_react_ui2.Tooltip.Arrow, null)))))), /* @__PURE__ */ import_react3.default.createElement(TextboxBlock, {
|
|
222
156
|
message,
|
|
223
157
|
isAuthor: userIsAuthor,
|
|
224
158
|
editing
|
|
225
|
-
}), import_live_object2.RefArray.allResolvedTargets(message.parts ?? []).map((part, index) => /* @__PURE__ */
|
|
159
|
+
}), import_live_object2.RefArray.allResolvedTargets(message.parts ?? []).map((part, index) => /* @__PURE__ */ import_react3.default.createElement(MessagePart, {
|
|
226
160
|
key: index,
|
|
227
161
|
part
|
|
228
162
|
})));
|
|
229
163
|
};
|
|
230
164
|
var MessagePart = ({ part }) => {
|
|
231
|
-
return /* @__PURE__ */
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
type: import_chunk_IC2NICNC.THREAD_ITEM,
|
|
235
|
-
path: part.id,
|
|
236
|
-
item: part,
|
|
237
|
-
Component: MessageBlockObjectTile
|
|
238
|
-
}));
|
|
165
|
+
return /* @__PURE__ */ import_react3.default.createElement(MessageBlockObjectTile, {
|
|
166
|
+
subject: part
|
|
167
|
+
});
|
|
239
168
|
};
|
|
240
169
|
var TextboxBlock = ({ message, isAuthor, editing }) => {
|
|
241
|
-
const { themeMode } = (0,
|
|
242
|
-
const inMemoryContentRef = (0,
|
|
243
|
-
const handleDocumentChange = (0,
|
|
170
|
+
const { themeMode } = (0, import_react_ui2.useThemeContext)();
|
|
171
|
+
const inMemoryContentRef = (0, import_react3.useRef)(message.text);
|
|
172
|
+
const handleDocumentChange = (0, import_react3.useCallback)((newState) => {
|
|
244
173
|
inMemoryContentRef.current = newState;
|
|
245
174
|
}, []);
|
|
246
|
-
const saveDocumentChange = (0,
|
|
175
|
+
const saveDocumentChange = (0, import_react3.useCallback)(() => {
|
|
247
176
|
message.text = inMemoryContentRef.current;
|
|
248
177
|
}, [
|
|
249
178
|
message
|
|
250
179
|
]);
|
|
251
|
-
(0,
|
|
180
|
+
(0, import_react_ui2.useOnTransition)(editing, true, false, saveDocumentChange);
|
|
252
181
|
const { parentRef, focusAttributes, view } = (0, import_react_ui_editor2.useTextEditor)(() => ({
|
|
253
182
|
initialValue: message.text,
|
|
254
183
|
extensions: [
|
|
@@ -272,55 +201,52 @@ var TextboxBlock = ({ message, isAuthor, editing }) => {
|
|
|
272
201
|
themeMode,
|
|
273
202
|
handleDocumentChange
|
|
274
203
|
]);
|
|
275
|
-
(0,
|
|
204
|
+
(0, import_react3.useEffect)(() => {
|
|
276
205
|
editing && view?.focus();
|
|
277
206
|
}, [
|
|
278
207
|
editing,
|
|
279
208
|
view
|
|
280
209
|
]);
|
|
281
|
-
useOnEditAnalytics(message, !!editing);
|
|
282
|
-
return /* @__PURE__ */
|
|
210
|
+
(0, import_chunk_AWSTZ2KN.useOnEditAnalytics)(message, !!editing);
|
|
211
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", {
|
|
283
212
|
role: "none",
|
|
284
213
|
ref: parentRef,
|
|
285
214
|
className: "mie-4",
|
|
286
215
|
...focusAttributes
|
|
287
216
|
});
|
|
288
217
|
};
|
|
289
|
-
var MessageBlockObjectTile = /* @__PURE__ */ (0,
|
|
290
|
-
let title =
|
|
218
|
+
var MessageBlockObjectTile = /* @__PURE__ */ (0, import_react3.forwardRef)(({ subject }, forwardedRef) => {
|
|
219
|
+
let title = subject.name ?? subject.title ?? subject.type ?? "Object";
|
|
291
220
|
if (typeof title !== "string") {
|
|
292
221
|
title = title?.content ?? "";
|
|
293
222
|
}
|
|
294
|
-
return /* @__PURE__ */
|
|
223
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", {
|
|
295
224
|
role: "group",
|
|
296
225
|
className: (0, import_react_ui_theme2.mx)("grid col-span-3 py-1 pr-4", import_react_ui_theme2.hoverableControls, import_react_ui_theme2.hoverableFocusedWithinControls),
|
|
297
|
-
style: draggableStyle,
|
|
298
226
|
ref: forwardedRef
|
|
299
|
-
}, /* @__PURE__ */
|
|
227
|
+
}, /* @__PURE__ */ import_react3.default.createElement(import_app_framework.Surface, {
|
|
300
228
|
role: "card",
|
|
301
229
|
limit: 1,
|
|
302
230
|
data: {
|
|
303
|
-
subject
|
|
231
|
+
subject
|
|
304
232
|
},
|
|
305
|
-
|
|
306
|
-
fallback: title,
|
|
307
|
-
...props
|
|
233
|
+
fallback: title
|
|
308
234
|
}));
|
|
309
235
|
});
|
|
310
236
|
var ChatContainer = ({ thread, context, current, autoFocusTextbox }) => {
|
|
311
237
|
const identity = (0, import_halo.useIdentity)();
|
|
312
|
-
const space = (0,
|
|
313
|
-
const members = (0,
|
|
314
|
-
const activity = useStatus(space, (0,
|
|
315
|
-
const { t } = (0,
|
|
316
|
-
const [_count, _setCount] = (0,
|
|
238
|
+
const space = (0, import_echo.getSpace)(thread);
|
|
239
|
+
const members = (0, import_echo.useMembers)(space?.key);
|
|
240
|
+
const activity = (0, import_chunk_AWSTZ2KN.useStatus)(space, (0, import_echo.fullyQualifiedId)(thread));
|
|
241
|
+
const { t } = (0, import_react_ui.useTranslation)(import_chunk_F735VMTN.THREAD_PLUGIN);
|
|
242
|
+
const [_count, _setCount] = (0, import_react.useState)(0);
|
|
317
243
|
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
318
|
-
const [autoFocus, setAutoFocus] = (0,
|
|
319
|
-
const threadScrollRef = (0,
|
|
320
|
-
const { themeMode } = (0,
|
|
321
|
-
const textboxMetadata = getMessageMetadata((0,
|
|
322
|
-
const messageRef = (0,
|
|
323
|
-
const extensions = (0,
|
|
244
|
+
const [autoFocus, setAutoFocus] = (0, import_react.useState)(autoFocusTextbox);
|
|
245
|
+
const threadScrollRef = (0, import_react.useRef)(null);
|
|
246
|
+
const { themeMode } = (0, import_react_ui.useThemeContext)();
|
|
247
|
+
const textboxMetadata = getMessageMetadata((0, import_echo.fullyQualifiedId)(thread), identity);
|
|
248
|
+
const messageRef = (0, import_react.useRef)("");
|
|
249
|
+
const extensions = (0, import_react.useMemo)(() => [
|
|
324
250
|
(0, import_react_ui_editor.createBasicExtensions)({
|
|
325
251
|
placeholder: t("message placeholder")
|
|
326
252
|
}),
|
|
@@ -339,20 +265,20 @@ var ChatContainer = ({ thread, context, current, autoFocusTextbox }) => {
|
|
|
339
265
|
behavior,
|
|
340
266
|
block: "end"
|
|
341
267
|
}), 10);
|
|
342
|
-
(0,
|
|
268
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
343
269
|
scrollToEnd("instant");
|
|
344
270
|
}, []);
|
|
345
271
|
const handleCreate = () => {
|
|
346
272
|
if (!messageRef.current?.length) {
|
|
347
273
|
return false;
|
|
348
274
|
}
|
|
349
|
-
thread.messages.push((0, import_live_object.makeRef)((0, import_live_object.create)(
|
|
275
|
+
thread.messages.push((0, import_live_object.makeRef)((0, import_live_object.create)(import_types.MessageType, {
|
|
350
276
|
sender: {
|
|
351
277
|
identityKey: identity.identityKey.toHex()
|
|
352
278
|
},
|
|
353
279
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
354
280
|
text: messageRef.current,
|
|
355
|
-
context: (0, import_live_object.makeRef)(context)
|
|
281
|
+
context: context ? (0, import_live_object.makeRef)(context) : void 0
|
|
356
282
|
})));
|
|
357
283
|
messageRef.current = "";
|
|
358
284
|
setAutoFocus(true);
|
|
@@ -366,32 +292,32 @@ var ChatContainer = ({ thread, context, current, autoFocusTextbox }) => {
|
|
|
366
292
|
thread.messages.splice(messageIndex, 1);
|
|
367
293
|
}
|
|
368
294
|
};
|
|
369
|
-
return /* @__PURE__ */
|
|
295
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react_ui_thread.Thread, {
|
|
370
296
|
current,
|
|
371
|
-
id: (0,
|
|
297
|
+
id: (0, import_echo.fullyQualifiedId)(thread),
|
|
372
298
|
classNames: "bs-full grid-rows-[1fr_min-content_min-content] overflow-hidden transition-[padding-block-end] [[data-sidebar-inline-start-state=open]_&]:lg:pbe-0"
|
|
373
|
-
}, /* @__PURE__ */
|
|
299
|
+
}, /* @__PURE__ */ import_react.default.createElement(import_react_ui.ScrollArea.Root, {
|
|
374
300
|
classNames: "col-span-2"
|
|
375
|
-
}, /* @__PURE__ */
|
|
301
|
+
}, /* @__PURE__ */ import_react.default.createElement(import_react_ui.ScrollArea.Viewport, {
|
|
376
302
|
classNames: "overflow-anchored after:overflow-anchor after:block after:bs-px after:-mbs-px [&>div]:min-bs-full [&>div]:!grid [&>div]:grid-rows-[1fr_0]"
|
|
377
|
-
}, /* @__PURE__ */
|
|
303
|
+
}, /* @__PURE__ */ import_react.default.createElement("div", {
|
|
378
304
|
role: "none",
|
|
379
305
|
className: (0, import_react_ui_theme.mx)(import_react_ui_thread.threadLayout, "place-self-end")
|
|
380
|
-
}, import_live_object.RefArray.allResolvedTargets(thread.messages ?? []).map((message) => /* @__PURE__ */
|
|
306
|
+
}, import_live_object.RefArray.allResolvedTargets(thread.messages ?? []).map((message) => /* @__PURE__ */ import_react.default.createElement(MessageContainer, {
|
|
381
307
|
key: message.id,
|
|
382
308
|
message,
|
|
383
309
|
members,
|
|
384
310
|
onDelete: handleDelete
|
|
385
|
-
}))), /* @__PURE__ */
|
|
311
|
+
}))), /* @__PURE__ */ import_react.default.createElement("div", {
|
|
386
312
|
role: "none",
|
|
387
313
|
className: "bs-px -mbs-px",
|
|
388
314
|
ref: threadScrollRef
|
|
389
|
-
}), /* @__PURE__ */
|
|
315
|
+
}), /* @__PURE__ */ import_react.default.createElement(import_react_ui.ScrollArea.Scrollbar, null, /* @__PURE__ */ import_react.default.createElement(import_react_ui.ScrollArea.Thumb, null)))), /* @__PURE__ */ import_react.default.createElement(import_react_ui_thread.MessageTextbox, {
|
|
390
316
|
extensions,
|
|
391
317
|
autoFocus,
|
|
392
318
|
onSend: handleCreate,
|
|
393
319
|
...textboxMetadata
|
|
394
|
-
}), /* @__PURE__ */
|
|
320
|
+
}), /* @__PURE__ */ import_react.default.createElement(import_react_ui_thread.ThreadFooter, {
|
|
395
321
|
activity
|
|
396
322
|
}, t("activity message")));
|
|
397
323
|
};
|
|
@@ -400,9 +326,6 @@ var ChatContainer = ({ thread, context, current, autoFocusTextbox }) => {
|
|
|
400
326
|
ChatContainer,
|
|
401
327
|
MessageContainer,
|
|
402
328
|
command,
|
|
403
|
-
getMessageMetadata
|
|
404
|
-
useAnalyticsCallback,
|
|
405
|
-
useOnEditAnalytics,
|
|
406
|
-
useStatus
|
|
329
|
+
getMessageMetadata
|
|
407
330
|
});
|
|
408
|
-
//# sourceMappingURL=chunk-
|
|
331
|
+
//# sourceMappingURL=chunk-RQR5Z23G.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/ChatContainer.tsx", "../../../src/components/MessageContainer.tsx", "../../../src/components/command-extension.ts", "../../../src/util.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport { Ref } from '@dxos/echo-schema';\nimport { create, makeRef, RefArray } from '@dxos/live-object';\nimport { MessageType } from '@dxos/plugin-space/types';\nimport { fullyQualifiedId, getSpace, useMembers } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport { Icon, ScrollArea, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, listener } from '@dxos/react-ui-editor';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { mx } from '@dxos/react-ui-theme';\nimport { MessageTextbox, type MessageTextboxProps, Thread, ThreadFooter, threadLayout } from '@dxos/react-ui-thread';\n\nimport { MessageContainer } from './MessageContainer';\nimport { command } from './command-extension';\nimport { type ThreadContainerProps } from './types';\nimport { useStatus } from '../hooks';\nimport { THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\nexport const ChatHeading = ({ attendableId }: { attendableId?: string }) => {\n const { t } = useTranslation(THREAD_PLUGIN);\n return (\n <div role='none' className='flex items-center'>\n <StackItem.SigilButton attendableId={attendableId}>\n <Icon icon='ph--chat--regular' size={5} />\n </StackItem.SigilButton>\n <StackItem.HeadingLabel attendableId={attendableId}>{t('chat heading')}</StackItem.HeadingLabel>\n </div>\n );\n};\n\nexport const ChatContainer = ({ thread, context, current, autoFocusTextbox }: ThreadContainerProps) => {\n const identity = useIdentity()!;\n const space = getSpace(thread);\n const members = useMembers(space?.key);\n const activity = useStatus(space, fullyQualifiedId(thread));\n const { t } = useTranslation(THREAD_PLUGIN);\n // TODO(wittjosiah): This is a hack to reset the editor after a message is sent.\n const [_count, _setCount] = useState(0);\n const rerenderEditor = () => _setCount((count) => count + 1);\n const [autoFocus, setAutoFocus] = useState(autoFocusTextbox);\n const threadScrollRef = useRef<HTMLDivElement | null>(null);\n const { themeMode } = useThemeContext();\n\n const textboxMetadata = getMessageMetadata(fullyQualifiedId(thread), identity);\n const messageRef = useRef('');\n const extensions = useMemo(\n () => [\n createBasicExtensions({ placeholder: t('message placeholder') }),\n createThemeExtensions({ themeMode }),\n listener({ onChange: (text) => (messageRef.current = text) }),\n command,\n ],\n [themeMode, _count],\n );\n\n // TODO(thure): Factor out.\n // TODO(thure): `flex-col-reverse` does not work to start the container scrolled to the end while also using\n // `ScrollArea`. This is the least-bad way I found to scroll to the end on mount. Note that 0ms was insufficient\n // for the desired effect; this is likely hardware-dependent and should be reevaluated.\n const scrollToEnd = (behavior: ScrollBehavior) =>\n setTimeout(() => threadScrollRef.current?.scrollIntoView({ behavior, block: 'end' }), 10);\n\n useLayoutEffect(() => {\n scrollToEnd('instant');\n }, []);\n\n // TODO(burdon): Change to model.\n const handleCreate: MessageTextboxProps['onSend'] = () => {\n if (!messageRef.current?.length) {\n return false;\n }\n\n thread.messages.push(\n makeRef(\n create(MessageType, {\n sender: { identityKey: identity.identityKey.toHex() },\n timestamp: new Date().toISOString(),\n text: messageRef.current,\n context: context ? makeRef(context) : undefined,\n }),\n ),\n );\n\n messageRef.current = '';\n setAutoFocus(true);\n scrollToEnd('smooth');\n rerenderEditor();\n return true;\n };\n\n const handleDelete = (id: string) => {\n const messageIndex = thread.messages.findIndex(Ref.hasObjectId(id));\n if (messageIndex !== -1) {\n thread.messages.splice(messageIndex, 1);\n }\n };\n\n return (\n <Thread\n current={current}\n id={fullyQualifiedId(thread)}\n classNames='bs-full grid-rows-[1fr_min-content_min-content] overflow-hidden transition-[padding-block-end] [[data-sidebar-inline-start-state=open]_&]:lg:pbe-0'\n >\n <ScrollArea.Root classNames='col-span-2'>\n <ScrollArea.Viewport classNames='overflow-anchored after:overflow-anchor after:block after:bs-px after:-mbs-px [&>div]:min-bs-full [&>div]:!grid [&>div]:grid-rows-[1fr_0]'>\n <div role='none' className={mx(threadLayout, 'place-self-end')}>\n {RefArray.allResolvedTargets(thread.messages ?? []).map((message) => (\n <MessageContainer key={message.id} message={message} members={members} onDelete={handleDelete} />\n ))}\n </div>\n {/* NOTE(thure): This can’t also be the `overflow-anchor` because `ScrollArea` injects an interceding node that contains this necessary ref’d element. */}\n <div role='none' className='bs-px -mbs-px' ref={threadScrollRef} />\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n <MessageTextbox extensions={extensions} autoFocus={autoFocus} onSend={handleCreate} {...textboxMetadata} />\n <ThreadFooter activity={activity}>{t('activity message')}</ThreadFooter>\n </Thread>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport { Check, PencilSimple, X } from '@phosphor-icons/react';\nimport React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';\n\nimport { Surface } from '@dxos/app-framework';\nimport { RefArray } from '@dxos/live-object';\nimport { type MessageType } from '@dxos/plugin-space/types';\nimport { PublicKey } from '@dxos/react-client';\nimport { type ReactiveEchoObject, type Expando, type SpaceMember } from '@dxos/react-client/echo';\nimport { useIdentity, type Identity } from '@dxos/react-client/halo';\nimport { Button, ButtonGroup, Tooltip, useOnTransition, useThemeContext, useTranslation } from '@dxos/react-ui';\nimport { createBasicExtensions, createThemeExtensions, useTextEditor } from '@dxos/react-ui-editor';\nimport {\n getSize,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { MessageHeading, MessageRoot } from '@dxos/react-ui-thread';\n\nimport { command } from './command-extension';\nimport { useOnEditAnalytics } from '../hooks';\nimport { THREAD_PLUGIN } from '../meta';\nimport { getMessageMetadata } from '../util';\n\n// TODO(thure): #8149\nconst messageControlClassNames = ['!p-1 !min-bs-0 transition-opacity', hoverableControlItem];\n\nexport const MessageContainer = ({\n message,\n members,\n onDelete,\n}: {\n message: MessageType;\n members: SpaceMember[];\n onDelete?: (id: string) => void;\n}) => {\n const senderIdentity = members.find(\n (member) => message.sender.identityKey && PublicKey.equals(member.identity.identityKey, message.sender.identityKey),\n )?.identity;\n const messageMetadata = getMessageMetadata(message.id, senderIdentity);\n const userIsAuthor = useIdentity()?.identityKey.toHex() === messageMetadata.authorId;\n const [editing, setEditing] = useState(false);\n const handleDelete = useCallback(() => onDelete?.(message.id), [message, onDelete]);\n const { t } = useTranslation(THREAD_PLUGIN);\n const editLabel = t(editing ? 'save message label' : 'edit message label');\n const deleteLabel = t('delete message label');\n\n return (\n <MessageRoot {...messageMetadata} classNames={[hoverableControls, hoverableFocusedWithinControls]}>\n <MessageHeading authorName={messageMetadata.authorName} timestamp={messageMetadata.timestamp}>\n <ButtonGroup classNames='mie-1'>\n {userIsAuthor && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}\n classNames={messageControlClassNames}\n onClick={() => setEditing((editing) => !editing)}\n >\n <span className='sr-only'>{editLabel}</span>\n {editing ? <Check className={getSize(4)} /> : <PencilSimple className={getSize(4)} />}\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content>\n {editLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n {onDelete && (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>\n <Button\n variant='ghost'\n data-testid='thread.message.delete'\n classNames={messageControlClassNames}\n onClick={() => handleDelete()}\n >\n <span className='sr-only'>{deleteLabel}</span>\n <X className={getSize(4)} />\n </Button>\n </Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content>\n {deleteLabel}\n <Tooltip.Arrow />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n )}\n </ButtonGroup>\n </MessageHeading>\n <TextboxBlock message={message} isAuthor={userIsAuthor} editing={editing} />\n {RefArray.allResolvedTargets(message.parts ?? []).map((part, index) => (\n <MessagePart key={index} part={part} />\n ))}\n </MessageRoot>\n );\n};\n\nconst MessagePart = ({ part }: { part: Expando }) => {\n return <MessageBlockObjectTile subject={part} />;\n};\n\nconst TextboxBlock = ({\n message,\n isAuthor,\n editing,\n}: {\n message: MessageType;\n editing?: boolean;\n isAuthor?: boolean;\n identity?: Identity;\n}) => {\n const { themeMode } = useThemeContext();\n const inMemoryContentRef = useRef(message.text);\n\n const handleDocumentChange = useCallback((newState: string) => {\n inMemoryContentRef.current = newState;\n }, []);\n\n const saveDocumentChange = useCallback(() => {\n message.text = inMemoryContentRef.current;\n }, [message]);\n\n useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: message.text,\n extensions: [\n createBasicExtensions({ readonly: !isAuthor || !editing }),\n createThemeExtensions({ themeMode }),\n command,\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n handleDocumentChange(update.state.doc.toString());\n }\n }),\n ],\n }),\n [message.text, editing, isAuthor, themeMode, handleDocumentChange],\n );\n\n useEffect(() => {\n editing && view?.focus();\n }, [editing, view]);\n\n useOnEditAnalytics(message, !!editing);\n\n return <div role='none' ref={parentRef} className='mie-4' {...focusAttributes} />;\n};\n\nconst MessageBlockObjectTile = forwardRef<HTMLDivElement, { subject: ReactiveEchoObject<any> }>(\n ({ subject }, forwardedRef) => {\n let title = subject.name ?? subject.title ?? subject.type ?? 'Object';\n if (typeof title !== 'string') {\n title = title?.content ?? '';\n }\n\n return (\n <div\n role='group'\n className={mx('grid col-span-3 py-1 pr-4', hoverableControls, hoverableFocusedWithinControls)}\n ref={forwardedRef}\n >\n <Surface role='card' limit={1} data={{ subject }} fallback={title} />\n </div>\n );\n },\n);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { type Extension } from '@codemirror/state';\n\nimport { tags } from '@dxos/react-ui-editor';\nimport { mx } from '@dxos/react-ui-theme';\n\n/**\n * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts\n */\nconst parser = StreamLanguage.define<{ count: number }>({\n startState: () => ({ count: 0 }),\n token: (stream, state) => {\n state.count++;\n if (stream.eatSpace()) {\n return null;\n }\n if (state.count === 1 && stream.match(/^(\\/\\w+)/)) {\n return 'tagName';\n }\n stream.next();\n return null;\n },\n});\n\nconst styles = HighlightStyle.define([\n { tag: tags.tagName, class: mx('dx-tag dx-tag--indigo text-baseText font-medium') },\n]);\n\nexport const command: Extension = [parser, syntaxHighlighting(styles)];\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { generateName } from '@dxos/display-name';\nimport { type PublicKey } from '@dxos/react-client';\nimport { type Identity } from '@dxos/react-client/halo';\nimport { type MessageMetadata } from '@dxos/react-ui-thread';\nimport { hexToFallback } from '@dxos/util';\n\nexport type MessagePropertiesProvider = (identityKey: PublicKey | undefined) => MessageMetadata;\n\nexport const getMessageMetadata = (id: string, identity?: Identity): MessageMetadata => {\n const fallback = hexToFallback(identity?.identityKey.toHex() ?? '0');\n return {\n id,\n authorId: identity?.identityKey.toHex(),\n authorName:\n identity?.profile?.displayName ??\n (identity?.identityKey ? generateName(identity.identityKey.toHex()) : undefined),\n authorAvatarProps: {\n hue: identity?.profile?.data?.hue ?? fallback.hue,\n emoji: identity?.profile?.data?.emoji ?? fallback.emoji,\n },\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_react", "import_live_object", "import_halo", "import_react_ui", "import_react_ui_editor", "import_react_ui_theme", "import_react_ui_thread", "parser", "StreamLanguage", "define", "startState", "count", "token", "stream", "state", "eatSpace", "match", "next", "styles", "HighlightStyle", "tag", "tags", "tagName", "class", "mx", "command", "syntaxHighlighting", "getMessageMetadata", "id", "identity", "fallback", "hexToFallback", "identityKey", "toHex", "authorId", "authorName", "profile", "displayName", "generateName", "undefined", "authorAvatarProps", "hue", "data", "emoji", "messageControlClassNames", "hoverableControlItem", "MessageContainer", "message", "members", "onDelete", "senderIdentity", "find", "member", "sender", "PublicKey", "equals", "messageMetadata", "userIsAuthor", "useIdentity", "editing", "setEditing", "useState", "handleDelete", "useCallback", "t", "useTranslation", "THREAD_PLUGIN", "editLabel", "deleteLabel", "React", "MessageRoot", "classNames", "hoverableControls", "hoverableFocusedWithinControls", "MessageHeading", "timestamp", "ButtonGroup", "Tooltip", "Root", "Trigger", "asChild", "Button", "variant", "data-testid", "onClick", "span", "className", "Check", "getSize", "PencilSimple", "Portal", "Content", "Arrow", "X", "TextboxBlock", "isAuthor", "RefArray", "allResolvedTargets", "parts", "map", "part", "index", "MessagePart", "key", "MessageBlockObjectTile", "subject", "themeMode", "useThemeContext", "inMemoryContentRef", "useRef", "text", "handleDocumentChange", "newState", "current", "saveDocumentChange", "useOnTransition", "parentRef", "focusAttributes", "view", "useTextEditor", "initialValue", "extensions", "createBasicExtensions", "readonly", "createThemeExtensions", "EditorView", "updateListener", "of", "update", "docChanged", "doc", "toString", "useEffect", "focus", "useOnEditAnalytics", "div", "role", "ref", "forwardRef", "forwardedRef", "title", "name", "type", "content", "Surface", "limit", "ChatContainer", "thread", "context", "autoFocusTextbox", "space", "getSpace", "useMembers", "activity", "useStatus", "fullyQualifiedId", "_count", "_setCount", "rerenderEditor", "autoFocus", "setAutoFocus", "threadScrollRef", "textboxMetadata", "messageRef", "useMemo", "placeholder", "listener", "onChange", "scrollToEnd", "behavior", "setTimeout", "scrollIntoView", "block", "useLayoutEffect", "handleCreate", "length", "messages", "push", "makeRef", "create", "MessageType", "Date", "toISOString", "messageIndex", "findIndex", "Ref", "hasObjectId", "splice", "Thread", "ScrollArea", "Viewport", "threadLayout", "Scrollbar", "Thumb", "MessageTextbox", "onSend", "ThreadFooter"]
|
|
7
|
+
}
|