2021-02-22 18:13:37 +00:00
|
|
|
import {
|
|
|
|
watch,
|
|
|
|
defineComponent,
|
|
|
|
ref,
|
2022-03-12 16:16:24 +00:00
|
|
|
Ref,
|
2021-02-22 18:13:37 +00:00
|
|
|
} from 'vue';
|
|
|
|
import { SbButton } from './Button';
|
|
|
|
|
|
|
|
import './ContextMenu.scss';
|
|
|
|
|
2022-03-12 16:16:24 +00:00
|
|
|
export interface IContextMenuSlotContext {
|
|
|
|
opened: Ref<boolean>;
|
|
|
|
open: () => void;
|
|
|
|
close: () => void;
|
|
|
|
toggle: () => void;
|
|
|
|
}
|
|
|
|
|
2021-02-22 18:13:37 +00:00
|
|
|
export const SbContextMenu = defineComponent({
|
|
|
|
name: 'sb-context-menu',
|
|
|
|
|
|
|
|
props: {
|
|
|
|
onClose: { type: Function, default: () => {} },
|
|
|
|
onOpen: { type: Function, default: () => {} },
|
|
|
|
},
|
|
|
|
|
2021-03-08 15:29:35 +00:00
|
|
|
setup(props, context) {
|
2021-02-22 18:13:37 +00:00
|
|
|
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);
|
2021-03-08 15:29:35 +00:00
|
|
|
props.onClose();
|
2021-02-22 23:12:06 +00:00
|
|
|
} else {
|
|
|
|
setTimeout(() => {
|
|
|
|
document.body.addEventListener('click', close);
|
|
|
|
document.body.addEventListener('keypress', closeOnEscape);
|
2021-03-08 15:29:35 +00:00
|
|
|
props.onOpen();
|
2021-02-22 23:12:06 +00:00
|
|
|
});
|
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
|
|
|
{
|
2021-03-08 15:29:35 +00:00
|
|
|
context.slots.context?.({
|
2021-02-22 18:13:37 +00:00
|
|
|
opened,
|
|
|
|
toggle,
|
|
|
|
close,
|
|
|
|
open,
|
2021-03-08 15:29:35 +00:00
|
|
|
}) || <SbButton {...{ onClick: toggle }}>Menu</SbButton>
|
2021-02-22 18:13:37 +00:00
|
|
|
}
|
|
|
|
<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
|
|
|
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
|
|
|
}}
|
2021-03-08 15:29:35 +00:00
|
|
|
{...{ onClose: close /* TODO: DialogHTMLAttributes needs an onClose handler type */ }}
|
2021-02-22 18:13:37 +00:00
|
|
|
>
|
2021-03-08 15:29:35 +00:00
|
|
|
{context.slots.default?.({
|
2021-02-22 18:13:37 +00:00
|
|
|
opened,
|
|
|
|
toggle,
|
|
|
|
close,
|
|
|
|
open,
|
|
|
|
}) || null}
|
|
|
|
</dialog>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|