@composy/keyboard-vue 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/dist/index.css +797 -0
- package/dist/index.js +1250 -0
- package/dist/index.js.map +1 -0
- package/dist/index.min.css +1 -0
- package/dist/index.min.js +1 -0
- package/es/components/KeyboardKey.js +17 -0
- package/es/components/KeyboardKey.js.map +1 -0
- package/es/components/KeyboardKey.vue_vue_type_script_setup_true_lang.js +131 -0
- package/es/components/KeyboardKey.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/es/components/KeyboardPopup.js +17 -0
- package/es/components/KeyboardPopup.js.map +1 -0
- package/es/components/KeyboardPopup.vue_vue_type_script_setup_true_lang.js +164 -0
- package/es/components/KeyboardPopup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/es/components/LicensePlateKeyboard.js +17 -0
- package/es/components/LicensePlateKeyboard.js.map +1 -0
- package/es/components/LicensePlateKeyboard.vue_vue_type_script_setup_true_lang.js +97 -0
- package/es/components/LicensePlateKeyboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/es/components/VirtualKeyboard.js +17 -0
- package/es/components/VirtualKeyboard.js.map +1 -0
- package/es/components/VirtualKeyboard.vue_vue_type_script_setup_true_lang.js +127 -0
- package/es/components/VirtualKeyboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/es/components/index.d.ts +9 -0
- package/es/components/index.d.ts.map +1 -0
- package/es/components/index.js +15 -0
- package/es/composables/index.d.ts +7 -0
- package/es/composables/index.d.ts.map +1 -0
- package/es/composables/index.js +13 -0
- package/es/composables/useKeyboard.d.ts +113 -0
- package/es/composables/useKeyboard.d.ts.map +1 -0
- package/es/composables/useKeyboard.js +75 -0
- package/es/composables/useKeyboard.js.map +1 -0
- package/es/composables/useKeyboardPopup.d.ts +73 -0
- package/es/composables/useKeyboardPopup.d.ts.map +1 -0
- package/es/composables/useKeyboardPopup.js +119 -0
- package/es/composables/useKeyboardPopup.js.map +1 -0
- package/es/directives/index.d.ts +6 -0
- package/es/directives/index.d.ts.map +1 -0
- package/es/directives/index.js +12 -0
- package/es/directives/v-keyboard.d.ts +36 -0
- package/es/directives/v-keyboard.d.ts.map +1 -0
- package/es/directives/v-keyboard.js +65 -0
- package/es/directives/v-keyboard.js.map +1 -0
- package/es/index.d.ts +42 -0
- package/es/index.d.ts.map +1 -0
- package/es/index.js +34 -0
- package/es/index.js.map +1 -0
- package/es/plugins/engine-plugin.d.ts +37 -0
- package/es/plugins/engine-plugin.d.ts.map +1 -0
- package/es/plugins/engine-plugin.js +37 -0
- package/es/plugins/engine-plugin.js.map +1 -0
- package/es/plugins/index.d.ts +6 -0
- package/es/plugins/index.d.ts.map +1 -0
- package/es/plugins/index.js +12 -0
- package/es/style/css.js +1 -0
- package/es/style/index.js +1 -0
- package/es/style/index.less +1 -0
- package/es/styles/index.less +267 -0
- package/es/styles/keyboard.less +399 -0
- package/es/styles/themes.less +233 -0
- package/lib/components/KeyboardKey.cjs +21 -0
- package/lib/components/KeyboardKey.cjs.map +1 -0
- package/lib/components/KeyboardKey.vue_vue_type_script_setup_true_lang.cjs +131 -0
- package/lib/components/KeyboardKey.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/lib/components/KeyboardPopup.cjs +21 -0
- package/lib/components/KeyboardPopup.cjs.map +1 -0
- package/lib/components/KeyboardPopup.vue_vue_type_script_setup_true_lang.cjs +164 -0
- package/lib/components/KeyboardPopup.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/lib/components/LicensePlateKeyboard.cjs +21 -0
- package/lib/components/LicensePlateKeyboard.cjs.map +1 -0
- package/lib/components/LicensePlateKeyboard.vue_vue_type_script_setup_true_lang.cjs +97 -0
- package/lib/components/LicensePlateKeyboard.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/lib/components/VirtualKeyboard.cjs +21 -0
- package/lib/components/VirtualKeyboard.cjs.map +1 -0
- package/lib/components/VirtualKeyboard.vue_vue_type_script_setup_true_lang.cjs +127 -0
- package/lib/components/VirtualKeyboard.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/lib/components/index.cjs +19 -0
- package/lib/components/index.d.ts +9 -0
- package/lib/composables/index.cjs +15 -0
- package/lib/composables/index.d.ts +7 -0
- package/lib/composables/useKeyboard.cjs +76 -0
- package/lib/composables/useKeyboard.cjs.map +1 -0
- package/lib/composables/useKeyboard.d.ts +113 -0
- package/lib/composables/useKeyboardPopup.cjs +120 -0
- package/lib/composables/useKeyboardPopup.cjs.map +1 -0
- package/lib/composables/useKeyboardPopup.d.ts +73 -0
- package/lib/directives/index.cjs +13 -0
- package/lib/directives/index.d.ts +6 -0
- package/lib/directives/v-keyboard.cjs +66 -0
- package/lib/directives/v-keyboard.cjs.map +1 -0
- package/lib/directives/v-keyboard.d.ts +36 -0
- package/lib/index.cjs +537 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.ts +42 -0
- package/lib/package.json +3 -0
- package/lib/plugins/engine-plugin.cjs +37 -0
- package/lib/plugins/engine-plugin.cjs.map +1 -0
- package/lib/plugins/engine-plugin.d.ts +37 -0
- package/lib/plugins/index.cjs +13 -0
- package/lib/plugins/index.d.ts +6 -0
- package/lib/style/css.js +1 -0
- package/lib/style/index.css +2 -0
- package/lib/style/index.js +1 -0
- package/lib/styles/index.css +229 -0
- package/lib/styles/keyboard.css +346 -0
- package/lib/styles/themes.css +213 -0
- package/package.json +141 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
const require_KeyboardKey = require("./KeyboardKey.cjs");
|
|
11
|
+
let vue = require("vue");
|
|
12
|
+
let _composy_keyboard_core = require("@composy/keyboard-core");
|
|
13
|
+
//#region src/components/VirtualKeyboard.vue?vue&type=script&setup=true&lang.ts
|
|
14
|
+
const _hoisted_1 = { class: "virtual-keyboard" };
|
|
15
|
+
const _hoisted_2 = {
|
|
16
|
+
key: 1,
|
|
17
|
+
class: "virtual-keyboard__empty"
|
|
18
|
+
};
|
|
19
|
+
const _hoisted_3 = {
|
|
20
|
+
key: 0,
|
|
21
|
+
class: "keyboard-options-panel"
|
|
22
|
+
};
|
|
23
|
+
const _hoisted_4 = { class: "keyboard-options-panel__header" };
|
|
24
|
+
const _hoisted_5 = { class: "keyboard-options-panel__grid" };
|
|
25
|
+
const _hoisted_6 = ["onMousedown", "onTouchstart"];
|
|
26
|
+
var VirtualKeyboard_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
27
|
+
__name: "VirtualKeyboard",
|
|
28
|
+
props: {
|
|
29
|
+
type: {
|
|
30
|
+
type: String,
|
|
31
|
+
required: false,
|
|
32
|
+
default: "qwerty"
|
|
33
|
+
},
|
|
34
|
+
isUpperCase: {
|
|
35
|
+
type: Boolean,
|
|
36
|
+
required: false,
|
|
37
|
+
default: false
|
|
38
|
+
},
|
|
39
|
+
layout: {
|
|
40
|
+
type: Object,
|
|
41
|
+
required: false
|
|
42
|
+
},
|
|
43
|
+
keyWidth: {
|
|
44
|
+
type: Number,
|
|
45
|
+
required: false,
|
|
46
|
+
default: 36
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
emits: ["keypress", "selectOption"],
|
|
50
|
+
setup(__props, { emit: __emit }) {
|
|
51
|
+
const props = __props;
|
|
52
|
+
const emit = __emit;
|
|
53
|
+
const showOptionsPanel = (0, vue.ref)(false);
|
|
54
|
+
const currentOptions = (0, vue.ref)([]);
|
|
55
|
+
const currentLayout = (0, vue.computed)(() => {
|
|
56
|
+
if (props.layout) return props.layout;
|
|
57
|
+
return (0, _composy_keyboard_core.getLayout)(props.type) ?? null;
|
|
58
|
+
});
|
|
59
|
+
const handleKeyPress = (key) => {
|
|
60
|
+
emit("keypress", key);
|
|
61
|
+
};
|
|
62
|
+
const handleShowOptions = (options) => {
|
|
63
|
+
currentOptions.value = options;
|
|
64
|
+
showOptionsPanel.value = true;
|
|
65
|
+
};
|
|
66
|
+
const handleSelectOption = (option, event) => {
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
event.stopPropagation();
|
|
69
|
+
showOptionsPanel.value = false;
|
|
70
|
+
emit("selectOption", option);
|
|
71
|
+
};
|
|
72
|
+
const closeOptionsPanel = () => {
|
|
73
|
+
showOptionsPanel.value = false;
|
|
74
|
+
};
|
|
75
|
+
const getRowStyle = (rowIndex) => {
|
|
76
|
+
return {};
|
|
77
|
+
};
|
|
78
|
+
return (_ctx, _cache) => {
|
|
79
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1, [
|
|
80
|
+
currentLayout.value ? ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, (0, vue.renderList)(currentLayout.value.rows, (row, rowIndex) => {
|
|
81
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
82
|
+
key: rowIndex,
|
|
83
|
+
class: (0, vue.normalizeClass)(["virtual-keyboard__row", row.className]),
|
|
84
|
+
style: (0, vue.normalizeStyle)(getRowStyle(rowIndex))
|
|
85
|
+
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(row.keys, (key) => {
|
|
86
|
+
return (0, vue.openBlock)(), (0, vue.createBlock)(require_KeyboardKey.default, {
|
|
87
|
+
key: key.id,
|
|
88
|
+
"key-def": key,
|
|
89
|
+
"is-upper-case": __props.isUpperCase,
|
|
90
|
+
"base-width": __props.keyWidth,
|
|
91
|
+
"use-flex": row.className === "numpad-row",
|
|
92
|
+
onPress: handleKeyPress,
|
|
93
|
+
onShowOptions: handleShowOptions
|
|
94
|
+
}, null, 8, [
|
|
95
|
+
"key-def",
|
|
96
|
+
"is-upper-case",
|
|
97
|
+
"base-width",
|
|
98
|
+
"use-flex"
|
|
99
|
+
]);
|
|
100
|
+
}), 128))], 6);
|
|
101
|
+
}), 128)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2, " 键盘布局未找到 ")),
|
|
102
|
+
(0, vue.createCommentVNode)(" 选项面板 "),
|
|
103
|
+
(0, vue.createVNode)(vue.Transition, { name: "options-panel" }, {
|
|
104
|
+
default: (0, vue.withCtx)(() => [showOptionsPanel.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3, [(0, vue.createElementVNode)("div", _hoisted_4, [_cache[0] || (_cache[0] = (0, vue.createElementVNode)("span", { class: "keyboard-options-panel__title" }, "选择邮箱后缀", -1)), (0, vue.createElementVNode)("button", {
|
|
105
|
+
class: "keyboard-options-panel__close",
|
|
106
|
+
type: "button",
|
|
107
|
+
onClick: closeOptionsPanel,
|
|
108
|
+
onTouchstart: (0, vue.withModifiers)(closeOptionsPanel, ["prevent"])
|
|
109
|
+
}, " × ", 32)]), (0, vue.createElementVNode)("div", _hoisted_5, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(currentOptions.value, (option) => {
|
|
110
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
111
|
+
key: option,
|
|
112
|
+
class: "keyboard-options-panel__item",
|
|
113
|
+
type: "button",
|
|
114
|
+
onMousedown: (0, vue.withModifiers)((e) => handleSelectOption(option, e), ["prevent"]),
|
|
115
|
+
onTouchstart: (0, vue.withModifiers)((e) => handleSelectOption(option, e), ["prevent"])
|
|
116
|
+
}, (0, vue.toDisplayString)(option), 41, _hoisted_6);
|
|
117
|
+
}), 128))])])) : (0, vue.createCommentVNode)("v-if", true)]),
|
|
118
|
+
_: 1
|
|
119
|
+
})
|
|
120
|
+
]);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
//#endregion
|
|
125
|
+
exports.default = VirtualKeyboard_vue_vue_type_script_setup_true_lang_default;
|
|
126
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|
|
127
|
+
//# sourceMappingURL=VirtualKeyboard.vue_vue_type_script_setup_true_lang.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualKeyboard.vue_vue_type_script_setup_true_lang.cjs","names":[],"sources":["../../src/components/VirtualKeyboard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type {\n KeyboardConfig,\n KeyboardType,\n KeyDefinition,\n} from '@composy/keyboard-core'\nimport { getLayout } from '@composy/keyboard-core'\nimport KeyboardKey from './KeyboardKey.vue'\n\nconst props = withDefaults(defineProps<{\n /**\n * 键盘类型\n */\n type?: KeyboardType | string\n /**\n * 是否大写状态\n */\n isUpperCase?: boolean\n /**\n * 自定义布局配置\n */\n layout?: KeyboardConfig\n /**\n * 按键基础宽度\n */\n keyWidth?: number\n}>(), {\n type: 'qwerty',\n isUpperCase: false,\n keyWidth: 36,\n})\n\nconst emit = defineEmits<{\n keypress: [key: KeyDefinition]\n selectOption: [option: string]\n}>()\n\n/**\n * 选项面板状态\n */\nconst showOptionsPanel = ref(false)\nconst currentOptions = ref<string[]>([])\n\n/**\n * 当前布局配置\n */\nconst currentLayout = computed(() => {\n if (props.layout) {\n return props.layout\n }\n return getLayout(props.type) ?? null\n})\n\n/**\n * 处理按键\n */\nconst handleKeyPress = (key: KeyDefinition) => {\n emit('keypress', key)\n}\n\n/**\n * 显示选项面板\n */\nconst handleShowOptions = (options: string[]) => {\n currentOptions.value = options\n showOptionsPanel.value = true\n}\n\n/**\n * 处理选项选择\n */\nconst handleSelectOption = (option: string, event: MouseEvent | TouchEvent) => {\n event.preventDefault()\n event.stopPropagation()\n showOptionsPanel.value = false\n emit('selectOption', option)\n}\n\n/**\n * 关闭选项面板\n */\nconst closeOptionsPanel = () => {\n showOptionsPanel.value = false\n}\n\n/**\n * 计算每行的总宽度,用于居中对齐\n */\nconst getRowStyle = (rowIndex: number) => {\n // 可以根据需要添加行样式\n return {}\n}\n</script>\n\n<template>\n <div class=\"virtual-keyboard\">\n <template v-if=\"currentLayout\">\n <div\n v-for=\"(row, rowIndex) in currentLayout.rows\"\n :key=\"rowIndex\"\n class=\"virtual-keyboard__row\"\n :class=\"row.className\"\n :style=\"getRowStyle(rowIndex)\"\n >\n <KeyboardKey\n v-for=\"key in row.keys\"\n :key=\"key.id\"\n :key-def=\"key\"\n :is-upper-case=\"isUpperCase\"\n :base-width=\"keyWidth\"\n :use-flex=\"row.className === 'numpad-row'\"\n @press=\"handleKeyPress\"\n @show-options=\"handleShowOptions\"\n />\n </div>\n </template>\n <div v-else class=\"virtual-keyboard__empty\">\n 键盘布局未找到\n </div>\n\n <!-- 选项面板 -->\n <Transition name=\"options-panel\">\n <div v-if=\"showOptionsPanel\" class=\"keyboard-options-panel\">\n <div class=\"keyboard-options-panel__header\">\n <span class=\"keyboard-options-panel__title\">选择邮箱后缀</span>\n <button class=\"keyboard-options-panel__close\" type=\"button\" @click=\"closeOptionsPanel\" @touchstart.prevent=\"closeOptionsPanel\">\n ×\n </button>\n </div>\n <div class=\"keyboard-options-panel__grid\">\n <button\n v-for=\"option in currentOptions\"\n :key=\"option\"\n class=\"keyboard-options-panel__item\"\n type=\"button\"\n @mousedown.prevent=\"(e) => handleSelectOption(option, e)\"\n @touchstart.prevent=\"(e) => handleSelectOption(option, e)\"\n >\n {{ option }}\n </button>\n </div>\n </div>\n </Transition>\n </div>\n</template>\n\n<style>\n.virtual-keyboard {\n --key-gap: var(--keyboard-key-gap, 6px);\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--key-gap);\n padding: var(--keyboard-padding, 6px);\n background-color: var(--keyboard-bg, #d1d5db);\n border-radius: 0;\n user-select: none;\n -webkit-user-select: none;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;\n}\n\n.virtual-keyboard__row {\n display: flex;\n justify-content: center;\n gap: var(--key-gap);\n width: 100%;\n padding: 0 2px;\n}\n\n/* 数字键盘行样式 - 按钮均匀分布填满宽度 */\n.virtual-keyboard__row.numpad-row {\n justify-content: stretch;\n}\n\n.virtual-keyboard__row.numpad-row .keyboard-key-wrapper {\n flex: 1;\n}\n\n.virtual-keyboard__empty {\n padding: 20px;\n color: #999;\n text-align: center;\n}\n\n/* 全屏选项面板 */\n.keyboard-options-panel {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n background: var(--keyboard-bg, #d1d5db);\n z-index: 10;\n display: flex;\n flex-direction: column;\n padding: 8px;\n}\n\n.keyboard-options-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 8px 12px;\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n margin-bottom: 8px;\n}\n\n.keyboard-options-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--keyboard-key-color, #333);\n}\n\n.keyboard-options-panel__close {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n background: var(--keyboard-fn-key-bg, #d4d6dc);\n color: var(--keyboard-key-color, #666);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.keyboard-options-panel__close:active {\n background: var(--keyboard-fn-key-active-bg, #b8bac0);\n}\n\n.keyboard-options-panel__grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.keyboard-options-panel__item {\n padding: 14px 8px;\n border: none;\n border-radius: 8px;\n background: var(--keyboard-key-bg, #fff);\n color: var(--keyboard-key-color, #333);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n transition: background-color 0.15s, transform 0.1s;\n}\n\n.keyboard-options-panel__item:active {\n background: var(--keyboard-option-active-bg, #e8e8e8);\n transform: scale(0.96);\n}\n\n/* 面板动画 */\n.options-panel-enter-active,\n.options-panel-leave-active {\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.options-panel-enter-from,\n.options-panel-leave-to {\n opacity: 0;\n transform: translateY(20px);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAuBd,MAAM,OAAO;EAQb,MAAM,oBAAA,GAAA,IAAA,IAAA,CAAuB,KAAK;EAClC,MAAM,kBAAA,GAAA,IAAA,IAAA,CAA+B,CAAC,CAAC;EAKvC,MAAM,iBAAA,GAAA,IAAA,SAAA,OAA+B;GACnC,IAAI,MAAM,QACR,OAAO,MAAM;GAEf,QAAA,GAAA,uBAAA,UAAA,CAAiB,MAAM,IAAI,KAAK;EAClC,CAAC;EAKD,MAAM,kBAAkB,QAAuB;GAC7C,KAAK,YAAY,GAAG;EACtB;EAKA,MAAM,qBAAqB,YAAsB;GAC/C,eAAe,QAAQ;GACvB,iBAAiB,QAAQ;EAC3B;EAKA,MAAM,sBAAsB,QAAgB,UAAmC;GAC7E,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,iBAAiB,QAAQ;GACzB,KAAK,gBAAgB,MAAM;EAC7B;EAKA,MAAM,0BAA0B;GAC9B,iBAAiB,QAAQ;EAC3B;EAKA,MAAM,eAAe,aAAqB;GAExC,OAAO,CAAC;EACV;;4DAoDQ,OAhDN,YAgDM;IA/CY,cAAA,UAAA,GAAA,IAAA,UAAA,CAAA,IAAA,IAAA,GAAA,IAAA,mBAAA,CAkBR,IAAA,UAAA,EAAA,KAAA,EAAA,IAAA,GAAA,IAAA,WAAA,CAhBsB,cAAA,MAAc,OAAhC,KAAK,aAAQ;8DAgBjB,OAAA;MAfH,KAAK;MACN,QAAA,GAAA,IAAA,eAAA,CAAK,CAAC,yBACE,IAAI,SAAS,CAAA;MACpB,QAAA,GAAA,IAAA,eAAA,CAAO,YAAY,QAAQ,CAAA;gEAW1B,IAAA,UAAA,OAAA,GAAA,IAAA,WAAA,CARc,IAAI,OAAX,QAAG;wDAQV,oBAAA,SAAA;OAPC,KAAK,IAAI;OACT,WAAS;OACT,iBAAe,QAAA;OACf,cAAY,QAAA;OACZ,YAAU,IAAI,cAAS;OACvB,SAAO;OACP,eAAc;;;;;;;;mEAMf,OAFN,YAA4C,WAE5C;gCAEA,QAAA;yBAsBa,IAAA,YAAA,EArBD,MAAK,gBAAe,GAAA;qCAoBxB,CAnBK,iBAAA,UAAA,GAAA,IAAA,UAAA,CAAA,IAAA,GAAA,IAAA,mBAAA,CAmBL,OAnBN,YAmBM,EAAA,GAAA,IAAA,mBAAA,CAbE,OALN,YAKM,CAAA,OAAA,OAAA,OAAA,MAAA,GAAA,IAAA,mBAAA,CAJqD,QAAA,EAAnD,OAAM,gCAA+B,GAAC,UAAM,EAAA,KAAA,GAAA,IAAA,mBAAA,CAGzC,UAAA;MAFD,OAAM;MAAgC,MAAK;MAAU,SAAO;MAAoB,eAAA,GAAA,IAAA,cAAA,CAAoB,mBAAiB,CAAA,SAAA,CAAA;QAAE,OAE/H,EAAA,CAAA,CAAA,IAAA,GAAA,IAAA,mBAAA,CAaI,OAXN,YAWM,GAAA,GAAA,IAAA,UAAA,CAAA,IAAA,IAAA,GAAA,IAAA,mBAAA,CADK,IAAA,UAAA,OAAA,GAAA,IAAA,WAAA,CARU,eAAA,QAAV,WAAM;+DAQN,UAAA;OAPN,KAAK;OACN,OAAM;OACN,MAAK;OACJ,cAAA,GAAA,IAAA,cAAA,EAAoB,MAAM,mBAAmB,QAAQ,CAAC,GAAA,CAAA,SAAA,CAAA;OACtD,eAAA,GAAA,IAAA,cAAA,EAAqB,MAAM,mBAAmB,QAAQ,CAAC,GAAA,CAAA,SAAA,CAAA;kCAErD,MAAM,GAAA,IAAA,UAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
const require_KeyboardKey = require("./KeyboardKey.cjs");
|
|
12
|
+
const require_VirtualKeyboard = require("./VirtualKeyboard.cjs");
|
|
13
|
+
const require_KeyboardPopup = require("./KeyboardPopup.cjs");
|
|
14
|
+
const require_LicensePlateKeyboard = require("./LicensePlateKeyboard.cjs");
|
|
15
|
+
exports.KeyboardKey = require_KeyboardKey.default;
|
|
16
|
+
exports.KeyboardPopup = require_KeyboardPopup.default;
|
|
17
|
+
exports.LicensePlateKeyboard = require_LicensePlateKeyboard.default;
|
|
18
|
+
exports.VirtualKeyboard = require_VirtualKeyboard.default;
|
|
19
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue 组件导出
|
|
3
|
+
* @module components
|
|
4
|
+
*/
|
|
5
|
+
export { default as VirtualKeyboard } from './VirtualKeyboard.vue';
|
|
6
|
+
export { default as KeyboardKey } from './KeyboardKey.vue';
|
|
7
|
+
export { default as KeyboardPopup } from './KeyboardPopup.vue';
|
|
8
|
+
export { default as LicensePlateKeyboard } from './LicensePlateKeyboard.vue';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
const require_useKeyboard = require("./useKeyboard.cjs");
|
|
12
|
+
const require_useKeyboardPopup = require("./useKeyboardPopup.cjs");
|
|
13
|
+
exports.useKeyboard = require_useKeyboard.useKeyboard;
|
|
14
|
+
exports.useKeyboardPopup = require_useKeyboardPopup.useKeyboardPopup;
|
|
15
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
let vue = require("vue");
|
|
12
|
+
let _composy_keyboard_core = require("@composy/keyboard-core");
|
|
13
|
+
//#region src/composables/useKeyboard.ts
|
|
14
|
+
function useKeyboard(options = {}) {
|
|
15
|
+
const { immediate = false, ...keyboardOptions } = options;
|
|
16
|
+
const manager = (0, _composy_keyboard_core.createKeyboardManager)(keyboardOptions);
|
|
17
|
+
const visible = (0, vue.ref)(false);
|
|
18
|
+
const type = (0, vue.ref)(keyboardOptions.type ?? "qwerty");
|
|
19
|
+
const isUpperCase = (0, vue.ref)(keyboardOptions.defaultUpperCase ?? false);
|
|
20
|
+
const value = (0, vue.ref)(keyboardOptions.value ?? "");
|
|
21
|
+
const cursorPosition = (0, vue.ref)(keyboardOptions.value?.length ?? 0);
|
|
22
|
+
const layout = (0, vue.shallowRef)(manager.getLayout());
|
|
23
|
+
const state = (0, vue.reactive)({
|
|
24
|
+
visible: false,
|
|
25
|
+
type: keyboardOptions.type ?? "qwerty",
|
|
26
|
+
isUpperCase: keyboardOptions.defaultUpperCase ?? false,
|
|
27
|
+
value: keyboardOptions.value ?? "",
|
|
28
|
+
cursorPosition: keyboardOptions.value?.length ?? 0,
|
|
29
|
+
maxLength: keyboardOptions.maxLength,
|
|
30
|
+
inputElement: null
|
|
31
|
+
});
|
|
32
|
+
const syncState = (newState) => {
|
|
33
|
+
visible.value = newState.visible;
|
|
34
|
+
type.value = newState.type;
|
|
35
|
+
isUpperCase.value = newState.isUpperCase;
|
|
36
|
+
value.value = newState.value;
|
|
37
|
+
cursorPosition.value = newState.cursorPosition;
|
|
38
|
+
Object.assign(state, newState);
|
|
39
|
+
};
|
|
40
|
+
manager.on("stateChange", syncState);
|
|
41
|
+
manager.on("switch", () => {
|
|
42
|
+
layout.value = manager.getLayout();
|
|
43
|
+
});
|
|
44
|
+
if (immediate) manager.show();
|
|
45
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
46
|
+
manager.destroy();
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
visible,
|
|
50
|
+
type,
|
|
51
|
+
isUpperCase,
|
|
52
|
+
value,
|
|
53
|
+
cursorPosition,
|
|
54
|
+
layout,
|
|
55
|
+
state,
|
|
56
|
+
show: (input) => manager.show(input),
|
|
57
|
+
hide: () => manager.hide(),
|
|
58
|
+
toggle: (input) => manager.toggle(input),
|
|
59
|
+
switchType: (t) => manager.switchType(t),
|
|
60
|
+
toggleShift: () => manager.toggleShift(),
|
|
61
|
+
handleKey: (key) => manager.handleKey(key),
|
|
62
|
+
getKeyLabel: (key) => manager.getKeyLabel(key),
|
|
63
|
+
setValue: (v) => manager.setValue(v),
|
|
64
|
+
appendValue: (text) => manager.appendValue(text),
|
|
65
|
+
setMaxLength: (maxLength) => manager.setMaxLength(maxLength),
|
|
66
|
+
bindInput: (input) => manager.bindInput(input),
|
|
67
|
+
unbindInput: () => manager.unbindInput(),
|
|
68
|
+
on: (event, handler) => manager.on(event, handler),
|
|
69
|
+
once: (event, handler) => manager.once(event, handler),
|
|
70
|
+
destroy: () => manager.destroy()
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
exports.useKeyboard = useKeyboard;
|
|
75
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|
|
76
|
+
//# sourceMappingURL=useKeyboard.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyboard.cjs","names":[],"sources":["../../src/composables/useKeyboard.ts"],"sourcesContent":["/**\n * 键盘管理 Composable\n * @module composables/useKeyboard\n */\n\nimport { computed, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue'\nimport type { Ref } from 'vue'\nimport {\n createKeyboardManager,\n type KeyboardConfig,\n type KeyboardEventMap,\n type KeyboardOptions,\n type KeyboardState,\n type KeyboardType,\n type KeyDefinition,\n} from '@composy/keyboard-core'\n\n/**\n * useKeyboard 选项\n */\nexport interface UseKeyboardOptions extends KeyboardOptions {\n /**\n * 是否立即显示\n */\n immediate?: boolean\n}\n\n/**\n * useKeyboard 返回值\n */\nexport interface UseKeyboardReturn {\n /**\n * 键盘是否可见\n */\n visible: Ref<boolean>\n\n /**\n * 当前键盘类型\n */\n type: Ref<KeyboardType>\n\n /**\n * 是否大写状态\n */\n isUpperCase: Ref<boolean>\n\n /**\n * 当前输入值\n */\n value: Ref<string>\n\n /**\n * 光标位置\n */\n cursorPosition: Ref<number>\n\n /**\n * 当前布局配置\n */\n layout: Ref<KeyboardConfig | null>\n\n /**\n * 完整状态\n */\n state: KeyboardState\n\n /**\n * 显示键盘\n */\n show: (input?: HTMLInputElement | HTMLTextAreaElement) => void\n\n /**\n * 隐藏键盘\n */\n hide: () => void\n\n /**\n * 切换显示/隐藏\n */\n toggle: (input?: HTMLInputElement | HTMLTextAreaElement) => void\n\n /**\n * 切换键盘类型\n */\n switchType: (type: KeyboardType | string) => void\n\n /**\n * 切换大小写\n */\n toggleShift: () => void\n\n /**\n * 处理按键\n */\n handleKey: (key: KeyDefinition) => void\n\n /**\n * 获取按键显示文本\n */\n getKeyLabel: (key: KeyDefinition) => string\n\n /**\n * 设置值\n */\n setValue: (value: string) => void\n\n /**\n * 追加值(在光标位置插入文本)\n */\n appendValue: (text: string) => void\n\n /**\n * 设置最大长度\n */\n setMaxLength: (maxLength?: number) => void\n\n /**\n * 绑定输入框\n */\n bindInput: (input: HTMLInputElement | HTMLTextAreaElement) => void\n\n /**\n * 解绑输入框\n */\n unbindInput: () => void\n\n /**\n * 事件监听\n */\n on: <K extends keyof KeyboardEventMap>(\n event: K,\n handler: (data: KeyboardEventMap[K]) => void\n ) => () => void\n\n /**\n * 单次事件监听\n */\n once: <K extends keyof KeyboardEventMap>(\n event: K,\n handler: (data: KeyboardEventMap[K]) => void\n ) => () => void\n\n /**\n * 销毁\n */\n destroy: () => void\n}\n\n/**\n * 键盘管理 Composable\n */\nexport function useKeyboard(options: UseKeyboardOptions = {}): UseKeyboardReturn {\n const { immediate = false, ...keyboardOptions } = options\n\n // 创建键盘管理器\n const manager = createKeyboardManager(keyboardOptions)\n\n // 响应式状态\n const visible = ref(false)\n const type = ref<KeyboardType>(keyboardOptions.type ?? 'qwerty')\n const isUpperCase = ref(keyboardOptions.defaultUpperCase ?? false)\n const value = ref(keyboardOptions.value ?? '')\n const cursorPosition = ref(keyboardOptions.value?.length ?? 0)\n const layout = shallowRef<KeyboardConfig | null>(manager.getLayout())\n\n // 完整状态(响应式对象)\n const state = reactive<KeyboardState>({\n visible: false,\n type: keyboardOptions.type ?? 'qwerty',\n isUpperCase: keyboardOptions.defaultUpperCase ?? false,\n value: keyboardOptions.value ?? '',\n cursorPosition: keyboardOptions.value?.length ?? 0,\n maxLength: keyboardOptions.maxLength,\n inputElement: null,\n })\n\n // 同步管理器状态到 Vue 响应式状态\n const syncState = (newState: KeyboardState) => {\n visible.value = newState.visible\n type.value = newState.type\n isUpperCase.value = newState.isUpperCase\n value.value = newState.value\n cursorPosition.value = newState.cursorPosition\n\n Object.assign(state, newState)\n }\n\n // 监听状态变化\n manager.on('stateChange', syncState)\n\n // 监听键盘类型切换,更新布局\n manager.on('switch', () => {\n layout.value = manager.getLayout()\n })\n\n // 立即显示\n if (immediate) {\n manager.show()\n }\n\n // 组件卸载时销毁\n onBeforeUnmount(() => {\n manager.destroy()\n })\n\n return {\n visible,\n type,\n isUpperCase,\n value,\n cursorPosition,\n layout,\n state,\n show: (input?: HTMLInputElement | HTMLTextAreaElement) => manager.show(input),\n hide: () => manager.hide(),\n toggle: (input?: HTMLInputElement | HTMLTextAreaElement) => manager.toggle(input),\n switchType: (t: KeyboardType | string) => manager.switchType(t),\n toggleShift: () => manager.toggleShift(),\n handleKey: (key: KeyDefinition) => manager.handleKey(key),\n getKeyLabel: (key: KeyDefinition) => manager.getKeyLabel(key),\n setValue: (v: string) => manager.setValue(v),\n appendValue: (text: string) => manager.appendValue(text),\n setMaxLength: (maxLength?: number) => manager.setMaxLength(maxLength),\n bindInput: (input: HTMLInputElement | HTMLTextAreaElement) => manager.bindInput(input),\n unbindInput: () => manager.unbindInput(),\n on: (event, handler) => manager.on(event, handler),\n once: (event, handler) => manager.once(event, handler),\n destroy: () => manager.destroy(),\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuJO,SAAS,YAAY,UAA8B,CAAC,GAAsB;CAC/E,MAAM,EAAE,YAAY,OAAO,GAAG,oBAAoB;CAGlD,MAAM,WAAA,GAAA,uBAAA,sBAAA,CAAgC,eAAe;CAGrD,MAAM,WAAA,GAAA,IAAA,IAAA,CAAc,KAAK;CACzB,MAAM,QAAA,GAAA,IAAA,IAAA,CAAyB,gBAAgB,QAAQ,QAAQ;CAC/D,MAAM,eAAA,GAAA,IAAA,IAAA,CAAkB,gBAAgB,oBAAoB,KAAK;CACjE,MAAM,SAAA,GAAA,IAAA,IAAA,CAAY,gBAAgB,SAAS,EAAE;CAC7C,MAAM,kBAAA,GAAA,IAAA,IAAA,CAAqB,gBAAgB,OAAO,UAAU,CAAC;CAC7D,MAAM,UAAA,GAAA,IAAA,WAAA,CAA2C,QAAQ,UAAU,CAAC;CAGpE,MAAM,SAAA,GAAA,IAAA,SAAA,CAAgC;EACpC,SAAS;EACT,MAAM,gBAAgB,QAAQ;EAC9B,aAAa,gBAAgB,oBAAoB;EACjD,OAAO,gBAAgB,SAAS;EAChC,gBAAgB,gBAAgB,OAAO,UAAU;EACjD,WAAW,gBAAgB;EAC3B,cAAc;CAChB,CAAC;CAGD,MAAM,aAAa,aAA4B;EAC7C,QAAQ,QAAQ,SAAS;EACzB,KAAK,QAAQ,SAAS;EACtB,YAAY,QAAQ,SAAS;EAC7B,MAAM,QAAQ,SAAS;EACvB,eAAe,QAAQ,SAAS;EAEhC,OAAO,OAAO,OAAO,QAAQ;CAC/B;CAGA,QAAQ,GAAG,eAAe,SAAS;CAGnC,QAAQ,GAAG,gBAAgB;EACzB,OAAO,QAAQ,QAAQ,UAAU;CACnC,CAAC;CAGD,IAAI,WACF,QAAQ,KAAK;CAIf,CAAA,GAAA,IAAA,gBAAA,OAAsB;EACpB,QAAQ,QAAQ;CAClB,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,UAAmD,QAAQ,KAAK,KAAK;EAC5E,YAAY,QAAQ,KAAK;EACzB,SAAS,UAAmD,QAAQ,OAAO,KAAK;EAChF,aAAa,MAA6B,QAAQ,WAAW,CAAC;EAC9D,mBAAmB,QAAQ,YAAY;EACvC,YAAY,QAAuB,QAAQ,UAAU,GAAG;EACxD,cAAc,QAAuB,QAAQ,YAAY,GAAG;EAC5D,WAAW,MAAc,QAAQ,SAAS,CAAC;EAC3C,cAAc,SAAiB,QAAQ,YAAY,IAAI;EACvD,eAAe,cAAuB,QAAQ,aAAa,SAAS;EACpE,YAAY,UAAkD,QAAQ,UAAU,KAAK;EACrF,mBAAmB,QAAQ,YAAY;EACvC,KAAK,OAAO,YAAY,QAAQ,GAAG,OAAO,OAAO;EACjD,OAAO,OAAO,YAAY,QAAQ,KAAK,OAAO,OAAO;EACrD,eAAe,QAAQ,QAAQ;CACjC;AACF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 键盘管理 Composable
|
|
3
|
+
* @module composables/useKeyboard
|
|
4
|
+
*/
|
|
5
|
+
import type { Ref } from 'vue';
|
|
6
|
+
import { type KeyboardConfig, type KeyboardEventMap, type KeyboardOptions, type KeyboardState, type KeyboardType, type KeyDefinition } from '@composy/keyboard-core';
|
|
7
|
+
/**
|
|
8
|
+
* useKeyboard 选项
|
|
9
|
+
*/
|
|
10
|
+
export interface UseKeyboardOptions extends KeyboardOptions {
|
|
11
|
+
/**
|
|
12
|
+
* 是否立即显示
|
|
13
|
+
*/
|
|
14
|
+
immediate?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* useKeyboard 返回值
|
|
18
|
+
*/
|
|
19
|
+
export interface UseKeyboardReturn {
|
|
20
|
+
/**
|
|
21
|
+
* 键盘是否可见
|
|
22
|
+
*/
|
|
23
|
+
visible: Ref<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* 当前键盘类型
|
|
26
|
+
*/
|
|
27
|
+
type: Ref<KeyboardType>;
|
|
28
|
+
/**
|
|
29
|
+
* 是否大写状态
|
|
30
|
+
*/
|
|
31
|
+
isUpperCase: Ref<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* 当前输入值
|
|
34
|
+
*/
|
|
35
|
+
value: Ref<string>;
|
|
36
|
+
/**
|
|
37
|
+
* 光标位置
|
|
38
|
+
*/
|
|
39
|
+
cursorPosition: Ref<number>;
|
|
40
|
+
/**
|
|
41
|
+
* 当前布局配置
|
|
42
|
+
*/
|
|
43
|
+
layout: Ref<KeyboardConfig | null>;
|
|
44
|
+
/**
|
|
45
|
+
* 完整状态
|
|
46
|
+
*/
|
|
47
|
+
state: KeyboardState;
|
|
48
|
+
/**
|
|
49
|
+
* 显示键盘
|
|
50
|
+
*/
|
|
51
|
+
show: (input?: HTMLInputElement | HTMLTextAreaElement) => void;
|
|
52
|
+
/**
|
|
53
|
+
* 隐藏键盘
|
|
54
|
+
*/
|
|
55
|
+
hide: () => void;
|
|
56
|
+
/**
|
|
57
|
+
* 切换显示/隐藏
|
|
58
|
+
*/
|
|
59
|
+
toggle: (input?: HTMLInputElement | HTMLTextAreaElement) => void;
|
|
60
|
+
/**
|
|
61
|
+
* 切换键盘类型
|
|
62
|
+
*/
|
|
63
|
+
switchType: (type: KeyboardType | string) => void;
|
|
64
|
+
/**
|
|
65
|
+
* 切换大小写
|
|
66
|
+
*/
|
|
67
|
+
toggleShift: () => void;
|
|
68
|
+
/**
|
|
69
|
+
* 处理按键
|
|
70
|
+
*/
|
|
71
|
+
handleKey: (key: KeyDefinition) => void;
|
|
72
|
+
/**
|
|
73
|
+
* 获取按键显示文本
|
|
74
|
+
*/
|
|
75
|
+
getKeyLabel: (key: KeyDefinition) => string;
|
|
76
|
+
/**
|
|
77
|
+
* 设置值
|
|
78
|
+
*/
|
|
79
|
+
setValue: (value: string) => void;
|
|
80
|
+
/**
|
|
81
|
+
* 追加值(在光标位置插入文本)
|
|
82
|
+
*/
|
|
83
|
+
appendValue: (text: string) => void;
|
|
84
|
+
/**
|
|
85
|
+
* 设置最大长度
|
|
86
|
+
*/
|
|
87
|
+
setMaxLength: (maxLength?: number) => void;
|
|
88
|
+
/**
|
|
89
|
+
* 绑定输入框
|
|
90
|
+
*/
|
|
91
|
+
bindInput: (input: HTMLInputElement | HTMLTextAreaElement) => void;
|
|
92
|
+
/**
|
|
93
|
+
* 解绑输入框
|
|
94
|
+
*/
|
|
95
|
+
unbindInput: () => void;
|
|
96
|
+
/**
|
|
97
|
+
* 事件监听
|
|
98
|
+
*/
|
|
99
|
+
on: <K extends keyof KeyboardEventMap>(event: K, handler: (data: KeyboardEventMap[K]) => void) => () => void;
|
|
100
|
+
/**
|
|
101
|
+
* 单次事件监听
|
|
102
|
+
*/
|
|
103
|
+
once: <K extends keyof KeyboardEventMap>(event: K, handler: (data: KeyboardEventMap[K]) => void) => () => void;
|
|
104
|
+
/**
|
|
105
|
+
* 销毁
|
|
106
|
+
*/
|
|
107
|
+
destroy: () => void;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* 键盘管理 Composable
|
|
111
|
+
*/
|
|
112
|
+
export declare function useKeyboard(options?: UseKeyboardOptions): UseKeyboardReturn;
|
|
113
|
+
//# sourceMappingURL=useKeyboard.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
let vue = require("vue");
|
|
12
|
+
let _composy_keyboard_core = require("@composy/keyboard-core");
|
|
13
|
+
//#region src/composables/useKeyboardPopup.ts
|
|
14
|
+
function useKeyboardPopup(options = {}) {
|
|
15
|
+
const { visible = (0, vue.ref)(false), target = (0, vue.ref)(null), popup = (0, vue.ref)(null), closeOnClickOutside = true, onClose, ...positionConfig } = options;
|
|
16
|
+
const positionManager = (0, _composy_keyboard_core.createPositionManager)(positionConfig);
|
|
17
|
+
const popupStyles = (0, vue.ref)({});
|
|
18
|
+
const maskStyles = (0, vue.ref)({});
|
|
19
|
+
const placement = (0, vue.ref)("bottom");
|
|
20
|
+
const isMobileDevice = (0, vue.ref)((0, _composy_keyboard_core.isMobile)());
|
|
21
|
+
const showMask = (0, vue.ref)(false);
|
|
22
|
+
const isAnimating = (0, vue.ref)(false);
|
|
23
|
+
let cleanupClickOutside = null;
|
|
24
|
+
let cleanupViewportChange = null;
|
|
25
|
+
let cleanupScroll = null;
|
|
26
|
+
const updatePosition = () => {
|
|
27
|
+
if (!popup.value) return;
|
|
28
|
+
const popupRect = popup.value.getBoundingClientRect();
|
|
29
|
+
const result = positionManager.calculate(target.value, {
|
|
30
|
+
width: popupRect.width || 300,
|
|
31
|
+
height: popupRect.height || 260
|
|
32
|
+
});
|
|
33
|
+
placement.value = result.placement;
|
|
34
|
+
showMask.value = positionManager.shouldShowMask();
|
|
35
|
+
if (result.placement === "bottom-sheet") popupStyles.value = {
|
|
36
|
+
position: "fixed",
|
|
37
|
+
left: "0",
|
|
38
|
+
right: "0",
|
|
39
|
+
bottom: "0",
|
|
40
|
+
maxHeight: `${result.maxHeight}px`,
|
|
41
|
+
zIndex: 1e3
|
|
42
|
+
};
|
|
43
|
+
else popupStyles.value = {
|
|
44
|
+
position: "fixed",
|
|
45
|
+
left: `${result.position.x}px`,
|
|
46
|
+
top: `${result.position.y}px`,
|
|
47
|
+
maxHeight: result.maxHeight ? `${result.maxHeight}px` : void 0,
|
|
48
|
+
maxWidth: result.maxWidth ? `${result.maxWidth}px` : void 0,
|
|
49
|
+
zIndex: 1e3
|
|
50
|
+
};
|
|
51
|
+
if (showMask.value) maskStyles.value = {
|
|
52
|
+
position: "fixed",
|
|
53
|
+
top: "0",
|
|
54
|
+
left: "0",
|
|
55
|
+
right: "0",
|
|
56
|
+
bottom: "0",
|
|
57
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
58
|
+
zIndex: 999
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const close = () => {
|
|
62
|
+
onClose?.();
|
|
63
|
+
};
|
|
64
|
+
(0, vue.watch)(visible, (newVisible) => {
|
|
65
|
+
if (newVisible) {
|
|
66
|
+
isMobileDevice.value = (0, _composy_keyboard_core.isMobile)();
|
|
67
|
+
requestAnimationFrame(() => {
|
|
68
|
+
updatePosition();
|
|
69
|
+
if (closeOnClickOutside && popup.value) cleanupClickOutside = (0, _composy_keyboard_core.onClickOutside)(popup.value, (event) => {
|
|
70
|
+
if (target.value && target.value.contains(event.target)) return;
|
|
71
|
+
close();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
cleanupViewportChange = (0, _composy_keyboard_core.onViewportChange)(() => {
|
|
75
|
+
isMobileDevice.value = (0, _composy_keyboard_core.isMobile)();
|
|
76
|
+
updatePosition();
|
|
77
|
+
});
|
|
78
|
+
if (!isMobileDevice.value) {
|
|
79
|
+
const handleScroll = () => {
|
|
80
|
+
requestAnimationFrame(() => {
|
|
81
|
+
updatePosition();
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
85
|
+
cleanupScroll = () => {
|
|
86
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
cleanupClickOutside?.();
|
|
91
|
+
cleanupClickOutside = null;
|
|
92
|
+
cleanupViewportChange?.();
|
|
93
|
+
cleanupViewportChange = null;
|
|
94
|
+
cleanupScroll?.();
|
|
95
|
+
cleanupScroll = null;
|
|
96
|
+
}
|
|
97
|
+
}, { immediate: true });
|
|
98
|
+
(0, vue.watch)(target, () => {
|
|
99
|
+
if (visible.value) updatePosition();
|
|
100
|
+
});
|
|
101
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
102
|
+
cleanupClickOutside?.();
|
|
103
|
+
cleanupViewportChange?.();
|
|
104
|
+
cleanupScroll?.();
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
popupStyles,
|
|
108
|
+
maskStyles,
|
|
109
|
+
placement,
|
|
110
|
+
isMobileDevice,
|
|
111
|
+
showMask,
|
|
112
|
+
isAnimating,
|
|
113
|
+
updatePosition,
|
|
114
|
+
close
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
exports.useKeyboardPopup = useKeyboardPopup;
|
|
119
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|
|
120
|
+
//# sourceMappingURL=useKeyboardPopup.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyboardPopup.cjs","names":[],"sources":["../../src/composables/useKeyboardPopup.ts"],"sourcesContent":["/**\n * 键盘弹出层 Composable\n * @module composables/useKeyboardPopup\n */\n\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport type { CSSProperties, Ref } from 'vue'\nimport {\n createPositionManager,\n isMobile,\n onClickOutside,\n onViewportChange,\n type PopupPlacement,\n type PopupPositionConfig,\n type PopupPositionResult,\n} from '@composy/keyboard-core'\n\n/**\n * useKeyboardPopup 选项\n */\nexport interface UseKeyboardPopupOptions extends PopupPositionConfig {\n /**\n * 是否显示\n */\n visible?: Ref<boolean>\n\n /**\n * 目标元素\n */\n target?: Ref<HTMLElement | null>\n\n /**\n * 弹出层元素\n */\n popup?: Ref<HTMLElement | null>\n\n /**\n * 点击外部关闭\n */\n closeOnClickOutside?: boolean\n\n /**\n * 关闭回调\n */\n onClose?: () => void\n}\n\n/**\n * useKeyboardPopup 返回值\n */\nexport interface UseKeyboardPopupReturn {\n /**\n * 弹出层样式\n */\n popupStyles: Ref<CSSProperties>\n\n /**\n * 遮罩层样式\n */\n maskStyles: Ref<CSSProperties>\n\n /**\n * 当前弹出位置\n */\n placement: Ref<PopupPlacement>\n\n /**\n * 是否移动端\n */\n isMobileDevice: Ref<boolean>\n\n /**\n * 是否显示遮罩\n */\n showMask: Ref<boolean>\n\n /**\n * 是否正在动画中\n */\n isAnimating: Ref<boolean>\n\n /**\n * 更新位置\n */\n updatePosition: () => void\n\n /**\n * 关闭弹出层\n */\n close: () => void\n}\n\n/**\n * 键盘弹出层 Composable\n */\nexport function useKeyboardPopup(options: UseKeyboardPopupOptions = {}): UseKeyboardPopupReturn {\n const {\n visible = ref(false),\n target = ref(null),\n popup = ref(null),\n closeOnClickOutside = true,\n onClose,\n ...positionConfig\n } = options\n\n // 创建位置管理器\n const positionManager = createPositionManager(positionConfig)\n\n // 响应式状态\n const popupStyles = ref<CSSProperties>({})\n const maskStyles = ref<CSSProperties>({})\n const placement = ref<PopupPlacement>('bottom')\n const isMobileDevice = ref(isMobile())\n const showMask = ref(false)\n const isAnimating = ref(false)\n\n // 清理函数\n let cleanupClickOutside: (() => void) | null = null\n let cleanupViewportChange: (() => void) | null = null\n let cleanupScroll: (() => void) | null = null\n\n /**\n * 更新弹出层位置\n */\n const updatePosition = () => {\n if (!popup.value) return\n\n const popupRect = popup.value.getBoundingClientRect()\n const result = positionManager.calculate(target.value, {\n width: popupRect.width || 300,\n height: popupRect.height || 260,\n })\n\n placement.value = result.placement\n showMask.value = positionManager.shouldShowMask()\n\n // 设置弹出层样式\n if (result.placement === 'bottom-sheet') {\n // 移动端底部弹出\n popupStyles.value = {\n position: 'fixed',\n left: '0',\n right: '0',\n bottom: '0',\n maxHeight: `${result.maxHeight}px`,\n zIndex: 1000,\n }\n }\n else {\n // PC 端下拉弹出\n popupStyles.value = {\n position: 'fixed',\n left: `${result.position.x}px`,\n top: `${result.position.y}px`,\n maxHeight: result.maxHeight ? `${result.maxHeight}px` : undefined,\n maxWidth: result.maxWidth ? `${result.maxWidth}px` : undefined,\n zIndex: 1000,\n }\n }\n\n // 设置遮罩层样式\n if (showMask.value) {\n maskStyles.value = {\n position: 'fixed',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n zIndex: 999,\n }\n }\n }\n\n /**\n * 关闭弹出层\n */\n const close = () => {\n onClose?.()\n }\n\n // 监听 visible 变化\n watch(visible, (newVisible) => {\n if (newVisible) {\n // 显示时\n isMobileDevice.value = isMobile()\n\n // 延迟计算位置(等待 DOM 渲染)\n requestAnimationFrame(() => {\n updatePosition()\n\n // 添加点击外部关闭监听\n if (closeOnClickOutside && popup.value) {\n cleanupClickOutside = onClickOutside(popup.value, (event) => {\n // 检查是否点击在目标元素上\n if (target.value && target.value.contains(event.target as Node)) {\n return\n }\n close()\n })\n }\n })\n\n // 监听视口变化\n cleanupViewportChange = onViewportChange(() => {\n isMobileDevice.value = isMobile()\n updatePosition()\n })\n\n // PC 端监听滚动事件,跟随滚动\n if (!isMobileDevice.value) {\n const handleScroll = () => {\n requestAnimationFrame(() => {\n updatePosition()\n })\n }\n window.addEventListener('scroll', handleScroll, true)\n cleanupScroll = () => {\n window.removeEventListener('scroll', handleScroll, true)\n }\n }\n }\n else {\n // 隐藏时清理\n cleanupClickOutside?.()\n cleanupClickOutside = null\n cleanupViewportChange?.()\n cleanupViewportChange = null\n cleanupScroll?.()\n cleanupScroll = null\n }\n }, { immediate: true })\n\n // 监听目标元素变化\n watch(target, () => {\n if (visible.value) {\n updatePosition()\n }\n })\n\n // 组件卸载时清理\n onBeforeUnmount(() => {\n cleanupClickOutside?.()\n cleanupViewportChange?.()\n cleanupScroll?.()\n })\n\n return {\n popupStyles,\n maskStyles,\n placement,\n isMobileDevice,\n showMask,\n isAnimating,\n updatePosition,\n close,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 键盘弹出层 Composable
|
|
3
|
+
* @module composables/useKeyboardPopup
|
|
4
|
+
*/
|
|
5
|
+
import type { CSSProperties, Ref } from 'vue';
|
|
6
|
+
import { type PopupPlacement, type PopupPositionConfig } from '@composy/keyboard-core';
|
|
7
|
+
/**
|
|
8
|
+
* useKeyboardPopup 选项
|
|
9
|
+
*/
|
|
10
|
+
export interface UseKeyboardPopupOptions extends PopupPositionConfig {
|
|
11
|
+
/**
|
|
12
|
+
* 是否显示
|
|
13
|
+
*/
|
|
14
|
+
visible?: Ref<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* 目标元素
|
|
17
|
+
*/
|
|
18
|
+
target?: Ref<HTMLElement | null>;
|
|
19
|
+
/**
|
|
20
|
+
* 弹出层元素
|
|
21
|
+
*/
|
|
22
|
+
popup?: Ref<HTMLElement | null>;
|
|
23
|
+
/**
|
|
24
|
+
* 点击外部关闭
|
|
25
|
+
*/
|
|
26
|
+
closeOnClickOutside?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 关闭回调
|
|
29
|
+
*/
|
|
30
|
+
onClose?: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* useKeyboardPopup 返回值
|
|
34
|
+
*/
|
|
35
|
+
export interface UseKeyboardPopupReturn {
|
|
36
|
+
/**
|
|
37
|
+
* 弹出层样式
|
|
38
|
+
*/
|
|
39
|
+
popupStyles: Ref<CSSProperties>;
|
|
40
|
+
/**
|
|
41
|
+
* 遮罩层样式
|
|
42
|
+
*/
|
|
43
|
+
maskStyles: Ref<CSSProperties>;
|
|
44
|
+
/**
|
|
45
|
+
* 当前弹出位置
|
|
46
|
+
*/
|
|
47
|
+
placement: Ref<PopupPlacement>;
|
|
48
|
+
/**
|
|
49
|
+
* 是否移动端
|
|
50
|
+
*/
|
|
51
|
+
isMobileDevice: Ref<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* 是否显示遮罩
|
|
54
|
+
*/
|
|
55
|
+
showMask: Ref<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* 是否正在动画中
|
|
58
|
+
*/
|
|
59
|
+
isAnimating: Ref<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* 更新位置
|
|
62
|
+
*/
|
|
63
|
+
updatePosition: () => void;
|
|
64
|
+
/**
|
|
65
|
+
* 关闭弹出层
|
|
66
|
+
*/
|
|
67
|
+
close: () => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 键盘弹出层 Composable
|
|
71
|
+
*/
|
|
72
|
+
export declare function useKeyboardPopup(options?: UseKeyboardPopupOptions): UseKeyboardPopupReturn;
|
|
73
|
+
//# sourceMappingURL=useKeyboardPopup.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ***********************************
|
|
3
|
+
* @composy/keyboard-vue v0.0.1 *
|
|
4
|
+
* Built with rollup *
|
|
5
|
+
* Build time: 2024-08-17 11:42:14 *
|
|
6
|
+
* Build mode: production *
|
|
7
|
+
* Minified: No *
|
|
8
|
+
* ***********************************
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
const require_v_keyboard = require("./v-keyboard.cjs");
|
|
12
|
+
exports.vKeyboard = require_v_keyboard.vKeyboard;
|
|
13
|
+
/*! End of @composy/keyboard-vue | Powered by @composy/builder */
|