/** @jsx createElement */ import { createElement, Fragment, render, FunctionalComponent } from 'preact'; import { StaticStore } from '@app/common/static_store'; import { useEffect, useRef } from 'preact/hooks'; import '@github/text-expander-element'; import styles from './text-expander.module.pcss'; import cx from 'classnames'; import { Theme } from '@app/common/types'; import useTheme from '@app/hooks/useTheme'; type Emoji = { key: string; emoji: string; }; function SuggestionList({ items, theme }: { items: Array; theme: Theme }) { const isDarkTheme = theme === `dark`; const suggesterClass = cx(styles.suggester, { [styles.suggesterDark]: isDarkTheme }); const suggesterItemClass = cx(styles.suggesterItem, { [styles.suggesterItemDark]: isDarkTheme }); return ( ); } function searchEmoji(key: string, text: string, theme: Theme) { return import(/* webpackChunkName: "node-emoji" */ `node-emoji`) .then(nodeEmoji => { if (key === ':') { const emojiList = nodeEmoji.search(text); if (emojiList.length === 0) { return Promise.resolve({ matched: false }); } const fragment = document.createDocumentFragment(); render(, fragment); return Promise.resolve({ matched: true, fragment: fragment.firstChild }); } return Promise.resolve({ matched: false }); }) .catch(() => Promise.resolve({ matched: false })); } type ChangeListerEvent = Event & { detail: { key: string; text: string; provide(value: Promise<{ matched: boolean }>): void; }; }; type ValueListerEvent = Event & { detail: { key: string; value: string; item: HTMLLIElement; }; }; export const TextExpander: FunctionalComponent = ({ children }) => { const expanderRef = useRef(); const theme = useTheme(); useEffect(() => { if (expanderRef.current) { const expander = expanderRef.current; expander.setAttribute(`keys`, ':'); const textExpanderChangeLister: EventListener = (event: Event) => { const { provide, key, text } = (event as ChangeListerEvent).detail; provide(searchEmoji(key, text, theme)); }; const textExpanderValueListener = (event: Event) => { const { key, item } = (event as ValueListerEvent).detail; if (key === ':') { (event as ValueListerEvent).detail.value = `:${item.dataset.value}:`; } }; expander.addEventListener('text-expander-change', textExpanderChangeLister); expander.addEventListener('text-expander-value', textExpanderValueListener); return () => { expander.removeEventListener('text-expander-change', textExpanderChangeLister); expander.removeEventListener('text-expander-value', textExpanderValueListener); }; } return () => {}; }, [theme]); if (StaticStore.config.emoji_enabled) { return {children}; } return {children}; };