diff --git a/src/assets/icons/emoji.svg b/src/assets/icons/emoji.svg
new file mode 100644
index 0000000..98dd788
--- /dev/null
+++ b/src/assets/icons/emoji.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/components/Buttons/ButtonGhost.tsx b/src/components/Buttons/ButtonGhost.tsx
new file mode 100644
index 0000000..f6aed61
--- /dev/null
+++ b/src/components/Buttons/ButtonGhost.tsx
@@ -0,0 +1,26 @@
+import { Button } from '@kobalte/core';
+import { Component, JSXElement } from 'solid-js';
+import { hookForDev } from '../../lib/devTools';
+
+import styles from './Buttons.module.scss';
+
+
+const ButtonGhost: Component<{
+ id?: string,
+ onClick?: (e: MouseEvent) => void,
+ children?: JSXElement,
+ disabled?: boolean,
+}> = (props) => {
+ return (
+
+ {props.children}
+
+ )
+}
+
+export default hookForDev(ButtonGhost);
diff --git a/src/components/Buttons/Buttons.module.scss b/src/components/Buttons/Buttons.module.scss
index 37339c2..5cd094d 100644
--- a/src/components/Buttons/Buttons.module.scss
+++ b/src/components/Buttons/Buttons.module.scss
@@ -200,3 +200,21 @@
border: 1px solid var(--text-tertiary);
}
}
+
+
+.ghost {
+ border-radius: 6px;
+ padding-inline: 10px;
+ padding-block: 6px;
+ font-size: 12px;
+ line-height: 16px;
+ font-weight: 700;
+ margin: 0px;
+ color: var(--text-primary);
+ background: none;
+ border: none;
+
+ &:hover {
+ background: none;
+ }
+}
diff --git a/src/components/EmojiPickModal/EmojiPickModal.module.scss b/src/components/EmojiPickModal/EmojiPickModal.module.scss
new file mode 100644
index 0000000..0d32c59
--- /dev/null
+++ b/src/components/EmojiPickModal/EmojiPickModal.module.scss
@@ -0,0 +1,88 @@
+.zapEmojiChangeModal {
+ position: fixed;
+ height: 344px;
+ color: var(--text-secondary);
+ background-color: var(--background-input);
+ border: 1px solid transparent;
+ border-radius: 6px;
+
+ display: flex;
+ flex-direction: column;
+ padding-left: 22px;
+ padding-right: 16px;
+ padding-block: 22px;
+
+ justify-content: flex-start;
+ align-items: center;
+
+ input {
+ display: flex;
+ width: 70%;
+ height: 36px;
+ text-align: left;
+ margin: 0;
+ margin-bottom: 24px;
+ padding-inline: 16px;
+ font-size: 16px;
+ font-weight: 600;
+ line-height: 20px;
+ color: var(--text-primary);
+ background: none;
+ border: none;
+ border-radius: 18px;
+
+ &:focus {
+ background-color: var(--subtile-devider);
+ outline: none;
+ box-shadow: none;
+ }
+
+ &::placeholder {
+ color: var(--text-tertiary);
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 20px;
+ }
+ }
+
+ .title {
+ font-weight: 800;
+ font-size: 18px;
+ line-height: 18px;
+ color: var(--text-secondary);
+ text-transform: uppercase;
+ margin-bottom: 20px;
+ }
+
+ .xClose {
+ background: none;
+ border: none;
+ margin: 0;
+ padding: 0;
+ width: fit-content;
+
+ position: absolute;
+ top: 16px;
+ right: 22px;
+
+ .iconClose {
+ width: 14px;
+ height: 14px;
+ display: inline-block;
+ margin: 0px 0px;
+ background-color: var(--text-secondary);
+ -webkit-mask: url(../../assets/icons/close.svg) no-repeat center;
+ mask: url(../../assets/icons/close.svg) no-repeat center;
+ }
+
+ &:hover {
+ .iconClose {
+ background-color: var(--text-primary);
+ }
+ }
+
+ &:focus {
+ box-shadow: none;
+ }
+ }
+}
diff --git a/src/components/EmojiPickModal/EmojiPickModal.tsx b/src/components/EmojiPickModal/EmojiPickModal.tsx
new file mode 100644
index 0000000..2dd01b1
--- /dev/null
+++ b/src/components/EmojiPickModal/EmojiPickModal.tsx
@@ -0,0 +1,85 @@
+import { Component, createEffect, createSignal, For } from 'solid-js';
+
+import styles from './EmojiPickModal.module.scss';
+import { useSettingsContext } from '../../contexts/SettingsContext';
+import { debounce, isVisibleInContainer, uuidv4 } from '../../utils';
+import { useIntl } from '@cookbook/solid-intl';
+import ConfirmModal from '../ConfirmModal/ConfirmModal';
+import { settings as t } from '../../translations';
+import { hookForDev } from '../../lib/devTools';
+import ButtonLink from '../Buttons/ButtonLink';
+import Modal from '../Modal/Modal';
+
+import emojiSearch from '@jukben/emoji-search';
+import { createStore } from 'solid-js/store';
+import { EmojiOption } from '../../types/primal';
+import ButtonPrimary from '../Buttons/ButtonPrimary';
+import EmojiPicker from '../EmojiPicker/EmojiPicker';
+
+const EmojiPickModal: Component<{
+ id?: string,
+ open: boolean,
+ onClose: (e: MouseEvent | KeyboardEvent) => void,
+ onSelect: (emoji: EmojiOption) => void,
+}> = (props) => {
+
+ const intl = useIntl();
+
+ const [emojiSearchTerm, setEmojiSearchTerm] = createSignal('smile');
+
+ const onKey = (e: KeyboardEvent) => {
+ if (e.code === 'Escape') {
+ props.onClose(e);
+ return;
+ }
+ };
+
+ let emojiInput: HTMLInputElement | undefined;
+
+ createEffect(() => {
+ if (props.open) {
+ window.addEventListener('keydown', onKey);
+ setTimeout(() => {
+ setEmojiSearchTerm(() => 'smile')
+ emojiInput?.focus();
+ }, 10);
+ }
+ else {
+ window.removeEventListener('keydown', onKey);
+ }
+ })
+
+ return (
+ props.onClose(e)}
+ >
+
+
+ {intl.formatMessage(t.zapEmojiFilterTitle)}
+
+
+
+
+
{
+ const target = e.target as HTMLInputElement;
+ setEmojiSearchTerm(() => target.value);
+ }}
+ placeholder={intl.formatMessage(t.zapEmojiFilterPlaceholder)}
+ >
+
+
+
+
+
+ );
+}
+
+export default EmojiPickModal;
diff --git a/src/components/NewNote/EditBox/EditBox.module.scss b/src/components/NewNote/EditBox/EditBox.module.scss
index cb8863b..0da6a6e 100644
--- a/src/components/NewNote/EditBox/EditBox.module.scss
+++ b/src/components/NewNote/EditBox/EditBox.module.scss
@@ -79,6 +79,7 @@
margin-left: 8px;
}
.editorOptions {
+ display: flex;
width: 100%;
.attachIcon {
@@ -93,6 +94,26 @@
background-color: var(--text-secondary);
}
}
+ .emojiIcon {
+ width: 21px;
+ height: 21px;
+ display: inline-block;
+ margin-right: 9px;
+ background-color: var(--text-tertiary);
+ cursor: pointer;
+
+ &:hover {
+ background-color: var(--text-secondary);
+ }
+ }
+
+ >button {
+ width: 26px;
+ height: 21px;
+ padding: 0;
+ margin-block: 0;
+ margin-inline: 8px;
+ }
}
diff --git a/src/components/NewNote/EditBox/EditBox.tsx b/src/components/NewNote/EditBox/EditBox.tsx
index 65321c7..73622a8 100644
--- a/src/components/NewNote/EditBox/EditBox.tsx
+++ b/src/components/NewNote/EditBox/EditBox.tsx
@@ -39,6 +39,9 @@ import { hookForDev } from "../../../lib/devTools";
import ButtonPrimary from "../../Buttons/ButtonPrimary";
import ButtonSecondary from "../../Buttons/ButtonSecondary";
import { useProfileContext } from "../../../contexts/ProfileContext";
+import ButtonTertiary from "../../Buttons/ButtonTertiary";
+import ButtonGhost from "../../Buttons/ButtonGhost";
+import EmojiPickModal from "../../EmojiPickModal/EmojiPickModal";
type AutoSizedTextArea = HTMLTextAreaElement & { _baseScrollHeight: number };
@@ -483,6 +486,9 @@ const EditBox: Component<{
const onEscape = (e: KeyboardEvent) => {
if (e.code === 'Escape') {
+ console.log('ESCAPE: ', isPickingEmoji())
+ if (isPickingEmoji()) return;
+
!isMentioning() && !isEmojiInput() ?
closeEditor() :
closeEmojiAndMentions();
@@ -992,14 +998,14 @@ const EditBox: Component<{
// Get index of the token and insert emoji character
const index = msg.slice(0, cursor).lastIndexOf(':');
- const value = msg.slice(0, index) + emoji.name + msg.slice(cursor);
+ const value = msg.slice(0, index) + `${emoji.name} ` + msg.slice(cursor);
// Reset query, update message and text area value
setMessage(value);
textArea.value = message();
// Calculate new cursor position
- textArea.selectionEnd = index + 1;
+ textArea.selectionEnd = index + 3;
textArea.focus();
setEmojiInput(false);
@@ -1148,6 +1154,30 @@ const EditBox: Component<{
callback && callback();
}
+ const [isPickingEmoji, setIsPickingEmoji] = createSignal(false);
+
+ const addSelectedEmoji = (emoji: EmojiOption) => {
+ if (!textArea || !emoji) {
+ return;
+ }
+
+ const msg = message();
+
+ // Get cursor position to determine insertion point
+ let cursor = textArea.selectionStart;
+
+ // Get index of the token and insert emoji character
+ const value = msg.slice(0, cursor) + `${emoji.name} ` + msg.slice(cursor);
+
+ // Reset query, update message and text area value
+ setMessage(value);
+ textArea.value = message();
+
+ // Calculate new cursor position
+ textArea.selectionEnd = cursor + 3;
+ textArea.focus();
+ };
+
return (
+ {setIsPickingEmoji(true)}}>
+
+
+
+ {
+ setTimeout(() => {
+ setIsPickingEmoji(false);
+ textArea?.focus();
+ }, 100)
+ }}
+ onSelect={addSelectedEmoji}
+ />
)
}
diff --git a/src/components/SettingsZap/SettingsZap.module.scss b/src/components/SettingsZap/SettingsZap.module.scss
index a2461af..0b7f467 100644
--- a/src/components/SettingsZap/SettingsZap.module.scss
+++ b/src/components/SettingsZap/SettingsZap.module.scss
@@ -111,92 +111,3 @@
justify-content: flex-start;
margin-top: 36px;
}
-
-.zapEmojiChangeModal {
- position: fixed;
- height: 344px;
- color: var(--text-secondary);
- background-color: var(--background-input);
- border: 1px solid transparent;
- border-radius: 6px;
-
- display: flex;
- flex-direction: column;
- padding-left: 22px;
- padding-right: 16px;
- padding-block: 22px;
-
- justify-content: flex-start;
- align-items: center;
-
- input {
- display: flex;
- width: 70%;
- height: 36px;
- text-align: left;
- margin: 0;
- margin-bottom: 24px;
- padding-inline: 16px;
- font-size: 16px;
- font-weight: 600;
- line-height: 20px;
- color: var(--text-primary);
- background: none;
- border: none;
- border-radius: 18px;
-
- &:focus {
- background-color: var(--subtile-devider);
- outline: none;
- box-shadow: none;
- }
-
- &::placeholder {
- color: var(--text-tertiary);
- font-size: 16px;
- font-weight: 400;
- line-height: 20px;
- }
- }
-
- .title {
- font-weight: 800;
- font-size: 18px;
- line-height: 18px;
- color: var(--text-secondary);
- text-transform: uppercase;
- margin-bottom: 20px;
- }
-
- .xClose {
- background: none;
- border: none;
- margin: 0;
- padding: 0;
- width: fit-content;
-
- position: absolute;
- top: 16px;
- right: 22px;
-
- .iconClose {
- width: 14px;
- height: 14px;
- display: inline-block;
- margin: 0px 0px;
- background-color: var(--text-secondary);
- -webkit-mask: url(../../assets/icons/close.svg) no-repeat center;
- mask: url(../../assets/icons/close.svg) no-repeat center;
- }
-
- &:hover {
- .iconClose {
- background-color: var(--text-primary);
- }
- }
-
- &:focus {
- box-shadow: none;
- }
- }
-}
diff --git a/src/components/SettingsZap/SettingsZap.tsx b/src/components/SettingsZap/SettingsZap.tsx
index e8b8c87..9fe6c20 100644
--- a/src/components/SettingsZap/SettingsZap.tsx
+++ b/src/components/SettingsZap/SettingsZap.tsx
@@ -15,6 +15,7 @@ import { createStore } from 'solid-js/store';
import { EmojiOption } from '../../types/primal';
import ButtonPrimary from '../Buttons/ButtonPrimary';
import EmojiPicker from '../EmojiPicker/EmojiPicker';
+import EmojiPickModal from '../EmojiPickModal/EmojiPickModal';
const SettingsZap: Component<{ id?: string }> = (props) => {
@@ -176,35 +177,11 @@ const SettingsZap: Component<{ id?: string }> = (props) => {
onAbort={() => setIsRestoringZaps(false)}
/>
- = 0}
- onBackdropClick={() => setIsEmojiChange(-1)}
- >
-
-
- {intl.formatMessage(t.zapEmojiFilterTitle)}
-
-
-
-
-
{
- const target = e.target as HTMLInputElement;
- setEmojiSearchTerm(() => target.value);
- }}
- placeholder={intl.formatMessage(t.zapEmojiFilterPlaceholder)}
- >
-
-
-
-
-
+ onClose={() => setIsEmojiChange(-1)}
+ onSelect={changeZapOptionEmoji}
+ />
);
}
diff --git a/src/index.scss b/src/index.scss
index 9f72943..6de4b28 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -159,6 +159,10 @@ a {
-webkit-mask: url(./assets/icons/attach_media.svg) no-repeat 0 / 100%;
mask: url(./assets/icons/attach_media.svg) no-repeat 0 / 100%;
}
+.emoji_icon {
+ -webkit-mask: url(./assets/icons/emoji.svg) no-repeat 0 / 100%;
+ mask: url(./assets/icons/emoji.svg) no-repeat 0 / 100%;
+}
.bordered {
border:solid 1px var(--subtile-devider);