GithubHelp home page GithubHelp logo

benwinding / command-pal Goto Github PK

View Code? Open in Web Editor NEW
67.0 2.0 8.0 682 KB

The hackable command palette for the web, inspired by Visual Studio Code.

Home Page: https://benwinding.github.io/command-pal/docs

License: MIT License

HTML 63.95% JavaScript 9.50% CSS 2.18% Svelte 24.36%
command-palette html js micro-framework

command-pal's Introduction

command-pal

⌨ The hackable command palette for the web, inspired by Visual Studio Code.

NPM Version License Downloads/week Github Issues

screen cap

Configure custom commands with custom keyboard shortcuts!

Demos

Benefit's of Command Palettes

  • Ease of use
    • Simply 1 keyboard shortcut to remember
    • Fuzzy search allows you to find commands easily
  • Speed
    • Keyboard makes it fast to access any command/function
    • Fuzzy search allows for quick ordering of commands
    • Efficient to find a commands that you used once a long time ago
  • Discoverability
    • You can scroll down the entire list of commands
    • Find commands by simply searching the Command palette
    • Tips and functions can be given to you as you type

Features

  • JS framework agnostic (can be attached to any site)
  • Keyboard first control (shortcuts configurable)
  • Custom commands
  • Dynamically Add/Remove commands
  • Nested commands
  • Fuzzy text matching (fuse.js)
  • Themeable (theme-light.css and theme-dark.css included)
  • Mobile friendly (button in bottom-left)

screen cap

Why?

Command Palettes have alwyas impressed me with how easy they are to use and develop for. I rarely see them on the web platform, so I thought I'd give it a shot.

Get Started

Install

Either install from npm

yarn add command-pal

Or use the script tag

<script src="https://cdn.jsdelivr.net/npm/command-pal"></script>

Usage - Simple

const c = new CommandPal({
  hotkey: "ctrl+space",
  commands: [
    {
      name: "Send Message",
      shortcut: "ctrl+m",
      handler: () => alert("Send Message"),
    },
    {
      name: "Search Contacts",
      handler: () => alert("Searching contacts..."),
    },
    {
      name: "Goto Profile",
      shortcut: "ctrl+4",
      handler: () => window.location.hash = "profile",
    },
  ],
});
c.start();

Usage - Advanced

const c = new CommandPal({
  hotkey: "ctrl+space",
  placeholder: "Custom placeholder text...",
  commands: [
    {
      name: "Change Language",
      children: [
        {
          name: "English",
          handler: () => alert("Changing to English")
        },
        {
          name: "Spanglish",
          handler: () => alert("Changing to Spanglish")
        }
      ]
    },
    {
      name: "Goto About",
      handler: () => window.location.hash = "about",
    },
  ],
});
c.start();

API

CommandPal instance

const c = new CommandPal({
  hotkey: "ctrl+space",  // Launcher shortcut
  hotkeysGlobal: true,       // Makes shortcut keys work in any <textarea>, <input> or <select>
  id: "CommandPal", // adds unique ID to aid in targeting with CSS
  placeholder: "Custom placeholder text...", //  Changes placeholder text of input
  debugOuput: false, // if true report debugging info to console
  hideButton: false, // if true, do not generate mobile button
  commands: [
    // Commands go here
  ]
});
// Start the instance
c.start()
// Destroy the instance
c.destroy()

Subscribe to events

There's a few events that can be subscribed to during command-pal's execution.

// When a command is executed
c.subscribe("exec", (e) => { console.log("exec", { e }); });
// On TextChanged
c.subscribe("textChanged", (e) => { console.log("textChanged", { e }); });
// When a command palette is opened
c.subscribe("opened", (e) => { console.log("opened", { e }); });
// When a command palette is closed
c.subscribe("closed", (e) => { console.log("closed", { e }); });

Command Item

{
  // Required name of command (displayed)
  name: "Open Messages",
  // Required name of command (displayed)
  description: "View all messages in inbox",
  // Shortcut of command
  shortcut: "ctrl+3",
  // Callback function of the command to execute
  handler: (e) => {
    // DO SOMETHING
  }
  // Child commands which can be executed
  children: [...]
},

Command Item Child

Note: Child commands cannot have shortcuts.

{
  // Required name of command (displayed)
  name: "Open Messages",
  // Description of command, used in matching command (not displayed)
  description: "View all messages in inbox",
  // Callback function of the command to execute
  handler: (e) => {
    // DO SOMETHING
  }
},

Add/Remove Command's At Runtime

The command list is an observed array, which means you can modify it even after it's instantiated. The following snippet shows how commands can be dynamically added during runtime.

const commands = [
  {
    name: "Add Command to List",
    handler: () => {
      commands.push({
        name: 'New Command',
        handler: () => {
          // Do something
        },
      });
    },
  },
];
const c = new CommandPal({
  hotkey: "ctrl+space",
  commands: commands,
});
c.start();

Styling CommandPal instances

The styles used by command-pal are included in the package. However you can override the default CSS using the following.

  /* mobile button */
  #CommandPal .mobile-button  { top: 30px; }
  /* modal background */
  #CommandPal .modal-mask { background-color: rgb(0,128,200,0.75); }
  /* item background */
  #CommandPal [slot=items] { background-color: yellow;}
  /* item text */
  #CommandPal .item { color:black; }

You can also assign a custom id to the CommandPal instance.

   c = CommandPal(..., id: 'mypal',)

Which allows you to style a specific instance.

  /* mobile button for CommandPal with id='mypal' */
  #mypal .mobile-button  { top: 30px; bottom: auto;}

Local Development

To develop on command-pal simply clone, install and run

npm run dev

Then the following link:

Prevent Blur

When the search input loses focus (receives a blur event), the palette closes. This makes inspecting the palette using the browser's DevTools difficult, as switching to DevTools causes the focus to be lost. It is possible to stop the palette from closing when focus is lost.

// Disable palette from closing during testing
window.commandPalIgnoreBlur = true;
// Re-enable
window.commandPalIgnoreBlur = false;

To close the palette. focus/select the search input and press the escape ESC key.

Have a go, PR's and issues always welcome.

Prior Art

Many applications have implemented this before, here's a few. My favourite implementation is the VScode, which is the main influence for this project.

Editors

Misc

command-pal's People

Contributors

benwinding avatar dependabot[bot] avatar marlamin avatar rouilj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

command-pal's Issues

Support for finding commands via additional keywords

Hello:

I was looking for a command palette to add to my roundup issue tracker tracker template. It looks like command-pal and ninja-keys are the only two implementations that work with vanilla JS.

Fuzzy search works well for typos, but suppose I want a search for email to find the "Contact" command in my palette?
Obviously fuzzy search won't handle that. Is there an alias/keyword array property that fuzzy search will look at to select the Contact field? I envision something like:

  commands: [
    {
      name: "Contact author",
      shortcut: "ctrl+E",
      handler: () => alert("Send Message"),
      aliases: [ "email", "reply", "send", "to author"],
    },

I suppose I could create child commands:

  function SendEmail () { ... }
  commands: [
    {
      name: "Contact author",
      shortcut: "ctrl+E",
      handler: () => SendEmail(),
      children: [
        {
            name: "Email author",
            shortcut: "Hmm, why no shortcut?"
            handler: SendEmail(),
        },
        {
            name: "Reply to author",
            handler: SendEmail(),
        },
        {
            name: "Send message to author",
            handler: SendEmail(),
        },
       ...,
    },

but that seems suboptimal for a few reasons:

  1. More code is required to implement.
  2. The UI requires navigating into the "Contact Author" command submenu. This requires retyping the search rather than just selecting the primary menu item.
    • Also by navigating into the submenu, you loose context. Only the submenu items are shown, there is no breadcrumb. For example: in your advanced language example, you can search for German, and it shows "Change Language". But once you change to the submenu, there is no hint that you are under the "Change Language" submenu. The prompt doesn't change to indicate where you are in the hierarchy.
    • Ideally your language example should show "Change Language > German" displayed as selection when you type "Ger" in the search box from the top level.
  3. It's not obvious that all these synonyms use the same command and shortcut since they are displayed as different menu items.
  4. It doesn't guide the user to understand the canonical term (and the ability to use a shortcut) for the command.

Thoughts?

Allow icon's in CommandList

I have this working:

image

The changes are pretty minimal. I'll link a pull request here in a few.

It is used with a command array like:

	  {
	    name: "Toggle Dark/Light Theme",
            shortcut: "ctrl+1",
	    icon: null,
            handler: () => {...}
          },
          {
            name: "Change Language",
            shortcut: "ctrl+shift+l",
	    icon: '<span class="icon">&nbsp;></span>',
            handler: () => {...}
         },
          {
            name: "Goto About",
            shortcut: "ctrl+d",
            handler: () => (window.location.hash = "about"),
	    icon: '<img src="../Cjdowner-Cryptocurrency-ICON.512.webp">'
          },
          {
            name: "Destroy Instance",
	    icon: '<svg version="1.1" id="Uploaded to svgrepo.com" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="24px" viewBox="0 0 32 32" xml:space="preserve"><path d="M17,9v0.459v1.468l1.401,0.44C21.75,12.419,24,15.487,24,19c0,4.411-3.589,8-8,8s-8-3.589-8-8 c0-3.513,2.25-6.581,5.599-7.633L15,10.927V9.459V9H17 M17.95,2C16.323,2,15,3.323,15,4.95V7h-2v2.459C8.943,10.734,6,14.523,6,19 c0,5.523,4.477,10,10,10s10-4.477,10-10c0-4.477-2.943-8.266-7-9.541V7h-2V4.95C17,4.426,17.426,4,17.956,4 c0.318,0,0.614,0.158,0.791,0.423l0.843,1.265C20.139,6.51,21.057,7,22.05,7C23.677,7,25,5.677,25,4.05V3h-2v1.05 C23,4.574,22.574,5,22.044,5c-0.318,0-0.614-0.158-0.791-0.423L20.41,3.312C19.861,2.49,18.943,2,17.95,2L17.95,2z M15,12.08 c-3.386,0.488-6,3.401-6,6.92h2c0-2.414,1.721-4.434,4-4.899V12.08z"/></svg>',
            handler: () => {...}

It supports 5 cases:

  1. if icon is not defined, it inserts an empty svg that holds 24px of space on the left of the label
  2. if icon is null, the space is not held and the label smooshes to the left (first item)
  3. if icon is a character, the character is used. You can pad it with &nbsp; to add space on the left side. If the string is
    longer than 24 px, it's cut off. (second item)
  4. the icon can be an image, css sized to 24x24px. (third item)
  5. the icon can be an svg, css sized to 24x24px fill set to currentColor. (fourth item)

The icon is separated from the text by .5em of space.

I have one question. For cases 1 and 2, should there be an option for CommandPal that swaps
them. So that a missing icon: doesn't reserve 24px of white space on the left?
In this case setting icon: null would result in an empty 24x24px space.

The reason I bring this up is that a user may not want any icons at all. e.g. for the list of languages, I have
no icons. I could add: icon:null" to each language command. But I think for that case it would be better to have
CommandPal not reserve the icon space.

Thoughts?

Command palette button needs some love

The little command terminal button on the lower left is a nice touch for mobile users. However it is too small.
Also it has a weird spacing compared to the border which is noticeable with larger line-heights.

Changing the svg declaration to add a viewport:

<svg viewport="0 0 24 24"... >

will let you scale up the size of the svg terminal prompt using css. The css I would use with it is:

.mobile-button > svg {
   width: 44px;
   height: 44px;
   display: block;
}

to provide a minimal size of 44px for the button.

display: block is used to remove space below the svg icon. Since the default display is inline, the icon
sits on the text baseline.

I would also add a title tag as the first element between the > for the svg tag and first g tag.

<title>Click here to open command palette.</title>

so the svg has some a11y accessible name. In thinking about it, probably adding that text as aria-label to the button element would be better. Maybe aria-label="Open Command Palette" would work.

Getting full aria working for command-pal is another set of steps, but I expect it would be useful for users.

Adding dynamic command seems to not be searchable until after command pallete is opened

Hello:

I am creating a command to copy the current URL to the clipboard. Since the user may not have given
me permission, or the clipboard API may not be available, I run some code to determine that the prerequisites
are available and add it dynamically.

To do this, I define a commands array and follow along with the documentation:

commands = [ {...}, {...},
      {
      name: "Add new entry here",
      handler: () => (add_new_entry(commands)),
    },
 ];

function add_new_entry (c) {
    c.push( {
        name: "New Command Here",
        handler: () => (alert("I'm a new command!!!") ),
          )
}

const c = new CommandPal({
  hotkey: "ctrl+space",
  commands: commands,
});

function add_copy_url_to_clipboard (c) {
    if ( ! navigator.clipboard ) return;
    navigator.permissions.query({name: "clipboard-write"}).then(
        function (result) {
            if (result.state === "granted") {
                c.push( {
                    name: "Copy URL to Clipboard",
                    handler: () => (navigator.clipboard.writeText(
                        window.location.href)), }
                      )
            }
        }
    )
}

add_copy_url_to_clipboard(commands)

c.start();

If I activate command-pal, I can see the "Copy URL to Clipboard" entry listed, but searching for URL doesn't
find it. If I exit (esc key) from command-pal and re-activate it, search for URL works.

Even on the first activation, I can choose the "Copy URL to Clipboard" item by arrowing down to it and it works as expected.

It looks like the dynamic entry is unsearchable only if it is the first invocation after the page loads.

If I choose the "Add new entry here" item (by search or arrow keys), I can see the new entry when I
re-activate the command-pal and I can search for "New command here" successfully.

What's weird is even if I change the code to read:

add_copy_url_to_clipboard(commands)

const c = new CommandPal({
  hotkey: "ctrl+space",
  commands: commands,
});

c.start();

searching still fails until the second restart. printing commands to the console shows what I expected.

I'm at a loss to explain this.

With command-pal deactivated, if I call add_new_entry(commands) in the console then activate command-pal,
the new item is not there. If I close and re-open command-pal the item is there and is searchable.

Am I doing something wrong?

Console is not reporting any errors.

Browser: Version 109.0.5414.120 (Official Build) (64-bit) on windows 10.

Ideas welcome.

-- rouilj

After destroying command-pal command hotkeys still trigger.

Using cp-advanced/index.html. If I click 'Destroy Instance' and then press ctrl+space
and watch the console I see:

opened 
Object { e: {} }
e: Object {  }
<prototype>: Object { … }

I I then type ctrl+d I see:

opened  Object { e: {} }
exec Object { e: {…} }
​    e: Object { name: "Goto About", shortcut: "ctrl+d", handler: handler()}
​<prototype>: Object { … }

Looks like destroy needs to remove the hotkey and all the shortcuts it added using hotkeys.js.
hotkeys.unbind() should work.

However if the app calling command-pal is also using hotkeys, this would wipe out their hotkeys as well.

You could loop through each hotkey/shortcut and unbind it.

However using hotkeys scope could provide another solution.

// register shortcuts in command-pal scope
export function setAllShortCuts(items, onExecCallback) {
  items
    .filter((item) => item.shortcut)
    .map((item) => {
      hotkeys.unbind(item.shortcut, 'command-pal' );
      hotkeys(item.shortcut, { scope: "command-pal"}, async function (e) {
        e.preventDefault();
        onExecCallback(item)
      });
    });

Use the 'command-pal' scope similarly when the hotkey that activates command pal.

Add:

hotkeys.setScope('command-pal');

to initShortCuts() to activate the command-pal scoped hotkey.

This will make all the command-pal shortcuts only work while hotkeys.getScope() == 'command-pal'.

When calling CommandPal.destroy, use hotkeys.deleteScope('command-pal') to delete all keybidings freeing all the resources. It should leave untouched hotkeys in other scopes (including the default "all"
scope).

Arguably we could expose an option hotkeysScope when calling CommandPal to allow the user to
control this better (e.g. add the hotkey/shortcuts to the 'all' scope).

Also scope allows the user to disable command-pal hotkeys if they are in a modal where they don't
want command-pal to be active. (Although adding enable/disable methods would probably be a
better way to expose this than having the user use hotkeys directly.)

I define this as done when I can't use the hotkeys after deleting the command-pal instance.
The rest of the stuff is not key to this ticket.

[Question] is this still actively maintained?

I last saw activity stretching 7 months ago and there are 11 pull requests most of which seem to be ready to be merged

I'm wondering politely if this is still actively maintained as it's hard to find a nice command palette that's not restricted to any js frameworks

Allow handler to determine how it was invoked

Right now the handler function doesn't get any argument. Would it be possible to have the handler
get information about how it was invoked. The use case is to allow the user to search for recent pages
that were accessed.

If the user hit enter or clicked on the entry the selected page from the command menu replaces the current page.
If he user crtl+click or ctlr+entered to select the page from command-pal, the page would be opened in a new
window/tab instead.

CommandPal hotkey doesn't work if browser binds the hotkey and you are in an input/textarea.... (e.g. ctrl-k)

Hi Ben:

When I first started using command-pal, I tried binding it to a key that was used to trigger a menu item in my
browser. It would only work some of the time and I didn't figure out what was going on.

I think the issue is that the hotkey defined for command-pal overrides the browser hotkey, but only when you are
not in a text input or textarea. I.E. the equivalent of hotkeysGlobal=True needs to be enabled for the hotkey.

I think defining the hotkeys.filter function defined by initShortCuts to return true if the key matches the
command-pal hotkey will do the trick. How to implement this, I am not sure. Ideally this should be settable from the
CommandPal({}) configuration object.

I haven't seen any activity from you in a while.
Hope your doing well.

-- rouilj

multi instance support - styling

It looks like it's possible to call new CommandPal multiple times.

Each instance can be bound to different hotkeys and this works to activate the correct instance.
However there is a problem with styling the instances and handling the buttons.

  1. all the buttons overlap and there is nothing in the markup that allows you to distinguish
    the buttons for different instances (so you can set a different top/bottom etc).
  2. all activated command palettes are the same structurally. There is nothing for css to use to
    tell one activated palette from another.

For example, how do you style one palette with a background/backdrop of: rgb(0,0,0.5), a semi-transparent
black (default), while another palette has a background of rgb(255,0,0.5), a semitransparent red? Right now styling
via CSS needs to be done via javascript. E.G. this changes the backdrop color:

document.querySelector('div.modal-mask:not(.hidden)').style.backgroundColor = 'rgb(255,0,0.5)'

I think this results in at least FOUC since you
would have to do it by responding to the opened event.

It looks like the structure of an activated palette is:

<div>
  <button class="mobile-button svelte-random_string">...</button>
  <div class="modal-mask svelte-random_string">...</div>
</div>

the div.modal-mask has a hidden class if it is not active. So you can target an element of the
currently activated command palette using:
`` `
document.querySelectorAll('div.modal-mask:not(.hidden) [slot=items]')

to isolate the item list for the non-hidden pallete. (Since this is expected to return just one element,
you can use querySelector instead. But testing to make sure your selector really isolates one item is
probably not a bad idea.)

I can make the background of the non-selected list items red by using:

document.querySelector('div.modal-mask:not(.hidden) [slot=items]').style.backgroundColor = "red"


I propose adding an option to CommandPal called id. This could be reflected in the markup as:
```html
<div id="myId">
  <button class="mobile-button svelte-random_string">...</button>
  <div class="modal-mask svelte-random_string">...</div>
</div>

so that pure CSS styles like:

  #myId [slot=items] { background-color: red; }
  #myid > button { bottom: 40px; }

would be applied to this instance of CommandPal and it's button but not any other instance. Since the
CSS would already be loaded, FOUC should not be an issue.

An alternate way to do this would be:

<div>
  <button class="mobile-button svelte-random_string" id="button-myId">...</button>
  <div class="modal-mask svelte-random_string" id="myId">...</div>
</div>

I am not sure which is better. From a CSS perspective I don't think it matters as selecting/styling the outer div
doesn't seem to do anything.

Thoughts?

[Edited to remove id on button element. That must have been something I did somehow while I was debugging 8-/. There is no id in the command-pal component AFAICT.]

Add CommandPalette.version property.

Would it be possible to add a version property to CommandPal? Would something like:

class CommandPal {

  version = "0.2.7";

  constructor(options) {
    console.log("CommandPal", { options });
    this.options = options || {};
    this.ps = pubsub.create();
  }

make:

cp = new CommandPal({
         commands: { 
              name: "CommandPal version",
              handler = () => (alert("CommandPal version " + CommandPal.version )),
              },
              name:  "Another version method",
              handler = () => (alert("CommandPal version " + cp.version )),
         }
      });

work?

Also in the docs, the handler definition is shown as:

// Callback function of the command to execute
  handler: (e) => {
    // DO SOMETHING
  }

What is e? From my testing it looks like it is undefined.

I assume there is some mechanism driven off of package.json to keep the version identifier up to date?

How to create dev environment

Hi Ben:

So far I have cloned the repo. Then added:

% sudo apt-get install npm

then after npm run dev reported it can't find rollup I did:

% sudo apt-get install rollup

Now I get:

%  npm run dev

> [email protected] dev
> rollup -c -w

[!] Error: Cannot find module 'rollup-plugin-svelte'
Require stack:
- /home/rouilj/develop/command-pal/rollup.config.js
- /usr/share/nodejs/rollup/dist/shared/loadConfigFile.js
- /usr/share/nodejs/rollup/dist/bin/rollup
Error: Cannot find module 'rollup-plugin-svelte'
Require stack:
- /home/rouilj/develop/command-pal/rollup.config.js
- /usr/share/nodejs/rollup/dist/shared/loadConfigFile.js
- /usr/share/nodejs/rollup/dist/bin/rollup
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/home/rouilj/develop/command-pal/rollup.config.js:5:14)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.require.extensions.<computed> [as .js] (/usr/share/nodejs/rollup/dist/shared/loadConfigFile.js:619:20)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Module.require (internal/modules/cjs/loader.js:887:19)

and the command hangs. ^c gets me back to the prompt.

apt search svelte doesn't return any hits.

% npm install rollup-plugin-svelte

works, but generates a bunch (20+) of deprecation warnings including for [email protected]
(upgrade to core > 3.23.3), highlight.js etc.

54 vulnerabilities (1 low, 20 moderate, 28 high, 5 critical)

is the result.

However npm run dev does start a server. Navigating to it and opening public/cp-advanced/
gives me a working page that I can invoke command-pal. However inspecting the button icon shows me an SVG without the viewBox. Checking the source in src/MobileButton.svelte shows the viewBox.

Where do I go from here?

Am I missing a build/update step or something?

Details:

OS Ubuntu 22.04
nodejs 12.22.9

npm list
[email protected] /home/rouilj/develop/command-pal
├── @rollup/[email protected]
├── @rollup/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

Detecting key state when executed

Ben,
is it possible to detect the shift and ctrl key states when an items is selected with keyboard (Shift+enter or shift+click).

thank you

Where does the description property get used?

In the documentation you have a name and a description property. In the codepen example I changed the first command item from:

  {
      name: "Goto Profile",
      handler: () => (window.location.hash = "profile"),
      shortcut: "ctrl+9",
    },

to

  {
      name: "Goto Profile",
      handler: () => (window.location.hash = "profile"),
      shortcut: "ctrl+9",
      description: "See my profile",
    },

Looking at the console output, I can see that the code is processing the updated command definition, but I don't
see the description shown anywhere. It does seem to be used for fuzzy matching though. So maybe that's my
answer for issue #8? Although I would expect a description to be shown to the user and not be used just for search matching.

key activation in textarea

Ben,
Is it possible for the activation key to work from a textara? I have CP loading when nothing is loaded in the UI, but it would be nice if it can be activated from any context.

Warm regards

Method to open/close palette.

If I create an instance of command-pal, can I activate it from a button I create?

It looks like the hotkey or clicking on the button set internal state, but that state isn't accessible to to me.

I guess I need to have App invoke callback into main.js similar to how shortcuts.js implements hotkeys right?

Accessing internal state of CP from command handlers.

I am looking at implementing a formatting function for a text area to be triggered from
command pal. To do this, being able to see what control was focused when command-pal
was invoked would be valuable.

Obviously I can't find that when command-pal is active as focus is in the search input.
In pull #33 I set focusedElement to store that data when command-pal is activated by
hotkey or button click.

It would be nice to access that from c.focusedElement (c=CommandPal(...)) or something.
Any ideas on how to do this cleanly?

I did manage to add a new displayPalette() method on #28. But the implementation feels hacky.

ESC and arrow keystrokes on mobile are not recognized

For some reason ESC, arrow (from hacker's keyboard) and other keys aren't being processed properly
on android.

I am trying to fix that now. If the palette takes up the whole screen, there is no easy way to shift focus
out of the search input. If the palette exceeds the window even figuring out how to close the keyboard doesn't show the backdrop to generate a blur event.

It looks like e.code.toLowerCase is returning undefined but e.key works.
Still investigating.

Dynamic list of commands?

Hello, very nice tool you have built here. is it possible to provide a list of dynamic commands? Basically I have a need where I have a list of commands that are static and a list that I have to generate dynamically when the palette is opened.

The examples you have here seem to be static, predefined in advanced.

Thank you

Sadly CSP need unsafe-nonce to work

Very nice JS library you have here.

I spent the weekend working with it and I like it. Unfortunately I have to change the content security policy to
include unsafe-inline to make it work. The diff of my CSP is:

-       "style-src 'self' 'nonce-{nonce}'; "
+       "style-src 'self' 'unsafe-inline'; "

sadly this is kind of deal breaker. I did some searching for svelte and CSP and it seems they did have some
issues with it in the past, but they were resolved. It's possible that rebuilding with updated dependencies will fix
this. However I am not steeped enough in svelte, npm etc. to try it myself.

Any chance you can look into this and see if it is easily fixable?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.