mirror of
https://github.com/directus/directus.git
synced 2026-01-27 02:17:55 -05:00
finish adding own shortcut handler
This commit is contained in:
@@ -34,13 +34,14 @@ export default defineComponent({
|
||||
setup(props, { emit }) {
|
||||
const dialog = ref<HTMLElement | null>(null);
|
||||
useShortcut(
|
||||
'esc',
|
||||
() => {
|
||||
console.log('A', dialog.value);
|
||||
|
||||
emit('toggle', false);
|
||||
if (_active.value) {
|
||||
emitToggle();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
ref(document.body)
|
||||
ref(document.body),
|
||||
'escape'
|
||||
);
|
||||
|
||||
const localActive = ref(false);
|
||||
|
||||
@@ -295,11 +295,11 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
useShortcut(
|
||||
'mod+a',
|
||||
() => {
|
||||
onToggleSelectAll(!allItemsSelected.value);
|
||||
},
|
||||
table
|
||||
table,
|
||||
'meta+a'
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useShortcut } from '@/composables/use-shortcut';
|
||||
|
||||
export default defineComponent({
|
||||
setup(props) {
|
||||
useShortcut('mod+s', save);
|
||||
useShortcut('meta+s', save);
|
||||
|
||||
function save() {
|
||||
// ...
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { onMounted, onUnmounted, Ref } from '@vue/composition-api';
|
||||
import Vue from 'vue';
|
||||
|
||||
type ShortcutHandler = () => void;
|
||||
type ShortcutHandler = (event: KeyboardEvent) => void | any | boolean;
|
||||
|
||||
let keysdown: string[] = [];
|
||||
const keysdown: Set<string> = new Set([]);
|
||||
const handlers: Record<string, ShortcutHandler[]> = {};
|
||||
|
||||
document.body.addEventListener('keydown', (event: KeyboardEvent) => {
|
||||
console.log(event.CAPTURING_PHASE);
|
||||
keysdown.push(mapKeys(event.key));
|
||||
callHandlers();
|
||||
if (event.repeat) return;
|
||||
|
||||
keysdown.add(mapKeys(event.key));
|
||||
callHandlers(event);
|
||||
});
|
||||
|
||||
document.body.addEventListener('keyup', (event: KeyboardEvent) => {
|
||||
keysdown = keysdown.filter((key) => key === mapKeys(event.key));
|
||||
const key = mapKeys(event.key);
|
||||
keysdown.delete(key.toLowerCase());
|
||||
keysdown.delete(key.toUpperCase());
|
||||
});
|
||||
|
||||
function mapKeys(key: string) {
|
||||
@@ -21,31 +24,31 @@ function mapKeys(key: string) {
|
||||
Control: 'meta',
|
||||
Command: 'meta',
|
||||
};
|
||||
return map.hasOwnProperty(key) ? map[key] : key;
|
||||
}
|
||||
key = map.hasOwnProperty(key) ? map[key] : key;
|
||||
|
||||
function callHandlers() {
|
||||
Object.entries(handlers).forEach(([key, value]) => {
|
||||
const rest = key.split('+').filter((keySegment) => keysdown.includes(keySegment) === false);
|
||||
// strg+A strg+shift+aaaa
|
||||
|
||||
if (rest.length > 0) return;
|
||||
value.forEach((f) => f());
|
||||
});
|
||||
}
|
||||
|
||||
function filterShortcut(shortcut: string) {
|
||||
let sections = shortcut.split('+');
|
||||
if (sections.find((s) => s.match(/^[A-Z]$/) !== null)) {
|
||||
const filtered = sections.filter((s) => s.toLowerCase() === 'shift');
|
||||
if (filtered.length % 2 === 0) {
|
||||
sections.unshift('shift');
|
||||
} else {
|
||||
sections = sections.filter((s) => s.toLowerCase() !== 'shift');
|
||||
}
|
||||
return sections.join('+').toLowerCase();
|
||||
if (key.match(/^[a-z]$/) !== null) {
|
||||
if (keysdown.has('shift')) key = key.toUpperCase();
|
||||
} else if (key.match(/^[A-Z]$/) !== null) {
|
||||
if (keysdown.has('shift')) key = key.toLowerCase();
|
||||
} else {
|
||||
key = key.toLowerCase();
|
||||
}
|
||||
return shortcut.toLowerCase();
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
function callHandlers(event: KeyboardEvent) {
|
||||
Object.entries(handlers).forEach(([key, value]) => {
|
||||
const rest = key.split('+').filter((keySegment) => keysdown.has(keySegment) === false);
|
||||
if (rest.length > 0) return;
|
||||
event.preventDefault();
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const cancel = value[i](event);
|
||||
|
||||
// if the return value is true discontinue going through the queue.
|
||||
if (typeof cancel === 'boolean' && cancel === true) break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default function useShortcut(
|
||||
@@ -53,7 +56,7 @@ export default function useShortcut(
|
||||
reference: Ref<HTMLElement | null> | Ref<Vue | null>,
|
||||
...shortcuts: string[]
|
||||
) {
|
||||
const callback: ShortcutHandler = () => {
|
||||
const callback: ShortcutHandler = (event) => {
|
||||
if (reference.value === null) return;
|
||||
const ref = reference.value instanceof HTMLElement ? reference.value : (reference.value.$el as HTMLElement);
|
||||
|
||||
@@ -62,24 +65,26 @@ export default function useShortcut(
|
||||
ref.contains(document.activeElement) ||
|
||||
document.activeElement === document.body
|
||||
) {
|
||||
handler();
|
||||
return handler(event);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
onMounted(() => {
|
||||
shortcuts.forEach((shortcut) => {
|
||||
const s = filterShortcut(shortcut);
|
||||
if (handlers.hasOwnProperty(s)) {
|
||||
handlers[s].unshift(callback);
|
||||
if (handlers.hasOwnProperty(shortcut)) {
|
||||
handlers[shortcut].unshift(callback);
|
||||
} else {
|
||||
handlers[s] = [callback];
|
||||
handlers[shortcut] = [callback];
|
||||
}
|
||||
});
|
||||
});
|
||||
onUnmounted(() => {
|
||||
shortcuts.forEach((shortcut) => {
|
||||
const s = filterShortcut(shortcut);
|
||||
if (handlers.hasOwnProperty(s)) {
|
||||
handlers[s] = handlers[s].filter((f) => f !== callback);
|
||||
if (handlers.hasOwnProperty(shortcut)) {
|
||||
handlers[shortcut] = handlers[shortcut].filter((f) => f !== callback);
|
||||
if (handlers[shortcut].length === 0) {
|
||||
delete handlers[shortcut];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -225,7 +225,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const form = ref<Vue | null>(null);
|
||||
const form = ref(null);
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { collection, primaryKey } = toRefs(props);
|
||||
@@ -286,8 +286,8 @@ export default defineComponent({
|
||||
return i18n.t('archive');
|
||||
});
|
||||
|
||||
useShortcut('mod+s', saveAndStay, form);
|
||||
useShortcut('mod+shift+s', saveAndAddNew, form);
|
||||
useShortcut(saveAndStay, form, 'meta+s');
|
||||
useShortcut(saveAndAddNew, form, 'meta+shift+s');
|
||||
|
||||
const navigationGuard: NavigationGuard = (to, from, next) => {
|
||||
const hasEdits = Object.keys(edits.value).length > 0;
|
||||
|
||||
@@ -293,7 +293,7 @@ export default defineComponent({
|
||||
|
||||
const { moveToDialogActive, moveToFolder, moving, selectedFolder } = useMovetoFolder();
|
||||
|
||||
useShortcut('mod+s', saveAndStay, form);
|
||||
useShortcut(saveAndStay, form, 'meta+s');
|
||||
|
||||
return {
|
||||
item,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<v-modal
|
||||
:active="active"
|
||||
@toggle="cancelField"
|
||||
:title="
|
||||
field === '+'
|
||||
? $t('creating_new_field', { collection: collectionInfo.name })
|
||||
|
||||
@@ -293,8 +293,8 @@ export default defineComponent({
|
||||
return i18n.t('archive');
|
||||
});
|
||||
|
||||
useShortcut('mod+s', saveAndStay, form);
|
||||
useShortcut('mod+shift+s', saveAndAddNew, form);
|
||||
useShortcut(saveAndStay, form, 'meta+s');
|
||||
useShortcut(saveAndAddNew, form, 'meta+shift+s');
|
||||
|
||||
return {
|
||||
title,
|
||||
|
||||
@@ -47,7 +47,7 @@ export default defineComponent({
|
||||
},
|
||||
setup(props) {
|
||||
const textarea = ref<HTMLElement | null>(null);
|
||||
useShortcut('mod+enter', postComment, textarea);
|
||||
useShortcut(postComment, textarea, 'meta+enter');
|
||||
const newCommentContent = ref<string | null>(null);
|
||||
const saving = ref(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user