Files
standardnotes-app-web/app/assets/javascripts/components/utils.ts
Mo 50c92619ce refactor: migrate remaining angular components to react (#833)
* refactor: menuRow directive to MenuRow component

* refactor: migrate footer to react

* refactor: migrate actions menu to react

* refactor: migrate history menu to react

* fix: click outside handler use capture to trigger event before re-render occurs which would otherwise cause node.contains to return incorrect result (specifically for the account menu)

* refactor: migrate revision preview modal to react

* refactor: migrate permissions modal to react

* refactor: migrate password wizard to react

* refactor: remove unused input modal directive

* refactor: remove unused delay hide component

* refactor: remove unused filechange directive

* refactor: remove unused elemReady directive

* refactor: remove unused sn-enter directive

* refactor: remove unused lowercase directive

* refactor: remove unused autofocus directive

* refactor(wip): note view to react

* refactor: use mutation observer to deinit textarea listeners

* refactor: migrate challenge modal to react

* refactor: migrate note group view to react

* refactor(wip): migrate remaining classes

* fix: navigation parent ref

* refactor: fully remove angular assets

* fix: account switcher

* fix: application view state

* refactor: remove unused password wizard type

* fix: revision preview and permissions modal

* fix: remove angular comment

* refactor: react panel resizers for editor

* feat: simple panel resizer

* fix: use simple panel resizer everywhere

* fix: simplify panel resizer state

* chore: rename simple panel resizer to panel resizer

* refactor: simplify column layout

* fix: editor mount safety check

* fix: use inline onLoad callback for iframe, as setting onload after it loads will never call it

* chore: fix note view test

* chore(deps): upgrade snjs
2022-01-30 19:01:30 -06:00

60 lines
1.6 KiB
TypeScript

import { FunctionComponent, h, render } from 'preact';
import { unmountComponentAtNode } from 'preact/compat';
import { StateUpdater, useCallback, useState, useEffect } from 'preact/hooks';
/**
* @returns a callback that will close a dropdown if none of its children has
* focus. Use the returned function as the onBlur callback of children that need to be
* monitored.
*/
export function useCloseOnBlur(
container: { current?: HTMLDivElement | null },
setOpen: (open: boolean) => void
): [
(event: { relatedTarget: EventTarget | null }) => void,
StateUpdater<boolean>
] {
const [locked, setLocked] = useState(false);
return [
useCallback(
function onBlur(event: { relatedTarget: EventTarget | null }) {
if (
!locked &&
!container.current?.contains(event.relatedTarget as Node)
) {
setOpen(false);
}
},
[container, setOpen, locked]
),
setLocked,
];
}
export function useCloseOnClickOutside(
container: { current: HTMLDivElement | null },
callback: () => void
): void {
const closeOnClickOutside = useCallback(
(event: { target: EventTarget | null }) => {
if (!container.current) {
return;
}
const isDescendant = container.current.contains(event.target as Node);
if (!isDescendant) {
callback();
}
},
[container, callback]
);
useEffect(() => {
document.addEventListener('click', closeOnClickOutside, { capture: true });
return () => {
document.removeEventListener('click', closeOnClickOutside, {
capture: true,
});
};
}, [closeOnClickOutside]);
}