@liveblocks/react-ui 2.7.0-beta1 → 2.7.0-versions
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/_private/README.md +5 -0
- package/_private/package.json +4 -0
- package/dist/_private/index.d.mts +72 -0
- package/dist/_private/index.d.ts +72 -0
- package/dist/_private/index.js +46 -0
- package/dist/_private/index.js.map +1 -0
- package/dist/_private/index.mjs +21 -0
- package/dist/_private/index.mjs.map +1 -0
- package/dist/components/Comment.js +7 -65
- package/dist/components/Comment.js.map +1 -1
- package/dist/components/Comment.mjs +9 -66
- package/dist/components/Comment.mjs.map +1 -1
- package/dist/components/Composer.js +101 -217
- package/dist/components/Composer.js.map +1 -1
- package/dist/components/Composer.mjs +104 -220
- package/dist/components/Composer.mjs.map +1 -1
- package/dist/components/HistoryVersionSummary.js +42 -0
- package/dist/components/HistoryVersionSummary.js.map +1 -0
- package/dist/components/HistoryVersionSummary.mjs +40 -0
- package/dist/components/HistoryVersionSummary.mjs.map +1 -0
- package/dist/components/HistoryVersionSummaryList.js +22 -0
- package/dist/components/HistoryVersionSummaryList.js.map +1 -0
- package/dist/components/HistoryVersionSummaryList.mjs +20 -0
- package/dist/components/HistoryVersionSummaryList.mjs.map +1 -0
- package/dist/components/InboxNotification.js +10 -25
- package/dist/components/InboxNotification.js.map +1 -1
- package/dist/components/InboxNotification.mjs +10 -25
- package/dist/components/InboxNotification.mjs.map +1 -1
- package/dist/components/Thread.js +0 -2
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/Thread.mjs +0 -2
- package/dist/components/Thread.mjs.map +1 -1
- package/dist/components/internal/Button.js +8 -1
- package/dist/components/internal/Button.js.map +1 -1
- package/dist/components/internal/Button.mjs +8 -1
- package/dist/components/internal/Button.mjs.map +1 -1
- package/dist/components/internal/EmojiPicker.js +3 -3
- package/dist/components/internal/EmojiPicker.js.map +1 -1
- package/dist/components/internal/EmojiPicker.mjs +3 -3
- package/dist/components/internal/EmojiPicker.mjs.map +1 -1
- package/dist/components/internal/InboxNotificationThread.js +2 -10
- package/dist/components/internal/InboxNotificationThread.js.map +1 -1
- package/dist/components/internal/InboxNotificationThread.mjs +3 -11
- package/dist/components/internal/InboxNotificationThread.mjs.map +1 -1
- package/dist/components/internal/User.js +3 -19
- package/dist/components/internal/User.js.map +1 -1
- package/dist/components/internal/User.mjs +3 -19
- package/dist/components/internal/User.mjs.map +1 -1
- package/dist/icons/ArrowUp.js +15 -0
- package/dist/icons/ArrowUp.js.map +1 -0
- package/dist/icons/ArrowUp.mjs +13 -0
- package/dist/icons/ArrowUp.mjs.map +1 -0
- package/dist/icons/{Warning.js → Missing.js} +3 -3
- package/dist/icons/{Warning.js.map → Missing.js.map} +1 -1
- package/dist/icons/{Warning.mjs → Missing.mjs} +3 -3
- package/dist/icons/{Warning.mjs.map → Missing.mjs.map} +1 -1
- package/dist/icons/Restore.js +17 -0
- package/dist/icons/Restore.js.map +1 -0
- package/dist/icons/Restore.mjs +15 -0
- package/dist/icons/Restore.mjs.map +1 -0
- package/dist/icons/Spinner.js +9 -3
- package/dist/icons/Spinner.js.map +1 -1
- package/dist/icons/Spinner.mjs +10 -4
- package/dist/icons/Spinner.mjs.map +1 -1
- package/dist/index.d.mts +74 -70
- package/dist/index.d.ts +74 -70
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/dist/overrides.js +5 -6
- package/dist/overrides.js.map +1 -1
- package/dist/overrides.mjs +5 -6
- package/dist/overrides.mjs.map +1 -1
- package/dist/primitives/Composer/contexts.js +3 -17
- package/dist/primitives/Composer/contexts.js.map +1 -1
- package/dist/primitives/Composer/contexts.mjs +4 -15
- package/dist/primitives/Composer/contexts.mjs.map +1 -1
- package/dist/primitives/Composer/index.js +26 -185
- package/dist/primitives/Composer/index.js.map +1 -1
- package/dist/primitives/Composer/index.mjs +31 -188
- package/dist/primitives/Composer/index.mjs.map +1 -1
- package/dist/primitives/Composer/utils.js +0 -224
- package/dist/primitives/Composer/utils.js.map +1 -1
- package/dist/primitives/Composer/utils.mjs +1 -222
- package/dist/primitives/Composer/utils.mjs.map +1 -1
- package/dist/primitives/EmojiPicker/utils.js +2 -2
- package/dist/primitives/EmojiPicker/utils.js.map +1 -1
- package/dist/primitives/EmojiPicker/utils.mjs +1 -1
- package/dist/primitives/EmojiPicker/utils.mjs.map +1 -1
- package/dist/primitives/index.d.mts +3 -83
- package/dist/primitives/index.d.ts +3 -83
- package/dist/primitives/index.js +0 -4
- package/dist/primitives/index.js.map +1 -1
- package/dist/primitives/index.mjs +0 -2
- package/dist/primitives/index.mjs.map +1 -1
- package/dist/utils/chunk.js +12 -0
- package/dist/utils/chunk.js.map +1 -0
- package/dist/utils/chunk.mjs +10 -0
- package/dist/utils/chunk.mjs.map +1 -0
- package/dist/utils/intl.js +0 -6
- package/dist/utils/intl.js.map +1 -1
- package/dist/utils/intl.mjs +1 -6
- package/dist/utils/intl.mjs.map +1 -1
- package/dist/utils/use-initial.js +1 -2
- package/dist/utils/use-initial.js.map +1 -1
- package/dist/utils/use-initial.mjs +2 -3
- package/dist/utils/use-initial.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/package.json +16 -4
- package/src/styles/dark/index.css +0 -1
- package/src/styles/index.css +219 -325
- package/src/styles/utils.css +6 -44
- package/styles/dark/attributes.css +1 -1
- package/styles/dark/attributes.css.map +1 -1
- package/styles/dark/media-query.css +1 -1
- package/styles/dark/media-query.css.map +1 -1
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/components/internal/Attachment.js +0 -226
- package/dist/components/internal/Attachment.js.map +0 -1
- package/dist/components/internal/Attachment.mjs +0 -224
- package/dist/components/internal/Attachment.mjs.map +0 -1
- package/dist/icons/Attachment.js +0 -15
- package/dist/icons/Attachment.js.map +0 -1
- package/dist/icons/Attachment.mjs +0 -13
- package/dist/icons/Attachment.mjs.map +0 -1
- package/dist/primitives/FileSize.js +0 -33
- package/dist/primitives/FileSize.js.map +0 -1
- package/dist/primitives/FileSize.mjs +0 -31
- package/dist/primitives/FileSize.mjs.map +0 -1
- package/dist/utils/download.js +0 -14
- package/dist/utils/download.js.map +0 -1
- package/dist/utils/download.mjs +0 -12
- package/dist/utils/download.mjs.map +0 -1
- package/dist/utils/format-file-size.js +0 -45
- package/dist/utils/format-file-size.js.map +0 -1
- package/dist/utils/format-file-size.mjs +0 -43
- package/dist/utils/format-file-size.mjs.map +0 -1
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { kInternal } from '@liveblocks/core';
|
|
3
|
-
import { useClient, useCreateThread, useCreateComment, useEditComment } from '@liveblocks/react';
|
|
4
|
-
import React__default, { forwardRef,
|
|
5
|
-
import { AttachmentIcon } from '../icons/Attachment.mjs';
|
|
3
|
+
import { useClient, useSelf, useCreateThread, useCreateComment, useEditComment } from '@liveblocks/react';
|
|
4
|
+
import React__default, { forwardRef, useMemo, useState, useCallback } from 'react';
|
|
6
5
|
import { EmojiIcon } from '../icons/Emoji.mjs';
|
|
7
6
|
import { MentionIcon } from '../icons/Mention.mjs';
|
|
8
7
|
import { SendIcon } from '../icons/Send.mjs';
|
|
9
8
|
import { useOverrides } from '../overrides.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { Editor as ComposerEditor, Submit as ComposerSubmit, Form as ComposerForm, Mention as ComposerMention$1, Suggestions as ComposerSuggestions, SuggestionsList as ComposerSuggestionsList, SuggestionsListItem as ComposerSuggestionsListItem, Link as ComposerLink$1 } from '../primitives/Composer/index.mjs';
|
|
11
10
|
import { useComposer } from '../primitives/Composer/contexts.mjs';
|
|
12
|
-
import { useComposerAttachmentsDropArea } from '../primitives/Composer/utils.mjs';
|
|
13
11
|
import { MENTION_CHARACTER } from '../slate/plugins/mentions.mjs';
|
|
14
12
|
import { classNames } from '../utils/class-names.mjs';
|
|
15
13
|
import { useControllableState } from '../utils/use-controllable-state.mjs';
|
|
16
|
-
import { useLayoutEffect } from '../utils/use-layout-effect.mjs';
|
|
17
|
-
import { FileAttachment } from './internal/Attachment.mjs';
|
|
18
14
|
import { Attribution } from './internal/Attribution.mjs';
|
|
19
15
|
import { Avatar } from './internal/Avatar.mjs';
|
|
20
16
|
import { Button } from './internal/Button.mjs';
|
|
@@ -86,31 +82,6 @@ function ComposerInsertEmojiEditorAction({
|
|
|
86
82
|
className: "lb-button-icon"
|
|
87
83
|
})))));
|
|
88
84
|
}
|
|
89
|
-
function ComposerAttachFilesEditorAction({
|
|
90
|
-
label,
|
|
91
|
-
className,
|
|
92
|
-
...props
|
|
93
|
-
}) {
|
|
94
|
-
const preventDefault = useCallback((event) => {
|
|
95
|
-
event.preventDefault();
|
|
96
|
-
}, []);
|
|
97
|
-
const stopPropagation = useCallback((event) => {
|
|
98
|
-
event.stopPropagation();
|
|
99
|
-
}, []);
|
|
100
|
-
return /* @__PURE__ */ React__default.createElement(Tooltip, {
|
|
101
|
-
content: label
|
|
102
|
-
}, /* @__PURE__ */ React__default.createElement(ComposerAttachFiles, {
|
|
103
|
-
asChild: true
|
|
104
|
-
}, /* @__PURE__ */ React__default.createElement(Button, {
|
|
105
|
-
className: classNames("lb-composer-editor-action", className),
|
|
106
|
-
onMouseDown: preventDefault,
|
|
107
|
-
onClick: stopPropagation,
|
|
108
|
-
"aria-label": label,
|
|
109
|
-
...props
|
|
110
|
-
}, /* @__PURE__ */ React__default.createElement(AttachmentIcon, {
|
|
111
|
-
className: "lb-button-icon"
|
|
112
|
-
}))));
|
|
113
|
-
}
|
|
114
85
|
function ComposerMention({ userId }) {
|
|
115
86
|
return /* @__PURE__ */ React__default.createElement(ComposerMention$1, {
|
|
116
87
|
className: "lb-composer-mention"
|
|
@@ -143,184 +114,68 @@ function ComposerLink({ href, children }) {
|
|
|
143
114
|
className: "lb-composer-link"
|
|
144
115
|
}, children);
|
|
145
116
|
}
|
|
146
|
-
function ComposerFileAttachment({
|
|
147
|
-
attachment,
|
|
148
|
-
className,
|
|
149
|
-
overrides,
|
|
150
|
-
...props
|
|
151
|
-
}) {
|
|
152
|
-
const { removeAttachment } = useComposer();
|
|
153
|
-
const handleDeleteClick = useCallback(() => {
|
|
154
|
-
removeAttachment(attachment.id);
|
|
155
|
-
}, [attachment.id, removeAttachment]);
|
|
156
|
-
return /* @__PURE__ */ React__default.createElement(FileAttachment, {
|
|
157
|
-
className: classNames("lb-composer-attachment", className),
|
|
158
|
-
...props,
|
|
159
|
-
attachment,
|
|
160
|
-
onDeleteClick: handleDeleteClick,
|
|
161
|
-
preventFocusOnDelete: true,
|
|
162
|
-
overrides
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
function ComposerAttachments({
|
|
166
|
-
overrides,
|
|
167
|
-
className,
|
|
168
|
-
...props
|
|
169
|
-
}) {
|
|
170
|
-
const { attachments } = useComposer();
|
|
171
|
-
if (attachments.length === 0) {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
return /* @__PURE__ */ React__default.createElement("div", {
|
|
175
|
-
className: classNames("lb-composer-attachments", className),
|
|
176
|
-
...props
|
|
177
|
-
}, attachments.map((attachment) => {
|
|
178
|
-
return /* @__PURE__ */ React__default.createElement(ComposerFileAttachment, {
|
|
179
|
-
key: attachment.id,
|
|
180
|
-
attachment,
|
|
181
|
-
overrides
|
|
182
|
-
});
|
|
183
|
-
}));
|
|
184
|
-
}
|
|
185
117
|
const editorComponents = {
|
|
186
118
|
Mention: ComposerMention,
|
|
187
119
|
MentionSuggestions: ComposerMentionSuggestions,
|
|
188
120
|
Link: ComposerLink
|
|
189
121
|
};
|
|
190
|
-
|
|
191
|
-
showAttachments = true,
|
|
192
|
-
showAttribution,
|
|
193
|
-
defaultValue,
|
|
194
|
-
isCollapsed,
|
|
195
|
-
overrides,
|
|
196
|
-
actions,
|
|
197
|
-
autoFocus,
|
|
198
|
-
hasResolveMentionSuggestions,
|
|
199
|
-
onEmojiPickerOpenChange,
|
|
200
|
-
onEmptyChange,
|
|
201
|
-
onEditorClick
|
|
202
|
-
}) {
|
|
203
|
-
const ref = useRef(null);
|
|
204
|
-
const { isEmpty } = useComposer();
|
|
205
|
-
const $ = useOverrides(overrides);
|
|
206
|
-
const ignoreDropAreaLeaveEvent = useCallback(
|
|
207
|
-
(event) => {
|
|
208
|
-
return Boolean(
|
|
209
|
-
event.relatedTarget && event.target && event.relatedTarget === ref.current && ref.current?.contains(event.target)
|
|
210
|
-
);
|
|
211
|
-
},
|
|
212
|
-
[]
|
|
213
|
-
);
|
|
214
|
-
const [isDraggingOver, dropAreaProps] = useComposerAttachmentsDropArea({
|
|
215
|
-
ignoreLeaveEvent: ignoreDropAreaLeaveEvent
|
|
216
|
-
});
|
|
217
|
-
useLayoutEffect(() => {
|
|
218
|
-
onEmptyChange(isEmpty);
|
|
219
|
-
}, [isEmpty, onEmptyChange]);
|
|
220
|
-
const preventDefault = useCallback((event) => {
|
|
221
|
-
event.preventDefault();
|
|
222
|
-
}, []);
|
|
223
|
-
const stopPropagation = useCallback((event) => {
|
|
224
|
-
event.stopPropagation();
|
|
225
|
-
}, []);
|
|
226
|
-
return /* @__PURE__ */ React__default.createElement("div", {
|
|
227
|
-
className: "lb-composer-editor-container",
|
|
228
|
-
ref,
|
|
229
|
-
...dropAreaProps
|
|
230
|
-
}, /* @__PURE__ */ React__default.createElement(ComposerEditor, {
|
|
231
|
-
className: "lb-composer-editor",
|
|
232
|
-
onClick: onEditorClick,
|
|
233
|
-
placeholder: $.COMPOSER_PLACEHOLDER,
|
|
234
|
-
defaultValue,
|
|
235
|
-
autoFocus,
|
|
236
|
-
components: editorComponents,
|
|
237
|
-
dir: $.dir
|
|
238
|
-
}), showAttachments && /* @__PURE__ */ React__default.createElement(ComposerAttachments, {
|
|
239
|
-
overrides
|
|
240
|
-
}), (!isCollapsed || isDraggingOver) && /* @__PURE__ */ React__default.createElement("div", {
|
|
241
|
-
className: "lb-composer-footer"
|
|
242
|
-
}, /* @__PURE__ */ React__default.createElement("div", {
|
|
243
|
-
className: "lb-composer-editor-actions"
|
|
244
|
-
}, hasResolveMentionSuggestions && /* @__PURE__ */ React__default.createElement(ComposerInsertMentionEditorAction, {
|
|
245
|
-
label: $.COMPOSER_INSERT_MENTION
|
|
246
|
-
}), /* @__PURE__ */ React__default.createElement(ComposerInsertEmojiEditorAction, {
|
|
247
|
-
label: $.COMPOSER_INSERT_EMOJI,
|
|
248
|
-
onPickerOpenChange: onEmojiPickerOpenChange
|
|
249
|
-
}), showAttachments && /* @__PURE__ */ React__default.createElement(ComposerAttachFilesEditorAction, {
|
|
250
|
-
label: $.COMPOSER_ATTACH_FILES
|
|
251
|
-
})), showAttribution && /* @__PURE__ */ React__default.createElement(Attribution, null), /* @__PURE__ */ React__default.createElement("div", {
|
|
252
|
-
className: "lb-composer-actions"
|
|
253
|
-
}, actions ?? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ShortcutTooltip, {
|
|
254
|
-
content: $.COMPOSER_SEND,
|
|
255
|
-
shortcut: /* @__PURE__ */ React__default.createElement(ShortcutTooltipKey, {
|
|
256
|
-
name: "enter"
|
|
257
|
-
})
|
|
258
|
-
}, /* @__PURE__ */ React__default.createElement(ComposerSubmit, {
|
|
259
|
-
asChild: true
|
|
260
|
-
}, /* @__PURE__ */ React__default.createElement(Button, {
|
|
261
|
-
onMouseDown: preventDefault,
|
|
262
|
-
onClick: stopPropagation,
|
|
263
|
-
className: "lb-composer-action",
|
|
264
|
-
variant: "primary",
|
|
265
|
-
"aria-label": $.COMPOSER_SEND
|
|
266
|
-
}, /* @__PURE__ */ React__default.createElement(SendIcon, null))))))), showAttachments && isDraggingOver && /* @__PURE__ */ React__default.createElement("div", {
|
|
267
|
-
className: "lb-composer-attachments-drop-area"
|
|
268
|
-
}, /* @__PURE__ */ React__default.createElement("div", {
|
|
269
|
-
className: "lb-composer-attachments-drop-area-label"
|
|
270
|
-
}, /* @__PURE__ */ React__default.createElement(AttachmentIcon, null), $.COMPOSER_ATTACH_FILES)));
|
|
271
|
-
}
|
|
272
|
-
const Composer = forwardRef(
|
|
122
|
+
const ComposerWithContext = forwardRef(
|
|
273
123
|
({
|
|
274
|
-
threadId,
|
|
275
|
-
commentId,
|
|
276
|
-
metadata,
|
|
277
124
|
defaultValue,
|
|
278
|
-
|
|
279
|
-
|
|
125
|
+
disabled,
|
|
126
|
+
autoFocus,
|
|
280
127
|
collapsed: controlledCollapsed,
|
|
281
128
|
defaultCollapsed,
|
|
282
129
|
onCollapsedChange: controlledOnCollapsedChange,
|
|
283
|
-
overrides,
|
|
284
130
|
actions,
|
|
131
|
+
overrides,
|
|
132
|
+
showAttribution,
|
|
133
|
+
onFocus,
|
|
285
134
|
onBlur,
|
|
286
135
|
className,
|
|
287
|
-
onFocus,
|
|
288
|
-
autoFocus,
|
|
289
|
-
disabled,
|
|
290
|
-
showAttachments = true,
|
|
291
|
-
showAttribution,
|
|
292
136
|
...props
|
|
293
137
|
}, forwardedRef) => {
|
|
294
138
|
const client = useClient();
|
|
295
|
-
const createThread = useCreateThread();
|
|
296
|
-
const createComment = useCreateComment();
|
|
297
|
-
const editComment = useEditComment();
|
|
298
139
|
const hasResolveMentionSuggestions = client[kInternal].resolveMentionSuggestions !== void 0;
|
|
299
|
-
const
|
|
300
|
-
const
|
|
140
|
+
const self = useSelf();
|
|
141
|
+
const isDisabled = useMemo(
|
|
142
|
+
() => disabled || (self ? !self.canComment : false),
|
|
143
|
+
[disabled, self?.canComment]
|
|
144
|
+
);
|
|
145
|
+
const { isEmpty } = useComposer();
|
|
301
146
|
const $ = useOverrides(overrides);
|
|
302
|
-
const [
|
|
147
|
+
const [isEmojiPickerOpen, setEmojiPickerOpen] = useState(false);
|
|
148
|
+
const [collapsed, onCollapsedChange] = useControllableState(
|
|
303
149
|
controlledCollapsed === void 0 && defaultCollapsed === void 0 ? false : controlledCollapsed,
|
|
304
150
|
controlledOnCollapsedChange,
|
|
305
151
|
defaultCollapsed
|
|
306
152
|
);
|
|
307
|
-
const
|
|
308
|
-
|
|
153
|
+
const preventDefault = useCallback((event) => {
|
|
154
|
+
event.preventDefault();
|
|
309
155
|
}, []);
|
|
310
|
-
const
|
|
311
|
-
|
|
156
|
+
const stopPropagation = useCallback((event) => {
|
|
157
|
+
event.stopPropagation();
|
|
312
158
|
}, []);
|
|
159
|
+
const handleEditorClick = useCallback(
|
|
160
|
+
(event) => {
|
|
161
|
+
event.stopPropagation();
|
|
162
|
+
if (isEmpty) {
|
|
163
|
+
onCollapsedChange?.(false);
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
[isEmpty, onCollapsedChange]
|
|
167
|
+
);
|
|
313
168
|
const handleFocus = useCallback(
|
|
314
169
|
(event) => {
|
|
315
170
|
onFocus?.(event);
|
|
316
171
|
if (event.isDefaultPrevented()) {
|
|
317
172
|
return;
|
|
318
173
|
}
|
|
319
|
-
if (
|
|
174
|
+
if (isEmpty) {
|
|
320
175
|
onCollapsedChange?.(false);
|
|
321
176
|
}
|
|
322
177
|
},
|
|
323
|
-
[onCollapsedChange, onFocus]
|
|
178
|
+
[isEmpty, onCollapsedChange, onFocus]
|
|
324
179
|
);
|
|
325
180
|
const handleBlur = useCallback(
|
|
326
181
|
(event) => {
|
|
@@ -328,24 +183,75 @@ const Composer = forwardRef(
|
|
|
328
183
|
if (event.isDefaultPrevented()) {
|
|
329
184
|
return;
|
|
330
185
|
}
|
|
331
|
-
const isOutside = !event.currentTarget.contains(
|
|
332
|
-
|
|
333
|
-
);
|
|
334
|
-
if (isOutside && isEmptyRef.current && !isEmojiPickerOpenRef.current) {
|
|
186
|
+
const isOutside = !event.currentTarget.contains(event.relatedTarget);
|
|
187
|
+
if (isOutside && isEmpty && !isEmojiPickerOpen) {
|
|
335
188
|
onCollapsedChange?.(true);
|
|
336
189
|
}
|
|
337
190
|
},
|
|
338
|
-
[onBlur, onCollapsedChange]
|
|
339
|
-
);
|
|
340
|
-
const handleEditorClick = useCallback(
|
|
341
|
-
(event) => {
|
|
342
|
-
event.stopPropagation();
|
|
343
|
-
if (isEmptyRef.current) {
|
|
344
|
-
onCollapsedChange?.(false);
|
|
345
|
-
}
|
|
346
|
-
},
|
|
347
|
-
[onCollapsedChange]
|
|
191
|
+
[isEmojiPickerOpen, isEmpty, onBlur, onCollapsedChange]
|
|
348
192
|
);
|
|
193
|
+
return /* @__PURE__ */ React__default.createElement("form", {
|
|
194
|
+
className: classNames(
|
|
195
|
+
"lb-root lb-composer lb-composer-form",
|
|
196
|
+
className
|
|
197
|
+
),
|
|
198
|
+
dir: $.dir,
|
|
199
|
+
...props,
|
|
200
|
+
ref: forwardedRef,
|
|
201
|
+
"data-collapsed": collapsed ? "" : void 0,
|
|
202
|
+
onFocus: handleFocus,
|
|
203
|
+
onBlur: handleBlur
|
|
204
|
+
}, /* @__PURE__ */ React__default.createElement(ComposerEditor, {
|
|
205
|
+
className: "lb-composer-editor",
|
|
206
|
+
onClick: handleEditorClick,
|
|
207
|
+
placeholder: $.COMPOSER_PLACEHOLDER,
|
|
208
|
+
defaultValue,
|
|
209
|
+
disabled: isDisabled,
|
|
210
|
+
autoFocus,
|
|
211
|
+
components: editorComponents,
|
|
212
|
+
dir: $.dir
|
|
213
|
+
}), !collapsed && /* @__PURE__ */ React__default.createElement("div", {
|
|
214
|
+
className: "lb-composer-footer"
|
|
215
|
+
}, /* @__PURE__ */ React__default.createElement("div", {
|
|
216
|
+
className: "lb-composer-editor-actions"
|
|
217
|
+
}, hasResolveMentionSuggestions && /* @__PURE__ */ React__default.createElement(ComposerInsertMentionEditorAction, {
|
|
218
|
+
label: $.COMPOSER_INSERT_MENTION,
|
|
219
|
+
disabled: isDisabled
|
|
220
|
+
}), /* @__PURE__ */ React__default.createElement(ComposerInsertEmojiEditorAction, {
|
|
221
|
+
label: $.COMPOSER_INSERT_EMOJI,
|
|
222
|
+
onPickerOpenChange: setEmojiPickerOpen,
|
|
223
|
+
disabled: isDisabled
|
|
224
|
+
})), showAttribution && /* @__PURE__ */ React__default.createElement(Attribution, null), /* @__PURE__ */ React__default.createElement("div", {
|
|
225
|
+
className: "lb-composer-actions"
|
|
226
|
+
}, actions ?? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(ShortcutTooltip, {
|
|
227
|
+
content: $.COMPOSER_SEND,
|
|
228
|
+
shortcut: /* @__PURE__ */ React__default.createElement(ShortcutTooltipKey, {
|
|
229
|
+
name: "enter"
|
|
230
|
+
})
|
|
231
|
+
}, /* @__PURE__ */ React__default.createElement(ComposerSubmit, {
|
|
232
|
+
disabled: isDisabled,
|
|
233
|
+
asChild: true
|
|
234
|
+
}, /* @__PURE__ */ React__default.createElement(Button, {
|
|
235
|
+
onMouseDown: preventDefault,
|
|
236
|
+
onClick: stopPropagation,
|
|
237
|
+
className: "lb-composer-action",
|
|
238
|
+
variant: "primary",
|
|
239
|
+
"aria-label": $.COMPOSER_SEND
|
|
240
|
+
}, /* @__PURE__ */ React__default.createElement(SendIcon, null))))))));
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
const Composer = forwardRef(
|
|
244
|
+
({
|
|
245
|
+
threadId,
|
|
246
|
+
commentId,
|
|
247
|
+
metadata,
|
|
248
|
+
onComposerSubmit,
|
|
249
|
+
onFocus,
|
|
250
|
+
...props
|
|
251
|
+
}, forwardedRef) => {
|
|
252
|
+
const createThread = useCreateThread();
|
|
253
|
+
const createComment = useCreateComment();
|
|
254
|
+
const editComment = useEditComment();
|
|
349
255
|
const handleCommentSubmit = useCallback(
|
|
350
256
|
(comment, event) => {
|
|
351
257
|
onComposerSubmit?.(comment, event);
|
|
@@ -356,20 +262,17 @@ const Composer = forwardRef(
|
|
|
356
262
|
editComment({
|
|
357
263
|
commentId,
|
|
358
264
|
threadId,
|
|
359
|
-
body: comment.body
|
|
360
|
-
attachments: comment.attachments
|
|
265
|
+
body: comment.body
|
|
361
266
|
});
|
|
362
267
|
} else if (threadId) {
|
|
363
268
|
createComment({
|
|
364
269
|
threadId,
|
|
365
|
-
body: comment.body
|
|
366
|
-
attachments: comment.attachments
|
|
270
|
+
body: comment.body
|
|
367
271
|
});
|
|
368
272
|
} else {
|
|
369
273
|
createThread({
|
|
370
274
|
body: comment.body,
|
|
371
|
-
metadata: metadata ?? {}
|
|
372
|
-
attachments: comment.attachments
|
|
275
|
+
metadata: metadata ?? {}
|
|
373
276
|
});
|
|
374
277
|
}
|
|
375
278
|
},
|
|
@@ -385,30 +288,11 @@ const Composer = forwardRef(
|
|
|
385
288
|
);
|
|
386
289
|
return /* @__PURE__ */ React__default.createElement(TooltipProvider, null, /* @__PURE__ */ React__default.createElement(ComposerForm, {
|
|
387
290
|
onComposerSubmit: handleCommentSubmit,
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
),
|
|
392
|
-
dir: $.dir,
|
|
291
|
+
onFocus,
|
|
292
|
+
asChild: true
|
|
293
|
+
}, /* @__PURE__ */ React__default.createElement(ComposerWithContext, {
|
|
393
294
|
...props,
|
|
394
|
-
ref: forwardedRef
|
|
395
|
-
"data-collapsed": isCollapsed ? "" : void 0,
|
|
396
|
-
onFocus: handleFocus,
|
|
397
|
-
onBlur: handleBlur,
|
|
398
|
-
disabled,
|
|
399
|
-
defaultAttachments
|
|
400
|
-
}, /* @__PURE__ */ React__default.createElement(ComposerEditorContainer, {
|
|
401
|
-
defaultValue,
|
|
402
|
-
actions,
|
|
403
|
-
overrides,
|
|
404
|
-
isCollapsed,
|
|
405
|
-
showAttachments,
|
|
406
|
-
showAttribution,
|
|
407
|
-
hasResolveMentionSuggestions,
|
|
408
|
-
onEmptyChange: setEmptyRef,
|
|
409
|
-
onEmojiPickerOpenChange: setEmojiPickerOpenRef,
|
|
410
|
-
onEditorClick: handleEditorClick,
|
|
411
|
-
autoFocus
|
|
295
|
+
ref: forwardedRef
|
|
412
296
|
})));
|
|
413
297
|
}
|
|
414
298
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Composer.mjs","sources":["../../src/components/Composer.tsx"],"sourcesContent":["\"use client\";\n\nimport type {\n BaseMetadata,\n CommentAttachment,\n CommentMixedAttachment,\n DM,\n} from \"@liveblocks/core\";\nimport { kInternal } from \"@liveblocks/core\";\nimport {\n useClient,\n useCreateComment,\n useCreateThread,\n useEditComment,\n} from \"@liveblocks/react\";\nimport type {\n ComponentPropsWithoutRef,\n DragEvent,\n FocusEvent,\n FormEvent,\n ForwardedRef,\n MouseEvent,\n ReactNode,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport React, { forwardRef, useCallback, useRef } from \"react\";\n\nimport { AttachmentIcon } from \"../icons/Attachment\";\nimport { EmojiIcon } from \"../icons/Emoji\";\nimport { MentionIcon } from \"../icons/Mention\";\nimport { SendIcon } from \"../icons/Send\";\nimport type { ComposerOverrides, GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport * as ComposerPrimitive from \"../primitives/Composer\";\nimport { useComposer } from \"../primitives/Composer/contexts\";\nimport type {\n ComposerEditorComponents,\n ComposerEditorLinkProps,\n ComposerEditorMentionProps,\n ComposerEditorMentionSuggestionsProps,\n ComposerEditorProps,\n ComposerFormProps,\n ComposerSubmitComment,\n} from \"../primitives/Composer/types\";\nimport { useComposerAttachmentsDropArea } from \"../primitives/Composer/utils\";\nimport { MENTION_CHARACTER } from \"../slate/plugins/mentions\";\nimport { classNames } from \"../utils/class-names\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport { useLayoutEffect } from \"../utils/use-layout-effect\";\nimport { FileAttachment } from \"./internal/Attachment\";\nimport { Attribution } from \"./internal/Attribution\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Button } from \"./internal/Button\";\nimport type { EmojiPickerProps } from \"./internal/EmojiPicker\";\nimport { EmojiPicker, EmojiPickerTrigger } from \"./internal/EmojiPicker\";\nimport {\n ShortcutTooltip,\n ShortcutTooltipKey,\n Tooltip,\n TooltipProvider,\n} from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\ninterface EditorActionProps extends ComponentPropsWithoutRef<\"button\"> {\n label: string;\n}\n\ninterface EmojiEditorActionProps extends EditorActionProps {\n onPickerOpenChange?: EmojiPickerProps[\"onOpenChange\"];\n}\n\ntype ComposerCreateThreadProps<M extends BaseMetadata> = {\n threadId?: never;\n commentId?: never;\n\n /**\n * The metadata of the thread to create.\n */\n metadata?: M;\n};\n\ntype ComposerCreateCommentProps = {\n /**\n * The ID of the thread to reply to.\n */\n threadId: string;\n commentId?: never;\n metadata?: never;\n};\n\ntype ComposerEditCommentProps = {\n /**\n * The ID of the thread to edit a comment in.\n */\n threadId: string;\n\n /**\n * The ID of the comment to edit.\n */\n commentId: string;\n metadata?: never;\n};\n\nexport type ComposerProps<M extends BaseMetadata = DM> = Omit<\n ComponentPropsWithoutRef<\"form\">,\n \"defaultValue\"\n> &\n (\n | ComposerCreateThreadProps<M>\n | ComposerCreateCommentProps\n | ComposerEditCommentProps\n ) & {\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: (\n comment: ComposerSubmitComment,\n event: FormEvent<HTMLFormElement>\n ) => Promise<void> | void;\n\n /**\n * The composer's initial value.\n */\n defaultValue?: ComposerEditorProps[\"defaultValue\"];\n\n /**\n * The composer's initial attachments.\n */\n defaultAttachments?: CommentAttachment[];\n\n /**\n * Whether the composer is collapsed. Setting a value will make the composer controlled.\n */\n collapsed?: boolean;\n\n /**\n * The event handler called when the collapsed state of the composer changes.\n */\n onCollapsedChange?: (collapsed: boolean) => void;\n\n /**\n * Whether the composer is initially collapsed. Setting a value will make the composer uncontrolled.\n */\n defaultCollapsed?: boolean;\n\n /**\n * Whether to show and allow adding attachments.\n */\n showAttachments?: boolean;\n\n /**\n * Whether the composer is disabled.\n */\n disabled?: ComposerFormProps[\"disabled\"];\n\n /**\n * Whether to focus the composer on mount.\n */\n autoFocus?: ComposerEditorProps[\"autoFocus\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & ComposerOverrides>;\n\n /**\n * @internal\n */\n actions?: ReactNode;\n\n /**\n * @internal\n */\n showAttribution?: boolean;\n };\n\ninterface ComposerEditorContainerProps\n extends Pick<\n ComposerProps,\n | \"defaultValue\"\n | \"showAttachments\"\n | \"showAttribution\"\n | \"overrides\"\n | \"actions\"\n | \"autoFocus\"\n > {\n isCollapsed: boolean | undefined;\n onEmptyChange: (isEmpty: boolean) => void;\n hasResolveMentionSuggestions: boolean;\n onEmojiPickerOpenChange: (isOpen: boolean) => void;\n onEditorClick: (event: MouseEvent<HTMLDivElement>) => void;\n}\n\nfunction ComposerInsertMentionEditorAction({\n label,\n className,\n onClick,\n ...props\n}: EditorActionProps) {\n const { createMention } = useComposer();\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n\n if (!event.isDefaultPrevented()) {\n event.stopPropagation();\n createMention();\n }\n },\n [createMention, onClick]\n );\n\n return (\n <Tooltip content={label}>\n <Button\n className={classNames(\"lb-composer-editor-action\", className)}\n onMouseDown={preventDefault}\n onClick={handleClick}\n aria-label={label}\n {...props}\n >\n <MentionIcon className=\"lb-button-icon\" />\n </Button>\n </Tooltip>\n );\n}\n\nfunction ComposerInsertEmojiEditorAction({\n label,\n onPickerOpenChange,\n className,\n ...props\n}: EmojiEditorActionProps) {\n const { insertText } = useComposer();\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n return (\n <EmojiPicker onEmojiSelect={insertText} onOpenChange={onPickerOpenChange}>\n <Tooltip content={label}>\n <EmojiPickerTrigger asChild>\n <Button\n className={classNames(\"lb-composer-editor-action\", className)}\n onMouseDown={preventDefault}\n onClick={stopPropagation}\n aria-label={label}\n {...props}\n >\n <EmojiIcon className=\"lb-button-icon\" />\n </Button>\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n );\n}\n\nfunction ComposerAttachFilesEditorAction({\n label,\n className,\n ...props\n}: EditorActionProps) {\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n return (\n <Tooltip content={label}>\n <ComposerPrimitive.AttachFiles asChild>\n <Button\n className={classNames(\"lb-composer-editor-action\", className)}\n onMouseDown={preventDefault}\n onClick={stopPropagation}\n aria-label={label}\n {...props}\n >\n <AttachmentIcon className=\"lb-button-icon\" />\n </Button>\n </ComposerPrimitive.AttachFiles>\n </Tooltip>\n );\n}\n\nfunction ComposerMention({ userId }: ComposerEditorMentionProps) {\n return (\n <ComposerPrimitive.Mention className=\"lb-composer-mention\">\n {MENTION_CHARACTER}\n <User userId={userId} />\n </ComposerPrimitive.Mention>\n );\n}\n\nfunction ComposerMentionSuggestions({\n userIds,\n}: ComposerEditorMentionSuggestionsProps) {\n return userIds.length > 0 ? (\n <ComposerPrimitive.Suggestions className=\"lb-root lb-portal lb-elevation lb-composer-suggestions lb-composer-mention-suggestions\">\n <ComposerPrimitive.SuggestionsList className=\"lb-composer-suggestions-list lb-composer-mention-suggestions-list\">\n {userIds.map((userId) => (\n <ComposerPrimitive.SuggestionsListItem\n key={userId}\n className=\"lb-composer-suggestions-list-item lb-composer-mention-suggestion\"\n value={userId}\n >\n <Avatar\n userId={userId}\n className=\"lb-composer-mention-suggestion-avatar\"\n />\n <User\n userId={userId}\n className=\"lb-composer-mention-suggestion-user\"\n />\n </ComposerPrimitive.SuggestionsListItem>\n ))}\n </ComposerPrimitive.SuggestionsList>\n </ComposerPrimitive.Suggestions>\n ) : null;\n}\n\nfunction ComposerLink({ href, children }: ComposerEditorLinkProps) {\n return (\n <ComposerPrimitive.Link href={href} className=\"lb-composer-link\">\n {children}\n </ComposerPrimitive.Link>\n );\n}\n\ninterface ComposerAttachmentsProps extends ComponentPropsWithoutRef<\"div\"> {\n overrides?: Partial<GlobalOverrides & ComposerOverrides>;\n}\n\ninterface ComposerFileAttachmentProps extends ComponentPropsWithoutRef<\"div\"> {\n attachment: CommentMixedAttachment;\n overrides?: Partial<GlobalOverrides & ComposerOverrides>;\n}\n\nfunction ComposerFileAttachment({\n attachment,\n className,\n overrides,\n ...props\n}: ComposerFileAttachmentProps) {\n const { removeAttachment } = useComposer();\n\n const handleDeleteClick = useCallback(() => {\n removeAttachment(attachment.id);\n }, [attachment.id, removeAttachment]);\n\n return (\n <FileAttachment\n className={classNames(\"lb-composer-attachment\", className)}\n {...props}\n attachment={attachment}\n onDeleteClick={handleDeleteClick}\n preventFocusOnDelete\n overrides={overrides}\n />\n );\n}\n\nfunction ComposerAttachments({\n overrides,\n className,\n ...props\n}: ComposerAttachmentsProps) {\n const { attachments } = useComposer();\n\n if (attachments.length === 0) {\n return null;\n }\n\n return (\n <div\n className={classNames(\"lb-composer-attachments\", className)}\n {...props}\n >\n {attachments.map((attachment) => {\n return (\n <ComposerFileAttachment\n key={attachment.id}\n attachment={attachment}\n overrides={overrides}\n />\n );\n })}\n </div>\n );\n}\n\nconst editorComponents: ComposerEditorComponents = {\n Mention: ComposerMention,\n MentionSuggestions: ComposerMentionSuggestions,\n Link: ComposerLink,\n};\n\nfunction ComposerEditorContainer({\n showAttachments = true,\n showAttribution,\n defaultValue,\n isCollapsed,\n overrides,\n actions,\n autoFocus,\n hasResolveMentionSuggestions,\n onEmojiPickerOpenChange,\n onEmptyChange,\n onEditorClick,\n}: ComposerEditorContainerProps) {\n const ref = useRef<HTMLDivElement>(null);\n const { isEmpty } = useComposer();\n const $ = useOverrides(overrides);\n const ignoreDropAreaLeaveEvent = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n return Boolean(\n event.relatedTarget &&\n event.target &&\n event.relatedTarget === ref.current &&\n ref.current?.contains(event.target as HTMLElement)\n );\n },\n []\n );\n const [isDraggingOver, dropAreaProps] = useComposerAttachmentsDropArea({\n ignoreLeaveEvent: ignoreDropAreaLeaveEvent,\n });\n\n useLayoutEffect(() => {\n onEmptyChange(isEmpty);\n }, [isEmpty, onEmptyChange]);\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n return (\n <div className=\"lb-composer-editor-container\" ref={ref} {...dropAreaProps}>\n <ComposerPrimitive.Editor\n className=\"lb-composer-editor\"\n onClick={onEditorClick}\n placeholder={$.COMPOSER_PLACEHOLDER}\n defaultValue={defaultValue}\n autoFocus={autoFocus}\n components={editorComponents}\n dir={$.dir}\n />\n {showAttachments && <ComposerAttachments overrides={overrides} />}\n {(!isCollapsed || isDraggingOver) && (\n <div className=\"lb-composer-footer\">\n <div className=\"lb-composer-editor-actions\">\n {hasResolveMentionSuggestions && (\n <ComposerInsertMentionEditorAction\n label={$.COMPOSER_INSERT_MENTION}\n />\n )}\n <ComposerInsertEmojiEditorAction\n label={$.COMPOSER_INSERT_EMOJI}\n onPickerOpenChange={onEmojiPickerOpenChange}\n />\n {showAttachments && (\n <ComposerAttachFilesEditorAction\n label={$.COMPOSER_ATTACH_FILES}\n />\n )}\n </div>\n {showAttribution && <Attribution />}\n <div className=\"lb-composer-actions\">\n {actions ?? (\n <>\n <ShortcutTooltip\n content={$.COMPOSER_SEND}\n shortcut={<ShortcutTooltipKey name=\"enter\" />}\n >\n <ComposerPrimitive.Submit asChild>\n <Button\n onMouseDown={preventDefault}\n onClick={stopPropagation}\n className=\"lb-composer-action\"\n variant=\"primary\"\n aria-label={$.COMPOSER_SEND}\n >\n <SendIcon />\n </Button>\n </ComposerPrimitive.Submit>\n </ShortcutTooltip>\n </>\n )}\n </div>\n </div>\n )}\n {showAttachments && isDraggingOver && (\n <div className=\"lb-composer-attachments-drop-area\">\n <div className=\"lb-composer-attachments-drop-area-label\">\n <AttachmentIcon />\n {$.COMPOSER_ATTACH_FILES}\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Displays a composer to create comments.\n *\n * @example\n * <Composer />\n */\nexport const Composer = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n threadId,\n commentId,\n metadata,\n defaultValue,\n defaultAttachments,\n onComposerSubmit,\n collapsed: controlledCollapsed,\n defaultCollapsed,\n onCollapsedChange: controlledOnCollapsedChange,\n overrides,\n actions,\n onBlur,\n className,\n onFocus,\n autoFocus,\n disabled,\n showAttachments = true,\n showAttribution,\n ...props\n }: ComposerProps<M>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const client = useClient();\n const createThread = useCreateThread();\n const createComment = useCreateComment();\n const editComment = useEditComment();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const isEmptyRef = useRef(true);\n const isEmojiPickerOpenRef = useRef(false);\n const $ = useOverrides(overrides);\n const [isCollapsed, onCollapsedChange] = useControllableState(\n // If the composer is neither controlled nor uncontrolled, it defaults to controlled as uncollapsed.\n controlledCollapsed === undefined && defaultCollapsed === undefined\n ? false\n : controlledCollapsed,\n controlledOnCollapsedChange,\n defaultCollapsed\n );\n\n const setEmptyRef = useCallback((isEmpty: boolean) => {\n isEmptyRef.current = isEmpty;\n }, []);\n\n const setEmojiPickerOpenRef = useCallback((isEmojiPickerOpen: boolean) => {\n isEmojiPickerOpenRef.current = isEmojiPickerOpen;\n }, []);\n\n const handleFocus = useCallback(\n (event: FocusEvent<HTMLFormElement>) => {\n onFocus?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n if (isEmptyRef.current) {\n onCollapsedChange?.(false);\n }\n },\n [onCollapsedChange, onFocus]\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLFormElement>) => {\n onBlur?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n const isOutside = !event.currentTarget.contains(\n event.relatedTarget ?? document.activeElement\n );\n\n // TODO: Handle \"delete\" buttons on attachments (hide them when the composer is collapsed)\n if (isOutside && isEmptyRef.current && !isEmojiPickerOpenRef.current) {\n onCollapsedChange?.(true);\n }\n },\n [onBlur, onCollapsedChange]\n );\n\n const handleEditorClick = useCallback(\n (event: MouseEvent<HTMLDivElement>) => {\n event.stopPropagation();\n\n if (isEmptyRef.current) {\n onCollapsedChange?.(false);\n }\n },\n [onCollapsedChange]\n );\n\n const handleCommentSubmit = useCallback(\n (comment: ComposerSubmitComment, event: FormEvent<HTMLFormElement>) => {\n onComposerSubmit?.(comment, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n if (commentId && threadId) {\n editComment({\n commentId,\n threadId,\n body: comment.body,\n attachments: comment.attachments,\n });\n } else if (threadId) {\n createComment({\n threadId,\n body: comment.body,\n attachments: comment.attachments,\n });\n } else {\n createThread({\n body: comment.body,\n metadata: metadata ?? {},\n attachments: comment.attachments,\n });\n }\n },\n [\n commentId,\n createComment,\n createThread,\n editComment,\n metadata,\n onComposerSubmit,\n threadId,\n ]\n );\n\n return (\n <TooltipProvider>\n <ComposerPrimitive.Form\n onComposerSubmit={handleCommentSubmit}\n className={classNames(\n \"lb-root lb-composer lb-composer-form\",\n className\n )}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n data-collapsed={isCollapsed ? \"\" : undefined}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n defaultAttachments={defaultAttachments}\n >\n <ComposerEditorContainer\n defaultValue={defaultValue}\n actions={actions}\n overrides={overrides}\n isCollapsed={isCollapsed}\n showAttachments={showAttachments}\n showAttribution={showAttribution}\n hasResolveMentionSuggestions={hasResolveMentionSuggestions}\n onEmptyChange={setEmptyRef}\n onEmojiPickerOpenChange={setEmojiPickerOpenRef}\n onEditorClick={handleEditorClick}\n autoFocus={autoFocus}\n />\n </ComposerPrimitive.Form>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ComposerProps<M> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkMA;AAA2C;AACzC;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAqB;AAGvB;AAAoB;AAEhB;AAEA;AACE;AACA;AAAc;AAChB;AACF;AACuB;AAGzB;AACG;AAAiB;AACf;AAC6D;AAC/C;AACJ;AACG;AACR;AAEH;AAAsB;AAI/B;AAEA;AAAyC;AACvC;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAqB;AAGvB;AACE;AAAsB;AAGxB;AACG;AAA2B;AAA0B;AACnD;AAAiB;AACf;AAA0B;AACxB;AAC6D;AAC/C;AACJ;AACG;AACR;AAEH;AAAoB;AAMjC;AAEA;AAAyC;AACvC;AACA;AAEF;AACE;AACE;AAAqB;AAGvB;AACE;AAAsB;AAGxB;AACG;AAAiB;AACf;AAAqC;AACnC;AAC6D;AAC/C;AACJ;AACG;AACR;AAEH;AAAyB;AAKpC;AAEA;AACE;AACG;AAAoC;AAElC;AAAK;AAGZ;AAEA;AAAoC;AAEpC;AACE;AACG;AAAwC;AACtC;AAA4C;AAExC;AACM;AACK;AACH;AAEN;AACC;AACU;AAEX;AACC;AACU;AAOxB;AAEA;AACE;AACG;AAAuB;AAAsB;AAIlD;AAWA;AAAgC;AAC9B;AACA;AACA;AAEF;AACE;AAEA;AACE;AAA8B;AAGhC;AACG;AAC0D;AACrD;AACJ;AACe;AACK;AACpB;AAGN;AAEA;AAA6B;AAC3B;AACA;AAEF;AACE;AAEA;AACE;AAAO;AAGT;AACG;AAC2D;AACtD;AAGF;AACG;AACiB;AAChB;AACA;AACF;AAKV;AAEA;AAAmD;AACxC;AACW;AAEtB;AAEA;AAAiC;AACb;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEF;AACE;AACA;AACA;AACA;AAAiC;AAE7B;AAAO;AAI8C;AACrD;AACF;AACC;AAEH;AAAuE;AACnD;AAGpB;AACE;AAAqB;AAGvB;AACE;AAAqB;AAGvB;AACE;AAAsB;AAGxB;AACG;AAAc;AAA+B;AAAc;AACzD;AACW;AACD;AACM;AACf;AACA;AACY;AACL;AAEY;AAAoB;AAEtC;AAAc;AACZ;AAAc;AAEV;AACU;AAGZ;AACU;AACW;AAGnB;AACU;AAKd;AAAc;AAGR;AACY;AACA;AAAwB;AAAQ;AAE1C;AAAgC;AAC9B;AACc;AACJ;AACC;AACF;AACM;AAY3B;AAAc;AACZ;AAAc;AAQzB;AAQO;AAAiB;AAEpB;AACE;AACA;AACA;AACA;AACA;AACA;AACW;AACX;AACmB;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACkB;AAClB;AACG;AAIL;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAAyC;AAInC;AACJ;AACA;AAGF;AACE;AAAqB;AAGvB;AACE;AAA+B;AAGjC;AAAoB;AAEhB;AAEA;AACE;AAAA;AAGF;AACE;AAAyB;AAC3B;AACF;AAC2B;AAG7B;AAAmB;AAEf;AAEA;AACE;AAAA;AAGF;AAAuC;AACL;AAIlC;AACE;AAAwB;AAC1B;AACF;AAC0B;AAG5B;AAA0B;AAEtB;AAEA;AACE;AAAyB;AAC3B;AACF;AACkB;AAGpB;AAA4B;AAExB;AAEA;AACE;AAAA;AAGF;AACE;AAAY;AACV;AACA;AACc;AACO;AACtB;AAED;AAAc;AACZ;AACc;AACO;AACtB;AAED;AAAa;AACG;AACS;AACF;AACtB;AACH;AACF;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAGF;AAEK;AACmB;AACP;AACT;AACA;AACF;AACO;AACH;AACC;AAC8B;AAC1B;AACD;AACR;AACA;AAEC;AACC;AACA;AACA;AACA;AACA;AACA;AACA;AACe;AACU;AACV;AACf;AAGN;AAGN;;"}
|
|
1
|
+
{"version":3,"file":"Composer.mjs","sources":["../../src/components/Composer.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BaseMetadata, DM } from \"@liveblocks/core\";\nimport { kInternal } from \"@liveblocks/core\";\nimport {\n useClient,\n useCreateComment,\n useCreateThread,\n useEditComment,\n useSelf,\n} from \"@liveblocks/react\";\nimport type {\n ComponentPropsWithoutRef,\n FocusEvent,\n FormEvent,\n ForwardedRef,\n MouseEvent,\n ReactNode,\n RefAttributes,\n SyntheticEvent,\n} from \"react\";\nimport React, { forwardRef, useCallback, useMemo, useState } from \"react\";\n\nimport { EmojiIcon } from \"../icons/Emoji\";\nimport { MentionIcon } from \"../icons/Mention\";\nimport { SendIcon } from \"../icons/Send\";\nimport type { ComposerOverrides, GlobalOverrides } from \"../overrides\";\nimport { useOverrides } from \"../overrides\";\nimport * as ComposerPrimitive from \"../primitives/Composer\";\nimport { useComposer } from \"../primitives/Composer/contexts\";\nimport type {\n ComposerEditorComponents,\n ComposerEditorLinkProps,\n ComposerEditorMentionProps,\n ComposerEditorMentionSuggestionsProps,\n ComposerEditorProps,\n ComposerSubmitComment,\n} from \"../primitives/Composer/types\";\nimport { MENTION_CHARACTER } from \"../slate/plugins/mentions\";\nimport { classNames } from \"../utils/class-names\";\nimport { useControllableState } from \"../utils/use-controllable-state\";\nimport { Attribution } from \"./internal/Attribution\";\nimport { Avatar } from \"./internal/Avatar\";\nimport { Button } from \"./internal/Button\";\nimport type { EmojiPickerProps } from \"./internal/EmojiPicker\";\nimport { EmojiPicker, EmojiPickerTrigger } from \"./internal/EmojiPicker\";\nimport {\n ShortcutTooltip,\n ShortcutTooltipKey,\n Tooltip,\n TooltipProvider,\n} from \"./internal/Tooltip\";\nimport { User } from \"./internal/User\";\n\ninterface EditorActionProps extends ComponentPropsWithoutRef<\"button\"> {\n label: string;\n}\n\ninterface EmojiEditorActionProps extends EditorActionProps {\n onPickerOpenChange?: EmojiPickerProps[\"onOpenChange\"];\n}\n\ntype ComposerCreateThreadProps<M extends BaseMetadata> = {\n threadId?: never;\n commentId?: never;\n\n /**\n * The metadata of the thread to create.\n */\n metadata?: M;\n};\n\ntype ComposerCreateCommentProps = {\n /**\n * The ID of the thread to reply to.\n */\n threadId: string;\n commentId?: never;\n metadata?: never;\n};\n\ntype ComposerEditCommentProps = {\n /**\n * The ID of the thread to edit a comment in.\n */\n threadId: string;\n\n /**\n * The ID of the comment to edit.\n */\n commentId: string;\n metadata?: never;\n};\n\nexport type ComposerProps<M extends BaseMetadata = DM> = Omit<\n ComponentPropsWithoutRef<\"form\">,\n \"defaultValue\"\n> &\n (\n | ComposerCreateThreadProps<M>\n | ComposerCreateCommentProps\n | ComposerEditCommentProps\n ) & {\n /**\n * The event handler called when the composer is submitted.\n */\n onComposerSubmit?: (\n comment: ComposerSubmitComment,\n event: FormEvent<HTMLFormElement>\n ) => Promise<void> | void;\n\n /**\n * The composer's initial value.\n */\n defaultValue?: ComposerEditorProps[\"defaultValue\"];\n\n /**\n * Whether the composer is collapsed. Setting a value will make the composer controlled.\n */\n collapsed?: boolean;\n\n /**\n * The event handler called when the collapsed state of the composer changes.\n */\n onCollapsedChange?: (collapsed: boolean) => void;\n\n /**\n * Whether the composer is initially collapsed. Setting a value will make the composer uncontrolled.\n */\n defaultCollapsed?: boolean;\n\n /**\n * Whether the composer is disabled.\n */\n disabled?: ComposerEditorProps[\"disabled\"];\n\n /**\n * Whether to focus the composer on mount.\n */\n autoFocus?: ComposerEditorProps[\"autoFocus\"];\n\n /**\n * Override the component's strings.\n */\n overrides?: Partial<GlobalOverrides & ComposerOverrides>;\n\n /**\n * @internal\n */\n actions?: ReactNode;\n\n /**\n * @internal\n */\n showAttribution?: boolean;\n };\n\nfunction ComposerInsertMentionEditorAction({\n label,\n className,\n onClick,\n ...props\n}: EditorActionProps) {\n const { createMention } = useComposer();\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n\n if (!event.isDefaultPrevented()) {\n event.stopPropagation();\n createMention();\n }\n },\n [createMention, onClick]\n );\n\n return (\n <Tooltip content={label}>\n <Button\n className={classNames(\"lb-composer-editor-action\", className)}\n onMouseDown={preventDefault}\n onClick={handleClick}\n aria-label={label}\n {...props}\n >\n <MentionIcon className=\"lb-button-icon\" />\n </Button>\n </Tooltip>\n );\n}\n\nfunction ComposerInsertEmojiEditorAction({\n label,\n onPickerOpenChange,\n className,\n ...props\n}: EmojiEditorActionProps) {\n const { insertText } = useComposer();\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n return (\n <EmojiPicker onEmojiSelect={insertText} onOpenChange={onPickerOpenChange}>\n <Tooltip content={label}>\n <EmojiPickerTrigger asChild>\n <Button\n className={classNames(\"lb-composer-editor-action\", className)}\n onMouseDown={preventDefault}\n onClick={stopPropagation}\n aria-label={label}\n {...props}\n >\n <EmojiIcon className=\"lb-button-icon\" />\n </Button>\n </EmojiPickerTrigger>\n </Tooltip>\n </EmojiPicker>\n );\n}\n\nfunction ComposerMention({ userId }: ComposerEditorMentionProps) {\n return (\n <ComposerPrimitive.Mention className=\"lb-composer-mention\">\n {MENTION_CHARACTER}\n <User userId={userId} />\n </ComposerPrimitive.Mention>\n );\n}\n\nfunction ComposerMentionSuggestions({\n userIds,\n}: ComposerEditorMentionSuggestionsProps) {\n return userIds.length > 0 ? (\n <ComposerPrimitive.Suggestions className=\"lb-root lb-portal lb-elevation lb-composer-suggestions lb-composer-mention-suggestions\">\n <ComposerPrimitive.SuggestionsList className=\"lb-composer-suggestions-list lb-composer-mention-suggestions-list\">\n {userIds.map((userId) => (\n <ComposerPrimitive.SuggestionsListItem\n key={userId}\n className=\"lb-composer-suggestions-list-item lb-composer-mention-suggestion\"\n value={userId}\n >\n <Avatar\n userId={userId}\n className=\"lb-composer-mention-suggestion-avatar\"\n />\n <User\n userId={userId}\n className=\"lb-composer-mention-suggestion-user\"\n />\n </ComposerPrimitive.SuggestionsListItem>\n ))}\n </ComposerPrimitive.SuggestionsList>\n </ComposerPrimitive.Suggestions>\n ) : null;\n}\n\nfunction ComposerLink({ href, children }: ComposerEditorLinkProps) {\n return (\n <ComposerPrimitive.Link href={href} className=\"lb-composer-link\">\n {children}\n </ComposerPrimitive.Link>\n );\n}\n\nconst editorComponents: ComposerEditorComponents = {\n Mention: ComposerMention,\n MentionSuggestions: ComposerMentionSuggestions,\n Link: ComposerLink,\n};\n\nconst ComposerWithContext = forwardRef<\n HTMLFormElement,\n Omit<ComposerProps, \"threadId\" | \"commentId\" | \"onComposerSubmit\">\n>(\n (\n {\n defaultValue,\n disabled,\n autoFocus,\n collapsed: controlledCollapsed,\n defaultCollapsed,\n onCollapsedChange: controlledOnCollapsedChange,\n actions,\n overrides,\n showAttribution,\n onFocus,\n onBlur,\n className,\n ...props\n },\n forwardedRef\n ) => {\n const client = useClient();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const self = useSelf();\n const isDisabled = useMemo(\n () => disabled || (self ? !self.canComment : false),\n [disabled, self?.canComment] // eslint-disable-line react-hooks/exhaustive-deps\n );\n const { isEmpty } = useComposer();\n const $ = useOverrides(overrides);\n const [isEmojiPickerOpen, setEmojiPickerOpen] = useState(false);\n const [collapsed, onCollapsedChange] = useControllableState(\n // If the composer is neither controlled nor uncontrolled, it defaults to controlled as uncollapsed.\n controlledCollapsed === undefined && defaultCollapsed === undefined\n ? false\n : controlledCollapsed,\n controlledOnCollapsedChange,\n defaultCollapsed\n );\n\n const preventDefault = useCallback((event: SyntheticEvent) => {\n event.preventDefault();\n }, []);\n\n const stopPropagation = useCallback((event: SyntheticEvent) => {\n event.stopPropagation();\n }, []);\n\n const handleEditorClick = useCallback(\n (event: MouseEvent<HTMLDivElement>) => {\n event.stopPropagation();\n\n if (isEmpty) {\n onCollapsedChange?.(false);\n }\n },\n [isEmpty, onCollapsedChange]\n );\n\n const handleFocus = useCallback(\n (event: FocusEvent<HTMLFormElement>) => {\n onFocus?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n if (isEmpty) {\n onCollapsedChange?.(false);\n }\n },\n [isEmpty, onCollapsedChange, onFocus]\n );\n\n const handleBlur = useCallback(\n (event: FocusEvent<HTMLFormElement>) => {\n onBlur?.(event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n const isOutside = !event.currentTarget.contains(event.relatedTarget);\n\n if (isOutside && isEmpty && !isEmojiPickerOpen) {\n onCollapsedChange?.(true);\n }\n },\n [isEmojiPickerOpen, isEmpty, onBlur, onCollapsedChange]\n );\n\n return (\n <form\n className={classNames(\n \"lb-root lb-composer lb-composer-form\",\n className\n )}\n dir={$.dir}\n {...props}\n ref={forwardedRef}\n data-collapsed={collapsed ? \"\" : undefined}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n <ComposerPrimitive.Editor\n className=\"lb-composer-editor\"\n onClick={handleEditorClick}\n placeholder={$.COMPOSER_PLACEHOLDER}\n defaultValue={defaultValue}\n disabled={isDisabled}\n autoFocus={autoFocus}\n components={editorComponents}\n dir={$.dir}\n />\n {!collapsed && (\n <div className=\"lb-composer-footer\">\n <div className=\"lb-composer-editor-actions\">\n {hasResolveMentionSuggestions && (\n <ComposerInsertMentionEditorAction\n label={$.COMPOSER_INSERT_MENTION}\n disabled={isDisabled}\n />\n )}\n <ComposerInsertEmojiEditorAction\n label={$.COMPOSER_INSERT_EMOJI}\n onPickerOpenChange={setEmojiPickerOpen}\n disabled={isDisabled}\n />\n </div>\n {showAttribution && <Attribution />}\n <div className=\"lb-composer-actions\">\n {actions ?? (\n <>\n <ShortcutTooltip\n content={$.COMPOSER_SEND}\n shortcut={<ShortcutTooltipKey name=\"enter\" />}\n >\n <ComposerPrimitive.Submit disabled={isDisabled} asChild>\n <Button\n onMouseDown={preventDefault}\n onClick={stopPropagation}\n className=\"lb-composer-action\"\n variant=\"primary\"\n aria-label={$.COMPOSER_SEND}\n >\n <SendIcon />\n </Button>\n </ComposerPrimitive.Submit>\n </ShortcutTooltip>\n </>\n )}\n </div>\n </div>\n )}\n </form>\n );\n }\n);\n\n/**\n * Displays a composer to create comments.\n *\n * @example\n * <Composer />\n */\nexport const Composer = forwardRef(\n <M extends BaseMetadata = DM>(\n {\n threadId,\n commentId,\n metadata,\n onComposerSubmit,\n onFocus,\n ...props\n }: ComposerProps<M>,\n forwardedRef: ForwardedRef<HTMLFormElement>\n ) => {\n const createThread = useCreateThread();\n const createComment = useCreateComment();\n const editComment = useEditComment();\n\n const handleCommentSubmit = useCallback(\n (comment: ComposerSubmitComment, event: FormEvent<HTMLFormElement>) => {\n onComposerSubmit?.(comment, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n if (commentId && threadId) {\n editComment({\n commentId,\n threadId,\n body: comment.body,\n });\n } else if (threadId) {\n createComment({\n threadId,\n body: comment.body,\n });\n } else {\n createThread({\n body: comment.body,\n metadata: metadata ?? {},\n });\n }\n },\n [\n commentId,\n createComment,\n createThread,\n editComment,\n metadata,\n onComposerSubmit,\n threadId,\n ]\n );\n\n return (\n <TooltipProvider>\n <ComposerPrimitive.Form\n onComposerSubmit={handleCommentSubmit}\n onFocus={onFocus}\n asChild\n >\n <ComposerWithContext {...props} ref={forwardedRef} />\n </ComposerPrimitive.Form>\n </TooltipProvider>\n );\n }\n) as <M extends BaseMetadata = DM>(\n props: ComposerProps<M> & RefAttributes<HTMLFormElement>\n) => JSX.Element;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6JA;AAA2C;AACzC;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAqB;AAGvB;AAAoB;AAEhB;AAEA;AACE;AACA;AAAc;AAChB;AACF;AACuB;AAGzB;AACG;AAAiB;AACf;AAC6D;AAC/C;AACJ;AACG;AACR;AAEH;AAAsB;AAI/B;AAEA;AAAyC;AACvC;AACA;AACA;AAEF;AACE;AAEA;AACE;AAAqB;AAGvB;AACE;AAAsB;AAGxB;AACG;AAA2B;AAA0B;AACnD;AAAiB;AACf;AAA0B;AACxB;AAC6D;AAC/C;AACJ;AACG;AACR;AAEH;AAAoB;AAMjC;AAEA;AACE;AACG;AAAoC;AAElC;AAAK;AAGZ;AAEA;AAAoC;AAEpC;AACE;AACG;AAAwC;AACtC;AAA4C;AAExC;AACM;AACK;AACH;AAEN;AACC;AACU;AAEX;AACC;AACU;AAOxB;AAEA;AACE;AACG;AAAuB;AAAsB;AAIlD;AAEA;AAAmD;AACxC;AACW;AAEtB;AAEA;AAA4B;AAKxB;AACE;AACA;AACA;AACW;AACX;AACmB;AACnB;AACA;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AAEA;AACA;AAAmB;AAC4B;AAClB;AAE7B;AACA;AACA;AACA;AAAuC;AAIjC;AACJ;AACA;AAGF;AACE;AAAqB;AAGvB;AACE;AAAsB;AAGxB;AAA0B;AAEtB;AAEA;AACE;AAAyB;AAC3B;AACF;AAC2B;AAG7B;AAAoB;AAEhB;AAEA;AACE;AAAA;AAGF;AACE;AAAyB;AAC3B;AACF;AACoC;AAGtC;AAAmB;AAEf;AAEA;AACE;AAAA;AAGF;AAEA;AACE;AAAwB;AAC1B;AACF;AACsD;AAGxD;AACG;AACY;AACT;AACA;AACF;AACO;AACH;AACC;AAC4B;AACxB;AACD;AAEP;AACW;AACD;AACM;AACf;AACU;AACV;AACY;AACL;AAGN;AAAc;AACZ;AAAc;AAEV;AACU;AACC;AAGb;AACU;AACW;AACV;AAIb;AAAc;AAGR;AACY;AACA;AAAwB;AAAQ;AAE1C;AAAmC;AAAmB;AACpD;AACc;AACJ;AACC;AACF;AACM;AAWhC;AAGN;AAQO;AAAiB;AAEpB;AACE;AACA;AACA;AACA;AACA;AACG;AAIL;AACA;AACA;AAEA;AAA4B;AAExB;AAEA;AACE;AAAA;AAGF;AACE;AAAY;AACV;AACA;AACc;AACf;AAED;AAAc;AACZ;AACc;AACf;AAED;AAAa;AACG;AACS;AACxB;AACH;AACF;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF;AAGF;AAEK;AACmB;AAClB;AACO;AAEN;AAAwB;AAAY;AAEzC;AAGN;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var overrides = require('../overrides.js');
|
|
6
|
+
require('../primitives/Comment/index.js');
|
|
7
|
+
require('../primitives/Composer/index.js');
|
|
8
|
+
require('../primitives/Composer/contexts.js');
|
|
9
|
+
require('../primitives/EmojiPicker/index.js');
|
|
10
|
+
var Timestamp = require('../primitives/Timestamp.js');
|
|
11
|
+
var classNames = require('../utils/class-names.js');
|
|
12
|
+
var List = require('./internal/List.js');
|
|
13
|
+
var User = require('./internal/User.js');
|
|
14
|
+
|
|
15
|
+
const AUTHORS_TRUNCATE = 3;
|
|
16
|
+
const HistoryVersionSummary = React.forwardRef(({ version, selected, className, ...props }, forwardedRef) => {
|
|
17
|
+
const $ = overrides.useOverrides();
|
|
18
|
+
return /* @__PURE__ */ React.createElement("button", {
|
|
19
|
+
...props,
|
|
20
|
+
className: classNames.classNames("lb-root lb-history-version-summary", className),
|
|
21
|
+
ref: forwardedRef,
|
|
22
|
+
"data-selected": selected ? "" : void 0
|
|
23
|
+
}, /* @__PURE__ */ React.createElement(Timestamp.Timestamp, {
|
|
24
|
+
locale: $.locale,
|
|
25
|
+
date: version.createdAt,
|
|
26
|
+
className: "lb-date lb-history-version-summary-date"
|
|
27
|
+
}), /* @__PURE__ */ React.createElement("span", {
|
|
28
|
+
className: "lb-history-version-summary-authors"
|
|
29
|
+
}, /* @__PURE__ */ React.createElement(List.List, {
|
|
30
|
+
values: version.authors.map((author) => /* @__PURE__ */ React.createElement(User.User, {
|
|
31
|
+
key: author.id,
|
|
32
|
+
userId: author.id,
|
|
33
|
+
replaceSelf: true
|
|
34
|
+
})),
|
|
35
|
+
formatRemaining: $.LIST_REMAINING_USERS,
|
|
36
|
+
truncate: AUTHORS_TRUNCATE,
|
|
37
|
+
locale: $.locale
|
|
38
|
+
})));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
exports.HistoryVersionSummary = HistoryVersionSummary;
|
|
42
|
+
//# sourceMappingURL=HistoryVersionSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistoryVersionSummary.js","sources":["../../src/components/HistoryVersionSummary.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HistoryVersion } from \"@liveblocks/core\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport React, { forwardRef } from \"react\";\n\nimport { useOverrides } from \"../overrides\";\nimport { Timestamp } from \"../primitives\";\nimport { classNames } from \"../utils/class-names\";\nimport { List } from \"./internal/List\";\nimport { User } from \"./internal/User\";\n\nconst AUTHORS_TRUNCATE = 3;\n\nexport interface HistoryVersionSummaryProps\n extends ComponentPropsWithoutRef<\"button\"> {\n version: HistoryVersion;\n selected?: boolean;\n}\n\n/**\n * Displays some information about a version.\n *\n * @example\n * <HistoryVersionSummary version={version} />\n */\nexport const HistoryVersionSummary = forwardRef<\n HTMLButtonElement,\n HistoryVersionSummaryProps\n>(({ version, selected, className, ...props }, forwardedRef) => {\n const $ = useOverrides();\n\n return (\n <button\n {...props}\n className={classNames(\"lb-root lb-history-version-summary\", className)}\n ref={forwardedRef}\n data-selected={selected ? \"\" : undefined}\n >\n <Timestamp\n locale={$.locale}\n date={version.createdAt}\n className=\"lb-date lb-history-version-summary-date\"\n />\n <span className=\"lb-history-version-summary-authors\">\n <List\n values={version.authors.map((author) => (\n <User key={author.id} userId={author.id} replaceSelf />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={AUTHORS_TRUNCATE}\n locale={$.locale}\n />\n </span>\n </button>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAYA;AAca;AAIX;AAEA;AACG;AACK;AACiE;AAChE;AAC0B;AAE9B;AACW;AACI;AACJ;AAEX;AAAe;AACb;AAEI;AAAiB;AAAmB;AAAe;AACrD;AACkB;AACT;AACA;AAKpB;;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React__default, { forwardRef } from 'react';
|
|
3
|
+
import { useOverrides } from '../overrides.mjs';
|
|
4
|
+
import '../primitives/Comment/index.mjs';
|
|
5
|
+
import '../primitives/Composer/index.mjs';
|
|
6
|
+
import '../primitives/Composer/contexts.mjs';
|
|
7
|
+
import '../primitives/EmojiPicker/index.mjs';
|
|
8
|
+
import { Timestamp } from '../primitives/Timestamp.mjs';
|
|
9
|
+
import { classNames } from '../utils/class-names.mjs';
|
|
10
|
+
import { List } from './internal/List.mjs';
|
|
11
|
+
import { User } from './internal/User.mjs';
|
|
12
|
+
|
|
13
|
+
const AUTHORS_TRUNCATE = 3;
|
|
14
|
+
const HistoryVersionSummary = forwardRef(({ version, selected, className, ...props }, forwardedRef) => {
|
|
15
|
+
const $ = useOverrides();
|
|
16
|
+
return /* @__PURE__ */ React__default.createElement("button", {
|
|
17
|
+
...props,
|
|
18
|
+
className: classNames("lb-root lb-history-version-summary", className),
|
|
19
|
+
ref: forwardedRef,
|
|
20
|
+
"data-selected": selected ? "" : void 0
|
|
21
|
+
}, /* @__PURE__ */ React__default.createElement(Timestamp, {
|
|
22
|
+
locale: $.locale,
|
|
23
|
+
date: version.createdAt,
|
|
24
|
+
className: "lb-date lb-history-version-summary-date"
|
|
25
|
+
}), /* @__PURE__ */ React__default.createElement("span", {
|
|
26
|
+
className: "lb-history-version-summary-authors"
|
|
27
|
+
}, /* @__PURE__ */ React__default.createElement(List, {
|
|
28
|
+
values: version.authors.map((author) => /* @__PURE__ */ React__default.createElement(User, {
|
|
29
|
+
key: author.id,
|
|
30
|
+
userId: author.id,
|
|
31
|
+
replaceSelf: true
|
|
32
|
+
})),
|
|
33
|
+
formatRemaining: $.LIST_REMAINING_USERS,
|
|
34
|
+
truncate: AUTHORS_TRUNCATE,
|
|
35
|
+
locale: $.locale
|
|
36
|
+
})));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { HistoryVersionSummary };
|
|
40
|
+
//# sourceMappingURL=HistoryVersionSummary.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistoryVersionSummary.mjs","sources":["../../src/components/HistoryVersionSummary.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HistoryVersion } from \"@liveblocks/core\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport React, { forwardRef } from \"react\";\n\nimport { useOverrides } from \"../overrides\";\nimport { Timestamp } from \"../primitives\";\nimport { classNames } from \"../utils/class-names\";\nimport { List } from \"./internal/List\";\nimport { User } from \"./internal/User\";\n\nconst AUTHORS_TRUNCATE = 3;\n\nexport interface HistoryVersionSummaryProps\n extends ComponentPropsWithoutRef<\"button\"> {\n version: HistoryVersion;\n selected?: boolean;\n}\n\n/**\n * Displays some information about a version.\n *\n * @example\n * <HistoryVersionSummary version={version} />\n */\nexport const HistoryVersionSummary = forwardRef<\n HTMLButtonElement,\n HistoryVersionSummaryProps\n>(({ version, selected, className, ...props }, forwardedRef) => {\n const $ = useOverrides();\n\n return (\n <button\n {...props}\n className={classNames(\"lb-root lb-history-version-summary\", className)}\n ref={forwardedRef}\n data-selected={selected ? \"\" : undefined}\n >\n <Timestamp\n locale={$.locale}\n date={version.createdAt}\n className=\"lb-date lb-history-version-summary-date\"\n />\n <span className=\"lb-history-version-summary-authors\">\n <List\n values={version.authors.map((author) => (\n <User key={author.id} userId={author.id} replaceSelf />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={AUTHORS_TRUNCATE}\n locale={$.locale}\n />\n </span>\n </button>\n );\n});\n"],"names":[],"mappings":";;;;;;;;;;;;AAYA;AAca;AAIX;AAEA;AACG;AACK;AACiE;AAChE;AAC0B;AAE9B;AACW;AACI;AACJ;AAEX;AAAe;AACb;AAEI;AAAiB;AAAmB;AAAe;AACrD;AACkB;AACT;AACA;AAKpB;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var classNames = require('../utils/class-names.js');
|
|
6
|
+
|
|
7
|
+
const HistoryVersionSummaryList = React.forwardRef(({ children, className, ...props }, forwardedRef) => {
|
|
8
|
+
return /* @__PURE__ */ React.createElement("ol", {
|
|
9
|
+
className: classNames.classNames(
|
|
10
|
+
"lb-root lb-history-version-summary-list",
|
|
11
|
+
className
|
|
12
|
+
),
|
|
13
|
+
...props,
|
|
14
|
+
ref: forwardedRef
|
|
15
|
+
}, React.Children.map(children, (child, index) => /* @__PURE__ */ React.createElement("li", {
|
|
16
|
+
key: index,
|
|
17
|
+
className: "lb-history-version-summary-list-item"
|
|
18
|
+
}, child)));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
exports.HistoryVersionSummaryList = HistoryVersionSummaryList;
|
|
22
|
+
//# sourceMappingURL=HistoryVersionSummaryList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistoryVersionSummaryList.js","sources":["../../src/components/HistoryVersionSummaryList.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport React, { Children, forwardRef } from \"react\";\n\nimport { classNames } from \"../utils/class-names\";\n\nexport type HistoryVersionSummaryListProps = ComponentPropsWithoutRef<\"ol\">;\n\n/**\n * Displays versions summaries as a list.\n *\n * @example\n * <HistoryVersionSummaryList>\n * {versions.map((version) => (\n * <HistoryVersionSummary key={version.id} version={version} />\n * ))}\n * </HistoryVersionSummaryList>\n */\nexport const HistoryVersionSummaryList = forwardRef<\n HTMLOListElement,\n HistoryVersionSummaryListProps\n>(({ children, className, ...props }, forwardedRef) => {\n return (\n <ol\n className={classNames(\n \"lb-root lb-history-version-summary-list\",\n className\n )}\n {...props}\n ref={forwardedRef}\n >\n {Children.map(children, (child, index) => (\n <li key={index} className=\"lb-history-version-summary-list-item\">\n {child}\n </li>\n ))}\n </ol>\n );\n});\n"],"names":[],"mappings":";;;;;;AAmBa;AAIX;AACG;AACY;AACT;AACA;AACF;AACI;AACC;AAGF;AAAQ;AAAiB;AAMlC;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React__default, { forwardRef, Children } from 'react';
|
|
3
|
+
import { classNames } from '../utils/class-names.mjs';
|
|
4
|
+
|
|
5
|
+
const HistoryVersionSummaryList = forwardRef(({ children, className, ...props }, forwardedRef) => {
|
|
6
|
+
return /* @__PURE__ */ React__default.createElement("ol", {
|
|
7
|
+
className: classNames(
|
|
8
|
+
"lb-root lb-history-version-summary-list",
|
|
9
|
+
className
|
|
10
|
+
),
|
|
11
|
+
...props,
|
|
12
|
+
ref: forwardedRef
|
|
13
|
+
}, Children.map(children, (child, index) => /* @__PURE__ */ React__default.createElement("li", {
|
|
14
|
+
key: index,
|
|
15
|
+
className: "lb-history-version-summary-list-item"
|
|
16
|
+
}, child)));
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export { HistoryVersionSummaryList };
|
|
20
|
+
//# sourceMappingURL=HistoryVersionSummaryList.mjs.map
|