diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index 78bc1718a..2417e804f 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -10,7 +10,7 @@ import { AppState } from '@/ui_models/app_state'; type Props = { application: WebApplication; appState: AppState; - tagsRef: RefObject + tagsRef: RefObject; }; export const AutocompleteTagInput: FunctionalComponent = ({ @@ -25,7 +25,7 @@ export const AutocompleteTagInput: FunctionalComponent = ({ const [hintVisible, setHintVisible] = useState(true); const getActiveNoteTagResults = (query: string) => { - const { activeNote } = appState.notes; + const { activeNote } = appState.activeNote; return application.searchTags(query, activeNote); }; @@ -41,10 +41,13 @@ export const AutocompleteTagInput: FunctionalComponent = ({ setTagResults(getActiveNoteTagResults('')); }; - const [closeOnBlur, setLockCloseOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => { - setDropdownVisible(visible); - clearResults(); - }); + const [closeOnBlur, setLockCloseOnBlur] = useCloseOnBlur( + dropdownRef, + (visible: boolean) => { + setDropdownVisible(visible); + clearResults(); + } + ); const showDropdown = () => { const { clientHeight } = document.documentElement; @@ -61,7 +64,7 @@ export const AutocompleteTagInput: FunctionalComponent = ({ const onTagOptionClick = async (tag: SNTag) => { setLockCloseOnBlur(true); - await appState.notes.addTagToActiveNote(tag); + await appState.activeNote.addTagToActiveNote(tag); inputRef.current.focus(); setTagResults(getActiveNoteTagResults(searchQuery)); setLockCloseOnBlur(false); @@ -69,7 +72,7 @@ export const AutocompleteTagInput: FunctionalComponent = ({ const createAndAddNewTag = async () => { const newTag = await application.findOrCreateTag(searchQuery); - await appState.notes.addTagToActiveNote(newTag); + await appState.activeNote.addTagToActiveNote(newTag); clearResults(); inputRef.current.focus(); }; @@ -84,7 +87,9 @@ export const AutocompleteTagInput: FunctionalComponent = ({ }; useEffect(() => { - setHintVisible(searchQuery !== '' && !tagResults.some((tag) => tag.title === searchQuery)); + setHintVisible( + searchQuery !== '' && !tagResults.some((tag) => tag.title === searchQuery) + ); }, [tagResults, searchQuery]); return ( @@ -100,7 +105,12 @@ export const AutocompleteTagInput: FunctionalComponent = ({ onBlur={closeOnBlur} onFocus={showDropdown} onKeyUp={(event) => { - if (event.key === 'Backspace' && searchQuery === '' && tagsRef.current && tagsRef.current.length > 1) { + if ( + event.key === 'Backspace' && + searchQuery === '' && + tagsRef.current && + tagsRef.current.length > 1 + ) { tagsRef.current[tagsRef.current.length - 1].focus(); } }} @@ -128,7 +138,8 @@ export const AutocompleteTagInput: FunctionalComponent = ({ = ({ onClick={onTagHintClick} onBlur={closeOnBlur} > - - Create new tag: - - - + Create new tag: + + {searchQuery} diff --git a/app/assets/javascripts/components/NoteTags.tsx b/app/assets/javascripts/components/NoteTags.tsx index a1c6cd798..1eaffc0e4 100644 --- a/app/assets/javascripts/components/NoteTags.tsx +++ b/app/assets/javascripts/components/NoteTags.tsx @@ -4,7 +4,7 @@ import { toDirective } from './utils'; import { Icon } from './Icon'; import { AutocompleteTagInput } from './AutocompleteTagInput'; import { WebApplication } from '@/ui_models/application'; -import { useCallback, useEffect, useRef, useState } from 'preact/hooks'; +import { useEffect, useRef, useState } from 'preact/hooks'; import { SNTag } from '@standardnotes/snjs'; type Props = { @@ -13,14 +13,14 @@ type Props = { }; const TAGS_ROW_RIGHT_MARGIN = 92; -const TAGS_ROW_HEIGHT = 32; +const TAGS_ROW_HEIGHT = 36; const MIN_OVERFLOW_TOP = 76; -const TAG_RIGHT_MARGIN = 8; +const TAGS_RIGHT_MARGIN = 8; const NoteTags = observer(({ application, appState }: Props) => { - const { activeNoteTags } = appState.notes; - const [tagsContainerMaxWidth, setTagsContainerMaxWidth] = - useState('auto'); + const { tags, tagsContainerPosition, tagsContainerMaxWidth } = + appState.activeNote; + const [overflowedTagsCount, setOverflowedTagsCount] = useState(0); const [overflowCountPosition, setOverflowCountPosition] = useState(0); const [tagsContainerCollapsed, setTagsContainerCollapsed] = useState(true); @@ -32,23 +32,28 @@ const NoteTags = observer(({ application, appState }: Props) => { tagsRef.current = []; const onTagBackspacePress = async (tag: SNTag) => { - await appState.notes.removeTagFromActiveNote(tag); + await appState.activeNote.removeTagFromActiveNote(tag); if (tagsRef.current.length > 1) { tagsRef.current[tagsRef.current.length - 1].focus(); } }; - const reloadOverflowCount = useCallback(() => { - const editorElement = document.getElementById('editor-column'); + const expandTags = () => { + setContainerHeight(tagsContainerRef.current.scrollHeight); + setTagsContainerCollapsed(false); + }; + + useEffect(() => { + appState.activeNote.reloadTagsContainerLayout(); let overflowCount = 0; for (const [index, tagElement] of tagsRef.current.entries()) { if (tagElement.getBoundingClientRect().top >= MIN_OVERFLOW_TOP) { if (overflowCount === 0) { setOverflowCountPosition( tagsRef.current[index - 1].getBoundingClientRect().right - - (editorElement ? editorElement.getBoundingClientRect().left : 0) + - TAG_RIGHT_MARGIN + (tagsContainerPosition ?? 0) + + TAGS_RIGHT_MARGIN ); } overflowCount += 1; @@ -59,34 +64,12 @@ const NoteTags = observer(({ application, appState }: Props) => { if (!tagsContainerCollapsed) { setContainerHeight(tagsContainerRef.current.scrollHeight); } - }, [tagsContainerCollapsed]); - - const expandTags = () => { - setContainerHeight(tagsContainerRef.current.scrollHeight); - setTagsContainerCollapsed(false); - }; - - useEffect(() => { - const editorElement = document.getElementById('editor-column'); - const resizeObserver = new ResizeObserver((entries) => { - const entry = entries[0]; - const { width } = entry.contentRect; - setTagsContainerMaxWidth(width); - reloadOverflowCount(); - }); - - if (editorElement) { - resizeObserver.observe(editorElement); - } - - return () => { - resizeObserver.disconnect(); - }; - }, [reloadOverflowCount]); - - useEffect(() => { - reloadOverflowCount(); - }, [activeNoteTags, reloadOverflowCount]); + }, [ + appState.activeNote, + tags, + tagsContainerCollapsed, + tagsContainerPosition, + ]); const tagClass = `bg-contrast border-0 rounded text-xs color-text py-1 pr-2 flex items-center mt-2 mr-2 cursor-pointer hover:bg-secondary-contrast focus:bg-secondary-contrast`; @@ -99,7 +82,7 @@ const NoteTags = observer(({ application, appState }: Props) => { >
{ marginRight: TAGS_ROW_RIGHT_MARGIN, }} > - {activeNoteTags.map((tag, index) => ( + {tags.map((tag: SNTag, index: number) => (