@solid-primitives/keyboard 2.0.0-next.1 → 2.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -156,6 +156,7 @@ Creates a keyboard shortcut observer. The provided callback will be called when
156
156
  - `options` — additional configuration:
157
157
  - `preventDefault` — call `e.preventDefault()` on the keyboard event, when the specified key is pressed. _(Defaults to `true`)_
158
158
  - `requireReset` — If `true`, the shortcut will only be triggered once until all of the keys stop being pressed. Disabled by default.
159
+ - `ignoreWithinInputs` — If `true`, the shortcut is ignored while focus is on an `input`, `textarea`, `select`, or `contenteditable` element, so it doesn't interrupt typing. Disabled by default.
159
160
 
160
161
  ```tsx
161
162
  import { createShortcut } from "@solid-primitives/keyboard";
@@ -175,6 +176,17 @@ When `preventDefault` is `true`, `e.preventDefault()` will be called not only on
175
176
 
176
177
  E.g. when listening for `Control + Shift + A`, all three keydown events will be prevented.
177
178
 
179
+ ### Ignoring shortcuts while typing
180
+
181
+ Single, unmodified-key shortcuts (e.g. `["S"]`) conflict with typing — pressing "s" in a text field would both type the character and trigger the shortcut. Set `ignoreWithinInputs: true` to skip the shortcut entirely while focus is on a form control or `contenteditable` element:
182
+
183
+ ```tsx
184
+ // won't fire while the user is typing in a text field
185
+ createShortcut(["S"], () => console.log("S was pressed"), { ignoreWithinInputs: true });
186
+ ```
187
+
188
+ Combos that include a modifier (e.g. `Control + S`) don't have this problem, since the modifier itself prevents a character from being typed — `ignoreWithinInputs` is usually unnecessary for those.
189
+
178
190
  ## `createKeyDown`
179
191
 
180
192
  Listens for a `keydown` event for a specific key on a document. Useful for global keyboard handlers that need to respond to a single key without setting up a full shortcut.
package/dist/index.d.ts CHANGED
@@ -131,17 +131,25 @@ export declare function createKeyHold(key: KbdKey, options?: {
131
131
  * @param options The options for the shortcut.
132
132
  * - `preventDefault` — Controls if the keydown event should have its default action prevented. Enabled by default.
133
133
  * - `requireReset` — If `true`, the shortcut will only be triggered once until all of the keys stop being pressed. Disabled by default.
134
+ * - `ignoreWithinInputs` — If `true`, the shortcut is ignored while focus is on an `input`, `textarea`, `select`,
135
+ * or `contenteditable` element, so typing isn't interrupted. Disabled by default — enable it for shortcuts
136
+ * made of plain, unmodified keys (e.g. a single letter); combos like `Control+S` are usually fine either way,
137
+ * since the modifier prevents a character from being typed.
134
138
  *
135
139
  * @example
136
140
  * ```ts
137
141
  * createShortcut(["CONTROL", "SHIFT", "C"], () => {
138
142
  * console.log("Ctrl+Shift+C was pressed");
139
143
  * });
144
+ *
145
+ * // won't fire while typing in a text field
146
+ * createShortcut(["S"], () => console.log("S was pressed"), { ignoreWithinInputs: true });
140
147
  * ```
141
148
  */
142
149
  export declare function createShortcut(keys: KbdKey[], callback: (event: KeyboardEvent | null) => void, options?: {
143
150
  preventDefault?: boolean;
144
151
  requireReset?: boolean;
152
+ ignoreWithinInputs?: boolean;
145
153
  }): void;
146
154
  export interface CreateKeyDownOptions {
147
155
  /** Whether the listener should be inactive. */
package/dist/index.js CHANGED
@@ -11,6 +11,19 @@ function equalsKeyHoldSequence(sequence, model) {
11
11
  }
12
12
  return true;
13
13
  }
14
+ /** Is the event target an editable form control, or inside a `contenteditable` element? */
15
+ function isEditableTarget(target) {
16
+ if (!(target instanceof HTMLElement))
17
+ return false;
18
+ switch (target.tagName) {
19
+ case "INPUT":
20
+ case "TEXTAREA":
21
+ case "SELECT":
22
+ return true;
23
+ default:
24
+ return target.isContentEditable;
25
+ }
26
+ }
14
27
  /**
15
28
  * Provides a signal with the last keydown event.
16
29
  *
@@ -244,12 +257,19 @@ export function createKeyHold(key, options = {}) {
244
257
  * @param options The options for the shortcut.
245
258
  * - `preventDefault` — Controls if the keydown event should have its default action prevented. Enabled by default.
246
259
  * - `requireReset` — If `true`, the shortcut will only be triggered once until all of the keys stop being pressed. Disabled by default.
260
+ * - `ignoreWithinInputs` — If `true`, the shortcut is ignored while focus is on an `input`, `textarea`, `select`,
261
+ * or `contenteditable` element, so typing isn't interrupted. Disabled by default — enable it for shortcuts
262
+ * made of plain, unmodified keys (e.g. a single letter); combos like `Control+S` are usually fine either way,
263
+ * since the modifier prevents a character from being typed.
247
264
  *
248
265
  * @example
249
266
  * ```ts
250
267
  * createShortcut(["CONTROL", "SHIFT", "C"], () => {
251
268
  * console.log("Ctrl+Shift+C was pressed");
252
269
  * });
270
+ *
271
+ * // won't fire while typing in a text field
272
+ * createShortcut(["S"], () => console.log("S was pressed"), { ignoreWithinInputs: true });
253
273
  * ```
254
274
  */
255
275
  export function createShortcut(keys, callback, options = {}) {
@@ -257,7 +277,7 @@ export function createShortcut(keys, callback, options = {}) {
257
277
  return;
258
278
  }
259
279
  keys = keys.map(key => key.toUpperCase());
260
- const { preventDefault = true, requireReset = false } = options;
280
+ const { preventDefault = true, requireReset = false, ignoreWithinInputs = false } = options;
261
281
  // Track pressed keys and sequence locally with plain JS state rather than
262
282
  // reactive signals. A signal reads from event listeners return
263
283
  // the pre-batch committed value, so synchronous shortcut checking requires
@@ -273,6 +293,8 @@ export function createShortcut(keys, callback, options = {}) {
273
293
  makeEventListener(window, "keydown", (e) => {
274
294
  if (e.repeat || typeof e.key !== "string")
275
295
  return;
296
+ if (ignoreWithinInputs && isEditableTarget(e.target))
297
+ return;
276
298
  const key = e.key.toUpperCase();
277
299
  if (!pressedKeys.includes(key)) {
278
300
  const newKeys = [...pressedKeys];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solid-primitives/keyboard",
3
- "version": "2.0.0-next.1",
3
+ "version": "2.0.0-next.2",
4
4
  "description": "A library of reactive promitives helping handling user's keyboard input.",
5
5
  "author": "Damian Tarnwski <gthetarnav@gmail.com>",
6
6
  "contributors": [],