{"_id":"@acepad/keypad","name":"@acepad/keypad","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@acepad/keypad","scripts":{"test":"run test/test-keypad.js"},"main":"./js/keypad.js","version":"1.0.0","type":"module","gitHead":"37284a979ef045b9d88090b35e1503ba8ac5e06c","types":"./js/keypad.d.ts","_id":"@acepad/keypad@1.0.0","description":"NOTE: This package is supporsed to work in [AcePad](https://github.com/hoge1e3/acepad-dev), not a regular node envronment.","_nodeVersion":"22.17.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-IuzC5bgGC20uECrBj3QhIZc6Yg9wznacE6H9fr082v9nHkr2GAOtcX/TyhSL15EWcLRx9gm4O4Hues9wKi4x5w==","shasum":"693b71c3394e140bcd99f3d49b821515ff4977fd","tarball":"https://registry.npmjs.org/@acepad/keypad/-/keypad-1.0.0.tgz","fileCount":20,"unpackedSize":54385,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGNsdyQyHxVFoKdOOeKrptLWvUtypl1KQwDdAE9d8tSkAiBkejfXEMrHHvOL1lBcqSxoF+9Vx64bp+XWhb4E1YjZJg=="}]},"_npmUser":{"name":"acepad","email":"pnode.acepad@gmail.com"},"directories":{},"maintainers":[{"name":"acepad","email":"pnode.acepad@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/keypad_1.0.0_1772502969614_0.7403626506857603"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-03T01:56:09.475Z","1.0.0":"2026-03-03T01:56:09.781Z","modified":"2026-03-03T01:56:10.060Z"},"maintainers":[{"name":"acepad","email":"pnode.acepad@gmail.com"}],"description":"NOTE: This package is supporsed to work in [AcePad](https://github.com/hoge1e3/acepad-dev), not a regular node envronment.","readme":"NOTE: This package is supporsed to work in [AcePad](https://github.com/hoge1e3/acepad-dev), not a regular node envronment.\n\n# @acepad/keypad\n\nA virtual keypad library for the AcePad editor. Handles key rendering, modifier key state management, long-tap behavior, and key event dispatching.\n\n---\n\n## Installation\n\nThis package is part of the `@acepad` monorepo. It is typically installed as a dependency rather than standalone.\n\n---\n\n## Overview\n\n`@acepad/keypad` provides the following modules:\n\n| Module | Description |\n|---|---|\n| `keypad.ts` | Core keypad initialization, button rendering, and click handling |\n| `modifier.ts` | Modifier key state (shift, ctrl, sym, etc.) management |\n| `longtap.ts` | Long-tap / auto-repeat touch/mouse event handling |\n| `types.ts` | Shared type definitions and constants |\n\n---\n\n## Modifier Keys\n\nThe following modifier keys are supported:\n\n| Key | Description |\n|---|---|\n| `shift` | Shift modifier (shows uppercase / alternate characters) |\n| `ctrl` | Control modifier (triggers `ctrl`-prefixed commands) |\n| `edit` | Edit mode modifier |\n| `sym` | Symbol modifier (shows symbol layer on keys) |\n| `select` | Selection mode (converts arrow keys to shift+arrow) |\n\nModifier keys support three states:\n\n| Value | Meaning |\n|---|---|\n| `0` | Off |\n| `1` | Active (single-shot — clears after next key press) |\n| `2` | Locked (stays active until tapped again) |\n\nLock behavior is controlled by the `lock` data attribute on the button element:\n\n| Lock Type | Behavior |\n|---|---|\n| `\"single\"` | Locks on first tap |\n| `\"double\"` | Locks on double tap (default) |\n| `\"none\"` | Never locks |\n\n---\n\n## Button Data Attributes\n\nButtons inside `#keypad` can carry the following `data-*` attributes to define their behavior:\n\n| Attribute | Type | Description |\n|---|---|---|\n| `data-text` | `string` | Character(s) to insert |\n| `data-key` | `string` | Key name (e.g. `ArrowLeft`, `Enter`) |\n| `data-command` | `string` | AcePad command string (sent as `ace:<command>`) |\n| `data-modifier` | `KP_ModifierKeys` | Makes the button a modifier toggle |\n| `data-modifier-off` | `KP_ModifierKeys` | Clears this modifier when pressed |\n| `data-lock` | `LockType` | Lock behavior for modifier buttons |\n| `data-ctrl` | `string` | Command triggered when `ctrl` modifier is active |\n| `data-keycode` | `string` | Raw keycode (legacy use) |\n\n### Multi-character `chr` buttons\n\nButtons with the class `chr` support automatic layered text rendering:\n\n- **1 alphabetic character** → generates `no-shift` and `shift` spans (lower/upper)\n- **2+ characters with an alphabetic first char** → also generates `sym` span\n- **2 characters, both non-alpha** → generates `no-sym` and `sym` spans\n\n---\n\n## API\n\n### `initKeypad({ events })`\n\nInitializes the entire `#keypad` element. Scans all `button` elements, sets up tap handlers, adds modifier CSS rules, and runs layout justification.\n\n```ts\nimport { initKeypad } from \"@acepad/keypad\";\n\ninitKeypad({ events: myEventHandler });\n```\n\n- `events` must be an `EventHandler` from `@hoge1e3/events`. The keypad fires:\n  - `keyclick` — when a key is pressed `{ b: HTMLElement }`\n  - `renderModifierState` — after the modifier state is re-rendered `{}`\n\n---\n\n### `initKey(button)`\n\nInitializes a single button element (called automatically by `initKeypad`).\n\n---\n\n### `doClick(button)`\n\nProgrammatically triggers the action of a button as if it were tapped.\n\n```ts\nimport { doClick } from \"@acepad/keypad\";\ndoClick(myButtonElement);\n```\n\n---\n\n### `doClickRender(button)`\n\nSame as `doClick`, but also fires the `keyclick` event and re-renders the modifier state.\n\n---\n\n### `getDatas(element)`\n\nReads all `data-*` attributes from an element and its visible children, returning a `Datas` object.\n\n```ts\nimport { getDatas } from \"@acepad/keypad\";\nconst d = getDatas(buttonEl);\n// d.text, d.modifier, d.command, ...\n```\n\n---\n\n### `renderModifierState()`\n\nApplies CSS classes to `#keypad` reflecting the current modifier state. For each active modifier key `k`, adds class `k` and optionally `lock-k` to `#keypad`.\n\n---\n\n### `toggleSym()`\n\nToggles the `sym` modifier to locked state (`2`), if a `sym` button is visible.\n\n---\n\n### `justify(row)` / `justifyAll()`\n\nDistributes visible child elements of a `.justify` row evenly by setting their widths as percentages. `justifyAll` applies this to all `.justify` elements and attaches a `ResizeObserver`.\n\n---\n\n### `hasSym()`\n\nReturns `true` if a visible `[data-modifier=\"sym\"]` button exists in the DOM.\n\n---\n\n### `showGuide(button, size?)`\n\nDisplays a floating guide overlay over the given button (or the button matching the given text), which shrinks over time. Useful for tutorials or onboarding.\n\n---\n\n### `textToButton()`\n\nReturns a map of `{ [text]: HTMLElement }` for all buttons in `#keypad` that have a `data-text` value.\n\n---\n\n## Modifier API (`modifiers` namespace)\n\nExported as `modifiers` from the main module:\n\n```ts\nimport { modifiers } from \"@acepad/keypad\";\n```\n\n| Function | Description |\n|---|---|\n| `getModifier(key)` | Returns current state value (`0`, `1`) |\n| `setModifier(key, value)` | Sets modifier to `0`, `1`, or `2` (locked) |\n| `modifierLocked(key)` | Returns whether modifier is locked |\n| `clearUnlockedModifiers()` | Clears all non-locked modifiers |\n| `modifierButtonPressed(datas)` | Handles tap on a modifier button |\n| `modifierStateToKeyboardEvent(state?)` | Converts modifier state to a `{ shiftKey, ctrlKey, ... }` object |\n| `currentModifierState()` | Returns the raw modifier state record |\n| `addModifierStyle()` | Injects CSS rules for modifier visibility masking |\n\n---\n\n## Long-tap Behavior (`longtap` module)\n\n`setLongtap(element, handlers)` attaches touch/mouse event listeners to an element and supports:\n\n- **`start(e)`** — called on initial press; shows a visual tip\n- **`longtap(e)`** — called after 300ms hold\n- **`autorepeat`** — if `true`, auto-repeats the `start` handler every 30ms after the initial long-tap delay\n- **`end(e)`** — called on release; hides the tip\n\nA tip element (`#tip`) must exist in the DOM for visual feedback.\n\n---\n\n## CSS Classes\n\nThe keypad relies on the following CSS class conventions:\n\n| Class | Applied to | Meaning |\n|---|---|---|\n| `chr` | `button` | Button text will be split into shift/sym layers |\n| `autorepeat` | `button` | Button uses auto-repeat on long-tap |\n| `justify` | container | Children will be auto-justified to fill the row |\n| `mask` | `span` inside `button` | Toggled visible/hidden based on modifier state |\n| `no-shift` / `shift` | `span.mask` | Shown when shift is off / on |\n| `no-sym` / `sym` | `span.mask` | Shown when sym is off / on |\n| `{modifier}` | `#keypad` | Added when that modifier is active |\n| `lock-{modifier}` | `#keypad` | Added when that modifier is locked |\n\n---\n\n## Dependencies\n\n- `@hoge1e3/key-stream` — key event push/sync pipeline\n- `@hoge1e3/events` — event handler interface\n- `user-gesture` — gesture event handler setup\n- `@hoge1e3/on-resume` — resume event for cleaning up tap state\n- jQuery (`$`) — DOM manipulation (expected as a global)\n\n---\n\n## License\n\nMIT License.","readmeFilename":"README.md","_rev":"1-b9d9b7e2559ce8cc46e88ec0cc2eb0a0"}