88217c5e7d
* Implement a first version of WithFloating and Portal * Add outside slot for Portal * Execute computePosition from WithFloating * Set up a first example of new WithFloating with the Latex menu * Use autoUpdate in WithFloating * Create sveltelib/position * Add event-store * Use event-store in close-on-click * Implement subscribeToUpdates * Introduce sass/elevation * Split close-on-click to closing-click and subscribe-trigger * Have closing-* stores return a symbol - This way they act more of an EventEmitter than a store * Allow passing show store * Remove styling on float on updatePosition removal * Implement a nice border for dropdowns * Apply different border and box-shadow to Popover in dark/light theme * Fix Ctrl+Shift+T not working * Satisfy formatters and tests * Add copyright header * move copyright header to top (dae)
65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
import type { Readable } from "svelte/store";
|
|
import { derived } from "svelte/store";
|
|
|
|
/**
|
|
* Typically the right-sided mouse button.
|
|
*/
|
|
function isSecondaryButton(event: MouseEvent): boolean {
|
|
return event.button === 2;
|
|
}
|
|
|
|
interface ClosingClickArgs {
|
|
/**
|
|
* Clicking on the reference element should not close.
|
|
* The reference should handle this itself.
|
|
*/
|
|
reference: EventTarget;
|
|
floating: EventTarget;
|
|
inside: boolean;
|
|
outside: boolean;
|
|
}
|
|
|
|
/**
|
|
* Returns a derived store, which translates `MouseEvent`s into a boolean
|
|
* indicating whether they constitue a click that should close `floating`.
|
|
*
|
|
* @param: Should be an event store wrapping document.click.
|
|
*/
|
|
function isClosingClick(
|
|
store: Readable<MouseEvent>,
|
|
{ reference, floating, inside, outside }: ClosingClickArgs,
|
|
): Readable<symbol> {
|
|
function isTriggerClick(path: EventTarget[]): boolean {
|
|
return (
|
|
// Reference element was clicked, e.g. the button.
|
|
// The reference element needs to handle opening/closing itself.
|
|
!path.includes(reference) &&
|
|
((inside && path.includes(floating)) ||
|
|
(outside && !path.includes(floating)))
|
|
);
|
|
}
|
|
|
|
function shouldClose(event: MouseEvent): boolean {
|
|
if (isSecondaryButton(event)) {
|
|
return true;
|
|
}
|
|
|
|
if (isTriggerClick(event.composedPath())) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return derived(store, (event: MouseEvent, set: (value: symbol) => void): void => {
|
|
if (shouldClose(event)) {
|
|
set(Symbol());
|
|
}
|
|
});
|
|
}
|
|
|
|
export default isClosingClick;
|