schlechtenburg/packages/core/lib/components/ContextMenu.tsx

82 lines
1.9 KiB
TypeScript
Raw Normal View History

2021-02-22 18:13:37 +00:00
import {
watch,
defineComponent,
ref,
} from 'vue';
import { SbButton } from './Button';
import './ContextMenu.scss';
interface ContextMenuProps {
onClose: () => void;
onOpen: () => void;
}
export const SbContextMenu = defineComponent({
name: 'sb-context-menu',
props: {
onClose: { type: Function, default: () => {} },
onOpen: { type: Function, default: () => {} },
},
setup(props: ContextMenuProps, context) {
const opened = ref(false);
2021-02-22 23:12:06 +00:00
const open = () => { opened.value = true; };
const close = () => { opened.value = false; };
2021-02-22 18:13:37 +00:00
const closeOnEscape = ($event: KeyboardEvent) => {
if ($event.key === 'Escape') {
close();
}
};
2021-02-22 23:12:06 +00:00
const toggle = () => { opened.value ? close() : open() };
2021-02-22 18:13:37 +00:00
2021-02-22 23:12:06 +00:00
watch(opened, (curr, prev) => {
if (curr === prev) {
return;
}
if (!curr) {
document.body.removeEventListener('click', close);
document.body.removeEventListener('keypress', closeOnEscape);
} else {
setTimeout(() => {
document.body.addEventListener('click', close);
document.body.addEventListener('keypress', closeOnEscape);
});
2021-02-22 18:13:37 +00:00
}
});
return () => (
2021-02-22 23:12:06 +00:00
<div class="sb-context">
2021-02-22 18:13:37 +00:00
{
context.slots.context({
opened,
toggle,
close,
open,
}) ||
<SbButton onClick={toggle}>Menu</SbButton>
}
<dialog
2021-02-22 23:12:06 +00:00
class="sb-context-menu"
open={opened.value ? true : undefined}
2021-02-22 18:13:37 +00:00
onClose={close}
onClick={($event: Event) => {
// Make sure clicks inside do not autoclose this
2021-02-22 23:12:06 +00:00
$event.stopPropagation();
2021-02-22 18:13:37 +00:00
}}
>
{context.slots.default({
opened,
toggle,
close,
open,
}) || null}
</dialog>
</div>
);
},
});