@sv-use/core
Version:
A collection of Svelte 5 utilities.
54 lines (53 loc) • 1.79 kB
JavaScript
import { onDestroy } from 'svelte';
import { handleEventListener } from '../handle-event-listener/index.svelte.js';
import { noop } from '../__internal__/utils.svelte.js';
import { defaultWindow } from '../__internal__/configurable.js';
/**
* Gets the range of text selected by the user or the current position of the caret.
* @param options Additional options to customize the behavior.
* @see https://svelte-librarian.github.io/sv-use/docs/core/browser/get-text-selection
*/
export function getTextSelection(options = {}) {
const { autoCleanup = true, window = defaultWindow } = options;
let cleanup = noop;
let current = $state(null);
const text = $derived.by(() => current?.toString() ?? '');
const ranges = $derived.by(() => (current ? getRangesFromSelection(current) : []));
const rects = $derived.by(() => ranges.map((range) => range.getBoundingClientRect()));
if (window) {
cleanup = handleEventListener(window.document, 'selectionchange', onSelectionChange, {
passive: true
});
}
if (autoCleanup) {
onDestroy(() => cleanup());
}
function getRangesFromSelection(selection) {
const rangeCount = selection.rangeCount ?? 0;
return Array.from({ length: rangeCount }, (_, i) => selection.getRangeAt(i));
}
function onSelectionChange() {
current = null;
if (window) {
current = window.getSelection();
}
}
return {
get current() {
return current;
},
set current(v) {
current = v;
},
get text() {
return text;
},
get rects() {
return rects;
},
get ranges() {
return ranges;
},
cleanup
};
}