feat: Unified icon picker (#7038)
This commit is contained in:
@@ -1,11 +1,7 @@
|
||||
import data, { type Emoji as TEmoji } from "@emoji-mart/data";
|
||||
import { init, Data } from "emoji-mart";
|
||||
import FuzzySearch from "fuzzy-search";
|
||||
import capitalize from "lodash/capitalize";
|
||||
import sortBy from "lodash/sortBy";
|
||||
import React from "react";
|
||||
import { emojiMartToGemoji, snakeCase } from "@shared/editor/lib/emoji";
|
||||
import { isMac } from "@shared/utils/browser";
|
||||
import { search as emojiSearch } from "@shared/utils/emoji";
|
||||
import EmojiMenuItem from "./EmojiMenuItem";
|
||||
import SuggestionsMenu, {
|
||||
Props as SuggestionsMenuProps,
|
||||
@@ -19,13 +15,6 @@ type Emoji = {
|
||||
attrs: { markup: string; "data-name": string };
|
||||
};
|
||||
|
||||
init({
|
||||
data,
|
||||
noCountryFlags: isMac() ? false : undefined,
|
||||
});
|
||||
|
||||
let searcher: FuzzySearch<TEmoji>;
|
||||
|
||||
type Props = Omit<
|
||||
SuggestionsMenuProps<Emoji>,
|
||||
"renderMenuItem" | "items" | "embeds" | "trigger"
|
||||
@@ -34,36 +23,26 @@ type Props = Omit<
|
||||
const EmojiMenu = (props: Props) => {
|
||||
const { search = "" } = props;
|
||||
|
||||
if (!searcher) {
|
||||
searcher = new FuzzySearch(Object.values(Data.emojis), ["search"], {
|
||||
caseSensitive: false,
|
||||
sort: true,
|
||||
});
|
||||
}
|
||||
const items = React.useMemo(
|
||||
() =>
|
||||
emojiSearch({ query: search })
|
||||
.map((item) => {
|
||||
// We snake_case the shortcode for backwards compatability with gemoji to
|
||||
// avoid multiple formats being written into documents.
|
||||
const shortcode = snakeCase(emojiMartToGemoji[item.id] || item.id);
|
||||
const emoji = item.value;
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const n = search.toLowerCase();
|
||||
|
||||
return sortBy(searcher.search(n), (item) => {
|
||||
const nlc = item.name.toLowerCase();
|
||||
return nlc === n ? -1 : nlc.startsWith(n) ? 0 : 1;
|
||||
})
|
||||
.map((item) => {
|
||||
// We snake_case the shortcode for backwards compatability with gemoji to
|
||||
// avoid multiple formats being written into documents.
|
||||
const shortcode = snakeCase(emojiMartToGemoji[item.id] || item.id);
|
||||
const emoji = item.skins[0].native;
|
||||
|
||||
return {
|
||||
name: "emoji",
|
||||
title: emoji,
|
||||
description: capitalize(item.name.toLowerCase()),
|
||||
emoji,
|
||||
attrs: { markup: shortcode, "data-name": shortcode },
|
||||
};
|
||||
})
|
||||
.slice(0, 15);
|
||||
}, [search]);
|
||||
return {
|
||||
name: "emoji",
|
||||
title: emoji,
|
||||
description: capitalize(item.name.toLowerCase()),
|
||||
emoji,
|
||||
attrs: { markup: shortcode, "data-name": shortcode },
|
||||
};
|
||||
})
|
||||
.slice(0, 15),
|
||||
[search]
|
||||
);
|
||||
|
||||
return (
|
||||
<SuggestionsMenu
|
||||
|
||||
@@ -7,6 +7,8 @@ import isMarkdown from "@shared/editor/lib/isMarkdown";
|
||||
import normalizePastedMarkdown from "@shared/editor/lib/markdown/normalize";
|
||||
import { isInCode } from "@shared/editor/queries/isInCode";
|
||||
import { isInList } from "@shared/editor/queries/isInList";
|
||||
import { IconType } from "@shared/types";
|
||||
import { determineIconType } from "@shared/utils/icon";
|
||||
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
|
||||
import { isDocumentUrl, isUrl } from "@shared/utils/urls";
|
||||
import stores from "~/stores";
|
||||
@@ -179,9 +181,12 @@ export default class PasteHandler extends Extension {
|
||||
if (document) {
|
||||
const { hash } = new URL(text);
|
||||
|
||||
const title = `${
|
||||
document.emoji ? document.emoji + " " : ""
|
||||
}${document.titleWithDefault}`;
|
||||
const hasEmoji =
|
||||
determineIconType(document.icon) === IconType.Emoji;
|
||||
|
||||
const title = `${hasEmoji ? document.icon + " " : ""}${
|
||||
document.titleWithDefault
|
||||
}`;
|
||||
insertLink(`${document.path}${hash}`, title);
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user