Skip to content

Commit

Permalink
feat: add @vgerbot/shortcuts-solid
Browse files Browse the repository at this point in the history
  • Loading branch information
y1j2x34 committed Apr 9, 2024
1 parent 0470b74 commit 27370b7
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 0 deletions.
99 changes: 99 additions & 0 deletions packages/solid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# @vgerbot/shortcuts-solid

`@vgerbot/shortcuts-solid` is a Solid.js library that provides a set of utilities for easily integrating keyboard shortcuts into your Solid.js applications. It is built on top of the `@vgerbot/shortcuts` library, which handles the underlying keyboard event management.

## Installation

```bash
npm install @vgerbot/shortcuts-solid
```

## Usage

### `KeyboardProvider`

The `KeyboardProvider` component is a Solid.js context provider that manages the keyboard instance and its options. It should be wrapped around the parts of your application where you want to use keyboard shortcuts.

```jsx
import { KeyboardProvider } from '@vgerbot/shortcuts-solid';

const App = () => (
<KeyboardProvider>
{/* Your app components */}
</KeyboardProvider>
);
```

You can pass options to the `KeyboardProvider` to configure the keyboard instance:

```jsx
<KeyboardProvider preventDefault stopPropagation>
{/* Your app components */}
</KeyboardProvider>
```

### `useKeyboard`

The `useKeyboard` hook returns a function that provides the keyboard instance, which can be used to register or unregister shortcut commands, add event interceptors, switch keyboard contexts, and more optionals manually. It also accepts an optional callback function that will be called with the keyboard instance.

```jsx
import { useKeyboard } from '@vgerbot/shortcuts-solid';

const MyComponent = () => {
const getKeyboard = useKeyboard((keyboard) => {
// Register a shortcut
const unregister = keyboard.register('save', () => {
console.log('Shortcut triggered!');
});
// Add an event interceptor
keyboard.addInterceptor((event, next) => {
// Intercept and handle keyboard events
// ...
return next(event);
});

// Switch keyboard context
keyboard.switchContext('editor');

// Unregister the shortcut
return unregister;
});

// Get the keyboard instance
const keyboard = getKeyboard();

// ...
};
```

### `useCommand`

The `useCommand` hook registers a keyboard shortcut with a provided command string and callback function.

```jsx
import { useCommand } from '@vgerbot/shortcuts-solid';

const MyComponent = () => {
useCommand('Ctrl+S', () => {
console.log('Shortcut triggered!');
});

// ...
};
```

### `useShortcutKeyMatch`

The `useShortcutKeyMatch` hook registers a keyboard shortcut with a provided shortcut object or string and callback function.

```jsx
import { useShortcutKeyMatch } from '@vgerbot/shortcuts-solid';

const MyComponent = () => {
useShortcutKeyMatch('Ctrl+S', () => {
console.log('Shortcut triggered!');
});

// ...
};
```
35 changes: 35 additions & 0 deletions packages/solid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@vgerbot/shortcuts-solid",
"version": "1.0.0",
"description": "Shortcuts for Solid-js",
"author": "y1j2x34 <[email protected]>",
"homepage": "https://github.com/y1j2x34/shortcuts/tree/main/packages/solid#readme",
"license": "MIT",
"main": "lib/index.cjs.js",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"publishConfig": {
"registry": "https://registry.npmmirror.com/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/y1j2x34/shortcuts.git"
},
"scripts": {},
"bugs": {
"url": "https://github.com/y1j2x34/shortcuts/issues"
},
"dependencies": {
"@vgerbot/shortcuts": "^1.0.0",
"solid-js": "^1.8.16"
},
"devDependencies": {},
"peerDependencies": {
"solid-js": ">= 1.8.0"
}
}
5 changes: 5 additions & 0 deletions packages/solid/src/context/KeyboardContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Keyboard } from '@vgerbot/shortcuts';
import { Context, createContext } from 'solid-js';
export const KeyboardContext = createContext<() => Keyboard>() as Context<
() => Keyboard
>;
74 changes: 74 additions & 0 deletions packages/solid/src/context/KeyboardContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
JSXElement,
ParentProps,
createEffect,
createSignal,
on,
untrack
} from 'solid-js';
import { KeyboardContext } from './KeyboardContext';
import { Keyboard } from '@vgerbot/shortcuts';

type Options = ConstructorParameters<typeof Keyboard>[0];

type InitKeyboardProviderProps = ParentProps<Options>;

type UserProvideKeyboardProps = ParentProps<{ keyboard: Keyboard }>;

export function KeyboardProvider(props: ParentProps<Options>): JSXElement;
export function KeyboardProvider(
props: ParentProps<{ keyboard: Keyboard }>
): JSXElement;
export function KeyboardProvider(
props: InitKeyboardProviderProps | UserProvideKeyboardProps
) {
if ('keyboard' in props) {
return (
<KeyboardContext.Provider value={() => props.keyboard}>
{props.children}
</KeyboardContext.Provider>
);
} else {
const [keyboard, setKeyboard] = createSignal(new Keyboard(props));
createEffect(() => {
const [eventOptions, macroRegistry] = untrack(() => [
props.eventOptions,
props.macroRegistry
]);
const oldKeyboard = keyboard();
if (oldKeyboard) {
oldKeyboard.destroy();
}
setKeyboard(
new Keyboard({
anchor: props.anchor,
eventOptions,
macroRegistry
})
);
});
createEffect(
on(
[() => props.eventOptions, () => props.macroRegistry],
([eventOptions, macroRegistry]) => {
const oldKeyboard = keyboard();
if (oldKeyboard) {
oldKeyboard.destroy();
}
setKeyboard(
new Keyboard({
anchor: props.anchor,
eventOptions,
macroRegistry
})
);
}
)
);
return (
<KeyboardContext.Provider value={keyboard}>
{props.children}
</KeyboardContext.Provider>
);
}
}
3 changes: 3 additions & 0 deletions packages/solid/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './useCommand';
export * from './useKeyboard';
export * from './useShortcutKeyMatch';
8 changes: 8 additions & 0 deletions packages/solid/src/hooks/useCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ShortcutEventHandler } from '@vgerbot/shortcuts';
import { useKeyboard } from './useKeyboard';

export function useCommand(command: string, callback: ShortcutEventHandler) {
useKeyboard(keyboard => {
return keyboard.on(command, callback);
});
}
16 changes: 16 additions & 0 deletions packages/solid/src/hooks/useKeyboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createEffect, useContext } from 'solid-js';
import { KeyboardContext } from '../context/KeyboardContext';
import { Keyboard } from '@vgerbot/shortcuts';

export function useKeyboard(
callback?: (keyboard: Keyboard) => void | (() => void)
) {
const getKeyboard = useContext(KeyboardContext);
if (callback) {
createEffect(() => {
const keyboard = getKeyboard();
return callback(keyboard);
});
}
return getKeyboard;
}
11 changes: 11 additions & 0 deletions packages/solid/src/hooks/useShortcutKeyMatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Shortcut, ShortcutEventHandler } from '@vgerbot/shortcuts';
import { useKeyboard } from './useKeyboard';

export function useShortcutKeyMatch(
shortcut: string | Shortcut,
callback: ShortcutEventHandler
) {
useKeyboard(keyboard => {
return keyboard.onShortcutKeyMatch(shortcut, callback);
});
}
2 changes: 2 additions & 0 deletions packages/solid/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './hooks';
export * from './context/KeyboardContextProvider';
8 changes: 8 additions & 0 deletions packages/solid/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js"
},
"extends": "../../tsconfig.json",
"include": ["src"]
}
46 changes: 46 additions & 0 deletions packages/solid/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@vgerbot/shortcuts@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@vgerbot/shortcuts/-/shortcuts-1.0.0.tgz#1d0341b3024f5d795d6cce9887040d072bc27f43"
integrity sha512-KqfEfkvi/mX+oeySNP55/mBQxM/rgA8dssx9UdiTN+TXqdaLkMr3af4bbzVVzioe5X6km5jJ1paJGXKdXgrVfA==
dependencies:
browser-detect "^0.2.28"

browser-detect@^0.2.28:
version "0.2.28"
resolved "https://registry.yarnpkg.com/browser-detect/-/browser-detect-0.2.28.tgz#5688fc22f638390614ebea4646483403fb20ebfb"
integrity sha512-KeWGHqYQmHDkCFG2dIiX/2wFUgqevbw/rd6wNi9N6rZbaSJFtG5kel0HtprRwCGp8sqpQP79LzDJXf/WCx4WAw==
dependencies:
core-js "^2.5.7"

core-js@^2.5.7:
version "2.6.12"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==

csstype@^3.1.0:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==

seroval-plugins@^1.0.3:
version "1.0.5"
resolved "https://registry.yarnpkg.com/seroval-plugins/-/seroval-plugins-1.0.5.tgz#eeded50d736d5e1dba142a72b0188df9f4e42b6d"
integrity sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==

seroval@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/seroval/-/seroval-1.0.5.tgz#d71ee540d936babaed92f56eda3e52d8e2a3deed"
integrity sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==

solid-js@^1.8.16:
version "1.8.16"
resolved "https://registry.yarnpkg.com/solid-js/-/solid-js-1.8.16.tgz#33ce9bff617154d5f4b889e1b2fb89d682b7a422"
integrity sha512-rja94MNU9flF3qQRLNsu60QHKBDKBkVE1DldJZPIfn2ypIn3NV2WpSbGTQIvsyGPBo+9E2IMjwqnqpbgfWuzeg==
dependencies:
csstype "^3.1.0"
seroval "^1.0.4"
seroval-plugins "^1.0.3"

0 comments on commit 27370b7

Please sign in to comment.