@composy/keyboard-core 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/README.md +156 -37
  2. package/dist/index.js +1540 -1395
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +2981 -1
  5. package/dist/index.min.js.map +1 -0
  6. package/es/.dts-output-manifest.json +1 -0
  7. package/es/.dts.tsbuildinfo +1 -0
  8. package/es/icons.d.ts +0 -1
  9. package/es/icons.js +1 -1
  10. package/es/icons.js.map +1 -1
  11. package/es/index.d.ts +3 -4
  12. package/es/index.js +15 -15
  13. package/es/layouts/amount.d.ts +0 -1
  14. package/es/layouts/amount.js +1 -1
  15. package/es/layouts/amount.js.map +1 -1
  16. package/es/layouts/bankcard.d.ts +0 -1
  17. package/es/layouts/bankcard.js +1 -1
  18. package/es/layouts/bankcard.js.map +1 -1
  19. package/es/layouts/email.d.ts +0 -1
  20. package/es/layouts/email.js +1 -1
  21. package/es/layouts/email.js.map +1 -1
  22. package/es/layouts/idcard.d.ts +0 -1
  23. package/es/layouts/idcard.js +1 -1
  24. package/es/layouts/idcard.js.map +1 -1
  25. package/es/layouts/index.d.ts +11 -12
  26. package/es/layouts/index.js +23 -23
  27. package/es/layouts/index.js.map +1 -1
  28. package/es/layouts/license-plate.d.ts +0 -1
  29. package/es/layouts/license-plate.js +1 -1
  30. package/es/layouts/license-plate.js.map +1 -1
  31. package/es/layouts/number.d.ts +0 -1
  32. package/es/layouts/number.js +1 -1
  33. package/es/layouts/number.js.map +1 -1
  34. package/es/layouts/phone.d.ts +0 -1
  35. package/es/layouts/phone.js +1 -1
  36. package/es/layouts/phone.js.map +1 -1
  37. package/es/layouts/punct.d.ts +0 -1
  38. package/es/layouts/punct.js +1 -1
  39. package/es/layouts/punct.js.map +1 -1
  40. package/es/layouts/qwerty.d.ts +0 -1
  41. package/es/layouts/qwerty.js +1 -1
  42. package/es/layouts/qwerty.js.map +1 -1
  43. package/es/layouts/search.d.ts +0 -1
  44. package/es/layouts/search.js +1 -1
  45. package/es/layouts/search.js.map +1 -1
  46. package/es/layouts/symbol.d.ts +0 -1
  47. package/es/layouts/symbol.js +1 -1
  48. package/es/layouts/symbol.js.map +1 -1
  49. package/es/layouts/url.d.ts +0 -1
  50. package/es/layouts/url.js +1 -1
  51. package/es/layouts/url.js.map +1 -1
  52. package/es/layouts/verifycode.d.ts +0 -1
  53. package/es/layouts/verifycode.js +1 -1
  54. package/es/layouts/verifycode.js.map +1 -1
  55. package/es/managers/index.d.ts +1 -2
  56. package/es/managers/index.js +1 -1
  57. package/es/managers/keyboard-manager.d.ts +2 -1
  58. package/es/managers/keyboard-manager.js +79 -22
  59. package/es/managers/keyboard-manager.js.map +1 -1
  60. package/es/managers/keyboard-renderer.d.ts +3 -2
  61. package/es/managers/keyboard-renderer.js +81 -39
  62. package/es/managers/keyboard-renderer.js.map +1 -1
  63. package/es/managers/position-manager.d.ts +4 -3
  64. package/es/managers/position-manager.js +42 -21
  65. package/es/managers/position-manager.js.map +1 -1
  66. package/es/themes/index.d.ts +1 -2
  67. package/es/themes/index.js +2 -1
  68. package/es/themes/index.js.map +1 -1
  69. package/es/themes/presets.d.ts +0 -1
  70. package/es/themes/presets.js +1 -1
  71. package/es/themes/presets.js.map +1 -1
  72. package/es/themes/types.d.ts +1 -1
  73. package/es/themes/types.js +1 -1
  74. package/es/types/index.d.ts +0 -1
  75. package/es/types/index.js +1 -1
  76. package/es/types/keyboard.d.ts +0 -1
  77. package/es/types/keyboard.js +1 -1
  78. package/es/types/position.d.ts +0 -1
  79. package/es/types/position.js +1 -1
  80. package/es/utils/device.d.ts +0 -1
  81. package/es/utils/device.js +11 -7
  82. package/es/utils/device.js.map +1 -1
  83. package/es/utils/dom.d.ts +4 -1
  84. package/es/utils/dom.js +25 -7
  85. package/es/utils/dom.js.map +1 -1
  86. package/es/utils/event-emitter.d.ts +0 -1
  87. package/es/utils/event-emitter.js +2 -1
  88. package/es/utils/event-emitter.js.map +1 -1
  89. package/es/utils/formatters.d.ts +0 -1
  90. package/es/utils/formatters.js +4 -4
  91. package/es/utils/formatters.js.map +1 -1
  92. package/es/utils/index.d.ts +2 -3
  93. package/es/utils/index.js +5 -5
  94. package/es/utils/random.d.ts +4 -1
  95. package/es/utils/random.js +2 -2
  96. package/es/utils/random.js.map +1 -1
  97. package/esm/icons.js +1 -1
  98. package/esm/icons.js.map +1 -1
  99. package/esm/index.js +15 -15
  100. package/esm/layouts/amount.js +1 -1
  101. package/esm/layouts/amount.js.map +1 -1
  102. package/esm/layouts/bankcard.js +1 -1
  103. package/esm/layouts/bankcard.js.map +1 -1
  104. package/esm/layouts/email.js +1 -1
  105. package/esm/layouts/email.js.map +1 -1
  106. package/esm/layouts/idcard.js +1 -1
  107. package/esm/layouts/idcard.js.map +1 -1
  108. package/esm/layouts/index.js +23 -23
  109. package/esm/layouts/index.js.map +1 -1
  110. package/esm/layouts/license-plate.js +1 -1
  111. package/esm/layouts/license-plate.js.map +1 -1
  112. package/esm/layouts/number.js +1 -1
  113. package/esm/layouts/number.js.map +1 -1
  114. package/esm/layouts/phone.js +1 -1
  115. package/esm/layouts/phone.js.map +1 -1
  116. package/esm/layouts/punct.js +1 -1
  117. package/esm/layouts/punct.js.map +1 -1
  118. package/esm/layouts/qwerty.js +1 -1
  119. package/esm/layouts/qwerty.js.map +1 -1
  120. package/esm/layouts/search.js +1 -1
  121. package/esm/layouts/search.js.map +1 -1
  122. package/esm/layouts/symbol.js +1 -1
  123. package/esm/layouts/symbol.js.map +1 -1
  124. package/esm/layouts/url.js +1 -1
  125. package/esm/layouts/url.js.map +1 -1
  126. package/esm/layouts/verifycode.js +1 -1
  127. package/esm/layouts/verifycode.js.map +1 -1
  128. package/esm/managers/index.js +1 -1
  129. package/esm/managers/keyboard-manager.js +79 -22
  130. package/esm/managers/keyboard-manager.js.map +1 -1
  131. package/esm/managers/keyboard-renderer.js +81 -39
  132. package/esm/managers/keyboard-renderer.js.map +1 -1
  133. package/esm/managers/position-manager.js +42 -21
  134. package/esm/managers/position-manager.js.map +1 -1
  135. package/esm/themes/index.js +2 -1
  136. package/esm/themes/index.js.map +1 -1
  137. package/esm/themes/presets.js +1 -1
  138. package/esm/themes/presets.js.map +1 -1
  139. package/esm/utils/device.js +11 -7
  140. package/esm/utils/device.js.map +1 -1
  141. package/esm/utils/dom.js +25 -7
  142. package/esm/utils/dom.js.map +1 -1
  143. package/esm/utils/event-emitter.js +2 -1
  144. package/esm/utils/event-emitter.js.map +1 -1
  145. package/esm/utils/formatters.js +4 -4
  146. package/esm/utils/formatters.js.map +1 -1
  147. package/esm/utils/random.js +2 -2
  148. package/esm/utils/random.js.map +1 -1
  149. package/lib/icons.cjs +1 -1
  150. package/lib/icons.cjs.map +1 -1
  151. package/{esm/icons.d.ts → lib/icons.d.cts} +0 -1
  152. package/lib/index.cjs +14 -13
  153. package/{esm/index.d.ts → lib/index.d.cts} +3 -4
  154. package/lib/layouts/amount.cjs +1 -1
  155. package/lib/layouts/amount.cjs.map +1 -1
  156. package/{esm/layouts/amount.d.ts → lib/layouts/amount.d.cts} +0 -1
  157. package/lib/layouts/bankcard.cjs +1 -1
  158. package/lib/layouts/bankcard.cjs.map +1 -1
  159. package/{esm/layouts/bankcard.d.ts → lib/layouts/bankcard.d.cts} +0 -1
  160. package/lib/layouts/email.cjs +1 -1
  161. package/lib/layouts/email.cjs.map +1 -1
  162. package/lib/layouts/{email.d.ts → email.d.cts} +0 -1
  163. package/lib/layouts/idcard.cjs +1 -1
  164. package/lib/layouts/idcard.cjs.map +1 -1
  165. package/{esm/layouts/idcard.d.ts → lib/layouts/idcard.d.cts} +0 -1
  166. package/lib/layouts/index.cjs +23 -23
  167. package/lib/layouts/index.cjs.map +1 -1
  168. package/{esm/layouts/index.d.ts → lib/layouts/index.d.cts} +11 -12
  169. package/lib/layouts/license-plate.cjs +1 -1
  170. package/lib/layouts/license-plate.cjs.map +1 -1
  171. package/{esm/layouts/license-plate.d.ts → lib/layouts/license-plate.d.cts} +0 -1
  172. package/lib/layouts/number.cjs +1 -1
  173. package/lib/layouts/number.cjs.map +1 -1
  174. package/{esm/layouts/number.d.ts → lib/layouts/number.d.cts} +0 -1
  175. package/lib/layouts/phone.cjs +1 -1
  176. package/lib/layouts/phone.cjs.map +1 -1
  177. package/lib/layouts/{phone.d.ts → phone.d.cts} +0 -1
  178. package/lib/layouts/punct.cjs +1 -1
  179. package/lib/layouts/punct.cjs.map +1 -1
  180. package/lib/layouts/{punct.d.ts → punct.d.cts} +0 -1
  181. package/lib/layouts/qwerty.cjs +1 -1
  182. package/lib/layouts/qwerty.cjs.map +1 -1
  183. package/{esm/layouts/qwerty.d.ts → lib/layouts/qwerty.d.cts} +0 -1
  184. package/lib/layouts/search.cjs +1 -1
  185. package/lib/layouts/search.cjs.map +1 -1
  186. package/{esm/layouts/search.d.ts → lib/layouts/search.d.cts} +0 -1
  187. package/lib/layouts/symbol.cjs +1 -1
  188. package/lib/layouts/symbol.cjs.map +1 -1
  189. package/{esm/layouts/symbol.d.ts → lib/layouts/symbol.d.cts} +0 -1
  190. package/lib/layouts/url.cjs +1 -1
  191. package/lib/layouts/url.cjs.map +1 -1
  192. package/{esm/layouts/url.d.ts → lib/layouts/url.d.cts} +0 -1
  193. package/lib/layouts/verifycode.cjs +1 -1
  194. package/lib/layouts/verifycode.cjs.map +1 -1
  195. package/lib/layouts/{verifycode.d.ts → verifycode.d.cts} +0 -1
  196. package/lib/managers/index.cjs +1 -1
  197. package/lib/managers/{index.d.ts → index.d.cts} +1 -2
  198. package/lib/managers/keyboard-manager.cjs +79 -22
  199. package/lib/managers/keyboard-manager.cjs.map +1 -1
  200. package/lib/managers/{keyboard-manager.d.ts → keyboard-manager.d.cts} +2 -1
  201. package/lib/managers/keyboard-renderer.cjs +80 -38
  202. package/lib/managers/keyboard-renderer.cjs.map +1 -1
  203. package/lib/managers/{keyboard-renderer.d.ts → keyboard-renderer.d.cts} +3 -2
  204. package/lib/managers/position-manager.cjs +42 -21
  205. package/lib/managers/position-manager.cjs.map +1 -1
  206. package/lib/managers/{position-manager.d.ts → position-manager.d.cts} +4 -3
  207. package/lib/themes/index.cjs +2 -1
  208. package/lib/themes/index.cjs.map +1 -1
  209. package/lib/themes/{index.d.ts → index.d.cts} +1 -2
  210. package/lib/themes/presets.cjs +1 -1
  211. package/lib/themes/presets.cjs.map +1 -1
  212. package/lib/themes/{presets.d.ts → presets.d.cts} +0 -1
  213. package/lib/themes/types.cjs +1 -1
  214. package/{esm/themes/types.d.ts → lib/themes/types.d.cts} +1 -1
  215. package/lib/types/index.cjs +1 -1
  216. package/{esm/types/index.d.ts → lib/types/index.d.cts} +0 -1
  217. package/lib/types/keyboard.cjs +1 -1
  218. package/{esm/types/keyboard.d.ts → lib/types/keyboard.d.cts} +0 -1
  219. package/lib/types/position.cjs +1 -1
  220. package/lib/types/{position.d.ts → position.d.cts} +0 -1
  221. package/lib/utils/device.cjs +11 -7
  222. package/lib/utils/device.cjs.map +1 -1
  223. package/{esm/utils/device.d.ts → lib/utils/device.d.cts} +0 -1
  224. package/lib/utils/dom.cjs +25 -6
  225. package/lib/utils/dom.cjs.map +1 -1
  226. package/{esm/utils/dom.d.ts → lib/utils/dom.d.cts} +4 -1
  227. package/lib/utils/event-emitter.cjs +2 -1
  228. package/lib/utils/event-emitter.cjs.map +1 -1
  229. package/{esm/utils/event-emitter.d.ts → lib/utils/event-emitter.d.cts} +0 -1
  230. package/lib/utils/formatters.cjs +4 -4
  231. package/lib/utils/formatters.cjs.map +1 -1
  232. package/{esm/utils/formatters.d.ts → lib/utils/formatters.d.cts} +0 -1
  233. package/lib/utils/index.cjs +4 -3
  234. package/{esm/utils/index.d.ts → lib/utils/index.d.cts} +2 -3
  235. package/lib/utils/random.cjs +2 -2
  236. package/lib/utils/random.cjs.map +1 -1
  237. package/{esm/utils/random.d.ts → lib/utils/random.d.cts} +4 -1
  238. package/package.json +28 -14
  239. package/es/icons.d.ts.map +0 -1
  240. package/es/index.d.ts.map +0 -1
  241. package/es/layouts/amount.d.ts.map +0 -1
  242. package/es/layouts/bankcard.d.ts.map +0 -1
  243. package/es/layouts/email.d.ts.map +0 -1
  244. package/es/layouts/idcard.d.ts.map +0 -1
  245. package/es/layouts/index.d.ts.map +0 -1
  246. package/es/layouts/license-plate.d.ts.map +0 -1
  247. package/es/layouts/number.d.ts.map +0 -1
  248. package/es/layouts/phone.d.ts.map +0 -1
  249. package/es/layouts/punct.d.ts.map +0 -1
  250. package/es/layouts/qwerty.d.ts.map +0 -1
  251. package/es/layouts/search.d.ts.map +0 -1
  252. package/es/layouts/symbol.d.ts.map +0 -1
  253. package/es/layouts/url.d.ts.map +0 -1
  254. package/es/layouts/verifycode.d.ts.map +0 -1
  255. package/es/managers/index.d.ts.map +0 -1
  256. package/es/managers/keyboard-manager.d.ts.map +0 -1
  257. package/es/managers/keyboard-renderer.d.ts.map +0 -1
  258. package/es/managers/position-manager.d.ts.map +0 -1
  259. package/es/themes/index.d.ts.map +0 -1
  260. package/es/themes/presets.d.ts.map +0 -1
  261. package/es/themes/types.d.ts.map +0 -1
  262. package/es/types/index.d.ts.map +0 -1
  263. package/es/types/keyboard.d.ts.map +0 -1
  264. package/es/types/position.d.ts.map +0 -1
  265. package/es/utils/device.d.ts.map +0 -1
  266. package/es/utils/dom.d.ts.map +0 -1
  267. package/es/utils/event-emitter.d.ts.map +0 -1
  268. package/es/utils/formatters.d.ts.map +0 -1
  269. package/es/utils/index.d.ts.map +0 -1
  270. package/es/utils/random.d.ts.map +0 -1
  271. package/esm/icons.d.ts.map +0 -1
  272. package/esm/index.d.ts.map +0 -1
  273. package/esm/layouts/amount.d.ts.map +0 -1
  274. package/esm/layouts/bankcard.d.ts.map +0 -1
  275. package/esm/layouts/email.d.ts +0 -11
  276. package/esm/layouts/email.d.ts.map +0 -1
  277. package/esm/layouts/idcard.d.ts.map +0 -1
  278. package/esm/layouts/index.d.ts.map +0 -1
  279. package/esm/layouts/license-plate.d.ts.map +0 -1
  280. package/esm/layouts/number.d.ts.map +0 -1
  281. package/esm/layouts/phone.d.ts +0 -15
  282. package/esm/layouts/phone.d.ts.map +0 -1
  283. package/esm/layouts/punct.d.ts +0 -7
  284. package/esm/layouts/punct.d.ts.map +0 -1
  285. package/esm/layouts/qwerty.d.ts.map +0 -1
  286. package/esm/layouts/search.d.ts.map +0 -1
  287. package/esm/layouts/symbol.d.ts.map +0 -1
  288. package/esm/layouts/url.d.ts.map +0 -1
  289. package/esm/layouts/verifycode.d.ts +0 -15
  290. package/esm/layouts/verifycode.d.ts.map +0 -1
  291. package/esm/managers/index.d.ts +0 -8
  292. package/esm/managers/index.d.ts.map +0 -1
  293. package/esm/managers/keyboard-manager.d.ts +0 -130
  294. package/esm/managers/keyboard-manager.d.ts.map +0 -1
  295. package/esm/managers/keyboard-renderer.d.ts +0 -115
  296. package/esm/managers/keyboard-renderer.d.ts.map +0 -1
  297. package/esm/managers/position-manager.d.ts +0 -72
  298. package/esm/managers/position-manager.d.ts.map +0 -1
  299. package/esm/themes/index.d.ts +0 -70
  300. package/esm/themes/index.d.ts.map +0 -1
  301. package/esm/themes/presets.d.ts +0 -39
  302. package/esm/themes/presets.d.ts.map +0 -1
  303. package/esm/themes/types.d.ts.map +0 -1
  304. package/esm/themes/types.js +0 -10
  305. package/esm/types/index.d.ts.map +0 -1
  306. package/esm/types/index.js +0 -10
  307. package/esm/types/keyboard.d.ts.map +0 -1
  308. package/esm/types/keyboard.js +0 -10
  309. package/esm/types/position.d.ts +0 -139
  310. package/esm/types/position.d.ts.map +0 -1
  311. package/esm/types/position.js +0 -10
  312. package/esm/utils/device.d.ts.map +0 -1
  313. package/esm/utils/dom.d.ts.map +0 -1
  314. package/esm/utils/event-emitter.d.ts.map +0 -1
  315. package/esm/utils/formatters.d.ts.map +0 -1
  316. package/esm/utils/index.d.ts.map +0 -1
  317. package/esm/utils/index.js +0 -16
  318. package/esm/utils/random.d.ts.map +0 -1
  319. package/lib/icons.d.ts +0 -58
  320. package/lib/index.d.ts +0 -12
  321. package/lib/layouts/amount.d.ts +0 -14
  322. package/lib/layouts/bankcard.d.ts +0 -15
  323. package/lib/layouts/idcard.d.ts +0 -16
  324. package/lib/layouts/index.d.ts +0 -54
  325. package/lib/layouts/license-plate.d.ts +0 -35
  326. package/lib/layouts/number.d.ts +0 -14
  327. package/lib/layouts/qwerty.d.ts +0 -10
  328. package/lib/layouts/search.d.ts +0 -7
  329. package/lib/layouts/symbol.d.ts +0 -14
  330. package/lib/layouts/url.d.ts +0 -7
  331. package/lib/themes/types.d.ts +0 -118
  332. package/lib/types/index.d.ts +0 -7
  333. package/lib/types/keyboard.d.ts +0 -253
  334. package/lib/utils/device.d.ts +0 -45
  335. package/lib/utils/dom.d.ts +0 -69
  336. package/lib/utils/event-emitter.d.ts +0 -52
  337. package/lib/utils/formatters.d.ts +0 -51
  338. package/lib/utils/index.d.ts +0 -10
  339. package/lib/utils/random.d.ts +0 -71
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["deletedChar","newValue"],"sources":["../src/layouts/qwerty.ts","../src/icons.ts","../src/layouts/number.ts","../src/layouts/symbol.ts","../src/layouts/license-plate.ts","../src/layouts/idcard.ts","../src/layouts/phone.ts","../src/layouts/amount.ts","../src/layouts/bankcard.ts","../src/layouts/verifycode.ts","../src/layouts/email.ts","../src/layouts/url.ts","../src/layouts/search.ts","../src/layouts/punct.ts","../src/layouts/index.ts","../src/utils/event-emitter.ts","../src/utils/device.ts","../src/utils/dom.ts","../src/managers/keyboard-manager.ts","../src/managers/position-manager.ts","../src/themes/presets.ts","../src/themes/index.ts","../src/managers/keyboard-renderer.ts","../src/utils/random.ts","../src/utils/formatters.ts"],"sourcesContent":["/**\n * QWERTY 标准字母键盘布局\n * @module layouts/qwerty\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n\n/**\n * 创建字符按键\n */\nfunction createCharKey(char: string): KeyDefinition {\n return {\n id: `char-${char.toLowerCase()}`,\n type: 'char',\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() },\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() },\n }\n}\n\n/**\n * QWERTY 键盘配置\n */\nexport const qwertyLayout: KeyboardConfig = {\n type: 'qwerty',\n name: '字母键盘',\n supportShift: true,\n defaultUpperCase: false,\n switchable: ['number', 'symbol'],\n rows: [\n {\n keys: [\n createCharKey('Q'),\n createCharKey('W'),\n createCharKey('E'),\n createCharKey('R'),\n createCharKey('T'),\n createCharKey('Y'),\n createCharKey('U'),\n createCharKey('I'),\n createCharKey('O'),\n createCharKey('P'),\n ],\n },\n {\n keys: [\n createCharKey('A'),\n createCharKey('S'),\n createCharKey('D'),\n createCharKey('F'),\n createCharKey('G'),\n createCharKey('H'),\n createCharKey('J'),\n createCharKey('K'),\n createCharKey('L'),\n ],\n },\n {\n keys: [\n {\n id: 'shift',\n type: 'shift',\n label: '⇧',\n width: 1.5,\n className: 'key-shift',\n },\n createCharKey('Z'),\n createCharKey('X'),\n createCharKey('C'),\n createCharKey('V'),\n createCharKey('B'),\n createCharKey('N'),\n createCharKey('M'),\n {\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n width: 1.5,\n className: 'key-backspace',\n },\n ],\n },\n {\n keys: [\n {\n id: 'switch-number',\n type: 'tab',\n label: '123',\n width: 1.5,\n className: 'key-switch',\n data: { targetType: 'number' },\n },\n {\n id: 'switch-symbol',\n type: 'tab',\n label: '#+=',\n width: 1.25,\n className: 'key-switch',\n data: { targetType: 'symbol' },\n },\n {\n id: 'space',\n type: 'space',\n label: '空格',\n value: ' ',\n width: 4,\n className: 'key-space',\n },\n {\n id: 'done',\n type: 'done',\n label: '完成',\n width: 2,\n className: 'key-done',\n },\n ],\n },\n ],\n}\n","/**\n * 键盘图标 SVG\n * 使用 Lucide 图标的 SVG 路径\n * @module icons\n */\n\n/**\n * 删除图标 (Delete/Backspace)\n */\nexport const ICON_DELETE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z\"/><path d=\"m12 9 6 6\"/><path d=\"m18 9-6 6\"/></svg>`\n\n/**\n * 清空图标 (X Circle)\n */\nexport const ICON_CLEAR = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9-6 6\"/><path d=\"m9 9 6 6\"/></svg>`\n\n/**\n * 关闭图标 (X)\n */\nexport const ICON_CLOSE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`\n\n/**\n * 确认图标 (Check)\n */\nexport const ICON_CHECK = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>`\n\n/**\n * 换行图标 (Corner Down Left)\n */\nexport const ICON_ENTER = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 10 4 15 9 20\"/><path d=\"M20 4v7a4 4 0 0 1-4 4H4\"/></svg>`\n\n/**\n * Shift 图标 (Arrow Big Up)\n */\nexport const ICON_SHIFT = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 18v-6H5l7-7 7 7h-4v6H9z\"/></svg>`\n\n/**\n * 空格图标 (Space)\n */\nexport const ICON_SPACE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1\"/></svg>`\n\n/**\n * 键盘图标 (Keyboard)\n */\nexport const ICON_KEYBOARD = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"/><path d=\"M6 8h.001\"/><path d=\"M10 8h.001\"/><path d=\"M14 8h.001\"/><path d=\"M18 8h.001\"/><path d=\"M8 12h.001\"/><path d=\"M12 12h.001\"/><path d=\"M16 12h.001\"/><path d=\"M7 16h10\"/></svg>`\n\n/**\n * 语音图标 (Mic)\n */\nexport const ICON_VOICE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/><path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>`\n\n/**\n * 所有图标映射\n */\nexport const ICONS = {\n delete: ICON_DELETE,\n clear: ICON_CLEAR,\n close: ICON_CLOSE,\n check: ICON_CHECK,\n enter: ICON_ENTER,\n shift: ICON_SHIFT,\n space: ICON_SPACE,\n keyboard: ICON_KEYBOARD,\n voice: ICON_VOICE,\n} as const\n\n/** IconName - 图标名称类型 */\nexport type IconName = keyof typeof ICONS\n","/**\n * 数字键盘布局\n * @module layouts/number\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `num-${num}`,\n type: 'char',\n label: num,\n value: num,\n className: 'key-num',\n }\n}\n\n/**\n * 数字键盘配置 - 紧凑4x4布局\n */\nexport const numberLayout: KeyboardConfig = {\n type: 'number',\n name: '数字键盘',\n supportShift: false,\n switchable: ['qwerty', 'symbol'],\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'close',\n type: 'close',\n label: '关闭',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'decimal',\n type: 'char',\n label: '.',\n value: '.',\n className: 'key-num',\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n}\n\n/**\n * 纯整数键盘 - 紧凑4x4布局\n */\nexport const integerLayout: KeyboardConfig = {\n type: 'integer',\n name: '整数键盘',\n supportShift: false,\n switchable: ['qwerty'],\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'close',\n type: 'close',\n label: '关闭',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'switch-qwerty',\n type: 'tab',\n label: 'ABC',\n className: 'key-numpad-fn',\n data: { targetType: 'qwerty' },\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n}\n","/**\n * 符号键盘布局\n * @module layouts/symbol\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n\n/**\n * 创建符号按键\n */\nfunction createSymbolKey(symbol: string, id?: string): KeyDefinition {\n return {\n id: id || `symbol-${symbol.charCodeAt(0)}`,\n type: 'char',\n label: symbol,\n value: symbol,\n }\n}\n\n/**\n * 符号键盘配置\n */\nexport const symbolLayout: KeyboardConfig = {\n type: 'symbol',\n name: '符号键盘',\n supportShift: false,\n switchable: ['qwerty', 'number'],\n rows: [\n {\n keys: [\n createSymbolKey('1'),\n createSymbolKey('2'),\n createSymbolKey('3'),\n createSymbolKey('4'),\n createSymbolKey('5'),\n createSymbolKey('6'),\n createSymbolKey('7'),\n createSymbolKey('8'),\n createSymbolKey('9'),\n createSymbolKey('0'),\n ],\n },\n {\n keys: [\n createSymbolKey('-'),\n createSymbolKey('/'),\n createSymbolKey(':'),\n createSymbolKey(';'),\n createSymbolKey('('),\n createSymbolKey(')'),\n createSymbolKey('¥', 'yen'),\n createSymbolKey('@'),\n createSymbolKey('\"', 'quote'),\n ],\n },\n {\n keys: [\n {\n id: 'switch-symbol-2',\n type: 'tab',\n label: '#+= ',\n width: 1.5,\n className: 'key-switch',\n data: { targetType: 'symbol-2' },\n },\n createSymbolKey('.'),\n createSymbolKey(','),\n createSymbolKey('?'),\n createSymbolKey('!'),\n createSymbolKey('\\'', 'apostrophe'),\n {\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n width: 1.5,\n className: 'key-backspace',\n },\n ],\n },\n {\n keys: [\n {\n id: 'switch-qwerty',\n type: 'tab',\n label: 'ABC',\n width: 1.5,\n className: 'key-switch',\n data: { targetType: 'qwerty' },\n },\n {\n id: 'switch-number',\n type: 'tab',\n label: '123',\n width: 1.25,\n className: 'key-switch',\n data: { targetType: 'number' },\n },\n {\n id: 'space',\n type: 'space',\n label: '空格',\n value: ' ',\n width: 4,\n className: 'key-space',\n },\n {\n id: 'done',\n type: 'done',\n label: '完成',\n width: 2,\n className: 'key-done',\n },\n ],\n },\n ],\n}\n\n/**\n * 符号键盘第二页\n */\nexport const symbolLayout2: KeyboardConfig = {\n type: 'symbol',\n name: '符号键盘2',\n supportShift: false,\n switchable: ['qwerty', 'number'],\n rows: [\n {\n keys: [\n createSymbolKey('['),\n createSymbolKey(']'),\n createSymbolKey('{'),\n createSymbolKey('}'),\n createSymbolKey('#'),\n createSymbolKey('%'),\n createSymbolKey('^'),\n createSymbolKey('*'),\n createSymbolKey('+'),\n createSymbolKey('='),\n ],\n },\n {\n keys: [\n createSymbolKey('_'),\n createSymbolKey('\\\\'),\n createSymbolKey('|'),\n createSymbolKey('~'),\n createSymbolKey('<'),\n createSymbolKey('>'),\n createSymbolKey('€', 'euro'),\n createSymbolKey('$'),\n createSymbolKey('&'),\n ],\n },\n {\n keys: [\n {\n id: 'switch-symbol-1',\n type: 'tab',\n label: '123',\n width: 1.5,\n className: 'key-switch',\n data: { targetType: 'symbol' },\n },\n createSymbolKey('`', 'backtick'),\n createSymbolKey('·', 'middle-dot'),\n createSymbolKey('…', 'ellipsis'),\n createSymbolKey('°', 'degree'),\n createSymbolKey('•', 'bullet'),\n {\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n width: 1.5,\n className: 'key-backspace',\n },\n ],\n },\n {\n keys: [\n {\n id: 'switch-qwerty',\n type: 'tab',\n label: 'ABC',\n width: 1.5,\n className: 'key-switch',\n data: { targetType: 'qwerty' },\n },\n {\n id: 'switch-number',\n type: 'tab',\n label: '123',\n width: 1.25,\n className: 'key-switch',\n data: { targetType: 'number' },\n },\n {\n id: 'space',\n type: 'space',\n label: '空格',\n value: ' ',\n width: 4,\n className: 'key-space',\n },\n {\n id: 'done',\n type: 'done',\n label: '完成',\n width: 2,\n className: 'key-done',\n },\n ],\n },\n ],\n}\n","/**\n * 车牌号键盘布局\n * @module layouts/license-plate\n * 省份键盘类似26键布局,点击省份后自动切换到字母数字键盘\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport { ICON_DELETE } from '../icons'\n\n/**\n * 省份简称列表(按地理区域排列,10列布局)\n */\nexport const PROVINCES = [\n '京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘',\n '皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘', '晋',\n '蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁',\n '琼', '港', '澳',\n]\n\n/**\n * 车牌字母(排除 I 和 O,避免与数字混淆)\n */\nexport const PLATE_LETTERS = [\n 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',\n 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',\n 'W', 'X', 'Y', 'Z',\n]\n\n/**\n * 创建省份按键(点击后自动切换到字母数字键盘)\n */\nfunction createProvinceKey(province: string): KeyDefinition {\n return {\n id: `province-${province}`,\n type: 'char',\n label: province,\n value: province,\n className: 'key-plate-province',\n data: { switchAfterInput: 'license-plate-alphanumeric' },\n }\n}\n\n/**\n * 创建字母按键\n */\nfunction createLetterKey(letter: string): KeyDefinition {\n return {\n id: `letter-${letter}`,\n type: 'char',\n label: letter,\n value: letter,\n className: 'key-plate-letter',\n }\n}\n\n/**\n * 创建数字按键\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `num-${num}`,\n type: 'char',\n label: num,\n value: num,\n className: 'key-plate-number',\n }\n}\n\n/**\n * 省份键盘配置 - 类似26键布局\n * 10列布局,更紧凑美观\n */\nexport const licensePlateProvinceLayout: KeyboardConfig = {\n type: 'license-plate-province',\n name: '省份简称',\n supportShift: false,\n rows: [\n {\n className: 'plate-keyboard-row',\n keys: PROVINCES.slice(0, 10).map(createProvinceKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: PROVINCES.slice(10, 20).map(createProvinceKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: PROVINCES.slice(20, 30).map(createProvinceKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: [\n ...PROVINCES.slice(30, 33).map(createProvinceKey),\n {\n id: 'plate-xue',\n type: 'char',\n label: '学',\n value: '学',\n className: 'key-plate-special',\n data: { switchAfterInput: 'license-plate-alphanumeric' },\n },\n {\n id: 'plate-jing',\n type: 'char',\n label: '警',\n value: '警',\n className: 'key-plate-special',\n data: { switchAfterInput: 'license-plate-alphanumeric' },\n },\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n width: 1.5,\n className: 'key-plate-fn',\n },\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2.5,\n className: 'key-plate-done',\n },\n ],\n },\n ],\n data: {\n maxLength: 8,\n inputType: 'license-plate',\n },\n}\n\n/**\n * 字母数字键盘配置(车牌第2-8位)\n * 10列布局\n */\nexport const licensePlateAlphanumericLayout: KeyboardConfig = {\n type: 'license-plate-alphanumeric',\n name: '字母数字',\n supportShift: false,\n rows: [\n {\n className: 'plate-keyboard-row',\n keys: '1234567890'.split('').map(createNumberKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: PLATE_LETTERS.slice(0, 10).map(createLetterKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: [\n ...PLATE_LETTERS.slice(10, 19).map(createLetterKey),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-plate-fn',\n },\n ],\n },\n {\n className: 'plate-keyboard-row',\n keys: [\n {\n id: 'switch-province',\n type: 'tab',\n label: '省份',\n width: 1.5,\n className: 'key-plate-switch',\n data: { targetType: 'license-plate-province' },\n },\n ...PLATE_LETTERS.slice(19, 24).map(createLetterKey),\n {\n id: 'plate-xue',\n type: 'char',\n label: '学',\n value: '学',\n className: 'key-plate-special',\n },\n {\n id: 'plate-jing',\n type: 'char',\n label: '警',\n value: '警',\n className: 'key-plate-special',\n },\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 1.5,\n className: 'key-plate-done',\n },\n ],\n },\n ],\n data: {\n maxLength: 8,\n inputType: 'license-plate',\n },\n}\n\n/**\n * 纯字母键盘配置(车牌第2位,只能输入字母)\n * 6列布局,排除 I 和 O\n */\nexport const licensePlateLetterLayout: KeyboardConfig = {\n type: 'license-plate-letter',\n name: '字母',\n supportShift: false,\n rows: [\n {\n className: 'plate-keyboard-row',\n keys: PLATE_LETTERS.slice(0, 8).map(createLetterKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: PLATE_LETTERS.slice(8, 16).map(createLetterKey),\n },\n {\n className: 'plate-keyboard-row',\n keys: [\n ...PLATE_LETTERS.slice(16, 24).map(createLetterKey),\n ],\n },\n {\n className: 'plate-keyboard-row',\n keys: [\n {\n id: 'switch-province',\n type: 'tab',\n label: '省份',\n width: 2,\n className: 'key-plate-switch',\n data: { targetType: 'license-plate-province' },\n },\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n width: 2,\n className: 'key-plate-fn',\n },\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-plate-done',\n },\n ],\n },\n ],\n data: {\n maxLength: 8,\n inputType: 'license-plate',\n },\n}\n\n/**\n * 完整车牌号键盘(自动切换模式)\n * 默认显示省份键盘,点击省份后自动切换到字母数字键盘\n */\nexport const licensePlateLayout: KeyboardConfig = {\n type: 'license-plate',\n name: '车牌号键盘',\n supportShift: false,\n data: {\n autoSwitch: true,\n maxLength: 8,\n inputType: 'license-plate',\n },\n rows: licensePlateProvinceLayout.rows,\n}\n","/**\n * 身份证号键盘布局\n * @module layouts/idcard\n */\n\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 从图标模块中导入删除键图标和清除键图标\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n * @param num - 数字字符串(如 '0'-'9')\n * @returns 返回一个按键定义对象\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `idcard-${num}`, // 按键唯一标识符,格式为 idcard-数字\n type: 'char', // 按键类型为字符键\n label: num, // 按键上显示的文本\n value: num, // 按键按下后输出的值\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\n }\n}\n\n/**\n * 身份证号键盘配置\n * 紧凑3x4布局,无空白位置\n * 布局结构:\n * 第1行: 1 2 3 [退格]\n * 第2行: 4 5 6 [清除]\n * 第3行: 7 8 9 X\n * 第4行: [关闭] 0 [确定(占2格)]\n */\nexport const idcardLayout: KeyboardConfig = {\n type: 'idcard', // 键盘类型标识\n name: '身份证键盘', // 键盘的显示名称\n supportShift: false, // 不支持 Shift 切换(纯数字+X键盘无需切换)\n rows: [ // 键盘的行数组\n // ---- 第1行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [ // 该行包含的按键数组\n createNumberKey('1'), // 数字键 1\n createNumberKey('2'), // 数字键 2\n createNumberKey('3'), // 数字键 3\n {\n id: 'backspace', // 退格键的唯一标识\n type: 'backspace', // 按键类型为退格,删除最后一个字符\n icon: ICON_DELETE, // 使用删除图标作为显示内容\n label: '', // 无文本标签(由图标替代)\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第2行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('4'), // 数字键 4\n createNumberKey('5'), // 数字键 5\n createNumberKey('6'), // 数字键 6\n {\n id: 'clear', // 清除键的唯一标识\n type: 'clear', // 按键类型为清除,清空所有输入\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\n label: '', // 无文本标签\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第3行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('7'), // 数字键 7\n createNumberKey('8'), // 数字键 8\n createNumberKey('9'), // 数字键 9\n {\n id: 'idcard-x', // X 键的唯一标识\n type: 'char', // 按键类型为字符\n label: 'X', // 按钮上显示的文本(身份证尾号可能是X)\n value: 'X', // 按下后输出的值\n className: 'key-num', // 使用数字键的 CSS 类名,保持外观一致\n },\n ],\n },\n // ---- 第4行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n {\n id: 'close', // 关闭键的唯一标识\n type: 'close', // 按键类型为关闭,收起键盘\n label: '关闭', // 按钮上显示的文本\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n createNumberKey('0'), // 数字键 0\n {\n id: 'done', // 确定键的唯一标识\n type: 'done', // 按键类型为确定,完成输入\n label: '确定', // 按钮上显示的文本\n width: 2, // 占据 2 个键的宽度\n className: 'key-numpad-done', // 确定键的 CSS 类名\n },\n ],\n },\n ],\n data: { // 键盘的附加数据\n maxLength: 18, // 身份证号最大输入长度为 18 位\n inputType: 'idcard', // 输入类型标识,用于外部判断\n },\n}\n","/**\n * 手机号键盘布局\n * @module layouts/phone\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `phone-${num}`,\n type: 'char',\n label: num,\n value: num,\n className: 'key-num',\n }\n}\n\n/**\n * 手机号键盘配置\n * 紧凑4x4布局\n */\nexport const phoneLayout: KeyboardConfig = {\n type: 'phone',\n name: '手机号键盘',\n supportShift: false,\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'close',\n type: 'close',\n label: '关闭',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'phone-plus',\n type: 'char',\n label: '+',\n value: '+',\n className: 'key-num',\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n data: {\n maxLength: 11,\n inputType: 'phone',\n },\n}\n\n/**\n * 简洁版拨号键盘(带 * #)\n */\nexport const phoneSimpleLayout: KeyboardConfig = {\n type: 'phone-simple',\n name: '拨号键盘',\n supportShift: false,\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'phone-hash',\n type: 'char',\n label: '#',\n value: '#',\n className: 'key-num',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'phone-star',\n type: 'char',\n label: '*',\n value: '*',\n className: 'key-num',\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '拨打',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n data: {\n maxLength: 13,\n inputType: 'phone',\n },\n}\n","/**\n * 金额键盘布局\n * @module layouts/amount\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `amount-${num}`,\n type: 'char',\n label: num,\n value: num,\n className: 'key-num',\n }\n}\n\n/**\n * 金额键盘配置 - 紧凑4x4布局\n */\nexport const amountLayout: KeyboardConfig = {\n type: 'amount',\n name: '金额键盘',\n supportShift: false,\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'double-zero',\n type: 'char',\n label: '00',\n value: '00',\n className: 'key-num',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'decimal',\n type: 'char',\n label: '.',\n value: '.',\n className: 'key-num',\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n data: {\n inputType: 'amount',\n decimalPlaces: 2,\n },\n}\n\n/**\n * 简洁金额键盘 - 紧凑4x4布局\n */\nexport const amountSimpleLayout: KeyboardConfig = {\n type: 'amount-simple',\n name: '金额键盘',\n supportShift: false,\n rows: [\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('1'),\n createNumberKey('2'),\n createNumberKey('3'),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('4'),\n createNumberKey('5'),\n createNumberKey('6'),\n {\n id: 'clear',\n type: 'clear',\n icon: ICON_CLEAR,\n label: '',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n createNumberKey('7'),\n createNumberKey('8'),\n createNumberKey('9'),\n {\n id: 'close',\n type: 'close',\n label: '关闭',\n className: 'key-numpad-fn',\n },\n ],\n },\n {\n className: 'numpad-row',\n keys: [\n {\n id: 'decimal',\n type: 'char',\n label: '.',\n value: '.',\n className: 'key-num',\n },\n createNumberKey('0'),\n {\n id: 'done',\n type: 'done',\n label: '确定',\n width: 2,\n className: 'key-numpad-done',\n },\n ],\n },\n ],\n data: {\n inputType: 'amount',\n decimalPlaces: 2,\n },\n}\n","/**\n * 银行卡键盘布局\n * @module layouts/bankcard\n */\n\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 从图标模块中导入删除键图标和清除键图标\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n * @param num - 数字字符串(如 '0'-'9')\n * @returns 返回一个按键定义对象\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `bankcard-${num}`, // 按键唯一标识符,格式为 bankcard-数字\n type: 'char', // 按键类型为字符键\n label: num, // 按键上显示的文本\n value: num, // 按键按下后输出的值\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\n }\n}\n\n/**\n * 银行卡键盘配置 - 紧凑4x4布局\n * 布局结构:\n * 第1行: 1 2 3 [退格]\n * 第2行: 4 5 6 [清除]\n * 第3行: 7 8 9 [关闭]\n * 第4行: [ABC] 0 [确定(占2格)]\n */\nexport const bankcardLayout: KeyboardConfig = {\n type: 'bankcard', // 键盘类型标识\n name: '银行卡键盘', // 键盘的显示名称\n supportShift: false, // 不支持 Shift 切换(纯数字键盘无需切换)\n rows: [ // 键盘的行数组\n // ---- 第1行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [ // 该行包含的按键数组\n createNumberKey('1'), // 数字键 1\n createNumberKey('2'), // 数字键 2\n createNumberKey('3'), // 数字键 3\n {\n id: 'backspace', // 退格键的唯一标识\n type: 'backspace', // 按键类型为退格,删除最后一个字符\n icon: ICON_DELETE, // 使用删除图标作为显示内容\n label: '', // 无文本标签(由图标替代)\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第2行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('4'), // 数字键 4\n createNumberKey('5'), // 数字键 5\n createNumberKey('6'), // 数字键 6\n {\n id: 'clear', // 清除键的唯一标识\n type: 'clear', // 按键类型为清除,清空所有输入\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\n label: '', // 无文本标签\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第3行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('7'), // 数字键 7\n createNumberKey('8'), // 数字键 8\n createNumberKey('9'), // 数字键 9\n {\n id: 'close', // 关闭键的唯一标识\n type: 'close', // 按键类型为关闭,收起键盘\n label: '关闭', // 按钮上显示的文本\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第4行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n {\n id: 'switch-qwerty', // 切换到全键盘的按键唯一标识\n type: 'tab', // 按键类型为标签页切换\n label: 'ABC', // 按钮上显示的文本,提示可切换到字母键盘\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n data: { targetType: 'qwerty' }, // 附加数据,指定切换目标为 QWERTY 全键盘\n },\n createNumberKey('0'), // 数字键 0\n {\n id: 'done', // 确定键的唯一标识\n type: 'done', // 按键类型为确定,完成输入\n label: '确定', // 按钮上显示的文本\n width: 2, // 占据 2 个键的宽度\n className: 'key-numpad-done', // 确定键的 CSS 类名\n },\n ],\n },\n ],\n data: { // 键盘的附加数据\n maxLength: 19, // 银行卡号最大输入长度为 19 位\n inputType: 'bankcard', // 输入类型标识,用于外部判断\n },\n}\n","/**\n * 验证码键盘布局\n * @module layouts/verifycode\n */\n\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 从图标模块中导入删除键图标和清除键图标\nimport { ICON_DELETE, ICON_CLEAR } from '../icons'\n\n/**\n * 创建数字按键\n * @param num - 数字字符串(如 '0'-'9')\n * @returns 返回一个按键定义对象\n */\nfunction createNumberKey(num: string): KeyDefinition {\n return {\n id: `verify-${num}`, // 按键唯一标识符,格式为 verify-数字\n type: 'char', // 按键类型为字符键\n label: num, // 按键上显示的文本\n value: num, // 按键按下后输出的值\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\n }\n}\n\n/**\n * 验证码键盘配置 - 4x4布局(与其他数字键盘一致)\n * 布局结构:\n * 第1行: 1 2 3 [退格]\n * 第2行: 4 5 6 [清除]\n * 第3行: 7 8 9 [关闭]\n * 第4行: [空] 0 [确定(占2格)]\n */\nexport const verifycodeLayout: KeyboardConfig = {\n type: 'verifycode', // 键盘类型标识\n name: '验证码键盘', // 键盘的显示名称\n supportShift: false, // 不支持 Shift 切换(纯数字键盘无需切换)\n rows: [ // 键盘的行数组\n // ---- 第1行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [ // 该行包含的按键数组\n createNumberKey('1'), // 数字键 1\n createNumberKey('2'), // 数字键 2\n createNumberKey('3'), // 数字键 3\n {\n id: 'backspace', // 退格键的唯一标识\n type: 'backspace', // 按键类型为退格,删除最后一个字符\n icon: ICON_DELETE, // 使用删除图标作为显示内容\n label: '', // 无文本标签(由图标替代)\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第2行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('4'), // 数字键 4\n createNumberKey('5'), // 数字键 5\n createNumberKey('6'), // 数字键 6\n {\n id: 'clear', // 清除键的唯一标识\n type: 'clear', // 按键类型为清除,清空所有输入\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\n label: '', // 无文本标签\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第3行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n createNumberKey('7'), // 数字键 7\n createNumberKey('8'), // 数字键 8\n createNumberKey('9'), // 数字键 9\n {\n id: 'close', // 关闭键的唯一标识\n type: 'close', // 按键类型为关闭,收起键盘\n label: '关闭', // 按钮上显示的文本\n className: 'key-numpad-fn', // 功能键的 CSS 类名\n },\n ],\n },\n // ---- 第4行 ----\n {\n className: 'numpad-row', // 行的 CSS 类名\n keys: [\n {\n id: 'empty', // 占位空键的唯一标识\n type: 'char', // 类型为字符键(但被禁用)\n label: '', // 无显示文本\n value: '', // 无输出值\n disabled: true, // 禁用状态,不可点击\n className: 'key-numpad-empty', // 空占位键的 CSS 类名\n },\n createNumberKey('0'), // 数字键 0\n {\n id: 'done', // 确定键的唯一标识\n type: 'done', // 按键类型为确定,完成输入\n label: '确定', // 按钮上显示的文本\n width: 2, // 占据 2 个键的宽度\n className: 'key-numpad-done', // 确定键的 CSS 类名\n },\n ],\n },\n ],\n data: { // 键盘的附加数据\n maxLength: 6, // 验证码最大输入长度为 6 位\n inputType: 'verifycode', // 输入类型标识,用于外部判断\n },\n}\n","/**\n * 邮箱键盘布局\n * @module layouts/email\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport { ICON_DELETE, ICON_SHIFT } from '../icons'\n\n/**\n * 创建字符按键(支持大小写)\n */\nfunction createCharKey(char: string): KeyDefinition {\n return {\n id: `email-char-${char.toLowerCase()}`,\n type: 'char',\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() },\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() },\n }\n}\n\n/**\n * 创建快捷片段按键\n */\nfunction snippet(label: string, id?: string): KeyDefinition {\n return {\n id: id || `email-snippet-${label.replace(/[^a-z0-9]/gi, '')}`,\n type: 'char',\n label,\n value: label,\n className: 'key-snippet',\n }\n}\n\n/**\n * 常见邮箱后缀列表\n */\nexport const EMAIL_SUFFIXES = [\n '@qq.com',\n '@163.com',\n '@126.com',\n '@gmail.com',\n '@outlook.com',\n '@hotmail.com',\n '@sina.com',\n '@sohu.com',\n '@icloud.com',\n '@foxmail.com',\n '@yeah.net',\n '@139.com',\n]\n\nexport const emailLayout: KeyboardConfig = {\n type: 'email',\n name: '邮箱键盘',\n supportShift: true,\n defaultUpperCase: false,\n switchable: ['symbol', 'number'],\n rows: [\n // QWERTY 第一行\n {\n keys: 'qwertyuiop'.split('').map(createCharKey),\n },\n // QWERTY 第二行\n {\n keys: 'asdfghjkl'.split('').map(createCharKey),\n },\n // QWERTY 第三行 + Shift + 退格\n {\n keys: [\n {\n id: 'shift',\n type: 'shift',\n icon: ICON_SHIFT,\n label: '',\n width: 1.5,\n className: 'key-shift',\n },\n ...'zxcvbnm'.split('').map(createCharKey),\n {\n id: 'backspace',\n type: 'backspace',\n icon: ICON_DELETE,\n label: '',\n width: 1.5,\n className: 'key-backspace',\n },\n ],\n },\n // 底部行:切换 + @ + 常用邮箱 + 符号 + 空格 + 完成\n {\n keys: [\n { id: 'switch-number', type: 'tab', label: '123', width: 1.25, className: 'key-switch', data: { targetType: 'number' } },\n {\n id: 'email-at',\n type: 'char',\n label: '@',\n value: '@',\n className: 'key-at',\n },\n {\n id: 'email-suffix',\n type: 'char',\n label: '.com',\n value: '',\n width: 1.5,\n className: 'key-suffix',\n options: EMAIL_SUFFIXES,\n },\n snippet('.', 'email-dot'),\n snippet('-', 'email-dash'),\n snippet('_', 'email-underscore'),\n { id: 'space', type: 'space', label: '', value: ' ', width: 2, className: 'key-space' },\n { id: 'email-done', type: 'done', label: '确定', width: 1.5, className: 'key-done' },\n ],\n },\n ],\n}\n","/**\n * URL/链接键盘布局\n * @module layouts/url\n */\n\n// 导入键盘配置和按键定义的类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 导入删除和Shift图标资源\nimport { ICON_DELETE, ICON_SHIFT } from '../icons'\n\n/**\n * 创建字符按键(支持大小写)\n * @param char - 字符,用于生成大小写标签和值\n * @returns 返回一个按键定义对象\n */\nfunction createCharKey(char: string): KeyDefinition {\n return {\n id: `url-char-${char.toLowerCase()}`, // 按键唯一标识,格式为 url-char-x\n type: 'char', // 按键类型为字符键\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 显示标签:小写/大写\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 输出值:小写/大写\n }\n}\n\n/**\n * 创建快捷片段按键\n * 用于URL键盘中常用的符号和域名后缀\n * @param label - 按键显示文本\n * @param width - 可选,按键宽度倍数\n * @returns 返回一个片段按键定义对象\n */\nfunction snippet(label: string, width?: number): KeyDefinition {\n // 生成唯一 ID:用 label 的字符编码(去除非法字符后拼接)\n const idSuffix = label.replace(/[^a-z0-9]/gi, '') || label.split('').map(c => c.charCodeAt(0)).join('')\n return {\n id: `url-snippet-${idSuffix}`, // 按键唯一标识,格式为 url-snippet-xxx\n type: 'char', // 按键类型为字符键\n label, // 显示文本\n value: label, // 输出值与显示文本相同\n width, // 按键宽度倍数\n className: 'key-snippet', // 自定义CSS类名,用于样式控制\n }\n}\n\n// 导出URL键盘布局配置\nexport const urlLayout: KeyboardConfig = {\n type: 'url', // 布局类型标识为 url\n name: '网址键盘', // 布局显示名称\n supportShift: true, // 支持Shift切换大小写\n defaultUpperCase: false, // 默认为小写状态\n switchable: ['symbol', 'number'], // 可切换到符号键盘和数字键盘\n rows: [\n // QWERTY 第一行:q w e r t y u i o p\n {\n keys: 'qwertyuiop'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\n },\n // QWERTY 第二行:a s d f g h j k l\n {\n keys: 'asdfghjkl'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\n },\n // QWERTY 第三行 + Shift + 退格\n {\n keys: [\n {\n id: 'shift', // Shift键标识\n type: 'shift', // 按键类型为Shift\n icon: ICON_SHIFT, // 使用Shift图标\n label: '', // 无文字标签,仅显示图标\n width: 1.5, // 宽度为1.5倍\n className: 'key-shift', // CSS类名\n },\n ...'zxcvbnm'.split('').map(createCharKey), // 展开第三行字母 z x c v b n m 的按键定义\n {\n id: 'backspace', // 退格键标识\n type: 'backspace', // 按键类型为退格\n icon: ICON_DELETE, // 使用删除图标\n label: '', // 无文字标签,仅显示图标\n width: 1.5, // 宽度为1.5倍\n className: 'key-backspace', // CSS类名\n },\n ],\n },\n // 底部行:切换 + 符号 + 域名后缀 + 前往\n {\n keys: [\n { id: 'switch-number', type: 'tab', label: '123', width: 1.2, className: 'key-switch', data: { targetType: 'number' } }, // 切换到数字键盘\n snippet('/', 0.8), // 斜杠快捷键,宽度0.8倍\n snippet('.', 0.8), // 点号快捷键,宽度0.8倍\n snippet('-', 0.8), // 横杠快捷键,宽度0.8倍\n snippet('.com', 1.5), // .com域名后缀快捷键,宽度1.5倍\n snippet('.cn', 1.2), // .cn域名后缀快捷键,宽度1.2倍\n { id: 'space', type: 'space', label: '', value: ' ', width: 1.5, className: 'key-space' }, // 空格键,宽度1.5倍\n { id: 'url-go', type: 'done', label: '前往', width: 1.5, className: 'key-done' }, // 前往/完成按钮,宽度1.5倍\n ],\n },\n ],\n}\n","/**\n * 搜索键盘布局\n * @module layouts/search\n */\n\n// 导入键盘配置和按键定义的类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 导入删除、Shift和语音图标资源\nimport { ICON_DELETE, ICON_SHIFT, ICON_VOICE } from '../icons'\n\n/**\n * 创建字符按键(支持大小写)\n * @param char - 字符,用于生成大小写标签和值\n * @returns 返回一个按键定义对象\n */\nfunction createCharKey(char: string): KeyDefinition {\n return {\n id: `search-char-${char.toLowerCase()}`, // 按键唯一标识,格式为 search-char-x\n type: 'char', // 按键类型为字符键\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 显示标签:小写/大写\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 输出值:小写/大写\n }\n}\n\n// 导出搜索键盘布局配置\nexport const searchLayout: KeyboardConfig = {\n type: 'search', // 布局类型标识为 search\n name: '搜索键盘', // 布局显示名称\n supportShift: true, // 支持Shift切换大小写\n defaultUpperCase: false, // 默认为小写状态\n switchable: ['symbol', 'number'], // 可切换到符号键盘和数字键盘\n rows: [\n // QWERTY 第一行:q w e r t y u i o p\n {\n keys: 'qwertyuiop'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\n },\n // QWERTY 第二行:a s d f g h j k l\n {\n keys: 'asdfghjkl'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\n },\n // QWERTY 第三行 + Shift + 退格\n {\n keys: [\n {\n id: 'shift', // Shift键标识\n type: 'shift', // 按键类型为Shift\n icon: ICON_SHIFT, // 使用Shift图标\n label: '', // 无文字标签,仅显示图标\n width: 1.5, // 宽度为1.5倍\n className: 'key-shift', // CSS类名\n },\n ...'zxcvbnm'.split('').map(createCharKey), // 展开第三行字母 z x c v b n m 的按键定义\n {\n id: 'backspace', // 退格键标识\n type: 'backspace', // 按键类型为退格\n icon: ICON_DELETE, // 使用删除图标\n label: '', // 无文字标签,仅显示图标\n width: 1.5, // 宽度为1.5倍\n className: 'key-backspace', // CSS类名\n },\n ],\n },\n // 底部行:切换 + 空格 + 语音 + 搜索\n {\n keys: [\n { id: 'switch-number', type: 'tab', label: '123', width: 1.25, className: 'key-switch', data: { targetType: 'number' } }, // 切换到数字键盘,宽度1.25倍\n { id: 'switch-symbol', type: 'tab', label: '#+=', width: 1.25, className: 'key-switch', data: { targetType: 'symbol' } }, // 切换到符号键盘,宽度1.25倍\n { id: 'space', type: 'space', label: '', value: ' ', width: 4, className: 'key-space' }, // 空格键,宽度4倍\n { id: 'voice', type: 'custom', icon: ICON_VOICE, label: '', width: 1, className: 'key-voice', data: { action: 'voice' } }, // 语音输入按钮,宽度1倍\n { id: 'search-done', type: 'done', label: '搜索', width: 2, className: 'key-done' }, // 搜索/完成按钮,宽度2倍\n ],\n },\n ],\n}\n","/**\n * 标点符号键盘布局 (中文)\n * @module layouts/punct\n */\n\n// 导入键盘配置和按键定义的类型\nimport type { KeyboardConfig, KeyDefinition } from '../types'\n// 导入删除和确认图标资源\nimport { ICON_DELETE, ICON_CHECK } from '../icons'\n\n/**\n * 创建标点符号按键的快捷函数\n * @param label - 按键显示文本(同时也是默认输出值)\n * @param value - 可选,按键输出值,不传则与label相同\n * @returns 返回一个标点按键定义对象\n */\nfunction p(label: string, value?: string): KeyDefinition {\n return { id: `punct-${label}`, type: 'char', label, value: value ?? label, className: 'key-num' }\n}\n\n// 导出中文标点键盘布局配置\nexport const punctLayout: KeyboardConfig = {\n type: 'punct', // 布局类型标识为 punct\n name: '中文标点', // 布局显示名称\n supportShift: false, // 不支持Shift切换(标点键盘无需大小写)\n switchable: ['qwerty', 'punct-en'], // 可切换到QWERTY键盘和英文标点键盘\n rows: [\n // 第一行:常用中文标点符号\n {\n className: 'virtual-keyboard__row', // 行的CSS类名\n keys: [',', '。', '?', '!', ':', ';', '\"', '\"'].map(s => p(s)), // 逗号、句号、问号、感叹号、冒号、分号、左右双引号\n },\n // 第二行:括号类标点符号\n {\n className: 'virtual-keyboard__row', // 行的CSS类名\n keys: ['(', ')', '【', '】', '《', '》', '……', '——'].map(s => p(s)), // 小括号、中括号、书名号、省略号、破折号\n },\n // 第三行:其他标点 + 退格键\n {\n className: 'virtual-keyboard__row', // 行的CSS类名\n keys: [\n p('·'), // 间隔号(中间点)\n p('、'), // 顿号\n p('「'), // 左单书名号\n p('」'), // 右单书名号\n p('『'), // 左双书名号\n p('』'), // 右双书名号\n p('~'), // 波浪号\n { id: 'backspace', type: 'backspace', icon: ICON_DELETE, label: '', className: 'key-numpad-fn' }, // 退格键\n ],\n },\n // 底部行:切换键盘 + 空格 + 确认\n {\n className: 'virtual-keyboard__row', // 行的CSS类名\n keys: [\n { id: 'switch-punct-en', type: 'tab', label: '英', data: { targetType: 'punct-en' }, className: 'key-numpad-fn' }, // 切换到英文标点键盘\n { id: 'switch-qwerty', type: 'tab', label: 'ABC', data: { targetType: 'qwerty' }, className: 'key-numpad-fn' }, // 切换到QWERTY字母键盘\n { id: 'space', type: 'space', label: '空格', value: ' ', width: 4, className: 'key-num' }, // 空格键,宽度4倍\n { id: 'done', type: 'done', icon: ICON_CHECK, label: '', width: 2, className: 'key-numpad-done' }, // 确认/完成按钮,宽度2倍\n ],\n },\n ],\n}\n","/**\n * 键盘布局管理\n * @module layouts\n */\n\nimport type { KeyboardConfig, KeyboardType } from '../types'\nimport { qwertyLayout } from './qwerty'\nimport { integerLayout, numberLayout } from './number'\nimport { symbolLayout, symbolLayout2 } from './symbol'\nimport {\n licensePlateAlphanumericLayout,\n licensePlateLayout,\n licensePlateLetterLayout,\n licensePlateProvinceLayout,\n PLATE_LETTERS,\n PROVINCES,\n} from './license-plate'\nimport { idcardLayout } from './idcard'\nimport { phoneLayout, phoneSimpleLayout } from './phone'\nimport { amountLayout, amountSimpleLayout } from './amount'\nimport { bankcardLayout } from './bankcard'\nimport { verifycodeLayout } from './verifycode'\nimport { emailLayout, EMAIL_SUFFIXES } from './email'\nimport { urlLayout } from './url'\nimport { searchLayout } from './search'\nimport { punctLayout } from './punct'\n\n// 导出所有布局\nexport {\n qwertyLayout,\n numberLayout,\n integerLayout,\n symbolLayout,\n symbolLayout2,\n licensePlateLayout,\n licensePlateProvinceLayout,\n licensePlateLetterLayout,\n licensePlateAlphanumericLayout,\n PROVINCES,\n PLATE_LETTERS,\n // 场景化键盘\n idcardLayout,\n phoneLayout,\n phoneSimpleLayout,\n amountLayout,\n amountSimpleLayout,\n bankcardLayout,\n verifycodeLayout,\n // 输入场景键盘\n emailLayout,\n urlLayout,\n searchLayout,\n EMAIL_SUFFIXES,\n // 标点键盘\n punctLayout,\n}\n\n/**\n * 内置布局映射\n */\nconst builtinLayouts: Record<string, KeyboardConfig> = {\n 'qwerty': qwertyLayout,\n 'number': numberLayout,\n 'integer': integerLayout,\n 'symbol': symbolLayout,\n 'symbol-2': symbolLayout2,\n 'license-plate': licensePlateLayout,\n 'license-plate-province': licensePlateProvinceLayout,\n 'license-plate-letter': licensePlateLetterLayout,\n 'license-plate-alphanumeric': licensePlateAlphanumericLayout,\n // 场景化键盘\n 'idcard': idcardLayout,\n 'phone': phoneLayout,\n 'phone-simple': phoneSimpleLayout,\n 'amount': amountLayout,\n 'amount-simple': amountSimpleLayout,\n 'bankcard': bankcardLayout,\n 'verifycode': verifycodeLayout,\n // 输入场景键盘\n 'email': emailLayout,\n 'url': urlLayout,\n 'search': searchLayout,\n // 标点键盘\n 'punct': punctLayout,\n}\n\n/**\n * 自定义布局存储\n */\nconst customLayouts: Record<string, KeyboardConfig> = {}\n\n/**\n * 注册自定义布局\n * @param name - 布局名称\n * @param layout - 布局配置\n */\nexport function registerLayout(name: string, layout: KeyboardConfig): void {\n if (builtinLayouts[name]) {\n console.warn(`[Keyboard] Cannot override builtin layout \"${name}\"`)\n return\n }\n customLayouts[name] = layout\n}\n\n/**\n * 获取布局配置\n * @param type - 键盘类型或布局名称\n * @returns 布局配置,如果不存在则返回 undefined\n */\nexport function getLayout(type: KeyboardType | string): KeyboardConfig | undefined {\n return customLayouts[type] || builtinLayouts[type]\n}\n\n/**\n * 获取所有可用布局名称\n * @returns 布局名称数组\n */\nexport function getAvailableLayouts(): string[] {\n return [...Object.keys(builtinLayouts), ...Object.keys(customLayouts)]\n}\n\n/**\n * 检查布局是否存在\n * @param name - 布局名称\n * @returns 是否存在\n */\nexport function hasLayout(name: string): boolean {\n return name in builtinLayouts || name in customLayouts\n}\n\n/**\n * 移除自定义布局\n * @param name - 布局名称\n * @returns 是否成功移除\n */\nexport function unregisterLayout(name: string): boolean {\n if (name in customLayouts) {\n delete customLayouts[name]\n return true\n }\n return false\n}\n\n/**\n * 批量注册布局\n * @param layouts - 布局映射对象\n */\nexport function registerLayouts(layouts: Record<string, KeyboardConfig>): void {\n Object.entries(layouts).forEach(([name, layout]) => {\n registerLayout(name, layout)\n })\n}\n","/**\n * 事件发射器\n * @module utils/event-emitter\n */\n\n/**\n * 事件处理函数类型\n */\nexport type EventHandler<T = unknown> = (data: T) => void\n\n/**\n * 事件处理器配置\n */\nexport interface EventHandlerOptions {\n /**\n * 是否只触发一次\n */\n once?: boolean\n\n /**\n * 优先级(数字越大优先级越高)\n */\n priority?: number\n}\n\n/**\n * 内部事件处理器包装\n */\ninterface EventHandlerWrapper<T> {\n handler: EventHandler<T>\n options: EventHandlerOptions\n}\n\n/**\n * 事件发射器类\n */\nexport class EventEmitter<EventMap extends Record<string, unknown>> {\n private handlers = new Map<keyof EventMap, Set<EventHandlerWrapper<unknown>>>()\n\n /**\n * 订阅事件\n */\n on<K extends keyof EventMap>(\n event: K,\n handler: EventHandler<EventMap[K]>,\n options: EventHandlerOptions = {},\n ): () => void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set())\n }\n\n const handlers = this.handlers.get(event)!\n const wrapper: EventHandlerWrapper<EventMap[K]> = {\n handler: handler as EventHandler<unknown>,\n options,\n }\n\n handlers.add(wrapper as EventHandlerWrapper<unknown>)\n\n return () => {\n handlers.delete(wrapper as EventHandlerWrapper<unknown>)\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n /**\n * 订阅事件(仅触发一次)\n */\n once<K extends keyof EventMap>(\n event: K,\n handler: EventHandler<EventMap[K]>,\n options: EventHandlerOptions = {},\n ): () => void {\n return this.on(event, handler, { ...options, once: true })\n }\n\n /**\n * 取消订阅事件\n */\n off<K extends keyof EventMap>(\n event: K,\n handler?: EventHandler<EventMap[K]>,\n ): void {\n if (!handler) {\n this.handlers.delete(event)\n return\n }\n\n const handlers = this.handlers.get(event)\n if (handlers) {\n handlers.forEach((wrapper) => {\n if (wrapper.handler === handler) {\n handlers.delete(wrapper)\n }\n })\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n }\n\n /**\n * 发布事件\n */\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\n const handlers = this.handlers.get(event)\n if (!handlers || handlers.size === 0) {\n return\n }\n\n // 按优先级排序\n const sortedHandlers = Array.from(handlers).sort((a, b) => {\n const priorityA = a.options.priority ?? 0\n const priorityB = b.options.priority ?? 0\n return priorityB - priorityA\n })\n\n const toRemove: EventHandlerWrapper<unknown>[] = []\n\n sortedHandlers.forEach((wrapper) => {\n try {\n wrapper.handler(data)\n if (wrapper.options.once) {\n toRemove.push(wrapper)\n }\n }\n catch (error) {\n console.error(`[KeyboardEventEmitter] Error in event handler for \"${String(event)}\":`, error)\n }\n })\n\n // 移除 once 处理器\n toRemove.forEach(wrapper => handlers.delete(wrapper))\n if (handlers.size === 0) {\n this.handlers.delete(event)\n }\n }\n\n /**\n * 清除所有事件订阅\n */\n clear(): void {\n this.handlers.clear()\n }\n\n /**\n * 获取事件订阅数量\n */\n listenerCount(event?: keyof EventMap): number {\n if (event !== undefined) {\n return this.handlers.get(event)?.size ?? 0\n }\n\n let count = 0\n this.handlers.forEach((handlers) => {\n count += handlers.size\n })\n return count\n }\n}\n","/**\n * 设备检测工具\n * @module utils/device\n */\n\nimport type { DeviceType, ViewportInfo } from '../types'\n\n/**\n * 移动设备 UA 正则\n */\nconst MOBILE_UA_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i\n\n/**\n * 触摸设备检测缓存\n */\nlet cachedIsTouchDevice: boolean | null = null\n\n/**\n * 检测是否为触摸设备\n */\nexport function isTouchDevice(): boolean {\n if (cachedIsTouchDevice !== null) {\n return cachedIsTouchDevice\n }\n\n if (typeof window === 'undefined') {\n cachedIsTouchDevice = false\n return false\n }\n\n cachedIsTouchDevice = (\n 'ontouchstart' in window\n || navigator.maxTouchPoints > 0\n // @ts-expect-error - msMaxTouchPoints is IE specific\n || navigator.msMaxTouchPoints > 0\n )\n\n return cachedIsTouchDevice\n}\n\n/**\n * 检测是否为移动设备(基于 UA)\n */\nexport function isMobileUA(): boolean {\n if (typeof navigator === 'undefined') {\n return false\n }\n return MOBILE_UA_REGEX.test(navigator.userAgent)\n}\n\n/**\n * 检测是否为移动设备(综合判断)\n */\nexport function isMobile(): boolean {\n if (typeof window === 'undefined') {\n return false\n }\n\n // 优先使用 UA 判断\n if (isMobileUA()) {\n return true\n }\n\n // 其次使用屏幕宽度判断\n const screenWidth = window.innerWidth || document.documentElement.clientWidth\n if (screenWidth <= 768) {\n return true\n }\n\n // 最后使用触摸检测\n return isTouchDevice()\n}\n\n/**\n * 获取设备类型\n */\nexport function getDeviceType(): DeviceType {\n return isMobile() ? 'mobile' : 'desktop'\n}\n\n/**\n * 获取视口信息\n */\nexport function getViewportInfo(): ViewportInfo {\n if (typeof window === 'undefined') {\n return {\n width: 0,\n height: 0,\n scrollX: 0,\n scrollY: 0,\n isMobile: false,\n }\n }\n\n const width = window.innerWidth || document.documentElement.clientWidth\n const height = window.innerHeight || document.documentElement.clientHeight\n\n // 获取安全区域(iOS 刘海屏等)\n const safeArea = getSafeAreaInsets()\n\n return {\n width,\n height,\n scrollX: window.scrollX || window.pageXOffset,\n scrollY: window.scrollY || window.pageYOffset,\n isMobile: isMobile(),\n safeArea,\n }\n}\n\n/**\n * 获取安全区域边距\n */\nexport function getSafeAreaInsets(): ViewportInfo['safeArea'] {\n if (typeof window === 'undefined' || typeof CSS === 'undefined' || !CSS.supports) {\n return { top: 0, right: 0, bottom: 0, left: 0 }\n }\n\n // 检查是否支持 env() 函数\n if (!CSS.supports('padding-top', 'env(safe-area-inset-top)')) {\n return { top: 0, right: 0, bottom: 0, left: 0 }\n }\n\n // 创建临时元素获取安全区域值\n const div = document.createElement('div')\n div.style.cssText = `\n position: fixed;\n top: env(safe-area-inset-top);\n right: env(safe-area-inset-right);\n bottom: env(safe-area-inset-bottom);\n left: env(safe-area-inset-left);\n pointer-events: none;\n visibility: hidden;\n `\n document.body.appendChild(div)\n\n const computed = getComputedStyle(div)\n const safeArea = {\n top: Number.parseFloat(computed.top) || 0,\n right: Number.parseFloat(computed.right) || 0,\n bottom: Number.parseFloat(computed.bottom) || 0,\n left: Number.parseFloat(computed.left) || 0,\n }\n\n document.body.removeChild(div)\n return safeArea\n}\n\n/**\n * 检测是否支持震动 API\n */\nexport function supportsVibrate(): boolean {\n return typeof navigator !== 'undefined' && 'vibrate' in navigator\n}\n\n/**\n * 触发震动反馈\n * @param pattern - 震动模式(毫秒)\n */\nexport function vibrate(pattern: number | number[] = 10): boolean {\n if (supportsVibrate()) {\n return navigator.vibrate(pattern)\n }\n return false\n}\n\n/**\n * 监听视口变化\n * @param callback - 回调函数\n * @returns 取消监听函数\n */\nexport function onViewportChange(callback: (info: ViewportInfo) => void): () => void {\n if (typeof window === 'undefined') {\n return () => {}\n }\n\n const handler = () => {\n callback(getViewportInfo())\n }\n\n window.addEventListener('resize', handler)\n window.addEventListener('orientationchange', handler)\n\n return () => {\n window.removeEventListener('resize', handler)\n window.removeEventListener('orientationchange', handler)\n }\n}\n","/**\n * DOM 操作工具\n * @module utils/dom\n */\n\nimport type { BoundingRect, Position } from '../types'\n\n/**\n * 获取元素的边界矩形\n */\nexport function getBoundingRect(element: HTMLElement): BoundingRect {\n const rect = element.getBoundingClientRect()\n return {\n x: rect.left,\n y: rect.top,\n width: rect.width,\n height: rect.height,\n }\n}\n\n/**\n * 获取元素相对于文档的位置\n */\nexport function getElementOffset(element: HTMLElement): Position {\n const rect = element.getBoundingClientRect()\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop\n\n return {\n x: rect.left + scrollLeft,\n y: rect.top + scrollTop,\n }\n}\n\n/**\n * 检查元素是否在视口内\n */\nexport function isElementInViewport(element: HTMLElement): boolean {\n const rect = element.getBoundingClientRect()\n return (\n rect.top >= 0\n && rect.left >= 0\n && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight)\n && rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n )\n}\n\n/**\n * 检查点击是否在元素外部\n */\nexport function isClickOutside(event: MouseEvent | TouchEvent, element: HTMLElement): boolean {\n const target = event.target as Node\n return !element.contains(target)\n}\n\n/**\n * 阻止元素默认事件(用于防止输入框获取焦点)\n */\nexport function preventDefaultAndStopPropagation(event: Event): void {\n event.preventDefault()\n event.stopPropagation()\n}\n\n/**\n * 添加点击外部监听\n */\nexport function onClickOutside(\n element: HTMLElement,\n callback: (event: MouseEvent | TouchEvent) => void,\n): () => void {\n const handler = (event: MouseEvent | TouchEvent) => {\n if (isClickOutside(event, element)) {\n callback(event)\n }\n }\n\n document.addEventListener('mousedown', handler)\n document.addEventListener('touchstart', handler)\n\n return () => {\n document.removeEventListener('mousedown', handler)\n document.removeEventListener('touchstart', handler)\n }\n}\n\n/**\n * 滚动元素到可视区域\n */\nexport function scrollIntoViewIfNeeded(element: HTMLElement, container?: HTMLElement): void {\n if (!container) {\n element.scrollIntoView({ behavior: 'smooth', block: 'nearest' })\n return\n }\n\n const elementRect = element.getBoundingClientRect()\n const containerRect = container.getBoundingClientRect()\n\n if (elementRect.bottom > containerRect.bottom) {\n container.scrollTop += elementRect.bottom - containerRect.bottom\n }\n else if (elementRect.top < containerRect.top) {\n container.scrollTop -= containerRect.top - elementRect.top\n }\n}\n\n/**\n * 获取输入框的光标位置\n */\nexport function getInputCursorPosition(input: HTMLInputElement | HTMLTextAreaElement): number {\n return input.selectionStart ?? input.value.length\n}\n\n/**\n * 设置输入框的光标位置\n */\nexport function setInputCursorPosition(\n input: HTMLInputElement | HTMLTextAreaElement,\n position: number,\n): void {\n input.setSelectionRange(position, position)\n}\n\n/**\n * 在输入框当前光标位置插入文本\n */\nexport function insertTextAtCursor(\n input: HTMLInputElement | HTMLTextAreaElement,\n text: string,\n maxLength?: number,\n): { value: string; cursorPosition: number } {\n const start = input.selectionStart ?? input.value.length\n const end = input.selectionEnd ?? input.value.length\n const currentValue = input.value\n\n let newValue = currentValue.substring(0, start) + text + currentValue.substring(end)\n\n // 检查最大长度\n if (maxLength !== undefined && newValue.length > maxLength) {\n const allowedLength = maxLength - (currentValue.length - (end - start))\n if (allowedLength <= 0) {\n return { value: currentValue, cursorPosition: start }\n }\n newValue = currentValue.substring(0, start) + text.substring(0, allowedLength) + currentValue.substring(end)\n }\n\n const newCursorPosition = start + text.length\n\n return {\n value: newValue,\n cursorPosition: Math.min(newCursorPosition, newValue.length),\n }\n}\n\n/**\n * 删除输入框光标前的字符\n */\nexport function deleteCharBeforeCursor(\n input: HTMLInputElement | HTMLTextAreaElement,\n): { value: string; deletedChar: string; cursorPosition: number } {\n const start = input.selectionStart ?? input.value.length\n const end = input.selectionEnd ?? input.value.length\n const currentValue = input.value\n\n // 如果有选中内容,删除选中内容\n if (start !== end) {\n const deletedChar = currentValue.substring(start, end)\n const newValue = currentValue.substring(0, start) + currentValue.substring(end)\n return {\n value: newValue,\n deletedChar,\n cursorPosition: start,\n }\n }\n\n // 没有选中内容,删除光标前一个字符\n if (start === 0) {\n return {\n value: currentValue,\n deletedChar: '',\n cursorPosition: 0,\n }\n }\n\n const deletedChar = currentValue.charAt(start - 1)\n const newValue = currentValue.substring(0, start - 1) + currentValue.substring(start)\n\n return {\n value: newValue,\n deletedChar,\n cursorPosition: start - 1,\n }\n}\n\n/**\n * 创建 DOM 元素\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs?: Record<string, string>,\n children?: (HTMLElement | string)[],\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag)\n\n if (attrs) {\n Object.entries(attrs).forEach(([key, value]) => {\n element.setAttribute(key, value)\n })\n }\n\n if (children) {\n children.forEach((child) => {\n if (typeof child === 'string') {\n element.appendChild(document.createTextNode(child))\n }\n else {\n element.appendChild(child)\n }\n })\n }\n\n return element\n}\n\n/**\n * 添加/移除 CSS 类\n */\nexport function toggleClass(element: HTMLElement, className: string, force?: boolean): void {\n element.classList.toggle(className, force)\n}\n\n/**\n * 设置 CSS 样式\n */\nexport function setStyles(element: HTMLElement, styles: Partial<CSSStyleDeclaration>): void {\n Object.assign(element.style, styles)\n}\n","/**\n * 键盘管理器\n * @module managers/keyboard-manager\n */\n\nimport type {\n KeyboardConfig,\n KeyboardEventMap,\n KeyboardOptions,\n KeyboardState,\n KeyboardType,\n KeyDefinition,\n} from '../types'\nimport { getLayout } from '../layouts'\nimport { EventEmitter } from '../utils/event-emitter'\nimport { isMobile, vibrate } from '../utils/device'\nimport {\n deleteCharBeforeCursor,\n getInputCursorPosition,\n insertTextAtCursor,\n setInputCursorPosition,\n} from '../utils/dom'\n\n/**\n * 默认键盘选项\n */\nconst DEFAULT_OPTIONS: Required<KeyboardOptions> = {\n type: 'qwerty',\n value: '',\n maxLength: undefined as unknown as number,\n defaultUpperCase: false,\n closeOnClickOutside: true,\n enableSound: false,\n enableVibrate: true,\n customLayouts: {},\n}\n\n/**\n * 键盘管理器类\n * 处理键盘状态管理、输入处理等核心逻辑\n */\nexport class KeyboardManager extends EventEmitter<KeyboardEventMap> {\n /** 配置选项 */\n private options: Required<KeyboardOptions>\n\n /** 当前状态 */\n private state: KeyboardState\n\n /** 当前布局配置 */\n private currentLayout: KeyboardConfig | null = null\n\n constructor(options: KeyboardOptions = {}) {\n super()\n this.options = { ...DEFAULT_OPTIONS, ...options }\n\n // 注册自定义布局\n if (options.customLayouts) {\n Object.entries(options.customLayouts).forEach(([name, layout]) => {\n // 这里不用 registerLayout 以避免覆盖内置布局的警告\n this.options.customLayouts[name] = layout\n })\n }\n\n // 初始化状态\n this.state = {\n visible: false,\n type: this.options.type,\n isUpperCase: this.options.defaultUpperCase,\n value: this.options.value,\n cursorPosition: this.options.value.length,\n maxLength: this.options.maxLength,\n inputElement: null,\n }\n\n // 加载初始布局\n this.loadLayout(this.options.type)\n }\n\n /**\n * 获取当前状态\n */\n getState(): Readonly<KeyboardState> {\n return { ...this.state }\n }\n\n /**\n * 获取当前布局配置\n */\n getLayout(): KeyboardConfig | null {\n return this.currentLayout\n }\n\n /**\n * 获取配置选项\n */\n getOptions(): Readonly<Required<KeyboardOptions>> {\n return { ...this.options }\n }\n\n /**\n * 加载键盘布局\n */\n private loadLayout(type: KeyboardType | string): boolean {\n // 先从自定义布局查找\n let layout = this.options.customLayouts[type]\n\n // 再从内置布局查找\n if (!layout) {\n layout = getLayout(type) as KeyboardConfig\n }\n\n if (!layout) {\n console.error(`[KeyboardManager] Layout \"${type}\" not found`)\n return false\n }\n\n this.currentLayout = layout\n\n // 更新大小写状态\n if (layout.supportShift) {\n this.state.isUpperCase = layout.defaultUpperCase ?? this.options.defaultUpperCase\n }\n\n return true\n }\n\n /**\n * 显示键盘\n */\n show(inputElement?: HTMLInputElement | HTMLTextAreaElement): void {\n if (this.state.visible) return\n\n this.state.visible = true\n this.state.inputElement = inputElement ?? null\n\n // 同步输入框的值\n if (inputElement) {\n this.state.value = inputElement.value\n this.state.cursorPosition = getInputCursorPosition(inputElement)\n }\n\n this.emitStateChange()\n this.emit('show', { type: this.state.type })\n }\n\n /**\n * 隐藏键盘\n */\n hide(): void {\n if (!this.state.visible) return\n\n const prevType = this.state.type\n this.state.visible = false\n this.state.inputElement = null\n\n this.emitStateChange()\n this.emit('hide', { type: prevType })\n }\n\n /**\n * 切换键盘显示/隐藏\n */\n toggle(inputElement?: HTMLInputElement | HTMLTextAreaElement): void {\n if (this.state.visible) {\n this.hide()\n }\n else {\n this.show(inputElement)\n }\n }\n\n /**\n * 切换键盘类型\n */\n switchType(type: KeyboardType | string): void {\n if (this.state.type === type) return\n\n const fromType = this.state.type\n if (!this.loadLayout(type)) return\n\n this.state.type = type as KeyboardType\n\n this.emitStateChange()\n this.emit('switch', { from: fromType, to: type as KeyboardType })\n }\n\n /**\n * 切换大小写\n */\n toggleShift(): void {\n if (!this.currentLayout?.supportShift) return\n\n this.state.isUpperCase = !this.state.isUpperCase\n this.emitStateChange()\n this.emit('shift', { isUpperCase: this.state.isUpperCase })\n }\n\n /**\n * 设置大小写状态\n */\n setShift(isUpperCase: boolean): void {\n if (!this.currentLayout?.supportShift) return\n if (this.state.isUpperCase === isUpperCase) return\n\n this.state.isUpperCase = isUpperCase\n this.emitStateChange()\n this.emit('shift', { isUpperCase })\n }\n\n /**\n * 处理按键\n */\n handleKey(key: KeyDefinition): void {\n // 触发震动反馈\n if (this.options.enableVibrate && isMobile()) {\n vibrate(10)\n }\n\n this.emit('keypress', { key, value: this.state.value })\n\n switch (key.type) {\n case 'char':\n case 'space':\n this.handleCharKey(key)\n break\n case 'backspace':\n this.handleBackspace()\n break\n case 'shift':\n this.toggleShift()\n break\n case 'clear':\n this.handleClear()\n break\n case 'enter':\n case 'done':\n this.handleConfirm()\n break\n case 'close':\n this.hide()\n break\n case 'tab':\n this.handleTab(key)\n break\n case 'custom':\n // 自定义按键,只触发事件\n break\n }\n }\n\n /**\n * 处理字符输入\n */\n private handleCharKey(key: KeyDefinition): void {\n const keyValue = this.getKeyValue(key)\n if (!keyValue) return\n\n const input = this.state.inputElement\n\n if (input) {\n // 如果有绑定输入框,直接操作输入框\n const result = insertTextAtCursor(input, keyValue, this.state.maxLength)\n input.value = result.value\n setInputCursorPosition(input, result.cursorPosition)\n this.state.value = result.value\n this.state.cursorPosition = result.cursorPosition\n\n // 触发原生 input 事件\n input.dispatchEvent(new Event('input', { bubbles: true }))\n }\n else {\n // 没有输入框,直接修改内部值\n if (this.state.maxLength && this.state.value.length >= this.state.maxLength) {\n return\n }\n const newValue = this.state.value.slice(0, this.state.cursorPosition)\n + keyValue\n + this.state.value.slice(this.state.cursorPosition)\n this.state.value = newValue\n this.state.cursorPosition += keyValue.length\n }\n\n this.emitStateChange()\n this.emit('input', { value: this.state.value, key })\n\n // 车牌号智能切换\n this.autoSwitchLicensePlate()\n }\n\n /**\n * 处理退格\n */\n private handleBackspace(): void {\n const input = this.state.inputElement\n\n if (input) {\n const result = deleteCharBeforeCursor(input)\n input.value = result.value\n setInputCursorPosition(input, result.cursorPosition)\n this.state.value = result.value\n this.state.cursorPosition = result.cursorPosition\n\n // 触发原生 input 事件\n input.dispatchEvent(new Event('input', { bubbles: true }))\n\n this.emitStateChange()\n this.emit('backspace', { deletedChar: result.deletedChar, value: this.state.value })\n }\n else {\n if (this.state.cursorPosition === 0) return\n\n const deletedChar = this.state.value.charAt(this.state.cursorPosition - 1)\n this.state.value = this.state.value.slice(0, this.state.cursorPosition - 1)\n + this.state.value.slice(this.state.cursorPosition)\n this.state.cursorPosition--\n\n this.emitStateChange()\n this.emit('backspace', { deletedChar, value: this.state.value })\n }\n\n // 车牌号智能切换\n this.autoSwitchLicensePlate()\n }\n\n /**\n * 车牌号智能切换逻辑\n * 根据当前值长度自动切换键盘布局\n * 只有 2 种布局:省份键盘(第1位)和 字母+数字混合键盘(第2-8位)\n */\n private autoSwitchLicensePlate(): void {\n // 只在车牌键盘类型时生效\n if (!this.state.type.startsWith('license-plate')) return\n\n const len = this.state.value.length\n let targetType: string | null = null\n\n if (len === 0) {\n // 第1位:省份简称\n targetType = 'license-plate-province'\n }\n else {\n // 第2-8位:字母+数字混合键盘\n // (第2位虽然只能输入字母,但显示混合键盘,用户自己知道不能输入数字)\n targetType = 'license-plate-alphanumeric'\n }\n\n // 如果需要切换\n if (targetType && this.state.type !== targetType) {\n this.switchType(targetType)\n }\n }\n\n /**\n * 处理清空\n */\n private handleClear(): void {\n const previousValue = this.state.value\n\n if (this.state.inputElement) {\n this.state.inputElement.value = ''\n this.state.inputElement.dispatchEvent(new Event('input', { bubbles: true }))\n }\n\n this.state.value = ''\n this.state.cursorPosition = 0\n\n this.emitStateChange()\n this.emit('clear', { previousValue })\n \n // 车牌号智能切换\n this.autoSwitchLicensePlate()\n }\n\n /**\n * 处理确认\n */\n private handleConfirm(): void {\n this.emit('confirm', { value: this.state.value })\n this.hide()\n }\n\n /**\n * 处理切换键盘\n */\n private handleTab(key: KeyDefinition): void {\n const targetType = key.data?.targetType as KeyboardType | string | undefined\n if (targetType) {\n this.switchType(targetType)\n }\n }\n\n /**\n * 获取按键的实际输出值\n */\n private getKeyValue(key: KeyDefinition): string {\n const value = key.value ?? key.label\n\n if (typeof value === 'string') {\n return value\n }\n\n return this.state.isUpperCase ? value.upper : value.lower\n }\n\n /**\n * 获取按键的显示文本\n */\n getKeyLabel(key: KeyDefinition): string {\n const label = key.label\n\n if (typeof label === 'string') {\n return label\n }\n\n return this.state.isUpperCase ? label.upper : label.lower\n }\n\n /**\n * 设置值\n */\n setValue(value: string): void {\n this.state.value = value\n this.state.cursorPosition = value.length\n\n if (this.state.inputElement) {\n this.state.inputElement.value = value\n setInputCursorPosition(this.state.inputElement, value.length)\n }\n\n this.emitStateChange()\n \n // 车牌号智能切换\n this.autoSwitchLicensePlate()\n }\n\n /**\n * 追加值(在光标位置插入文本)\n */\n appendValue(text: string): void {\n if (!text) return\n\n const input = this.state.inputElement\n\n if (input) {\n const result = insertTextAtCursor(input, text, this.state.maxLength)\n input.value = result.value\n setInputCursorPosition(input, result.cursorPosition)\n this.state.value = result.value\n this.state.cursorPosition = result.cursorPosition\n\n // 触发原生 input 事件\n input.dispatchEvent(new Event('input', { bubbles: true }))\n }\n else {\n if (this.state.maxLength && this.state.value.length + text.length > this.state.maxLength) {\n text = text.slice(0, this.state.maxLength - this.state.value.length)\n }\n const newValue = this.state.value.slice(0, this.state.cursorPosition)\n + text\n + this.state.value.slice(this.state.cursorPosition)\n this.state.value = newValue\n this.state.cursorPosition += text.length\n }\n\n this.emitStateChange()\n }\n\n /**\n * 设置最大长度\n */\n setMaxLength(maxLength?: number): void {\n this.state.maxLength = maxLength\n this.emitStateChange()\n }\n\n /**\n * 绑定输入框\n */\n bindInput(input: HTMLInputElement | HTMLTextAreaElement): void {\n this.state.inputElement = input\n this.state.value = input.value\n this.state.cursorPosition = getInputCursorPosition(input)\n this.emitStateChange()\n }\n\n /**\n * 解绑输入框\n */\n unbindInput(): void {\n this.state.inputElement = null\n this.emitStateChange()\n }\n\n /**\n * 发送状态变化事件\n */\n private emitStateChange(): void {\n this.emit('stateChange', { ...this.state })\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n this.hide()\n this.clear()\n this.state.inputElement = null\n }\n}\n\n/**\n * 创建键盘管理器实例\n */\nexport function createKeyboardManager(options?: KeyboardOptions): KeyboardManager {\n return new KeyboardManager(options)\n}\n","/**\n * 弹出位置管理器\n * @module managers/position-manager\n */\n\nimport type {\n BoundingRect,\n PopupPlacement,\n PopupPositionConfig,\n PopupPositionResult,\n Position,\n} from '../types'\nimport { getBoundingRect } from '../utils/dom'\nimport { getViewportInfo, isMobile } from '../utils/device'\n\n/**\n * 默认位置配置\n */\nconst DEFAULT_CONFIG: Required<PopupPositionConfig> = {\n offset: { x: 0, y: 8 },\n autoAdjust: true,\n viewportPadding: 8,\n desktopPlacement: 'bottom',\n mobilePlacement: 'bottom-sheet',\n showMask: true,\n maskClosable: true,\n animationDuration: 300,\n}\n\n/**\n * 位置管理器类\n * 计算键盘弹出层的位置,支持 PC 和移动端自适应\n */\nexport class PositionManager {\n private config: Required<PopupPositionConfig>\n\n constructor(config: PopupPositionConfig = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config }\n }\n\n /**\n * 更新配置\n */\n updateConfig(config: Partial<PopupPositionConfig>): void {\n Object.assign(this.config, config)\n }\n\n /**\n * 获取配置\n */\n getConfig(): Readonly<Required<PopupPositionConfig>> {\n return { ...this.config }\n }\n\n /**\n * 计算弹出位置\n * @param targetElement - 目标元素(如 input)\n * @param popupSize - 弹出层尺寸\n * @returns 位置计算结果\n */\n calculate(\n targetElement: HTMLElement | null,\n popupSize: { width: number; height: number },\n ): PopupPositionResult {\n const viewport = getViewportInfo()\n const isMobileDevice = isMobile()\n\n // 移动端使用 bottom-sheet\n if (isMobileDevice && this.config.mobilePlacement === 'bottom-sheet') {\n return this.calculateBottomSheet(viewport, popupSize)\n }\n\n // PC 端或移动端非 bottom-sheet\n if (!targetElement) {\n // 无目标元素,居中显示\n return this.calculateCentered(viewport, popupSize)\n }\n\n const targetRect = getBoundingRect(targetElement)\n const placement = isMobileDevice\n ? this.config.mobilePlacement\n : this.config.desktopPlacement\n\n // bottom-sheet 已经在前面处理,这里只会是 'bottom' 或 'top'\n const relativePlace = placement === 'bottom-sheet' ? 'bottom' : placement\n return this.calculateRelativeToTarget(targetRect, popupSize, viewport, relativePlace)\n }\n\n /**\n * 计算 bottom-sheet 位置(移动端从底部滑出)\n */\n private calculateBottomSheet(\n viewport: { width: number; height: number; scrollY: number; safeArea?: { bottom: number } },\n popupSize: { width: number; height: number },\n ): PopupPositionResult {\n const safeAreaBottom = viewport.safeArea?.bottom ?? 0\n\n return {\n position: {\n x: 0,\n y: viewport.height - popupSize.height - safeAreaBottom,\n },\n placement: 'bottom-sheet',\n flipped: false,\n maxHeight: viewport.height * 0.6, // 最大占屏幕高度的 60%\n maxWidth: viewport.width,\n transform: 'translateY(0)',\n }\n }\n\n /**\n * 计算居中位置\n */\n private calculateCentered(\n viewport: { width: number; height: number },\n popupSize: { width: number; height: number },\n ): PopupPositionResult {\n return {\n position: {\n x: (viewport.width - popupSize.width) / 2,\n y: (viewport.height - popupSize.height) / 2,\n },\n placement: 'bottom',\n flipped: false,\n }\n }\n\n /**\n * 计算相对于目标元素的位置\n */\n private calculateRelativeToTarget(\n targetRect: BoundingRect,\n popupSize: { width: number; height: number },\n viewport: { width: number; height: number; scrollX: number; scrollY: number },\n preferredPlacement: Exclude<PopupPlacement, 'bottom-sheet'>,\n ): PopupPositionResult {\n const { offset, viewportPadding, autoAdjust } = this.config\n\n let position: Position\n let placement = preferredPlacement\n let flipped = false\n\n // 计算 bottom 位置(左对齐)\n const bottomPosition: Position = {\n x: targetRect.x + (offset.x ?? 0),\n y: targetRect.y + targetRect.height + (offset.y ?? 8),\n }\n\n // 计算 top 位置(左对齐)\n const topPosition: Position = {\n x: targetRect.x + (offset.x ?? 0),\n y: targetRect.y - popupSize.height - (offset.y ?? 8),\n }\n\n if (preferredPlacement === 'bottom') {\n position = bottomPosition\n\n // 检查是否需要翻转到顶部\n if (autoAdjust && position.y + popupSize.height > viewport.height - viewportPadding) {\n // 检查顶部是否有足够空间\n if (topPosition.y >= viewportPadding) {\n position = topPosition\n placement = 'top'\n flipped = true\n }\n }\n }\n else {\n position = topPosition\n\n // 检查是否需要翻转到底部\n if (autoAdjust && position.y < viewportPadding) {\n // 检查底部是否有足够空间\n if (bottomPosition.y + popupSize.height <= viewport.height - viewportPadding) {\n position = bottomPosition\n placement = 'bottom'\n flipped = true\n }\n }\n }\n\n // 水平方向调整,确保不超出视口\n if (autoAdjust) {\n // 左边界检查\n if (position.x < viewportPadding) {\n position.x = viewportPadding\n }\n\n // 右边界检查\n if (position.x + popupSize.width > viewport.width - viewportPadding) {\n position.x = viewport.width - popupSize.width - viewportPadding\n }\n }\n\n // 计算最大可用高度\n const maxHeight = placement === 'bottom'\n ? viewport.height - position.y - viewportPadding\n : targetRect.y - viewportPadding\n\n return {\n position,\n placement,\n flipped,\n maxHeight: Math.max(200, maxHeight), // 最小高度 200px\n maxWidth: viewport.width - viewportPadding * 2,\n }\n }\n\n /**\n * 获取弹出层初始样式(用于动画)\n */\n getInitialStyles(placement: PopupPlacement): Partial<CSSStyleDeclaration> {\n switch (placement) {\n case 'bottom-sheet':\n return {\n transform: 'translateY(100%)',\n opacity: '1',\n }\n case 'bottom':\n return {\n transform: 'translateY(-10px)',\n opacity: '0',\n }\n case 'top':\n return {\n transform: 'translateY(10px)',\n opacity: '0',\n }\n default:\n return {\n opacity: '0',\n }\n }\n }\n\n /**\n * 获取弹出层最终样式(动画结束)\n */\n getFinalStyles(placement: PopupPlacement): Partial<CSSStyleDeclaration> {\n return {\n transform: 'translateY(0)',\n opacity: '1',\n }\n }\n\n /**\n * 获取弹出层退出样式\n */\n getExitStyles(placement: PopupPlacement): Partial<CSSStyleDeclaration> {\n return this.getInitialStyles(placement)\n }\n\n /**\n * 获取动画时长\n */\n getAnimationDuration(): number {\n return this.config.animationDuration\n }\n\n /**\n * 检查是否显示遮罩\n */\n shouldShowMask(): boolean {\n return isMobile() && this.config.showMask\n }\n\n /**\n * 检查遮罩是否可点击关闭\n */\n isMaskClosable(): boolean {\n return this.config.maskClosable\n }\n}\n\n/**\n * 创建位置管理器实例\n */\nexport function createPositionManager(config?: PopupPositionConfig): PositionManager {\n return new PositionManager(config)\n}\n","/**\n * 预设主题配置\n * @module themes/presets\n */\n\nimport type { ThemeConfig } from './types'\n\n/**\n * MIUI 小米风格主题(默认)\n * 特点:纯净、扁平、简洁、无多余装饰\n */\nexport const miuiTheme: ThemeConfig = {\n name: 'miui',\n displayName: 'MIUI',\n description: '小米风格 - 纯净简洁',\n isDark: false,\n colors: {\n background: '#f5f5f5',\n keyBackground: '#ffffff',\n keyColor: '#1a1a1a',\n keyActiveBackground: '#e8e8e8',\n fnKeyBackground: '#e0e0e0',\n fnKeyColor: '#666666',\n fnKeyActiveBackground: '#d0d0d0',\n primaryBackground: '#ff6700', // 小米橙\n primaryActiveBackground: '#e55d00',\n primaryColor: '#ffffff',\n borderColor: 'transparent',\n dividerColor: '#eeeeee',\n },\n sizes: {\n keyHeight: 46,\n keyRadius: 8,\n keyGap: 6,\n fontSize: 18,\n fnFontSize: 14,\n padding: 8,\n },\n effects: {\n keyShadow: 'none',\n keyActiveShadow: 'none',\n keyActiveScale: 0.96,\n transitionDuration: 100,\n enableBlur: false,\n blurAmount: 0,\n enableRipple: false,\n },\n}\n\n/**\n * iOS 风格主题\n * 特点:毛玻璃、圆润阴影、精致\n */\nexport const iosTheme: ThemeConfig = {\n name: 'ios',\n displayName: 'iOS',\n description: 'Apple 风格 - 精致优雅',\n isDark: false,\n colors: {\n background: '#d1d3d9',\n keyBackground: '#ffffff',\n keyColor: '#000000',\n keyActiveBackground: '#b8bac2',\n fnKeyBackground: '#a8aab4',\n fnKeyColor: '#000000',\n fnKeyActiveBackground: '#9699a3',\n primaryBackground: '#007aff',\n primaryActiveBackground: '#0062cc',\n primaryColor: '#ffffff',\n borderColor: 'transparent',\n dividerColor: '#c8cad0',\n },\n sizes: {\n keyHeight: 43,\n keyRadius: 5,\n keyGap: 6,\n fontSize: 22,\n fnFontSize: 15,\n padding: 4,\n },\n effects: {\n keyShadow: '0 1px 0 rgba(0,0,0,0.35)',\n keyActiveShadow: '0 0 0 rgba(0,0,0,0)',\n keyActiveScale: 1,\n transitionDuration: 80,\n enableBlur: true,\n blurAmount: 20,\n enableRipple: false,\n },\n}\n\n/**\n * Material Design 主题\n * 特点:深色、涟漪动效、层次感\n */\nexport const materialTheme: ThemeConfig = {\n name: 'material',\n displayName: 'Material',\n description: 'Google 风格 - 深邃现代',\n isDark: true,\n colors: {\n background: '#263238',\n keyBackground: '#37474f',\n keyColor: '#ffffff',\n keyActiveBackground: '#455a64',\n fnKeyBackground: '#455a64',\n fnKeyColor: '#b0bec5',\n fnKeyActiveBackground: '#546e7a',\n primaryBackground: '#4caf50', // Material Green\n primaryActiveBackground: '#43a047',\n primaryColor: '#ffffff',\n borderColor: 'transparent',\n dividerColor: '#37474f',\n },\n sizes: {\n keyHeight: 48,\n keyRadius: 4,\n keyGap: 4,\n fontSize: 20,\n fnFontSize: 14,\n padding: 6,\n },\n effects: {\n keyShadow: '0 1px 3px rgba(0,0,0,0.2)',\n keyActiveShadow: '0 2px 6px rgba(0,0,0,0.3)',\n keyActiveScale: 1,\n transitionDuration: 150,\n enableBlur: false,\n blurAmount: 0,\n enableRipple: true,\n },\n}\n\n/**\n * 极简主题\n * 特点:无边框、超简洁、透明感\n */\nexport const minimalTheme: ThemeConfig = {\n name: 'minimal',\n displayName: 'Minimal',\n description: '极简风格 - 轻盈透明',\n isDark: false,\n colors: {\n background: 'rgba(250, 250, 250, 0.95)',\n keyBackground: 'transparent',\n keyColor: '#333333',\n keyActiveBackground: 'rgba(0, 0, 0, 0.08)',\n fnKeyBackground: 'transparent',\n fnKeyColor: '#888888',\n fnKeyActiveBackground: 'rgba(0, 0, 0, 0.08)',\n primaryBackground: '#333333',\n primaryActiveBackground: '#000000',\n primaryColor: '#ffffff',\n borderColor: '#eeeeee',\n dividerColor: '#eeeeee',\n },\n sizes: {\n keyHeight: 44,\n keyRadius: 12,\n keyGap: 8,\n fontSize: 17,\n fnFontSize: 13,\n padding: 12,\n },\n effects: {\n keyShadow: 'none',\n keyActiveShadow: 'none',\n keyActiveScale: 0.92,\n transitionDuration: 120,\n enableBlur: true,\n blurAmount: 30,\n enableRipple: false,\n },\n}\n\n/**\n * 深色主题\n * 特点:护眼、现代、高对比\n */\nexport const darkTheme: ThemeConfig = {\n name: 'dark',\n displayName: 'Dark',\n description: '深色模式 - 护眼舒适',\n isDark: true,\n colors: {\n background: '#1c1c1e',\n keyBackground: '#3a3a3c',\n keyColor: '#ffffff',\n keyActiveBackground: '#4a4a4c',\n fnKeyBackground: '#2c2c2e',\n fnKeyColor: '#ebebf5',\n fnKeyActiveBackground: '#3c3c3e',\n primaryBackground: '#0a84ff',\n primaryActiveBackground: '#0070e0',\n primaryColor: '#ffffff',\n borderColor: '#3a3a3c',\n dividerColor: '#3a3a3c',\n },\n sizes: {\n keyHeight: 45,\n keyRadius: 8,\n keyGap: 6,\n fontSize: 18,\n fnFontSize: 14,\n padding: 8,\n },\n effects: {\n keyShadow: '0 1px 2px rgba(0,0,0,0.4)',\n keyActiveShadow: '0 0 8px rgba(10,132,255,0.3)',\n keyActiveScale: 0.97,\n transitionDuration: 100,\n enableBlur: true,\n blurAmount: 20,\n enableRipple: false,\n },\n}\n\n/**\n * 所有预设主题\n */\nexport const presetThemes: Record<string, ThemeConfig> = {\n miui: miuiTheme,\n ios: iosTheme,\n material: materialTheme,\n minimal: minimalTheme,\n dark: darkTheme,\n}\n\n/**\n * 默认主题\n */\nexport const defaultTheme = miuiTheme\n","/**\n * 主题管理模块\n * @module themes\n */\n\nimport type { ThemeConfig, ThemeCSSVariables, ThemeName } from './types'\nimport { defaultTheme, presetThemes } from './presets'\n\nexport * from './types'\nexport * from './presets'\n\n/**\n * 自定义主题存储\n */\nconst customThemes: Map<string, ThemeConfig> = new Map()\n\n/**\n * 当前激活的主题\n */\nlet currentTheme: ThemeConfig = defaultTheme\n\n/**\n * 获取主题配置\n * @param name - 主题名称\n * @returns 主题配置,如果不存在则返回默认主题\n */\nexport function getTheme(name: ThemeName | string): ThemeConfig {\n return customThemes.get(name) || presetThemes[name] || defaultTheme\n}\n\n/**\n * 注册自定义主题\n * @param theme - 主题配置\n */\nexport function registerTheme(theme: ThemeConfig): void {\n customThemes.set(theme.name, theme)\n}\n\n/**\n * 获取所有可用主题\n * @returns 主题名称列表\n */\nexport function getAvailableThemes(): string[] {\n return [...Object.keys(presetThemes), ...customThemes.keys()]\n}\n\n/**\n * 获取所有主题配置\n * @returns 主题配置列表\n */\nexport function getAllThemes(): ThemeConfig[] {\n return [\n ...Object.values(presetThemes),\n ...customThemes.values(),\n ]\n}\n\n/**\n * 设置当前主题\n * @param name - 主题名称\n */\nexport function setCurrentTheme(name: ThemeName | string): ThemeConfig {\n currentTheme = getTheme(name)\n return currentTheme\n}\n\n/**\n * 获取当前主题\n */\nexport function getCurrentTheme(): ThemeConfig {\n return currentTheme\n}\n\n/**\n * 将主题配置转换为 CSS 变量\n * @param theme - 主题配置\n * @returns CSS 变量对象\n */\nexport function themeToCSS(theme: ThemeConfig): ThemeCSSVariables {\n return {\n '--keyboard-bg': theme.colors.background,\n '--keyboard-key-bg': theme.colors.keyBackground,\n '--keyboard-key-color': theme.colors.keyColor,\n '--keyboard-key-active-bg': theme.colors.keyActiveBackground,\n '--keyboard-fn-key-bg': theme.colors.fnKeyBackground,\n '--keyboard-fn-key-color': theme.colors.fnKeyColor,\n '--keyboard-fn-key-active-bg': theme.colors.fnKeyActiveBackground,\n '--keyboard-primary-bg': theme.colors.primaryBackground,\n '--keyboard-primary-active-bg': theme.colors.primaryActiveBackground,\n '--keyboard-primary-color': theme.colors.primaryColor,\n '--keyboard-key-height': `${theme.sizes.keyHeight}px`,\n '--keyboard-key-radius': `${theme.sizes.keyRadius}px`,\n '--keyboard-key-gap': `${theme.sizes.keyGap}px`,\n '--keyboard-font-size': `${theme.sizes.fontSize}px`,\n '--keyboard-fn-font-size': `${theme.sizes.fnFontSize}px`,\n '--keyboard-padding': `${theme.sizes.padding}px`,\n '--keyboard-key-shadow': theme.effects.keyShadow,\n '--keyboard-transition-duration': `${theme.effects.transitionDuration}ms`,\n '--keyboard-border-color': theme.colors.borderColor,\n '--keyboard-divider-color': theme.colors.dividerColor,\n }\n}\n\n/**\n * 将 CSS 变量应用到元素\n * @param element - 目标元素\n * @param theme - 主题配置\n */\nexport function applyTheme(element: HTMLElement, theme: ThemeConfig): void {\n const cssVars = themeToCSS(theme)\n Object.entries(cssVars).forEach(([key, value]) => {\n if (value) {\n element.style.setProperty(key, value)\n }\n })\n\n // 添加主题类名\n element.classList.remove('keyboard-theme-light', 'keyboard-theme-dark')\n element.classList.add(theme.isDark ? 'keyboard-theme-dark' : 'keyboard-theme-light')\n element.dataset.theme = theme.name\n}\n\n/**\n * 生成主题的内联样式字符串\n * @param theme - 主题配置\n * @returns 内联样式字符串\n */\nexport function generateThemeStyle(theme: ThemeConfig): string {\n const cssVars = themeToCSS(theme)\n return Object.entries(cssVars)\n .filter(([, value]) => value)\n .map(([key, value]) => `${key}: ${value}`)\n .join('; ')\n}\n\n/**\n * 合并主题配置\n * @param base - 基础主题\n * @param overrides - 覆盖配置\n * @returns 合并后的主题\n */\nexport function mergeTheme(\n base: ThemeConfig,\n overrides: Partial<ThemeConfig>,\n): ThemeConfig {\n return {\n ...base,\n ...overrides,\n colors: { ...base.colors, ...overrides.colors },\n sizes: { ...base.sizes, ...overrides.sizes },\n effects: { ...base.effects, ...overrides.effects },\n }\n}\n\n/**\n * 创建自定义主题\n * @param name - 主题名称\n * @param baseTheme - 基础主题名称\n * @param customization - 自定义配置\n */\nexport function createTheme(\n name: string,\n baseTheme: ThemeName | string,\n customization: Partial<Omit<ThemeConfig, 'name'>>,\n): ThemeConfig {\n const base = getTheme(baseTheme)\n const theme = mergeTheme(base, {\n ...customization,\n name,\n })\n registerTheme(theme)\n return theme\n}\n","/**\n * 键盘 DOM 渲染器\n * 框架无关的键盘渲染器,用于原生 JS 项目\n * @module managers/keyboard-renderer\n */\n\nimport type {\n KeyboardConfig,\n KeyboardOptions,\n KeyboardType,\n KeyDefinition,\n PopupPositionConfig,\n} from '../types'\nimport type { ThemeConfig } from '../themes/types'\nimport { KeyboardManager } from './keyboard-manager'\nimport { PositionManager } from './position-manager'\nimport { getTheme, themeToCSS, defaultTheme } from '../themes'\nimport { isMobile } from '../utils/device'\nimport { onClickOutside } from '../utils/dom'\n\n/**\n * 渲染器配置\n */\nexport interface KeyboardRendererOptions extends KeyboardOptions {\n /** 挂载容器(默认 document.body) */\n container?: HTMLElement\n /** 主题名称或主题配置 */\n theme?: string | ThemeConfig\n /** 弹出层配置 */\n position?: PopupPositionConfig\n /** 点击外部关闭 */\n closeOnClickOutside?: boolean\n /** 确认回调 */\n onConfirm?: (value: string) => void\n /** 输入变化回调 */\n onInput?: (value: string) => void\n /** 关闭回调 */\n onClose?: () => void\n}\n\n/**\n * 键盘 DOM 渲染器\n * 提供完整的键盘 DOM 创建、事件绑定、位置管理\n */\nexport class KeyboardRenderer {\n /** 键盘管理器 */\n readonly manager: KeyboardManager\n\n /** 位置管理器 */\n private positionManager: PositionManager\n\n /** 配置 */\n private options: KeyboardRendererOptions\n\n /** DOM 元素 */\n private rootEl: HTMLElement | null = null\n private maskEl: HTMLElement | null = null\n private keyboardEl: HTMLElement | null = null\n\n /** 挂载容器 */\n private container: HTMLElement\n\n /** 主题配置 */\n private theme: ThemeConfig\n\n /** 当前目标元素 */\n private targetEl: HTMLInputElement | HTMLTextAreaElement | null = null\n\n /** 清理函数 */\n private cleanupFns: Array<() => void> = []\n\n /** 是否已销毁 */\n private destroyed = false\n\n constructor(options: KeyboardRendererOptions = {}) {\n this.options = options\n this.container = options.container || document.body\n this.manager = new KeyboardManager(options)\n this.positionManager = new PositionManager(options.position)\n\n // 解析主题\n if (typeof options.theme === 'string') {\n this.theme = getTheme(options.theme)\n } else if (options.theme) {\n this.theme = options.theme\n } else {\n this.theme = defaultTheme\n }\n\n // 绑定事件\n this.setupEvents()\n }\n\n /**\n * 设置事件监听\n */\n private setupEvents(): void {\n this.manager.on('stateChange', (state) => {\n if (state.visible) {\n this.render()\n } else {\n this.unmount()\n }\n })\n\n this.manager.on('input', ({ value }) => {\n this.options.onInput?.(value)\n })\n\n this.manager.on('confirm', ({ value }) => {\n this.options.onConfirm?.(value)\n })\n\n this.manager.on('switch', () => {\n if (this.manager.getState().visible) {\n this.render()\n }\n })\n\n this.manager.on('shift', () => {\n if (this.manager.getState().visible) {\n this.render()\n }\n })\n }\n\n /**\n * 打开键盘\n */\n open(target?: HTMLInputElement | HTMLTextAreaElement): void {\n this.targetEl = target ?? null\n this.manager.show(target)\n }\n\n /**\n * 关闭键盘\n */\n close(): void {\n this.manager.hide()\n this.options.onClose?.()\n }\n\n /**\n * 切换键盘类型\n */\n switchType(type: KeyboardType | string): void {\n this.manager.switchType(type)\n }\n\n /**\n * 设置主题\n */\n setTheme(theme: string | ThemeConfig): void {\n if (typeof theme === 'string') {\n this.theme = getTheme(theme)\n } else {\n this.theme = theme\n }\n if (this.manager.getState().visible) {\n this.render()\n }\n }\n\n /**\n * 获取当前值\n */\n getValue(): string {\n return this.manager.getState().value\n }\n\n /**\n * 设置值\n */\n setValue(value: string): void {\n this.manager.setValue(value)\n }\n\n /**\n * 渲染键盘 DOM\n */\n private render(): void {\n const layout = this.manager.getLayout()\n if (!layout) return\n\n // 清理旧的 DOM\n this.unmount()\n\n // 创建根元素\n this.rootEl = document.createElement('div')\n this.rootEl.className = 'lk-renderer-root'\n\n const isMobileDevice = isMobile()\n\n // 移动端创建遮罩\n if (isMobileDevice) {\n this.maskEl = document.createElement('div')\n this.maskEl.className = 'lk-mask'\n this.maskEl.addEventListener('click', () => this.close())\n this.rootEl.appendChild(this.maskEl)\n }\n\n // 创建键盘容器\n this.keyboardEl = document.createElement('div')\n this.keyboardEl.className = `lk-popup lk-popup--${isMobileDevice ? 'mobile' : 'desktop'}`\n\n // 应用主题 CSS 变量\n const cssVars = themeToCSS(this.theme)\n Object.entries(cssVars).forEach(([key, value]) => {\n if (value) {\n this.keyboardEl!.style.setProperty(key, value)\n }\n })\n\n // 渲染键盘内容\n const contentEl = this.renderKeyboard(layout)\n this.keyboardEl.appendChild(contentEl)\n\n this.rootEl.appendChild(this.keyboardEl)\n this.container.appendChild(this.rootEl)\n\n // 计算位置\n if (!isMobileDevice && this.targetEl) {\n const rect = this.keyboardEl.getBoundingClientRect()\n const result = this.positionManager.calculate(this.targetEl, {\n width: rect.width,\n height: rect.height,\n })\n this.keyboardEl.style.position = 'fixed'\n this.keyboardEl.style.left = `${result.position.x}px`\n this.keyboardEl.style.top = `${result.position.y}px`\n this.keyboardEl.style.zIndex = '10000'\n } else if (isMobileDevice) {\n this.keyboardEl.style.position = 'fixed'\n this.keyboardEl.style.left = '0'\n this.keyboardEl.style.right = '0'\n this.keyboardEl.style.bottom = '0'\n this.keyboardEl.style.zIndex = '10000'\n }\n\n // 添加动画类\n requestAnimationFrame(() => {\n this.keyboardEl?.classList.add('lk-popup--visible')\n this.maskEl?.classList.add('lk-mask--visible')\n })\n\n // 点击外部关闭\n if (this.options.closeOnClickOutside !== false && this.keyboardEl) {\n const cleanup = onClickOutside(this.keyboardEl, (event) => {\n if (this.targetEl && this.targetEl.contains(event.target as Node)) return\n this.close()\n })\n this.cleanupFns.push(cleanup)\n }\n\n // 注入样式\n this.injectStyles()\n }\n\n /**\n * 渲染键盘内容\n */\n private renderKeyboard(layout: KeyboardConfig): HTMLElement {\n const el = document.createElement('div')\n el.className = 'lk-keyboard'\n\n const state = this.manager.getState()\n\n layout.rows.forEach((row) => {\n const rowEl = document.createElement('div')\n rowEl.className = `lk-row ${row.className || ''}`\n\n const isNumpad = row.className === 'numpad-row'\n\n row.keys.forEach((key) => {\n const wrapperEl = document.createElement('div')\n wrapperEl.className = 'lk-key-wrapper'\n\n if (isNumpad) {\n wrapperEl.style.flex = String(key.width ?? 1)\n } else if (key.width) {\n const baseW = 36\n const gap = this.theme.sizes?.keyGap ?? 6\n const w = baseW * key.width + (key.width - 1) * gap\n wrapperEl.style.width = `${w}px`\n }\n\n const btnEl = document.createElement('button')\n btnEl.type = 'button'\n btnEl.className = this.getKeyClass(key, state.isUpperCase)\n\n if (key.disabled) {\n btnEl.disabled = true\n }\n\n // 内容\n if (key.icon) {\n btnEl.innerHTML = key.icon\n } else {\n const label = typeof key.label === 'string'\n ? key.label\n : state.isUpperCase ? key.label.upper : key.label.lower\n btnEl.textContent = label\n }\n\n // 事件\n const handler = (e: Event) => {\n e.preventDefault()\n e.stopPropagation()\n if (!key.disabled) {\n this.manager.handleKey(key)\n }\n }\n\n btnEl.addEventListener('mousedown', handler)\n btnEl.addEventListener('touchstart', handler, { passive: false })\n\n wrapperEl.appendChild(btnEl)\n rowEl.appendChild(wrapperEl)\n })\n\n el.appendChild(rowEl)\n })\n\n return el\n }\n\n /**\n * 获取按键 CSS 类名\n */\n private getKeyClass(key: KeyDefinition, isUpperCase: boolean): string {\n const classes = ['lk-key', `lk-key--${key.type}`]\n if (key.className) classes.push(key.className)\n if (key.disabled) classes.push('lk-key--disabled')\n if (key.type === 'shift' && isUpperCase) classes.push('lk-key--active')\n return classes.join(' ')\n }\n\n /**\n * 卸载 DOM\n */\n private unmount(): void {\n this.cleanupFns.forEach(fn => fn())\n this.cleanupFns = []\n\n if (this.rootEl && this.rootEl.parentNode) {\n this.rootEl.parentNode.removeChild(this.rootEl)\n }\n this.rootEl = null\n this.maskEl = null\n this.keyboardEl = null\n }\n\n /**\n * 注入样式(单例)\n */\n private injectStyles(): void {\n if (document.getElementById('lk-renderer-styles')) return\n\n const style = document.createElement('style')\n style.id = 'lk-renderer-styles'\n style.textContent = `\n .lk-renderer-root { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }\n .lk-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 9999; opacity: 0; transition: opacity 0.3s ease; }\n .lk-mask--visible { opacity: 1; }\n .lk-popup { background: var(--keyboard-bg, #d1d5db); box-shadow: 0 -2px 16px rgba(0,0,0,0.15); overflow: hidden; transform: translateY(20px); opacity: 0; transition: transform 0.3s cubic-bezier(0.4,0,0.2,1), opacity 0.2s ease; }\n .lk-popup--visible { transform: translateY(0); opacity: 1; }\n .lk-popup--desktop { border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.18), 0 2px 8px rgba(0,0,0,0.1); min-width: 320px; }\n .lk-popup--mobile { border-top-left-radius: 16px; border-top-right-radius: 16px; padding-bottom: env(safe-area-inset-bottom, 0); }\n .lk-keyboard { display: flex; flex-direction: column; gap: var(--keyboard-key-gap, 6px); padding: var(--keyboard-padding, 6px); user-select: none; -webkit-user-select: none; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; }\n .lk-row { display: flex; justify-content: center; gap: var(--keyboard-key-gap, 6px); padding: 0 2px; }\n .lk-row.numpad-row { justify-content: stretch; }\n .lk-row.numpad-row .lk-key-wrapper { flex: 1; }\n .lk-key-wrapper { position: relative; display: inline-flex; }\n .lk-key { display: inline-flex; align-items: center; justify-content: center; height: var(--keyboard-key-height, 42px); min-width: 32px; width: 100%; padding: 0 6px; border: none; border-radius: var(--keyboard-key-radius, 6px); background: var(--keyboard-key-bg, #fff); color: var(--keyboard-key-color, #333); font-size: var(--keyboard-font-size, 16px); font-weight: 500; cursor: pointer; touch-action: manipulation; box-shadow: var(--keyboard-key-shadow, 0 1px 3px rgba(0,0,0,0.1)); transition: background-color 0.1s, transform 0.1s; }\n .lk-key:active { background: var(--keyboard-key-active-bg, #e0e0e0); transform: scale(0.95); }\n .lk-key--disabled { opacity: 0.4; cursor: not-allowed; }\n .lk-key--disabled:active { transform: none; background: var(--keyboard-key-bg, #fff); }\n .lk-key--backspace, .lk-key--shift, .lk-key--tab, .lk-key--clear, .lk-key--close { background: var(--keyboard-fn-key-bg, #d4d6dc); color: var(--keyboard-fn-key-color, #333); font-size: var(--keyboard-fn-font-size, 14px); }\n .lk-key--backspace:active, .lk-key--shift:active, .lk-key--tab:active, .lk-key--clear:active, .lk-key--close:active { background: var(--keyboard-fn-key-active-bg, #b8bac0); }\n .lk-key--active { background: var(--keyboard-key-active-bg, #007aff) !important; color: #fff !important; }\n .lk-key--done, .lk-key--enter { background: var(--keyboard-primary-bg, #007aff); color: var(--keyboard-primary-color, #fff); font-size: var(--keyboard-fn-font-size, 14px); }\n .lk-key--done:active, .lk-key--enter:active { background: var(--keyboard-primary-active-bg, #0062cc); }\n .lk-key--space { background: var(--keyboard-key-bg, #fff); }\n .lk-key svg { pointer-events: none; }\n `\n document.head.appendChild(style)\n }\n\n /**\n * 绑定到输入框(聚焦时自动打开键盘)\n */\n bindInput(input: HTMLInputElement | HTMLTextAreaElement): () => void {\n const handleFocus = () => this.open(input)\n input.addEventListener('focus', handleFocus)\n\n // 阻止移动端原生键盘\n input.setAttribute('readonly', 'readonly')\n input.style.caretColor = 'transparent'\n\n return () => {\n input.removeEventListener('focus', handleFocus)\n input.removeAttribute('readonly')\n input.style.caretColor = ''\n }\n }\n\n /**\n * 销毁渲染器\n */\n destroy(): void {\n if (this.destroyed) return\n this.destroyed = true\n this.unmount()\n this.manager.destroy()\n\n // 移除样式\n const styleEl = document.getElementById('lk-renderer-styles')\n if (styleEl) styleEl.remove()\n }\n}\n\n/**\n * 创建键盘渲染器\n */\nexport function createKeyboardRenderer(options?: KeyboardRendererOptions): KeyboardRenderer {\n return new KeyboardRenderer(options)\n}\n","/**\n * 随机工具函数\n * @module utils/random\n */\n\nimport type { KeyboardConfig, KeyboardRow, KeyDefinition } from '../types'\n\n/**\n * Fisher-Yates 洗牌算法\n * @param array - 要洗牌的数组\n * @returns 洗牌后的新数组\n */\nexport function shuffleArray<T>(array: T[]): T[] {\n const result = [...array]\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[result[i], result[j]] = [result[j], result[i]]\n }\n return result\n}\n\n/**\n * 生成随机数字数组 (0-9)\n */\nexport function getRandomNumbers(): string[] {\n return shuffleArray(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])\n}\n\n/**\n * 生成随机字母数组 (A-Z)\n */\nexport function getRandomLetters(): string[] {\n const letters = Array.from({ length: 26 }, (_, i) =>\n String.fromCharCode(65 + i),\n )\n return shuffleArray(letters)\n}\n\n/**\n * 生成随机数字+字母数组\n */\nexport function getRandomAlphanumeric(): string[] {\n const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n const letters = Array.from({ length: 26 }, (_, i) =>\n String.fromCharCode(65 + i),\n )\n return shuffleArray([...numbers, ...letters])\n}\n\n/**\n * 创建字符按键\n */\nfunction createCharKey(char: string, index: number): KeyDefinition {\n return {\n id: `random-${char}-${index}`,\n type: 'char',\n label: char,\n value: char,\n className: 'key-random',\n }\n}\n\n/**\n * 将字符数组分成行\n */\nfunction chunkArray<T>(array: T[], chunkSize: number): T[][] {\n const chunks: T[][] = []\n for (let i = 0; i < array.length; i += chunkSize) {\n chunks.push(array.slice(i, i + chunkSize))\n }\n return chunks\n}\n\n/**\n * 生成随机数字键盘布局\n * @param options - 配置选项\n */\nexport function createRandomNumberLayout(options?: {\n /** 每行按键数 */\n keysPerRow?: number\n /** 是否包含退格键 */\n includeBackspace?: boolean\n /** 是否包含完成键 */\n includeDone?: boolean\n /** 是否包含清空键 */\n includeClear?: boolean\n}): KeyboardConfig {\n const {\n keysPerRow = 3,\n includeBackspace = true,\n includeDone = true,\n includeClear = false,\n } = options || {}\n\n const randomNumbers = getRandomNumbers()\n const numberKeys = randomNumbers.map((n, i) => createCharKey(n, i))\n const chunks = chunkArray(numberKeys, keysPerRow)\n\n const rows: KeyboardRow[] = chunks.map((keys, index) => ({\n className: 'numpad-row',\n keys,\n }))\n\n // 添加功能键行\n const fnKeys: KeyDefinition[] = []\n\n if (includeClear) {\n fnKeys.push({\n id: 'clear',\n type: 'clear',\n label: '清空',\n className: 'key-clear key-fn',\n })\n }\n\n if (includeBackspace) {\n fnKeys.push({\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n className: 'key-backspace key-fn',\n })\n }\n\n if (includeDone) {\n fnKeys.push({\n id: 'done',\n type: 'done',\n label: '确定',\n className: 'key-done key-fn',\n })\n }\n\n if (fnKeys.length > 0) {\n rows.push({\n className: 'numpad-row',\n keys: fnKeys,\n })\n }\n\n return {\n type: 'custom',\n name: '随机数字键盘',\n supportShift: false,\n rows,\n data: {\n isRandom: true,\n randomType: 'number',\n },\n }\n}\n\n/**\n * 生成4x3随机数字键盘(密码输入常用)\n */\nexport function createRandomPinLayout(options?: {\n /** 是否包含退格键 */\n includeBackspace?: boolean\n /** 是否包含完成键 */\n includeDone?: boolean\n}): KeyboardConfig {\n const { includeBackspace = true, includeDone = true } = options || {}\n\n const randomNumbers = getRandomNumbers()\n\n // 前9个数字 (3x3)\n const rows: KeyboardRow[] = [\n {\n className: 'numpad-row',\n keys: randomNumbers.slice(0, 3).map((n, i) => createCharKey(n, i)),\n },\n {\n className: 'numpad-row',\n keys: randomNumbers.slice(3, 6).map((n, i) => createCharKey(n, i + 3)),\n },\n {\n className: 'numpad-row',\n keys: randomNumbers.slice(6, 9).map((n, i) => createCharKey(n, i + 6)),\n },\n ]\n\n // 最后一行:功能键 + 0 + 功能键\n const lastRow: KeyDefinition[] = []\n\n if (includeBackspace) {\n lastRow.push({\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n className: 'key-backspace key-fn',\n })\n } else {\n lastRow.push({\n id: 'empty-1',\n type: 'char',\n label: '',\n value: '',\n disabled: true,\n className: 'key-placeholder',\n })\n }\n\n lastRow.push(createCharKey(randomNumbers[9], 9))\n\n if (includeDone) {\n lastRow.push({\n id: 'done',\n type: 'done',\n label: '确定',\n className: 'key-done key-fn',\n })\n } else {\n lastRow.push({\n id: 'empty-2',\n type: 'char',\n label: '',\n value: '',\n disabled: true,\n className: 'key-placeholder',\n })\n }\n\n rows.push({\n className: 'numpad-row',\n keys: lastRow,\n })\n\n return {\n type: 'custom',\n name: '随机PIN键盘',\n supportShift: false,\n rows,\n data: {\n isRandom: true,\n randomType: 'pin',\n },\n }\n}\n\n/**\n * 生成随机字母键盘布局\n * 默认使用 QWERTY 风格行分布 (10/9/7),看起来像真实键盘\n */\nexport function createRandomLetterLayout(options?: {\n /** 是否大写 */\n uppercase?: boolean\n /** 行分布,默认 [10, 9, 7] 模拟 QWERTY 布局 */\n rowDistribution?: number[]\n}): KeyboardConfig {\n const { uppercase = true, rowDistribution = [10, 9, 7] } = options || {}\n\n let randomLetters = getRandomLetters()\n if (!uppercase) {\n randomLetters = randomLetters.map((l) => l.toLowerCase())\n }\n\n const letterKeys = randomLetters.map((l, i) => createCharKey(l, i))\n\n // 按行分布切割\n const rows: KeyboardRow[] = []\n let offset = 0\n for (const count of rowDistribution) {\n rows.push({\n className: 'numpad-row',\n keys: letterKeys.slice(offset, offset + count),\n })\n offset += count\n }\n // 剩余字母放最后一行\n if (offset < letterKeys.length) {\n rows.push({\n className: 'numpad-row',\n keys: letterKeys.slice(offset),\n })\n }\n\n // 功能键行\n rows.push({\n className: 'numpad-row',\n keys: [\n {\n id: 'clear',\n type: 'clear',\n label: '清空',\n className: 'key-clear key-fn',\n },\n {\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n className: 'key-backspace key-fn',\n },\n {\n id: 'done',\n type: 'done',\n label: '确定',\n className: 'key-done key-fn',\n },\n ],\n })\n\n return {\n type: 'custom',\n name: '随机字母键盘',\n supportShift: false,\n rows,\n data: {\n isRandom: true,\n randomType: 'letter',\n },\n }\n}\n\n/**\n * 生成混合随机键盘(数字+字母)\n * 默认使用 QWERTY 风格行分布 (10/10/9/7),看起来像真实键盘\n */\nexport function createRandomMixedLayout(options?: {\n /** 行分布,默认 [10, 10, 9, 7] */\n rowDistribution?: number[]\n}): KeyboardConfig {\n const { rowDistribution = [10, 10, 9, 7] } = options || {}\n\n const randomChars = getRandomAlphanumeric()\n const charKeys = randomChars.map((c, i) => createCharKey(c, i))\n\n // 按行分布切割\n const rows: KeyboardRow[] = []\n let offset = 0\n for (const count of rowDistribution) {\n if (offset >= charKeys.length) break\n rows.push({\n className: 'numpad-row',\n keys: charKeys.slice(offset, offset + count),\n })\n offset += count\n }\n // 剩余字符放最后一行\n if (offset < charKeys.length) {\n rows.push({\n className: 'numpad-row',\n keys: charKeys.slice(offset),\n })\n }\n\n // 功能键行\n rows.push({\n className: 'numpad-row',\n keys: [\n {\n id: 'clear',\n type: 'clear',\n label: '清空',\n className: 'key-clear key-fn',\n },\n {\n id: 'backspace',\n type: 'backspace',\n label: '⌫',\n className: 'key-backspace key-fn',\n },\n {\n id: 'done',\n type: 'done',\n label: '确定',\n className: 'key-done key-fn',\n },\n ],\n })\n\n return {\n type: 'custom',\n name: '随机混合键盘',\n supportShift: false,\n rows,\n data: {\n isRandom: true,\n randomType: 'mixed',\n },\n }\n}\n\n/**\n * 刷新随机键盘布局\n * @param layout - 现有布局\n * @returns 新的随机布局\n */\nexport function refreshRandomLayout(layout: KeyboardConfig): KeyboardConfig {\n const randomType = layout.data?.randomType as string | undefined\n\n switch (randomType) {\n case 'number':\n return createRandomNumberLayout()\n case 'pin':\n return createRandomPinLayout()\n case 'letter':\n return createRandomLetterLayout()\n case 'mixed':\n return createRandomMixedLayout()\n default:\n return layout\n }\n}\n","/**\n * 输入格式化工具\n * @module utils/formatters\n */\n\n/**\n * 格式化手机号 (3-4-4)\n * @example formatPhone('13812345678') => '138 1234 5678'\n */\nexport function formatPhone(value: string): string {\n const digits = value.replace(/\\D/g, '').slice(0, 11)\n if (digits.length <= 3) return digits\n if (digits.length <= 7) return `${digits.slice(0, 3)} ${digits.slice(3)}`\n return `${digits.slice(0, 3)} ${digits.slice(3, 7)} ${digits.slice(7)}`\n}\n\n/**\n * 格式化银行卡号 (4-4-4-4-3)\n * @example formatBankCard('6222021234567890123') => '6222 0212 3456 7890 123'\n */\nexport function formatBankCard(value: string): string {\n const digits = value.replace(/\\D/g, '').slice(0, 19)\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ')\n}\n\n/**\n * 格式化金额(限制小数位数)\n * @param value - 输入值\n * @param decimalPlaces - 小数位数,默认 2\n */\nexport function formatAmount(value: string, decimalPlaces: number = 2): string {\n // 移除非数字和小数点\n let result = value.replace(/[^\\d.]/g, '')\n\n // 只保留第一个小数点\n const parts = result.split('.')\n if (parts.length > 2) {\n result = parts[0] + '.' + parts.slice(1).join('')\n }\n\n // 限制小数位数\n if (parts.length === 2 && parts[1].length > decimalPlaces) {\n result = parts[0] + '.' + parts[1].slice(0, decimalPlaces)\n }\n\n // 移除前导零(保留 0.xx 格式)\n if (result.length > 1 && result.startsWith('0') && result[1] !== '.') {\n result = result.replace(/^0+/, '') || '0'\n }\n\n return result\n}\n\n/**\n * 格式化身份证号(自动大写 X)\n */\nexport function formatIdCard(value: string): string {\n return value\n .replace(/[^\\dXx]/g, '')\n .slice(0, 18)\n .toUpperCase()\n}\n\n/**\n * 格式化车牌号\n */\nexport function formatLicensePlate(value: string): string {\n return value.toUpperCase().slice(0, 8)\n}\n\n/**\n * 格式化验证码(纯数字)\n * @param value - 输入值\n * @param length - 验证码长度,默认 6\n */\nexport function formatVerifyCode(value: string, length: number = 6): string {\n return value.replace(/\\D/g, '').slice(0, length)\n}\n\n/**\n * 通用格式化器注册表\n */\nexport type FormatterFunction = (value: string) => string\n\nconst formatters: Map<string, FormatterFunction> = new Map([\n ['phone', formatPhone],\n ['bankcard', formatBankCard],\n ['idcard', formatIdCard],\n ['license-plate', formatLicensePlate],\n ['verifycode', formatVerifyCode],\n])\n\n/**\n * 注册自定义格式化器\n */\nexport function registerFormatter(name: string, formatter: FormatterFunction): void {\n formatters.set(name, formatter)\n}\n\n/**\n * 获取格式化器\n */\nexport function getFormatter(name: string): FormatterFunction | undefined {\n return formatters.get(name)\n}\n\n/**\n * 应用格式化\n */\nexport function applyFormatter(name: string, value: string): string {\n const formatter = formatters.get(name)\n return formatter ? formatter(value) : value\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["deletedChar","newValue","document"],"sources":["../src/icons.ts","../src/layouts/amount.ts","../src/layouts/bankcard.ts","../src/layouts/email.ts","../src/layouts/idcard.ts","../src/layouts/license-plate.ts","../src/layouts/number.ts","../src/layouts/phone.ts","../src/layouts/punct.ts","../src/layouts/qwerty.ts","../src/layouts/search.ts","../src/layouts/symbol.ts","../src/layouts/url.ts","../src/layouts/verifycode.ts","../src/layouts/index.ts","../src/utils/device.ts","../src/utils/dom.ts","../src/utils/event-emitter.ts","../src/managers/keyboard-manager.ts","../src/themes/presets.ts","../src/themes/index.ts","../src/managers/position-manager.ts","../src/managers/keyboard-renderer.ts","../src/utils/formatters.ts","../src/utils/random.ts"],"sourcesContent":["/**\r\n * 键盘图标 SVG\r\n * 使用 Lucide 图标的 SVG 路径\r\n * @module icons\r\n */\r\n\r\n/**\r\n * 删除图标 (Delete/Backspace)\r\n */\r\nexport const ICON_DELETE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z\"/><path d=\"m12 9 6 6\"/><path d=\"m18 9-6 6\"/></svg>`\r\n\r\n/**\r\n * 清空图标 (X Circle)\r\n */\r\nexport const ICON_CLEAR = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9-6 6\"/><path d=\"m9 9 6 6\"/></svg>`\r\n\r\n/**\r\n * 关闭图标 (X)\r\n */\r\nexport const ICON_CLOSE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`\r\n\r\n/**\r\n * 确认图标 (Check)\r\n */\r\nexport const ICON_CHECK = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>`\r\n\r\n/**\r\n * 换行图标 (Corner Down Left)\r\n */\r\nexport const ICON_ENTER = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 10 4 15 9 20\"/><path d=\"M20 4v7a4 4 0 0 1-4 4H4\"/></svg>`\r\n\r\n/**\r\n * Shift 图标 (Arrow Big Up)\r\n */\r\nexport const ICON_SHIFT = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 18v-6H5l7-7 7 7h-4v6H9z\"/></svg>`\r\n\r\n/**\r\n * 空格图标 (Space)\r\n */\r\nexport const ICON_SPACE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1\"/></svg>`\r\n\r\n/**\r\n * 键盘图标 (Keyboard)\r\n */\r\nexport const ICON_KEYBOARD = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"/><path d=\"M6 8h.001\"/><path d=\"M10 8h.001\"/><path d=\"M14 8h.001\"/><path d=\"M18 8h.001\"/><path d=\"M8 12h.001\"/><path d=\"M12 12h.001\"/><path d=\"M16 12h.001\"/><path d=\"M7 16h10\"/></svg>`\r\n\r\n/**\r\n * 语音图标 (Mic)\r\n */\r\nexport const ICON_VOICE = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/><path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>`\r\n\r\n/**\r\n * 所有图标映射\r\n */\r\nexport const ICONS = {\r\n delete: ICON_DELETE,\r\n clear: ICON_CLEAR,\r\n close: ICON_CLOSE,\r\n check: ICON_CHECK,\r\n enter: ICON_ENTER,\r\n shift: ICON_SHIFT,\r\n space: ICON_SPACE,\r\n keyboard: ICON_KEYBOARD,\r\n voice: ICON_VOICE,\r\n} as const\r\n\r\n/** IconName - 图标名称类型 */\r\nexport type IconName = keyof typeof ICONS\r\n","/**\r\n * 金额键盘布局\r\n * @module layouts/amount\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `amount-${num}`,\r\n type: 'char',\r\n label: num,\r\n value: num,\r\n className: 'key-num',\r\n }\r\n}\r\n\r\n/**\r\n * 金额键盘配置 - 紧凑4x4布局\r\n */\r\nexport const amountLayout: KeyboardConfig = {\r\n type: 'amount',\r\n name: '金额键盘',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'double-zero',\r\n type: 'char',\r\n label: '00',\r\n value: '00',\r\n className: 'key-num',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'decimal',\r\n type: 'char',\r\n label: '.',\r\n value: '.',\r\n className: 'key-num',\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n inputType: 'amount',\r\n decimalPlaces: 2,\r\n },\r\n}\r\n\r\n/**\r\n * 简洁金额键盘 - 紧凑4x4布局\r\n */\r\nexport const amountSimpleLayout: KeyboardConfig = {\r\n type: 'amount-simple',\r\n name: '金额键盘',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'close',\r\n type: 'close',\r\n label: '关闭',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'decimal',\r\n type: 'char',\r\n label: '.',\r\n value: '.',\r\n className: 'key-num',\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n inputType: 'amount',\r\n decimalPlaces: 2,\r\n },\r\n}\r\n","/**\r\n * 银行卡键盘布局\r\n * @module layouts/bankcard\r\n */\r\n\r\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 从图标模块中导入删除键图标和清除键图标\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n * @param num - 数字字符串(如 '0'-'9')\r\n * @returns 返回一个按键定义对象\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `bankcard-${num}`, // 按键唯一标识符,格式为 bankcard-数字\r\n type: 'char', // 按键类型为字符键\r\n label: num, // 按键上显示的文本\r\n value: num, // 按键按下后输出的值\r\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\r\n }\r\n}\r\n\r\n/**\r\n * 银行卡键盘配置 - 紧凑4x4布局\r\n * 布局结构:\r\n * 第1行: 1 2 3 [退格]\r\n * 第2行: 4 5 6 [清除]\r\n * 第3行: 7 8 9 [关闭]\r\n * 第4行: [ABC] 0 [确定(占2格)]\r\n */\r\nexport const bankcardLayout: KeyboardConfig = {\r\n type: 'bankcard', // 键盘类型标识\r\n name: '银行卡键盘', // 键盘的显示名称\r\n supportShift: false, // 不支持 Shift 切换(纯数字键盘无需切换)\r\n rows: [\r\n // 键盘的行数组\r\n // ---- 第1行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n // 该行包含的按键数组\r\n createNumberKey('1'), // 数字键 1\r\n createNumberKey('2'), // 数字键 2\r\n createNumberKey('3'), // 数字键 3\r\n {\r\n id: 'backspace', // 退格键的唯一标识\r\n type: 'backspace', // 按键类型为退格,删除最后一个字符\r\n icon: ICON_DELETE, // 使用删除图标作为显示内容\r\n label: '', // 无文本标签(由图标替代)\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第2行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('4'), // 数字键 4\r\n createNumberKey('5'), // 数字键 5\r\n createNumberKey('6'), // 数字键 6\r\n {\r\n id: 'clear', // 清除键的唯一标识\r\n type: 'clear', // 按键类型为清除,清空所有输入\r\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\r\n label: '', // 无文本标签\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第3行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('7'), // 数字键 7\r\n createNumberKey('8'), // 数字键 8\r\n createNumberKey('9'), // 数字键 9\r\n {\r\n id: 'close', // 关闭键的唯一标识\r\n type: 'close', // 按键类型为关闭,收起键盘\r\n label: '关闭', // 按钮上显示的文本\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第4行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n {\r\n id: 'switch-qwerty', // 切换到全键盘的按键唯一标识\r\n type: 'tab', // 按键类型为标签页切换\r\n label: 'ABC', // 按钮上显示的文本,提示可切换到字母键盘\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n data: { targetType: 'qwerty' }, // 附加数据,指定切换目标为 QWERTY 全键盘\r\n },\r\n createNumberKey('0'), // 数字键 0\r\n {\r\n id: 'done', // 确定键的唯一标识\r\n type: 'done', // 按键类型为确定,完成输入\r\n label: '确定', // 按钮上显示的文本\r\n width: 2, // 占据 2 个键的宽度\r\n className: 'key-numpad-done', // 确定键的 CSS 类名\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n // 键盘的附加数据\r\n maxLength: 19, // 银行卡号最大输入长度为 19 位\r\n inputType: 'bankcard', // 输入类型标识,用于外部判断\r\n },\r\n}\r\n","/**\r\n * 邮箱键盘布局\r\n * @module layouts/email\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\nimport { ICON_DELETE, ICON_SHIFT } from '../icons'\r\n\r\n/**\r\n * 创建字符按键(支持大小写)\r\n */\r\nfunction createCharKey(char: string): KeyDefinition {\r\n return {\r\n id: `email-char-${char.toLowerCase()}`,\r\n type: 'char',\r\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() },\r\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() },\r\n }\r\n}\r\n\r\n/**\r\n * 创建快捷片段按键\r\n */\r\nfunction snippet(label: string, id?: string): KeyDefinition {\r\n return {\r\n id: id || `email-snippet-${label.replace(/[^a-z0-9]/gi, '')}`,\r\n type: 'char',\r\n label,\r\n value: label,\r\n className: 'key-snippet',\r\n }\r\n}\r\n\r\n/**\r\n * 常见邮箱后缀列表\r\n */\r\nexport const EMAIL_SUFFIXES = [\r\n '@qq.com',\r\n '@163.com',\r\n '@126.com',\r\n '@gmail.com',\r\n '@outlook.com',\r\n '@hotmail.com',\r\n '@sina.com',\r\n '@sohu.com',\r\n '@icloud.com',\r\n '@foxmail.com',\r\n '@yeah.net',\r\n '@139.com',\r\n]\r\n\r\nexport const emailLayout: KeyboardConfig = {\r\n type: 'email',\r\n name: '邮箱键盘',\r\n supportShift: true,\r\n defaultUpperCase: false,\r\n switchable: ['symbol', 'number'],\r\n rows: [\r\n // QWERTY 第一行\r\n {\r\n keys: 'qwertyuiop'.split('').map(createCharKey),\r\n },\r\n // QWERTY 第二行\r\n {\r\n keys: 'asdfghjkl'.split('').map(createCharKey),\r\n },\r\n // QWERTY 第三行 + Shift + 退格\r\n {\r\n keys: [\r\n {\r\n id: 'shift',\r\n type: 'shift',\r\n icon: ICON_SHIFT,\r\n label: '',\r\n width: 1.5,\r\n className: 'key-shift',\r\n },\r\n ...'zxcvbnm'.split('').map(createCharKey),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n width: 1.5,\r\n className: 'key-backspace',\r\n },\r\n ],\r\n },\r\n // 底部行:切换 + @ + 常用邮箱 + 符号 + 空格 + 完成\r\n {\r\n keys: [\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n },\r\n {\r\n id: 'email-at',\r\n type: 'char',\r\n label: '@',\r\n value: '@',\r\n className: 'key-at',\r\n },\r\n {\r\n id: 'email-suffix',\r\n type: 'char',\r\n label: '.com',\r\n value: '',\r\n width: 1.5,\r\n className: 'key-suffix',\r\n options: EMAIL_SUFFIXES,\r\n },\r\n snippet('.', 'email-dot'),\r\n snippet('-', 'email-dash'),\r\n snippet('_', 'email-underscore'),\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '',\r\n value: ' ',\r\n width: 2,\r\n className: 'key-space',\r\n },\r\n {\r\n id: 'email-done',\r\n type: 'done',\r\n label: '确定',\r\n width: 1.5,\r\n className: 'key-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * 身份证号键盘布局\r\n * @module layouts/idcard\r\n */\r\n\r\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 从图标模块中导入删除键图标和清除键图标\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n * @param num - 数字字符串(如 '0'-'9')\r\n * @returns 返回一个按键定义对象\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `idcard-${num}`, // 按键唯一标识符,格式为 idcard-数字\r\n type: 'char', // 按键类型为字符键\r\n label: num, // 按键上显示的文本\r\n value: num, // 按键按下后输出的值\r\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\r\n }\r\n}\r\n\r\n/**\r\n * 身份证号键盘配置\r\n * 紧凑3x4布局,无空白位置\r\n * 布局结构:\r\n * 第1行: 1 2 3 [退格]\r\n * 第2行: 4 5 6 [清除]\r\n * 第3行: 7 8 9 X\r\n * 第4行: [关闭] 0 [确定(占2格)]\r\n */\r\nexport const idcardLayout: KeyboardConfig = {\r\n type: 'idcard', // 键盘类型标识\r\n name: '身份证键盘', // 键盘的显示名称\r\n supportShift: false, // 不支持 Shift 切换(纯数字+X键盘无需切换)\r\n rows: [\r\n // 键盘的行数组\r\n // ---- 第1行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n // 该行包含的按键数组\r\n createNumberKey('1'), // 数字键 1\r\n createNumberKey('2'), // 数字键 2\r\n createNumberKey('3'), // 数字键 3\r\n {\r\n id: 'backspace', // 退格键的唯一标识\r\n type: 'backspace', // 按键类型为退格,删除最后一个字符\r\n icon: ICON_DELETE, // 使用删除图标作为显示内容\r\n label: '', // 无文本标签(由图标替代)\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第2行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('4'), // 数字键 4\r\n createNumberKey('5'), // 数字键 5\r\n createNumberKey('6'), // 数字键 6\r\n {\r\n id: 'clear', // 清除键的唯一标识\r\n type: 'clear', // 按键类型为清除,清空所有输入\r\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\r\n label: '', // 无文本标签\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第3行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('7'), // 数字键 7\r\n createNumberKey('8'), // 数字键 8\r\n createNumberKey('9'), // 数字键 9\r\n {\r\n id: 'idcard-x', // X 键的唯一标识\r\n type: 'char', // 按键类型为字符\r\n label: 'X', // 按钮上显示的文本(身份证尾号可能是X)\r\n value: 'X', // 按下后输出的值\r\n className: 'key-num', // 使用数字键的 CSS 类名,保持外观一致\r\n },\r\n ],\r\n },\r\n // ---- 第4行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n {\r\n id: 'close', // 关闭键的唯一标识\r\n type: 'close', // 按键类型为关闭,收起键盘\r\n label: '关闭', // 按钮上显示的文本\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n createNumberKey('0'), // 数字键 0\r\n {\r\n id: 'done', // 确定键的唯一标识\r\n type: 'done', // 按键类型为确定,完成输入\r\n label: '确定', // 按钮上显示的文本\r\n width: 2, // 占据 2 个键的宽度\r\n className: 'key-numpad-done', // 确定键的 CSS 类名\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n // 键盘的附加数据\r\n maxLength: 18, // 身份证号最大输入长度为 18 位\r\n inputType: 'idcard', // 输入类型标识,用于外部判断\r\n },\r\n}\r\n","/**\r\n * 车牌号键盘布局\r\n * @module layouts/license-plate\r\n * 省份键盘类似26键布局,点击省份后自动切换到字母数字键盘\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\nimport { ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 省份简称列表(按地理区域排列,10列布局)\r\n */\r\nexport const PROVINCES = [\r\n '京',\r\n '津',\r\n '沪',\r\n '渝',\r\n '冀',\r\n '豫',\r\n '云',\r\n '辽',\r\n '黑',\r\n '湘',\r\n '皖',\r\n '鲁',\r\n '新',\r\n '苏',\r\n '浙',\r\n '赣',\r\n '鄂',\r\n '桂',\r\n '甘',\r\n '晋',\r\n '蒙',\r\n '陕',\r\n '吉',\r\n '闽',\r\n '贵',\r\n '粤',\r\n '青',\r\n '藏',\r\n '川',\r\n '宁',\r\n '琼',\r\n '港',\r\n '澳',\r\n]\r\n\r\n/**\r\n * 车牌字母(排除 I 和 O,避免与数字混淆)\r\n */\r\nexport const PLATE_LETTERS = [\r\n 'A',\r\n 'B',\r\n 'C',\r\n 'D',\r\n 'E',\r\n 'F',\r\n 'G',\r\n 'H',\r\n 'J',\r\n 'K',\r\n 'L',\r\n 'M',\r\n 'N',\r\n 'P',\r\n 'Q',\r\n 'R',\r\n 'S',\r\n 'T',\r\n 'U',\r\n 'V',\r\n 'W',\r\n 'X',\r\n 'Y',\r\n 'Z',\r\n]\r\n\r\n/**\r\n * 创建省份按键(点击后自动切换到字母数字键盘)\r\n */\r\nfunction createProvinceKey(province: string): KeyDefinition {\r\n return {\r\n id: `province-${province}`,\r\n type: 'char',\r\n label: province,\r\n value: province,\r\n className: 'key-plate-province',\r\n data: { switchAfterInput: 'license-plate-alphanumeric' },\r\n }\r\n}\r\n\r\n/**\r\n * 创建字母按键\r\n */\r\nfunction createLetterKey(letter: string): KeyDefinition {\r\n return {\r\n id: `letter-${letter}`,\r\n type: 'char',\r\n label: letter,\r\n value: letter,\r\n className: 'key-plate-letter',\r\n }\r\n}\r\n\r\n/**\r\n * 创建数字按键\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `num-${num}`,\r\n type: 'char',\r\n label: num,\r\n value: num,\r\n className: 'key-plate-number',\r\n }\r\n}\r\n\r\n/**\r\n * 省份键盘配置 - 类似26键布局\r\n * 10列布局,更紧凑美观\r\n */\r\nexport const licensePlateProvinceLayout: KeyboardConfig = {\r\n type: 'license-plate-province',\r\n name: '省份简称',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PROVINCES.slice(0, 10).map(createProvinceKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PROVINCES.slice(10, 20).map(createProvinceKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PROVINCES.slice(20, 30).map(createProvinceKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: [\r\n ...PROVINCES.slice(30, 33).map(createProvinceKey),\r\n {\r\n id: 'plate-xue',\r\n type: 'char',\r\n label: '学',\r\n value: '学',\r\n className: 'key-plate-special',\r\n data: { switchAfterInput: 'license-plate-alphanumeric' },\r\n },\r\n {\r\n id: 'plate-jing',\r\n type: 'char',\r\n label: '警',\r\n value: '警',\r\n className: 'key-plate-special',\r\n data: { switchAfterInput: 'license-plate-alphanumeric' },\r\n },\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n width: 1.5,\r\n className: 'key-plate-fn',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2.5,\r\n className: 'key-plate-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n maxLength: 8,\r\n inputType: 'license-plate',\r\n },\r\n}\r\n\r\n/**\r\n * 字母数字键盘配置(车牌第2-8位)\r\n * 10列布局\r\n */\r\nexport const licensePlateAlphanumericLayout: KeyboardConfig = {\r\n type: 'license-plate-alphanumeric',\r\n name: '字母数字',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: '1234567890'.split('').map(createNumberKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PLATE_LETTERS.slice(0, 10).map(createLetterKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: [\r\n ...PLATE_LETTERS.slice(10, 19).map(createLetterKey),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-plate-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: [\r\n {\r\n id: 'switch-province',\r\n type: 'tab',\r\n label: '省份',\r\n width: 1.5,\r\n className: 'key-plate-switch',\r\n data: { targetType: 'license-plate-province' },\r\n },\r\n ...PLATE_LETTERS.slice(19, 24).map(createLetterKey),\r\n {\r\n id: 'plate-xue',\r\n type: 'char',\r\n label: '学',\r\n value: '学',\r\n className: 'key-plate-special',\r\n },\r\n {\r\n id: 'plate-jing',\r\n type: 'char',\r\n label: '警',\r\n value: '警',\r\n className: 'key-plate-special',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 1.5,\r\n className: 'key-plate-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n maxLength: 8,\r\n inputType: 'license-plate',\r\n },\r\n}\r\n\r\n/**\r\n * 纯字母键盘配置(车牌第2位,只能输入字母)\r\n * 6列布局,排除 I 和 O\r\n */\r\nexport const licensePlateLetterLayout: KeyboardConfig = {\r\n type: 'license-plate-letter',\r\n name: '字母',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PLATE_LETTERS.slice(0, 8).map(createLetterKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: PLATE_LETTERS.slice(8, 16).map(createLetterKey),\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: [...PLATE_LETTERS.slice(16, 24).map(createLetterKey)],\r\n },\r\n {\r\n className: 'plate-keyboard-row',\r\n keys: [\r\n {\r\n id: 'switch-province',\r\n type: 'tab',\r\n label: '省份',\r\n width: 2,\r\n className: 'key-plate-switch',\r\n data: { targetType: 'license-plate-province' },\r\n },\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n width: 2,\r\n className: 'key-plate-fn',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-plate-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n maxLength: 8,\r\n inputType: 'license-plate',\r\n },\r\n}\r\n\r\n/**\r\n * 完整车牌号键盘(自动切换模式)\r\n * 默认显示省份键盘,点击省份后自动切换到字母数字键盘\r\n */\r\nexport const licensePlateLayout: KeyboardConfig = {\r\n type: 'license-plate',\r\n name: '车牌号键盘',\r\n supportShift: false,\r\n data: {\r\n autoSwitch: true,\r\n maxLength: 8,\r\n inputType: 'license-plate',\r\n },\r\n rows: licensePlateProvinceLayout.rows,\r\n}\r\n","/**\r\n * 数字键盘布局\r\n * @module layouts/number\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `num-${num}`,\r\n type: 'char',\r\n label: num,\r\n value: num,\r\n className: 'key-num',\r\n }\r\n}\r\n\r\n/**\r\n * 数字键盘配置 - 紧凑4x4布局\r\n */\r\nexport const numberLayout: KeyboardConfig = {\r\n type: 'number',\r\n name: '数字键盘',\r\n supportShift: false,\r\n switchable: ['qwerty', 'symbol'],\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'close',\r\n type: 'close',\r\n label: '关闭',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'decimal',\r\n type: 'char',\r\n label: '.',\r\n value: '.',\r\n className: 'key-num',\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n\r\n/**\r\n * 纯整数键盘 - 紧凑4x4布局\r\n */\r\nexport const integerLayout: KeyboardConfig = {\r\n type: 'integer',\r\n name: '整数键盘',\r\n supportShift: false,\r\n switchable: ['qwerty'],\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'close',\r\n type: 'close',\r\n label: '关闭',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'switch-qwerty',\r\n type: 'tab',\r\n label: 'ABC',\r\n className: 'key-numpad-fn',\r\n data: { targetType: 'qwerty' },\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * 手机号键盘布局\r\n * @module layouts/phone\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `phone-${num}`,\r\n type: 'char',\r\n label: num,\r\n value: num,\r\n className: 'key-num',\r\n }\r\n}\r\n\r\n/**\r\n * 手机号键盘配置\r\n * 紧凑4x4布局\r\n */\r\nexport const phoneLayout: KeyboardConfig = {\r\n type: 'phone',\r\n name: '手机号键盘',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'close',\r\n type: 'close',\r\n label: '关闭',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'phone-plus',\r\n type: 'char',\r\n label: '+',\r\n value: '+',\r\n className: 'key-num',\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n maxLength: 11,\r\n inputType: 'phone',\r\n },\r\n}\r\n\r\n/**\r\n * 简洁版拨号键盘(带 * #)\r\n */\r\nexport const phoneSimpleLayout: KeyboardConfig = {\r\n type: 'phone-simple',\r\n name: '拨号键盘',\r\n supportShift: false,\r\n rows: [\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('1'),\r\n createNumberKey('2'),\r\n createNumberKey('3'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('4'),\r\n createNumberKey('5'),\r\n createNumberKey('6'),\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n icon: ICON_CLEAR,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n createNumberKey('7'),\r\n createNumberKey('8'),\r\n createNumberKey('9'),\r\n {\r\n id: 'phone-hash',\r\n type: 'char',\r\n label: '#',\r\n value: '#',\r\n className: 'key-num',\r\n },\r\n ],\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'phone-star',\r\n type: 'char',\r\n label: '*',\r\n value: '*',\r\n className: 'key-num',\r\n },\r\n createNumberKey('0'),\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '拨打',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n maxLength: 13,\r\n inputType: 'phone',\r\n },\r\n}\r\n","/**\r\n * 标点符号键盘布局 (中文)\r\n * @module layouts/punct\r\n */\r\n\r\n// 导入键盘配置和按键定义的类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 导入删除和确认图标资源\r\nimport { ICON_CHECK, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建标点符号按键的快捷函数\r\n * @param label - 按键显示文本(同时也是默认输出值)\r\n * @param value - 可选,按键输出值,不传则与label相同\r\n * @returns 返回一个标点按键定义对象\r\n */\r\nfunction p(label: string, value?: string): KeyDefinition {\r\n return {\r\n id: `punct-${label}`,\r\n type: 'char',\r\n label,\r\n value: value ?? label,\r\n className: 'key-num',\r\n }\r\n}\r\n\r\n// 导出中文标点键盘布局配置\r\nexport const punctLayout: KeyboardConfig = {\r\n type: 'punct', // 布局类型标识为 punct\r\n name: '中文标点', // 布局显示名称\r\n supportShift: false, // 不支持Shift切换(标点键盘无需大小写)\r\n switchable: ['qwerty', 'punct-en'], // 可切换到QWERTY键盘和英文标点键盘\r\n rows: [\r\n // 第一行:常用中文标点符号\r\n {\r\n className: 'virtual-keyboard__row', // 行的CSS类名\r\n keys: [',', '。', '?', '!', ':', ';', '\"', '\"'].map(s => p(s)), // 逗号、句号、问号、感叹号、冒号、分号、左右双引号\r\n },\r\n // 第二行:括号类标点符号\r\n {\r\n className: 'virtual-keyboard__row', // 行的CSS类名\r\n keys: ['(', ')', '【', '】', '《', '》', '……', '——'].map(s => p(s)), // 小括号、中括号、书名号、省略号、破折号\r\n },\r\n // 第三行:其他标点 + 退格键\r\n {\r\n className: 'virtual-keyboard__row', // 行的CSS类名\r\n keys: [\r\n p('·'), // 间隔号(中间点)\r\n p('、'), // 顿号\r\n p('「'), // 左单书名号\r\n p('」'), // 右单书名号\r\n p('『'), // 左双书名号\r\n p('』'), // 右双书名号\r\n p('~'), // 波浪号\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n icon: ICON_DELETE,\r\n label: '',\r\n className: 'key-numpad-fn',\r\n }, // 退格键\r\n ],\r\n },\r\n // 底部行:切换键盘 + 空格 + 确认\r\n {\r\n className: 'virtual-keyboard__row', // 行的CSS类名\r\n keys: [\r\n {\r\n id: 'switch-punct-en',\r\n type: 'tab',\r\n label: '英',\r\n data: { targetType: 'punct-en' },\r\n className: 'key-numpad-fn',\r\n }, // 切换到英文标点键盘\r\n {\r\n id: 'switch-qwerty',\r\n type: 'tab',\r\n label: 'ABC',\r\n data: { targetType: 'qwerty' },\r\n className: 'key-numpad-fn',\r\n }, // 切换到QWERTY字母键盘\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '空格',\r\n value: ' ',\r\n width: 4,\r\n className: 'key-num',\r\n }, // 空格键,宽度4倍\r\n {\r\n id: 'done',\r\n type: 'done',\r\n icon: ICON_CHECK,\r\n label: '',\r\n width: 2,\r\n className: 'key-numpad-done',\r\n }, // 确认/完成按钮,宽度2倍\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * QWERTY 标准字母键盘布局\r\n * @module layouts/qwerty\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n\r\n/**\r\n * 创建字符按键\r\n */\r\nfunction createCharKey(char: string): KeyDefinition {\r\n return {\r\n id: `char-${char.toLowerCase()}`,\r\n type: 'char',\r\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() },\r\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() },\r\n }\r\n}\r\n\r\n/**\r\n * QWERTY 键盘配置\r\n */\r\nexport const qwertyLayout: KeyboardConfig = {\r\n type: 'qwerty',\r\n name: '字母键盘',\r\n supportShift: true,\r\n defaultUpperCase: false,\r\n switchable: ['number', 'symbol'],\r\n rows: [\r\n {\r\n keys: [\r\n createCharKey('Q'),\r\n createCharKey('W'),\r\n createCharKey('E'),\r\n createCharKey('R'),\r\n createCharKey('T'),\r\n createCharKey('Y'),\r\n createCharKey('U'),\r\n createCharKey('I'),\r\n createCharKey('O'),\r\n createCharKey('P'),\r\n ],\r\n },\r\n {\r\n keys: [\r\n createCharKey('A'),\r\n createCharKey('S'),\r\n createCharKey('D'),\r\n createCharKey('F'),\r\n createCharKey('G'),\r\n createCharKey('H'),\r\n createCharKey('J'),\r\n createCharKey('K'),\r\n createCharKey('L'),\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'shift',\r\n type: 'shift',\r\n label: '⇧',\r\n width: 1.5,\r\n className: 'key-shift',\r\n },\r\n createCharKey('Z'),\r\n createCharKey('X'),\r\n createCharKey('C'),\r\n createCharKey('V'),\r\n createCharKey('B'),\r\n createCharKey('N'),\r\n createCharKey('M'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n width: 1.5,\r\n className: 'key-backspace',\r\n },\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.5,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n },\r\n {\r\n id: 'switch-symbol',\r\n type: 'tab',\r\n label: '#+=',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'symbol' },\r\n },\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '空格',\r\n value: ' ',\r\n width: 4,\r\n className: 'key-space',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '完成',\r\n width: 2,\r\n className: 'key-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * 搜索键盘布局\r\n * @module layouts/search\r\n */\r\n\r\n// 导入键盘配置和按键定义的类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 导入删除、Shift和语音图标资源\r\nimport { ICON_DELETE, ICON_SHIFT, ICON_VOICE } from '../icons'\r\n\r\n/**\r\n * 创建字符按键(支持大小写)\r\n * @param char - 字符,用于生成大小写标签和值\r\n * @returns 返回一个按键定义对象\r\n */\r\nfunction createCharKey(char: string): KeyDefinition {\r\n return {\r\n id: `search-char-${char.toLowerCase()}`, // 按键唯一标识,格式为 search-char-x\r\n type: 'char', // 按键类型为字符键\r\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 显示标签:小写/大写\r\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 输出值:小写/大写\r\n }\r\n}\r\n\r\n// 导出搜索键盘布局配置\r\nexport const searchLayout: KeyboardConfig = {\r\n type: 'search', // 布局类型标识为 search\r\n name: '搜索键盘', // 布局显示名称\r\n supportShift: true, // 支持Shift切换大小写\r\n defaultUpperCase: false, // 默认为小写状态\r\n switchable: ['symbol', 'number'], // 可切换到符号键盘和数字键盘\r\n rows: [\r\n // QWERTY 第一行:q w e r t y u i o p\r\n {\r\n keys: 'qwertyuiop'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\r\n },\r\n // QWERTY 第二行:a s d f g h j k l\r\n {\r\n keys: 'asdfghjkl'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\r\n },\r\n // QWERTY 第三行 + Shift + 退格\r\n {\r\n keys: [\r\n {\r\n id: 'shift', // Shift键标识\r\n type: 'shift', // 按键类型为Shift\r\n icon: ICON_SHIFT, // 使用Shift图标\r\n label: '', // 无文字标签,仅显示图标\r\n width: 1.5, // 宽度为1.5倍\r\n className: 'key-shift', // CSS类名\r\n },\r\n ...'zxcvbnm'.split('').map(createCharKey), // 展开第三行字母 z x c v b n m 的按键定义\r\n {\r\n id: 'backspace', // 退格键标识\r\n type: 'backspace', // 按键类型为退格\r\n icon: ICON_DELETE, // 使用删除图标\r\n label: '', // 无文字标签,仅显示图标\r\n width: 1.5, // 宽度为1.5倍\r\n className: 'key-backspace', // CSS类名\r\n },\r\n ],\r\n },\r\n // 底部行:切换 + 空格 + 语音 + 搜索\r\n {\r\n keys: [\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n }, // 切换到数字键盘,宽度1.25倍\r\n {\r\n id: 'switch-symbol',\r\n type: 'tab',\r\n label: '#+=',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'symbol' },\r\n }, // 切换到符号键盘,宽度1.25倍\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '',\r\n value: ' ',\r\n width: 4,\r\n className: 'key-space',\r\n }, // 空格键,宽度4倍\r\n {\r\n id: 'voice',\r\n type: 'custom',\r\n icon: ICON_VOICE,\r\n label: '',\r\n width: 1,\r\n className: 'key-voice',\r\n data: { action: 'voice' },\r\n }, // 语音输入按钮,宽度1倍\r\n {\r\n id: 'search-done',\r\n type: 'done',\r\n label: '搜索',\r\n width: 2,\r\n className: 'key-done',\r\n }, // 搜索/完成按钮,宽度2倍\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * 符号键盘布局\r\n * @module layouts/symbol\r\n */\r\n\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n\r\n/**\r\n * 创建符号按键\r\n */\r\nfunction createSymbolKey(symbol: string, id?: string): KeyDefinition {\r\n return {\r\n id: id || `symbol-${symbol.charCodeAt(0)}`,\r\n type: 'char',\r\n label: symbol,\r\n value: symbol,\r\n }\r\n}\r\n\r\n/**\r\n * 符号键盘配置\r\n */\r\nexport const symbolLayout: KeyboardConfig = {\r\n type: 'symbol',\r\n name: '符号键盘',\r\n supportShift: false,\r\n switchable: ['qwerty', 'number'],\r\n rows: [\r\n {\r\n keys: [\r\n createSymbolKey('1'),\r\n createSymbolKey('2'),\r\n createSymbolKey('3'),\r\n createSymbolKey('4'),\r\n createSymbolKey('5'),\r\n createSymbolKey('6'),\r\n createSymbolKey('7'),\r\n createSymbolKey('8'),\r\n createSymbolKey('9'),\r\n createSymbolKey('0'),\r\n ],\r\n },\r\n {\r\n keys: [\r\n createSymbolKey('-'),\r\n createSymbolKey('/'),\r\n createSymbolKey(':'),\r\n createSymbolKey(';'),\r\n createSymbolKey('('),\r\n createSymbolKey(')'),\r\n createSymbolKey('¥', 'yen'),\r\n createSymbolKey('@'),\r\n createSymbolKey('\"', 'quote'),\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'switch-symbol-2',\r\n type: 'tab',\r\n label: '#+= ',\r\n width: 1.5,\r\n className: 'key-switch',\r\n data: { targetType: 'symbol-2' },\r\n },\r\n createSymbolKey('.'),\r\n createSymbolKey(','),\r\n createSymbolKey('?'),\r\n createSymbolKey('!'),\r\n createSymbolKey(\"'\", 'apostrophe'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n width: 1.5,\r\n className: 'key-backspace',\r\n },\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'switch-qwerty',\r\n type: 'tab',\r\n label: 'ABC',\r\n width: 1.5,\r\n className: 'key-switch',\r\n data: { targetType: 'qwerty' },\r\n },\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n },\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '空格',\r\n value: ' ',\r\n width: 4,\r\n className: 'key-space',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '完成',\r\n width: 2,\r\n className: 'key-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n\r\n/**\r\n * 符号键盘第二页\r\n */\r\nexport const symbolLayout2: KeyboardConfig = {\r\n type: 'symbol',\r\n name: '符号键盘2',\r\n supportShift: false,\r\n switchable: ['qwerty', 'number'],\r\n rows: [\r\n {\r\n keys: [\r\n createSymbolKey('['),\r\n createSymbolKey(']'),\r\n createSymbolKey('{'),\r\n createSymbolKey('}'),\r\n createSymbolKey('#'),\r\n createSymbolKey('%'),\r\n createSymbolKey('^'),\r\n createSymbolKey('*'),\r\n createSymbolKey('+'),\r\n createSymbolKey('='),\r\n ],\r\n },\r\n {\r\n keys: [\r\n createSymbolKey('_'),\r\n createSymbolKey('\\\\'),\r\n createSymbolKey('|'),\r\n createSymbolKey('~'),\r\n createSymbolKey('<'),\r\n createSymbolKey('>'),\r\n createSymbolKey('€', 'euro'),\r\n createSymbolKey('$'),\r\n createSymbolKey('&'),\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'switch-symbol-1',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.5,\r\n className: 'key-switch',\r\n data: { targetType: 'symbol' },\r\n },\r\n createSymbolKey('`', 'backtick'),\r\n createSymbolKey('·', 'middle-dot'),\r\n createSymbolKey('…', 'ellipsis'),\r\n createSymbolKey('°', 'degree'),\r\n createSymbolKey('•', 'bullet'),\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n width: 1.5,\r\n className: 'key-backspace',\r\n },\r\n ],\r\n },\r\n {\r\n keys: [\r\n {\r\n id: 'switch-qwerty',\r\n type: 'tab',\r\n label: 'ABC',\r\n width: 1.5,\r\n className: 'key-switch',\r\n data: { targetType: 'qwerty' },\r\n },\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.25,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n },\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '空格',\r\n value: ' ',\r\n width: 4,\r\n className: 'key-space',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '完成',\r\n width: 2,\r\n className: 'key-done',\r\n },\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * URL/链接键盘布局\r\n * @module layouts/url\r\n */\r\n\r\n// 导入键盘配置和按键定义的类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 导入删除和Shift图标资源\r\nimport { ICON_DELETE, ICON_SHIFT } from '../icons'\r\n\r\n/**\r\n * 创建字符按键(支持大小写)\r\n * @param char - 字符,用于生成大小写标签和值\r\n * @returns 返回一个按键定义对象\r\n */\r\nfunction createCharKey(char: string): KeyDefinition {\r\n return {\r\n id: `url-char-${char.toLowerCase()}`, // 按键唯一标识,格式为 url-char-x\r\n type: 'char', // 按键类型为字符键\r\n label: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 显示标签:小写/大写\r\n value: { lower: char.toLowerCase(), upper: char.toUpperCase() }, // 输出值:小写/大写\r\n }\r\n}\r\n\r\n/**\r\n * 创建快捷片段按键\r\n * 用于URL键盘中常用的符号和域名后缀\r\n * @param label - 按键显示文本\r\n * @param width - 可选,按键宽度倍数\r\n * @returns 返回一个片段按键定义对象\r\n */\r\nfunction snippet(label: string, width?: number): KeyDefinition {\r\n // 生成唯一 ID:用 label 的字符编码(去除非法字符后拼接)\r\n const idSuffix =\r\n label.replace(/[^a-z0-9]/gi, '') ||\r\n label\r\n .split('')\r\n .map(c => c.charCodeAt(0))\r\n .join('')\r\n return {\r\n id: `url-snippet-${idSuffix}`, // 按键唯一标识,格式为 url-snippet-xxx\r\n type: 'char', // 按键类型为字符键\r\n label, // 显示文本\r\n value: label, // 输出值与显示文本相同\r\n width, // 按键宽度倍数\r\n className: 'key-snippet', // 自定义CSS类名,用于样式控制\r\n }\r\n}\r\n\r\n// 导出URL键盘布局配置\r\nexport const urlLayout: KeyboardConfig = {\r\n type: 'url', // 布局类型标识为 url\r\n name: '网址键盘', // 布局显示名称\r\n supportShift: true, // 支持Shift切换大小写\r\n defaultUpperCase: false, // 默认为小写状态\r\n switchable: ['symbol', 'number'], // 可切换到符号键盘和数字键盘\r\n rows: [\r\n // QWERTY 第一行:q w e r t y u i o p\r\n {\r\n keys: 'qwertyuiop'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\r\n },\r\n // QWERTY 第二行:a s d f g h j k l\r\n {\r\n keys: 'asdfghjkl'.split('').map(createCharKey), // 将字符串拆分为字符数组,逐个创建按键\r\n },\r\n // QWERTY 第三行 + Shift + 退格\r\n {\r\n keys: [\r\n {\r\n id: 'shift', // Shift键标识\r\n type: 'shift', // 按键类型为Shift\r\n icon: ICON_SHIFT, // 使用Shift图标\r\n label: '', // 无文字标签,仅显示图标\r\n width: 1.5, // 宽度为1.5倍\r\n className: 'key-shift', // CSS类名\r\n },\r\n ...'zxcvbnm'.split('').map(createCharKey), // 展开第三行字母 z x c v b n m 的按键定义\r\n {\r\n id: 'backspace', // 退格键标识\r\n type: 'backspace', // 按键类型为退格\r\n icon: ICON_DELETE, // 使用删除图标\r\n label: '', // 无文字标签,仅显示图标\r\n width: 1.5, // 宽度为1.5倍\r\n className: 'key-backspace', // CSS类名\r\n },\r\n ],\r\n },\r\n // 底部行:切换 + 符号 + 域名后缀 + 前往\r\n {\r\n keys: [\r\n {\r\n id: 'switch-number',\r\n type: 'tab',\r\n label: '123',\r\n width: 1.2,\r\n className: 'key-switch',\r\n data: { targetType: 'number' },\r\n }, // 切换到数字键盘\r\n snippet('/', 0.8), // 斜杠快捷键,宽度0.8倍\r\n snippet('.', 0.8), // 点号快捷键,宽度0.8倍\r\n snippet('-', 0.8), // 横杠快捷键,宽度0.8倍\r\n snippet('.com', 1.5), // .com域名后缀快捷键,宽度1.5倍\r\n snippet('.cn', 1.2), // .cn域名后缀快捷键,宽度1.2倍\r\n {\r\n id: 'space',\r\n type: 'space',\r\n label: '',\r\n value: ' ',\r\n width: 1.5,\r\n className: 'key-space',\r\n }, // 空格键,宽度1.5倍\r\n {\r\n id: 'url-go',\r\n type: 'done',\r\n label: '前往',\r\n width: 1.5,\r\n className: 'key-done',\r\n }, // 前往/完成按钮,宽度1.5倍\r\n ],\r\n },\r\n ],\r\n}\r\n","/**\r\n * 验证码键盘布局\r\n * @module layouts/verifycode\r\n */\r\n\r\n// 从类型定义文件中导入 KeyboardConfig(键盘配置)和 KeyDefinition(按键定义)类型\r\nimport type { KeyboardConfig, KeyDefinition } from '../types'\r\n// 从图标模块中导入删除键图标和清除键图标\r\nimport { ICON_CLEAR, ICON_DELETE } from '../icons'\r\n\r\n/**\r\n * 创建数字按键\r\n * @param num - 数字字符串(如 '0'-'9')\r\n * @returns 返回一个按键定义对象\r\n */\r\nfunction createNumberKey(num: string): KeyDefinition {\r\n return {\r\n id: `verify-${num}`, // 按键唯一标识符,格式为 verify-数字\r\n type: 'char', // 按键类型为字符键\r\n label: num, // 按键上显示的文本\r\n value: num, // 按键按下后输出的值\r\n className: 'key-num', // 按键的 CSS 类名,用于样式定制\r\n }\r\n}\r\n\r\n/**\r\n * 验证码键盘配置 - 4x4布局(与其他数字键盘一致)\r\n * 布局结构:\r\n * 第1行: 1 2 3 [退格]\r\n * 第2行: 4 5 6 [清除]\r\n * 第3行: 7 8 9 [关闭]\r\n * 第4行: [空] 0 [确定(占2格)]\r\n */\r\nexport const verifycodeLayout: KeyboardConfig = {\r\n type: 'verifycode', // 键盘类型标识\r\n name: '验证码键盘', // 键盘的显示名称\r\n supportShift: false, // 不支持 Shift 切换(纯数字键盘无需切换)\r\n rows: [\r\n // 键盘的行数组\r\n // ---- 第1行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n // 该行包含的按键数组\r\n createNumberKey('1'), // 数字键 1\r\n createNumberKey('2'), // 数字键 2\r\n createNumberKey('3'), // 数字键 3\r\n {\r\n id: 'backspace', // 退格键的唯一标识\r\n type: 'backspace', // 按键类型为退格,删除最后一个字符\r\n icon: ICON_DELETE, // 使用删除图标作为显示内容\r\n label: '', // 无文本标签(由图标替代)\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第2行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('4'), // 数字键 4\r\n createNumberKey('5'), // 数字键 5\r\n createNumberKey('6'), // 数字键 6\r\n {\r\n id: 'clear', // 清除键的唯一标识\r\n type: 'clear', // 按键类型为清除,清空所有输入\r\n icon: ICON_CLEAR, // 使用清除图标作为显示内容\r\n label: '', // 无文本标签\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第3行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n createNumberKey('7'), // 数字键 7\r\n createNumberKey('8'), // 数字键 8\r\n createNumberKey('9'), // 数字键 9\r\n {\r\n id: 'close', // 关闭键的唯一标识\r\n type: 'close', // 按键类型为关闭,收起键盘\r\n label: '关闭', // 按钮上显示的文本\r\n className: 'key-numpad-fn', // 功能键的 CSS 类名\r\n },\r\n ],\r\n },\r\n // ---- 第4行 ----\r\n {\r\n className: 'numpad-row', // 行的 CSS 类名\r\n keys: [\r\n {\r\n id: 'empty', // 占位空键的唯一标识\r\n type: 'char', // 类型为字符键(但被禁用)\r\n label: '', // 无显示文本\r\n value: '', // 无输出值\r\n disabled: true, // 禁用状态,不可点击\r\n className: 'key-numpad-empty', // 空占位键的 CSS 类名\r\n },\r\n createNumberKey('0'), // 数字键 0\r\n {\r\n id: 'done', // 确定键的唯一标识\r\n type: 'done', // 按键类型为确定,完成输入\r\n label: '确定', // 按钮上显示的文本\r\n width: 2, // 占据 2 个键的宽度\r\n className: 'key-numpad-done', // 确定键的 CSS 类名\r\n },\r\n ],\r\n },\r\n ],\r\n data: {\r\n // 键盘的附加数据\r\n maxLength: 6, // 验证码最大输入长度为 6 位\r\n inputType: 'verifycode', // 输入类型标识,用于外部判断\r\n },\r\n}\r\n","/**\r\n * 键盘布局管理\r\n * @module layouts\r\n */\r\n\r\nimport type { KeyboardConfig, KeyboardType } from '../types'\r\nimport { amountLayout, amountSimpleLayout } from './amount'\r\nimport { bankcardLayout } from './bankcard'\r\nimport { EMAIL_SUFFIXES, emailLayout } from './email'\r\nimport { idcardLayout } from './idcard'\r\nimport {\r\n licensePlateAlphanumericLayout,\r\n licensePlateLayout,\r\n licensePlateLetterLayout,\r\n licensePlateProvinceLayout,\r\n PLATE_LETTERS,\r\n PROVINCES,\r\n} from './license-plate'\r\nimport { integerLayout, numberLayout } from './number'\r\nimport { phoneLayout, phoneSimpleLayout } from './phone'\r\nimport { punctLayout } from './punct'\r\nimport { qwertyLayout } from './qwerty'\r\nimport { searchLayout } from './search'\r\nimport { symbolLayout, symbolLayout2 } from './symbol'\r\nimport { urlLayout } from './url'\r\nimport { verifycodeLayout } from './verifycode'\r\n\r\n// 导出所有布局\r\nexport {\r\n amountLayout,\r\n amountSimpleLayout,\r\n bankcardLayout,\r\n EMAIL_SUFFIXES,\r\n // 输入场景键盘\r\n emailLayout,\r\n // 场景化键盘\r\n idcardLayout,\r\n integerLayout,\r\n licensePlateAlphanumericLayout,\r\n licensePlateLayout,\r\n licensePlateLetterLayout,\r\n licensePlateProvinceLayout,\r\n numberLayout,\r\n phoneLayout,\r\n phoneSimpleLayout,\r\n PLATE_LETTERS,\r\n PROVINCES,\r\n // 标点键盘\r\n punctLayout,\r\n qwertyLayout,\r\n searchLayout,\r\n symbolLayout,\r\n symbolLayout2,\r\n urlLayout,\r\n verifycodeLayout,\r\n}\r\n\r\n/**\r\n * 内置布局映射\r\n */\r\nconst builtinLayouts: Record<string, KeyboardConfig> = {\r\n qwerty: qwertyLayout,\r\n number: numberLayout,\r\n integer: integerLayout,\r\n symbol: symbolLayout,\r\n 'symbol-2': symbolLayout2,\r\n 'license-plate': licensePlateLayout,\r\n 'license-plate-province': licensePlateProvinceLayout,\r\n 'license-plate-letter': licensePlateLetterLayout,\r\n 'license-plate-alphanumeric': licensePlateAlphanumericLayout,\r\n // 场景化键盘\r\n idcard: idcardLayout,\r\n phone: phoneLayout,\r\n 'phone-simple': phoneSimpleLayout,\r\n amount: amountLayout,\r\n 'amount-simple': amountSimpleLayout,\r\n bankcard: bankcardLayout,\r\n verifycode: verifycodeLayout,\r\n // 输入场景键盘\r\n email: emailLayout,\r\n url: urlLayout,\r\n search: searchLayout,\r\n // 标点键盘\r\n punct: punctLayout,\r\n}\r\n\r\n/**\r\n * 自定义布局存储\r\n */\r\nconst customLayouts: Record<string, KeyboardConfig> = {}\r\n\r\n/**\r\n * 注册自定义布局\r\n * @param name - 布局名称\r\n * @param layout - 布局配置\r\n */\r\nexport function registerLayout(name: string, layout: KeyboardConfig): void {\r\n if (builtinLayouts[name]) {\r\n console.warn(`[Keyboard] Cannot override builtin layout \"${name}\"`)\r\n return\r\n }\r\n customLayouts[name] = layout\r\n}\r\n\r\n/**\r\n * 获取布局配置\r\n * @param type - 键盘类型或布局名称\r\n * @returns 布局配置,如果不存在则返回 undefined\r\n */\r\nexport function getLayout(\r\n type: KeyboardType | string\r\n): KeyboardConfig | undefined {\r\n return customLayouts[type] || builtinLayouts[type]\r\n}\r\n\r\n/**\r\n * 获取所有可用布局名称\r\n * @returns 布局名称数组\r\n */\r\nexport function getAvailableLayouts(): string[] {\r\n return [...Object.keys(builtinLayouts), ...Object.keys(customLayouts)]\r\n}\r\n\r\n/**\r\n * 检查布局是否存在\r\n * @param name - 布局名称\r\n * @returns 是否存在\r\n */\r\nexport function hasLayout(name: string): boolean {\r\n return name in builtinLayouts || name in customLayouts\r\n}\r\n\r\n/**\r\n * 移除自定义布局\r\n * @param name - 布局名称\r\n * @returns 是否成功移除\r\n */\r\nexport function unregisterLayout(name: string): boolean {\r\n if (name in customLayouts) {\r\n delete customLayouts[name]\r\n return true\r\n }\r\n return false\r\n}\r\n\r\n/**\r\n * 批量注册布局\r\n * @param layouts - 布局映射对象\r\n */\r\nexport function registerLayouts(layouts: Record<string, KeyboardConfig>): void {\r\n Object.entries(layouts).forEach(([name, layout]) => {\r\n registerLayout(name, layout)\r\n })\r\n}\r\n","/**\r\n * 设备检测工具\r\n * @module utils/device\r\n */\r\n\r\nimport type { DeviceType, ViewportInfo } from '../types'\r\n\r\n/**\r\n * 移动设备 UA 正则\r\n */\r\nconst MOBILE_UA_REGEX =\r\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i\r\n\r\n/**\r\n * 触摸设备检测缓存\r\n */\r\nlet cachedIsTouchDevice: boolean | null = null\r\n\r\n/**\r\n * 检测是否为触摸设备\r\n */\r\nexport function isTouchDevice(): boolean {\r\n if (cachedIsTouchDevice !== null) {\r\n return cachedIsTouchDevice\r\n }\r\n\r\n if (typeof window === 'undefined') {\r\n return false\r\n }\r\n\r\n cachedIsTouchDevice =\r\n 'ontouchstart' in window ||\r\n navigator.maxTouchPoints > 0 ||\r\n // @ts-expect-error - msMaxTouchPoints is IE specific\r\n navigator.msMaxTouchPoints > 0\r\n\r\n return cachedIsTouchDevice\r\n}\r\n\r\n/**\r\n * 检测是否为移动设备(基于 UA)\r\n */\r\nexport function isMobileUA(): boolean {\r\n if (typeof navigator === 'undefined') {\r\n return false\r\n }\r\n return MOBILE_UA_REGEX.test(navigator.userAgent)\r\n}\r\n\r\n/**\r\n * 检测是否为移动设备(综合判断)\r\n */\r\nexport function isMobile(): boolean {\r\n if (typeof window === 'undefined') {\r\n return false\r\n }\r\n\r\n // 优先使用 UA 判断\r\n if (isMobileUA()) {\r\n return true\r\n }\r\n\r\n // 其次使用屏幕宽度判断\r\n const screenWidth = window.innerWidth || document.documentElement.clientWidth\r\n if (screenWidth <= 768) {\r\n return true\r\n }\r\n\r\n // 最后使用触摸检测\r\n return isTouchDevice()\r\n}\r\n\r\n/**\r\n * 获取设备类型\r\n */\r\nexport function getDeviceType(): DeviceType {\r\n return isMobile() ? 'mobile' : 'desktop'\r\n}\r\n\r\n/**\r\n * 获取视口信息\r\n */\r\nexport function getViewportInfo(): ViewportInfo {\r\n if (typeof window === 'undefined') {\r\n return {\r\n width: 0,\r\n height: 0,\r\n scrollX: 0,\r\n scrollY: 0,\r\n isMobile: false,\r\n }\r\n }\r\n\r\n const width = window.innerWidth || document.documentElement.clientWidth\r\n const height = window.innerHeight || document.documentElement.clientHeight\r\n\r\n // 获取安全区域(iOS 刘海屏等)\r\n const safeArea = getSafeAreaInsets()\r\n\r\n return {\r\n width,\r\n height,\r\n scrollX: window.scrollX || window.pageXOffset,\r\n scrollY: window.scrollY || window.pageYOffset,\r\n isMobile: isMobile(),\r\n safeArea,\r\n }\r\n}\r\n\r\n/**\r\n * 获取安全区域边距\r\n */\r\nexport function getSafeAreaInsets(): ViewportInfo['safeArea'] {\r\n if (\r\n typeof window === 'undefined' ||\r\n typeof CSS === 'undefined' ||\r\n !CSS.supports\r\n ) {\r\n return { top: 0, right: 0, bottom: 0, left: 0 }\r\n }\r\n\r\n // 检查是否支持 env() 函数\r\n if (!CSS.supports('padding-top', 'env(safe-area-inset-top)')) {\r\n return { top: 0, right: 0, bottom: 0, left: 0 }\r\n }\r\n\r\n // 创建临时元素获取安全区域值\r\n const div = document.createElement('div')\r\n div.style.cssText = `\r\n position: fixed;\r\n top: env(safe-area-inset-top);\r\n right: env(safe-area-inset-right);\r\n bottom: env(safe-area-inset-bottom);\r\n left: env(safe-area-inset-left);\r\n pointer-events: none;\r\n visibility: hidden;\r\n `\r\n const body = document.body\r\n if (!body) return { top: 0, right: 0, bottom: 0, left: 0 }\r\n body.appendChild(div)\r\n\r\n const computed = getComputedStyle(div)\r\n const safeArea = {\r\n top: Number.parseFloat(computed.top) || 0,\r\n right: Number.parseFloat(computed.right) || 0,\r\n bottom: Number.parseFloat(computed.bottom) || 0,\r\n left: Number.parseFloat(computed.left) || 0,\r\n }\r\n\r\n body.removeChild(div)\r\n return safeArea\r\n}\r\n\r\n/**\r\n * 检测是否支持震动 API\r\n */\r\nexport function supportsVibrate(): boolean {\r\n return typeof navigator !== 'undefined' && 'vibrate' in navigator\r\n}\r\n\r\n/**\r\n * 触发震动反馈\r\n * @param pattern - 震动模式(毫秒)\r\n */\r\nexport function vibrate(pattern: number | number[] = 10): boolean {\r\n if (supportsVibrate()) {\r\n return navigator.vibrate(pattern)\r\n }\r\n return false\r\n}\r\n\r\n/**\r\n * 监听视口变化\r\n * @param callback - 回调函数\r\n * @returns 取消监听函数\r\n */\r\nexport function onViewportChange(\r\n callback: (info: ViewportInfo) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => {}\r\n }\r\n\r\n const handler = () => {\r\n callback(getViewportInfo())\r\n }\r\n\r\n window.addEventListener('resize', handler)\r\n window.addEventListener('orientationchange', handler)\r\n\r\n return () => {\r\n window.removeEventListener('resize', handler)\r\n window.removeEventListener('orientationchange', handler)\r\n }\r\n}\r\n","/**\r\n * DOM 操作工具\r\n * @module utils/dom\r\n */\r\n\r\nimport type { BoundingRect, Position } from '../types'\r\n\r\n/**\r\n * 获取元素的边界矩形\r\n */\r\nexport function getBoundingRect(element: HTMLElement): BoundingRect {\r\n const rect = element.getBoundingClientRect()\r\n return {\r\n x: rect.left,\r\n y: rect.top,\r\n width: rect.width,\r\n height: rect.height,\r\n }\r\n}\r\n\r\n/**\r\n * 获取元素相对于文档的位置\r\n */\r\nexport function getElementOffset(element: HTMLElement): Position {\r\n const rect = element.getBoundingClientRect()\r\n const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft\r\n const scrollTop = window.pageYOffset || document.documentElement.scrollTop\r\n\r\n return {\r\n x: rect.left + scrollLeft,\r\n y: rect.top + scrollTop,\r\n }\r\n}\r\n\r\n/**\r\n * 检查元素是否在视口内\r\n */\r\nexport function isElementInViewport(element: HTMLElement): boolean {\r\n const rect = element.getBoundingClientRect()\r\n return (\r\n rect.top >= 0 &&\r\n rect.left >= 0 &&\r\n rect.bottom <=\r\n (window.innerHeight || document.documentElement.clientHeight) &&\r\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\r\n )\r\n}\r\n\r\n/**\r\n * 检查点击是否在元素外部\r\n */\r\nexport function isClickOutside(\r\n event: MouseEvent | TouchEvent,\r\n element: HTMLElement\r\n): boolean {\r\n const target = event.target as Node\r\n return !element.contains(target)\r\n}\r\n\r\n/**\r\n * 阻止元素默认事件(用于防止输入框获取焦点)\r\n */\r\nexport function preventDefaultAndStopPropagation(event: Event): void {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n}\r\n\r\n/**\r\n * 添加点击外部监听\r\n */\r\nexport function onClickOutside(\r\n element: HTMLElement,\r\n callback: (event: MouseEvent | TouchEvent) => void\r\n): () => void {\r\n const handler = (event: MouseEvent | TouchEvent) => {\r\n if (isClickOutside(event, element)) {\r\n callback(event)\r\n }\r\n }\r\n\r\n document.addEventListener('mousedown', handler)\r\n document.addEventListener('touchstart', handler)\r\n\r\n return () => {\r\n document.removeEventListener('mousedown', handler)\r\n document.removeEventListener('touchstart', handler)\r\n }\r\n}\r\n\r\n/**\r\n * 滚动元素到可视区域\r\n */\r\nexport function scrollIntoViewIfNeeded(\r\n element: HTMLElement,\r\n container?: HTMLElement\r\n): void {\r\n if (!container) {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'nearest' })\r\n return\r\n }\r\n\r\n const elementRect = element.getBoundingClientRect()\r\n const containerRect = container.getBoundingClientRect()\r\n\r\n if (elementRect.bottom > containerRect.bottom) {\r\n container.scrollTop += elementRect.bottom - containerRect.bottom\r\n } else if (elementRect.top < containerRect.top) {\r\n container.scrollTop -= containerRect.top - elementRect.top\r\n }\r\n}\r\n\r\n/**\r\n * 获取输入框的光标位置\r\n */\r\nexport function getInputCursorPosition(\r\n input: HTMLInputElement | HTMLTextAreaElement\r\n): number {\r\n return input.selectionStart ?? input.value.length\r\n}\r\n\r\n/**\r\n * 设置输入框的光标位置\r\n */\r\nexport function setInputCursorPosition(\r\n input: HTMLInputElement | HTMLTextAreaElement,\r\n position: number\r\n): void {\r\n input.setSelectionRange(position, position)\r\n}\r\n\r\n/**\r\n * 在输入框当前光标位置插入文本\r\n */\r\nexport function insertTextAtCursor(\r\n input: HTMLInputElement | HTMLTextAreaElement,\r\n text: string,\r\n maxLength?: number\r\n): { value: string; cursorPosition: number } {\r\n const start = input.selectionStart ?? input.value.length\r\n const end = input.selectionEnd ?? input.value.length\r\n const currentValue = input.value\r\n\r\n const normalizedMaxLength =\r\n maxLength === undefined || !Number.isFinite(maxLength)\r\n ? undefined\r\n : Math.max(0, Math.floor(maxLength))\r\n let insertedText = text\r\n let newValue =\r\n currentValue.substring(0, start) +\r\n insertedText +\r\n currentValue.substring(end)\r\n\r\n // 检查最大长度\r\n if (\r\n normalizedMaxLength !== undefined &&\r\n newValue.length > normalizedMaxLength\r\n ) {\r\n const allowedLength =\r\n normalizedMaxLength - (currentValue.length - (end - start))\r\n if (allowedLength <= 0) {\r\n return { value: currentValue, cursorPosition: start }\r\n }\r\n insertedText = text.substring(0, allowedLength)\r\n newValue =\r\n currentValue.substring(0, start) +\r\n insertedText +\r\n currentValue.substring(end)\r\n }\r\n\r\n const newCursorPosition = start + insertedText.length\r\n\r\n return {\r\n value: newValue,\r\n cursorPosition: Math.min(newCursorPosition, newValue.length),\r\n }\r\n}\r\n\r\n/**\r\n * 删除输入框光标前的字符\r\n */\r\nexport function deleteCharBeforeCursor(\r\n input: HTMLInputElement | HTMLTextAreaElement\r\n): { value: string; deletedChar: string; cursorPosition: number } {\r\n const start = input.selectionStart ?? input.value.length\r\n const end = input.selectionEnd ?? input.value.length\r\n const currentValue = input.value\r\n\r\n // 如果有选中内容,删除选中内容\r\n if (start !== end) {\r\n const deletedChar = currentValue.substring(start, end)\r\n const newValue =\r\n currentValue.substring(0, start) + currentValue.substring(end)\r\n return {\r\n value: newValue,\r\n deletedChar,\r\n cursorPosition: start,\r\n }\r\n }\r\n\r\n // 没有选中内容,删除光标前一个字符\r\n if (start === 0) {\r\n return {\r\n value: currentValue,\r\n deletedChar: '',\r\n cursorPosition: 0,\r\n }\r\n }\r\n\r\n const deletedChar = currentValue.charAt(start - 1)\r\n const newValue =\r\n currentValue.substring(0, start - 1) + currentValue.substring(start)\r\n\r\n return {\r\n value: newValue,\r\n deletedChar,\r\n cursorPosition: start - 1,\r\n }\r\n}\r\n\r\n/**\r\n * 创建 DOM 元素\r\n */\r\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\r\n tag: K,\r\n attrs?: Record<string, string>,\r\n children?: (HTMLElement | string)[]\r\n): HTMLElementTagNameMap[K] {\r\n const element = document.createElement(tag)\r\n\r\n if (attrs) {\r\n Object.entries(attrs).forEach(([key, value]) => {\r\n element.setAttribute(key, value)\r\n })\r\n }\r\n\r\n if (children) {\r\n children.forEach(child => {\r\n if (typeof child === 'string') {\r\n element.appendChild(document.createTextNode(child))\r\n } else {\r\n element.appendChild(child)\r\n }\r\n })\r\n }\r\n\r\n return element\r\n}\r\n\r\n/**\r\n * Sanitize a caller-provided SVG icon before inserting it into the DOM.\r\n */\r\nexport function sanitizeSvgIcon(icon: string): string {\r\n if (typeof DOMParser === 'undefined' || typeof XMLSerializer === 'undefined')\r\n return ''\r\n\r\n const document = new DOMParser().parseFromString(icon, 'image/svg+xml')\r\n const svg = document.documentElement\r\n if (\r\n svg.tagName.toLowerCase() !== 'svg' ||\r\n document.querySelector('parsererror')\r\n )\r\n return ''\r\n\r\n svg\r\n .querySelectorAll('script, style, foreignObject')\r\n .forEach(node => node.remove())\r\n svg.querySelectorAll('*').forEach(element => {\r\n Array.from(element.attributes).forEach(attribute => {\r\n const name = attribute.name.toLowerCase()\r\n const value = attribute.value.trim()\r\n if (\r\n name.startsWith('on') ||\r\n ((name === 'href' || name === 'xlink:href') && !value.startsWith('#'))\r\n ) {\r\n element.removeAttribute(attribute.name)\r\n }\r\n })\r\n })\r\n\r\n return new XMLSerializer().serializeToString(svg)\r\n}\r\n\r\n/**\r\n * 添加/移除 CSS 类\r\n */\r\nexport function toggleClass(\r\n element: HTMLElement,\r\n className: string,\r\n force?: boolean\r\n): void {\r\n element.classList.toggle(className, force)\r\n}\r\n\r\n/**\r\n * 设置 CSS 样式\r\n */\r\nexport function setStyles(\r\n element: HTMLElement,\r\n styles: Partial<CSSStyleDeclaration>\r\n): void {\r\n Object.assign(element.style, styles)\r\n}\r\n","/**\r\n * 事件发射器\r\n * @module utils/event-emitter\r\n */\r\n\r\n/**\r\n * 事件处理函数类型\r\n */\r\nexport type EventHandler<T = unknown> = (data: T) => void\r\n\r\n/**\r\n * 事件处理器配置\r\n */\r\nexport interface EventHandlerOptions {\r\n /**\r\n * 是否只触发一次\r\n */\r\n once?: boolean\r\n\r\n /**\r\n * 优先级(数字越大优先级越高)\r\n */\r\n priority?: number\r\n}\r\n\r\n/**\r\n * 内部事件处理器包装\r\n */\r\ninterface EventHandlerWrapper<T> {\r\n handler: EventHandler<T>\r\n options: EventHandlerOptions\r\n}\r\n\r\n/**\r\n * 事件发射器类\r\n */\r\nexport class EventEmitter<EventMap extends Record<string, unknown>> {\r\n private handlers = new Map<\r\n keyof EventMap,\r\n Set<EventHandlerWrapper<unknown>>\r\n >()\r\n\r\n /**\r\n * 订阅事件\r\n */\r\n on<K extends keyof EventMap>(\r\n event: K,\r\n handler: EventHandler<EventMap[K]>,\r\n options: EventHandlerOptions = {}\r\n ): () => void {\r\n if (!this.handlers.has(event)) {\r\n this.handlers.set(event, new Set())\r\n }\r\n\r\n const handlers = this.handlers.get(event)\r\n if (!handlers) {\r\n return () => undefined\r\n }\r\n const wrapper: EventHandlerWrapper<EventMap[K]> = {\r\n handler: handler as EventHandler<unknown>,\r\n options,\r\n }\r\n\r\n handlers.add(wrapper as EventHandlerWrapper<unknown>)\r\n\r\n return () => {\r\n handlers.delete(wrapper as EventHandlerWrapper<unknown>)\r\n if (handlers.size === 0) {\r\n this.handlers.delete(event)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 订阅事件(仅触发一次)\r\n */\r\n once<K extends keyof EventMap>(\r\n event: K,\r\n handler: EventHandler<EventMap[K]>,\r\n options: EventHandlerOptions = {}\r\n ): () => void {\r\n return this.on(event, handler, { ...options, once: true })\r\n }\r\n\r\n /**\r\n * 取消订阅事件\r\n */\r\n off<K extends keyof EventMap>(\r\n event: K,\r\n handler?: EventHandler<EventMap[K]>\r\n ): void {\r\n if (!handler) {\r\n this.handlers.delete(event)\r\n return\r\n }\r\n\r\n const handlers = this.handlers.get(event)\r\n if (handlers) {\r\n handlers.forEach(wrapper => {\r\n if (wrapper.handler === handler) {\r\n handlers.delete(wrapper)\r\n }\r\n })\r\n if (handlers.size === 0) {\r\n this.handlers.delete(event)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 发布事件\r\n */\r\n emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void {\r\n const handlers = this.handlers.get(event)\r\n if (!handlers || handlers.size === 0) {\r\n return\r\n }\r\n\r\n // 按优先级排序\r\n const sortedHandlers = Array.from(handlers).sort((a, b) => {\r\n const priorityA = a.options.priority ?? 0\r\n const priorityB = b.options.priority ?? 0\r\n return priorityB - priorityA\r\n })\r\n\r\n const toRemove: EventHandlerWrapper<unknown>[] = []\r\n\r\n sortedHandlers.forEach(wrapper => {\r\n try {\r\n wrapper.handler(data)\r\n if (wrapper.options.once) {\r\n toRemove.push(wrapper)\r\n }\r\n } catch (error) {\r\n console.error(\r\n `[KeyboardEventEmitter] Error in event handler for \"${String(event)}\":`,\r\n error\r\n )\r\n }\r\n })\r\n\r\n // 移除 once 处理器\r\n toRemove.forEach(wrapper => handlers.delete(wrapper))\r\n if (handlers.size === 0) {\r\n this.handlers.delete(event)\r\n }\r\n }\r\n\r\n /**\r\n * 清除所有事件订阅\r\n */\r\n clear(): void {\r\n this.handlers.clear()\r\n }\r\n\r\n /**\r\n * 获取事件订阅数量\r\n */\r\n listenerCount(event?: keyof EventMap): number {\r\n if (event !== undefined) {\r\n return this.handlers.get(event)?.size ?? 0\r\n }\r\n\r\n let count = 0\r\n this.handlers.forEach(handlers => {\r\n count += handlers.size\r\n })\r\n return count\r\n }\r\n}\r\n","/**\r\n * 键盘管理器\r\n * @module managers/keyboard-manager\r\n */\r\n\r\nimport type {\r\n KeyboardConfig,\r\n KeyboardEventMap,\r\n KeyboardOptions,\r\n KeyboardState,\r\n KeyboardType,\r\n KeyDefinition,\r\n} from '../types'\r\nimport { getLayout } from '../layouts'\r\nimport { isMobile, vibrate } from '../utils/device'\r\nimport {\r\n deleteCharBeforeCursor,\r\n getInputCursorPosition,\r\n insertTextAtCursor,\r\n setInputCursorPosition,\r\n} from '../utils/dom'\r\nimport { EventEmitter } from '../utils/event-emitter'\r\n\r\n/**\r\n * 默认键盘选项\r\n */\r\nconst DEFAULT_OPTIONS: Required<KeyboardOptions> = {\r\n type: 'qwerty',\r\n value: '',\r\n maxLength: undefined as unknown as number,\r\n defaultUpperCase: false,\r\n closeOnClickOutside: true,\r\n enableSound: false,\r\n enableVibrate: true,\r\n customLayouts: {},\r\n}\r\n\r\nfunction normalizeMaxLength(value: number | undefined): number | undefined {\r\n if (value === undefined || !Number.isFinite(value)) return undefined\r\n return Math.max(0, Math.floor(value))\r\n}\r\n\r\nfunction clampValue(value: string, maxLength: number | undefined): string {\r\n return maxLength === undefined ? value : value.slice(0, maxLength)\r\n}\r\n\r\n/**\r\n * 键盘管理器类\r\n * 处理键盘状态管理、输入处理等核心逻辑\r\n */\r\nexport class KeyboardManager extends EventEmitter<KeyboardEventMap> {\r\n /** 配置选项 */\r\n private options: Required<KeyboardOptions>\r\n\r\n /** 当前状态 */\r\n private state: KeyboardState\r\n\r\n /** 当前布局配置 */\r\n private currentLayout: KeyboardConfig | null = null\r\n\r\n private destroyed = false\r\n\r\n constructor(options: KeyboardOptions = {}) {\r\n super()\r\n const maxLength = normalizeMaxLength(options.maxLength)\r\n this.options = {\r\n ...DEFAULT_OPTIONS,\r\n ...options,\r\n maxLength,\r\n customLayouts: {\r\n ...DEFAULT_OPTIONS.customLayouts,\r\n ...(options.customLayouts ?? {}),\r\n },\r\n }\r\n\r\n // 注册自定义布局\r\n if (options.customLayouts) {\r\n Object.entries(options.customLayouts).forEach(([name, layout]) => {\r\n // 这里不用 registerLayout 以避免覆盖内置布局的警告\r\n this.options.customLayouts[name] = layout\r\n })\r\n }\r\n\r\n // 初始化状态\r\n this.state = {\r\n visible: false,\r\n type: this.options.type,\r\n isUpperCase: this.options.defaultUpperCase,\r\n value: clampValue(this.options.value, this.options.maxLength),\r\n cursorPosition: clampValue(this.options.value, this.options.maxLength)\r\n .length,\r\n maxLength: this.options.maxLength,\r\n inputElement: null,\r\n }\r\n\r\n // 加载初始布局\r\n this.loadLayout(this.options.type)\r\n }\r\n\r\n /**\r\n * 获取当前状态\r\n */\r\n getState(): Readonly<KeyboardState> {\r\n return { ...this.state }\r\n }\r\n\r\n /**\r\n * 获取当前布局配置\r\n */\r\n getLayout(): KeyboardConfig | null {\r\n return this.currentLayout\r\n }\r\n\r\n /**\r\n * 获取配置选项\r\n */\r\n getOptions(): Readonly<Required<KeyboardOptions>> {\r\n return { ...this.options, customLayouts: { ...this.options.customLayouts } }\r\n }\r\n\r\n /**\r\n * 加载键盘布局\r\n */\r\n private loadLayout(type: KeyboardType | string): boolean {\r\n // 先从自定义布局查找\r\n let layout = this.options.customLayouts[type]\r\n\r\n // 再从内置布局查找\r\n if (!layout) {\r\n layout = getLayout(type) as KeyboardConfig\r\n }\r\n\r\n if (!layout) {\r\n console.error(`[KeyboardManager] Layout \"${type}\" not found`)\r\n return false\r\n }\r\n\r\n this.currentLayout = layout\r\n\r\n // 更新大小写状态\r\n if (layout.supportShift) {\r\n this.state.isUpperCase =\r\n layout.defaultUpperCase ?? this.options.defaultUpperCase\r\n }\r\n\r\n return true\r\n }\r\n\r\n /**\r\n * 显示键盘\r\n */\r\n show(inputElement?: HTMLInputElement | HTMLTextAreaElement): void {\r\n if (this.destroyed) return\r\n if (this.state.visible) {\r\n if (inputElement && this.state.inputElement !== inputElement) {\r\n this.bindInput(inputElement)\r\n }\r\n return\r\n }\r\n\r\n this.state.visible = true\r\n this.state.inputElement = inputElement ?? null\r\n\r\n // 同步输入框的值\r\n if (inputElement) {\r\n this.state.value = inputElement.value\r\n this.state.cursorPosition = getInputCursorPosition(inputElement)\r\n }\r\n\r\n this.emitStateChange()\r\n this.emit('show', { type: this.state.type })\r\n }\r\n\r\n /**\r\n * 隐藏键盘\r\n */\r\n hide(): void {\r\n if (this.destroyed) return\r\n if (!this.state.visible) return\r\n\r\n const prevType = this.state.type\r\n this.state.visible = false\r\n this.state.inputElement = null\r\n\r\n this.emitStateChange()\r\n this.emit('hide', { type: prevType })\r\n }\r\n\r\n /**\r\n * 切换键盘显示/隐藏\r\n */\r\n toggle(inputElement?: HTMLInputElement | HTMLTextAreaElement): void {\r\n if (this.destroyed) return\r\n if (this.state.visible) {\r\n this.hide()\r\n } else {\r\n this.show(inputElement)\r\n }\r\n }\r\n\r\n /**\r\n * 切换键盘类型\r\n */\r\n switchType(type: KeyboardType | string): void {\r\n if (this.destroyed) return\r\n if (this.state.type === type) return\r\n\r\n const fromType = this.state.type\r\n if (!this.loadLayout(type)) return\r\n\r\n this.state.type = type as KeyboardType\r\n\r\n this.emitStateChange()\r\n this.emit('switch', { from: fromType, to: type as KeyboardType })\r\n }\r\n\r\n /**\r\n * 切换大小写\r\n */\r\n toggleShift(): void {\r\n if (this.destroyed) return\r\n if (!this.currentLayout?.supportShift) return\r\n\r\n this.state.isUpperCase = !this.state.isUpperCase\r\n this.emitStateChange()\r\n this.emit('shift', { isUpperCase: this.state.isUpperCase })\r\n }\r\n\r\n /**\r\n * 设置大小写状态\r\n */\r\n setShift(isUpperCase: boolean): void {\r\n if (this.destroyed) return\r\n if (!this.currentLayout?.supportShift) return\r\n if (this.state.isUpperCase === isUpperCase) return\r\n\r\n this.state.isUpperCase = isUpperCase\r\n this.emitStateChange()\r\n this.emit('shift', { isUpperCase })\r\n }\r\n\r\n /**\r\n * 处理按键\r\n */\r\n handleKey(key: KeyDefinition): void {\r\n if (this.destroyed) return\r\n // 触发震动反馈\r\n if (this.options.enableVibrate && isMobile()) {\r\n vibrate(10)\r\n }\r\n\r\n this.emit('keypress', { key, value: this.state.value })\r\n\r\n switch (key.type) {\r\n case 'char':\r\n case 'space':\r\n this.handleCharKey(key)\r\n break\r\n case 'backspace':\r\n this.handleBackspace()\r\n break\r\n case 'shift':\r\n this.toggleShift()\r\n break\r\n case 'clear':\r\n this.handleClear()\r\n break\r\n case 'enter':\r\n case 'done':\r\n this.handleConfirm()\r\n break\r\n case 'close':\r\n this.hide()\r\n break\r\n case 'tab':\r\n this.handleTab(key)\r\n break\r\n case 'custom':\r\n // 自定义按键,只触发事件\r\n break\r\n }\r\n }\r\n\r\n /**\r\n * 处理字符输入\r\n */\r\n private handleCharKey(key: KeyDefinition): void {\r\n const keyValue = this.getKeyValue(key)\r\n if (!keyValue) return\r\n\r\n const input = this.state.inputElement\r\n\r\n if (input) {\r\n // 如果有绑定输入框,直接操作输入框\r\n const result = insertTextAtCursor(input, keyValue, this.state.maxLength)\r\n input.value = result.value\r\n setInputCursorPosition(input, result.cursorPosition)\r\n this.state.value = result.value\r\n this.state.cursorPosition = result.cursorPosition\r\n\r\n // 触发原生 input 事件\r\n this.dispatchInputEvent(input)\r\n } else {\r\n // 没有输入框,直接修改内部值\r\n if (\r\n this.state.maxLength !== undefined &&\r\n this.state.value.length >= this.state.maxLength\r\n ) {\r\n return\r\n }\r\n const availableLength =\r\n this.state.maxLength === undefined\r\n ? keyValue.length\r\n : this.state.maxLength - this.state.value.length\r\n const valueToInsert = keyValue.slice(0, Math.max(0, availableLength))\r\n if (!valueToInsert) return\r\n const newValue =\r\n this.state.value.slice(0, this.state.cursorPosition) +\r\n valueToInsert +\r\n this.state.value.slice(this.state.cursorPosition)\r\n this.state.value = newValue\r\n this.state.cursorPosition += valueToInsert.length\r\n }\r\n\r\n this.emitStateChange()\r\n this.emit('input', { value: this.state.value, key })\r\n\r\n // 车牌号智能切换\r\n this.autoSwitchLicensePlate()\r\n }\r\n\r\n /**\r\n * 处理退格\r\n */\r\n private handleBackspace(): void {\r\n const input = this.state.inputElement\r\n\r\n if (input) {\r\n const result = deleteCharBeforeCursor(input)\r\n input.value = result.value\r\n setInputCursorPosition(input, result.cursorPosition)\r\n this.state.value = result.value\r\n this.state.cursorPosition = result.cursorPosition\r\n\r\n // 触发原生 input 事件\r\n this.dispatchInputEvent(input)\r\n\r\n this.emitStateChange()\r\n this.emit('backspace', {\r\n deletedChar: result.deletedChar,\r\n value: this.state.value,\r\n })\r\n } else {\r\n if (this.state.cursorPosition === 0) return\r\n\r\n const deletedChar = this.state.value.charAt(this.state.cursorPosition - 1)\r\n this.state.value =\r\n this.state.value.slice(0, this.state.cursorPosition - 1) +\r\n this.state.value.slice(this.state.cursorPosition)\r\n this.state.cursorPosition--\r\n\r\n this.emitStateChange()\r\n this.emit('backspace', { deletedChar, value: this.state.value })\r\n }\r\n\r\n // 车牌号智能切换\r\n this.autoSwitchLicensePlate()\r\n }\r\n\r\n /**\r\n * 车牌号智能切换逻辑\r\n * 根据当前值长度自动切换键盘布局\r\n * 只有 2 种布局:省份键盘(第1位)和 字母+数字混合键盘(第2-8位)\r\n */\r\n private autoSwitchLicensePlate(): void {\r\n // 只在车牌键盘类型时生效\r\n if (!this.state.type.startsWith('license-plate')) return\r\n\r\n const len = this.state.value.length\r\n let targetType: string | null = null\r\n\r\n if (len === 0) {\r\n // 第1位:省份简称\r\n targetType = 'license-plate-province'\r\n } else {\r\n // 第2-8位:字母+数字混合键盘\r\n // (第2位虽然只能输入字母,但显示混合键盘,用户自己知道不能输入数字)\r\n targetType = 'license-plate-alphanumeric'\r\n }\r\n\r\n // 如果需要切换\r\n if (targetType && this.state.type !== targetType) {\r\n this.switchType(targetType)\r\n }\r\n }\r\n\r\n /**\r\n * 处理清空\r\n */\r\n private handleClear(): void {\r\n const previousValue = this.state.value\r\n\r\n if (this.state.inputElement) {\r\n this.state.inputElement.value = ''\r\n this.dispatchInputEvent(this.state.inputElement)\r\n }\r\n\r\n this.state.value = ''\r\n this.state.cursorPosition = 0\r\n\r\n this.emitStateChange()\r\n this.emit('clear', { previousValue })\r\n\r\n // 车牌号智能切换\r\n this.autoSwitchLicensePlate()\r\n }\r\n\r\n /**\r\n * 处理确认\r\n */\r\n private handleConfirm(): void {\r\n this.emit('confirm', { value: this.state.value })\r\n this.hide()\r\n }\r\n\r\n /**\r\n * 处理切换键盘\r\n */\r\n private handleTab(key: KeyDefinition): void {\r\n const targetType = key.data?.targetType as KeyboardType | string | undefined\r\n if (targetType) {\r\n this.switchType(targetType)\r\n }\r\n }\r\n\r\n /**\r\n * 获取按键的实际输出值\r\n */\r\n private getKeyValue(key: KeyDefinition): string {\r\n const value = key.value ?? key.label\r\n\r\n if (typeof value === 'string') {\r\n return value\r\n }\r\n\r\n return this.state.isUpperCase ? value.upper : value.lower\r\n }\r\n\r\n /**\r\n * 获取按键的显示文本\r\n */\r\n getKeyLabel(key: KeyDefinition): string {\r\n const label = key.label\r\n\r\n if (typeof label === 'string') {\r\n return label\r\n }\r\n\r\n return this.state.isUpperCase ? label.upper : label.lower\r\n }\r\n\r\n /**\r\n * 设置值\r\n */\r\n setValue(value: string): void {\r\n if (this.destroyed) return\r\n const nextValue = clampValue(value, this.state.maxLength)\r\n this.state.value = nextValue\r\n this.state.cursorPosition = nextValue.length\r\n\r\n if (this.state.inputElement) {\r\n this.state.inputElement.value = nextValue\r\n setInputCursorPosition(this.state.inputElement, nextValue.length)\r\n this.dispatchInputEvent(this.state.inputElement)\r\n }\r\n\r\n this.emitStateChange()\r\n\r\n // 车牌号智能切换\r\n this.autoSwitchLicensePlate()\r\n }\r\n\r\n /**\r\n * 追加值(在光标位置插入文本)\r\n */\r\n appendValue(text: string): void {\r\n if (this.destroyed) return\r\n if (!text) return\r\n\r\n const input = this.state.inputElement\r\n\r\n if (input) {\r\n const result = insertTextAtCursor(input, text, this.state.maxLength)\r\n input.value = result.value\r\n setInputCursorPosition(input, result.cursorPosition)\r\n this.state.value = result.value\r\n this.state.cursorPosition = result.cursorPosition\r\n\r\n // 触发原生 input 事件\r\n this.dispatchInputEvent(input)\r\n } else {\r\n if (this.state.maxLength !== undefined) {\r\n text = text.slice(\r\n 0,\r\n Math.max(0, this.state.maxLength - this.state.value.length)\r\n )\r\n }\r\n if (!text) return\r\n const newValue =\r\n this.state.value.slice(0, this.state.cursorPosition) +\r\n text +\r\n this.state.value.slice(this.state.cursorPosition)\r\n this.state.value = newValue\r\n this.state.cursorPosition += text.length\r\n }\r\n\r\n this.emitStateChange()\r\n }\r\n\r\n /**\r\n * 设置最大长度\r\n */\r\n setMaxLength(maxLength?: number): void {\r\n if (this.destroyed) return\r\n const normalizedMaxLength = normalizeMaxLength(maxLength)\r\n this.state.maxLength = normalizedMaxLength\r\n const nextValue = clampValue(this.state.value, normalizedMaxLength)\r\n const changed = nextValue !== this.state.value\r\n this.state.value = nextValue\r\n this.state.cursorPosition = Math.min(\r\n this.state.cursorPosition,\r\n nextValue.length\r\n )\r\n if (\r\n this.state.inputElement &&\r\n this.state.inputElement.value !== nextValue\r\n ) {\r\n this.state.inputElement.value = nextValue\r\n setInputCursorPosition(this.state.inputElement, this.state.cursorPosition)\r\n this.dispatchInputEvent(this.state.inputElement)\r\n }\r\n this.emitStateChange()\r\n if (changed) this.autoSwitchLicensePlate()\r\n }\r\n\r\n /**\r\n * 绑定输入框\r\n */\r\n bindInput(input: HTMLInputElement | HTMLTextAreaElement): void {\r\n if (this.destroyed) return\r\n this.state.inputElement = input\r\n const nextValue = clampValue(input.value, this.state.maxLength)\r\n if (input.value !== nextValue) input.value = nextValue\r\n this.state.value = nextValue\r\n this.state.cursorPosition = Math.min(\r\n getInputCursorPosition(input),\r\n nextValue.length\r\n )\r\n this.emitStateChange()\r\n }\r\n\r\n /**\r\n * 解绑输入框\r\n */\r\n unbindInput(): void {\r\n if (this.destroyed) return\r\n this.state.inputElement = null\r\n this.emitStateChange()\r\n }\r\n\r\n /**\r\n * 发送状态变化事件\r\n */\r\n private emitStateChange(): void {\r\n this.emit('stateChange', { ...this.state })\r\n }\r\n\r\n private dispatchInputEvent(\r\n input: HTMLInputElement | HTMLTextAreaElement\r\n ): void {\r\n const EventConstructor = input.ownerDocument.defaultView?.Event ?? Event\r\n input.dispatchEvent(new EventConstructor('input', { bubbles: true }))\r\n }\r\n\r\n /**\r\n * 销毁\r\n */\r\n destroy(): void {\r\n if (this.destroyed) return\r\n this.hide()\r\n this.clear()\r\n this.state.inputElement = null\r\n this.destroyed = true\r\n }\r\n}\r\n\r\n/**\r\n * 创建键盘管理器实例\r\n */\r\nexport function createKeyboardManager(\r\n options?: KeyboardOptions\r\n): KeyboardManager {\r\n return new KeyboardManager(options)\r\n}\r\n","/**\r\n * 预设主题配置\r\n * @module themes/presets\r\n */\r\n\r\nimport type { ThemeConfig } from './types'\r\n\r\n/**\r\n * MIUI 小米风格主题(默认)\r\n * 特点:纯净、扁平、简洁、无多余装饰\r\n */\r\nexport const miuiTheme: ThemeConfig = {\r\n name: 'miui',\r\n displayName: 'MIUI',\r\n description: '小米风格 - 纯净简洁',\r\n isDark: false,\r\n colors: {\r\n background: '#f5f5f5',\r\n keyBackground: '#ffffff',\r\n keyColor: '#1a1a1a',\r\n keyActiveBackground: '#e8e8e8',\r\n fnKeyBackground: '#e0e0e0',\r\n fnKeyColor: '#666666',\r\n fnKeyActiveBackground: '#d0d0d0',\r\n primaryBackground: '#ff6700', // 小米橙\r\n primaryActiveBackground: '#e55d00',\r\n primaryColor: '#ffffff',\r\n borderColor: 'transparent',\r\n dividerColor: '#eeeeee',\r\n },\r\n sizes: {\r\n keyHeight: 46,\r\n keyRadius: 8,\r\n keyGap: 6,\r\n fontSize: 18,\r\n fnFontSize: 14,\r\n padding: 8,\r\n },\r\n effects: {\r\n keyShadow: 'none',\r\n keyActiveShadow: 'none',\r\n keyActiveScale: 0.96,\r\n transitionDuration: 100,\r\n enableBlur: false,\r\n blurAmount: 0,\r\n enableRipple: false,\r\n },\r\n}\r\n\r\n/**\r\n * iOS 风格主题\r\n * 特点:毛玻璃、圆润阴影、精致\r\n */\r\nexport const iosTheme: ThemeConfig = {\r\n name: 'ios',\r\n displayName: 'iOS',\r\n description: 'Apple 风格 - 精致优雅',\r\n isDark: false,\r\n colors: {\r\n background: '#d1d3d9',\r\n keyBackground: '#ffffff',\r\n keyColor: '#000000',\r\n keyActiveBackground: '#b8bac2',\r\n fnKeyBackground: '#a8aab4',\r\n fnKeyColor: '#000000',\r\n fnKeyActiveBackground: '#9699a3',\r\n primaryBackground: '#007aff',\r\n primaryActiveBackground: '#0062cc',\r\n primaryColor: '#ffffff',\r\n borderColor: 'transparent',\r\n dividerColor: '#c8cad0',\r\n },\r\n sizes: {\r\n keyHeight: 43,\r\n keyRadius: 5,\r\n keyGap: 6,\r\n fontSize: 22,\r\n fnFontSize: 15,\r\n padding: 4,\r\n },\r\n effects: {\r\n keyShadow: '0 1px 0 rgba(0,0,0,0.35)',\r\n keyActiveShadow: '0 0 0 rgba(0,0,0,0)',\r\n keyActiveScale: 1,\r\n transitionDuration: 80,\r\n enableBlur: true,\r\n blurAmount: 20,\r\n enableRipple: false,\r\n },\r\n}\r\n\r\n/**\r\n * Material Design 主题\r\n * 特点:深色、涟漪动效、层次感\r\n */\r\nexport const materialTheme: ThemeConfig = {\r\n name: 'material',\r\n displayName: 'Material',\r\n description: 'Google 风格 - 深邃现代',\r\n isDark: true,\r\n colors: {\r\n background: '#263238',\r\n keyBackground: '#37474f',\r\n keyColor: '#ffffff',\r\n keyActiveBackground: '#455a64',\r\n fnKeyBackground: '#455a64',\r\n fnKeyColor: '#b0bec5',\r\n fnKeyActiveBackground: '#546e7a',\r\n primaryBackground: '#4caf50', // Material Green\r\n primaryActiveBackground: '#43a047',\r\n primaryColor: '#ffffff',\r\n borderColor: 'transparent',\r\n dividerColor: '#37474f',\r\n },\r\n sizes: {\r\n keyHeight: 48,\r\n keyRadius: 4,\r\n keyGap: 4,\r\n fontSize: 20,\r\n fnFontSize: 14,\r\n padding: 6,\r\n },\r\n effects: {\r\n keyShadow: '0 1px 3px rgba(0,0,0,0.2)',\r\n keyActiveShadow: '0 2px 6px rgba(0,0,0,0.3)',\r\n keyActiveScale: 1,\r\n transitionDuration: 150,\r\n enableBlur: false,\r\n blurAmount: 0,\r\n enableRipple: true,\r\n },\r\n}\r\n\r\n/**\r\n * 极简主题\r\n * 特点:无边框、超简洁、透明感\r\n */\r\nexport const minimalTheme: ThemeConfig = {\r\n name: 'minimal',\r\n displayName: 'Minimal',\r\n description: '极简风格 - 轻盈透明',\r\n isDark: false,\r\n colors: {\r\n background: 'rgba(250, 250, 250, 0.95)',\r\n keyBackground: 'transparent',\r\n keyColor: '#333333',\r\n keyActiveBackground: 'rgba(0, 0, 0, 0.08)',\r\n fnKeyBackground: 'transparent',\r\n fnKeyColor: '#888888',\r\n fnKeyActiveBackground: 'rgba(0, 0, 0, 0.08)',\r\n primaryBackground: '#333333',\r\n primaryActiveBackground: '#000000',\r\n primaryColor: '#ffffff',\r\n borderColor: '#eeeeee',\r\n dividerColor: '#eeeeee',\r\n },\r\n sizes: {\r\n keyHeight: 44,\r\n keyRadius: 12,\r\n keyGap: 8,\r\n fontSize: 17,\r\n fnFontSize: 13,\r\n padding: 12,\r\n },\r\n effects: {\r\n keyShadow: 'none',\r\n keyActiveShadow: 'none',\r\n keyActiveScale: 0.92,\r\n transitionDuration: 120,\r\n enableBlur: true,\r\n blurAmount: 30,\r\n enableRipple: false,\r\n },\r\n}\r\n\r\n/**\r\n * 深色主题\r\n * 特点:护眼、现代、高对比\r\n */\r\nexport const darkTheme: ThemeConfig = {\r\n name: 'dark',\r\n displayName: 'Dark',\r\n description: '深色模式 - 护眼舒适',\r\n isDark: true,\r\n colors: {\r\n background: '#1c1c1e',\r\n keyBackground: '#3a3a3c',\r\n keyColor: '#ffffff',\r\n keyActiveBackground: '#4a4a4c',\r\n fnKeyBackground: '#2c2c2e',\r\n fnKeyColor: '#ebebf5',\r\n fnKeyActiveBackground: '#3c3c3e',\r\n primaryBackground: '#0a84ff',\r\n primaryActiveBackground: '#0070e0',\r\n primaryColor: '#ffffff',\r\n borderColor: '#3a3a3c',\r\n dividerColor: '#3a3a3c',\r\n },\r\n sizes: {\r\n keyHeight: 45,\r\n keyRadius: 8,\r\n keyGap: 6,\r\n fontSize: 18,\r\n fnFontSize: 14,\r\n padding: 8,\r\n },\r\n effects: {\r\n keyShadow: '0 1px 2px rgba(0,0,0,0.4)',\r\n keyActiveShadow: '0 0 8px rgba(10,132,255,0.3)',\r\n keyActiveScale: 0.97,\r\n transitionDuration: 100,\r\n enableBlur: true,\r\n blurAmount: 20,\r\n enableRipple: false,\r\n },\r\n}\r\n\r\n/**\r\n * 所有预设主题\r\n */\r\nexport const presetThemes: Record<string, ThemeConfig> = {\r\n miui: miuiTheme,\r\n ios: iosTheme,\r\n material: materialTheme,\r\n minimal: minimalTheme,\r\n dark: darkTheme,\r\n}\r\n\r\n/**\r\n * 默认主题\r\n */\r\nexport const defaultTheme = miuiTheme\r\n","/**\r\n * 主题管理模块\r\n * @module themes\r\n */\r\n\r\nimport type { ThemeConfig, ThemeCSSVariables, ThemeName } from './types'\r\nimport { defaultTheme, presetThemes } from './presets'\r\n\r\nexport * from './presets'\r\nexport * from './types'\r\n\r\n/**\r\n * 自定义主题存储\r\n */\r\nconst customThemes: Map<string, ThemeConfig> = new Map()\r\n\r\n/**\r\n * 当前激活的主题\r\n */\r\nlet currentTheme: ThemeConfig = defaultTheme\r\n\r\n/**\r\n * 获取主题配置\r\n * @param name - 主题名称\r\n * @returns 主题配置,如果不存在则返回默认主题\r\n */\r\nexport function getTheme(name: ThemeName | string): ThemeConfig {\r\n return customThemes.get(name) || presetThemes[name] || defaultTheme\r\n}\r\n\r\n/**\r\n * 注册自定义主题\r\n * @param theme - 主题配置\r\n */\r\nexport function registerTheme(theme: ThemeConfig): void {\r\n customThemes.set(theme.name, theme)\r\n}\r\n\r\n/**\r\n * 获取所有可用主题\r\n * @returns 主题名称列表\r\n */\r\nexport function getAvailableThemes(): string[] {\r\n return [...Object.keys(presetThemes), ...customThemes.keys()]\r\n}\r\n\r\n/**\r\n * 获取所有主题配置\r\n * @returns 主题配置列表\r\n */\r\nexport function getAllThemes(): ThemeConfig[] {\r\n return [...Object.values(presetThemes), ...customThemes.values()]\r\n}\r\n\r\n/**\r\n * 设置当前主题\r\n * @param name - 主题名称\r\n */\r\nexport function setCurrentTheme(name: ThemeName | string): ThemeConfig {\r\n currentTheme = getTheme(name)\r\n return currentTheme\r\n}\r\n\r\n/**\r\n * 获取当前主题\r\n */\r\nexport function getCurrentTheme(): ThemeConfig {\r\n return currentTheme\r\n}\r\n\r\n/**\r\n * 将主题配置转换为 CSS 变量\r\n * @param theme - 主题配置\r\n * @returns CSS 变量对象\r\n */\r\nexport function themeToCSS(theme: ThemeConfig): ThemeCSSVariables {\r\n return {\r\n '--keyboard-bg': theme.colors.background,\r\n '--keyboard-key-bg': theme.colors.keyBackground,\r\n '--keyboard-key-color': theme.colors.keyColor,\r\n '--keyboard-key-active-bg': theme.colors.keyActiveBackground,\r\n '--keyboard-fn-key-bg': theme.colors.fnKeyBackground,\r\n '--keyboard-fn-key-color': theme.colors.fnKeyColor,\r\n '--keyboard-fn-key-active-bg': theme.colors.fnKeyActiveBackground,\r\n '--keyboard-primary-bg': theme.colors.primaryBackground,\r\n '--keyboard-primary-active-bg': theme.colors.primaryActiveBackground,\r\n '--keyboard-primary-color': theme.colors.primaryColor,\r\n '--keyboard-key-height': `${theme.sizes.keyHeight}px`,\r\n '--keyboard-key-radius': `${theme.sizes.keyRadius}px`,\r\n '--keyboard-key-gap': `${theme.sizes.keyGap}px`,\r\n '--keyboard-font-size': `${theme.sizes.fontSize}px`,\r\n '--keyboard-fn-font-size': `${theme.sizes.fnFontSize}px`,\r\n '--keyboard-padding': `${theme.sizes.padding}px`,\r\n '--keyboard-key-shadow': theme.effects.keyShadow,\r\n '--keyboard-mask-bg':\r\n 'color-mix(in srgb, var(--ld-black) 40%, var(--ld-transparent))',\r\n '--keyboard-transition-duration': `${theme.effects.transitionDuration}ms`,\r\n '--keyboard-border-color': theme.colors.borderColor,\r\n '--keyboard-divider-color': theme.colors.dividerColor,\r\n }\r\n}\r\n\r\n/**\r\n * 将 CSS 变量应用到元素\r\n * @param element - 目标元素\r\n * @param theme - 主题配置\r\n */\r\nexport function applyTheme(element: HTMLElement, theme: ThemeConfig): void {\r\n const cssVars = themeToCSS(theme)\r\n Object.entries(cssVars).forEach(([key, value]) => {\r\n if (value) {\r\n element.style.setProperty(key, value)\r\n }\r\n })\r\n\r\n // 添加主题类名\r\n element.classList.remove('keyboard-theme-light', 'keyboard-theme-dark')\r\n element.classList.add(\r\n theme.isDark ? 'keyboard-theme-dark' : 'keyboard-theme-light'\r\n )\r\n element.dataset.theme = theme.name\r\n}\r\n\r\n/**\r\n * 生成主题的内联样式字符串\r\n * @param theme - 主题配置\r\n * @returns 内联样式字符串\r\n */\r\nexport function generateThemeStyle(theme: ThemeConfig): string {\r\n const cssVars = themeToCSS(theme)\r\n return Object.entries(cssVars)\r\n .filter(([, value]) => value)\r\n .map(([key, value]) => `${key}: ${value}`)\r\n .join('; ')\r\n}\r\n\r\n/**\r\n * 合并主题配置\r\n * @param base - 基础主题\r\n * @param overrides - 覆盖配置\r\n * @returns 合并后的主题\r\n */\r\nexport function mergeTheme(\r\n base: ThemeConfig,\r\n overrides: Partial<ThemeConfig>\r\n): ThemeConfig {\r\n return {\r\n ...base,\r\n ...overrides,\r\n colors: { ...base.colors, ...overrides.colors },\r\n sizes: { ...base.sizes, ...overrides.sizes },\r\n effects: { ...base.effects, ...overrides.effects },\r\n }\r\n}\r\n\r\n/**\r\n * 创建自定义主题\r\n * @param name - 主题名称\r\n * @param baseTheme - 基础主题名称\r\n * @param customization - 自定义配置\r\n */\r\nexport function createTheme(\r\n name: string,\r\n baseTheme: ThemeName | string,\r\n customization: Partial<Omit<ThemeConfig, 'name'>>\r\n): ThemeConfig {\r\n const base = getTheme(baseTheme)\r\n const theme = mergeTheme(base, {\r\n ...customization,\r\n name,\r\n })\r\n registerTheme(theme)\r\n return theme\r\n}\r\n","/**\r\n * 弹出位置管理器\r\n * @module managers/position-manager\r\n */\r\n\r\nimport type {\r\n BoundingRect,\r\n PopupPlacement,\r\n PopupPositionConfig,\r\n PopupPositionResult,\r\n Position,\r\n} from '../types'\r\nimport { getViewportInfo, isMobile } from '../utils/device'\r\nimport { getBoundingRect } from '../utils/dom'\r\n\r\n/**\r\n * 默认位置配置\r\n */\r\nconst DEFAULT_CONFIG: Required<PopupPositionConfig> = {\r\n offset: { x: 0, y: 8 },\r\n autoAdjust: true,\r\n viewportPadding: 8,\r\n desktopPlacement: 'bottom',\r\n mobilePlacement: 'bottom-sheet',\r\n showMask: true,\r\n maskClosable: true,\r\n animationDuration: 300,\r\n}\r\n\r\nfunction mergeConfig(\r\n config: PopupPositionConfig = {}\r\n): Required<PopupPositionConfig> {\r\n return {\r\n ...DEFAULT_CONFIG,\r\n ...config,\r\n offset: {\r\n ...DEFAULT_CONFIG.offset,\r\n ...config.offset,\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 位置管理器类\r\n * 计算键盘弹出层的位置,支持 PC 和移动端自适应\r\n */\r\nexport class PositionManager {\r\n private config: Required<PopupPositionConfig>\r\n\r\n constructor(config: PopupPositionConfig = {}) {\r\n this.config = mergeConfig(config)\r\n }\r\n\r\n /**\r\n * 更新配置\r\n */\r\n updateConfig(config: Partial<PopupPositionConfig>): void {\r\n this.config = mergeConfig({\r\n ...this.config,\r\n ...config,\r\n offset: { ...this.config.offset, ...config.offset },\r\n })\r\n }\r\n\r\n /**\r\n * 获取配置\r\n */\r\n getConfig(): Readonly<Required<PopupPositionConfig>> {\r\n return { ...this.config, offset: { ...this.config.offset } }\r\n }\r\n\r\n /**\r\n * 计算弹出位置\r\n * @param targetElement - 目标元素(如 input)\r\n * @param popupSize - 弹出层尺寸\r\n * @param popupSize.width - Popup width\r\n * @param popupSize.height - Popup height\r\n * @returns 位置计算结果\r\n */\r\n calculate(\r\n targetElement: HTMLElement | null,\r\n popupSize: { width: number; height: number }\r\n ): PopupPositionResult {\r\n const viewport = getViewportInfo()\r\n const isMobileDevice = isMobile()\r\n\r\n // 移动端使用 bottom-sheet\r\n if (isMobileDevice && this.config.mobilePlacement === 'bottom-sheet') {\r\n return this.calculateBottomSheet(viewport, popupSize)\r\n }\r\n\r\n // PC 端或移动端非 bottom-sheet\r\n if (!targetElement) {\r\n // 无目标元素,居中显示\r\n return this.calculateCentered(viewport, popupSize)\r\n }\r\n\r\n const targetRect = getBoundingRect(targetElement)\r\n const placement = isMobileDevice\r\n ? this.config.mobilePlacement\r\n : this.config.desktopPlacement\r\n\r\n // bottom-sheet 已经在前面处理,这里只会是 'bottom' 或 'top'\r\n const relativePlace = placement === 'bottom-sheet' ? 'bottom' : placement\r\n return this.calculateRelativeToTarget(\r\n targetRect,\r\n popupSize,\r\n viewport,\r\n relativePlace\r\n )\r\n }\r\n\r\n /**\r\n * 计算 bottom-sheet 位置(移动端从底部滑出)\r\n */\r\n private calculateBottomSheet(\r\n viewport: {\r\n width: number\r\n height: number\r\n scrollY: number\r\n safeArea?: { bottom: number }\r\n },\r\n popupSize: { width: number; height: number }\r\n ): PopupPositionResult {\r\n const safeAreaBottom = viewport.safeArea?.bottom ?? 0\r\n const maxHeight = Math.max(0, viewport.height * 0.6 - safeAreaBottom)\r\n const visibleHeight = Math.min(Math.max(0, popupSize.height), maxHeight)\r\n\r\n return {\r\n position: {\r\n x: 0,\r\n y: Math.max(0, viewport.height - visibleHeight - safeAreaBottom),\r\n },\r\n placement: 'bottom-sheet',\r\n flipped: false,\r\n maxHeight,\r\n maxWidth: Math.max(0, viewport.width),\r\n transform: 'translateY(0)',\r\n }\r\n }\r\n\r\n /**\r\n * 计算居中位置\r\n */\r\n private calculateCentered(\r\n viewport: { width: number; height: number },\r\n popupSize: { width: number; height: number }\r\n ): PopupPositionResult {\r\n return {\r\n position: {\r\n x: Math.max(0, (viewport.width - popupSize.width) / 2),\r\n y: Math.max(0, (viewport.height - popupSize.height) / 2),\r\n },\r\n placement: 'bottom',\r\n flipped: false,\r\n }\r\n }\r\n\r\n /**\r\n * 计算相对于目标元素的位置\r\n */\r\n private calculateRelativeToTarget(\r\n targetRect: BoundingRect,\r\n popupSize: { width: number; height: number },\r\n viewport: {\r\n width: number\r\n height: number\r\n scrollX: number\r\n scrollY: number\r\n },\r\n preferredPlacement: Exclude<PopupPlacement, 'bottom-sheet'>\r\n ): PopupPositionResult {\r\n const { offset, viewportPadding, autoAdjust } = this.config\r\n\r\n let position: Position\r\n let placement = preferredPlacement\r\n let flipped = false\r\n\r\n // 计算 bottom 位置(左对齐)\r\n const bottomPosition: Position = {\r\n x: targetRect.x + (offset.x ?? 0),\r\n y: targetRect.y + targetRect.height + (offset.y ?? 8),\r\n }\r\n\r\n // 计算 top 位置(左对齐)\r\n const topPosition: Position = {\r\n x: targetRect.x + (offset.x ?? 0),\r\n y: targetRect.y - popupSize.height - (offset.y ?? 8),\r\n }\r\n\r\n if (preferredPlacement === 'bottom') {\r\n position = bottomPosition\r\n\r\n // 检查是否需要翻转到顶部\r\n if (\r\n autoAdjust &&\r\n position.y + popupSize.height > viewport.height - viewportPadding\r\n ) {\r\n // 检查顶部是否有足够空间\r\n if (topPosition.y >= viewportPadding) {\r\n position = topPosition\r\n placement = 'top'\r\n flipped = true\r\n }\r\n }\r\n } else {\r\n position = topPosition\r\n\r\n // 检查是否需要翻转到底部\r\n if (autoAdjust && position.y < viewportPadding) {\r\n // 检查底部是否有足够空间\r\n if (\r\n bottomPosition.y + popupSize.height <=\r\n viewport.height - viewportPadding\r\n ) {\r\n position = bottomPosition\r\n placement = 'bottom'\r\n flipped = true\r\n }\r\n }\r\n }\r\n\r\n // 水平方向调整,确保不超出视口\r\n if (autoAdjust) {\r\n const maxX = Math.max(\r\n viewportPadding,\r\n viewport.width - popupSize.width - viewportPadding\r\n )\r\n position.x = Math.min(Math.max(position.x, viewportPadding), maxX)\r\n }\r\n\r\n // 计算最大可用高度\r\n const maxHeight =\r\n placement === 'bottom'\r\n ? viewport.height - position.y - viewportPadding\r\n : targetRect.y - viewportPadding\r\n\r\n return {\r\n position,\r\n placement,\r\n flipped,\r\n maxHeight: Math.max(0, maxHeight),\r\n maxWidth: Math.max(0, viewport.width - viewportPadding * 2),\r\n }\r\n }\r\n\r\n /**\r\n * 获取弹出层初始样式(用于动画)\r\n */\r\n getInitialStyles(placement: PopupPlacement): Partial<CSSStyleDeclaration> {\r\n switch (placement) {\r\n case 'bottom-sheet':\r\n return {\r\n transform: 'translateY(100%)',\r\n opacity: '1',\r\n }\r\n case 'bottom':\r\n return {\r\n transform: 'translateY(calc(-1 * var(--ld-px-10)))',\r\n opacity: '0',\r\n }\r\n case 'top':\r\n return {\r\n transform: 'translateY(var(--ld-px-10))',\r\n opacity: '0',\r\n }\r\n default:\r\n return {\r\n opacity: '0',\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取弹出层最终样式(动画结束)\r\n */\r\n getFinalStyles(_placement: PopupPlacement): Partial<CSSStyleDeclaration> {\r\n return {\r\n transform: 'translateY(0)',\r\n opacity: '1',\r\n }\r\n }\r\n\r\n /**\r\n * 获取弹出层退出样式\r\n */\r\n getExitStyles(_placement: PopupPlacement): Partial<CSSStyleDeclaration> {\r\n return this.getInitialStyles(_placement)\r\n }\r\n\r\n /**\r\n * 获取动画时长\r\n */\r\n getAnimationDuration(): number {\r\n return this.config.animationDuration\r\n }\r\n\r\n /**\r\n * 检查是否显示遮罩\r\n */\r\n shouldShowMask(): boolean {\r\n return isMobile() && this.config.showMask\r\n }\r\n\r\n /**\r\n * 检查遮罩是否可点击关闭\r\n */\r\n isMaskClosable(): boolean {\r\n return this.config.maskClosable\r\n }\r\n}\r\n\r\n/**\r\n * 创建位置管理器实例\r\n */\r\nexport function createPositionManager(\r\n config?: PopupPositionConfig\r\n): PositionManager {\r\n return new PositionManager(config)\r\n}\r\n","/**\r\n * 键盘 DOM 渲染器\r\n * 框架无关的键盘渲染器,用于原生 JS 项目\r\n * @module managers/keyboard-renderer\r\n */\r\n\r\nimport type { ThemeConfig } from '../themes/types'\r\nimport type {\r\n KeyboardConfig,\r\n KeyboardOptions,\r\n KeyboardType,\r\n KeyDefinition,\r\n PopupPositionConfig,\r\n} from '../types'\r\nimport { defaultTheme, getTheme, themeToCSS } from '../themes'\r\nimport { isMobile } from '../utils/device'\r\nimport { onClickOutside, sanitizeSvgIcon } from '../utils/dom'\r\nimport { KeyboardManager } from './keyboard-manager'\r\nimport { PositionManager } from './position-manager'\r\n\r\n/**\r\n * 渲染器配置\r\n */\r\nexport interface KeyboardRendererOptions extends KeyboardOptions {\r\n /** 挂载容器(默认 document.body) */\r\n container?: HTMLElement\r\n /** 主题名称或主题配置 */\r\n theme?: string | ThemeConfig\r\n /** 弹出层配置 */\r\n position?: PopupPositionConfig\r\n /** 点击外部关闭 */\r\n closeOnClickOutside?: boolean\r\n /** 确认回调 */\r\n onConfirm?: (value: string) => void\r\n /** 输入变化回调 */\r\n onInput?: (value: string) => void\r\n /** 关闭回调 */\r\n onClose?: () => void\r\n}\r\n\r\ninterface RendererStyleEntry {\r\n element: HTMLStyleElement\r\n users: number\r\n}\r\n\r\nconst rendererStyles = new WeakMap<Document, RendererStyleEntry>()\r\n\r\n/**\r\n * 键盘 DOM 渲染器\r\n * 提供完整的键盘 DOM 创建、事件绑定、位置管理\r\n */\r\nexport class KeyboardRenderer {\r\n /** 键盘管理器 */\r\n readonly manager: KeyboardManager\r\n\r\n /** 位置管理器 */\r\n private positionManager: PositionManager\r\n\r\n /** 配置 */\r\n private options: KeyboardRendererOptions\r\n\r\n /** DOM 元素 */\r\n private rootEl: HTMLElement | null = null\r\n private maskEl: HTMLElement | null = null\r\n private keyboardEl: HTMLElement | null = null\r\n\r\n /** 挂载容器 */\r\n private container: HTMLElement\r\n\r\n /** 主题配置 */\r\n private theme: ThemeConfig\r\n\r\n /** 当前目标元素 */\r\n private targetEl: HTMLInputElement | HTMLTextAreaElement | null = null\r\n\r\n /** 清理函数 */\r\n private cleanupFns: Array<() => void> = []\r\n private inputCleanupFns = new Set<() => void>()\r\n private styleDocument: Document | null = null\r\n\r\n /** 是否已销毁 */\r\n private destroyed = false\r\n\r\n constructor(options: KeyboardRendererOptions = {}) {\r\n this.options = options\r\n const container =\r\n options.container ??\r\n (typeof document !== 'undefined' ? document.body : null)\r\n if (!container) {\r\n throw new Error(\r\n '[KeyboardRenderer] A DOM container is required in non-browser environments'\r\n )\r\n }\r\n this.container = container\r\n this.manager = new KeyboardManager(options)\r\n this.positionManager = new PositionManager(options.position)\r\n\r\n // 解析主题\r\n if (typeof options.theme === 'string') {\r\n this.theme = getTheme(options.theme)\r\n } else if (options.theme) {\r\n this.theme = options.theme\r\n } else {\r\n this.theme = defaultTheme\r\n }\r\n\r\n // 绑定事件\r\n this.setupEvents()\r\n }\r\n\r\n /**\r\n * 设置事件监听\r\n */\r\n private setupEvents(): void {\r\n this.manager.on('stateChange', state => {\r\n if (state.visible) {\r\n this.render()\r\n } else {\r\n this.unmount()\r\n }\r\n })\r\n\r\n this.manager.on('input', ({ value }) => {\r\n this.options.onInput?.(value)\r\n })\r\n\r\n this.manager.on('confirm', ({ value }) => {\r\n this.options.onConfirm?.(value)\r\n })\r\n }\r\n\r\n /**\r\n * 打开键盘\r\n */\r\n open(target?: HTMLInputElement | HTMLTextAreaElement): void {\r\n if (this.destroyed) return\r\n this.targetEl = target ?? null\r\n this.manager.show(target)\r\n }\r\n\r\n /**\r\n * 关闭键盘\r\n */\r\n close(): void {\r\n if (this.destroyed) return\r\n const wasVisible = this.manager.getState().visible\r\n this.manager.hide()\r\n if (wasVisible) this.options.onClose?.()\r\n }\r\n\r\n /**\r\n * 切换键盘类型\r\n */\r\n switchType(type: KeyboardType | string): void {\r\n if (this.destroyed) return\r\n this.manager.switchType(type)\r\n }\r\n\r\n /**\r\n * 设置主题\r\n */\r\n setTheme(theme: string | ThemeConfig): void {\r\n if (this.destroyed) return\r\n if (typeof theme === 'string') {\r\n this.theme = getTheme(theme)\r\n } else {\r\n this.theme = theme\r\n }\r\n if (this.manager.getState().visible) {\r\n this.render()\r\n }\r\n }\r\n\r\n /**\r\n * 获取当前值\r\n */\r\n getValue(): string {\r\n return this.manager.getState().value\r\n }\r\n\r\n /**\r\n * 设置值\r\n */\r\n setValue(value: string): void {\r\n if (this.destroyed) return\r\n this.manager.setValue(value)\r\n }\r\n\r\n /**\r\n * 渲染键盘 DOM\r\n */\r\n private render(): void {\r\n if (this.destroyed) return\r\n const layout = this.manager.getLayout()\r\n if (!layout) return\r\n\r\n // 清理旧的 DOM\r\n this.unmount()\r\n\r\n // 创建根元素\r\n this.rootEl = document.createElement('div')\r\n this.rootEl.className = 'lk-renderer-root'\r\n\r\n const isMobileDevice = isMobile()\r\n\r\n // 移动端创建遮罩\r\n if (isMobileDevice) {\r\n this.maskEl = document.createElement('div')\r\n this.maskEl.className = 'lk-mask'\r\n this.maskEl.addEventListener('click', () => {\r\n if (this.positionManager.isMaskClosable()) this.close()\r\n })\r\n this.rootEl.appendChild(this.maskEl)\r\n }\r\n\r\n // 创建键盘容器\r\n this.keyboardEl = document.createElement('div')\r\n this.keyboardEl.className = `lk-popup lk-popup--${isMobileDevice ? 'mobile' : 'desktop'}`\r\n\r\n // 应用主题 CSS 变量\r\n const cssVars = themeToCSS(this.theme)\r\n const keyboardElement = this.keyboardEl\r\n if (!keyboardElement) return\r\n Object.entries(cssVars).forEach(([key, value]) => {\r\n if (value) {\r\n keyboardElement.style.setProperty(key, value)\r\n }\r\n })\r\n\r\n // 渲染键盘内容\r\n const contentEl = this.renderKeyboard(layout)\r\n this.keyboardEl.appendChild(contentEl)\r\n\r\n this.rootEl.appendChild(this.keyboardEl)\r\n this.container.appendChild(this.rootEl)\r\n\r\n // 计算位置\r\n if (!isMobileDevice && this.targetEl) {\r\n const rect = this.keyboardEl.getBoundingClientRect()\r\n const result = this.positionManager.calculate(this.targetEl, {\r\n width: rect.width,\r\n height: rect.height,\r\n })\r\n this.keyboardEl.style.position = 'fixed'\r\n this.keyboardEl.style.left = `${result.position.x}px`\r\n this.keyboardEl.style.top = `${result.position.y}px`\r\n this.keyboardEl.style.zIndex = '10000'\r\n } else if (isMobileDevice) {\r\n this.keyboardEl.style.position = 'fixed'\r\n this.keyboardEl.style.left = '0'\r\n this.keyboardEl.style.right = '0'\r\n this.keyboardEl.style.bottom = '0'\r\n this.keyboardEl.style.zIndex = '10000'\r\n }\r\n\r\n // 添加动画类\r\n requestAnimationFrame(() => {\r\n this.keyboardEl?.classList.add('lk-popup--visible')\r\n this.maskEl?.classList.add('lk-mask--visible')\r\n })\r\n\r\n // 点击外部关闭\r\n if (this.options.closeOnClickOutside !== false && this.keyboardEl) {\r\n const cleanup = onClickOutside(this.keyboardEl, event => {\r\n if (\r\n this.targetEl &&\r\n event.target instanceof Node &&\r\n this.targetEl.contains(event.target)\r\n )\r\n return\r\n this.close()\r\n })\r\n this.cleanupFns.push(cleanup)\r\n }\r\n\r\n // 注入样式\r\n this.injectStyles()\r\n }\r\n\r\n /**\r\n * 渲染键盘内容\r\n */\r\n private renderKeyboard(layout: KeyboardConfig): HTMLElement {\r\n const el = document.createElement('div')\r\n el.className = 'lk-keyboard'\r\n\r\n const state = this.manager.getState()\r\n\r\n layout.rows.forEach(row => {\r\n const rowEl = document.createElement('div')\r\n rowEl.className = `lk-row ${row.className || ''}`\r\n\r\n const isNumpad = row.className === 'numpad-row'\r\n\r\n row.keys.forEach(key => {\r\n const wrapperEl = document.createElement('div')\r\n wrapperEl.className = 'lk-key-wrapper'\r\n\r\n if (isNumpad) {\r\n wrapperEl.style.flex = String(key.width ?? 1)\r\n } else if (key.width) {\r\n const baseW = 36\r\n const gap = this.theme.sizes?.keyGap ?? 6\r\n const w = baseW * key.width + (key.width - 1) * gap\r\n wrapperEl.style.width = `${w}px`\r\n }\r\n\r\n const btnEl = document.createElement('button')\r\n btnEl.type = 'button'\r\n btnEl.className = this.getKeyClass(key, state.isUpperCase)\r\n\r\n if (key.disabled) {\r\n btnEl.disabled = true\r\n }\r\n\r\n // 内容\r\n if (key.icon) {\r\n const safeIcon = sanitizeSvgIcon(key.icon)\r\n if (safeIcon) btnEl.innerHTML = safeIcon\r\n else btnEl.textContent = key.icon\r\n } else {\r\n const label =\r\n typeof key.label === 'string'\r\n ? key.label\r\n : state.isUpperCase\r\n ? key.label.upper\r\n : key.label.lower\r\n btnEl.textContent = label\r\n }\r\n\r\n // 事件\r\n const handler = (e: Event) => {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n if (!key.disabled) {\r\n this.manager.handleKey(key)\r\n }\r\n }\r\n\r\n btnEl.addEventListener('mousedown', handler)\r\n btnEl.addEventListener('touchstart', handler, { passive: false })\r\n\r\n wrapperEl.appendChild(btnEl)\r\n rowEl.appendChild(wrapperEl)\r\n })\r\n\r\n el.appendChild(rowEl)\r\n })\r\n\r\n return el\r\n }\r\n\r\n /**\r\n * 获取按键 CSS 类名\r\n */\r\n private getKeyClass(key: KeyDefinition, isUpperCase: boolean): string {\r\n const classes = ['lk-key', `lk-key--${key.type}`]\r\n if (key.className) classes.push(key.className)\r\n if (key.disabled) classes.push('lk-key--disabled')\r\n if (key.type === 'shift' && isUpperCase) classes.push('lk-key--active')\r\n return classes.join(' ')\r\n }\r\n\r\n /**\r\n * 卸载 DOM\r\n */\r\n private unmount(): void {\r\n this.cleanupFns.forEach(fn => fn())\r\n this.cleanupFns = []\r\n\r\n if (this.rootEl && this.rootEl.parentNode) {\r\n this.rootEl.parentNode.removeChild(this.rootEl)\r\n }\r\n this.rootEl = null\r\n this.maskEl = null\r\n this.keyboardEl = null\r\n }\r\n\r\n /**\r\n * 注入样式(单例)\r\n */\r\n private injectStyles(): void {\r\n const styleDocument = this.container.ownerDocument\r\n if (this.styleDocument === styleDocument) return\r\n const existing = rendererStyles.get(styleDocument)\r\n if (existing) {\r\n existing.users += 1\r\n this.styleDocument = styleDocument\r\n return\r\n }\r\n\r\n const style = styleDocument.createElement('style')\r\n style.textContent = `\r\n .lk-renderer-root { font-family: var(--ld-font-family); }\r\n .lk-mask { position: fixed; inset: 0; z-index: 9999; background: var(--keyboard-mask-bg); opacity: 0; transition: opacity var(--ld-duration-fast); }\r\n .lk-mask--visible { opacity: 1; }\r\n .lk-popup { overflow: hidden; background: var(--keyboard-bg); box-shadow: var(--ld-shadow-md, none); transform: translateY(var(--ld-px-20)); opacity: 0; transition: transform var(--ld-duration-fast), opacity var(--ld-duration-fast); }\r\n .lk-popup--visible { transform: translateY(0); opacity: 1; }\r\n .lk-popup--desktop { min-width: var(--ld-px-280); border-radius: var(--ld-radius-lg); box-shadow: var(--ld-shadow-lg, none); }\r\n .lk-popup--mobile { border-top-left-radius: var(--ld-radius-lg); border-top-right-radius: var(--ld-radius-lg); padding-bottom: env(safe-area-inset-bottom, var(--ld-px-0)); }\r\n .lk-keyboard { display: flex; flex-direction: column; gap: var(--keyboard-key-gap); padding: var(--keyboard-padding); user-select: none; -webkit-user-select: none; font-family: var(--ld-font-family); }\r\n .lk-row { display: flex; justify-content: center; gap: var(--keyboard-key-gap); padding: 0 var(--ld-px-2); }\r\n .lk-row.numpad-row { justify-content: stretch; }\r\n .lk-row.numpad-row .lk-key-wrapper { flex: 1; }\r\n .lk-key-wrapper { position: relative; display: inline-flex; }\r\n .lk-key { display: inline-flex; align-items: center; justify-content: center; width: 100%; min-width: var(--ld-px-32); height: var(--keyboard-key-height); padding: 0 var(--ld-spacing-xs); border: 0; border-radius: var(--keyboard-key-radius); background: var(--keyboard-key-bg); color: var(--keyboard-key-color); font-size: var(--keyboard-font-size); font-weight: 500; cursor: pointer; touch-action: manipulation; box-shadow: var(--keyboard-key-shadow); transition: background-color var(--ld-duration-fast), transform var(--ld-duration-fast); }\r\n .lk-key:active { background: var(--keyboard-key-active-bg); transform: scale(0.95); }\r\n .lk-key--disabled { opacity: 0.4; cursor: not-allowed; }\r\n .lk-key--disabled:active { transform: none; background: var(--keyboard-key-bg); }\r\n .lk-key--backspace, .lk-key--shift, .lk-key--tab, .lk-key--clear, .lk-key--close { background: var(--keyboard-fn-key-bg); color: var(--keyboard-fn-key-color); font-size: var(--keyboard-fn-font-size); }\r\n .lk-key--backspace:active, .lk-key--shift:active, .lk-key--tab:active, .lk-key--clear:active, .lk-key--close:active { background: var(--keyboard-fn-key-active-bg); }\r\n .lk-key--active { background: var(--keyboard-key-active-bg) !important; color: var(--ld-text-inverse) !important; }\r\n .lk-key--done, .lk-key--enter { background: var(--keyboard-primary-bg); color: var(--keyboard-primary-color); font-size: var(--keyboard-fn-font-size); }\r\n .lk-key--done:active, .lk-key--enter:active { background: var(--keyboard-primary-active-bg); }\r\n .lk-key--space { background: var(--keyboard-key-bg); }\r\n .lk-key svg { pointer-events: none; }\r\n `\r\n style.id = 'lk-renderer-styles'\r\n styleDocument.head?.appendChild(style)\r\n rendererStyles.set(styleDocument, { element: style, users: 1 })\r\n this.styleDocument = styleDocument\r\n }\r\n\r\n /**\r\n * 绑定到输入框(聚焦时自动打开键盘)\r\n */\r\n bindInput(input: HTMLInputElement | HTMLTextAreaElement): () => void {\r\n if (this.destroyed) return () => undefined\r\n const handleFocus = () => this.open(input)\r\n input.addEventListener('focus', handleFocus)\r\n\r\n // 阻止移动端原生键盘\r\n input.setAttribute('readonly', 'readonly')\r\n input.style.caretColor = 'transparent'\r\n\r\n let cleaned = false\r\n const cleanup = () => {\r\n if (cleaned) return\r\n cleaned = true\r\n input.removeEventListener('focus', handleFocus)\r\n input.removeAttribute('readonly')\r\n input.style.caretColor = ''\r\n }\r\n this.inputCleanupFns.add(cleanup)\r\n return cleanup\r\n }\r\n\r\n /**\r\n * 销毁渲染器\r\n */\r\n destroy(): void {\r\n if (this.destroyed) return\r\n this.destroyed = true\r\n this.unmount()\r\n this.inputCleanupFns.forEach(cleanup => cleanup())\r\n this.inputCleanupFns.clear()\r\n this.manager.destroy()\r\n\r\n // 移除样式\r\n if (this.styleDocument) {\r\n const entry = rendererStyles.get(this.styleDocument)\r\n if (entry) {\r\n entry.users -= 1\r\n if (entry.users <= 0) {\r\n entry.element.remove()\r\n rendererStyles.delete(this.styleDocument)\r\n }\r\n }\r\n this.styleDocument = null\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 创建键盘渲染器\r\n */\r\nexport function createKeyboardRenderer(\r\n options?: KeyboardRendererOptions\r\n): KeyboardRenderer {\r\n return new KeyboardRenderer(options)\r\n}\r\n","/**\r\n * 输入格式化工具\r\n * @module utils/formatters\r\n */\r\n\r\n/**\r\n * 格式化手机号 (3-4-4)\r\n * @example formatPhone('13812345678') => '138 1234 5678'\r\n */\r\nexport function formatPhone(value: string): string {\r\n const digits = value.replace(/\\D/g, '').slice(0, 11)\r\n if (digits.length <= 3) return digits\r\n if (digits.length <= 7) return `${digits.slice(0, 3)} ${digits.slice(3)}`\r\n return `${digits.slice(0, 3)} ${digits.slice(3, 7)} ${digits.slice(7)}`\r\n}\r\n\r\n/**\r\n * 格式化银行卡号 (4-4-4-4-3)\r\n * @example formatBankCard('6222021234567890123') => '6222 0212 3456 7890 123'\r\n */\r\nexport function formatBankCard(value: string): string {\r\n const digits = value.replace(/\\D/g, '').slice(0, 19)\r\n return digits.replace(/(\\d{4})(?=\\d)/g, '$1 ')\r\n}\r\n\r\n/**\r\n * 格式化金额(限制小数位数)\r\n * @param value - 输入值\r\n * @param decimalPlaces - 小数位数,默认 2\r\n */\r\nexport function formatAmount(value: string, decimalPlaces: number = 2): string {\r\n // 移除非数字和小数点\r\n let result = value.replace(/[^\\d.]/g, '')\r\n\r\n // 只保留第一个小数点\r\n const parts = result.split('.')\r\n if (parts.length > 2) {\r\n result = `${parts[0]}.${parts.slice(1).join('')}`\r\n }\r\n\r\n // 限制小数位数\r\n if (parts.length === 2 && parts[1].length > decimalPlaces) {\r\n result = `${parts[0]}.${parts[1].slice(0, decimalPlaces)}`\r\n }\r\n\r\n // 移除前导零(保留 0.xx 格式)\r\n if (result.length > 1 && result.startsWith('0') && result[1] !== '.') {\r\n result = result.replace(/^0+/, '') || '0'\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * 格式化身份证号(自动大写 X)\r\n */\r\nexport function formatIdCard(value: string): string {\r\n return value\r\n .replace(/[^\\dX]/gi, '')\r\n .slice(0, 18)\r\n .toUpperCase()\r\n}\r\n\r\n/**\r\n * 格式化车牌号\r\n */\r\nexport function formatLicensePlate(value: string): string {\r\n return value.toUpperCase().slice(0, 8)\r\n}\r\n\r\n/**\r\n * 格式化验证码(纯数字)\r\n * @param value - 输入值\r\n * @param length - 验证码长度,默认 6\r\n */\r\nexport function formatVerifyCode(value: string, length: number = 6): string {\r\n return value.replace(/\\D/g, '').slice(0, length)\r\n}\r\n\r\n/**\r\n * 通用格式化器注册表\r\n */\r\nexport type FormatterFunction = (value: string) => string\r\n\r\nconst formatters: Map<string, FormatterFunction> = new Map([\r\n ['phone', formatPhone],\r\n ['bankcard', formatBankCard],\r\n ['idcard', formatIdCard],\r\n ['license-plate', formatLicensePlate],\r\n ['verifycode', formatVerifyCode],\r\n])\r\n\r\n/**\r\n * 注册自定义格式化器\r\n */\r\nexport function registerFormatter(\r\n name: string,\r\n formatter: FormatterFunction\r\n): void {\r\n formatters.set(name, formatter)\r\n}\r\n\r\n/**\r\n * 获取格式化器\r\n */\r\nexport function getFormatter(name: string): FormatterFunction | undefined {\r\n return formatters.get(name)\r\n}\r\n\r\n/**\r\n * 应用格式化\r\n */\r\nexport function applyFormatter(name: string, value: string): string {\r\n const formatter = formatters.get(name)\r\n return formatter ? formatter(value) : value\r\n}\r\n","/**\r\n * 随机工具函数\r\n * @module utils/random\r\n */\r\n\r\nimport type { KeyboardConfig, KeyboardRow, KeyDefinition } from '../types'\r\n\r\n/**\r\n * Fisher-Yates 洗牌算法\r\n * @param array - 要洗牌的数组\r\n * @returns 洗牌后的新数组\r\n */\r\nexport function shuffleArray<T>(array: T[]): T[] {\r\n const result = [...array]\r\n for (let i = result.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1))\r\n ;[result[i], result[j]] = [result[j], result[i]]\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * 生成随机数字数组 (0-9)\r\n */\r\nexport function getRandomNumbers(): string[] {\r\n return shuffleArray(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])\r\n}\r\n\r\n/**\r\n * 生成随机字母数组 (A-Z)\r\n */\r\nexport function getRandomLetters(): string[] {\r\n const letters = Array.from({ length: 26 }, (_, i) =>\r\n String.fromCharCode(65 + i)\r\n )\r\n return shuffleArray(letters)\r\n}\r\n\r\n/**\r\n * 生成随机数字+字母数组\r\n */\r\nexport function getRandomAlphanumeric(): string[] {\r\n const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\r\n const letters = Array.from({ length: 26 }, (_, i) =>\r\n String.fromCharCode(65 + i)\r\n )\r\n return shuffleArray([...numbers, ...letters])\r\n}\r\n\r\n/**\r\n * 创建字符按键\r\n */\r\nfunction createCharKey(char: string, index: number): KeyDefinition {\r\n return {\r\n id: `random-${char}-${index}`,\r\n type: 'char',\r\n label: char,\r\n value: char,\r\n className: 'key-random',\r\n }\r\n}\r\n\r\n/**\r\n * 将字符数组分成行\r\n */\r\nfunction chunkArray<T>(array: T[], chunkSize: number): T[][] {\r\n const chunks: T[][] = []\r\n for (let i = 0; i < array.length; i += chunkSize) {\r\n chunks.push(array.slice(i, i + chunkSize))\r\n }\r\n return chunks\r\n}\r\n\r\n/**\r\n * 生成随机数字键盘布局\r\n * @param options - 配置选项\r\n * @param options.keysPerRow - Number of keys per row\r\n * @param options.includeBackspace - Whether to include backspace\r\n * @param options.includeDone - Whether to include done\r\n * @param options.includeClear - Whether to include clear\r\n */\r\nexport function createRandomNumberLayout(options?: {\r\n /** 每行按键数 */\r\n keysPerRow?: number\r\n /** 是否包含退格键 */\r\n includeBackspace?: boolean\r\n /** 是否包含完成键 */\r\n includeDone?: boolean\r\n /** 是否包含清空键 */\r\n includeClear?: boolean\r\n}): KeyboardConfig {\r\n const {\r\n keysPerRow = 3,\r\n includeBackspace = true,\r\n includeDone = true,\r\n includeClear = false,\r\n } = options || {}\r\n\r\n const randomNumbers = getRandomNumbers()\r\n const numberKeys = randomNumbers.map((n, i) => createCharKey(n, i))\r\n const chunks = chunkArray(numberKeys, keysPerRow)\r\n\r\n const rows: KeyboardRow[] = chunks.map(keys => ({\r\n className: 'numpad-row',\r\n keys,\r\n }))\r\n\r\n // 添加功能键行\r\n const fnKeys: KeyDefinition[] = []\r\n\r\n if (includeClear) {\r\n fnKeys.push({\r\n id: 'clear',\r\n type: 'clear',\r\n label: '清空',\r\n className: 'key-clear key-fn',\r\n })\r\n }\r\n\r\n if (includeBackspace) {\r\n fnKeys.push({\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n className: 'key-backspace key-fn',\r\n })\r\n }\r\n\r\n if (includeDone) {\r\n fnKeys.push({\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n className: 'key-done key-fn',\r\n })\r\n }\r\n\r\n if (fnKeys.length > 0) {\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: fnKeys,\r\n })\r\n }\r\n\r\n return {\r\n type: 'custom',\r\n name: '随机数字键盘',\r\n supportShift: false,\r\n rows,\r\n data: {\r\n isRandom: true,\r\n randomType: 'number',\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 生成4x3随机数字键盘(密码输入常用)\r\n */\r\nexport function createRandomPinLayout(options?: {\r\n /** 是否包含退格键 */\r\n includeBackspace?: boolean\r\n /** 是否包含完成键 */\r\n includeDone?: boolean\r\n}): KeyboardConfig {\r\n const { includeBackspace = true, includeDone = true } = options || {}\r\n\r\n const randomNumbers = getRandomNumbers()\r\n\r\n // 前9个数字 (3x3)\r\n const rows: KeyboardRow[] = [\r\n {\r\n className: 'numpad-row',\r\n keys: randomNumbers.slice(0, 3).map((n, i) => createCharKey(n, i)),\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: randomNumbers.slice(3, 6).map((n, i) => createCharKey(n, i + 3)),\r\n },\r\n {\r\n className: 'numpad-row',\r\n keys: randomNumbers.slice(6, 9).map((n, i) => createCharKey(n, i + 6)),\r\n },\r\n ]\r\n\r\n // 最后一行:功能键 + 0 + 功能键\r\n const lastRow: KeyDefinition[] = []\r\n\r\n if (includeBackspace) {\r\n lastRow.push({\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n className: 'key-backspace key-fn',\r\n })\r\n } else {\r\n lastRow.push({\r\n id: 'empty-1',\r\n type: 'char',\r\n label: '',\r\n value: '',\r\n disabled: true,\r\n className: 'key-placeholder',\r\n })\r\n }\r\n\r\n lastRow.push(createCharKey(randomNumbers[9], 9))\r\n\r\n if (includeDone) {\r\n lastRow.push({\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n className: 'key-done key-fn',\r\n })\r\n } else {\r\n lastRow.push({\r\n id: 'empty-2',\r\n type: 'char',\r\n label: '',\r\n value: '',\r\n disabled: true,\r\n className: 'key-placeholder',\r\n })\r\n }\r\n\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: lastRow,\r\n })\r\n\r\n return {\r\n type: 'custom',\r\n name: '随机PIN键盘',\r\n supportShift: false,\r\n rows,\r\n data: {\r\n isRandom: true,\r\n randomType: 'pin',\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 生成随机字母键盘布局\r\n * 默认使用 QWERTY 风格行分布 (10/9/7),看起来像真实键盘\r\n */\r\nexport function createRandomLetterLayout(options?: {\r\n /** 是否大写 */\r\n uppercase?: boolean\r\n /** 行分布,默认 [10, 9, 7] 模拟 QWERTY 布局 */\r\n rowDistribution?: number[]\r\n}): KeyboardConfig {\r\n const { uppercase = true, rowDistribution = [10, 9, 7] } = options || {}\r\n\r\n let randomLetters = getRandomLetters()\r\n if (!uppercase) {\r\n randomLetters = randomLetters.map(l => l.toLowerCase())\r\n }\r\n\r\n const letterKeys = randomLetters.map((l, i) => createCharKey(l, i))\r\n\r\n // 按行分布切割\r\n const rows: KeyboardRow[] = []\r\n let offset = 0\r\n for (const count of rowDistribution) {\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: letterKeys.slice(offset, offset + count),\r\n })\r\n offset += count\r\n }\r\n // 剩余字母放最后一行\r\n if (offset < letterKeys.length) {\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: letterKeys.slice(offset),\r\n })\r\n }\r\n\r\n // 功能键行\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n label: '清空',\r\n className: 'key-clear key-fn',\r\n },\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n className: 'key-backspace key-fn',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n className: 'key-done key-fn',\r\n },\r\n ],\r\n })\r\n\r\n return {\r\n type: 'custom',\r\n name: '随机字母键盘',\r\n supportShift: false,\r\n rows,\r\n data: {\r\n isRandom: true,\r\n randomType: 'letter',\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 生成混合随机键盘(数字+字母)\r\n * 默认使用 QWERTY 风格行分布 (10/10/9/7),看起来像真实键盘\r\n */\r\nexport function createRandomMixedLayout(options?: {\r\n /** 行分布,默认 [10, 10, 9, 7] */\r\n rowDistribution?: number[]\r\n}): KeyboardConfig {\r\n const { rowDistribution = [10, 10, 9, 7] } = options || {}\r\n\r\n const randomChars = getRandomAlphanumeric()\r\n const charKeys = randomChars.map((c, i) => createCharKey(c, i))\r\n\r\n // 按行分布切割\r\n const rows: KeyboardRow[] = []\r\n let offset = 0\r\n for (const count of rowDistribution) {\r\n if (offset >= charKeys.length) break\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: charKeys.slice(offset, offset + count),\r\n })\r\n offset += count\r\n }\r\n // 剩余字符放最后一行\r\n if (offset < charKeys.length) {\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: charKeys.slice(offset),\r\n })\r\n }\r\n\r\n // 功能键行\r\n rows.push({\r\n className: 'numpad-row',\r\n keys: [\r\n {\r\n id: 'clear',\r\n type: 'clear',\r\n label: '清空',\r\n className: 'key-clear key-fn',\r\n },\r\n {\r\n id: 'backspace',\r\n type: 'backspace',\r\n label: '⌫',\r\n className: 'key-backspace key-fn',\r\n },\r\n {\r\n id: 'done',\r\n type: 'done',\r\n label: '确定',\r\n className: 'key-done key-fn',\r\n },\r\n ],\r\n })\r\n\r\n return {\r\n type: 'custom',\r\n name: '随机混合键盘',\r\n supportShift: false,\r\n rows,\r\n data: {\r\n isRandom: true,\r\n randomType: 'mixed',\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 刷新随机键盘布局\r\n * @param layout - 现有布局\r\n * @returns 新的随机布局\r\n */\r\nexport function refreshRandomLayout(layout: KeyboardConfig): KeyboardConfig {\r\n const randomType = layout.data?.randomType as string | undefined\r\n\r\n switch (randomType) {\r\n case 'number':\r\n return createRandomNumberLayout()\r\n case 'pin':\r\n return createRandomPinLayout()\r\n case 'letter':\r\n return createRandomLetterLayout()\r\n case 'mixed':\r\n return createRandomMixedLayout()\r\n default:\r\n return layout\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;CASO,MAAM,cAAc;CAKpB,MAAM,aAAa;CAKnB,MAAM,aAAa;CAKnB,MAAM,aAAa;CAKnB,MAAM,aAAa;CAKnB,MAAM,aAAa;CAKnB,MAAM,aAAa;CAKnB,MAAM,gBAAgB;CAKtB,MAAM,aAAa;CAKnB,MAAM,QAAQ;EACnB,QAAQ;EACR,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,UAAU;EACV,OAAO;CACT;;;CCrDA,SAAS,kBAAgB,KAA4B;EACnD,OAAO;GACL,IAAI,UAAU;GACd,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;EACb;CACF;CAKO,MAAM,eAA+B;EAC1C,MAAM;EACN,MAAM;EACN,cAAc;EACd,MAAM;GACJ;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;KACA,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;EACF;EACA,MAAM;GACJ,WAAW;GACX,eAAe;EACjB;CACF;CAKO,MAAM,qBAAqC;EAChD,MAAM;EACN,MAAM;EACN,cAAc;EACd,MAAM;GACJ;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GACA;IACE,WAAW;IACX,MAAM;KACJ;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;KACA,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;EACF;EACA,MAAM;GACJ,WAAW;GACX,eAAe;EACjB;CACF;;;CCnKA,SAAS,kBAAgB,KAA4B;EACnD,OAAO;GACL,IAAI,YAAY;GAChB,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;EACb;CACF;CAUO,MAAM,iBAAiC;EAC5C,MAAM;EACN,MAAM;EACN,cAAc;EACd,MAAM;GAGJ;IACE,WAAW;IACX,MAAM;KAEJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,WAAW;MACX,MAAM,EAAE,YAAY,SAAS;KAC/B;KACA,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;EACF;EACA,MAAM;GAEJ,WAAW;GACX,WAAW;EACb;CACF;;;CCvGA,SAAS,gBAAc,MAA6B;EAClD,OAAO;GACL,IAAI,cAAc,KAAK,YAAY;GACnC,MAAM;GACN,OAAO;IAAE,OAAO,KAAK,YAAY;IAAG,OAAO,KAAK,YAAY;GAAE;GAC9D,OAAO;IAAE,OAAO,KAAK,YAAY;IAAG,OAAO,KAAK,YAAY;GAAE;EAChE;CACF;CAKA,SAAS,UAAQ,OAAe,IAA4B;EAC1D,OAAO;GACL,IAAI,MAAM,iBAAiB,MAAM,QAAQ,eAAe,EAAE;GAC1D,MAAM;GACN;GACA,OAAO;GACP,WAAW;EACb;CACF;CAKO,MAAM,iBAAiB;EAC5B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEO,MAAM,cAA8B;EACzC,MAAM;EACN,MAAM;EACN,cAAc;EACd,kBAAkB;EAClB,YAAY,CAAC,UAAU,QAAQ;EAC/B,MAAM;GAEJ,EACE,MAAM,aAAa,MAAM,EAAE,CAAA,CAAE,IAAI,eAAa,EAChD;GAEA,EACE,MAAM,YAAY,MAAM,EAAE,CAAA,CAAE,IAAI,eAAa,EAC/C;GAEA,EACE,MAAM;IACJ;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;IACA,GAAG,UAAU,MAAM,EAAE,CAAA,CAAE,IAAI,eAAa;IACxC;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;GACF,EACF;GAEA,EACE,MAAM;IACJ;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;KACX,MAAM,EAAE,YAAY,SAAS;IAC/B;IACA;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;IACA;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,OAAO;KACP,WAAW;KACX,SAAS;IACX;IACA,UAAQ,KAAK,WAAW;IACxB,UAAQ,KAAK,YAAY;IACzB,UAAQ,KAAK,kBAAkB;IAC/B;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,OAAO;KACP,WAAW;IACb;IACA;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;GACF,EACF;EACF;CACF;;;CCzHA,SAAS,kBAAgB,KAA4B;EACnD,OAAO;GACL,IAAI,UAAU;GACd,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;EACb;CACF;CAWO,MAAM,eAA+B;EAC1C,MAAM;EACN,MAAM;EACN,cAAc;EACd,MAAM;GAGJ;IACE,WAAW;IACX,MAAM;KAEJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;GAEA;IACE,WAAW;IACX,MAAM;KACJ;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,WAAW;KACb;KACA,kBAAgB,GAAG;KACnB;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;IACF;GACF;EACF;EACA,MAAM;GAEJ,WAAW;GACX,WAAW;EACb;CACF;;;CCvGO,MAAM,YAAY;EACvB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAKO,MAAM,gBAAgB;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAKA,SAAS,kBAAkB,UAAiC;EAC1D,OAAO;GACL,IAAI,YAAY;GAChB,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;GACX,MAAM,EAAE,kBAAkB,6BAA6B;EACzD;CACF;CAKA,SAAS,gBAAgB,QAA+B;EACtD,OAAO;GACL,IAAI,UAAU;GACd,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;EACb;CACF;CAKA,SAAS,kBAAgB,KAA4B;EACnD,OAAO;GACL,IAAI,OAAO;GACX,MAAM;GACN,OAAO;GACP,OAAO;GACP,WAAW;EACb;CACF;CAMO,MAAM,6BAA6C;EACxD,MAAM;EACN,MAAM;EACN,cAAc;EACd,MAAM;GACJ;IACE,WAAW;IACX,MAAM,UAAU,MAAM,GAAG,EAAE,CAAA,CAAE,IAAI,iBAAiB;GACpD;GACA;IACE,WAAW;IACX,MAAM,UAAU,MAAM,IAAI,EAAE,CAAA,CAAE,IAAI,iBAAiB;GACrD;GACA;IACE,WAAW;IACX,MAAM,UAAU,MAAM,IAAI,EAAE,CAAA,CAAE,IAAI,iBAAiB;GACrD;GACA;IACE,WAAW;IACX,MAAM;KACJ,GAAG,UAAU,MAAM,IAAI,EAAE,CAAA,CAAE,IAAI,iBAAiB;KAChD;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;MACX,MAAM,EAAE,kBAAkB,6BAA6B;KACzD;KACA;MACE,IAAI;MACJ,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;MACX,MAAM,EAAE,kBAAkB,6BAA6B;KACzD;KACA;MACE,IAAI;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,OAAO;MACP,WAAW;KACb;KA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"}