-
Notifications
You must be signed in to change notification settings - Fork 239
Add keyboard macros #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add keyboard macros #305
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
5650bad
add jsonrpc keyboard macro get/set
Savid 2ba8e19
add ui keyboard macros settings and macro bar
Savid 452e782
use notifications component and handle jsonrpc errors
Savid 2766f50
cleanup settings menu
Savid 7cac289
return error rather than truncate steps in validation
Savid c65d222
feat(ui): add className prop to Checkbox component to allow custom st…
Savid 669e424
use existing components and CTA
Savid 6406400
extract display key mappings
Savid 223558a
create generic combobox component
Savid 5c3424e
remove macro description
Savid 0206d79
cleanup styles and macro list
Savid 48d8523
create sortable list component
Savid 7b87258
split up macro routes
Savid 4438dbb
remove sortable list and simplify
Savid 54d0118
cleanup macrobar
Savid 0651cb8
use and add info to fieldlabel
Savid 8a05696
add useCallback optimizations
Savid 5fcc1f4
add confirm dialog component
Savid 7d5cf91
cleanup delete buttons
Savid 10dbdf7
merge dev
Savid 95eb908
revert info on field label
Savid 6b6b862
cleanup combobox focus
Savid 40acb6e
cleanup icons
Savid dc51218
Merge branch 'dev' into feat/macros
Savid 36d427b
set default label for delay
Savid File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| import { useRef } from "react"; | ||
| import clsx from "clsx"; | ||
| import { Combobox as HeadlessCombobox, ComboboxInput, ComboboxOption, ComboboxOptions } from "@headlessui/react"; | ||
| import { cva } from "@/cva.config"; | ||
| import Card from "./Card"; | ||
|
|
||
| export interface ComboboxOption { | ||
| value: string; | ||
| label: string; | ||
| } | ||
|
|
||
| const sizes = { | ||
| XS: "h-[24.5px] pl-3 pr-8 text-xs", | ||
| SM: "h-[32px] pl-3 pr-8 text-[13px]", | ||
| MD: "h-[40px] pl-4 pr-10 text-sm", | ||
| LG: "h-[48px] pl-4 pr-10 px-5 text-base", | ||
| } as const; | ||
|
|
||
| const comboboxVariants = cva({ | ||
| variants: { size: sizes }, | ||
| }); | ||
|
|
||
| type BaseProps = React.ComponentProps<typeof HeadlessCombobox>; | ||
|
|
||
| interface ComboboxProps extends Omit<BaseProps, 'displayValue'> { | ||
| displayValue: (option: ComboboxOption) => string; | ||
| onInputChange: (option: string) => void; | ||
| options: () => ComboboxOption[]; | ||
| placeholder?: string; | ||
| emptyMessage?: string; | ||
| size?: keyof typeof sizes; | ||
| disabledMessage?: string; | ||
| } | ||
|
|
||
| export function Combobox({ | ||
| onInputChange, | ||
| displayValue, | ||
| options, | ||
| disabled = false, | ||
| placeholder = "Search...", | ||
| emptyMessage = "No results found", | ||
| size = "MD", | ||
| onChange, | ||
| disabledMessage = "Input disabled", | ||
| ...otherProps | ||
| }: ComboboxProps) { | ||
| const inputRef = useRef<HTMLInputElement>(null); | ||
| const classes = comboboxVariants({ size }); | ||
|
|
||
| return ( | ||
| <HeadlessCombobox | ||
| onChange={onChange} | ||
| {...otherProps} | ||
| > | ||
| {() => ( | ||
| <> | ||
| <Card className="w-auto !border border-solid !border-slate-800/30 shadow outline-0 dark:!border-slate-300/30"> | ||
| <ComboboxInput | ||
| ref={inputRef} | ||
| className={clsx( | ||
| classes, | ||
|
|
||
| // General styling | ||
| "block w-full cursor-pointer rounded border-none py-0 font-medium shadow-none outline-0 transition duration-300", | ||
|
|
||
| // Hover | ||
| "hover:bg-blue-50/80 active:bg-blue-100/60", | ||
|
|
||
| // Dark mode | ||
| "dark:bg-slate-800 dark:text-white dark:hover:bg-slate-700 dark:active:bg-slate-800/60", | ||
|
|
||
| // Focus | ||
| "focus:outline-blue-600 focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 dark:focus:outline-blue-500 dark:focus:ring-blue-500", | ||
|
|
||
| // Disabled | ||
| disabled && "pointer-events-none select-none bg-slate-50 text-slate-500/80 dark:bg-slate-800 dark:text-slate-400/80 disabled:hover:bg-white dark:disabled:hover:bg-slate-800" | ||
| )} | ||
| placeholder={disabled ? disabledMessage : placeholder} | ||
| displayValue={displayValue} | ||
| onChange={(event) => onInputChange(event.target.value)} | ||
| disabled={disabled} | ||
| /> | ||
| </Card> | ||
|
|
||
| {options().length > 0 && ( | ||
| <ComboboxOptions className="absolute left-0 z-[100] mt-1 w-full max-h-60 overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black/5 dark:bg-slate-800 dark:ring-slate-700 hide-scrollbar"> | ||
| {options().map((option) => ( | ||
| <ComboboxOption | ||
| key={option.value} | ||
| value={option} | ||
| className={clsx( | ||
| // General styling | ||
| "cursor-default select-none py-2 px-4", | ||
|
|
||
| // Hover and active states | ||
| "hover:bg-blue-50/80 ui-active:bg-blue-50/80 ui-active:text-blue-900", | ||
|
|
||
| // Dark mode | ||
| "dark:text-slate-300 dark:hover:bg-slate-700 dark:ui-active:bg-slate-700 dark:ui-active:text-blue-200" | ||
| )} | ||
| > | ||
| {option.label} | ||
| </ComboboxOption> | ||
| ))} | ||
| </ComboboxOptions> | ||
| )} | ||
|
|
||
| {options().length === 0 && inputRef.current?.value && ( | ||
| <div className="absolute left-0 z-[100] mt-1 w-full rounded-md bg-white dark:bg-slate-800 py-2 px-4 text-sm shadow-lg ring-1 ring-black/5 dark:ring-slate-700"> | ||
| <div className="text-slate-500 dark:text-slate-400"> | ||
| {emptyMessage} | ||
| </div> | ||
| </div> | ||
| )} | ||
| </> | ||
| )} | ||
| </HeadlessCombobox> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.