import { ref, Ref, onMounted, onBeforeUnmount, defineComponent, computed, } from 'vue'; import debounce from 'lodash/debounce'; import { useRootElement } from '../use-root-element'; import { useFormattingToolbar } from './use-formatting-toolbar'; import { getSelection, getAnchorElementForSelection, getRangeFromSelection, getRect, } from './selection'; import './FormattingToolbar.scss'; export const SbFormattingToolbar = defineComponent({ name: 'sb-inlinetoolbar', setup() { const { rootElement } = useRootElement(); const { activeClient, setActiveClient, clients, getAllTools, } = useFormattingToolbar(); const allTools = computed(() => getAllTools()); const selection: Ref= ref(null); const selectionRect: Ref= ref(null); const updateSelectionRect = () => { selectionRect.value = getRect(selection.value!); }; const showing: Ref = ref(false); const show = () => { showing.value = true; updateSelectionRect(); }; const hide = () => { showing.value = false; setActiveClient(null); }; const style = computed(() => { const rootRect = rootElement.value?.getBoundingClientRect(); const x = (selectionRect.value?.x || 0) - (rootRect?.left || 0); const y = (selectionRect.value?.y || 0) + (selectionRect.value?.height || 0) - (rootRect?.top || 0); return { left: Math.floor(x) + 'px', top: Math.floor(y) + 'px', }; }); const classes = computed(() => ({ 'sb-inline-toolbar': true, })); const onSelectionChanged = debounce(() => { selection.value = getSelection(); if (!selection.value) { console.warn('Could not get selection'); return } const range = getRangeFromSelection(selection.value); // If we're not selecting anything, bail if (!range || range.endOffset === range.startOffset) { hide(); return; } const focusedElement = document.activeElement; if (!focusedElement) { hide(); return; } // If new selection is not in registered clients, close it if (!clients.value.find(client => client === focusedElement)) { hide(); return; } setActiveClient(document.activeElement as HTMLElement|null); show(); }, 50); onMounted(() => { rootElement.value?.addEventListener('click', close); document.addEventListener('selectionchange', onSelectionChanged, true); }); onBeforeUnmount(() => { rootElement.value?.removeEventListener('click', close); document.removeEventListener('selectionchange', onSelectionChanged); }); return () => (allTools.value.length && showing.value) ?
{ event.stopPropagation(); }} >{allTools.value.map((tool) => { const ToolUI = tool.ui as any; return ; })}
: null; }, });