@witchcraft/spellcraft 0.0.1

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.
Files changed (367) hide show
  1. package/README.md +579 -0
  2. package/dist/core/EmulatedEvent.d.ts +10 -0
  3. package/dist/core/EmulatedEvent.js +19 -0
  4. package/dist/core/Emulator.d.ts +74 -0
  5. package/dist/core/Emulator.js +153 -0
  6. package/dist/core/ShortcutManagerManager.d.ts +103 -0
  7. package/dist/core/ShortcutManagerManager.js +267 -0
  8. package/dist/core/addCommand.d.ts +7 -0
  9. package/dist/core/addCommand.js +7 -0
  10. package/dist/core/addKey.d.ts +7 -0
  11. package/dist/core/addKey.js +7 -0
  12. package/dist/core/addShortcut.d.ts +7 -0
  13. package/dist/core/addShortcut.js +7 -0
  14. package/dist/core/attach.d.ts +10 -0
  15. package/dist/core/attach.js +13 -0
  16. package/dist/core/createCommand.d.ts +4 -0
  17. package/dist/core/createCommand.js +11 -0
  18. package/dist/core/createCommands.d.ts +11 -0
  19. package/dist/core/createCommands.js +20 -0
  20. package/dist/core/createCondition.d.ts +7 -0
  21. package/dist/core/createCondition.js +11 -0
  22. package/dist/core/createContext.d.ts +2 -0
  23. package/dist/core/createContext.js +8 -0
  24. package/dist/core/createKey.d.ts +10 -0
  25. package/dist/core/createKey.js +35 -0
  26. package/dist/core/createKeys.d.ts +5 -0
  27. package/dist/core/createKeys.js +36 -0
  28. package/dist/core/createManager.d.ts +81 -0
  29. package/dist/core/createManager.js +83 -0
  30. package/dist/core/createManagerEventListeners.d.ts +4 -0
  31. package/dist/core/createManagerEventListeners.js +130 -0
  32. package/dist/core/createManagerOptions.d.ts +8 -0
  33. package/dist/core/createManagerOptions.js +17 -0
  34. package/dist/core/createShortcut.d.ts +8 -0
  35. package/dist/core/createShortcut.js +24 -0
  36. package/dist/core/createShortcuts.d.ts +13 -0
  37. package/dist/core/createShortcuts.js +20 -0
  38. package/dist/core/detach.d.ts +10 -0
  39. package/dist/core/detach.js +6 -0
  40. package/dist/core/index.d.ts +32 -0
  41. package/dist/core/index.js +32 -0
  42. package/dist/core/removeCommand.d.ts +7 -0
  43. package/dist/core/removeCommand.js +7 -0
  44. package/dist/core/removeKey.d.ts +7 -0
  45. package/dist/core/removeKey.js +7 -0
  46. package/dist/core/removeShortcut.d.ts +7 -0
  47. package/dist/core/removeShortcut.js +7 -0
  48. package/dist/core/setCommandProp.d.ts +17 -0
  49. package/dist/core/setCommandProp.js +96 -0
  50. package/dist/core/setCommandsProp.d.ts +15 -0
  51. package/dist/core/setCommandsProp.js +94 -0
  52. package/dist/core/setKeyProp.d.ts +16 -0
  53. package/dist/core/setKeyProp.js +47 -0
  54. package/dist/core/setKeysProp.d.ts +10 -0
  55. package/dist/core/setKeysProp.js +166 -0
  56. package/dist/core/setManagerProp.d.ts +34 -0
  57. package/dist/core/setManagerProp.js +54 -0
  58. package/dist/core/setShortcutProp.d.ts +9 -0
  59. package/dist/core/setShortcutProp.js +50 -0
  60. package/dist/core/setShortcutsProp.d.ts +12 -0
  61. package/dist/core/setShortcutsProp.js +93 -0
  62. package/dist/defaults/KeysSorter.d.ts +35 -0
  63. package/dist/defaults/KeysSorter.js +20 -0
  64. package/dist/defaults/Stringifier.d.ts +66 -0
  65. package/dist/defaults/Stringifier.js +119 -0
  66. package/dist/defaults/defaultConditionEquals.d.ts +19 -0
  67. package/dist/defaults/defaultConditionEquals.js +5 -0
  68. package/dist/defaults/defaultManagerCallback.d.ts +7 -0
  69. package/dist/defaults/defaultManagerCallback.js +5 -0
  70. package/dist/helpers/KnownError.d.ts +8 -0
  71. package/dist/helpers/KnownError.js +3 -0
  72. package/dist/helpers/calculateAndSetPositionAndWidth.d.ts +13 -0
  73. package/dist/helpers/calculateAndSetPositionAndWidth.js +18 -0
  74. package/dist/helpers/calculateLayoutSize.d.ts +9 -0
  75. package/dist/helpers/calculateLayoutSize.js +13 -0
  76. package/dist/helpers/doesShortcutConflict.d.ts +18 -0
  77. package/dist/helpers/doesShortcutConflict.js +42 -0
  78. package/dist/helpers/equalsCommand.d.ts +7 -0
  79. package/dist/helpers/equalsCommand.js +4 -0
  80. package/dist/helpers/equalsContext.d.ts +7 -0
  81. package/dist/helpers/equalsContext.js +19 -0
  82. package/dist/helpers/equalsShortcut.d.ts +9 -0
  83. package/dist/helpers/equalsShortcut.js +7 -0
  84. package/dist/helpers/forceClear.d.ts +12 -0
  85. package/dist/helpers/forceClear.js +16 -0
  86. package/dist/helpers/forceUpdateNativeKeysState.d.ts +5 -0
  87. package/dist/helpers/forceUpdateNativeKeysState.js +4 -0
  88. package/dist/helpers/generateKeyShortcutMap.d.ts +23 -0
  89. package/dist/helpers/generateKeyShortcutMap.js +64 -0
  90. package/dist/helpers/getKeyFromEventCode.d.ts +15 -0
  91. package/dist/helpers/getKeyFromEventCode.js +36 -0
  92. package/dist/helpers/getKeyFromIdOrVariant.d.ts +4 -0
  93. package/dist/helpers/getKeyFromIdOrVariant.js +26 -0
  94. package/dist/helpers/getKeyboardLayoutMap.d.ts +5 -0
  95. package/dist/helpers/getKeyboardLayoutMap.js +7 -0
  96. package/dist/helpers/getLabel.d.ts +9 -0
  97. package/dist/helpers/getLabel.js +6 -0
  98. package/dist/helpers/getTriggerableShortcut.d.ts +6 -0
  99. package/dist/helpers/getTriggerableShortcut.js +25 -0
  100. package/dist/helpers/index.d.ts +28 -0
  101. package/dist/helpers/index.js +28 -0
  102. package/dist/helpers/isValidManager.d.ts +3 -0
  103. package/dist/helpers/isValidManager.js +20 -0
  104. package/dist/helpers/isValidShortcut.d.ts +3 -0
  105. package/dist/helpers/isValidShortcut.js +10 -0
  106. package/dist/helpers/labelWithEvent.d.ts +13 -0
  107. package/dist/helpers/labelWithEvent.js +20 -0
  108. package/dist/helpers/labelWithKeyboardMap.d.ts +15 -0
  109. package/dist/helpers/labelWithKeyboardMap.js +17 -0
  110. package/dist/helpers/managerToStorableClone.d.ts +12 -0
  111. package/dist/helpers/managerToStorableClone.js +13 -0
  112. package/dist/helpers/onKeyboardLayoutChange.d.ts +10 -0
  113. package/dist/helpers/onKeyboardLayoutChange.js +7 -0
  114. package/dist/helpers/safeSetManagerChain.d.ts +20 -0
  115. package/dist/helpers/safeSetManagerChain.js +37 -0
  116. package/dist/helpers/shortcutCanExecuteIn.d.ts +4 -0
  117. package/dist/helpers/shortcutCanExecuteIn.js +9 -0
  118. package/dist/helpers/shortcutIsTriggerableBy.d.ts +2 -0
  119. package/dist/helpers/shortcutIsTriggerableBy.js +5 -0
  120. package/dist/helpers/shortcutSwapChords.d.ts +75 -0
  121. package/dist/helpers/shortcutSwapChords.js +118 -0
  122. package/dist/helpers/virtualPress.d.ts +13 -0
  123. package/dist/helpers/virtualPress.js +15 -0
  124. package/dist/helpers/virtualRelease.d.ts +5 -0
  125. package/dist/helpers/virtualRelease.js +15 -0
  126. package/dist/helpers/virtualToggle.d.ts +7 -0
  127. package/dist/helpers/virtualToggle.js +16 -0
  128. package/dist/internal/addToChain.d.ts +3 -0
  129. package/dist/internal/addToChain.js +27 -0
  130. package/dist/internal/areValidKeys.d.ts +7 -0
  131. package/dist/internal/areValidKeys.js +28 -0
  132. package/dist/internal/areValidVariants.d.ts +4 -0
  133. package/dist/internal/areValidVariants.js +45 -0
  134. package/dist/internal/checkTrigger.d.ts +2 -0
  135. package/dist/internal/checkTrigger.js +47 -0
  136. package/dist/internal/checkUntrigger.d.ts +2 -0
  137. package/dist/internal/checkUntrigger.js +18 -0
  138. package/dist/internal/cloneLastChord.d.ts +4 -0
  139. package/dist/internal/cloneLastChord.js +5 -0
  140. package/dist/internal/containsPossibleToggleChords.d.ts +13 -0
  141. package/dist/internal/containsPossibleToggleChords.js +65 -0
  142. package/dist/internal/errorTextAdd.d.ts +1 -0
  143. package/dist/internal/errorTextAdd.js +11 -0
  144. package/dist/internal/errorTextInUse.d.ts +1 -0
  145. package/dist/internal/errorTextInUse.js +8 -0
  146. package/dist/internal/errorTextRemove.d.ts +1 -0
  147. package/dist/internal/errorTextRemove.js +8 -0
  148. package/dist/internal/getModifierState.d.ts +2 -0
  149. package/dist/internal/getModifierState.js +7 -0
  150. package/dist/internal/getPressedKeys.d.ts +7 -0
  151. package/dist/internal/getPressedKeys.js +18 -0
  152. package/dist/internal/getPressedModifierKeys.d.ts +2 -0
  153. package/dist/internal/getPressedModifierKeys.js +10 -0
  154. package/dist/internal/getPressedNonModifierKeys.d.ts +7 -0
  155. package/dist/internal/getPressedNonModifierKeys.js +11 -0
  156. package/dist/internal/inChain.d.ts +5 -0
  157. package/dist/internal/inChain.js +14 -0
  158. package/dist/internal/isValidChain.d.ts +10 -0
  159. package/dist/internal/isValidChain.js +22 -0
  160. package/dist/internal/isValidChord.d.ts +11 -0
  161. package/dist/internal/isValidChord.js +59 -0
  162. package/dist/internal/isValidCommand.d.ts +12 -0
  163. package/dist/internal/isValidCommand.js +20 -0
  164. package/dist/internal/keyOrder.d.ts +6 -0
  165. package/dist/internal/keyOrder.js +14 -0
  166. package/dist/internal/removeFromChain.d.ts +3 -0
  167. package/dist/internal/removeFromChain.js +32 -0
  168. package/dist/internal/safeSetEmulatedToggleState.d.ts +4 -0
  169. package/dist/internal/safeSetEmulatedToggleState.js +13 -0
  170. package/dist/internal/setKeysState.d.ts +8 -0
  171. package/dist/internal/setKeysState.js +42 -0
  172. package/dist/internal/updateNativeKeysState.d.ts +14 -0
  173. package/dist/internal/updateNativeKeysState.js +58 -0
  174. package/dist/layouts/createLayout.d.ts +25 -0
  175. package/dist/layouts/createLayout.js +221 -0
  176. package/dist/module.d.mts +13 -0
  177. package/dist/module.json +9 -0
  178. package/dist/module.mjs +40 -0
  179. package/dist/runtime/composables/useLabeledByKeyboardLayoutMap.d.ts +9 -0
  180. package/dist/runtime/composables/useLabeledByKeyboardLayoutMap.js +19 -0
  181. package/dist/runtime/composables/usePointerCoords.d.ts +32 -0
  182. package/dist/runtime/composables/usePointerCoords.js +17 -0
  183. package/dist/runtime/composables/useShortcutManagerContextCount.d.ts +14 -0
  184. package/dist/runtime/composables/useShortcutManagerContextCount.js +61 -0
  185. package/dist/runtime/composables/useShortcutManagerKeysLayout.d.ts +18 -0
  186. package/dist/runtime/composables/useShortcutManagerKeysLayout.js +22 -0
  187. package/dist/runtime/composables/useShortcutManagerVirtualPress.d.ts +6 -0
  188. package/dist/runtime/composables/useShortcutManagerVirtualPress.js +24 -0
  189. package/dist/runtime/types.d.ts +10 -0
  190. package/dist/runtime/types.js +1 -0
  191. package/dist/runtime/utils/shortcutToId.d.ts +5 -0
  192. package/dist/runtime/utils/shortcutToId.js +6 -0
  193. package/dist/types/commands.d.ts +113 -0
  194. package/dist/types/commands.js +0 -0
  195. package/dist/types/condition.d.ts +29 -0
  196. package/dist/types/condition.js +0 -0
  197. package/dist/types/context.d.ts +18 -0
  198. package/dist/types/context.js +0 -0
  199. package/dist/types/enums.d.ts +186 -0
  200. package/dist/types/enums.js +70 -0
  201. package/dist/types/general.d.ts +92 -0
  202. package/dist/types/general.js +0 -0
  203. package/dist/types/index.d.ts +8 -0
  204. package/dist/types/index.js +8 -0
  205. package/dist/types/keys.d.ts +332 -0
  206. package/dist/types/keys.js +0 -0
  207. package/dist/types/manager.d.ts +249 -0
  208. package/dist/types/manager.js +0 -0
  209. package/dist/types/plugins.d.ts +1 -0
  210. package/dist/types/plugins.js +0 -0
  211. package/dist/types/shortcuts.d.ts +144 -0
  212. package/dist/types/shortcuts.js +0 -0
  213. package/dist/types/utils.d.ts +1 -0
  214. package/dist/types/utils.js +0 -0
  215. package/dist/types.d.mts +3 -0
  216. package/dist/utils/chainContainsSubset.d.ts +27 -0
  217. package/dist/utils/chainContainsSubset.js +45 -0
  218. package/dist/utils/cloneChain.d.ts +2 -0
  219. package/dist/utils/cloneChain.js +11 -0
  220. package/dist/utils/cloneKey.d.ts +3 -0
  221. package/dist/utils/cloneKey.js +26 -0
  222. package/dist/utils/containsKey.d.ts +7 -0
  223. package/dist/utils/containsKey.js +4 -0
  224. package/dist/utils/dedupeKeys.d.ts +9 -0
  225. package/dist/utils/dedupeKeys.js +9 -0
  226. package/dist/utils/equalsKey.d.ts +12 -0
  227. package/dist/utils/equalsKey.js +13 -0
  228. package/dist/utils/equalsKeys.d.ts +24 -0
  229. package/dist/utils/equalsKeys.js +15 -0
  230. package/dist/utils/index.d.ts +14 -0
  231. package/dist/utils/index.js +14 -0
  232. package/dist/utils/isAnyKey.d.ts +5 -0
  233. package/dist/utils/isAnyKey.js +5 -0
  234. package/dist/utils/isMouseKey.d.ts +5 -0
  235. package/dist/utils/isMouseKey.js +20 -0
  236. package/dist/utils/isNormalKey.d.ts +5 -0
  237. package/dist/utils/isNormalKey.js +5 -0
  238. package/dist/utils/isTriggerKey.d.ts +5 -0
  239. package/dist/utils/isTriggerKey.js +3 -0
  240. package/dist/utils/isWheelKey.d.ts +5 -0
  241. package/dist/utils/isWheelKey.js +11 -0
  242. package/dist/utils/mapKeys.d.ts +8 -0
  243. package/dist/utils/mapKeys.js +5 -0
  244. package/dist/utils/removeKeys.d.ts +7 -0
  245. package/dist/utils/removeKeys.js +4 -0
  246. package/package.json +156 -0
  247. package/src/core/EmulatedEvent.ts +29 -0
  248. package/src/core/Emulator.ts +185 -0
  249. package/src/core/ShortcutManagerManager.ts +380 -0
  250. package/src/core/addCommand.ts +24 -0
  251. package/src/core/addKey.ts +25 -0
  252. package/src/core/addShortcut.ts +24 -0
  253. package/src/core/attach.ts +27 -0
  254. package/src/core/createCommand.ts +24 -0
  255. package/src/core/createCommands.ts +45 -0
  256. package/src/core/createCondition.ts +21 -0
  257. package/src/core/createContext.ts +14 -0
  258. package/src/core/createKey.ts +59 -0
  259. package/src/core/createKeys.ts +68 -0
  260. package/src/core/createManager.ts +209 -0
  261. package/src/core/createManagerEventListeners.ts +139 -0
  262. package/src/core/createManagerOptions.ts +29 -0
  263. package/src/core/createShortcut.ts +49 -0
  264. package/src/core/createShortcuts.ts +51 -0
  265. package/src/core/detach.ts +21 -0
  266. package/src/core/index.ts +35 -0
  267. package/src/core/removeCommand.ts +25 -0
  268. package/src/core/removeKey.ts +25 -0
  269. package/src/core/removeShortcut.ts +24 -0
  270. package/src/core/setCommandProp.ts +140 -0
  271. package/src/core/setCommandsProp.ts +128 -0
  272. package/src/core/setKeyProp.ts +80 -0
  273. package/src/core/setKeysProp.ts +205 -0
  274. package/src/core/setManagerProp.ts +111 -0
  275. package/src/core/setShortcutProp.ts +89 -0
  276. package/src/core/setShortcutsProp.ts +124 -0
  277. package/src/defaults/KeysSorter.ts +55 -0
  278. package/src/defaults/Stringifier.ts +234 -0
  279. package/src/defaults/defaultConditionEquals.ts +29 -0
  280. package/src/defaults/defaultManagerCallback.ts +14 -0
  281. package/src/helpers/KnownError.ts +13 -0
  282. package/src/helpers/calculateAndSetPositionAndWidth.ts +30 -0
  283. package/src/helpers/calculateLayoutSize.ts +22 -0
  284. package/src/helpers/doesShortcutConflict.ts +72 -0
  285. package/src/helpers/equalsCommand.ts +18 -0
  286. package/src/helpers/equalsContext.ts +29 -0
  287. package/src/helpers/equalsShortcut.ts +34 -0
  288. package/src/helpers/forceClear.ts +31 -0
  289. package/src/helpers/forceUpdateNativeKeysState.ts +9 -0
  290. package/src/helpers/generateKeyShortcutMap.ts +113 -0
  291. package/src/helpers/getKeyFromEventCode.ts +67 -0
  292. package/src/helpers/getKeyFromIdOrVariant.ts +33 -0
  293. package/src/helpers/getKeyboardLayoutMap.ts +13 -0
  294. package/src/helpers/getLabel.ts +15 -0
  295. package/src/helpers/getTriggerableShortcut.ts +37 -0
  296. package/src/helpers/index.ts +30 -0
  297. package/src/helpers/isValidManager.ts +29 -0
  298. package/src/helpers/isValidShortcut.ts +20 -0
  299. package/src/helpers/labelWithEvent.ts +41 -0
  300. package/src/helpers/labelWithKeyboardMap.ts +37 -0
  301. package/src/helpers/managerToStorableClone.ts +26 -0
  302. package/src/helpers/onKeyboardLayoutChange.ts +17 -0
  303. package/src/helpers/safeSetManagerChain.ts +66 -0
  304. package/src/helpers/shortcutCanExecuteIn.ts +24 -0
  305. package/src/helpers/shortcutIsTriggerableBy.ts +15 -0
  306. package/src/helpers/shortcutSwapChords.ts +240 -0
  307. package/src/helpers/virtualPress.ts +34 -0
  308. package/src/helpers/virtualRelease.ts +25 -0
  309. package/src/helpers/virtualToggle.ts +28 -0
  310. package/src/internal/addToChain.ts +40 -0
  311. package/src/internal/areValidKeys.ts +40 -0
  312. package/src/internal/areValidVariants.ts +59 -0
  313. package/src/internal/checkTrigger.ts +55 -0
  314. package/src/internal/checkUntrigger.ts +26 -0
  315. package/src/internal/cloneLastChord.ts +10 -0
  316. package/src/internal/containsPossibleToggleChords.ts +91 -0
  317. package/src/internal/errorTextAdd.ts +18 -0
  318. package/src/internal/errorTextInUse.ts +10 -0
  319. package/src/internal/errorTextRemove.ts +10 -0
  320. package/src/internal/getModifierState.ts +15 -0
  321. package/src/internal/getPressedKeys.ts +26 -0
  322. package/src/internal/getPressedModifierKeys.ts +14 -0
  323. package/src/internal/getPressedNonModifierKeys.ts +19 -0
  324. package/src/internal/inChain.ts +25 -0
  325. package/src/internal/isValidChain.ts +42 -0
  326. package/src/internal/isValidChord.ts +87 -0
  327. package/src/internal/isValidCommand.ts +35 -0
  328. package/src/internal/keyOrder.ts +24 -0
  329. package/src/internal/removeFromChain.ts +46 -0
  330. package/src/internal/safeSetEmulatedToggleState.ts +23 -0
  331. package/src/internal/setKeysState.ts +71 -0
  332. package/src/internal/updateNativeKeysState.ts +84 -0
  333. package/src/layouts/createLayout.ts +328 -0
  334. package/src/module.ts +62 -0
  335. package/src/runtime/composables/useLabeledByKeyboardLayoutMap.ts +28 -0
  336. package/src/runtime/composables/usePointerCoords.ts +40 -0
  337. package/src/runtime/composables/useShortcutManagerContextCount.ts +81 -0
  338. package/src/runtime/composables/useShortcutManagerKeysLayout.ts +42 -0
  339. package/src/runtime/composables/useShortcutManagerVirtualPress.ts +30 -0
  340. package/src/runtime/types.ts +10 -0
  341. package/src/runtime/utils/shortcutToId.ts +14 -0
  342. package/src/types/commands.ts +148 -0
  343. package/src/types/condition.ts +35 -0
  344. package/src/types/context.ts +19 -0
  345. package/src/types/enums.ts +236 -0
  346. package/src/types/general.ts +117 -0
  347. package/src/types/index.ts +10 -0
  348. package/src/types/keys.ts +385 -0
  349. package/src/types/manager.ts +374 -0
  350. package/src/types/plugins.ts +32 -0
  351. package/src/types/shortcuts.ts +204 -0
  352. package/src/types/utils.ts +40 -0
  353. package/src/utils/chainContainsSubset.ts +97 -0
  354. package/src/utils/cloneChain.ts +13 -0
  355. package/src/utils/cloneKey.ts +33 -0
  356. package/src/utils/containsKey.ts +17 -0
  357. package/src/utils/dedupeKeys.ts +23 -0
  358. package/src/utils/equalsKey.ts +32 -0
  359. package/src/utils/equalsKeys.ts +50 -0
  360. package/src/utils/index.ts +16 -0
  361. package/src/utils/isAnyKey.ts +12 -0
  362. package/src/utils/isMouseKey.ts +27 -0
  363. package/src/utils/isNormalKey.ts +15 -0
  364. package/src/utils/isTriggerKey.ts +7 -0
  365. package/src/utils/isWheelKey.ts +18 -0
  366. package/src/utils/mapKeys.ts +21 -0
  367. package/src/utils/removeKeys.ts +16 -0
@@ -0,0 +1,153 @@
1
+ import { EmulatedEvent } from "./EmulatedEvent.js";
2
+ const mouseButtons = ["0", "1", "2", "3", "4", "5"];
3
+ const mouseButtonsDown = mouseButtons.map((b) => `${b}+`);
4
+ const mouseButtonsUp = mouseButtons.map((b) => `${b}-`);
5
+ const wheelKeys = ["wheelUp", "wheelDown"];
6
+ export class Emulator {
7
+ validKeys;
8
+ constructor(keys) {
9
+ this.validKeys = keys;
10
+ }
11
+ listeners = {
12
+ keydown: [],
13
+ keyup: [],
14
+ wheel: [],
15
+ mousedown: [],
16
+ mouseenter: [],
17
+ mouseup: []
18
+ };
19
+ initiated = false;
20
+ addEventListener(type, func) {
21
+ this.listeners[type].push(func);
22
+ this.initiated = true;
23
+ }
24
+ removeEventListener(type, func) {
25
+ const i = this.listeners[type].indexOf(func);
26
+ if (i === -1) throw new Error(`Listener ${type} could not be found.`);
27
+ this.listeners[type].splice(i, 1);
28
+ }
29
+ mouseenter(modifiers = []) {
30
+ const event = new EmulatedEvent("mouseenter", {}, modifiers);
31
+ this._dispatch("mouseenter", event);
32
+ }
33
+ /**
34
+ *
35
+ * Emulate pressing/releasing keys.
36
+ *
37
+ * ```ts
38
+ * // press and release a
39
+ * emulator.fire("KeyA")
40
+ * // hold A down
41
+ * emulator.fire("KeyA+")
42
+ * // release A
43
+ * emulator.fire("KeyA-")
44
+ * // press Ctrl+A
45
+ * emulator.fire("Ctrl+ KeyA Ctrl-")
46
+ *
47
+ * // to truly simulate pressing native modifiers, pass all modifiers pressed as an array
48
+ * emulator.fire("Ctrl+ KeyA Ctrl-", ["ControlLeft"])
49
+ *
50
+ * // emulate a modifier state change out of focus
51
+ * // e.g. user focuses out, holds control+A, and focuses back
52
+ * // only KeyA would fire
53
+ * emulator.fire("KeyA+", ["ControlLeft"])
54
+ * // they release both in focus
55
+ * emulater.fire("KeyA- Ctrl-")
56
+ *
57
+ * // to simulate them releasing out of focus again you will have to add a delay since no events would fire
58
+ * delay(1000)
59
+ *
60
+ * ```
61
+ *
62
+ * Keys should be a {@link KeyboardEvent.code} (though this is not validated) seperated by one or more whitespace characters*. For buttons `0-5` can be used. For wheel events, you can pass `wheelUp/Down` to set the deltaY respectively which is how the manager gets the direction.
63
+ *
64
+ * `+` and `-` are used to indicate keydown and keyup respectively (except for wheel events*). This can seem confusing but think of the signs as adding/removing from the set of currently held keys. If no `+/-` is given, both are fired.
65
+ *
66
+ * There is no need to handle toggle keys in any special way. You should fire the root code normally (e.g. `emulator.fire("Capslock")` or `emulator.fire("Capslock+ Capslock-")`)
67
+ *
68
+ * \* Multiple whitespace characters have no real meaning, but in tests usually I use them to more easily delimite chords.
69
+ * \*\* Wheel events do not have keyup/keydown so passing `wheelUp+/-` will incorrectly create a keyboard event.
70
+ *
71
+ * Note: While the emulator is aware of correct mouse/wheel names, it does not check key names are valid.
72
+ */
73
+ fire(str, modifiers = [], validKeys) {
74
+ if (!this.initiated) {
75
+ console.warn("No manager attached to the emulator.");
76
+ return;
77
+ }
78
+ const keys = str.split(/(\s+)/).filter((part) => part.trim() !== "");
79
+ for (const key of keys) {
80
+ if (mouseButtons.includes(key)) {
81
+ this.press("mouse", key, modifiers, validKeys);
82
+ this.release("mouse", key, modifiers, validKeys);
83
+ } else if (mouseButtonsDown.includes(key)) {
84
+ this.press("mouse", key[0], modifiers, validKeys);
85
+ } else if (mouseButtonsUp.includes(key)) {
86
+ this.release("mouse", key[0], modifiers, validKeys);
87
+ } else if (wheelKeys.includes(key)) {
88
+ this.press("wheel", key, modifiers, validKeys);
89
+ } else if (key.endsWith("+")) {
90
+ this.press("key", key.slice(0, key.length - 1), modifiers, validKeys);
91
+ } else if (key.endsWith("-")) {
92
+ this.release("key", key.slice(0, key.length - 1), modifiers, validKeys);
93
+ } else {
94
+ this.press("key", key, modifiers, validKeys);
95
+ this.release("key", key, modifiers, validKeys);
96
+ }
97
+ }
98
+ }
99
+ press(type, key, modifiers = [], validKeys) {
100
+ this._checkIsValidKey(key, validKeys);
101
+ switch (type) {
102
+ case "mouse":
103
+ {
104
+ const event = new EmulatedEvent("mousedown", { button: Number.parseInt(key, 10) }, modifiers);
105
+ this._dispatch("mousedown", event);
106
+ }
107
+ break;
108
+ case "wheel":
109
+ {
110
+ const event = new EmulatedEvent("wheel", { deltaY: key === "wheelDown" ? 1 : 0 }, modifiers);
111
+ this._dispatch("wheel", event);
112
+ }
113
+ break;
114
+ case "key":
115
+ {
116
+ const event = new EmulatedEvent("keydown", { code: key }, modifiers);
117
+ this._dispatch("keydown", event);
118
+ }
119
+ break;
120
+ }
121
+ }
122
+ release(type, key, modifiers = [], validKeys) {
123
+ this._checkIsValidKey(key, validKeys);
124
+ switch (type) {
125
+ case "mouse":
126
+ {
127
+ const event = new EmulatedEvent("mouseup", { button: Number.parseInt(key, 10) }, modifiers);
128
+ this._dispatch("mouseup", event);
129
+ }
130
+ break;
131
+ case "key":
132
+ {
133
+ const event = new EmulatedEvent("keyup", { code: key }, modifiers);
134
+ this._dispatch("keyup", event);
135
+ }
136
+ break;
137
+ }
138
+ }
139
+ _checkIsValidKey(key, validKeys) {
140
+ const valid = validKeys ?? this.validKeys;
141
+ if (valid) {
142
+ const match = Object.values(valid.entries).find((k) => k.id === key || k.toggleOnId === key || k.toggleOffId === key || k.variants?.includes(key));
143
+ if (match === void 0) {
144
+ throw new Error(`Emulator was asked to fire key not in valid keys array. ${key}`);
145
+ }
146
+ }
147
+ }
148
+ _dispatch(type, event) {
149
+ for (const listener of this.listeners[type]) {
150
+ listener(event);
151
+ }
152
+ }
153
+ }
@@ -0,0 +1,103 @@
1
+ import type { DeepPartial } from "@alanscodelog/utils";
2
+ import { type Result } from "@alanscodelog/utils/Result";
3
+ import type { Manager, PickManager } from "../types/index.js";
4
+ export declare class ShortcutManagerManager {
5
+ storageKeys: {
6
+ /** Prefix for all keys. */
7
+ prefix: string;
8
+ /** @default "shortcut-manager:names" */
9
+ managerNames: string;
10
+ /** @default "shortcut-manager:manager." */
11
+ managerPrefix: string;
12
+ /** @default "shortcut-manager:active" */
13
+ activeManager: string;
14
+ };
15
+ readonly managerNames: string[];
16
+ readonly managers: Readonly<Record<string, Manager>>;
17
+ readonly activeManagerName: string;
18
+ /** A debounced version of the save function. Is already bound to the instance. */
19
+ debouncedSave: (name: string) => void;
20
+ storage: {
21
+ setItem: (key: string, value: string) => void;
22
+ getItem: (key: string) => string | null;
23
+ removeItem: (key: string) => void;
24
+ };
25
+ /**
26
+ * All new managers will be created using this function. It should be capable of taking as little information as `{name}` (when a new manager is created) and returining a full manger.
27
+ *
28
+ * It's suggested you not do validation here, use the `onParse` hook instead.
29
+ *
30
+ * If you return an error, `onError` will be called, and no manager will be created.
31
+ */
32
+ createManager: (raw: Partial<Omit<Manager, "options" | "hooks" | "listener" | "state">> & {
33
+ options: PickManager<"options", "enableShortcuts" | "enableListeners" | "updateStateOnAllEvents">;
34
+ }, isNew: boolean) => Manager | Error;
35
+ hooks: {
36
+ /**
37
+ * Called on any errors loading/saving/etc, should be used to notify the user.
38
+ */
39
+ onError: (err: Error) => void;
40
+ /**
41
+ * Called when a manager is parsed from storage after being sucessfully JSON.parsed.
42
+ *
43
+ * You can validate the parsed object here so it's in the correct shape to pass to `createManager`.
44
+ *
45
+ * If you return an error, `onError` will be called and `createManager` will be skipped.
46
+ */
47
+ onParse?: (parsed: object) => undefined | Error;
48
+ /**
49
+ * Called when a manager is saved or exported. It's called with the cloned version of the manager that has been stripped of properties that should not be saved (see {@link managerToStorableClone}).
50
+ *
51
+ * You can delete/add properties here (it will not modify the original manager).
52
+ */
53
+ onSave?: (clone: DeepPartial<Manager>) => void;
54
+ /**
55
+ * Called when a manager is exported. Can be used to actually do the export.
56
+ */
57
+ onExport?: (res: object) => void;
58
+ /**
59
+ * Called when a manager is set. Can be used to update your state.
60
+ */
61
+ onSetManager?: (name: string, clone: Manager) => void;
62
+ /**
63
+ * Called when the manager names are set. Can be used to update your state.
64
+ */
65
+ onSetManagerNames?: (names: string[]) => void;
66
+ /**
67
+ * Called when the active manager is set. Can be used to update your state.
68
+ */
69
+ onSetActiveManager?: (name: string) => void;
70
+ };
71
+ constructor(createManager: ShortcutManagerManager["createManager"], hooks: ShortcutManagerManager["hooks"], { storageKeys, storage }?: {
72
+ storageKeys?: Partial<ShortcutManagerManager["storageKeys"]>;
73
+ storage?: ShortcutManagerManager["storage"];
74
+ });
75
+ init(): void;
76
+ setManager(name: string, clone?: any): void;
77
+ setManagerNames(names: string[]): void;
78
+ setActiveManager(name: string): void;
79
+ protected addManager(name: string, clone: any): void;
80
+ protected removeManager(name: string): void;
81
+ protected storageSaveManager(name: string, clone: any): void;
82
+ protected storageRemoveManager(name: string): void;
83
+ protected storageReadManager(name: string, { force }?: {
84
+ force?: boolean;
85
+ }): Result<Manager, Error>;
86
+ parseJsonManager(raw: string): Result<any, Error>;
87
+ load(manager: Manager, { doActivate }?: {
88
+ doActivate?: boolean;
89
+ }): void;
90
+ protected loadOrCreateDefault(): void;
91
+ save(name: string): void;
92
+ protected notifyIfError<T extends Result<any, Error>>(res: T): T;
93
+ changeManager(name: string, opts?: {
94
+ force?: boolean;
95
+ }): Result<void, Error>;
96
+ deleteManager(name: string): Result<void, Error>;
97
+ renameManager(name: string): void;
98
+ duplicateManager(oldName: string, newName: string): Result<Manager, Error>;
99
+ exportManagers(names: string[]): Result<object, Error>;
100
+ importManagers(content: string): Result<void, Error>;
101
+ /** Clears all managers and resets the state. `init` must be called again if you want to use the class instance again. */
102
+ clearAll(): void;
103
+ }
@@ -0,0 +1,267 @@
1
+ import { debounce } from "@alanscodelog/utils/debounce";
2
+ import { isArray } from "@alanscodelog/utils/isArray";
3
+ import { keys } from "@alanscodelog/utils/keys";
4
+ import { Err, Ok } from "@alanscodelog/utils/Result";
5
+ import { setReadOnly } from "@alanscodelog/utils/setReadOnly";
6
+ import { managerToStorableClone } from "../helpers/managerToStorableClone.js";
7
+ export class ShortcutManagerManager {
8
+ storageKeys;
9
+ managerNames = [];
10
+ managers = {};
11
+ activeManagerName = "default";
12
+ /** A debounced version of the save function. Is already bound to the instance. */
13
+ debouncedSave;
14
+ storage;
15
+ /**
16
+ * All new managers will be created using this function. It should be capable of taking as little information as `{name}` (when a new manager is created) and returining a full manger.
17
+ *
18
+ * It's suggested you not do validation here, use the `onParse` hook instead.
19
+ *
20
+ * If you return an error, `onError` will be called, and no manager will be created.
21
+ */
22
+ createManager;
23
+ hooks;
24
+ constructor(createManager, hooks, {
25
+ storageKeys = {},
26
+ storage = localStorage
27
+ } = {}) {
28
+ this.createManager = createManager;
29
+ this.hooks = hooks;
30
+ storageKeys.prefix ??= "";
31
+ storageKeys.managerNames ??= "shortcut-manager:names";
32
+ storageKeys.managerPrefix ??= "shortcut-manager:manager.";
33
+ storageKeys.activeManager ??= "shortcut-manager:active";
34
+ if (storageKeys.prefix) {
35
+ for (const key of keys(storageKeys)) {
36
+ if (key === "prefix") continue;
37
+ storageKeys[key] = `${storageKeys.prefix}${storageKeys[key]}`;
38
+ }
39
+ }
40
+ this.storageKeys = storageKeys;
41
+ this.storage = storage;
42
+ this.debouncedSave = debounce(this.save.bind(this), 500);
43
+ }
44
+ init() {
45
+ const list = this.storage.getItem(this.storageKeys.managerNames);
46
+ const active = this.storage.getItem(this.storageKeys.activeManager);
47
+ this.setManagerNames(list ? JSON.parse(list) : []);
48
+ if (this.managerNames.length > 0) {
49
+ const res = this.managerNames.map((m) => {
50
+ const r = this.storageReadManager(m, { force: true });
51
+ this.notifyIfError(r);
52
+ if (r.isOk) {
53
+ this.load(r.value);
54
+ }
55
+ return r;
56
+ });
57
+ const ok = res.filter((r) => r.isOk);
58
+ if (ok.length > 0) {
59
+ this.loadOrCreateDefault();
60
+ }
61
+ if (active && this.managerNames.includes(active)) {
62
+ this.setActiveManager(active);
63
+ } else {
64
+ this.setActiveManager(this.managerNames[0]);
65
+ }
66
+ } else {
67
+ this.loadOrCreateDefault();
68
+ }
69
+ }
70
+ setManager(name, clone) {
71
+ if (clone === void 0) {
72
+ delete this.managers[name];
73
+ } else {
74
+ setReadOnly(this.managers, name, clone);
75
+ }
76
+ this.hooks.onSetManager?.(name, clone);
77
+ }
78
+ setManagerNames(names) {
79
+ setReadOnly(this, "managerNames", names);
80
+ this.hooks.onSetManagerNames?.(names);
81
+ }
82
+ setActiveManager(name) {
83
+ setReadOnly(this, "activeManagerName", name);
84
+ this.storage.setItem(this.storageKeys.activeManager, name);
85
+ this.hooks.onSetActiveManager?.(name);
86
+ }
87
+ addManager(name, clone) {
88
+ this.setManager(name, clone);
89
+ if (!this.managerNames.includes(name)) {
90
+ this.setManagerNames([...this.managerNames, name]);
91
+ }
92
+ }
93
+ removeManager(name) {
94
+ this.setManager(name, void 0);
95
+ const index = this.managerNames.indexOf(name);
96
+ if (index === -1) return;
97
+ this.setManagerNames(this.managerNames.toSpliced(index, 1));
98
+ }
99
+ storageSaveManager(name, clone) {
100
+ this.storage.setItem(`${this.storageKeys.managerPrefix}${name}`, JSON.stringify(clone));
101
+ if (!this.managerNames.includes(name)) {
102
+ this.managerNames.push(name);
103
+ this.storage.setItem(
104
+ this.storageKeys.managerNames,
105
+ JSON.stringify(this.managerNames)
106
+ );
107
+ }
108
+ }
109
+ storageRemoveManager(name) {
110
+ this.storage.removeItem(`${this.storageKeys.managerPrefix}${name}`);
111
+ const index = this.managerNames.indexOf(name);
112
+ if (index > -1) {
113
+ this.managerNames.splice(index, 1);
114
+ this.storage.setItem(
115
+ this.storageKeys.managerNames,
116
+ JSON.stringify(this.managerNames)
117
+ );
118
+ }
119
+ }
120
+ storageReadManager(name, { force = false } = {}) {
121
+ const raw = this.storage.getItem(`${this.storageKeys.managerPrefix}${name}`);
122
+ if (!raw && !force) {
123
+ const res = Err(new Error(`No manager found by the name of ${name}.`));
124
+ return this.notifyIfError(res);
125
+ }
126
+ const r = this.createManager(
127
+ !raw && force ? { name } : this.parseJsonManager(raw).unwrap(),
128
+ force
129
+ );
130
+ if (r instanceof Error) return Err(r);
131
+ return Ok(r);
132
+ }
133
+ parseJsonManager(raw) {
134
+ if (!raw) {
135
+ return Err(new Error(`Nothing to parse.`));
136
+ }
137
+ try {
138
+ const parsed = JSON.parse(raw);
139
+ const res = this.hooks.onParse?.(parsed);
140
+ if (res instanceof Error) {
141
+ return this.notifyIfError(Err(res));
142
+ }
143
+ if (res === void 0) throw new Error(`onParse must return a value.`);
144
+ return Ok(res ?? parsed);
145
+ } catch (e) {
146
+ return Err(e);
147
+ }
148
+ }
149
+ load(manager, {
150
+ doActivate = true
151
+ } = {}) {
152
+ this.setManager(manager.name, manager);
153
+ if (doActivate) {
154
+ this.setActiveManager(manager.name);
155
+ }
156
+ this.save(manager.name);
157
+ }
158
+ loadOrCreateDefault() {
159
+ const r = this.storageReadManager("default", { force: true });
160
+ this.notifyIfError(r);
161
+ if (r.isOk) {
162
+ this.load(r.value);
163
+ }
164
+ }
165
+ save(name) {
166
+ if (!this.managers[name]) {
167
+ this.notifyIfError(Err(new Error(`Manager ${name} not found`)));
168
+ }
169
+ const clone = managerToStorableClone(this.managers[name]);
170
+ this.hooks.onSave?.(clone);
171
+ this.storageSaveManager(name, clone);
172
+ }
173
+ notifyIfError(res) {
174
+ if (!res.isOk) {
175
+ this.hooks.onError?.(res.error);
176
+ }
177
+ return res;
178
+ }
179
+ changeManager(name, opts = {}) {
180
+ if (this.managerNames.includes(name)) {
181
+ this.setActiveManager(name);
182
+ return Ok();
183
+ } else {
184
+ const m = this.storageReadManager(name, opts);
185
+ if (m.isOk) {
186
+ this.load(m.value);
187
+ this.setActiveManager(name);
188
+ }
189
+ return Ok();
190
+ }
191
+ }
192
+ deleteManager(name) {
193
+ const index = this.managerNames.indexOf(name);
194
+ let nextName = this.managerNames[index - 1] ?? this.managerNames[index + 1] ?? "default";
195
+ this.storageRemoveManager(name);
196
+ this.setManager(name, void 0);
197
+ if (nextName === name) nextName = "default";
198
+ const res = this.changeManager(nextName, { force: true });
199
+ this.notifyIfError(res);
200
+ return res;
201
+ }
202
+ renameManager(name) {
203
+ this.storageRemoveManager(this.activeManagerName);
204
+ this.setManager(name, this.managers[this.activeManagerName]);
205
+ this.setManager(this.activeManagerName, void 0);
206
+ this.setActiveManager(name);
207
+ this.save(name);
208
+ }
209
+ duplicateManager(oldName, newName) {
210
+ const m = this.managers[oldName];
211
+ if (!m) {
212
+ const res = Err(new Error(`No manager found by the name of ${oldName}.`));
213
+ return this.notifyIfError(res);
214
+ }
215
+ const clone = managerToStorableClone(m);
216
+ clone.name = newName;
217
+ const instance = this.createManager(clone, false);
218
+ if (instance instanceof Error) return this.notifyIfError(Err(instance));
219
+ else if (instance) this.load(instance);
220
+ return Ok(instance);
221
+ }
222
+ exportManagers(names) {
223
+ const obj = { managers: [] };
224
+ for (const name of names) {
225
+ const m = this.managers[name];
226
+ if (!m) {
227
+ const res = Err(new Error(`No manager found by the name of ${name}.`));
228
+ return this.notifyIfError(res);
229
+ }
230
+ const clone = managerToStorableClone(m);
231
+ this.hooks.onSave?.(clone);
232
+ obj.managers.push(clone);
233
+ }
234
+ this.hooks.onExport?.(obj);
235
+ return Ok(obj);
236
+ }
237
+ importManagers(content) {
238
+ const p = JSON.parse(content);
239
+ if (!p.managers || !isArray(p.manager)) {
240
+ return Err(new Error(`Not a valid manager file.`));
241
+ }
242
+ const ok = [];
243
+ for (const parsedM of p.managers) {
244
+ const m = this.parseJsonManager(JSON.stringify(parsedM));
245
+ this.notifyIfError(m);
246
+ if (m.isOk) {
247
+ const instance = this.createManager(m.value, false);
248
+ if (instance instanceof Error) return this.notifyIfError(Err(instance));
249
+ ok.push(instance);
250
+ }
251
+ }
252
+ for (const instance of ok) {
253
+ this.load(instance);
254
+ }
255
+ return Ok();
256
+ }
257
+ /** Clears all managers and resets the state. `init` must be called again if you want to use the class instance again. */
258
+ clearAll() {
259
+ this.storage.removeItem(this.storageKeys.managerNames);
260
+ this.storage.removeItem(this.storageKeys.activeManager);
261
+ for (const name of this.managerNames) {
262
+ this.storageRemoveManager(name);
263
+ }
264
+ this.setManagerNames([]);
265
+ this.setActiveManager("default");
266
+ }
267
+ }
@@ -0,0 +1,7 @@
1
+ import { type Result } from "@alanscodelog/utils/Result";
2
+ import type { CanHookErrors, Command, CommandsSetEntries, Manager, MultipleErrors } from "../types/index.js";
3
+ export declare function addCommand<THooks extends Manager["hooks"], TCheck extends boolean | "only" = true>(command: Command, manager: CommandsSetEntries["entries@add"]["manager"] & {
4
+ hooks?: THooks;
5
+ }, opts?: {
6
+ check?: TCheck;
7
+ }): Result<TCheck extends "only" ? true : Command, MultipleErrors<CommandsSetEntries["entries@add"]["error"]> | CanHookErrors<THooks extends never ? never : THooks, "canSetCommandsProp">>;
@@ -0,0 +1,7 @@
1
+ import { Ok } from "@alanscodelog/utils/Result";
2
+ import { setCommandsProp } from "./setCommandsProp.js";
3
+ export function addCommand(command, manager, opts = {}) {
4
+ const res = setCommandsProp("entries@add", command, manager, opts);
5
+ if (res.isError) return res;
6
+ return Ok(command);
7
+ }
@@ -0,0 +1,7 @@
1
+ import { type Result } from "@alanscodelog/utils/Result";
2
+ import type { CanHookErrors, Key, KeysSetEntries, Manager, MultipleErrors } from "../types/index.js";
3
+ export declare function addKey<THooks extends Manager["hooks"], TCheck extends boolean | "only" = true>(key: Key, manager: KeysSetEntries["entries@add"]["manager"] & {
4
+ hooks?: THooks;
5
+ }, opts?: {
6
+ check?: TCheck;
7
+ }): Result<TCheck extends "only" ? true : Key, MultipleErrors<KeysSetEntries["entries@add"]["error"]> | CanHookErrors<THooks extends never ? never : THooks, "canSetKeysProp">>;
@@ -0,0 +1,7 @@
1
+ import { Ok } from "@alanscodelog/utils/Result";
2
+ import { setKeysProp } from "./setKeysProp.js";
3
+ export function addKey(key, manager, opts = {}) {
4
+ const res = setKeysProp("entries@add", key, manager, opts);
5
+ if (res.isError) return res;
6
+ return Ok(key);
7
+ }
@@ -0,0 +1,7 @@
1
+ import { type Result } from "@alanscodelog/utils/Result";
2
+ import type { CanHookErrors, Manager, MultipleErrors, Shortcut, ShortcutsSetEntries } from "../types/index.js";
3
+ export declare function addShortcut<THooks extends Manager["hooks"], TCheck extends boolean | "only" = true>(shortcut: Shortcut, manager: ShortcutsSetEntries["entries@add"]["manager"] & {
4
+ hooks?: THooks;
5
+ }, opts?: {
6
+ check?: TCheck;
7
+ }): Result<TCheck extends "only" ? true : Shortcut, MultipleErrors<ShortcutsSetEntries["entries@add"]["error"]> | CanHookErrors<THooks extends never ? never : THooks, "canSetShortcutsProp">>;
@@ -0,0 +1,7 @@
1
+ import { Ok } from "@alanscodelog/utils/Result";
2
+ import { setShortcutsProp } from "./setShortcutsProp.js";
3
+ export function addShortcut(shortcut, manager, opts = {}) {
4
+ const res = setShortcutsProp("entries@add", shortcut, manager, opts);
5
+ if (res.isError) return res;
6
+ return Ok(shortcut);
7
+ }
@@ -0,0 +1,10 @@
1
+ import type { AnyFunction } from "@alanscodelog/utils/types";
2
+ import type { AttachTarget, EventTypes } from "../types/index.js";
3
+ /**
4
+ * Attach the event listeners created by {@link createManagerEventListeners} to an element or {@link Emulator} so the manager can listen to the needed event hooks.
5
+ *
6
+ * They can be removed with {@link detach} or by aborting the controller returned by the function.
7
+ */
8
+ export declare function attach(el: AttachTarget, listeners: Record<EventTypes, AnyFunction>,
9
+ /** Add options to some listeners. An abort controller is added by default. You can use the `*` key to set a default for all. */
10
+ opts?: Partial<Record<EventTypes | "*", AddEventListenerOptions>>): AbortController;
@@ -0,0 +1,13 @@
1
+ import { keys } from "@alanscodelog/utils/keys";
2
+ export function attach(el, listeners, opts = { wheel: { passive: true } }) {
3
+ const controller = new AbortController();
4
+ const defaultOpts = opts["*"] ?? {};
5
+ for (const listenerName of keys(listeners)) {
6
+ el.addEventListener(listenerName, listeners[listenerName], {
7
+ signal: controller.signal,
8
+ ...defaultOpts,
9
+ ...opts[listenerName]
10
+ });
11
+ }
12
+ return controller;
13
+ }
@@ -0,0 +1,4 @@
1
+ import type { Command, CommandExecute, RawCommand } from "../types/index.js";
2
+ export declare function createCommand<TName extends string = string, TCommand extends RawCommand<TName> = RawCommand<TName>>(name: TName, rawCommand?: Omit<TCommand, "name" | "execute"> & {
3
+ execute: CommandExecute<TName>;
4
+ }): Command;
@@ -0,0 +1,11 @@
1
+ export function createCommand(name, rawCommand = {}) {
2
+ const command = {
3
+ ...rawCommand,
4
+ type: "command",
5
+ name,
6
+ execute: rawCommand.execute,
7
+ description: rawCommand.description ?? "",
8
+ condition: rawCommand.condition ?? { type: "condition", text: "" }
9
+ };
10
+ return command;
11
+ }
@@ -0,0 +1,11 @@
1
+ import { type Result } from "@alanscodelog/utils/Result";
2
+ import type { CanHookErrors, Command, Commands, CommandsSetEntries, Manager, MultipleErrors, PickManager } from "../types/index.js";
3
+ /**
4
+ * # Commands
5
+ * Creates a set of commands.
6
+ */
7
+ export declare function createCommands<THooks extends Manager["hooks"], TEntries extends Record<string, Command>, TCheck extends boolean | "only" = true>(commandsList: Command[], manager?: PickManager<"options", "stringifier"> & {
8
+ hooks?: THooks;
9
+ }, { check }?: {
10
+ check?: TCheck;
11
+ }): Result<TCheck extends "only" ? true : Commands<TEntries>, MultipleErrors<CommandsSetEntries["entries@add"]["error"]> | CanHookErrors<THooks extends never ? never : THooks, "canSetCommandsProp">>;
@@ -0,0 +1,20 @@
1
+ import { Ok } from "@alanscodelog/utils/Result";
2
+ import { addCommand } from "./addCommand.js";
3
+ import { defaultStringifier } from "../defaults/Stringifier.js";
4
+ export function createCommands(commandsList, manager = {
5
+ options: { stringifier: defaultStringifier }
6
+ }, { check = true } = {}) {
7
+ const commands = {
8
+ type: "commands",
9
+ entries: {}
10
+ };
11
+ const managerClone = { ...manager, commands };
12
+ if (check) {
13
+ for (const command of commandsList) {
14
+ const res = addCommand(command, managerClone);
15
+ if (res.isError) return res;
16
+ }
17
+ }
18
+ if (check === "only") return Ok(true);
19
+ return Ok(commands);
20
+ }
@@ -0,0 +1,7 @@
1
+ import type { Condition } from "../types/index.js";
2
+ export declare function createCondition<TTextCondition extends string, TReturn extends Condition>(rawCondition: TTextCondition,
3
+ /**
4
+ * Optionally modify the shape of the condition and add your own properties.
5
+ * For example, you can append a parsed AST like representation of the condition.
6
+ */
7
+ parse?: (raw: TTextCondition, condition: Condition) => TReturn): TReturn;
@@ -0,0 +1,11 @@
1
+ export function createCondition(rawCondition, parse) {
2
+ let condition = {
3
+ ...rawCondition,
4
+ type: "condition",
5
+ text: rawCondition ?? ""
6
+ };
7
+ if (parse) {
8
+ condition = parse(rawCondition, condition);
9
+ }
10
+ return condition;
11
+ }