From 0d21f17509477571c9c80c609805b123fe0cc592 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Mon, 24 Apr 2023 12:23:19 +0200 Subject: [PATCH] cmdk hotkeys work if input if focsed --- .../CommandPalette/CommandPalette.svelte | 10 +- src/lib/components/CommandPalette/commands.ts | 294 +++++++++--------- src/lib/components/Modal.svelte | 2 +- 3 files changed, 153 insertions(+), 153 deletions(-) diff --git a/src/lib/components/CommandPalette/CommandPalette.svelte b/src/lib/components/CommandPalette/CommandPalette.svelte index e890bc307..9b16412ca 100644 --- a/src/lib/components/CommandPalette/CommandPalette.svelte +++ b/src/lib/components/CommandPalette/CommandPalette.svelte @@ -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); } }) ); diff --git a/src/lib/components/CommandPalette/commands.ts b/src/lib/components/CommandPalette/commands.ts index 68c28c139..3d925525d 100644 --- a/src/lib/components/CommandPalette/commands.ts +++ b/src/lib/components/CommandPalette/commands.ts @@ -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 { - 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; + title: string; + hotkey?: string; + action: Action; + icon?: Newable; }; 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 => - 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; }; diff --git a/src/lib/components/Modal.svelte b/src/lib/components/Modal.svelte index 0819760bc..02de78774 100644 --- a/src/lib/components/Modal.svelte +++ b/src/lib/components/Modal.svelte @@ -12,7 +12,7 @@ }; export const isOpen = () => open; - const close = () => { + export const close = () => { open = false; dialog.close(); };