From d415e66b355c75d5d1da55f607f9c52cc5a71301 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 3 Oct 2024 08:59:20 +0800 Subject: refactor: set Suggestion as custom element --- src/MenuItem.mjs | 41 ++++++++++++++++------------------------- src/css/index.css | 5 ++--- src/editor.mjs | 22 +++++++++++++--------- 3 files changed, 31 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index d485032..4028702 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs @@ -134,41 +134,32 @@ export const addGeoLink = ({ utils }, range) => } }) -export class Suggestion { - constructor ({ text, replace }) { - this.text = text +export class Suggestion extends Item { + constructor ({ text, replace, cm }) { + super({ text }) this.replace = replace - } + this.classList.add('suggestion') - createElement (codemirror) { - const option = document.createElement('div') - if (this.text.startsWith('<')) { - option.innerHTML = this.text - } else { - option.innerText = this.text - } - option.classList.add('container__suggestion') - option.onmouseover = () => { - Array.from(option.parentElement?.children)?.forEach(s => + this.onmouseover = () => { + Array.from(this.parentElement?.children)?.forEach(s => s.classList.remove('focus') ) - option.classList.add('focus') + this.classList.add('focus') } - option.onmouseout = () => { - option.classList.remove('focus') + this.onmouseout = () => { + this.classList.remove('focus') } - option.onclick = () => { - const anchor = codemirror.getCursor() - codemirror.setSelection(anchor, { ...anchor, ch: 0 }) - codemirror.replaceSelection(this.replace) - codemirror.focus() + this.onclick = () => { + const anchor = cm.getCursor() + cm.setSelection(anchor, { ...anchor, ch: 0 }) + cm.replaceSelection(this.replace) + cm.focus() const newAnchor = { ...anchor, ch: this.replace.length } - codemirror.setCursor(newAnchor) + cm.setCursor(newAnchor) } - - return option } } +window.customElements.define('menu-item-suggestion', Suggestion, { extends: 'div' }) export const renderResults = ({ modal, modalContent }, map) => new Item({ diff --git a/src/css/index.css b/src/css/index.css index 858182d..a2ef454 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -117,13 +117,12 @@ body { } } -.container__suggestion { +.suggestion { display: flex; overflow: hidden; justify-content: space-between; align-items: center; - height: fit-content; - min-height: 2rem; + max-width: 700px; cursor: pointer; white-space: nowrap; diff --git a/src/editor.mjs b/src/editor.mjs index 2938745..82d93b0 100644 --- a/src/editor.mjs +++ b/src/editor.mjs @@ -3,6 +3,7 @@ import { markdown2HTML, generateMaps } from './dumbymap' import { defaultAliases, parseConfigsFromYaml } from 'mapclay' import * as menuItem from './MenuItem' +import { shiftByWindow } from './utils.mjs' // Set up Containers {{{ @@ -382,7 +383,8 @@ const getSuggestionsForOptions = (optionTyped, validOptions) => { o => new menuItem.Suggestion({ text: `${o.valueOf()}`, - replace: `${o.valueOf()}: ` + replace: `${o.valueOf()}: `, + cm }) ) } @@ -397,7 +399,8 @@ const getSuggestionFromMapOption = option => { return new menuItem.Suggestion({ text, - replace: `${option.valueOf()}: ${option.example ?? ''}` + replace: `${option.valueOf()}: ${option.example ?? ''}`, + cm }) } // }}} @@ -408,7 +411,8 @@ const getSuggestionsFromAliases = option => const valueString = JSON.stringify(value).replaceAll('"', '') return new menuItem.Suggestion({ text: `${alias}${valueString}`, - replace: `${option.valueOf()}: ${valueString}` + replace: `${option.valueOf()}: ${valueString}`, + cm }) }) ?? [] // }}} @@ -523,7 +527,8 @@ const getSuggestions = anchor => { ([renderer, info]) => new menuItem.Suggestion({ text: `use: ${renderer}`, - replace: `use: ${renderer}` + replace: `use: ${renderer}`, + cm }) ) return rendererSuggestions.length > 0 ? rendererSuggestions : [] @@ -542,7 +547,6 @@ const addSuggestions = (anchor, suggestions) => { menu.innerHTML = '' suggestions - .map(s => s.createElement(cm)) .forEach(option => menu.appendChild(option)) const widgetAnchor = document.createElement('div') @@ -550,8 +554,8 @@ const addSuggestions = (anchor, suggestions) => { const rect = widgetAnchor.getBoundingClientRect() menu.style.left = `calc(${rect.left}px + 2rem)` menu.style.top = `calc(${rect.bottom}px + 1rem)` - menu.style.maxWidth = `calc(${window.innerWidth}px - ${rect.x}px - 3rem)` menu.style.display = 'block' + shiftByWindow(menu) } // }}} // EVENT: Suggests for current selection {{{ @@ -583,7 +587,7 @@ cm.on('keydown', (_, e) => { ) { return } // Directly add a newline when no suggestion is selected - const currentSuggestion = menu.querySelector('.container__suggestion.focus') + const currentSuggestion = menu.querySelector('.menu-item.focus') if (!currentSuggestion && e.key === 'Enter') return // Override default behavior @@ -592,10 +596,10 @@ cm.on('keydown', (_, e) => { // Suggestion when pressing Tab or Shift + Tab const nextSuggestion = currentSuggestion?.nextSibling ?? - menu.querySelector('.container__suggestion:first-child') + menu.querySelector('.menu-item:first-child') const previousSuggestion = currentSuggestion?.previousSibling ?? - menu.querySelector('.container__suggestion:last-child') + menu.querySelector('.menu-item:last-child') const focusSuggestion = e.shiftKey ? previousSuggestion : nextSuggestion // Current editor selection state -- cgit v1.2.3-70-g09d2