@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.
- package/README.md +156 -37
- package/dist/index.js +1540 -1395
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2981 -1
- package/dist/index.min.js.map +1 -0
- package/es/.dts-output-manifest.json +1 -0
- package/es/.dts.tsbuildinfo +1 -0
- package/es/icons.d.ts +0 -1
- package/es/icons.js +1 -1
- package/es/icons.js.map +1 -1
- package/es/index.d.ts +3 -4
- package/es/index.js +15 -15
- package/es/layouts/amount.d.ts +0 -1
- package/es/layouts/amount.js +1 -1
- package/es/layouts/amount.js.map +1 -1
- package/es/layouts/bankcard.d.ts +0 -1
- package/es/layouts/bankcard.js +1 -1
- package/es/layouts/bankcard.js.map +1 -1
- package/es/layouts/email.d.ts +0 -1
- package/es/layouts/email.js +1 -1
- package/es/layouts/email.js.map +1 -1
- package/es/layouts/idcard.d.ts +0 -1
- package/es/layouts/idcard.js +1 -1
- package/es/layouts/idcard.js.map +1 -1
- package/es/layouts/index.d.ts +11 -12
- package/es/layouts/index.js +23 -23
- package/es/layouts/index.js.map +1 -1
- package/es/layouts/license-plate.d.ts +0 -1
- package/es/layouts/license-plate.js +1 -1
- package/es/layouts/license-plate.js.map +1 -1
- package/es/layouts/number.d.ts +0 -1
- package/es/layouts/number.js +1 -1
- package/es/layouts/number.js.map +1 -1
- package/es/layouts/phone.d.ts +0 -1
- package/es/layouts/phone.js +1 -1
- package/es/layouts/phone.js.map +1 -1
- package/es/layouts/punct.d.ts +0 -1
- package/es/layouts/punct.js +1 -1
- package/es/layouts/punct.js.map +1 -1
- package/es/layouts/qwerty.d.ts +0 -1
- package/es/layouts/qwerty.js +1 -1
- package/es/layouts/qwerty.js.map +1 -1
- package/es/layouts/search.d.ts +0 -1
- package/es/layouts/search.js +1 -1
- package/es/layouts/search.js.map +1 -1
- package/es/layouts/symbol.d.ts +0 -1
- package/es/layouts/symbol.js +1 -1
- package/es/layouts/symbol.js.map +1 -1
- package/es/layouts/url.d.ts +0 -1
- package/es/layouts/url.js +1 -1
- package/es/layouts/url.js.map +1 -1
- package/es/layouts/verifycode.d.ts +0 -1
- package/es/layouts/verifycode.js +1 -1
- package/es/layouts/verifycode.js.map +1 -1
- package/es/managers/index.d.ts +1 -2
- package/es/managers/index.js +1 -1
- package/es/managers/keyboard-manager.d.ts +2 -1
- package/es/managers/keyboard-manager.js +79 -22
- package/es/managers/keyboard-manager.js.map +1 -1
- package/es/managers/keyboard-renderer.d.ts +3 -2
- package/es/managers/keyboard-renderer.js +81 -39
- package/es/managers/keyboard-renderer.js.map +1 -1
- package/es/managers/position-manager.d.ts +4 -3
- package/es/managers/position-manager.js +42 -21
- package/es/managers/position-manager.js.map +1 -1
- package/es/themes/index.d.ts +1 -2
- package/es/themes/index.js +2 -1
- package/es/themes/index.js.map +1 -1
- package/es/themes/presets.d.ts +0 -1
- package/es/themes/presets.js +1 -1
- package/es/themes/presets.js.map +1 -1
- package/es/themes/types.d.ts +1 -1
- package/es/themes/types.js +1 -1
- package/es/types/index.d.ts +0 -1
- package/es/types/index.js +1 -1
- package/es/types/keyboard.d.ts +0 -1
- package/es/types/keyboard.js +1 -1
- package/es/types/position.d.ts +0 -1
- package/es/types/position.js +1 -1
- package/es/utils/device.d.ts +0 -1
- package/es/utils/device.js +11 -7
- package/es/utils/device.js.map +1 -1
- package/es/utils/dom.d.ts +4 -1
- package/es/utils/dom.js +25 -7
- package/es/utils/dom.js.map +1 -1
- package/es/utils/event-emitter.d.ts +0 -1
- package/es/utils/event-emitter.js +2 -1
- package/es/utils/event-emitter.js.map +1 -1
- package/es/utils/formatters.d.ts +0 -1
- package/es/utils/formatters.js +4 -4
- package/es/utils/formatters.js.map +1 -1
- package/es/utils/index.d.ts +2 -3
- package/es/utils/index.js +5 -5
- package/es/utils/random.d.ts +4 -1
- package/es/utils/random.js +2 -2
- package/es/utils/random.js.map +1 -1
- package/esm/icons.js +1 -1
- package/esm/icons.js.map +1 -1
- package/esm/index.js +15 -15
- package/esm/layouts/amount.js +1 -1
- package/esm/layouts/amount.js.map +1 -1
- package/esm/layouts/bankcard.js +1 -1
- package/esm/layouts/bankcard.js.map +1 -1
- package/esm/layouts/email.js +1 -1
- package/esm/layouts/email.js.map +1 -1
- package/esm/layouts/idcard.js +1 -1
- package/esm/layouts/idcard.js.map +1 -1
- package/esm/layouts/index.js +23 -23
- package/esm/layouts/index.js.map +1 -1
- package/esm/layouts/license-plate.js +1 -1
- package/esm/layouts/license-plate.js.map +1 -1
- package/esm/layouts/number.js +1 -1
- package/esm/layouts/number.js.map +1 -1
- package/esm/layouts/phone.js +1 -1
- package/esm/layouts/phone.js.map +1 -1
- package/esm/layouts/punct.js +1 -1
- package/esm/layouts/punct.js.map +1 -1
- package/esm/layouts/qwerty.js +1 -1
- package/esm/layouts/qwerty.js.map +1 -1
- package/esm/layouts/search.js +1 -1
- package/esm/layouts/search.js.map +1 -1
- package/esm/layouts/symbol.js +1 -1
- package/esm/layouts/symbol.js.map +1 -1
- package/esm/layouts/url.js +1 -1
- package/esm/layouts/url.js.map +1 -1
- package/esm/layouts/verifycode.js +1 -1
- package/esm/layouts/verifycode.js.map +1 -1
- package/esm/managers/index.js +1 -1
- package/esm/managers/keyboard-manager.js +79 -22
- package/esm/managers/keyboard-manager.js.map +1 -1
- package/esm/managers/keyboard-renderer.js +81 -39
- package/esm/managers/keyboard-renderer.js.map +1 -1
- package/esm/managers/position-manager.js +42 -21
- package/esm/managers/position-manager.js.map +1 -1
- package/esm/themes/index.js +2 -1
- package/esm/themes/index.js.map +1 -1
- package/esm/themes/presets.js +1 -1
- package/esm/themes/presets.js.map +1 -1
- package/esm/utils/device.js +11 -7
- package/esm/utils/device.js.map +1 -1
- package/esm/utils/dom.js +25 -7
- package/esm/utils/dom.js.map +1 -1
- package/esm/utils/event-emitter.js +2 -1
- package/esm/utils/event-emitter.js.map +1 -1
- package/esm/utils/formatters.js +4 -4
- package/esm/utils/formatters.js.map +1 -1
- package/esm/utils/random.js +2 -2
- package/esm/utils/random.js.map +1 -1
- package/lib/icons.cjs +1 -1
- package/lib/icons.cjs.map +1 -1
- package/{esm/icons.d.ts → lib/icons.d.cts} +0 -1
- package/lib/index.cjs +14 -13
- package/{esm/index.d.ts → lib/index.d.cts} +3 -4
- package/lib/layouts/amount.cjs +1 -1
- package/lib/layouts/amount.cjs.map +1 -1
- package/{esm/layouts/amount.d.ts → lib/layouts/amount.d.cts} +0 -1
- package/lib/layouts/bankcard.cjs +1 -1
- package/lib/layouts/bankcard.cjs.map +1 -1
- package/{esm/layouts/bankcard.d.ts → lib/layouts/bankcard.d.cts} +0 -1
- package/lib/layouts/email.cjs +1 -1
- package/lib/layouts/email.cjs.map +1 -1
- package/lib/layouts/{email.d.ts → email.d.cts} +0 -1
- package/lib/layouts/idcard.cjs +1 -1
- package/lib/layouts/idcard.cjs.map +1 -1
- package/{esm/layouts/idcard.d.ts → lib/layouts/idcard.d.cts} +0 -1
- package/lib/layouts/index.cjs +23 -23
- package/lib/layouts/index.cjs.map +1 -1
- package/{esm/layouts/index.d.ts → lib/layouts/index.d.cts} +11 -12
- package/lib/layouts/license-plate.cjs +1 -1
- package/lib/layouts/license-plate.cjs.map +1 -1
- package/{esm/layouts/license-plate.d.ts → lib/layouts/license-plate.d.cts} +0 -1
- package/lib/layouts/number.cjs +1 -1
- package/lib/layouts/number.cjs.map +1 -1
- package/{esm/layouts/number.d.ts → lib/layouts/number.d.cts} +0 -1
- package/lib/layouts/phone.cjs +1 -1
- package/lib/layouts/phone.cjs.map +1 -1
- package/lib/layouts/{phone.d.ts → phone.d.cts} +0 -1
- package/lib/layouts/punct.cjs +1 -1
- package/lib/layouts/punct.cjs.map +1 -1
- package/lib/layouts/{punct.d.ts → punct.d.cts} +0 -1
- package/lib/layouts/qwerty.cjs +1 -1
- package/lib/layouts/qwerty.cjs.map +1 -1
- package/{esm/layouts/qwerty.d.ts → lib/layouts/qwerty.d.cts} +0 -1
- package/lib/layouts/search.cjs +1 -1
- package/lib/layouts/search.cjs.map +1 -1
- package/{esm/layouts/search.d.ts → lib/layouts/search.d.cts} +0 -1
- package/lib/layouts/symbol.cjs +1 -1
- package/lib/layouts/symbol.cjs.map +1 -1
- package/{esm/layouts/symbol.d.ts → lib/layouts/symbol.d.cts} +0 -1
- package/lib/layouts/url.cjs +1 -1
- package/lib/layouts/url.cjs.map +1 -1
- package/{esm/layouts/url.d.ts → lib/layouts/url.d.cts} +0 -1
- package/lib/layouts/verifycode.cjs +1 -1
- package/lib/layouts/verifycode.cjs.map +1 -1
- package/lib/layouts/{verifycode.d.ts → verifycode.d.cts} +0 -1
- package/lib/managers/index.cjs +1 -1
- package/lib/managers/{index.d.ts → index.d.cts} +1 -2
- package/lib/managers/keyboard-manager.cjs +79 -22
- package/lib/managers/keyboard-manager.cjs.map +1 -1
- package/lib/managers/{keyboard-manager.d.ts → keyboard-manager.d.cts} +2 -1
- package/lib/managers/keyboard-renderer.cjs +80 -38
- package/lib/managers/keyboard-renderer.cjs.map +1 -1
- package/lib/managers/{keyboard-renderer.d.ts → keyboard-renderer.d.cts} +3 -2
- package/lib/managers/position-manager.cjs +42 -21
- package/lib/managers/position-manager.cjs.map +1 -1
- package/lib/managers/{position-manager.d.ts → position-manager.d.cts} +4 -3
- package/lib/themes/index.cjs +2 -1
- package/lib/themes/index.cjs.map +1 -1
- package/lib/themes/{index.d.ts → index.d.cts} +1 -2
- package/lib/themes/presets.cjs +1 -1
- package/lib/themes/presets.cjs.map +1 -1
- package/lib/themes/{presets.d.ts → presets.d.cts} +0 -1
- package/lib/themes/types.cjs +1 -1
- package/{esm/themes/types.d.ts → lib/themes/types.d.cts} +1 -1
- package/lib/types/index.cjs +1 -1
- package/{esm/types/index.d.ts → lib/types/index.d.cts} +0 -1
- package/lib/types/keyboard.cjs +1 -1
- package/{esm/types/keyboard.d.ts → lib/types/keyboard.d.cts} +0 -1
- package/lib/types/position.cjs +1 -1
- package/lib/types/{position.d.ts → position.d.cts} +0 -1
- package/lib/utils/device.cjs +11 -7
- package/lib/utils/device.cjs.map +1 -1
- package/{esm/utils/device.d.ts → lib/utils/device.d.cts} +0 -1
- package/lib/utils/dom.cjs +25 -6
- package/lib/utils/dom.cjs.map +1 -1
- package/{esm/utils/dom.d.ts → lib/utils/dom.d.cts} +4 -1
- package/lib/utils/event-emitter.cjs +2 -1
- package/lib/utils/event-emitter.cjs.map +1 -1
- package/{esm/utils/event-emitter.d.ts → lib/utils/event-emitter.d.cts} +0 -1
- package/lib/utils/formatters.cjs +4 -4
- package/lib/utils/formatters.cjs.map +1 -1
- package/{esm/utils/formatters.d.ts → lib/utils/formatters.d.cts} +0 -1
- package/lib/utils/index.cjs +4 -3
- package/{esm/utils/index.d.ts → lib/utils/index.d.cts} +2 -3
- package/lib/utils/random.cjs +2 -2
- package/lib/utils/random.cjs.map +1 -1
- package/{esm/utils/random.d.ts → lib/utils/random.d.cts} +4 -1
- package/package.json +28 -14
- package/es/icons.d.ts.map +0 -1
- package/es/index.d.ts.map +0 -1
- package/es/layouts/amount.d.ts.map +0 -1
- package/es/layouts/bankcard.d.ts.map +0 -1
- package/es/layouts/email.d.ts.map +0 -1
- package/es/layouts/idcard.d.ts.map +0 -1
- package/es/layouts/index.d.ts.map +0 -1
- package/es/layouts/license-plate.d.ts.map +0 -1
- package/es/layouts/number.d.ts.map +0 -1
- package/es/layouts/phone.d.ts.map +0 -1
- package/es/layouts/punct.d.ts.map +0 -1
- package/es/layouts/qwerty.d.ts.map +0 -1
- package/es/layouts/search.d.ts.map +0 -1
- package/es/layouts/symbol.d.ts.map +0 -1
- package/es/layouts/url.d.ts.map +0 -1
- package/es/layouts/verifycode.d.ts.map +0 -1
- package/es/managers/index.d.ts.map +0 -1
- package/es/managers/keyboard-manager.d.ts.map +0 -1
- package/es/managers/keyboard-renderer.d.ts.map +0 -1
- package/es/managers/position-manager.d.ts.map +0 -1
- package/es/themes/index.d.ts.map +0 -1
- package/es/themes/presets.d.ts.map +0 -1
- package/es/themes/types.d.ts.map +0 -1
- package/es/types/index.d.ts.map +0 -1
- package/es/types/keyboard.d.ts.map +0 -1
- package/es/types/position.d.ts.map +0 -1
- package/es/utils/device.d.ts.map +0 -1
- package/es/utils/dom.d.ts.map +0 -1
- package/es/utils/event-emitter.d.ts.map +0 -1
- package/es/utils/formatters.d.ts.map +0 -1
- package/es/utils/index.d.ts.map +0 -1
- package/es/utils/random.d.ts.map +0 -1
- package/esm/icons.d.ts.map +0 -1
- package/esm/index.d.ts.map +0 -1
- package/esm/layouts/amount.d.ts.map +0 -1
- package/esm/layouts/bankcard.d.ts.map +0 -1
- package/esm/layouts/email.d.ts +0 -11
- package/esm/layouts/email.d.ts.map +0 -1
- package/esm/layouts/idcard.d.ts.map +0 -1
- package/esm/layouts/index.d.ts.map +0 -1
- package/esm/layouts/license-plate.d.ts.map +0 -1
- package/esm/layouts/number.d.ts.map +0 -1
- package/esm/layouts/phone.d.ts +0 -15
- package/esm/layouts/phone.d.ts.map +0 -1
- package/esm/layouts/punct.d.ts +0 -7
- package/esm/layouts/punct.d.ts.map +0 -1
- package/esm/layouts/qwerty.d.ts.map +0 -1
- package/esm/layouts/search.d.ts.map +0 -1
- package/esm/layouts/symbol.d.ts.map +0 -1
- package/esm/layouts/url.d.ts.map +0 -1
- package/esm/layouts/verifycode.d.ts +0 -15
- package/esm/layouts/verifycode.d.ts.map +0 -1
- package/esm/managers/index.d.ts +0 -8
- package/esm/managers/index.d.ts.map +0 -1
- package/esm/managers/keyboard-manager.d.ts +0 -130
- package/esm/managers/keyboard-manager.d.ts.map +0 -1
- package/esm/managers/keyboard-renderer.d.ts +0 -115
- package/esm/managers/keyboard-renderer.d.ts.map +0 -1
- package/esm/managers/position-manager.d.ts +0 -72
- package/esm/managers/position-manager.d.ts.map +0 -1
- package/esm/themes/index.d.ts +0 -70
- package/esm/themes/index.d.ts.map +0 -1
- package/esm/themes/presets.d.ts +0 -39
- package/esm/themes/presets.d.ts.map +0 -1
- package/esm/themes/types.d.ts.map +0 -1
- package/esm/themes/types.js +0 -10
- package/esm/types/index.d.ts.map +0 -1
- package/esm/types/index.js +0 -10
- package/esm/types/keyboard.d.ts.map +0 -1
- package/esm/types/keyboard.js +0 -10
- package/esm/types/position.d.ts +0 -139
- package/esm/types/position.d.ts.map +0 -1
- package/esm/types/position.js +0 -10
- package/esm/utils/device.d.ts.map +0 -1
- package/esm/utils/dom.d.ts.map +0 -1
- package/esm/utils/event-emitter.d.ts.map +0 -1
- package/esm/utils/formatters.d.ts.map +0 -1
- package/esm/utils/index.d.ts.map +0 -1
- package/esm/utils/index.js +0 -16
- package/esm/utils/random.d.ts.map +0 -1
- package/lib/icons.d.ts +0 -58
- package/lib/index.d.ts +0 -12
- package/lib/layouts/amount.d.ts +0 -14
- package/lib/layouts/bankcard.d.ts +0 -15
- package/lib/layouts/idcard.d.ts +0 -16
- package/lib/layouts/index.d.ts +0 -54
- package/lib/layouts/license-plate.d.ts +0 -35
- package/lib/layouts/number.d.ts +0 -14
- package/lib/layouts/qwerty.d.ts +0 -10
- package/lib/layouts/search.d.ts +0 -7
- package/lib/layouts/symbol.d.ts +0 -14
- package/lib/layouts/url.d.ts +0 -7
- package/lib/themes/types.d.ts +0 -118
- package/lib/types/index.d.ts +0 -7
- package/lib/types/keyboard.d.ts +0 -253
- package/lib/utils/device.d.ts +0 -45
- package/lib/utils/dom.d.ts +0 -69
- package/lib/utils/event-emitter.d.ts +0 -52
- package/lib/utils/formatters.d.ts +0 -51
- package/lib/utils/index.d.ts +0 -10
- package/lib/utils/random.d.ts +0 -71
package/es/utils/device.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.js","names":[],"sources":["../../src/utils/device.ts"],"sourcesContent":["/**\n * 设备检测工具\n * @module utils/device\n */\n\nimport type { DeviceType, ViewportInfo } from '../types'\n\n/**\n * 移动设备 UA 正则\n */\nconst MOBILE_UA_REGEX
|
|
1
|
+
{"version":3,"file":"device.js","names":[],"sources":["../../src/utils/device.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;AAUA,MAAM,kBACJ;AAKF,IAAI,sBAAsC;AAKnC,SAAS,gBAAyB;CACvC,IAAI,wBAAwB,MAC1B,OAAO;CAGT,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,sBACE,kBAAkB,UAClB,UAAU,iBAAiB,KAE3B,UAAU,mBAAmB;CAE/B,OAAO;AACT;AAKO,SAAS,aAAsB;CACpC,IAAI,OAAO,cAAc,aACvB,OAAO;CAET,OAAO,gBAAgB,KAAK,UAAU,SAAS;AACjD;AAKO,SAAS,WAAoB;CAClC,IAAI,OAAO,WAAW,aACpB,OAAO;CAIT,IAAI,WAAW,GACb,OAAO;CAKT,KADoB,OAAO,cAAc,SAAS,gBAAgB,gBAC/C,KACjB,OAAO;CAIT,OAAO,cAAc;AACvB;AAKO,SAAS,gBAA4B;CAC1C,OAAO,SAAS,IAAI,WAAW;AACjC;AAKO,SAAS,kBAAgC;CAC9C,IAAI,OAAO,WAAW,aACpB,OAAO;EACL,OAAO;EACP,QAAQ;EACR,SAAS;EACT,SAAS;EACT,UAAU;CACZ;CAGF,MAAM,QAAQ,OAAO,cAAc,SAAS,gBAAgB;CAC5D,MAAM,SAAS,OAAO,eAAe,SAAS,gBAAgB;CAG9D,MAAM,WAAW,kBAAkB;CAEnC,OAAO;EACL;EACA;EACA,SAAS,OAAO,WAAW,OAAO;EAClC,SAAS,OAAO,WAAW,OAAO;EAClC,UAAU,SAAS;EACnB;CACF;AACF;AAKO,SAAS,oBAA8C;CAC5D,IACE,OAAO,WAAW,eAClB,OAAO,QAAQ,eACf,CAAC,IAAI,UAEL,OAAO;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;CAAE;CAIhD,IAAI,CAAC,IAAI,SAAS,eAAe,0BAA0B,GACzD,OAAO;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;CAAE;CAIhD,MAAM,MAAM,SAAS,cAAc,KAAK;CACxC,IAAI,MAAM,UAAU;;;;;;;;;CASpB,MAAM,OAAO,SAAS;CACtB,IAAI,CAAC,MAAM,OAAO;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;CAAE;CACzD,KAAK,YAAY,GAAG;CAEpB,MAAM,WAAW,iBAAiB,GAAG;CACrC,MAAM,WAAW;EACf,KAAK,OAAO,WAAW,SAAS,GAAG,KAAK;EACxC,OAAO,OAAO,WAAW,SAAS,KAAK,KAAK;EAC5C,QAAQ,OAAO,WAAW,SAAS,MAAM,KAAK;EAC9C,MAAM,OAAO,WAAW,SAAS,IAAI,KAAK;CAC5C;CAEA,KAAK,YAAY,GAAG;CACpB,OAAO;AACT;AAKO,SAAS,kBAA2B;CACzC,OAAO,OAAO,cAAc,eAAe,aAAa;AAC1D;AAMO,SAAS,QAAQ,UAA6B,IAAa;CAChE,IAAI,gBAAgB,GAClB,OAAO,UAAU,QAAQ,OAAO;CAElC,OAAO;AACT;AAOO,SAAS,iBACd,UACY;CACZ,IAAI,OAAO,WAAW,aACpB,aAAa,CAAC;CAGhB,MAAM,gBAAgB;EACpB,SAAS,gBAAgB,CAAC;CAC5B;CAEA,OAAO,iBAAiB,UAAU,OAAO;CACzC,OAAO,iBAAiB,qBAAqB,OAAO;CAEpD,aAAa;EACX,OAAO,oBAAoB,UAAU,OAAO;EAC5C,OAAO,oBAAoB,qBAAqB,OAAO;CACzD;AACF"}
|
package/es/utils/dom.d.ts
CHANGED
|
@@ -58,6 +58,10 @@ export declare function deleteCharBeforeCursor(input: HTMLInputElement | HTMLTex
|
|
|
58
58
|
* 创建 DOM 元素
|
|
59
59
|
*/
|
|
60
60
|
export declare function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, attrs?: Record<string, string>, children?: (HTMLElement | string)[]): HTMLElementTagNameMap[K];
|
|
61
|
+
/**
|
|
62
|
+
* Sanitize a caller-provided SVG icon before inserting it into the DOM.
|
|
63
|
+
*/
|
|
64
|
+
export declare function sanitizeSvgIcon(icon: string): string;
|
|
61
65
|
/**
|
|
62
66
|
* 添加/移除 CSS 类
|
|
63
67
|
*/
|
|
@@ -66,4 +70,3 @@ export declare function toggleClass(element: HTMLElement, className: string, for
|
|
|
66
70
|
* 设置 CSS 样式
|
|
67
71
|
*/
|
|
68
72
|
export declare function setStyles(element: HTMLElement, styles: Partial<CSSStyleDeclaration>): void;
|
|
69
|
-
//# sourceMappingURL=dom.d.ts.map
|
package/es/utils/dom.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
@@ -72,16 +72,19 @@ function insertTextAtCursor(input, text, maxLength) {
|
|
|
72
72
|
const start = input.selectionStart ?? input.value.length;
|
|
73
73
|
const end = input.selectionEnd ?? input.value.length;
|
|
74
74
|
const currentValue = input.value;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
const normalizedMaxLength = maxLength === void 0 || !Number.isFinite(maxLength) ? void 0 : Math.max(0, Math.floor(maxLength));
|
|
76
|
+
let insertedText = text;
|
|
77
|
+
let newValue = currentValue.substring(0, start) + insertedText + currentValue.substring(end);
|
|
78
|
+
if (normalizedMaxLength !== void 0 && newValue.length > normalizedMaxLength) {
|
|
79
|
+
const allowedLength = normalizedMaxLength - (currentValue.length - (end - start));
|
|
78
80
|
if (allowedLength <= 0) return {
|
|
79
81
|
value: currentValue,
|
|
80
82
|
cursorPosition: start
|
|
81
83
|
};
|
|
82
|
-
|
|
84
|
+
insertedText = text.substring(0, allowedLength);
|
|
85
|
+
newValue = currentValue.substring(0, start) + insertedText + currentValue.substring(end);
|
|
83
86
|
}
|
|
84
|
-
const newCursorPosition = start +
|
|
87
|
+
const newCursorPosition = start + insertedText.length;
|
|
85
88
|
return {
|
|
86
89
|
value: newValue,
|
|
87
90
|
cursorPosition: Math.min(newCursorPosition, newValue.length)
|
|
@@ -122,6 +125,21 @@ function createElement(tag, attrs, children) {
|
|
|
122
125
|
});
|
|
123
126
|
return element;
|
|
124
127
|
}
|
|
128
|
+
function sanitizeSvgIcon(icon) {
|
|
129
|
+
if (typeof DOMParser === "undefined" || typeof XMLSerializer === "undefined") return "";
|
|
130
|
+
const document2 = new DOMParser().parseFromString(icon, "image/svg+xml");
|
|
131
|
+
const svg = document2.documentElement;
|
|
132
|
+
if (svg.tagName.toLowerCase() !== "svg" || document2.querySelector("parsererror")) return "";
|
|
133
|
+
svg.querySelectorAll("script, style, foreignObject").forEach((node) => node.remove());
|
|
134
|
+
svg.querySelectorAll("*").forEach((element) => {
|
|
135
|
+
Array.from(element.attributes).forEach((attribute) => {
|
|
136
|
+
const name = attribute.name.toLowerCase();
|
|
137
|
+
const value = attribute.value.trim();
|
|
138
|
+
if (name.startsWith("on") || (name === "href" || name === "xlink:href") && !value.startsWith("#")) element.removeAttribute(attribute.name);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
return new XMLSerializer().serializeToString(svg);
|
|
142
|
+
}
|
|
125
143
|
function toggleClass(element, className, force) {
|
|
126
144
|
element.classList.toggle(className, force);
|
|
127
145
|
}
|
|
@@ -129,6 +147,6 @@ function setStyles(element, styles) {
|
|
|
129
147
|
Object.assign(element.style, styles);
|
|
130
148
|
}
|
|
131
149
|
//#endregion
|
|
132
|
-
export { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass };
|
|
150
|
+
export { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, sanitizeSvgIcon, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass };
|
|
133
151
|
/*! End of @composy/keyboard-core | Powered by @composy/builder */
|
|
134
152
|
//# sourceMappingURL=dom.js.map
|
package/es/utils/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","names":["deletedChar","newValue"],"sources":["../../src/utils/dom.ts"],"sourcesContent":["/**\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dom.js","names":["deletedChar","newValue","document"],"sources":["../../src/utils/dom.ts"],"sourcesContent":["/**\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"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
@@ -18,6 +18,7 @@ var EventEmitter = class {
|
|
|
18
18
|
on(event, handler, options = {}) {
|
|
19
19
|
if (!this.handlers.has(event)) this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
20
20
|
const handlers = this.handlers.get(event);
|
|
21
|
+
if (!handlers) return () => void 0;
|
|
21
22
|
const wrapper = {
|
|
22
23
|
handler,
|
|
23
24
|
options
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-emitter.js","names":[],"sources":["../../src/utils/event-emitter.ts"],"sourcesContent":["/**\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
|
|
1
|
+
{"version":3,"file":"event-emitter.js","names":[],"sources":["../../src/utils/event-emitter.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;AAoCO,IAAM,eAAN,MAA6D;CAA7D,cAAA;EACL,KAAQ,2BAAW,IAAI,IAGrB;CAAA;;;;CAKF,GACE,OACA,SACA,UAA+B,CAAC,GACpB;EACZ,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,GAC1B,KAAK,SAAS,IAAI,uBAAO,IAAI,IAAI,CAAC;EAGpC,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;EACxC,IAAI,CAAC,UACH,aAAa,KAAA;EAEf,MAAM,UAA4C;GAChD;GACA;EACF;EAEA,SAAS,IAAI,OAAuC;EAEpD,aAAa;GACX,SAAS,OAAO,OAAuC;GACvD,IAAI,SAAS,SAAS,GACpB,KAAK,SAAS,OAAO,KAAK;EAE9B;CACF;;;;CAKA,KACE,OACA,SACA,UAA+B,CAAC,GACpB;EACZ,OAAO,KAAK,GAAG,OAAO,SAAS;GAAE,GAAG;GAAS,MAAM;EAAK,CAAC;CAC3D;;;;CAKA,IACE,OACA,SACM;EACN,IAAI,CAAC,SAAS;GACZ,KAAK,SAAS,OAAO,KAAK;GAC1B;EACF;EAEA,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;EACxC,IAAI,UAAU;GACZ,SAAS,SAAQ,YAAW;IAC1B,IAAI,QAAQ,YAAY,SACtB,SAAS,OAAO,OAAO;GAE3B,CAAC;GACD,IAAI,SAAS,SAAS,GACpB,KAAK,SAAS,OAAO,KAAK;EAE9B;CACF;;;;CAKA,KAA+B,OAAU,MAAyB;EAChE,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;EACxC,IAAI,CAAC,YAAY,SAAS,SAAS,GACjC;EAIF,MAAM,iBAAiB,MAAM,KAAK,QAAQ,CAAA,CAAE,MAAM,GAAG,MAAM;GACzD,MAAM,YAAY,EAAE,QAAQ,YAAY;GAExC,QADkB,EAAE,QAAQ,YAAY,KACrB;EACrB,CAAC;EAED,MAAM,WAA2C,CAAC;EAElD,eAAe,SAAQ,YAAW;GAChC,IAAI;IACF,QAAQ,QAAQ,IAAI;IACpB,IAAI,QAAQ,QAAQ,MAClB,SAAS,KAAK,OAAO;GAEzB,SAAS,OAAO;IACd,QAAQ,MACN,sDAAsD,OAAO,KAAK,EAAC,KACnE,KACF;GACF;EACF,CAAC;EAGD,SAAS,SAAQ,YAAW,SAAS,OAAO,OAAO,CAAC;EACpD,IAAI,SAAS,SAAS,GACpB,KAAK,SAAS,OAAO,KAAK;CAE9B;;;;CAKA,QAAc;EACZ,KAAK,SAAS,MAAM;CACtB;;;;CAKA,cAAc,OAAgC;EAC5C,IAAI,UAAU,KAAA,GACZ,OAAO,KAAK,SAAS,IAAI,KAAK,CAAA,EAAG,QAAQ;EAG3C,IAAI,QAAQ;EACZ,KAAK,SAAS,SAAQ,aAAY;GAChC,SAAS,SAAS;EACpB,CAAC;EACD,OAAO;CACT;AACF"}
|
package/es/utils/formatters.d.ts
CHANGED
package/es/utils/formatters.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
@@ -20,13 +20,13 @@ function formatBankCard(value) {
|
|
|
20
20
|
function formatAmount(value, decimalPlaces = 2) {
|
|
21
21
|
let result = value.replace(/[^\d.]/g, "");
|
|
22
22
|
const parts = result.split(".");
|
|
23
|
-
if (parts.length > 2) result = parts[0]
|
|
24
|
-
if (parts.length === 2 && parts[1].length > decimalPlaces) result = parts[0]
|
|
23
|
+
if (parts.length > 2) result = `${parts[0]}.${parts.slice(1).join("")}`;
|
|
24
|
+
if (parts.length === 2 && parts[1].length > decimalPlaces) result = `${parts[0]}.${parts[1].slice(0, decimalPlaces)}`;
|
|
25
25
|
if (result.length > 1 && result.startsWith("0") && result[1] !== ".") result = result.replace(/^0+/, "") || "0";
|
|
26
26
|
return result;
|
|
27
27
|
}
|
|
28
28
|
function formatIdCard(value) {
|
|
29
|
-
return value.replace(/[^\
|
|
29
|
+
return value.replace(/[^\dX]/gi, "").slice(0, 18).toUpperCase();
|
|
30
30
|
}
|
|
31
31
|
function formatLicensePlate(value) {
|
|
32
32
|
return value.toUpperCase().slice(0, 8);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatters.js","names":[],"sources":["../../src/utils/formatters.ts"],"sourcesContent":["/**\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]
|
|
1
|
+
{"version":3,"file":"formatters.js","names":[],"sources":["../../src/utils/formatters.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;AASO,SAAS,YAAY,OAAuB;CACjD,MAAM,SAAS,MAAM,QAAQ,OAAO,EAAE,CAAA,CAAE,MAAM,GAAG,EAAE;CACnD,IAAI,OAAO,UAAU,GAAG,OAAO;CAC/B,IAAI,OAAO,UAAU,GAAG,OAAO,GAAG,OAAO,MAAM,GAAG,CAAC,EAAC,GAAI,OAAO,MAAM,CAAC;CACtE,OAAO,GAAG,OAAO,MAAM,GAAG,CAAC,EAAC,GAAI,OAAO,MAAM,GAAG,CAAC,EAAC,GAAI,OAAO,MAAM,CAAC;AACtE;AAMO,SAAS,eAAe,OAAuB;CAEpD,OADe,MAAM,QAAQ,OAAO,EAAE,CAAA,CAAE,MAAM,GAAG,EAC1C,CAAA,CAAO,QAAQ,kBAAkB,KAAK;AAC/C;AAOO,SAAS,aAAa,OAAe,gBAAwB,GAAW;CAE7E,IAAI,SAAS,MAAM,QAAQ,WAAW,EAAE;CAGxC,MAAM,QAAQ,OAAO,MAAM,GAAG;CAC9B,IAAI,MAAM,SAAS,GACjB,SAAS,GAAG,MAAM,GAAE,GAAI,MAAM,MAAM,CAAC,CAAA,CAAE,KAAK,EAAE;CAIhD,IAAI,MAAM,WAAW,KAAK,MAAM,EAAC,CAAE,SAAS,eAC1C,SAAS,GAAG,MAAM,GAAE,GAAI,MAAM,EAAC,CAAE,MAAM,GAAG,aAAa;CAIzD,IAAI,OAAO,SAAS,KAAK,OAAO,WAAW,GAAG,KAAK,OAAO,OAAO,KAC/D,SAAS,OAAO,QAAQ,OAAO,EAAE,KAAK;CAGxC,OAAO;AACT;AAKO,SAAS,aAAa,OAAuB;CAClD,OAAO,MACJ,QAAQ,YAAY,EAAE,CAAA,CACtB,MAAM,GAAG,EAAE,CAAA,CACX,YAAY;AACjB;AAKO,SAAS,mBAAmB,OAAuB;CACxD,OAAO,MAAM,YAAY,CAAA,CAAE,MAAM,GAAG,CAAC;AACvC;AAOO,SAAS,iBAAiB,OAAe,SAAiB,GAAW;CAC1E,OAAO,MAAM,QAAQ,OAAO,EAAE,CAAA,CAAE,MAAM,GAAG,MAAM;AACjD;AAOA,MAAM,6BAA6C,IAAI,IAAI;CACzD,CAAC,SAAS,WAAW;CACrB,CAAC,YAAY,cAAc;CAC3B,CAAC,UAAU,YAAY;CACvB,CAAC,iBAAiB,kBAAkB;CACpC,CAAC,cAAc,gBAAgB;AACjC,CAAC;AAKM,SAAS,kBACd,MACA,WACM;CACN,WAAW,IAAI,MAAM,SAAS;AAChC;AAKO,SAAS,aAAa,MAA6C;CACxE,OAAO,WAAW,IAAI,IAAI;AAC5B;AAKO,SAAS,eAAe,MAAc,OAAuB;CAClE,MAAM,YAAY,WAAW,IAAI,IAAI;CACrC,OAAO,YAAY,UAAU,KAAK,IAAI;AACxC"}
|
package/es/utils/index.d.ts
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* 工具函数导出
|
|
3
3
|
* @module utils
|
|
4
4
|
*/
|
|
5
|
-
export * from './event-emitter';
|
|
6
5
|
export * from './device';
|
|
7
6
|
export * from './dom';
|
|
8
|
-
export * from './
|
|
7
|
+
export * from './event-emitter';
|
|
9
8
|
export * from './formatters';
|
|
10
|
-
|
|
9
|
+
export * from './random';
|
package/es/utils/index.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
9
9
|
*/
|
|
10
|
-
import { EventEmitter } from "./event-emitter.js";
|
|
11
10
|
import { getDeviceType, getSafeAreaInsets, getViewportInfo, isMobile, isMobileUA, isTouchDevice, onViewportChange, supportsVibrate, vibrate } from "./device.js";
|
|
12
|
-
import { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass } from "./dom.js";
|
|
13
|
-
import {
|
|
11
|
+
import { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, sanitizeSvgIcon, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass } from "./dom.js";
|
|
12
|
+
import { EventEmitter } from "./event-emitter.js";
|
|
14
13
|
import { applyFormatter, formatAmount, formatBankCard, formatIdCard, formatLicensePlate, formatPhone, formatVerifyCode, getFormatter, registerFormatter } from "./formatters.js";
|
|
15
|
-
|
|
14
|
+
import { createRandomLetterLayout, createRandomMixedLayout, createRandomNumberLayout, createRandomPinLayout, getRandomAlphanumeric, getRandomLetters, getRandomNumbers, refreshRandomLayout, shuffleArray } from "./random.js";
|
|
15
|
+
export { EventEmitter, applyFormatter, createElement, createRandomLetterLayout, createRandomMixedLayout, createRandomNumberLayout, createRandomPinLayout, deleteCharBeforeCursor, formatAmount, formatBankCard, formatIdCard, formatLicensePlate, formatPhone, formatVerifyCode, getBoundingRect, getDeviceType, getElementOffset, getFormatter, getInputCursorPosition, getRandomAlphanumeric, getRandomLetters, getRandomNumbers, getSafeAreaInsets, getViewportInfo, insertTextAtCursor, isClickOutside, isElementInViewport, isMobile, isMobileUA, isTouchDevice, onClickOutside, onViewportChange, preventDefaultAndStopPropagation, refreshRandomLayout, registerFormatter, sanitizeSvgIcon, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, shuffleArray, supportsVibrate, toggleClass, vibrate };
|
|
16
16
|
/*! End of @composy/keyboard-core | Powered by @composy/builder */
|
package/es/utils/random.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export declare function getRandomAlphanumeric(): string[];
|
|
|
24
24
|
/**
|
|
25
25
|
* 生成随机数字键盘布局
|
|
26
26
|
* @param options - 配置选项
|
|
27
|
+
* @param options.keysPerRow - Number of keys per row
|
|
28
|
+
* @param options.includeBackspace - Whether to include backspace
|
|
29
|
+
* @param options.includeDone - Whether to include done
|
|
30
|
+
* @param options.includeClear - Whether to include clear
|
|
27
31
|
*/
|
|
28
32
|
export declare function createRandomNumberLayout(options?: {
|
|
29
33
|
/** 每行按键数 */
|
|
@@ -68,4 +72,3 @@ export declare function createRandomMixedLayout(options?: {
|
|
|
68
72
|
* @returns 新的随机布局
|
|
69
73
|
*/
|
|
70
74
|
export declare function refreshRandomLayout(layout: KeyboardConfig): KeyboardConfig;
|
|
71
|
-
//# sourceMappingURL=random.d.ts.map
|
package/es/utils/random.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
@@ -65,7 +65,7 @@ function chunkArray(array, chunkSize) {
|
|
|
65
65
|
}
|
|
66
66
|
function createRandomNumberLayout(options) {
|
|
67
67
|
const { keysPerRow = 3, includeBackspace = true, includeDone = true, includeClear = false } = options || {};
|
|
68
|
-
const rows = chunkArray(getRandomNumbers().map((n, i) => createCharKey(n, i)), keysPerRow).map((keys
|
|
68
|
+
const rows = chunkArray(getRandomNumbers().map((n, i) => createCharKey(n, i)), keysPerRow).map((keys) => ({
|
|
69
69
|
className: "numpad-row",
|
|
70
70
|
keys
|
|
71
71
|
}));
|
package/es/utils/random.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random.js","names":[],"sources":["../../src/utils/random.ts"],"sourcesContent":["/**\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"random.js","names":[],"sources":["../../src/utils/random.ts"],"sourcesContent":["/**\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":"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"}
|
package/esm/icons.js
CHANGED
package/esm/icons.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.js","names":[],"sources":["../src/icons.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;AASO,MAAM,cAAc;AAKpB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,gBAAgB;AAKtB,MAAM,aAAa;AAKnB,MAAM,QAAQ;CACnB,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,UAAU;CACV,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"icons.js","names":[],"sources":["../src/icons.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"],"mappings":";;;;;;;;;;AASO,MAAM,cAAc;AAKpB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,aAAa;AAKnB,MAAM,gBAAgB;AAKtB,MAAM,aAAa;AAKnB,MAAM,QAAQ;CACnB,QAAQ;CACR,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,OAAO;CACP,UAAU;CACV,OAAO;AACT"}
|
package/esm/index.js
CHANGED
|
@@ -2,36 +2,36 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/keyboard-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:29:15 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
9
9
|
*/
|
|
10
|
-
import { qwertyLayout } from "./layouts/qwerty.js";
|
|
11
10
|
import { ICONS, ICON_CHECK, ICON_CLEAR, ICON_CLOSE, ICON_DELETE, ICON_ENTER, ICON_KEYBOARD, ICON_SHIFT, ICON_SPACE, ICON_VOICE } from "./icons.js";
|
|
12
|
-
import { integerLayout, numberLayout } from "./layouts/number.js";
|
|
13
|
-
import { symbolLayout, symbolLayout2 } from "./layouts/symbol.js";
|
|
14
|
-
import { PLATE_LETTERS, PROVINCES, licensePlateAlphanumericLayout, licensePlateLayout, licensePlateLetterLayout, licensePlateProvinceLayout } from "./layouts/license-plate.js";
|
|
15
|
-
import { idcardLayout } from "./layouts/idcard.js";
|
|
16
|
-
import { phoneLayout, phoneSimpleLayout } from "./layouts/phone.js";
|
|
17
11
|
import { amountLayout, amountSimpleLayout } from "./layouts/amount.js";
|
|
18
12
|
import { bankcardLayout } from "./layouts/bankcard.js";
|
|
19
|
-
import { verifycodeLayout } from "./layouts/verifycode.js";
|
|
20
13
|
import { EMAIL_SUFFIXES, emailLayout } from "./layouts/email.js";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
14
|
+
import { idcardLayout } from "./layouts/idcard.js";
|
|
15
|
+
import { PLATE_LETTERS, PROVINCES, licensePlateAlphanumericLayout, licensePlateLayout, licensePlateLetterLayout, licensePlateProvinceLayout } from "./layouts/license-plate.js";
|
|
16
|
+
import { integerLayout, numberLayout } from "./layouts/number.js";
|
|
17
|
+
import { phoneLayout, phoneSimpleLayout } from "./layouts/phone.js";
|
|
23
18
|
import { punctLayout } from "./layouts/punct.js";
|
|
19
|
+
import { qwertyLayout } from "./layouts/qwerty.js";
|
|
20
|
+
import { searchLayout } from "./layouts/search.js";
|
|
21
|
+
import { symbolLayout, symbolLayout2 } from "./layouts/symbol.js";
|
|
22
|
+
import { urlLayout } from "./layouts/url.js";
|
|
23
|
+
import { verifycodeLayout } from "./layouts/verifycode.js";
|
|
24
24
|
import { getAvailableLayouts, getLayout, hasLayout, registerLayout, registerLayouts, unregisterLayout } from "./layouts/index.js";
|
|
25
|
-
import { EventEmitter } from "./utils/event-emitter.js";
|
|
26
25
|
import { getDeviceType, getSafeAreaInsets, getViewportInfo, isMobile, isMobileUA, isTouchDevice, onViewportChange, supportsVibrate, vibrate } from "./utils/device.js";
|
|
27
|
-
import { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass } from "./utils/dom.js";
|
|
26
|
+
import { createElement, deleteCharBeforeCursor, getBoundingRect, getElementOffset, getInputCursorPosition, insertTextAtCursor, isClickOutside, isElementInViewport, onClickOutside, preventDefaultAndStopPropagation, sanitizeSvgIcon, scrollIntoViewIfNeeded, setInputCursorPosition, setStyles, toggleClass } from "./utils/dom.js";
|
|
27
|
+
import { EventEmitter } from "./utils/event-emitter.js";
|
|
28
28
|
import { KeyboardManager, createKeyboardManager } from "./managers/keyboard-manager.js";
|
|
29
|
-
import { PositionManager, createPositionManager } from "./managers/position-manager.js";
|
|
30
29
|
import { darkTheme, defaultTheme, iosTheme, materialTheme, minimalTheme, miuiTheme, presetThemes } from "./themes/presets.js";
|
|
31
30
|
import { applyTheme, createTheme, generateThemeStyle, getAllThemes, getAvailableThemes, getCurrentTheme, getTheme, mergeTheme, registerTheme, setCurrentTheme, themeToCSS } from "./themes/index.js";
|
|
31
|
+
import { PositionManager, createPositionManager } from "./managers/position-manager.js";
|
|
32
32
|
import { KeyboardRenderer, createKeyboardRenderer } from "./managers/keyboard-renderer.js";
|
|
33
33
|
import "./managers/index.js";
|
|
34
|
-
import { createRandomLetterLayout, createRandomMixedLayout, createRandomNumberLayout, createRandomPinLayout, getRandomAlphanumeric, getRandomLetters, getRandomNumbers, refreshRandomLayout, shuffleArray } from "./utils/random.js";
|
|
35
34
|
import { applyFormatter, formatAmount, formatBankCard, formatIdCard, formatLicensePlate, formatPhone, formatVerifyCode, getFormatter, registerFormatter } from "./utils/formatters.js";
|
|
36
|
-
|
|
35
|
+
import { createRandomLetterLayout, createRandomMixedLayout, createRandomNumberLayout, createRandomPinLayout, getRandomAlphanumeric, getRandomLetters, getRandomNumbers, refreshRandomLayout, shuffleArray } from "./utils/random.js";
|
|
36
|
+
export { EMAIL_SUFFIXES, EventEmitter, ICONS, ICON_CHECK, ICON_CLEAR, ICON_CLOSE, ICON_DELETE, ICON_ENTER, ICON_KEYBOARD, ICON_SHIFT, ICON_SPACE, ICON_VOICE, KeyboardManager, KeyboardRenderer, PLATE_LETTERS, PROVINCES, PositionManager, amountLayout, amountSimpleLayout, applyFormatter, applyTheme, bankcardLayout, createElement, createKeyboardManager, createKeyboardRenderer, createPositionManager, createRandomLetterLayout, createRandomMixedLayout, createRandomNumberLayout, createRandomPinLayout, createTheme, darkTheme, defaultTheme, deleteCharBeforeCursor, emailLayout, formatAmount, formatBankCard, formatIdCard, formatLicensePlate, formatPhone, formatVerifyCode, generateThemeStyle, getAllThemes, getAvailableLayouts, getAvailableThemes, getBoundingRect, getCurrentTheme, getDeviceType, getElementOffset, getFormatter, getInputCursorPosition, getLayout, getRandomAlphanumeric, getRandomLetters, getRandomNumbers, getSafeAreaInsets, getTheme, getViewportInfo, hasLayout, idcardLayout, insertTextAtCursor, integerLayout, iosTheme, isClickOutside, isElementInViewport, isMobile, isMobileUA, isTouchDevice, licensePlateAlphanumericLayout, licensePlateLayout, licensePlateLetterLayout, licensePlateProvinceLayout, materialTheme, mergeTheme, minimalTheme, miuiTheme, numberLayout, onClickOutside, onViewportChange, phoneLayout, phoneSimpleLayout, presetThemes, preventDefaultAndStopPropagation, punctLayout, qwertyLayout, refreshRandomLayout, registerFormatter, registerLayout, registerLayouts, registerTheme, sanitizeSvgIcon, scrollIntoViewIfNeeded, searchLayout, setCurrentTheme, setInputCursorPosition, setStyles, shuffleArray, supportsVibrate, symbolLayout, symbolLayout2, themeToCSS, toggleClass, unregisterLayout, urlLayout, verifycodeLayout, vibrate };
|
|
37
37
|
/*! End of @composy/keyboard-core | Powered by @composy/builder */
|
package/esm/layouts/amount.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"amount.js","names":[],"sources":["../../src/layouts/amount.ts"],"sourcesContent":["/**\n * 金额键盘布局\n * @module layouts/amount\n */\n\nimport type { KeyboardConfig, KeyDefinition } from '../types'\nimport {
|
|
1
|
+
{"version":3,"file":"amount.js","names":[],"sources":["../../src/layouts/amount.ts"],"sourcesContent":["/**\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"],"mappings":";;;;;;;;;;;AAWA,SAAS,gBAAgB,KAA4B;CACnD,OAAO;EACL,IAAI,UAAU;EACd,MAAM;EACN,OAAO;EACP,OAAO;EACP,WAAW;CACb;AACF;AAKO,MAAM,eAA+B;CAC1C,MAAM;CACN,MAAM;CACN,cAAc;CACd,MAAM;EACJ;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;IACA,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;GACF;EACF;CACF;CACA,MAAM;EACJ,WAAW;EACX,eAAe;CACjB;AACF;AAKO,MAAM,qBAAqC;CAChD,MAAM;CACN,MAAM;CACN,cAAc;CACd,MAAM;EACJ;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,MAAM;KACN,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,WAAW;IACb;GACF;EACF;EACA;GACE,WAAW;GACX,MAAM;IACJ;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;IACA,gBAAgB,GAAG;IACnB;KACE,IAAI;KACJ,MAAM;KACN,OAAO;KACP,OAAO;KACP,WAAW;IACb;GACF;EACF;CACF;CACA,MAAM;EACJ,WAAW;EACX,eAAe;CACjB;AACF"}
|