import { ref, Ref, onMounted, onBeforeUnmount, defineComponent, computed, } from 'vue'; import debounce from 'lodash/debounce'; import { useRootElement } from '../use-root-element'; import { useInline } from './use-inline'; import { getSelection, getAnchorElementForSelection, getRangeFromSelection, getRect, } from './selection'; import './InlineToolbar.scss'; export const SbInlineToolbar = defineComponent({ name: 'sb-inlinetoolbar', setup() { const { rootElement } = useRootElement(); const { clients, getAllTools, } = useInline(); const allTools = computed(() => getAllTools()); const selectionRect: Ref= ref(null); const updateSelectionRect = () => { const selection = getSelection(); if (!selection) { console.warn('Could not get selection'); return; } selectionRect.value = getRect(selection); }; const showing: Ref = ref(false); const show = () => { showing.value = true; updateSelectionRect(); }; const hide = () => { showing.value = false; }; 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, 'sb-inline-toolbar_hidden': !showing.value, })); const onSelectionChanged = debounce(() => { const selection = getSelection(); if (!selection) { console.warn('Could not get selection'); return } const range = getRangeFromSelection(selection); // If we're not selecting anything, bail if (!range || range.endOffset === range.startOffset) { hide(); return; } const focusedElement = getAnchorElementForSelection(selection); if (!focusedElement) { hide(); return; } // If new selection is not in registered clients, close it if (!clients.value.find(client => client === focusedElement)) { hide(); return; } 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 ?
{allTools.value.map(tool => tool.ui)}
: null; }, });