@ramstack/alpinegear-typegrab 1.4.0

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 ADDED
@@ -0,0 +1,77 @@
1
+ # @ramstack/alpinegear-typegrab
2
+
3
+ [![NPM](https://img.shields.io/npm/v/@ramstack/alpinegear-typegrab)](https://www.npmjs.com/package/@ramstack/alpinegear-typegrab)
4
+ [![MIT](https://img.shields.io/github/license/rameel/ramstack.alpinegear.js)](https://github.com/rameel/ramstack.alpinegear.js/blob/main/LICENSE)
5
+
6
+ `@ramstack/alpinegear-typegrab` is a lightweight plugin for [Alpine.js](https://alpinejs.dev/) that provides the `x-typegrab` directive.
7
+
8
+ The directive automatically focuses an element when the user starts typing **any printable, non-whitespace character**,
9
+ as long as no editable element is currently focused. This is useful for search inputs, command palettes,
10
+ and similar UX patterns where typing should immediately direct input to a specific field.
11
+
12
+ ## How it works
13
+
14
+ * Listens globally to the `keydown` event.
15
+ * Triggers only for **printable, non-whitespace characters**.
16
+ * Ignores events with `Ctrl`, `Alt`, or `Meta` modifiers.
17
+ * Does nothing if the active element is `input`, `textarea`, or an element with `contenteditable`.
18
+ * Focuses the element marked with `x-typegrab`.
19
+
20
+ ## Installation
21
+
22
+ ### Using CDN
23
+
24
+ ```html
25
+ <!-- alpine.js plugin -->
26
+ <script src="https://cdn.jsdelivr.net/npm/@ramstack/alpinegear-typegrab@1/alpinegear-typegrab.min.js" defer></script>
27
+
28
+ <!-- alpine.js -->
29
+ <script src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js" defer></script>
30
+ ```
31
+
32
+ ### Using NPM
33
+
34
+ ```bash
35
+ npm install --save @ramstack/alpinegear-typegrab
36
+ ```
37
+
38
+ ```js
39
+ import Alpine from "alpinejs";
40
+ import Typegrab from "@ramstack/alpinegear-typegrab";
41
+
42
+ Alpine.plugin(Typegrab);
43
+ Alpine.start();
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ```html
49
+ <input
50
+ type="search"
51
+ placeholder="Type to search..."
52
+ x-typegrab
53
+ />
54
+ ```
55
+
56
+ When the user presses any printable character key (excluding whitespace) while no other editable element is focused,
57
+ this input will automatically receive focus.
58
+
59
+ ## Notes
60
+
61
+ * The directive does not cancel or modify the original keyboard event.
62
+ * The target element must be focusable.
63
+ * Focus will not be stolen from active editable elements.
64
+
65
+ ## Source code
66
+
67
+ You can find the source code for this plugin on GitHub:
68
+ https://github.com/rameel/ramstack.alpinegear.js/tree/main/src/plugins/typegrab
69
+
70
+ ## Contributions
71
+
72
+ Bug reports and contributions are welcome.
73
+
74
+ ## License
75
+
76
+ This package is released as open source under the **MIT License**.
77
+ See the [LICENSE](https://github.com/rameel/ramstack.alpinegear.js/blob/main/LICENSE) file for more details.
@@ -0,0 +1,34 @@
1
+ const listen = (target, type, listener, options) => {
2
+ target.addEventListener(type, listener, options);
3
+ return () => target.removeEventListener(type, listener, options);
4
+ };
5
+
6
+ const matches = (el, selector) => el.matches(selector);
7
+
8
+ const is_active_element_editable = () => {
9
+ const el = document.activeElement;
10
+ if (el === document.body || !el) {
11
+ return false;
12
+ }
13
+
14
+ return matches(el, "input")
15
+ || matches(el, "textarea")
16
+ || el.isContentEditable;
17
+ };
18
+
19
+ const is_printable_key_pressed = ({ key, metaKey, ctrlKey, altKey }) =>
20
+ !metaKey && !ctrlKey && !altKey && /^[^\p{M}\p{Z}\p{C}]$/u.test(key);
21
+
22
+ function plugin({ directive }) {
23
+ directive("typegrab", (el, _, { cleanup }) => {
24
+ cleanup(
25
+ listen(document, "keydown", e => {
26
+ if (!is_active_element_editable() && is_printable_key_pressed(e)) {
27
+ el.focus();
28
+ }
29
+ }, { passive: true })
30
+ );
31
+ });
32
+ }
33
+
34
+ export { plugin as typegrab };
@@ -0,0 +1 @@
1
+ const e=(e,t)=>e.matches(t);function t({directive:t}){t("typegrab",(t,n,{cleanup:a})=>{var o,c,r;a(((o=document).addEventListener("keydown",c=n=>{!(()=>{const t=document.activeElement;return!(t===document.body||!t)&&(e(t,"input")||e(t,"textarea")||t.isContentEditable)})()&&(({key:e,metaKey:t,ctrlKey:n,altKey:a})=>!t&&!n&&!a&&/^[^\p{M}\p{Z}\p{C}]$/u.test(e))(n)&&t.focus()},r={passive:!0}),()=>o.removeEventListener("keydown",c,r)))})}export{t as typegrab};
@@ -0,0 +1,39 @@
1
+ (function () {
2
+ 'use strict';
3
+
4
+ const listen = (target, type, listener, options) => {
5
+ target.addEventListener(type, listener, options);
6
+ return () => target.removeEventListener(type, listener, options);
7
+ };
8
+
9
+ const matches = (el, selector) => el.matches(selector);
10
+
11
+ const is_active_element_editable = () => {
12
+ const el = document.activeElement;
13
+ if (el === document.body || !el) {
14
+ return false;
15
+ }
16
+
17
+ return matches(el, "input")
18
+ || matches(el, "textarea")
19
+ || el.isContentEditable;
20
+ };
21
+
22
+ const is_printable_key_pressed = ({ key, metaKey, ctrlKey, altKey }) =>
23
+ !metaKey && !ctrlKey && !altKey && /^[^\p{M}\p{Z}\p{C}]$/u.test(key);
24
+
25
+ function plugin({ directive }) {
26
+ directive("typegrab", (el, _, { cleanup }) => {
27
+ cleanup(
28
+ listen(document, "keydown", e => {
29
+ if (!is_active_element_editable() && is_printable_key_pressed(e)) {
30
+ el.focus();
31
+ }
32
+ }, { passive: true })
33
+ );
34
+ });
35
+ }
36
+
37
+ document.addEventListener("alpine:init", () => { Alpine.plugin(plugin); });
38
+
39
+ })();
@@ -0,0 +1 @@
1
+ !function(){"use strict";const e=(e,t)=>e.matches(t);function t({directive:t}){t("typegrab",(t,n,{cleanup:i})=>{var c,a,o;i(((c=document).addEventListener("keydown",a=n=>{!(()=>{const t=document.activeElement;return!(t===document.body||!t)&&(e(t,"input")||e(t,"textarea")||t.isContentEditable)})()&&(({key:e,metaKey:t,ctrlKey:n,altKey:i})=>!t&&!n&&!i&&/^[^\p{M}\p{Z}\p{C}]$/u.test(e))(n)&&t.focus()},o={passive:!0}),()=>c.removeEventListener("keydown",a,o)))})}document.addEventListener("alpine:init",()=>{Alpine.plugin(t)})}();
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@ramstack/alpinegear-typegrab",
3
+ "version": "1.4.0",
4
+ "description": "@ramstack/alpinegear-typegrab provides the x-typegrab Alpine.js directive, which automatically focuses an element when the user starts typing and no editable element is active.",
5
+ "author": "Rameel Burhan",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/rameel/ramstack.alpinegear.js.git",
10
+ "directory": "src/plugins/typegrab"
11
+ },
12
+ "keywords": [
13
+ "alpine.js",
14
+ "alpinejs",
15
+ "alpinejs-directive",
16
+ "alpinejs-plugin",
17
+ "keyboard",
18
+ "focus",
19
+ "ux"
20
+ ],
21
+ "main": "alpinegear-typegrab.js",
22
+ "module": "alpinegear-typegrab.esm.js"
23
+ }