ssleptsov / ninja-keys Goto Github PK
View Code? Open in Web Editor NEWKeyboard shortcuts interface for your website. Working with static HTML, Vanilla JS, Vue, React, Svelte.
Home Page: https://ninja-keys-demo.vercel.app/
License: MIT License
Keyboard shortcuts interface for your website. Working with static HTML, Vanilla JS, Vue, React, Svelte.
Home Page: https://ninja-keys-demo.vercel.app/
License: MIT License
Currently in order to dismiss the command bar/palette from the page, the escape button needs to be hit twice.
Reproducible on demo site.
Is there currently a way to prevent the menu from opening when the hotkey (ctrl + k
) is invoked?
I have a scenario where the component which mounts the ninja-key
element has an initial loading state, and I would like to be able to prevent the command menu from opening while in the loading state.
Thanks
Getting the following when installing with html/js
<script type="module" src="https://unpkg.com/ninja-keys?module"></script>
GET https://unpkg.com/[email protected]/async-directive.js?module net::ERR_ABORTED 500 (Internal Server Error)
ref.js:1
GET https://unpkg.com/[email protected]/lit-html.js?module net::ERR_ABORTED 500 (Internal Server Error)
Hi @ssleptsov
Awesome library! I love it very much!
Could you please add "Close" button to dialog header? I can't close menu on phone and tablet. Also I would like to close dialog with mouse sometimes.
Thank you!
We're planning on making the ninja-keys as the primary search window for our tool. It works well for items which are defined already, but is there a way to make api requests and get data and show them in Ninja keys command palette?
CC: @ssleptsov
Hi,
can I change breadcrumbs depending on the URL? So if browser is on '/exercises' page ninja-keys menu breadcrumbs would be 'Main / Exercises '?
Thank you
Petr R.
Great library! It makes building cmd tools super easy!
I recently got a situation when I use ninja-keys
to work with my react project. I use global storage to store the state of ninja-keys
, but I don't know when should I set the state to false and I couldn't find any eventListener to check modal is open ore close.
If there is any way to listen modal state will be great!
Hello!
First of all thank you for such a nice library. I'm facing the following issue, steps to reproduce:
Relevant details
Thank you!
In this example you can see that the entries are clipped at the border of the Ninja window. How can the text be made to wrap?
🇺🇦
Huge thanks for making this very nice library! Is there any way to set the font-family for the whole modal?
I've tried
.ninja-keys {
--ninja-font-family: 'Titillium';
&::part(ninja-input) {
font-family: var(--ninja-font-family);
}
}
...but have found no way of setting the font for the breadcrumbs.
I'm using this with Vue2, so not sure if it's related to that.... It seems which ever items has children: []
, any item below that never gets rendered, but is still searchable.
data() {
return {
hotkeys: [
{id: 'Home', title: 'Home'},
{id: 'Publish', title: 'Publish'},
{id: 'Settings', title: 'Settings'},
{id: 'Theme', title: 'Theme', children: [{id: 'Light', title: 'Light Theme'}]}
]
}
}
data() {
return {
hotkeys: [
{id: 'Home', title: 'Home', children: [{id: 'Notifications', title: 'Notifications'}]},
{id: 'Publish', title: 'Publish'},
{id: 'Settings', title: 'Settings'},
{id: 'Theme', title: 'Theme'}
]
}
}
This may just be a configuration setup issue, but I'm not sure what I'm missing.
Using version 1.2.1
Is it possible to custom the to select
, to navigate
, to close
and move to parent
text content in the footer?
Hi, I have some zIndex > 1 elements, and the modal is hidden behind them.
Since, there is no shadow for outer div.modal
, it cannot be styled with shadow part method.
Is it possible to export zIndex varaible to be overwrited ?
Thanks for your great work.
I couldn't figure out how to get cmd+k or other keyboard shortcuts to work when these elements had the focus within ninja-keys.
However, I was able to get around this by importing the hotkeys-js
library myself and following the guidance in their docs (see https://github.com/jaywcjlove/hotkeys#filter)
import "ninja-keys"
import hotkeys from "hotkeys-js"
hotkeys.filter = _event => true
How exactly you implement this for your project is going to depend on what framework you're using, but this might get you close.
Ideally, this would be exposed as an attribute off of ninja-keys or a configuration option, but I wanted to create this issue in case anyone else ran into it.
I use the css below:
/* chrome, edge, not work🙃 */
ninja-keys::part(actions-list)::-webkit-scrollbar-thumb {
background-color: #bfbfbf;
outline: none;
border-radius: 6px;
}
ninja-keys::part(actions-list)::-webkit-scrollbar {
width: 6px;
height: 6px;
}
/* firefox, work🙂 */
ninja-keys::part(actions-list) {
scrollbar-width: thin;
}
Hi,
I'm trying to use ninja-keys in a project with latest ninja-keys 1.2.1, latest Vue 3.2.33 and Vite 2.9.6 (using <script setup>
).
While running the dev server, I get the warning "reactive-element.ts:66 Multiple versions of Lit loaded. Loading multiple versions is not recommended. See https://lit.dev/msg/multiple-versions for more information." Which might not be a big deal.
...but deployed / in production mode, I'm getting "DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "ninja-header" has already been used with this registry".
Any ideas at all what could be happening here? Are you able to set up ninja-keys using Vue/Vite/<script setup>
without errors?
Hey @ssleptsov I just found out that adding keys dynamically to ninja keys make the keyboard navigation navigate randomly inside ninja keys.
Is there a way to force render the list again, I believe this is specifically happening because we are adding the hot keys dynamically when the route changes like below.
hotKeys() {
return [...this.conversationHotKeys, ...this.goToCommandHotKeys];
},
The conversationHotkeys array gets added only if we're on a specific page.
Here's how it behaves.
If there's an event to re initiate the hot keys, I think this will definitely resolve the issue.
Frist of all, congrats for the amazing project!
I'd like to propose a default handle/fallback when the user want to search something that's not a explicitly command. Right now it works like this:
Throwing a error if the user press enter
.
I'd like to propose something like this:
const ninja = document.querySelector('ninja-keys');
ninja.defaultHandler = (query) => { /* do what you want here */ }
Using the exemple on the screenshot, the query
variable would return "nothing". For instance, I could call a search function on my inside defaultHandler
using the query
param:
ninja.defaultHandler = (query) => { myVeryOwnSearch(query) }
The defaultHandler
method would only be called if there's no command available to select (maybe fallbackHandler
is a better name).
First off I just want to say this is great, and I'm super excited to use Ninja Keys in an app I'm working on.
Webpack 5 is unable to compile a project using Ninja Keys, and needs some additional, and hopefully optional configuration.
Error when trying to compile with no Webpack configuration change:
ERROR in ./node_modules/ninja-keys/dist/ninja-keys.js 12:0-24
Module not found: Error: Can't resolve './ninja-header' in '<omitted>/node_modules/ninja-keys/dist'
Did you mean 'ninja-header.js'?
BREAKING CHANGE: The request './ninja-header' failed to resolve only because it was resolved as fully specified
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
I found a needed configuration change in this SO article, which helped me in adding the following to my webpack.config.js file:
// most of config omitted.
module: {
rules: [{
test: /\.m?js$/,
resolve: {
fullySpecified: false
}
}]
},
This isn't a problem for me right now, but I could see it becoming an issue, or at least a sticky point for others trying to get Ninja Keys up and running.
Thanks again!
I'm looking to integrate a search in to this, and I saw #9 was fixed which allows me to do this; however, the results don't show until after I clear the search results:
https://codesandbox.io/s/ninja-keys-demo-forked-u9gprl?file=/src/App.vue
In this example, when you open the ninja keys, there's 2 items. Then you search for "test" which will add the third, but you don't see the result. Then if you clear your search, you'll see that the 3rd item was added.
How can I get this to show the result at the time the search is being made?
Hey folks,
I am currently trying to integrate ninja-keys into my solidjs-app and tried to do so via the solid-wrapper as well as by using ninja-keys as standalone library. However
All basic navigation shortcuts on the modal don't seem to work for me (arrow keys, enter, esc etc.)
Any idea what I could be doing wrong?
// index.tsx
import { render } from 'solid-js/web'
import { Router } from '@solidjs/router'
import App from './App'
import './index.css'
import { hydrateStoresFromPersistence } from 'stores/hydrateStoresFromPersistence'
import CommandPalette from 'App/CommandPalette'
hydrateStoresFromPersistence()
render(
() => (
<Router>
<App />
<CommandPalette />
</Router>
),
document.getElementById('root') as HTMLElement
)
// CommandPalette
import { NinjaKeys } from 'solid-ninja-keys'
function CommandPalette() {
return (
<NinjaKeys
hotkeys={[
{
id: 'Overview',
title: 'Open Overview',
hotkey: 'cmd+o',
handler: () => {
console.log('navigation to overview')
},
},
{
id: 'Settings',
title: 'Open Settings',
hotkey: 'cmd+s',
handler: () => {
console.log('navigation to settings')
},
},
]}
/>
)
}
export default CommandPalette
Thanks in advance :)
I experience detached elements when using ninja keys. To show you what I mean I have made a small repro. Use MS Edge and open devtools and the panel called detached elements. Ninja keys is added on the Home page and should be removed on the other views. Ninja keys can not be removed by the garbage collector causing memory leaks. Here is a link to my repro https://lit-tiptap-example-h9lodq6rv-marcuslindblom.vercel.app
Related to #34
I have a page where I don't even load ninja-keys. It's a fairly static page to only display text, and never have user interaction on it.
However, since ninja keys is added in to my main.js build, this line still seems to get ran. I think that's mainly where that error is being thrown because it seems that since ninja-keys doesn't exist on this page, there's no inputRef to hook in to.
I think this should be fairly easy to duplicate. Add a page that includes the ninja-keys import, but don't actually add the <ninja-keys />
tag. Along with nothing else on the page.
This may be related to mobile browser issues, but I have about 7k bugsnag reports of this._inputRef.value is undefined
and Cannot read properties of undefined (reading 'focus')
which I was able to trace back to this line.
ninja-keys/src/ninja-header.ts
Line 124 in 52ccc0d
I'm not quite sure how this part works, but my guess is maybe a guard clause is needed to ensure _inputRef
exists and is the correct type?
I think an additional svelte example could be very helpful for some people.
I could get it to work in svelte (kind of) but i think a fully working svelte example would be very helpful
I tried installing Ninja keys with Nuxt 3, but I keep getting lots of errors. Any ides on how to use this?
Here's a repro - https://stackblitz.com/edit/nuxt-starter-sgpcca?file=app.vue
I want to change group-header padding.
below selector not work:
ninja-keys::part(actions-list) .group-header
How can I access the group-header so that I can change its style?
Thanks for creating this package! Although I am having some trouble integrating with Vue2, it seems very useful.
I understand that you've created this package mainly to work with several of your own Vue projects, so I was wondering if you have a working example using Vue2? I am not able to use Vue3 just yet, so hoping to get this working with Vue2.
The Vue example seems to be using Vue3, and the :data
with Vue2 doesn't seem to behave the same way (results in [[object Object], ...]
serialized on the DOM element.
Thanks
I am dynamically adding new data and passing it to Ninja keys, using this way this.$refs.ninjakeys.data = this.hotKeys
, but using the same ref to call the .open()
method does not seem to work.
Below .open does not seem to do anything.
handler: () => {
if (command.children) {
this.$refs.ninjakeys.open({ parent: command.id });
return { keepOpen: true };
} else {
this.openRoute(command.path(this.accountId));
}
}
After removing <ninja keys/>
and related DOM, requestAnimationFrame()=>this_ InputRef. value Focus()
Still working
Hey there,
Great work on this, I love it! I'm working on customizing Ninja Keys on my site and am having issues customizing the color of the placeholder text even with custom CSS.
Is it possible to have this added as a CSS variable anytime in the future or does a way to customize the placeholder already exist?
Great work again!
It would be nice if we could customize the commands' HTML, or at least be able to natively highlight the matched characters in the text (using bold probably) while searching. I think this makes searching more intuitive and allows for better queries on the future.
This issue is somewhat related to #16.
The idea here to have a similar functionality to the VS Code command palette (or other IDEs like it) in this regard.
The Codesandbox for Svelte integration currently errors with
Error Function called outside component initialization
I get a modal open when I hit cmd + k, but wont render the list items. I used the same code from the codesandbox example which was mentioned.
I am on vue version 2.6.12.
I am getting this below error.
TypeError: Cannot read properties of null (reading 'map')
I think this below method _flattern
is not getting its argument members
, this is on ninja-keys.js
line: 262.
key: "_flattern",
value: function _flattern(members, parent) {
var children = [];
return members.map(function (mem) {
var alreadyFlatternByUser = mem.children && mem.children.some(function (value) {
return typeof value == 'string';
});
var m = _objectSpread(_objectSpread({}, mem), {}, {
parent: mem.parent || parent
});
if (alreadyFlatternByUser) {
return m;
} else {
if (m.children && m.children.length) {
parent = mem.id;
children = [].concat(_toConsumableArray(children), _toConsumableArray(m.children));
}
m.children = m.children ? m.children.map(function (c) {
return c.id;
}) : [];
return m;
}
}).concat(children.length ? this._flattern(children, parent) : children);
}
```
[email protected]/lit-html.js - This file is responding with error 500, resulting in the non-functioning of Ninja Keys in HTML.
Ninja-keys HTML Sandbox is also not working.
Allow commands to be fuzzy-matched when searching (with something like https://github.com/farzher/fuzzysort, but not necessarily it).
Potentially also allow typos. e.g. for command named Open
allow searching using Opne
(within a threshold)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.