@selfcommunity/react-ui 0.7.5-alpha.2 → 0.7.5-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/lib/cjs/components/Composer/Composer.js +34 -4
  2. package/lib/cjs/components/Editor/Editor.js +1 -1
  3. package/lib/cjs/components/Editor/plugins/LexicalRichTextPlugin.d.ts +6 -0
  4. package/lib/cjs/components/Editor/plugins/LexicalRichTextPlugin.js +43 -0
  5. package/lib/cjs/components/Editor/shared/useCanShowPlaceholder.d.ts +9 -0
  6. package/lib/cjs/components/Editor/shared/useCanShowPlaceholder.js +27 -0
  7. package/lib/cjs/components/Editor/shared/useDecorators.d.ts +16 -0
  8. package/lib/cjs/components/Editor/shared/useDecorators.js +41 -0
  9. package/lib/cjs/components/Editor/shared/useEditorFocus.d.ts +2 -0
  10. package/lib/cjs/components/Editor/shared/useEditorFocus.js +20 -0
  11. package/lib/cjs/components/Editor/shared/useRichTextSetup.d.ts +9 -0
  12. package/lib/cjs/components/Editor/shared/useRichTextSetup.js +13 -0
  13. package/lib/cjs/components/UserProfileHeader/UserProfileHeader.js +5 -1
  14. package/lib/esm/components/Composer/Composer.js +34 -4
  15. package/lib/esm/components/Editor/Editor.js +1 -1
  16. package/lib/esm/components/Editor/plugins/LexicalRichTextPlugin.d.ts +6 -0
  17. package/lib/esm/components/Editor/plugins/LexicalRichTextPlugin.js +38 -0
  18. package/lib/esm/components/Editor/shared/useCanShowPlaceholder.d.ts +9 -0
  19. package/lib/esm/components/Editor/shared/useCanShowPlaceholder.js +23 -0
  20. package/lib/esm/components/Editor/shared/useDecorators.d.ts +16 -0
  21. package/lib/esm/components/Editor/shared/useDecorators.js +36 -0
  22. package/lib/esm/components/Editor/shared/useEditorFocus.d.ts +2 -0
  23. package/lib/esm/components/Editor/shared/useEditorFocus.js +17 -0
  24. package/lib/esm/components/Editor/shared/useRichTextSetup.d.ts +9 -0
  25. package/lib/esm/components/Editor/shared/useRichTextSetup.js +9 -0
  26. package/lib/esm/components/UserProfileHeader/UserProfileHeader.js +5 -1
  27. package/lib/umd/871.js +2 -0
  28. package/lib/umd/react-ui.js +1 -1
  29. package/package.json +2 -2
  30. package/lib/umd/92.js +0 -2
  31. /package/lib/umd/{92.js.LICENSE.txt → 871.js.LICENSE.txt} +0 -0
@@ -172,6 +172,7 @@ function Composer(inProps) {
172
172
  // REFS
173
173
  const dialogRef = (0, react_1.useRef)();
174
174
  const unloadRef = (0, react_1.useRef)(false);
175
+ const pointerStartY = (0, react_1.useRef)(null);
175
176
  // Create a ref for medias because of state update error on chunk upload
176
177
  const mediasRef = (0, react_1.useRef)({ medias });
177
178
  mediasRef.current = { medias };
@@ -224,15 +225,44 @@ function Composer(inProps) {
224
225
  window.onbeforeunload = null;
225
226
  }
226
227
  }, [state, canSubmit]);
228
+ /**
229
+ * On iOS, since it is not possible to anchor meadiaObject actions
230
+ * to the bottom of the viewport, detect 'pan' gesture to close the
231
+ * soft keyboard on device and show actions
232
+ */
227
233
  (0, react_1.useEffect)(() => {
228
234
  if (!dialogRef.current || !isIOS) {
229
235
  return;
230
236
  }
231
- const handleBlur = () => {
232
- dialogRef.current.focus();
237
+ /**
238
+ * On touchStart event save the initial Y
239
+ * @param event
240
+ */
241
+ const handleTouchStart = (event) => {
242
+ pointerStartY.current = event.touches[0].clientY;
243
+ };
244
+ /**
245
+ * Perform blur only if gesture is a pan (bottom direction)
246
+ * @param event
247
+ */
248
+ const handleTouchmove = (event) => {
249
+ const currentY = event.touches[0].clientY;
250
+ const deltaY = currentY - pointerStartY.current;
251
+ pointerStartY.current = currentY;
252
+ if (deltaY > 0) {
253
+ dialogRef.current.focus();
254
+ }
255
+ };
256
+ /**
257
+ * Attach touchstart, touchmove necessary to detect the pan gesture
258
+ */
259
+ dialogRef.current.addEventListener('touchstart', handleTouchStart);
260
+ dialogRef.current.addEventListener('touchmove', handleTouchmove);
261
+ return () => {
262
+ var _a, _b;
263
+ (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('touchstart', handleTouchStart);
264
+ (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('touchmove', handleTouchmove);
233
265
  };
234
- dialogRef.current.addEventListener('touchstart', handleBlur);
235
- return () => { var _a; return (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('touchstart', handleBlur); };
236
266
  }, [dialogRef.current, isIOS]);
237
267
  /* Handlers */
238
268
  const handleAddLayer = (0, react_1.useCallback)((layer) => setLayer(layer), []);
@@ -11,7 +11,7 @@ const nodes_1 = tslib_1.__importDefault(require("./nodes"));
11
11
  const LexicalComposer_1 = require("@lexical/react/LexicalComposer");
12
12
  const LexicalContentEditable_1 = require("@lexical/react/LexicalContentEditable");
13
13
  const LexicalHistoryPlugin_1 = require("@lexical/react/LexicalHistoryPlugin");
14
- const LexicalRichTextPlugin_1 = require("@lexical/react/LexicalRichTextPlugin");
14
+ const LexicalRichTextPlugin_1 = require("./plugins/LexicalRichTextPlugin");
15
15
  const LexicalErrorBoundary_1 = tslib_1.__importDefault(require("@lexical/react/LexicalErrorBoundary"));
16
16
  const LexicalHorizontalRulePlugin_1 = require("@lexical/react/LexicalHorizontalRulePlugin");
17
17
  const plugins_1 = require("./plugins");
@@ -0,0 +1,6 @@
1
+ import { ErrorBoundaryType } from '../shared/useDecorators';
2
+ export declare function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary }: {
3
+ contentEditable: JSX.Element;
4
+ placeholder: ((isEditable: boolean) => null | JSX.Element) | null | JSX.Element;
5
+ ErrorBoundary: ErrorBoundaryType;
6
+ }): JSX.Element;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RichTextPlugin = void 0;
4
+ const tslib_1 = require("tslib");
5
+ /**
6
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
7
+ *
8
+ * This source code is licensed under the MIT license found in the
9
+ * LICENSE file in the root directory of this source tree.
10
+ *
11
+ */
12
+ const React = tslib_1.__importStar(require("react"));
13
+ const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
14
+ const useLexicalEditable_1 = tslib_1.__importDefault(require("@lexical/react/useLexicalEditable"));
15
+ const useDecorators_1 = require("../shared/useDecorators");
16
+ const useEditorFocus_1 = require("../shared/useEditorFocus");
17
+ const useCanShowPlaceholder_1 = require("../shared/useCanShowPlaceholder");
18
+ const useRichTextSetup_1 = require("../shared/useRichTextSetup");
19
+ function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary }) {
20
+ const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
21
+ const decorators = (0, useDecorators_1.useDecorators)(editor, ErrorBoundary);
22
+ (0, useRichTextSetup_1.useRichTextSetup)(editor);
23
+ return (React.createElement(React.Fragment, null,
24
+ contentEditable,
25
+ React.createElement(Placeholder, { content: placeholder }),
26
+ decorators));
27
+ }
28
+ exports.RichTextPlugin = RichTextPlugin;
29
+ function Placeholder({ content }) {
30
+ const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
31
+ const showPlaceholder = (0, useCanShowPlaceholder_1.useCanShowPlaceholder)(editor);
32
+ const editable = (0, useLexicalEditable_1.default)();
33
+ const hasFocus = (0, useEditorFocus_1.useEditorFocus)();
34
+ if (!showPlaceholder || hasFocus) {
35
+ return null;
36
+ }
37
+ if (typeof content === 'function') {
38
+ return content(editable);
39
+ }
40
+ else {
41
+ return content;
42
+ }
43
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ export declare function useCanShowPlaceholder(editor: LexicalEditor): boolean;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useCanShowPlaceholder = void 0;
4
+ const text_1 = require("@lexical/text");
5
+ const utils_1 = require("@lexical/utils");
6
+ const react_1 = require("react");
7
+ const react_core_1 = require("@selfcommunity/react-core");
8
+ function canShowPlaceholderFromCurrentEditorState(editor) {
9
+ return editor.getEditorState().read((0, text_1.$canShowPlaceholderCurry)(editor.isComposing()));
10
+ }
11
+ function useCanShowPlaceholder(editor) {
12
+ const [canShowPlaceholder, setCanShowPlaceholder] = (0, react_1.useState)(() => canShowPlaceholderFromCurrentEditorState(editor));
13
+ (0, react_core_1.useIsomorphicLayoutEffect)(() => {
14
+ function resetCanShowPlaceholder() {
15
+ const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
16
+ setCanShowPlaceholder(currentCanShowPlaceholder);
17
+ }
18
+ resetCanShowPlaceholder();
19
+ return (0, utils_1.mergeRegister)(editor.registerUpdateListener(() => {
20
+ resetCanShowPlaceholder();
21
+ }), editor.registerEditableListener(() => {
22
+ resetCanShowPlaceholder();
23
+ }));
24
+ }, [editor]);
25
+ return canShowPlaceholder;
26
+ }
27
+ exports.useCanShowPlaceholder = useCanShowPlaceholder;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ import * as React from 'react';
10
+ declare type ErrorBoundaryProps = {
11
+ children: JSX.Element;
12
+ onError: (error: Error) => void;
13
+ };
14
+ export declare type ErrorBoundaryType = React.ComponentClass<ErrorBoundaryProps> | React.FC<ErrorBoundaryProps>;
15
+ export declare function useDecorators(editor: LexicalEditor, ErrorBoundary: ErrorBoundaryType): Array<JSX.Element>;
16
+ export {};
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDecorators = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = require("react");
6
+ const React = tslib_1.__importStar(require("react"));
7
+ const react_dom_1 = require("react-dom");
8
+ const react_core_1 = require("@selfcommunity/react-core");
9
+ function useDecorators(editor, ErrorBoundary) {
10
+ const [decorators, setDecorators] = (0, react_1.useState)(() => editor.getDecorators());
11
+ // Subscribe to changes
12
+ (0, react_core_1.useIsomorphicLayoutEffect)(() => {
13
+ return editor.registerDecoratorListener((nextDecorators) => {
14
+ (0, react_dom_1.flushSync)(() => {
15
+ setDecorators(nextDecorators);
16
+ });
17
+ });
18
+ }, [editor]);
19
+ (0, react_1.useEffect)(() => {
20
+ // If the content editable mounts before the subscription is added, then
21
+ // nothing will be rendered on initial pass. We can get around that by
22
+ // ensuring that we set the value.
23
+ setDecorators(editor.getDecorators());
24
+ }, [editor]);
25
+ // Return decorators defined as React Portals
26
+ return (0, react_1.useMemo)(() => {
27
+ const decoratedPortals = [];
28
+ const decoratorKeys = Object.keys(decorators);
29
+ for (let i = 0; i < decoratorKeys.length; i++) {
30
+ const nodeKey = decoratorKeys[i];
31
+ const reactDecorator = (React.createElement(ErrorBoundary, { onError: (e) => editor._onError(e) },
32
+ React.createElement(react_1.Suspense, { fallback: null }, decorators[nodeKey])));
33
+ const element = editor.getElementByKey(nodeKey);
34
+ if (element !== null) {
35
+ decoratedPortals.push((0, react_dom_1.createPortal)(reactDecorator, element, nodeKey));
36
+ }
37
+ }
38
+ return decoratedPortals;
39
+ }, [ErrorBoundary, decorators, editor]);
40
+ }
41
+ exports.useDecorators = useDecorators;
@@ -0,0 +1,2 @@
1
+ declare const useEditorFocus: () => boolean;
2
+ export { useEditorFocus };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useEditorFocus = void 0;
4
+ const react_1 = require("react");
5
+ const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
6
+ const lexical_1 = require("lexical");
7
+ const useEditorFocus = () => {
8
+ const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
9
+ const [hasFocus, setFocus] = (0, react_1.useState)(false);
10
+ (0, react_1.useEffect)(() => editor.registerCommand(lexical_1.BLUR_COMMAND, () => {
11
+ setFocus(false);
12
+ return false;
13
+ }, lexical_1.COMMAND_PRIORITY_LOW), []);
14
+ (0, react_1.useEffect)(() => editor.registerCommand(lexical_1.FOCUS_COMMAND, () => {
15
+ setFocus(true);
16
+ return false;
17
+ }, lexical_1.COMMAND_PRIORITY_LOW), []);
18
+ return hasFocus;
19
+ };
20
+ exports.useEditorFocus = useEditorFocus;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ export declare function useRichTextSetup(editor: LexicalEditor): void;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRichTextSetup = void 0;
4
+ const dragon_1 = require("@lexical/dragon");
5
+ const rich_text_1 = require("@lexical/rich-text");
6
+ const utils_1 = require("@lexical/utils");
7
+ const react_core_1 = require("@selfcommunity/react-core");
8
+ function useRichTextSetup(editor) {
9
+ (0, react_core_1.useIsomorphicLayoutEffect)(() => {
10
+ return (0, utils_1.mergeRegister)((0, rich_text_1.registerRichText)(editor), (0, dragon_1.registerDragonSupport)(editor));
11
+ }, [editor]);
12
+ }
13
+ exports.useRichTextSetup = useRichTextSetup;
@@ -11,6 +11,7 @@ const Skeleton_1 = tslib_1.__importDefault(require("./Skeleton"));
11
11
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
12
12
  const system_1 = require("@mui/system");
13
13
  const constants_1 = require("./constants");
14
+ const UserAvatar_1 = tslib_1.__importDefault(require("../../shared/UserAvatar"));
14
15
  const classes = {
15
16
  root: `${constants_1.PREFIX}-root`,
16
17
  cover: `${constants_1.PREFIX}-cover`,
@@ -108,9 +109,12 @@ function UserProfileHeader(inProps) {
108
109
  ? { background: `url('${scUser.cover}') center / cover` }
109
110
  : { background: `url('${scPreferences.preferences[react_core_1.SCPreferences.IMAGES_USER_DEFAULT_COVER].value}') center / cover` }));
110
111
  const realName = (isMe && scUserContext.user.real_name) || scUser.real_name;
112
+ const hasBadge = scUser && scUser.community_badge;
111
113
  return (react_1.default.createElement(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className) }, rest),
112
114
  react_1.default.createElement(material_1.Paper, { style: _backgroundCover, classes: { root: classes.cover } },
113
- react_1.default.createElement("img", { src: scUser.avatar ? scUser.avatar : '', className: classes.avatar }),
115
+ react_1.default.createElement(material_1.Box, { className: classes.avatar },
116
+ react_1.default.createElement(UserAvatar_1.default, { hide: !hasBadge },
117
+ react_1.default.createElement("img", { src: scUser.avatar ? scUser.avatar : '' }))),
114
118
  isMe && (react_1.default.createElement(react_1.default.Fragment, null,
115
119
  react_1.default.createElement(ChangePicture_1.default, Object.assign({ iconButton: true, onChange: handleChangeAvatar, className: classes.changePicture }, ChangePictureProps)),
116
120
  react_1.default.createElement("div", { className: classes.changeCover },
@@ -170,6 +170,7 @@ export default function Composer(inProps) {
170
170
  // REFS
171
171
  const dialogRef = useRef();
172
172
  const unloadRef = useRef(false);
173
+ const pointerStartY = useRef(null);
173
174
  // Create a ref for medias because of state update error on chunk upload
174
175
  const mediasRef = useRef({ medias });
175
176
  mediasRef.current = { medias };
@@ -222,15 +223,44 @@ export default function Composer(inProps) {
222
223
  window.onbeforeunload = null;
223
224
  }
224
225
  }, [state, canSubmit]);
226
+ /**
227
+ * On iOS, since it is not possible to anchor meadiaObject actions
228
+ * to the bottom of the viewport, detect 'pan' gesture to close the
229
+ * soft keyboard on device and show actions
230
+ */
225
231
  useEffect(() => {
226
232
  if (!dialogRef.current || !isIOS) {
227
233
  return;
228
234
  }
229
- const handleBlur = () => {
230
- dialogRef.current.focus();
235
+ /**
236
+ * On touchStart event save the initial Y
237
+ * @param event
238
+ */
239
+ const handleTouchStart = (event) => {
240
+ pointerStartY.current = event.touches[0].clientY;
241
+ };
242
+ /**
243
+ * Perform blur only if gesture is a pan (bottom direction)
244
+ * @param event
245
+ */
246
+ const handleTouchmove = (event) => {
247
+ const currentY = event.touches[0].clientY;
248
+ const deltaY = currentY - pointerStartY.current;
249
+ pointerStartY.current = currentY;
250
+ if (deltaY > 0) {
251
+ dialogRef.current.focus();
252
+ }
253
+ };
254
+ /**
255
+ * Attach touchstart, touchmove necessary to detect the pan gesture
256
+ */
257
+ dialogRef.current.addEventListener('touchstart', handleTouchStart);
258
+ dialogRef.current.addEventListener('touchmove', handleTouchmove);
259
+ return () => {
260
+ var _a, _b;
261
+ (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('touchstart', handleTouchStart);
262
+ (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('touchmove', handleTouchmove);
231
263
  };
232
- dialogRef.current.addEventListener('touchstart', handleBlur);
233
- return () => { var _a; return (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('touchstart', handleBlur); };
234
264
  }, [dialogRef.current, isIOS]);
235
265
  /* Handlers */
236
266
  const handleAddLayer = useCallback((layer) => setLayer(layer), []);
@@ -8,7 +8,7 @@ import nodes from './nodes';
8
8
  import { LexicalComposer } from '@lexical/react/LexicalComposer';
9
9
  import { ContentEditable } from '@lexical/react/LexicalContentEditable';
10
10
  import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
11
- import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
11
+ import { RichTextPlugin } from './plugins/LexicalRichTextPlugin';
12
12
  import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
13
13
  import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin';
14
14
  import { AutoLinkPlugin, DefaultHtmlValuePlugin, EmojiPlugin, ImagePlugin, MentionsPlugin, OnChangePlugin } from './plugins';
@@ -0,0 +1,6 @@
1
+ import { ErrorBoundaryType } from '../shared/useDecorators';
2
+ export declare function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary }: {
3
+ contentEditable: JSX.Element;
4
+ placeholder: ((isEditable: boolean) => null | JSX.Element) | null | JSX.Element;
5
+ ErrorBoundary: ErrorBoundaryType;
6
+ }): JSX.Element;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import * as React from 'react';
9
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
10
+ import useLexicalEditable from '@lexical/react/useLexicalEditable';
11
+ import { useDecorators } from '../shared/useDecorators';
12
+ import { useEditorFocus } from '../shared/useEditorFocus';
13
+ import { useCanShowPlaceholder } from '../shared/useCanShowPlaceholder';
14
+ import { useRichTextSetup } from '../shared/useRichTextSetup';
15
+ export function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary }) {
16
+ const [editor] = useLexicalComposerContext();
17
+ const decorators = useDecorators(editor, ErrorBoundary);
18
+ useRichTextSetup(editor);
19
+ return (React.createElement(React.Fragment, null,
20
+ contentEditable,
21
+ React.createElement(Placeholder, { content: placeholder }),
22
+ decorators));
23
+ }
24
+ function Placeholder({ content }) {
25
+ const [editor] = useLexicalComposerContext();
26
+ const showPlaceholder = useCanShowPlaceholder(editor);
27
+ const editable = useLexicalEditable();
28
+ const hasFocus = useEditorFocus();
29
+ if (!showPlaceholder || hasFocus) {
30
+ return null;
31
+ }
32
+ if (typeof content === 'function') {
33
+ return content(editable);
34
+ }
35
+ else {
36
+ return content;
37
+ }
38
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ export declare function useCanShowPlaceholder(editor: LexicalEditor): boolean;
@@ -0,0 +1,23 @@
1
+ import { $canShowPlaceholderCurry } from '@lexical/text';
2
+ import { mergeRegister } from '@lexical/utils';
3
+ import { useState } from 'react';
4
+ import { useIsomorphicLayoutEffect } from '@selfcommunity/react-core';
5
+ function canShowPlaceholderFromCurrentEditorState(editor) {
6
+ return editor.getEditorState().read($canShowPlaceholderCurry(editor.isComposing()));
7
+ }
8
+ export function useCanShowPlaceholder(editor) {
9
+ const [canShowPlaceholder, setCanShowPlaceholder] = useState(() => canShowPlaceholderFromCurrentEditorState(editor));
10
+ useIsomorphicLayoutEffect(() => {
11
+ function resetCanShowPlaceholder() {
12
+ const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
13
+ setCanShowPlaceholder(currentCanShowPlaceholder);
14
+ }
15
+ resetCanShowPlaceholder();
16
+ return mergeRegister(editor.registerUpdateListener(() => {
17
+ resetCanShowPlaceholder();
18
+ }), editor.registerEditableListener(() => {
19
+ resetCanShowPlaceholder();
20
+ }));
21
+ }, [editor]);
22
+ return canShowPlaceholder;
23
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ import * as React from 'react';
10
+ declare type ErrorBoundaryProps = {
11
+ children: JSX.Element;
12
+ onError: (error: Error) => void;
13
+ };
14
+ export declare type ErrorBoundaryType = React.ComponentClass<ErrorBoundaryProps> | React.FC<ErrorBoundaryProps>;
15
+ export declare function useDecorators(editor: LexicalEditor, ErrorBoundary: ErrorBoundaryType): Array<JSX.Element>;
16
+ export {};
@@ -0,0 +1,36 @@
1
+ import { Suspense, useEffect, useMemo, useState } from 'react';
2
+ import * as React from 'react';
3
+ import { createPortal, flushSync } from 'react-dom';
4
+ import { useIsomorphicLayoutEffect } from '@selfcommunity/react-core';
5
+ export function useDecorators(editor, ErrorBoundary) {
6
+ const [decorators, setDecorators] = useState(() => editor.getDecorators());
7
+ // Subscribe to changes
8
+ useIsomorphicLayoutEffect(() => {
9
+ return editor.registerDecoratorListener((nextDecorators) => {
10
+ flushSync(() => {
11
+ setDecorators(nextDecorators);
12
+ });
13
+ });
14
+ }, [editor]);
15
+ useEffect(() => {
16
+ // If the content editable mounts before the subscription is added, then
17
+ // nothing will be rendered on initial pass. We can get around that by
18
+ // ensuring that we set the value.
19
+ setDecorators(editor.getDecorators());
20
+ }, [editor]);
21
+ // Return decorators defined as React Portals
22
+ return useMemo(() => {
23
+ const decoratedPortals = [];
24
+ const decoratorKeys = Object.keys(decorators);
25
+ for (let i = 0; i < decoratorKeys.length; i++) {
26
+ const nodeKey = decoratorKeys[i];
27
+ const reactDecorator = (React.createElement(ErrorBoundary, { onError: (e) => editor._onError(e) },
28
+ React.createElement(Suspense, { fallback: null }, decorators[nodeKey])));
29
+ const element = editor.getElementByKey(nodeKey);
30
+ if (element !== null) {
31
+ decoratedPortals.push(createPortal(reactDecorator, element, nodeKey));
32
+ }
33
+ }
34
+ return decoratedPortals;
35
+ }, [ErrorBoundary, decorators, editor]);
36
+ }
@@ -0,0 +1,2 @@
1
+ declare const useEditorFocus: () => boolean;
2
+ export { useEditorFocus };
@@ -0,0 +1,17 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
3
+ import { BLUR_COMMAND, COMMAND_PRIORITY_LOW, FOCUS_COMMAND } from 'lexical';
4
+ const useEditorFocus = () => {
5
+ const [editor] = useLexicalComposerContext();
6
+ const [hasFocus, setFocus] = useState(false);
7
+ useEffect(() => editor.registerCommand(BLUR_COMMAND, () => {
8
+ setFocus(false);
9
+ return false;
10
+ }, COMMAND_PRIORITY_LOW), []);
11
+ useEffect(() => editor.registerCommand(FOCUS_COMMAND, () => {
12
+ setFocus(true);
13
+ return false;
14
+ }, COMMAND_PRIORITY_LOW), []);
15
+ return hasFocus;
16
+ };
17
+ export { useEditorFocus };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalEditor } from 'lexical';
9
+ export declare function useRichTextSetup(editor: LexicalEditor): void;
@@ -0,0 +1,9 @@
1
+ import { registerDragonSupport } from '@lexical/dragon';
2
+ import { registerRichText } from '@lexical/rich-text';
3
+ import { mergeRegister } from '@lexical/utils';
4
+ import { useIsomorphicLayoutEffect } from '@selfcommunity/react-core';
5
+ export function useRichTextSetup(editor) {
6
+ useIsomorphicLayoutEffect(() => {
7
+ return mergeRegister(registerRichText(editor), registerDragonSupport(editor));
8
+ }, [editor]);
9
+ }
@@ -9,6 +9,7 @@ import UserProfileHeaderSkeleton from './Skeleton';
9
9
  import classNames from 'classnames';
10
10
  import { useThemeProps } from '@mui/system';
11
11
  import { PREFIX } from './constants';
12
+ import UserAvatar from '../../shared/UserAvatar';
12
13
  const classes = {
13
14
  root: `${PREFIX}-root`,
14
15
  cover: `${PREFIX}-cover`,
@@ -106,9 +107,12 @@ export default function UserProfileHeader(inProps) {
106
107
  ? { background: `url('${scUser.cover}') center / cover` }
107
108
  : { background: `url('${scPreferences.preferences[SCPreferences.IMAGES_USER_DEFAULT_COVER].value}') center / cover` }));
108
109
  const realName = (isMe && scUserContext.user.real_name) || scUser.real_name;
110
+ const hasBadge = scUser && scUser.community_badge;
109
111
  return (React.createElement(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest),
110
112
  React.createElement(Paper, { style: _backgroundCover, classes: { root: classes.cover } },
111
- React.createElement("img", { src: scUser.avatar ? scUser.avatar : '', className: classes.avatar }),
113
+ React.createElement(Box, { className: classes.avatar },
114
+ React.createElement(UserAvatar, { hide: !hasBadge },
115
+ React.createElement("img", { src: scUser.avatar ? scUser.avatar : '' }))),
112
116
  isMe && (React.createElement(React.Fragment, null,
113
117
  React.createElement(ChangePicture, Object.assign({ iconButton: true, onChange: handleChangeAvatar, className: classes.changePicture }, ChangePictureProps)),
114
118
  React.createElement("div", { className: classes.changeCover },