@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,84 @@
1
+ import { multisplice } from "@alanscodelog/utils/multisplice"
2
+
3
+ import { addToChain } from "./addToChain.js"
4
+ import { getModifierState } from "./getModifierState.js"
5
+ import { removeFromChain } from "./removeFromChain.js"
6
+ import { safeSetEmulatedToggleState } from "./safeSetEmulatedToggleState.js"
7
+
8
+ import { setKeyProp } from "../core/setKeyProp.js"
9
+ import { KnownError } from "../helpers/KnownError.js"
10
+ import type { AnyInputEvent, Manager } from "../types/index.js"
11
+ import { SHORTCUT_ERROR } from "../types/index.js"
12
+
13
+ /**
14
+ * Should be used after we attempt to process the event and set key states.
15
+ *
16
+ * This should cause it to only actually change the state if it was changed off-focus.
17
+ *
18
+ * Technically not neccesary with wheel/mouse events, but ordered similarly for consistency.
19
+ *
20
+ * Modifiers need to be added/removed from the chain on changes, but not toggles.
21
+ *
22
+ * Mutates the passed keys array to remove processed keys.
23
+ *
24
+ */
25
+ export function updateNativeKeysState(
26
+ manager: Manager,
27
+ e: AnyInputEvent,
28
+ keyIds: string[] = []
29
+ ): void {
30
+ const s = manager.options.stringifier
31
+ for (const id of manager.keys.nativeToggleKeys) {
32
+ const key = manager.keys.entries[id]
33
+ if (key.toggleOnPressed && key.toggleOffPressed) {
34
+ throw new KnownError(SHORTCUT_ERROR.INCORRECT_TOGGLE_STATE, `Key ${s.stringify(key, manager)} is a toggle key whose on and off versions are both pressed, which is not a valid state.`, { key })
35
+ }
36
+ // this does not guarantee the key code is valid
37
+ // it just returns false even for made up keys
38
+ const modifierState = getModifierState(key, e, manager)
39
+
40
+
41
+ if (modifierState === null) continue
42
+ if (modifierState) {
43
+ if (!key.toggleOnPressed) {
44
+ safeSetEmulatedToggleState(key, true, manager)
45
+ }
46
+ } else {
47
+ if (key.toggleOnPressed) {
48
+ safeSetEmulatedToggleState(key, false, manager)
49
+ }
50
+ }
51
+ }
52
+ const added: string[] = []
53
+ const removed: string[] = []
54
+ for (const id of manager.keys.nativeModifierKeys) {
55
+ const key = manager.keys.entries[id]
56
+ const modifierState = getModifierState(key, e, manager)
57
+ if (modifierState === null) continue
58
+ if (modifierState) {
59
+ if (!key.pressed) {
60
+ if (setKeyProp(key, "pressed", true, manager).isOk) {
61
+ added.push(id)
62
+ }
63
+ }
64
+ } else {
65
+ if (key.pressed) {
66
+ if (setKeyProp(key, "pressed", false, manager).isOk) {
67
+ removed.push(id)
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ if (added.length > 0) {
74
+ addToChain(manager, added, e)
75
+ const indexes = keyIds.map(key => added.indexOf(key)).filter(i => i > -1)
76
+ multisplice(keyIds, indexes)
77
+ }
78
+ if (removed.length > 0) {
79
+ removeFromChain(manager, removed, e)
80
+ const indexes = keyIds.map(key => added.indexOf(key)).filter(i => i > -1)
81
+ multisplice(keyIds, indexes)
82
+ }
83
+ }
84
+
@@ -0,0 +1,328 @@
1
+ import { calculateAndSetPositionAndSize } from "../helpers/calculateAndSetPositionAndWidth.js"
2
+ import type { RawKey } from "../types/keys.js"
3
+
4
+
5
+ const start = 0
6
+ const mediaKey = { height: 0.5, width: 4 / 3 }
7
+ const setY = <T extends Record<"id", string>>(yVal: number) => (val: T): (T & { y: number }) => {
8
+ (val as any).y = yVal
9
+ return val as any
10
+ }
11
+
12
+ /**
13
+ * Creates the given keyboard layout, assiging the correct sizes and positions to keys.
14
+ *
15
+ * It returns an array of raw keys so that if you're extending {@link Key} you can create them with your extended class (you should override {@link Key.create}).
16
+ *
17
+ * Labels are assigned for most keys in english as a fallback, see {@link labelWithEvent}/{@link labelWithKeyboardMap} for proper labeling during runtime.
18
+ *
19
+ * Currently only supports generating the following layouts: `ansi`, `iso`. Technically the layout returned is a variation of these that includes half height 1.3333u (4u / 3 keys) media keys over the numpad.
20
+ *
21
+ * Pull requests for [standard layouts]([https://www.w3.org/TR/uievents-code) welcomed.
22
+ *
23
+ * You can remove sections using the options. Note that this just removes them and does not do any repositioning. If you only remove the numpad, for example, the media keys will still be placed above it. The idea is to easily allow reducing the size of the created layout to then adjust only a few keys to your liking.
24
+ *
25
+ * Also note the `navigation` section is split into two sections with `navigation` only refering to the 6 `Insert`, `Home`, etc. keys, and `arrowKeys` refering to the arrow keys.
26
+ *
27
+ * This also adds the following classes to some keys: `center-label` for media and arrow keys, and `iso-enter` for the iso enter which requires a different approach to styling (see the demo, it's painful).
28
+ */
29
+
30
+ export function createLayout<
31
+ TNumpad extends boolean = true,
32
+ TMediaKeys extends boolean = true,
33
+ TFn extends boolean = true,
34
+ TNavigation extends boolean = true,
35
+ TArrowKeys extends boolean = true,
36
+ TNames extends string = "Escape"
37
+ | (
38
+ TFn extends true
39
+ ? "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12"
40
+ : never
41
+ )
42
+ | "Backquote" | "Digit1" | "Digit2" | "Digit3" | "Digit4" | "Digit5" | "Digit6" | "Digit7" | "Digit8" | "Digit9" | "Digit0" | "Minus" | "Equal" | "Backspace"
43
+ | "Tab" | "KeyQ" | "KeyW" | "KeyE" | "KeyR" | "KeyT" | "KeyY" | "KeyU" | "KeyI" | "KeyO" | "KeyP" | "BracketLeft" | "BracketRight" | "Backslash"
44
+ | "CapsLock" | "KeyA" | "KeyS" | "KeyD" | "KeyF" | "KeyG" | "KeyH" | "KeyJ" | "KeyK" | "KeyL" | "Semicolon" | "Quote" | "Enter"
45
+ | "VirtualShiftLeft" | "IntlBackslash" | "KeyZ" | "KeyX" | "KeyC" | "KeyV" | "KeyB" | "KeyN" | "KeyM" | "Comma" | "Period" | "Slash" | "VirtualShiftRight"
46
+ | "VirtualControlLeft" | "VirtualMetaLeft" | "VirtualAltLeft" | "Space" | "VirtualAltRight" | "VirtualMetaRight" | "ContextMenu" | "VirtualControlRight"
47
+
48
+ | "PrintScreen"
49
+ | "ScrollLock"
50
+ | "Pause"
51
+
52
+ | (
53
+ TNavigation extends true
54
+ ? "Insert" | "Home" | "PageUp"
55
+ : never
56
+ )
57
+ | (
58
+ TArrowKeys extends true
59
+ ? "ArrowUp" | "ArrowLeft" | "ArrowDown" | "ArrowRight"
60
+ : never
61
+ )
62
+
63
+ | (
64
+ TMediaKeys extends true
65
+ ? "AudioVolumeMute" | "AudioVolumeDown" | "AudioVolumeUp" | "MediaTrackPrevious" | "MediaTrackPause" | "MediaTrackNext"
66
+ : never
67
+ )
68
+ | (
69
+ TNumpad extends true
70
+ ? ("NumLock" | "NumpadDivide" | "NumpadMultiply" | "NumpadSubtract"
71
+ | "Numpad7" | "Numpad8" | "Numpad9" | "NumpadAdd"
72
+ | "Numpad4" | "Numpad5" | "Numpad6"
73
+ | "Numpad1" | "Numpad2" | "Numpad3" | "NumpadEnter"
74
+ | "Numpad0" | "NumpadDecimal")
75
+ : never
76
+ )
77
+ >(
78
+ type: "ansi" | "iso" | "" = "ansi",
79
+ {
80
+ numpad = true as any,
81
+ mediaKeys = true as any,
82
+ fn = true as any,
83
+ navigation = true as any,
84
+ arrowKeys = true as any
85
+ }:
86
+ Partial<{
87
+ numpad: TNumpad
88
+ mediaKeys: TMediaKeys
89
+ fn: TFn
90
+ navigation: TNavigation
91
+ arrowKeys: TArrowKeys
92
+ }> = {}
93
+ ): RawKey<TNames>[] {
94
+ const keys = [
95
+ ...calculateAndSetPositionAndSize([
96
+ { id: "Escape" as const, label: "Esc" },
97
+ ...(fn
98
+ ? [
99
+ { id: "F1" as const, x: 2 },
100
+ { id: "F2" as const },
101
+ { id: "F3" as const },
102
+ { id: "F4" as const },
103
+ { id: "F5" as const, x: 6.5 },
104
+ { id: "F6" as const },
105
+ { id: "F7" as const },
106
+ { id: "F8" as const },
107
+ { id: "F9" as const, x: 11 },
108
+ { id: "F10" as const },
109
+ { id: "F11" as const },
110
+ { id: "F12" as const }
111
+ ] as const
112
+ : []
113
+ )
114
+ ]).map(setY(start + 0)),
115
+ ...calculateAndSetPositionAndSize([
116
+ { id: "Backquote" as const, label: "`" },
117
+ { id: "Digit1" as const, label: "1" },
118
+ { id: "Digit2" as const, label: "2" },
119
+ { id: "Digit3" as const, label: "3" },
120
+ { id: "Digit4" as const, label: "4" },
121
+ { id: "Digit5" as const, label: "5" },
122
+ { id: "Digit6" as const, label: "6" },
123
+ { id: "Digit7" as const, label: "7" },
124
+ { id: "Digit8" as const, label: "8" },
125
+ { id: "Digit9" as const, label: "9" },
126
+ { id: "Digit0" as const, label: "0" },
127
+ { id: "Minus" as const, label: "-" },
128
+ { id: "Equal" as const, label: "=" },
129
+ { id: "Backspace" as const, width: 2 }
130
+ ] as const).map(setY(start + 2)),
131
+ ...calculateAndSetPositionAndSize([
132
+ { id: "Tab" as const, width: 1.5 },
133
+ { id: "KeyQ" as const, label: "q" },
134
+ { id: "KeyW" as const, label: "w" },
135
+ { id: "KeyE" as const, label: "e" },
136
+ { id: "KeyR" as const, label: "r" },
137
+ { id: "KeyT" as const, label: "t" },
138
+ { id: "KeyY" as const, label: "y" },
139
+ { id: "KeyU" as const, label: "u" },
140
+ { id: "KeyI" as const, label: "i" },
141
+ { id: "KeyO" as const, label: "o" },
142
+ { id: "KeyP" as const, label: "p" },
143
+ { id: "BracketLeft" as const, label: "[" },
144
+ { id: "BracketRight" as const, label: "]" },
145
+ type === "ansi"
146
+ ? { id: "Backslash" as const, label: "\\", width: 1.5 }
147
+ : type === "iso"
148
+ ? { id: "Enter" as const, width: 1.5, height: 2, classes: ["iso-enter"] }
149
+ : {} as never
150
+ ] as const).map(setY(start + 3)),
151
+ ...calculateAndSetPositionAndSize([
152
+ { id: "CapsLock" as const, width: 1.75, isToggle: "native" as const },
153
+ { id: "KeyA" as const, label: "a" },
154
+ { id: "KeyS" as const, label: "s" },
155
+ { id: "KeyD" as const, label: "d" },
156
+ { id: "KeyF" as const, label: "f" },
157
+ { id: "KeyG" as const, label: "g" },
158
+ { id: "KeyH" as const, label: "h" },
159
+ { id: "KeyJ" as const, label: "j" },
160
+ { id: "KeyK" as const, label: "k" },
161
+ { id: "KeyL" as const, label: "l" },
162
+ { id: "Semicolon" as const, label: ";" },
163
+ { id: "Quote" as const, label: "'" },
164
+ type === "ansi"
165
+ ? { id: "Enter" as const, width: 2.25 }
166
+ : type === "iso"
167
+ ? { id: "Backslash" as const, label: "#", width: 1 }
168
+ : {} as never
169
+ ] as const).map(setY(start + 4)),
170
+ ...calculateAndSetPositionAndSize([
171
+ ...(type === "ansi"
172
+ ? [
173
+ { id: "VirtualShiftLeft" as const, isModifier: "native" as const, label: "Shift", variants: ["ShiftLeft", "ShiftRight", "Shift"], width: 2.25 }
174
+ ]
175
+ : type === "iso"
176
+ ? [
177
+ { id: "VirtualShiftLeft" as const, isModifier: "native" as const, label: "Shift", variants: ["ShiftLeft", "ShiftRight", "Shift"], width: 1.25 },
178
+ { id: "IntlBackslash" as const, label: "\\", width: 1 }
179
+ ]
180
+ : []),
181
+ { id: "KeyZ" as const, label: "z" },
182
+ { id: "KeyX" as const, label: "x" },
183
+ { id: "KeyC" as const, label: "c" },
184
+ { id: "KeyV" as const, label: "v" },
185
+ { id: "KeyB" as const, label: "b" },
186
+ { id: "KeyN" as const, label: "n" },
187
+ { id: "KeyM" as const, label: "m" },
188
+ { id: "Comma" as const, label: "," },
189
+ { id: "Period" as const, label: "." },
190
+ { id: "Slash" as const, label: "/" },
191
+ {
192
+ id: "VirtualShiftRight" as const,
193
+ isModifier: "native" as const,
194
+ label: "Shift",
195
+ variants: ["ShiftLeft", "ShiftRight", "Shift"],
196
+ width: 2.75
197
+ }
198
+ ] as const).map(setY(start + 5)),
199
+ ...calculateAndSetPositionAndSize([
200
+ {
201
+ id: "VirtualControlLeft" as const,
202
+ isModifier: "native" as const,
203
+ label: "Ctrl",
204
+ variants: ["ControlLeft", "ControlRight", "Control", "Ctrl"],
205
+ width: 1.25
206
+ },
207
+ {
208
+ id: "VirtualMetaLeft" as const,
209
+ isModifier: "native" as const,
210
+ label: "Meta",
211
+ variants: ["MetaLeft", "MetaRight", "Meta"],
212
+ width: 1.25
213
+ },
214
+ {
215
+ id: "VirtualAltLeft" as const,
216
+ isModifier: "native" as const,
217
+ label: "Alt",
218
+ variants: ["AltLeft", "AltRight", "Alt"],
219
+ width: 1.25
220
+ },
221
+ { id: "Space" as const, label: "", width: 6.25 },
222
+ {
223
+ id: "VirtualAltRight" as const,
224
+ isModifier: "native" as const,
225
+ label: "Alt",
226
+ variants: ["AltLeft", "AltRight", "Alt"],
227
+ width: 1.25
228
+ },
229
+ {
230
+ id: "VirtualMetaRight" as const,
231
+ isModifier: "native" as const,
232
+ label: "Meta",
233
+ variants: ["MetaLeft", "MetaRight", "Meta"],
234
+ width: 1.25
235
+ },
236
+ { id: "ContextMenu" as const, label: "Menu", width: 1.25 },
237
+ {
238
+ id: "VirtualControlRight" as const,
239
+ isModifier: "native" as const,
240
+ label: "Ctrl",
241
+ variants: ["ControlLeft", "ControlRight", "Control", "Ctrl"],
242
+ width: 1.25
243
+ }
244
+ ] as const).map(setY(start + 6)),
245
+ ...calculateAndSetPositionAndSize([
246
+ { id: "PrintScreen" as const, label: "PrtScn", x: 15.5 },
247
+ { id: "ScrollLock" as const, label: "Scroll\nLock", isToggle: "native" as const },
248
+ { id: "Pause" as const, label: "Pause\nBreak" }
249
+ ] as const).map(setY(start)),
250
+ ...(navigation
251
+ ? [
252
+ ...calculateAndSetPositionAndSize([
253
+ { id: "Insert" as const, x: 15.5 },
254
+ { id: "Home" as const },
255
+ { id: "PageUp" as const, label: "Pg\nUp" }
256
+ ] as const).map(setY(start + 2)),
257
+ ...calculateAndSetPositionAndSize([
258
+ { id: "Delete" as const, x: 15.5 },
259
+ { id: "End" as const },
260
+ { id: "PageDown" as const, label: "Pg\nDown" }
261
+ ] as const).map(setY(start + 3))
262
+ ]
263
+ : []
264
+ ),
265
+ ...(arrowKeys
266
+ ? [
267
+ ...calculateAndSetPositionAndSize([
268
+ { id: "ArrowUp" as const, label: "▲", x: 16.5, y: start + 5, classes: ["center-label"] }
269
+ ]),
270
+ ...calculateAndSetPositionAndSize([
271
+ { id: "ArrowLeft" as const, label: "◄", x: 15.5, classes: ["center-label"] },
272
+ { id: "ArrowDown" as const, label: "▼", classes: ["center-label"] },
273
+ { id: "ArrowRight" as const, label: "►", classes: ["center-label"] }
274
+ ] as const).map(setY(start + 6))
275
+ ]
276
+ : []
277
+ ),
278
+ ...(
279
+ mediaKeys
280
+ ? [
281
+ ...calculateAndSetPositionAndSize([
282
+ { id: "AudioVolumeMute" as const, label: "🔇", x: 19, ...mediaKey, classes: ["center-label"] },
283
+ { id: "AudioVolumeDown" as const, label: "🔉", ...mediaKey, classes: ["center-label"] },
284
+ { id: "AudioVolumeUp" as const, label: "🔊", ...mediaKey, classes: ["center-label"] }
285
+ ]).map(setY(start)),
286
+ ...calculateAndSetPositionAndSize([
287
+ { id: "MediaTrackPrevious" as const, label: "⏮️", x: 19, ...mediaKey, classes: ["center-label"] },
288
+ { id: "MediaTrackPause" as const, label: "⏯️", ...mediaKey, classes: ["center-label"] },
289
+ { id: "MediaTrackNext" as const, label: "⏭️", ...mediaKey, classes: ["center-label"] }
290
+ ]).map(setY(start + 0.5))
291
+ ]
292
+ : []
293
+ ),
294
+ ...(numpad
295
+ ? [
296
+ ...calculateAndSetPositionAndSize([
297
+ { id: "NumLock" as const, label: "Num\nLock", x: 19, isToggle: "native" as const },
298
+ { id: "NumpadDivide" as const, label: "/" },
299
+ { id: "NumpadMultiply" as const, label: "*" },
300
+ { id: "NumpadSubtract" as const, label: "-" }
301
+ ]).map(setY(start + 2)),
302
+ ...calculateAndSetPositionAndSize([
303
+ { id: "Numpad7" as const, label: "7", x: 19 },
304
+ { id: "Numpad8" as const, label: "8" },
305
+ { id: "Numpad9" as const, label: "9" },
306
+ { id: "NumpadAdd" as const, label: "+", height: 2 }
307
+ ]).map(setY(start + 3)),
308
+ ...calculateAndSetPositionAndSize([
309
+ { id: "Numpad4" as const, label: "4", x: 19 },
310
+ { id: "Numpad5" as const, label: "5" },
311
+ { id: "Numpad6" as const, label: "6" }
312
+ ]).map(setY(start + 4)),
313
+ ...calculateAndSetPositionAndSize([
314
+ { id: "Numpad1" as const, label: "1", x: 19 },
315
+ { id: "Numpad2" as const, label: "2" },
316
+ { id: "Numpad3" as const, label: "3" },
317
+ { id: "NumpadEnter" as const, label: "+", height: 2 }
318
+ ]).map(setY(start + 5)),
319
+ ...calculateAndSetPositionAndSize([
320
+ { id: "Numpad0" as const, label: "0", x: 19, width: 2 },
321
+ { id: "NumpadDecimal" as const, label: "." }
322
+ ]).map(setY(start + 6))
323
+ ]
324
+ : []
325
+ )
326
+ ] satisfies RawKey[]
327
+ return keys as any
328
+ }
package/src/module.ts ADDED
@@ -0,0 +1,62 @@
1
+ import {
2
+ addImportsDir,
3
+ addTypeTemplate,
4
+ createResolver,
5
+ defineNuxtModule
6
+ } from "@nuxt/kit"
7
+
8
+ import pkg from "../package.json" with { type: "json" }
9
+
10
+
11
+ const { resolve } = createResolver(import.meta.url)
12
+
13
+ declare module "@nuxt/schema" {
14
+ interface PublicRuntimeConfig {
15
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
16
+ witchcraftSpellcraft: {}
17
+ }
18
+ }
19
+
20
+ export interface ModuleOptions {
21
+
22
+ }
23
+
24
+ export default defineNuxtModule<ModuleOptions>({
25
+ meta: {
26
+ name: "witchcraftSpellcraft",
27
+ configKey: "witchcraftSpellcraft"
28
+ },
29
+ defaults: {
30
+ },
31
+ moduleDependencies: {
32
+ "@witchcraft/ui/nuxt": {
33
+ version: pkg.dependencies["@witchcraft/ui"]
34
+ }
35
+ },
36
+ async setup(_options, nuxt) {
37
+ // nuxt.options.runtimeConfig.public.witchcraftSpellcraft = defu(
38
+ // nuxt.options.runtimeConfig.public.witchcraftSpellcraft,
39
+ // {
40
+ // }
41
+ // )
42
+ addTypeTemplate({
43
+ filename: "types/witchcraft-spellcraft.d.ts",
44
+
45
+ getContents: () => `
46
+ import { type NavigatorWKeyboard } from "./src/types/general.ts"
47
+
48
+
49
+ declare global {
50
+ interface Navigator {
51
+ keyboard: NavigatorWKeyboard["keyboard"]
52
+ }
53
+ }
54
+ `
55
+ })
56
+
57
+ addImportsDir(resolve("runtime/composables"))
58
+ addImportsDir(resolve("runtime/utils"))
59
+
60
+ nuxt.options.alias["#witchcraft-spellcraft"] = resolve("runtime")
61
+ }
62
+ })
@@ -0,0 +1,28 @@
1
+ import { type Ref, ref } from "vue"
2
+
3
+ import { getKeyboardLayoutMap } from "../../helpers/getKeyboardLayoutMap.js"
4
+ import { labelWithKeyboardMap } from "../../helpers/labelWithKeyboardMap.js"
5
+ import { onKeyboardLayoutChange } from "../../helpers/onKeyboardLayoutChange.js"
6
+ import type { Manager } from "../../types/manager.js"
7
+
8
+ /**
9
+ * Sets up {@link getKeyboardLayoutMap} and {@link onKeyboardLayoutChange} to use {@link labelWithKeyboardMap}.
10
+ *
11
+ * Returns a ref of the latest key labels to have been set.
12
+ */
13
+ export function useLabeledByKeyboardLayoutMap(manager: Manager): Ref<ReturnType<typeof labelWithKeyboardMap> | undefined> {
14
+ const labeledByMap = ref<ReturnType<typeof labelWithKeyboardMap>>()
15
+
16
+ void getKeyboardLayoutMap().then(map => {
17
+ if (map) {
18
+ labeledByMap.value = labelWithKeyboardMap(manager, { map })
19
+ }
20
+ })
21
+ void onKeyboardLayoutChange(async () => {
22
+ const map = await getKeyboardLayoutMap()
23
+ if (map) {
24
+ labeledByMap.value = labelWithKeyboardMap(manager, { map })
25
+ }
26
+ })
27
+ return labeledByMap
28
+ }
@@ -0,0 +1,40 @@
1
+ import { computed, type ComputedRef, reactive } from "vue"
2
+ /**
3
+ * Returns a set of coordinates that includes an initial offset.
4
+ *
5
+ * For use with drag or similar events.
6
+ *
7
+ * `setInitialOffset` should be called at drag start.
8
+ *
9
+ * `setPointerCoords` can then be called on drag move.
10
+ *
11
+ * And `coords` will reflect the coordinates of the event + the initial offset.
12
+ *
13
+ * This can then be used to position an element and it won't jump, it will stay grabbed from where the user initially grabbed it.
14
+ */
15
+
16
+
17
+ export const usePointerCoords = (): {
18
+ pointerCoords: { x: number, y: number }
19
+ coords: ComputedRef<{ x: number, y: number }>
20
+ setPointerCoords: (e: { clientX: number, clientY: number }) => void
21
+ setInitialPointerOffset: (e: { clientX: number, clientY: number }, el: HTMLElement) => void
22
+ } => {
23
+ const pointerCoords = reactive<{ x: number, y: number }>({ x: 0, y: 0 })
24
+ const offsetCoords = reactive<{ x: number, y: number }>({ x: 0, y: 0 })
25
+ const coords = computed(() => ({ x: pointerCoords.x - offsetCoords.x, y: pointerCoords.y - offsetCoords.y }))
26
+
27
+ const setPointerCoords = (e: { clientX: number, clientY: number }): void => {
28
+ pointerCoords.x = e.clientX
29
+ pointerCoords.y = e.clientY
30
+ }
31
+
32
+ const setInitialPointerOffset = (e: { clientX: number, clientY: number }, el: HTMLElement): void => {
33
+ setPointerCoords(e)
34
+ const clientRect = el.getBoundingClientRect()
35
+ offsetCoords.x = pointerCoords.x - clientRect.x
36
+ offsetCoords.y = pointerCoords.y - clientRect.y
37
+ }
38
+
39
+ return { pointerCoords, coords, setPointerCoords, setInitialPointerOffset }
40
+ }
@@ -0,0 +1,81 @@
1
+ import { keys } from "@alanscodelog/utils/keys"
2
+ import { unreachable } from "@alanscodelog/utils/unreachable"
3
+ import { extractTokens } from "@witchcraft/expressit/utils/extractTokens"
4
+ import { type ComputedRef, type Ref, watch } from "vue"
5
+
6
+ import type { Manager } from "../../types/manager.js"
7
+ import type { ContextInfo } from "../types.js"
8
+
9
+ /**
10
+ * Updates the count of the ctx variables depending on how many shortcuts are using the variable. Requires shortcuts use the expressit library to set the ast property of conditions.
11
+ *
12
+ * Useful to know if we can delete a ctx.
13
+ */
14
+ export function useShortcutManagerContextCount(manager: Ref<Manager> | ComputedRef<Manager>, context: Ref<ContextInfo>): {
15
+ addContext(ctx: string): void
16
+ removeContext(ctx: string): void
17
+ activateContext(ctx: string): void
18
+ deactivateContext(ctx: string): void
19
+ } {
20
+ watch(() => manager.value.shortcuts.entries, newShortcuts => {
21
+ const rc: Record<string, number> = {}
22
+ for (const shortcut of newShortcuts) {
23
+ if (!("ast" in shortcut.condition)) continue
24
+ const c = shortcut.condition.ast
25
+ if (c) {
26
+ const tokens = extractTokens(c as any) // todo
27
+ const seen: string[] = []
28
+ for (const token of tokens) {
29
+ if (token.type === "VALUE") {
30
+ if (seen.includes(token.value)) continue
31
+ seen.push(token.value)
32
+ rc[token.value] = rc[token.value] ? rc[token.value] + 1 : 1
33
+ }
34
+ }
35
+ }
36
+ }
37
+ for (const ctx of keys(context.value)) {
38
+ context.value.count[ctx] = rc[ctx] ?? 0
39
+ }
40
+ for (const ctx of keys(rc)) {
41
+ if (!context.value.isActive[ctx]) {
42
+ context.value.isActive[ctx] = false
43
+ context.value.count[ctx] = rc[ctx]
44
+ }
45
+ }
46
+ }, { deep: true, immediate: true })
47
+ // we're using unreachable, because the checks should already be in the ui
48
+
49
+ function addContext(ctx: string): void {
50
+ if (!context.value.isActive[ctx]) {
51
+ context.value.isActive[ctx] = true
52
+ context.value.count[ctx] = 0
53
+ } else {
54
+ unreachable()
55
+ }
56
+ }
57
+
58
+ function removeContext(ctx: string): void {
59
+ if (context.value.count[ctx] === 0) {
60
+ delete context.value.isActive[ctx]
61
+ delete context.value.count[ctx]
62
+ } else {
63
+ unreachable()
64
+ }
65
+ }
66
+
67
+ function activateContext(ctx: string): void {
68
+ context.value.isActive[ctx] ||= true
69
+ }
70
+
71
+ function deactivateContext(ctx: string): void {
72
+ context.value.isActive[ctx] &&= false
73
+ }
74
+
75
+ return {
76
+ addContext,
77
+ removeContext,
78
+ activateContext,
79
+ deactivateContext
80
+ }
81
+ }
@@ -0,0 +1,42 @@
1
+ import { useGlobalResizeObserver } from "@witchcraft/ui/composables/useGlobalResizeObserver"
2
+ import { computed, reactive, type Ref, ref, watch } from "vue"
3
+
4
+ import type { Keys } from "../../types/keys.js"
5
+
6
+ /**
7
+ * Watches Keys.layout.x/y and listens to resize changes on the element containing the keys to update what the pixel height of the element should be and what the pixel keyWidth.
8
+ *
9
+ * While it also returns the width and the ratio, you should not set the element to them.
10
+ *
11
+ */
12
+ export const useShortcutManagerKeysLayout = (keys: Keys, keyboardEl: Ref<HTMLElement | null>): {
13
+ width: Ref<number>
14
+ height: Ref<number>
15
+ ratio: Ref<number>
16
+ keyWidth: Ref<number>
17
+ layout: {
18
+ x: number
19
+ y: number
20
+ }
21
+ } => {
22
+ const layout = reactive({ x: keys.layout.x, y: keys.layout.y })
23
+ watch([() => keys.layout.x, () => keys.layout.y], ([x, y]) => {
24
+ layout.x = x
25
+ layout.y = y
26
+ })
27
+
28
+ const width = ref(0)
29
+ const keyWidth = computed(() => {
30
+ const val = width.value / layout.x
31
+ return Number.isNaN(val) ? 1 : val
32
+ })
33
+ const ratio = computed(() => layout.x / layout.y)
34
+ const height = computed(() => width.value / ratio.value)
35
+ useGlobalResizeObserver(keyboardEl, function updateSize() {
36
+ if (keyboardEl.value) {
37
+ width.value = Math.max(keyboardEl.value.offsetWidth, 1000)
38
+ }
39
+ })
40
+ return { width, height, ratio, keyWidth, layout }
41
+ }
42
+