mirror of
https://github.com/docmost/docmost
synced 2025-03-28 21:13:28 +00:00
Fix: Ensure only one emoji list appears (#572)
* Fix: Ensure only one emoji list appears * fix: refactor logic * remove unused file node-id-atoms * small fix * align with Mantine UI * close emoji picker on escape * translate string --------- Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
This commit is contained in:
parent
59b514fa26
commit
f7efb6c2c9
@ -1,14 +1,14 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import {
|
||||
ActionIcon,
|
||||
Popover,
|
||||
Button,
|
||||
useMantineColorScheme,
|
||||
} from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const Picker = React.lazy(() => import('@emoji-mart/react'));
|
||||
} from "@mantine/core";
|
||||
import { useClickOutside, useDisclosure, useWindowEvent } from "@mantine/hooks";
|
||||
import { Suspense } from "react";
|
||||
const Picker = React.lazy(() => import("@emoji-mart/react"));
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export interface EmojiPickerInterface {
|
||||
onEmojiSelect: (emoji: any) => void;
|
||||
@ -23,8 +23,26 @@ function EmojiPicker({
|
||||
removeEmojiAction,
|
||||
readOnly,
|
||||
}: EmojiPickerInterface) {
|
||||
const { t } = useTranslation();
|
||||
const [opened, handlers] = useDisclosure(false);
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
const [target, setTarget] = useState<HTMLElement | null>(null);
|
||||
const [dropdown, setDropdown] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
useClickOutside(
|
||||
() => handlers.close(),
|
||||
["mousedown", "touchstart"],
|
||||
[dropdown, target],
|
||||
);
|
||||
|
||||
// We need this because the default Mantine popover closeOnEscape does not work
|
||||
useWindowEvent("keydown", (event) => {
|
||||
if (opened && event.key === "Escape") {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
handlers.close();
|
||||
}
|
||||
});
|
||||
|
||||
const handleEmojiSelect = (emoji) => {
|
||||
onEmojiSelect(emoji);
|
||||
@ -43,16 +61,17 @@ function EmojiPicker({
|
||||
width={332}
|
||||
position="bottom"
|
||||
disabled={readOnly}
|
||||
closeOnEscape={true}
|
||||
>
|
||||
<Popover.Target>
|
||||
<Popover.Target ref={setTarget}>
|
||||
<ActionIcon c="gray" variant="transparent" onClick={handlers.toggle}>
|
||||
{icon}
|
||||
</ActionIcon>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown bg="000" style={{ border: 'none' }}>
|
||||
<Popover.Dropdown bg="000" style={{ border: "none" }} ref={setDropdown}>
|
||||
<Suspense fallback={null}>
|
||||
<Picker
|
||||
data={async () => (await import('@emoji-mart/data')).default}
|
||||
data={async () => (await import("@emoji-mart/data")).default}
|
||||
onEmojiSelect={handleEmojiSelect}
|
||||
perLine={8}
|
||||
skinTonePosition="search"
|
||||
@ -64,14 +83,14 @@ function EmojiPicker({
|
||||
c="gray"
|
||||
size="xs"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
position: "absolute",
|
||||
zIndex: 2,
|
||||
bottom: '1rem',
|
||||
right: '1rem',
|
||||
bottom: "1rem",
|
||||
right: "1rem",
|
||||
}}
|
||||
onClick={handleRemoveEmoji}
|
||||
>
|
||||
Remove
|
||||
{t("Remove")}
|
||||
</Button>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
|
@ -15,7 +15,8 @@ import {
|
||||
IconChevronDown,
|
||||
IconChevronRight,
|
||||
IconDotsVertical,
|
||||
IconFileDescription, IconFileExport,
|
||||
IconFileDescription,
|
||||
IconFileExport,
|
||||
IconLink,
|
||||
IconPlus,
|
||||
IconPointFilled,
|
||||
@ -140,13 +141,13 @@ export default function SpaceTree({ spaceId, readOnly }: SpaceTreeProps) {
|
||||
flatTreeItems = [
|
||||
...flatTreeItems,
|
||||
...children.filter(
|
||||
(child) => !flatTreeItems.some((item) => item.id === child.id)
|
||||
(child) => !flatTreeItems.some((item) => item.id === child.id),
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
const fetchPromises = ancestors.map((ancestor) =>
|
||||
fetchAndUpdateChildren(ancestor)
|
||||
fetchAndUpdateChildren(ancestor),
|
||||
);
|
||||
|
||||
// Wait for all fetch operations to complete
|
||||
@ -160,7 +161,7 @@ export default function SpaceTree({ spaceId, readOnly }: SpaceTreeProps) {
|
||||
const updatedTree = appendNodeChildren(
|
||||
data,
|
||||
rootChild.id,
|
||||
rootChild.children
|
||||
rootChild.children,
|
||||
);
|
||||
setData(updatedTree);
|
||||
|
||||
@ -255,7 +256,7 @@ function Node({ node, style, dragHandle, tree }: NodeRendererProps<any>) {
|
||||
const updatedTreeData = appendNodeChildren(
|
||||
treeData,
|
||||
node.data.id,
|
||||
childrenTree
|
||||
childrenTree,
|
||||
);
|
||||
|
||||
setTreeData(updatedTreeData);
|
||||
@ -468,9 +469,7 @@ function NodeMenu({ node, treeApi }: NodeMenuProps) {
|
||||
|
||||
<Menu.Item
|
||||
c="red"
|
||||
leftSection={
|
||||
<IconTrash size={16} />
|
||||
}
|
||||
leftSection={<IconTrash size={16} />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
Loading…
x
Reference in New Issue
Block a user