@liveblocks/react-ui 2.12.2 → 2.13.0
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/_private/index.d.mts +1 -1
- package/dist/_private/index.d.ts +1 -1
- package/dist/components/Comment.js +2 -0
- package/dist/components/Comment.js.map +1 -1
- package/dist/components/Comment.mjs +2 -0
- package/dist/components/Comment.mjs.map +1 -1
- package/dist/components/Composer.js +74 -6
- package/dist/components/Composer.js.map +1 -1
- package/dist/components/Composer.mjs +77 -9
- package/dist/components/Composer.mjs.map +1 -1
- package/dist/components/HistoryVersionSummary.js +1 -0
- package/dist/components/HistoryVersionSummary.js.map +1 -1
- package/dist/components/HistoryVersionSummary.mjs +1 -0
- package/dist/components/HistoryVersionSummary.mjs.map +1 -1
- package/dist/components/Thread.js +3 -0
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/Thread.mjs +3 -0
- package/dist/components/Thread.mjs.map +1 -1
- package/dist/components/internal/Button.js.map +1 -1
- package/dist/components/internal/Button.mjs.map +1 -1
- package/dist/icons/Bold.js +15 -0
- package/dist/icons/Bold.js.map +1 -0
- package/dist/icons/Bold.mjs +13 -0
- package/dist/icons/Bold.mjs.map +1 -0
- package/dist/icons/Code.js +15 -0
- package/dist/icons/Code.js.map +1 -0
- package/dist/icons/Code.mjs +13 -0
- package/dist/icons/Code.mjs.map +1 -0
- package/dist/icons/Italic.js +15 -0
- package/dist/icons/Italic.js.map +1 -0
- package/dist/icons/Italic.mjs +13 -0
- package/dist/icons/Italic.mjs.map +1 -0
- package/dist/icons/Strikethrough.js +15 -0
- package/dist/icons/Strikethrough.js.map +1 -0
- package/dist/icons/Strikethrough.mjs +13 -0
- package/dist/icons/Strikethrough.mjs.map +1 -0
- package/dist/index.d.mts +94 -103
- package/dist/index.d.ts +94 -103
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/overrides.js +15 -0
- package/dist/overrides.js.map +1 -1
- package/dist/overrides.mjs +15 -0
- package/dist/overrides.mjs.map +1 -1
- package/dist/primitives/Composer/contexts.js +12 -0
- package/dist/primitives/Composer/contexts.js.map +1 -1
- package/dist/primitives/Composer/contexts.mjs +11 -1
- package/dist/primitives/Composer/contexts.mjs.map +1 -1
- package/dist/primitives/Composer/index.js +251 -76
- package/dist/primitives/Composer/index.js.map +1 -1
- package/dist/primitives/Composer/index.mjs +239 -85
- package/dist/primitives/Composer/index.mjs.map +1 -1
- package/dist/primitives/Composer/utils.js +94 -21
- package/dist/primitives/Composer/utils.js.map +1 -1
- package/dist/primitives/Composer/utils.mjs +91 -20
- package/dist/primitives/Composer/utils.mjs.map +1 -1
- package/dist/primitives/index.d.mts +57 -1
- package/dist/primitives/index.d.ts +57 -1
- package/dist/slate/plugins/auto-formatting.js +1 -2
- package/dist/slate/plugins/auto-formatting.js.map +1 -1
- package/dist/slate/plugins/auto-formatting.mjs +1 -2
- package/dist/slate/plugins/auto-formatting.mjs.map +1 -1
- package/dist/slate/plugins/auto-links.js +3 -2
- package/dist/slate/plugins/auto-links.js.map +1 -1
- package/dist/slate/plugins/auto-links.mjs +2 -1
- package/dist/slate/plugins/auto-links.mjs.map +1 -1
- package/dist/slate/plugins/custom-links.js +3 -2
- package/dist/slate/plugins/custom-links.js.map +1 -1
- package/dist/slate/plugins/custom-links.mjs +2 -1
- package/dist/slate/plugins/custom-links.mjs.map +1 -1
- package/dist/slate/plugins/mentions.js +3 -4
- package/dist/slate/plugins/mentions.js.map +1 -1
- package/dist/slate/plugins/mentions.mjs +4 -5
- package/dist/slate/plugins/mentions.mjs.map +1 -1
- package/dist/slate/utils/marks.js +27 -8
- package/dist/slate/utils/marks.js.map +1 -1
- package/dist/slate/utils/marks.mjs +27 -10
- package/dist/slate/utils/marks.mjs.map +1 -1
- package/dist/utils/use-observable.js +15 -0
- package/dist/utils/use-observable.js.map +1 -0
- package/dist/utils/use-observable.mjs +13 -0
- package/dist/utils/use-observable.mjs.map +1 -0
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +4 -4
- package/src/styles/constants.css +1 -1
- package/src/styles/index.css +70 -9
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/slate/utils/is-selection-collapsed.js +0 -10
- package/dist/slate/utils/is-selection-collapsed.js.map +0 -1
- package/dist/slate/utils/is-selection-collapsed.mjs +0 -8
- package/dist/slate/utils/is-selection-collapsed.mjs.map +0 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var reactDom = require('@floating-ui/react-dom');
|
|
5
4
|
var core = require('@liveblocks/core');
|
|
6
5
|
var _private = require('@liveblocks/react/_private');
|
|
7
6
|
var reactSlot = require('@radix-ui/react-slot');
|
|
7
|
+
var TogglePrimitive = require('@radix-ui/react-toggle');
|
|
8
8
|
var React = require('react');
|
|
9
9
|
var slate = require('slate');
|
|
10
10
|
var slateHistory = require('slate-history');
|
|
11
11
|
var slateReact = require('slate-react');
|
|
12
12
|
var config = require('../../config.js');
|
|
13
|
-
var constants = require('../../constants.js');
|
|
14
13
|
var autoFormatting = require('../../slate/plugins/auto-formatting.js');
|
|
15
14
|
var autoLinks = require('../../slate/plugins/auto-links.js');
|
|
16
15
|
var customLinks = require('../../slate/plugins/custom-links.js');
|
|
@@ -29,14 +28,36 @@ var useId = require('../../utils/use-id.js');
|
|
|
29
28
|
var useIndex = require('../../utils/use-index.js');
|
|
30
29
|
var useInitial = require('../../utils/use-initial.js');
|
|
31
30
|
var useLayoutEffect = require('../../utils/use-layout-effect.js');
|
|
31
|
+
var useObservable = require('../../utils/use-observable.js');
|
|
32
32
|
var useRefs = require('../../utils/use-refs.js');
|
|
33
33
|
var utils$1 = require('../Comment/utils.js');
|
|
34
34
|
var contexts = require('./contexts.js');
|
|
35
35
|
var utils = require('./utils.js');
|
|
36
36
|
|
|
37
|
+
function _interopNamespaceDefault(e) {
|
|
38
|
+
var n = Object.create(null);
|
|
39
|
+
if (e) {
|
|
40
|
+
Object.keys(e).forEach(function (k) {
|
|
41
|
+
if (k !== 'default') {
|
|
42
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
43
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () { return e[k]; }
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
n.default = e;
|
|
51
|
+
return Object.freeze(n);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var TogglePrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TogglePrimitive);
|
|
55
|
+
|
|
37
56
|
const MENTION_SUGGESTIONS_POSITION = "top";
|
|
57
|
+
const FLOATING_TOOLBAR_POSITION = "top";
|
|
38
58
|
const COMPOSER_MENTION_NAME = "ComposerMention";
|
|
39
59
|
const COMPOSER_LINK_NAME = "ComposerLink";
|
|
60
|
+
const COMPOSER_FLOATING_TOOLBAR_NAME = "ComposerFloatingToolbar";
|
|
40
61
|
const COMPOSER_SUGGESTIONS_NAME = "ComposerSuggestions";
|
|
41
62
|
const COMPOSER_SUGGESTIONS_LIST_NAME = "ComposerSuggestionsList";
|
|
42
63
|
const COMPOSER_SUGGESTIONS_LIST_ITEM_NAME = "ComposerSuggestionsListItem";
|
|
@@ -44,6 +65,7 @@ const COMPOSER_SUBMIT_NAME = "ComposerSubmit";
|
|
|
44
65
|
const COMPOSER_EDITOR_NAME = "ComposerEditor";
|
|
45
66
|
const COMPOSER_ATTACH_FILES_NAME = "ComposerAttachFiles";
|
|
46
67
|
const COMPOSER_ATTACHMENTS_DROP_AREA_NAME = "ComposerAttachmentsDropArea";
|
|
68
|
+
const COMPOSER_MARK_TOGGLE_NAME = "ComposerMarkToggle";
|
|
47
69
|
const COMPOSER_FORM_NAME = "ComposerForm";
|
|
48
70
|
const emptyCommentBody = {
|
|
49
71
|
version: 1,
|
|
@@ -107,52 +129,18 @@ function ComposerEditorMentionSuggestionsWrapper({
|
|
|
107
129
|
selectedUserId,
|
|
108
130
|
setSelectedUserId,
|
|
109
131
|
mentionDraft,
|
|
132
|
+
setMentionDraft,
|
|
110
133
|
onItemSelect,
|
|
111
134
|
position = MENTION_SUGGESTIONS_POSITION,
|
|
112
135
|
dir,
|
|
113
136
|
MentionSuggestions
|
|
114
137
|
}) {
|
|
115
138
|
const editor = slateReact.useSlateStatic();
|
|
139
|
+
const { onEditorChange } = contexts.useComposerEditorContext();
|
|
116
140
|
const { isFocused } = contexts.useComposer();
|
|
117
|
-
const [content, setContent] = React.useState(null);
|
|
118
|
-
const [contentZIndex, setContentZIndex] = React.useState();
|
|
119
|
-
const contentRef = React.useCallback(setContent, [setContent]);
|
|
120
141
|
const { portalContainer } = config.useLiveblocksUIConfig();
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
padding: constants.FLOATING_ELEMENT_COLLISION_PADDING
|
|
124
|
-
};
|
|
125
|
-
return {
|
|
126
|
-
strategy: "fixed",
|
|
127
|
-
placement: utils.getPlacementFromPosition(position, dir),
|
|
128
|
-
middleware: [
|
|
129
|
-
reactDom.flip({ ...detectOverflowOptions, crossAxis: false }),
|
|
130
|
-
reactDom.hide(detectOverflowOptions),
|
|
131
|
-
reactDom.shift({
|
|
132
|
-
...detectOverflowOptions,
|
|
133
|
-
limiter: reactDom.limitShift()
|
|
134
|
-
}),
|
|
135
|
-
reactDom.size({
|
|
136
|
-
...detectOverflowOptions,
|
|
137
|
-
apply({ availableWidth, availableHeight, elements }) {
|
|
138
|
-
elements.floating.style.setProperty(
|
|
139
|
-
"--lb-composer-suggestions-available-width",
|
|
140
|
-
`${availableWidth}px`
|
|
141
|
-
);
|
|
142
|
-
elements.floating.style.setProperty(
|
|
143
|
-
"--lb-composer-suggestions-available-height",
|
|
144
|
-
`${availableHeight}px`
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
})
|
|
148
|
-
],
|
|
149
|
-
whileElementsMounted: (...args) => {
|
|
150
|
-
return reactDom.autoUpdate(...args, {
|
|
151
|
-
animationFrame: true
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
}, [position, dir]);
|
|
142
|
+
const [contentRef, contentZIndex] = utils.useContentZIndex();
|
|
143
|
+
const isOpen = isFocused && mentionDraft?.range !== void 0 && userIds !== void 0;
|
|
156
144
|
const {
|
|
157
145
|
refs: { setReference, setFloating },
|
|
158
146
|
strategy,
|
|
@@ -160,25 +148,24 @@ function ComposerEditorMentionSuggestionsWrapper({
|
|
|
160
148
|
placement,
|
|
161
149
|
x,
|
|
162
150
|
y
|
|
163
|
-
} =
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
151
|
+
} = utils.useFloatingWithOptions({
|
|
152
|
+
position,
|
|
153
|
+
dir,
|
|
154
|
+
alignment: "start",
|
|
155
|
+
open: isOpen
|
|
156
|
+
});
|
|
157
|
+
useObservable.useObservable(onEditorChange, () => {
|
|
158
|
+
setMentionDraft(mentions.getMentionDraftAtSelection(editor));
|
|
159
|
+
});
|
|
169
160
|
useLayoutEffect.useLayoutEffect(() => {
|
|
170
161
|
if (!mentionDraft) {
|
|
162
|
+
setReference(null);
|
|
171
163
|
return;
|
|
172
164
|
}
|
|
173
165
|
const domRange = getDomRange.getDOMRange(editor, mentionDraft.range);
|
|
174
|
-
|
|
175
|
-
setReference({
|
|
176
|
-
getBoundingClientRect: () => domRange.getBoundingClientRect(),
|
|
177
|
-
getClientRects: () => domRange.getClientRects()
|
|
178
|
-
});
|
|
179
|
-
}
|
|
166
|
+
setReference(domRange ?? null);
|
|
180
167
|
}, [setReference, editor, mentionDraft]);
|
|
181
|
-
return /* @__PURE__ */ React.createElement(Persist.Persist, null,
|
|
168
|
+
return /* @__PURE__ */ React.createElement(Persist.Persist, null, isOpen ? /* @__PURE__ */ React.createElement(contexts.ComposerSuggestionsContext.Provider, {
|
|
182
169
|
value: {
|
|
183
170
|
id,
|
|
184
171
|
itemId,
|
|
@@ -205,6 +192,126 @@ function ComposerEditorMentionSuggestionsWrapper({
|
|
|
205
192
|
selectedUserId
|
|
206
193
|
}))) : null);
|
|
207
194
|
}
|
|
195
|
+
function ComposerEditorFloatingToolbarWrapper({
|
|
196
|
+
id,
|
|
197
|
+
position = FLOATING_TOOLBAR_POSITION,
|
|
198
|
+
dir,
|
|
199
|
+
FloatingToolbar,
|
|
200
|
+
hasFloatingToolbarRange,
|
|
201
|
+
setHasFloatingToolbarRange
|
|
202
|
+
}) {
|
|
203
|
+
const editor = slateReact.useSlateStatic();
|
|
204
|
+
const { onEditorChange } = contexts.useComposerEditorContext();
|
|
205
|
+
const { isFocused } = contexts.useComposer();
|
|
206
|
+
const { portalContainer } = config.useLiveblocksUIConfig();
|
|
207
|
+
const [contentRef, contentZIndex] = utils.useContentZIndex();
|
|
208
|
+
const [isPointerDown, setPointerDown] = React.useState(false);
|
|
209
|
+
const isOpen = isFocused && !isPointerDown && hasFloatingToolbarRange;
|
|
210
|
+
const {
|
|
211
|
+
refs: { setReference, setFloating },
|
|
212
|
+
strategy,
|
|
213
|
+
isPositioned,
|
|
214
|
+
placement,
|
|
215
|
+
x,
|
|
216
|
+
y
|
|
217
|
+
} = utils.useFloatingWithOptions({
|
|
218
|
+
type: "range",
|
|
219
|
+
position,
|
|
220
|
+
dir,
|
|
221
|
+
alignment: "center",
|
|
222
|
+
open: isOpen
|
|
223
|
+
});
|
|
224
|
+
useLayoutEffect.useLayoutEffect(() => {
|
|
225
|
+
if (!isFocused) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const handlePointerDown = () => setPointerDown(true);
|
|
229
|
+
const handlePointerUp = () => setPointerDown(false);
|
|
230
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
231
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
232
|
+
return () => {
|
|
233
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
234
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
235
|
+
};
|
|
236
|
+
}, [isFocused]);
|
|
237
|
+
useObservable.useObservable(onEditorChange, () => {
|
|
238
|
+
setReference(null);
|
|
239
|
+
requestAnimationFrame(() => {
|
|
240
|
+
const domSelection = window.getSelection();
|
|
241
|
+
if (!editor.selection || slate.Range.isCollapsed(editor.selection) || !domSelection || !domSelection.rangeCount) {
|
|
242
|
+
setHasFloatingToolbarRange(false);
|
|
243
|
+
setReference(null);
|
|
244
|
+
} else {
|
|
245
|
+
setHasFloatingToolbarRange(true);
|
|
246
|
+
const domRange = domSelection.getRangeAt(0);
|
|
247
|
+
setReference(domRange);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
return /* @__PURE__ */ React.createElement(Persist.Persist, null, isOpen ? /* @__PURE__ */ React.createElement(contexts.ComposerFloatingToolbarContext.Provider, {
|
|
252
|
+
value: {
|
|
253
|
+
id,
|
|
254
|
+
placement,
|
|
255
|
+
dir,
|
|
256
|
+
ref: contentRef
|
|
257
|
+
}
|
|
258
|
+
}, /* @__PURE__ */ React.createElement(Portal.Portal, {
|
|
259
|
+
ref: setFloating,
|
|
260
|
+
container: portalContainer,
|
|
261
|
+
style: {
|
|
262
|
+
position: strategy,
|
|
263
|
+
top: 0,
|
|
264
|
+
left: 0,
|
|
265
|
+
transform: isPositioned ? `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)` : "translate3d(0, -200%, 0)",
|
|
266
|
+
minWidth: "max-content",
|
|
267
|
+
zIndex: contentZIndex
|
|
268
|
+
}
|
|
269
|
+
}, /* @__PURE__ */ React.createElement(FloatingToolbar, null))) : null);
|
|
270
|
+
}
|
|
271
|
+
const ComposerFloatingToolbar = React.forwardRef(({ children, onPointerDown, style, asChild, ...props }, forwardedRef) => {
|
|
272
|
+
const [isPresent] = Persist.usePersist();
|
|
273
|
+
const ref = React.useRef(null);
|
|
274
|
+
const {
|
|
275
|
+
id,
|
|
276
|
+
ref: contentRef,
|
|
277
|
+
placement,
|
|
278
|
+
dir
|
|
279
|
+
} = contexts.useComposerFloatingToolbarContext(COMPOSER_FLOATING_TOOLBAR_NAME);
|
|
280
|
+
const mergedRefs = useRefs.useRefs(forwardedRef, contentRef, ref);
|
|
281
|
+
const [side, align] = React.useMemo(
|
|
282
|
+
() => utils.getSideAndAlignFromFloatingPlacement(placement),
|
|
283
|
+
[placement]
|
|
284
|
+
);
|
|
285
|
+
const Component = asChild ? reactSlot.Slot : "div";
|
|
286
|
+
Persist.useAnimationPersist(ref);
|
|
287
|
+
const handlePointerDown = React.useCallback(
|
|
288
|
+
(event) => {
|
|
289
|
+
onPointerDown?.(event);
|
|
290
|
+
event.preventDefault();
|
|
291
|
+
event.stopPropagation();
|
|
292
|
+
},
|
|
293
|
+
[onPointerDown]
|
|
294
|
+
);
|
|
295
|
+
return /* @__PURE__ */ React.createElement(Component, {
|
|
296
|
+
dir,
|
|
297
|
+
role: "toolbar",
|
|
298
|
+
id,
|
|
299
|
+
"aria-label": "Floating toolbar",
|
|
300
|
+
...props,
|
|
301
|
+
onPointerDown: handlePointerDown,
|
|
302
|
+
"data-state": isPresent ? "open" : "closed",
|
|
303
|
+
"data-side": side,
|
|
304
|
+
"data-align": align,
|
|
305
|
+
style: {
|
|
306
|
+
display: "flex",
|
|
307
|
+
flexDirection: "row",
|
|
308
|
+
maxWidth: "var(--lb-composer-floating-available-width)",
|
|
309
|
+
overflowX: "auto",
|
|
310
|
+
...style
|
|
311
|
+
},
|
|
312
|
+
ref: mergedRefs
|
|
313
|
+
}, children);
|
|
314
|
+
});
|
|
208
315
|
function ComposerEditorElement({
|
|
209
316
|
Mention,
|
|
210
317
|
Link,
|
|
@@ -292,7 +399,7 @@ const ComposerSuggestions = React.forwardRef(({ children, style, asChild, ...pro
|
|
|
292
399
|
} = contexts.useComposerSuggestionsContext(COMPOSER_SUGGESTIONS_NAME);
|
|
293
400
|
const mergedRefs = useRefs.useRefs(forwardedRef, contentRef, ref);
|
|
294
401
|
const [side, align] = React.useMemo(
|
|
295
|
-
() => utils.
|
|
402
|
+
() => utils.getSideAndAlignFromFloatingPlacement(placement),
|
|
296
403
|
[placement]
|
|
297
404
|
);
|
|
298
405
|
const Component = asChild ? reactSlot.Slot : "div";
|
|
@@ -306,7 +413,7 @@ const ComposerSuggestions = React.forwardRef(({ children, style, asChild, ...pro
|
|
|
306
413
|
style: {
|
|
307
414
|
display: "flex",
|
|
308
415
|
flexDirection: "column",
|
|
309
|
-
maxHeight: "var(--lb-composer-
|
|
416
|
+
maxHeight: "var(--lb-composer-floating-available-height)",
|
|
310
417
|
overflowY: "auto",
|
|
311
418
|
...style
|
|
312
419
|
},
|
|
@@ -418,10 +525,12 @@ const ComposerEditor = React.forwardRef(
|
|
|
418
525
|
dir,
|
|
419
526
|
...props
|
|
420
527
|
}, forwardedRef) => {
|
|
421
|
-
const
|
|
528
|
+
const client = _private.useClientOrNull();
|
|
529
|
+
const { editor, validate, setFocused, onEditorChange, roomId } = contexts.useComposerEditorContext();
|
|
422
530
|
const {
|
|
423
531
|
submit,
|
|
424
532
|
focus,
|
|
533
|
+
blur,
|
|
425
534
|
select,
|
|
426
535
|
canSubmit,
|
|
427
536
|
isDisabled: isComposerDisabled,
|
|
@@ -432,10 +541,12 @@ const ComposerEditor = React.forwardRef(
|
|
|
432
541
|
const initialEditorValue = React.useMemo(() => {
|
|
433
542
|
return utils.commentBodyToComposerBody(initialBody);
|
|
434
543
|
}, [initialBody]);
|
|
435
|
-
const { Link, Mention, MentionSuggestions } = React.useMemo(
|
|
544
|
+
const { Link, Mention, MentionSuggestions, FloatingToolbar } = React.useMemo(
|
|
436
545
|
() => ({ ...defaultEditorComponents, ...components }),
|
|
437
546
|
[components]
|
|
438
547
|
);
|
|
548
|
+
const [hasFloatingToolbarRange, setHasFloatingToolbarRange] = React.useState(false);
|
|
549
|
+
const hasResolveMentionSuggestions = client ? client[core.kInternal].resolveMentionSuggestions !== void 0 : true;
|
|
439
550
|
const [mentionDraft, setMentionDraft] = React.useState();
|
|
440
551
|
const mentionSuggestions = _private.useMentionSuggestions(
|
|
441
552
|
roomId,
|
|
@@ -448,6 +559,10 @@ const ComposerEditor = React.forwardRef(
|
|
|
448
559
|
setSelectedMentionSuggestionIndex
|
|
449
560
|
] = useIndex.useIndex(0, mentionSuggestions?.length ?? 0);
|
|
450
561
|
const id = useId.useId();
|
|
562
|
+
const floatingToolbarId = React.useMemo(
|
|
563
|
+
() => `liveblocks-floating-toolbar-${id}`,
|
|
564
|
+
[id]
|
|
565
|
+
);
|
|
451
566
|
const suggestionsListId = React.useMemo(
|
|
452
567
|
() => `liveblocks-suggestions-list-${id}`,
|
|
453
568
|
[id]
|
|
@@ -469,9 +584,9 @@ const ComposerEditor = React.forwardRef(
|
|
|
469
584
|
const handleChange = React.useCallback(
|
|
470
585
|
(value) => {
|
|
471
586
|
validate(value);
|
|
472
|
-
|
|
587
|
+
onEditorChange.notify();
|
|
473
588
|
},
|
|
474
|
-
[
|
|
589
|
+
[validate, onEditorChange]
|
|
475
590
|
);
|
|
476
591
|
const createMention = React.useCallback(
|
|
477
592
|
(userId) => {
|
|
@@ -517,9 +632,15 @@ const ComposerEditor = React.forwardRef(
|
|
|
517
632
|
setSelectedMentionSuggestionIndex(0);
|
|
518
633
|
}
|
|
519
634
|
} else {
|
|
635
|
+
if (hasFloatingToolbarRange) {
|
|
636
|
+
if (isKey.isKey(event, "Escape")) {
|
|
637
|
+
event.preventDefault();
|
|
638
|
+
setHasFloatingToolbarRange(false);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
520
641
|
if (isKey.isKey(event, "Escape")) {
|
|
521
642
|
event.preventDefault();
|
|
522
|
-
|
|
643
|
+
blur();
|
|
523
644
|
}
|
|
524
645
|
if (isKey.isKey(event, "Enter", { shift: false })) {
|
|
525
646
|
event.preventDefault();
|
|
@@ -550,16 +671,18 @@ const ComposerEditor = React.forwardRef(
|
|
|
550
671
|
}
|
|
551
672
|
},
|
|
552
673
|
[
|
|
553
|
-
|
|
554
|
-
editor,
|
|
555
|
-
canSubmit,
|
|
674
|
+
onKeyDown,
|
|
556
675
|
mentionDraft,
|
|
557
676
|
mentionSuggestions,
|
|
558
|
-
|
|
559
|
-
|
|
677
|
+
hasFloatingToolbarRange,
|
|
678
|
+
editor,
|
|
560
679
|
setNextSelectedMentionSuggestionIndex,
|
|
561
680
|
setPreviousSelectedMentionSuggestionIndex,
|
|
681
|
+
selectedMentionSuggestionIndex,
|
|
682
|
+
createMention,
|
|
562
683
|
setSelectedMentionSuggestionIndex,
|
|
684
|
+
blur,
|
|
685
|
+
canSubmit,
|
|
563
686
|
submit
|
|
564
687
|
]
|
|
565
688
|
);
|
|
@@ -594,7 +717,7 @@ const ComposerEditor = React.forwardRef(
|
|
|
594
717
|
},
|
|
595
718
|
[setSelectedMentionSuggestionIndex, mentionSuggestions]
|
|
596
719
|
);
|
|
597
|
-
const
|
|
720
|
+
const additionalProps = React.useMemo(
|
|
598
721
|
() => mentionDraft ? {
|
|
599
722
|
role: "combobox",
|
|
600
723
|
"aria-autocomplete": "list",
|
|
@@ -603,23 +726,28 @@ const ComposerEditor = React.forwardRef(
|
|
|
603
726
|
"aria-activedescendant": suggestionsListItemId(
|
|
604
727
|
selectedMentionSuggestionUserId
|
|
605
728
|
)
|
|
729
|
+
} : hasFloatingToolbarRange ? {
|
|
730
|
+
"aria-haspopup": true,
|
|
731
|
+
"aria-controls": floatingToolbarId
|
|
606
732
|
} : {},
|
|
607
733
|
[
|
|
608
734
|
mentionDraft,
|
|
609
735
|
suggestionsListId,
|
|
610
736
|
suggestionsListItemId,
|
|
611
|
-
selectedMentionSuggestionUserId
|
|
737
|
+
selectedMentionSuggestionUserId,
|
|
738
|
+
hasFloatingToolbarRange,
|
|
739
|
+
floatingToolbarId
|
|
612
740
|
]
|
|
613
741
|
);
|
|
614
742
|
React.useImperativeHandle(forwardedRef, () => {
|
|
615
743
|
return slateReact.ReactEditor.toDOMNode(editor, editor);
|
|
616
744
|
}, [editor]);
|
|
617
|
-
|
|
745
|
+
useLayoutEffect.useLayoutEffect(() => {
|
|
618
746
|
if (autoFocus) {
|
|
619
747
|
focus();
|
|
620
748
|
}
|
|
621
749
|
}, [autoFocus, editor, focus]);
|
|
622
|
-
|
|
750
|
+
useLayoutEffect.useLayoutEffect(() => {
|
|
623
751
|
if (isFocused && editor.selection === null) {
|
|
624
752
|
select();
|
|
625
753
|
}
|
|
@@ -635,7 +763,7 @@ const ComposerEditor = React.forwardRef(
|
|
|
635
763
|
"aria-label": "Composer editor",
|
|
636
764
|
"data-focused": isFocused || void 0,
|
|
637
765
|
"data-disabled": isDisabled || void 0,
|
|
638
|
-
...
|
|
766
|
+
...additionalProps,
|
|
639
767
|
...props,
|
|
640
768
|
readOnly: isDisabled,
|
|
641
769
|
disabled: isDisabled,
|
|
@@ -645,9 +773,10 @@ const ComposerEditor = React.forwardRef(
|
|
|
645
773
|
renderElement,
|
|
646
774
|
renderLeaf: ComposerEditorLeaf,
|
|
647
775
|
renderPlaceholder: ComposerEditorPlaceholder
|
|
648
|
-
}), /* @__PURE__ */ React.createElement(ComposerEditorMentionSuggestionsWrapper, {
|
|
776
|
+
}), hasResolveMentionSuggestions && /* @__PURE__ */ React.createElement(ComposerEditorMentionSuggestionsWrapper, {
|
|
649
777
|
dir,
|
|
650
778
|
mentionDraft,
|
|
779
|
+
setMentionDraft,
|
|
651
780
|
selectedUserId: selectedMentionSuggestionUserId,
|
|
652
781
|
setSelectedUserId: setSelectedMentionSuggestionUserId,
|
|
653
782
|
userIds: mentionSuggestions,
|
|
@@ -655,6 +784,12 @@ const ComposerEditor = React.forwardRef(
|
|
|
655
784
|
itemId: suggestionsListItemId,
|
|
656
785
|
onItemSelect: createMention,
|
|
657
786
|
MentionSuggestions
|
|
787
|
+
}), FloatingToolbar && /* @__PURE__ */ React.createElement(ComposerEditorFloatingToolbarWrapper, {
|
|
788
|
+
dir,
|
|
789
|
+
id: floatingToolbarId,
|
|
790
|
+
hasFloatingToolbarRange,
|
|
791
|
+
setHasFloatingToolbarRange,
|
|
792
|
+
FloatingToolbar
|
|
658
793
|
}));
|
|
659
794
|
}
|
|
660
795
|
);
|
|
@@ -713,6 +848,7 @@ const ComposerForm = React.forwardRef(
|
|
|
713
848
|
const canSubmit = React.useMemo(() => {
|
|
714
849
|
return !isEmpty$1 && !isUploadingAttachments;
|
|
715
850
|
}, [isEmpty$1, isUploadingAttachments]);
|
|
851
|
+
const [marks$1, setMarks] = React.useState(marks.getMarks);
|
|
716
852
|
const ref = React.useRef(null);
|
|
717
853
|
const mergedRefs = useRefs.useRefs(forwardedRef, ref);
|
|
718
854
|
const fileInputRef = React.useRef(null);
|
|
@@ -751,6 +887,7 @@ const ComposerForm = React.forwardRef(
|
|
|
751
887
|
pasteFilesAsAttachments
|
|
752
888
|
})
|
|
753
889
|
);
|
|
890
|
+
const onEditorChange = useInitial.useInitial(core.makeEventSource);
|
|
754
891
|
const validate = React.useCallback(
|
|
755
892
|
(value) => {
|
|
756
893
|
setEmpty(isEmpty.isEmpty(editor, value));
|
|
@@ -776,10 +913,7 @@ const ComposerForm = React.forwardRef(
|
|
|
776
913
|
});
|
|
777
914
|
}, [editor]);
|
|
778
915
|
const select = React.useCallback(() => {
|
|
779
|
-
slate.Transforms.select(editor,
|
|
780
|
-
anchor: slate.Editor.end(editor, []),
|
|
781
|
-
focus: slate.Editor.end(editor, [])
|
|
782
|
-
});
|
|
916
|
+
slate.Transforms.select(editor, slate.Editor.end(editor, []));
|
|
783
917
|
}, [editor]);
|
|
784
918
|
const focus = React.useCallback(
|
|
785
919
|
(resetSelection = true) => {
|
|
@@ -885,11 +1019,21 @@ const ComposerForm = React.forwardRef(
|
|
|
885
1019
|
const stopPropagation = React.useCallback((event) => {
|
|
886
1020
|
event.stopPropagation();
|
|
887
1021
|
}, []);
|
|
1022
|
+
const toggleMark = React.useCallback(
|
|
1023
|
+
(mark) => {
|
|
1024
|
+
marks.toggleMark(editor, mark);
|
|
1025
|
+
},
|
|
1026
|
+
[editor]
|
|
1027
|
+
);
|
|
1028
|
+
useObservable.useObservable(onEditorChange, () => {
|
|
1029
|
+
setMarks(marks.getMarks(editor));
|
|
1030
|
+
});
|
|
888
1031
|
return /* @__PURE__ */ React.createElement(contexts.ComposerEditorContext.Provider, {
|
|
889
1032
|
value: {
|
|
890
1033
|
editor,
|
|
891
1034
|
validate,
|
|
892
1035
|
setFocused,
|
|
1036
|
+
onEditorChange,
|
|
893
1037
|
roomId
|
|
894
1038
|
}
|
|
895
1039
|
}, /* @__PURE__ */ React.createElement(contexts.ComposerAttachmentsContext.Provider, {
|
|
@@ -915,7 +1059,9 @@ const ComposerForm = React.forwardRef(
|
|
|
915
1059
|
insertText,
|
|
916
1060
|
attachments,
|
|
917
1061
|
attachFiles,
|
|
918
|
-
removeAttachment
|
|
1062
|
+
removeAttachment,
|
|
1063
|
+
toggleMark,
|
|
1064
|
+
marks: marks$1
|
|
919
1065
|
}
|
|
920
1066
|
}, /* @__PURE__ */ React.createElement(Component, {
|
|
921
1067
|
...props,
|
|
@@ -995,10 +1141,36 @@ const ComposerAttachmentsDropArea = React.forwardRef(
|
|
|
995
1141
|
});
|
|
996
1142
|
}
|
|
997
1143
|
);
|
|
1144
|
+
const ComposerMarkToggle = React.forwardRef(
|
|
1145
|
+
({ children, mark, onValueChange, onClick, asChild, ...props }, forwardedRef) => {
|
|
1146
|
+
const Component = asChild ? reactSlot.Slot : "button";
|
|
1147
|
+
const { marks, toggleMark } = contexts.useComposer();
|
|
1148
|
+
const handleClick = React.useCallback(
|
|
1149
|
+
(event) => {
|
|
1150
|
+
onClick?.(event);
|
|
1151
|
+
if (!event.isDefaultPrevented()) {
|
|
1152
|
+
toggleMark(mark);
|
|
1153
|
+
onValueChange?.(mark);
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
[mark, onClick, onValueChange, toggleMark]
|
|
1157
|
+
);
|
|
1158
|
+
return /* @__PURE__ */ React.createElement(TogglePrimitive__namespace.Root, {
|
|
1159
|
+
asChild: true,
|
|
1160
|
+
pressed: marks[mark],
|
|
1161
|
+
onClick: handleClick,
|
|
1162
|
+
...props
|
|
1163
|
+
}, /* @__PURE__ */ React.createElement(Component, {
|
|
1164
|
+
...props,
|
|
1165
|
+
ref: forwardedRef
|
|
1166
|
+
}, children));
|
|
1167
|
+
}
|
|
1168
|
+
);
|
|
998
1169
|
if (process.env.NODE_ENV !== "production") {
|
|
999
1170
|
ComposerAttachFiles.displayName = COMPOSER_ATTACH_FILES_NAME;
|
|
1000
1171
|
ComposerAttachmentsDropArea.displayName = COMPOSER_ATTACHMENTS_DROP_AREA_NAME;
|
|
1001
1172
|
ComposerEditor.displayName = COMPOSER_EDITOR_NAME;
|
|
1173
|
+
ComposerFloatingToolbar.displayName = COMPOSER_FLOATING_TOOLBAR_NAME;
|
|
1002
1174
|
ComposerForm.displayName = COMPOSER_FORM_NAME;
|
|
1003
1175
|
ComposerMention.displayName = COMPOSER_MENTION_NAME;
|
|
1004
1176
|
ComposerLink.displayName = COMPOSER_LINK_NAME;
|
|
@@ -1006,13 +1178,16 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
1006
1178
|
ComposerSuggestions.displayName = COMPOSER_SUGGESTIONS_NAME;
|
|
1007
1179
|
ComposerSuggestionsList.displayName = COMPOSER_SUGGESTIONS_LIST_NAME;
|
|
1008
1180
|
ComposerSuggestionsListItem.displayName = COMPOSER_SUGGESTIONS_LIST_ITEM_NAME;
|
|
1181
|
+
ComposerMarkToggle.displayName = COMPOSER_MARK_TOGGLE_NAME;
|
|
1009
1182
|
}
|
|
1010
1183
|
|
|
1011
1184
|
exports.AttachFiles = ComposerAttachFiles;
|
|
1012
1185
|
exports.AttachmentsDropArea = ComposerAttachmentsDropArea;
|
|
1013
1186
|
exports.Editor = ComposerEditor;
|
|
1187
|
+
exports.FloatingToolbar = ComposerFloatingToolbar;
|
|
1014
1188
|
exports.Form = ComposerForm;
|
|
1015
1189
|
exports.Link = ComposerLink;
|
|
1190
|
+
exports.MarkToggle = ComposerMarkToggle;
|
|
1016
1191
|
exports.Mention = ComposerMention;
|
|
1017
1192
|
exports.Submit = ComposerSubmit;
|
|
1018
1193
|
exports.Suggestions = ComposerSuggestions;
|