cmdk hotkeys work if input if focsed

This commit is contained in:
Nikita Galaiko 2023-04-24 12:23:19 +02:00
parent 70d61314a6
commit 0d21f17509
3 changed files with 153 additions and 153 deletions

View File

@ -61,7 +61,7 @@
action.href.startsWith('http') || action.href.startsWith('mailto')
? open(action.href)
: goto(action.href);
modal?.hide();
modal?.close();
} else if (Action.isGroup(action)) {
selectedGroup.set(action);
}
@ -115,11 +115,9 @@
if (command.hotkey) {
unregisterCommandHotkeys.push(
tinykeys(window, {
[command.hotkey]: (event: KeyboardEvent) => {
const target = event.target as HTMLElement;
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') return;
// only trigger if the modal is visible
modal?.isOpen() && trigger(command.action);
[command.hotkey]: () => {
if (!modal?.isOpen()) return;
trigger(command.action);
}
})
);

View File

@ -5,182 +5,184 @@ import type { SvelteComponent } from 'svelte';
import { format, startOfISOWeek, startOfMonth, subDays, subMonths, subWeeks } from 'date-fns';
type ActionLink = {
href: string;
href: string;
};
interface Newable<ReturnType> {
new (...args: any[]): ReturnType;
new(...args: any[]): ReturnType;
}
export type Action = ActionLink | Group;
export namespace Action {
export const isLink = (action: Action): action is ActionLink => 'href' in action;
export const isGroup = (action: Action): action is Group => 'commands' in action;
export const isLink = (action: Action): action is ActionLink => 'href' in action;
export const isGroup = (action: Action): action is Group => 'commands' in action;
}
export type Command = {
title: string;
hotkey?: string;
action: Action;
icon?: Newable<SvelteComponent>;
title: string;
hotkey?: string;
action: Action;
icon?: Newable<SvelteComponent>;
};
export type Group = {
title: string;
description?: string;
commands: Command[];
title: string;
description?: string;
commands: Command[];
};
const goToProjectGroup = ({ projects, input }: { projects: Project[]; input: string }): Group => ({
title: 'Go to project',
commands: projects
.map((project) => ({
title: project.title,
action: {
href: `/projects/${project.id}/`
},
icon: IconProject
}))
.filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
title: 'Go to project',
commands: projects
.filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
.map((project, i) => ({
title: project.title,
hotkey: `${i + 1}`,
action: {
href: `/projects/${project.id}/`
},
icon: IconProject
}))
});
const actionsGroup = ({ project, input }: { project: Project; input: string }): Group => ({
title: 'Actions',
commands: [
{
title: 'Commit',
hotkey: 'Shift+C',
action: {
href: `/projects/${project.id}/commit/`
},
icon: GitCommitIcon
},
{
title: 'Terminal',
hotkey: 'Shift+T',
action: {
href: `/projects/${project?.id}/terminal/`
},
icon: IconTerminal
},
{
title: 'Replay History',
action: {
title: 'Replay working history',
commands: [
{
title: 'Eralier today',
icon: RewindIcon,
hotkey: '1',
action: {
href: `/projects/${project.id}/player/${format(new Date(), 'yyyy-MM-dd')}/`
}
},
{
title: 'Yesterday',
icon: RewindIcon,
hotkey: '2',
action: {
href: `/projects/${project.id}/player/${format(
subDays(new Date(), 1),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The day before yesterday',
icon: RewindIcon,
hotkey: '3',
action: {
href: `/projects/${project.id}/player/${format(
subDays(new Date(), 2),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The beginning of last week',
icon: RewindIcon,
hotkey: '4',
action: {
href: `/projects/${project.id}/player/${format(
startOfISOWeek(subWeeks(new Date(), 1)),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The beginning of last month',
icon: RewindIcon,
hotkey: '5',
action: {
href: `/projects/${project.id}/player/${format(
startOfMonth(subMonths(new Date(), 1)),
'yyyy-MM-dd'
)}/`
}
}
]
},
icon: RewindIcon
}
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
title: 'Actions',
commands: [
{
title: 'Commit',
hotkey: 'Shift+C',
action: {
href: `/projects/${project.id}/commit/`
},
icon: GitCommitIcon
},
{
title: 'Terminal',
hotkey: 'Shift+T',
action: {
href: `/projects/${project?.id}/terminal/`
},
icon: IconTerminal
},
{
title: 'Replay History',
hotkey: 'Shift+R',
action: {
title: 'Replay working history',
commands: [
{
title: 'Eralier today',
icon: RewindIcon,
hotkey: '1',
action: {
href: `/projects/${project.id}/player/${format(new Date(), 'yyyy-MM-dd')}/`
}
},
{
title: 'Yesterday',
icon: RewindIcon,
hotkey: '2',
action: {
href: `/projects/${project.id}/player/${format(
subDays(new Date(), 1),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The day before yesterday',
icon: RewindIcon,
hotkey: '3',
action: {
href: `/projects/${project.id}/player/${format(
subDays(new Date(), 2),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The beginning of last week',
icon: RewindIcon,
hotkey: '4',
action: {
href: `/projects/${project.id}/player/${format(
startOfISOWeek(subWeeks(new Date(), 1)),
'yyyy-MM-dd'
)}/`
}
},
{
title: 'The beginning of last month',
icon: RewindIcon,
hotkey: '5',
action: {
href: `/projects/${project.id}/player/${format(
startOfMonth(subMonths(new Date(), 1)),
'yyyy-MM-dd'
)}/`
}
}
]
},
icon: RewindIcon
}
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
});
const fileGroup = ({
project,
input
project,
input
}: {
project: Project;
input: string;
project: Project;
input: string;
}): Group | Promise<Group> =>
input.length === 0
? {
title: 'Files',
description: 'type part of a file name',
commands: []
}
: matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
title: 'Files',
description: files.length === 0 ? `no files containing '${input}'` : '',
commands: files.map((file) => ({
title: file,
action: {
href: '/'
},
icon: IconFile
}))
}));
input.length === 0
? {
title: 'Files',
description: 'type part of a file name',
commands: []
}
: matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
title: 'Files',
description: files.length === 0 ? `no files containing '${input}'` : '',
commands: files.map((file) => ({
title: file,
action: {
href: '/'
},
icon: IconFile
}))
}));
const supportGroup = ({ input }: { input: string }): Group => ({
title: 'Help & Support',
commands: [
{
title: 'Documentation',
action: {
href: `https://docs.gitbutler.com`
},
icon: FileIcon
},
{
title: 'Discord',
action: {
href: `https://discord.gg/MmFkmaJ42D`
},
icon: GitCommitIcon
}
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
title: 'Help & Support',
commands: [
{
title: 'Documentation',
action: {
href: `https://docs.gitbutler.com`
},
icon: FileIcon
},
{
title: 'Discord',
action: {
href: `https://discord.gg/MmFkmaJ42D`
},
icon: GitCommitIcon
}
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
});
export default (params: { projects: Project[]; project?: Project; input: string }) => {
const { projects, input, project } = params;
const groups = [];
const { projects, input, project } = params;
const groups = [];
!project && groups.push(goToProjectGroup({ projects, input }));
project && groups.push(actionsGroup({ project, input }));
project && groups.push(fileGroup({ project, input }));
groups.push(supportGroup({ input }));
!project && groups.push(goToProjectGroup({ projects, input }));
project && groups.push(actionsGroup({ project, input }));
project && groups.push(fileGroup({ project, input }));
groups.push(supportGroup({ input }));
return groups;
return groups;
};

View File

@ -12,7 +12,7 @@
};
export const isOpen = () => open;
const close = () => {
export const close = () => {
open = false;
dialog.close();
};