hw-cus-ui 1.0.22 → 1.0.24
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/DraggableBottomPopup/DraggableBottomPopup.vue +195 -0
- package/DraggableBottomPopup/index.ts +10 -0
- package/HwBtn/HwBtn.vue +16 -0
- package/HwBtn/index.ts +10 -0
- package/index.d.ts +11 -0
- package/index.ts +21 -0
- package/package.json +14 -45
- package/README.md +0 -70
- package/dist/hw-cus-ui.css +0 -2
- package/dist/hw-cus-ui.es.cjs +0 -17
- package/dist/hw-cus-ui.umd.cjs +0 -1
- package/dist/types/components/HwBtn/HwBtn.vue.d.ts +0 -3
- package/dist/types/components/HwBtn/index.d.ts +0 -2
- package/dist/types/components/index.d.ts +0 -7
- package/dist/types/index.d.ts +0 -3
- package/dist/vite.svg +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="draggable-popup-mask">
|
|
3
|
+
<view
|
|
4
|
+
class="draggable-popup-container"
|
|
5
|
+
:style="{
|
|
6
|
+
top: popupTop + 'px',
|
|
7
|
+
position: isDrag ? 'fixed' : 'initial',
|
|
8
|
+
borderTopLeftRadius: isDrag ? '20rpx' : '0',
|
|
9
|
+
borderTopRightRadius: isDrag ? '20rpx' : '0'
|
|
10
|
+
}"
|
|
11
|
+
>
|
|
12
|
+
<view
|
|
13
|
+
v-if="isDrag"
|
|
14
|
+
class="draggable-popup-handle"
|
|
15
|
+
@touchstart="handleTouchStart"
|
|
16
|
+
@touchmove="handleTouchMove"
|
|
17
|
+
@touchend="handleTouchEnd"
|
|
18
|
+
@touchcancel="handleTouchEnd"
|
|
19
|
+
>
|
|
20
|
+
<view class="draggable-popup-handle-line"></view>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="draggable-popup-content" :style="{ height: isDrag ? contentPopupTop + 'px' : 'auto' }">
|
|
23
|
+
<slot></slot>
|
|
24
|
+
</view>
|
|
25
|
+
</view>
|
|
26
|
+
</view>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script>
|
|
30
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
31
|
+
export default {
|
|
32
|
+
name: 'DraggableBottomPopup',
|
|
33
|
+
props: {
|
|
34
|
+
heightCalc: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: '0.4'
|
|
37
|
+
},
|
|
38
|
+
isDrag: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: () => true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
startY: 0,
|
|
46
|
+
startTop: 0,
|
|
47
|
+
popupTop: 0,
|
|
48
|
+
windowHeight: 0,
|
|
49
|
+
contentPopupTop: 0,
|
|
50
|
+
isMoving: false,
|
|
51
|
+
containerHeight: 0, // 容器高度
|
|
52
|
+
updateContentPopupTop: null // 防抖函数
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
mounted() {
|
|
57
|
+
this.getWindowInfo();
|
|
58
|
+
this.initPopupPosition();
|
|
59
|
+
// 初始化防抖函数
|
|
60
|
+
this.updateContentPopupTop = useDebounceFn(() => {
|
|
61
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
62
|
+
}, 300);
|
|
63
|
+
},
|
|
64
|
+
methods: {
|
|
65
|
+
getWindowInfo() {
|
|
66
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
67
|
+
this.windowHeight = systemInfo.windowHeight;
|
|
68
|
+
// 初始位置在屏幕外,隐藏状态
|
|
69
|
+
this.popupTop = this.windowHeight;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
initPopupPosition() {
|
|
73
|
+
this.$nextTick(() => {
|
|
74
|
+
// 获取内容高度
|
|
75
|
+
const query = uni.createSelectorQuery().in(this);
|
|
76
|
+
query
|
|
77
|
+
.select('.draggable-popup-container')
|
|
78
|
+
.boundingClientRect((data) => {
|
|
79
|
+
if (data) {
|
|
80
|
+
this.containerHeight = data.height;
|
|
81
|
+
// 默认显示屏幕高度的60%
|
|
82
|
+
this.popupTop = this.windowHeight * this.heightCalc;
|
|
83
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
84
|
+
this.changeTop();
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
.exec();
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
handleTouchStart(e) {
|
|
92
|
+
this.isMoving = true;
|
|
93
|
+
this.startY = e.touches[0].clientY;
|
|
94
|
+
this.startTop = this.popupTop;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
handleTouchMove(e) {
|
|
98
|
+
if (!this.isMoving) return;
|
|
99
|
+
|
|
100
|
+
const moveY = e.touches[0].clientY - this.startY;
|
|
101
|
+
let newTop = this.startTop + moveY;
|
|
102
|
+
|
|
103
|
+
// 限制拖动范围,但允许拖出屏幕一定距离
|
|
104
|
+
const maxDragDistance = 100; // 最大可拖出屏幕的距离
|
|
105
|
+
|
|
106
|
+
if (newTop < -maxDragDistance) {
|
|
107
|
+
newTop = -maxDragDistance;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 保留一部分在屏幕内,方便拖回
|
|
111
|
+
if (this.containerHeight > 0) {
|
|
112
|
+
const maxTop = this.windowHeight - 50; // 至少保留50px在屏幕内
|
|
113
|
+
if (newTop > maxTop) {
|
|
114
|
+
newTop = maxTop;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.popupTop = newTop;
|
|
118
|
+
this.changeTop();
|
|
119
|
+
// 调用防抖函数而不是创建它
|
|
120
|
+
this.updateContentPopupTop();
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
handleTouchEnd(e) {
|
|
124
|
+
if (!this.isMoving) return;
|
|
125
|
+
this.isMoving = false;
|
|
126
|
+
|
|
127
|
+
// 修改:拖动结束后停留在当前位置,不自动展开或收起
|
|
128
|
+
// 只要确保popupTop在有效范围内即可
|
|
129
|
+
|
|
130
|
+
if (this.popupTop < 0) {
|
|
131
|
+
this.popupTop = 110;
|
|
132
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
133
|
+
} else if (this.popupTop > this.windowHeight) {
|
|
134
|
+
this.popupTop = this.windowHeight - 60;
|
|
135
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
136
|
+
} else if (this.popupTop < 110) {
|
|
137
|
+
this.popupTop = 110;
|
|
138
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
139
|
+
}
|
|
140
|
+
this.changeTop();
|
|
141
|
+
},
|
|
142
|
+
changeTop() {
|
|
143
|
+
this.$emit('changeTop', this.popupTop);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
</script>
|
|
148
|
+
|
|
149
|
+
<style lang="scss" scoped>
|
|
150
|
+
/* .draggable-popup-mask {
|
|
151
|
+
position: fixed;
|
|
152
|
+
top: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
right: 0;
|
|
155
|
+
bottom: 0;
|
|
156
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
157
|
+
z-index: 98;
|
|
158
|
+
} */
|
|
159
|
+
|
|
160
|
+
.draggable-popup-container {
|
|
161
|
+
position: fixed;
|
|
162
|
+
left: 0;
|
|
163
|
+
right: 0;
|
|
164
|
+
bottom: 0;
|
|
165
|
+
background-color: #ffffff;
|
|
166
|
+
border-top-left-radius: 20rpx;
|
|
167
|
+
border-top-right-radius: 20rpx;
|
|
168
|
+
transition: top 0.1s ease; /* 减少过渡时间使拖动更流畅 */
|
|
169
|
+
z-index: 99;
|
|
170
|
+
display: flex;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
overflow: auto;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.draggable-popup-handle {
|
|
176
|
+
display: flex;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
align-items: center;
|
|
179
|
+
padding: 20rpx 0;
|
|
180
|
+
cursor: move;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.draggable-popup-handle-line {
|
|
184
|
+
width: 60rpx;
|
|
185
|
+
height: 8rpx;
|
|
186
|
+
border-radius: 4rpx;
|
|
187
|
+
background-color: rgba(23, 26, 29, 0.24);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.draggable-popup-content {
|
|
191
|
+
overflow: auto;
|
|
192
|
+
position: relative;
|
|
193
|
+
z-index: 100;
|
|
194
|
+
}
|
|
195
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import DraggableBottomPopup from './DraggableBottomPopup.vue';
|
|
4
|
+
|
|
5
|
+
// 使用install方法,在app.use挂载
|
|
6
|
+
DraggableBottomPopup.install = (app: App) => {
|
|
7
|
+
app.component(DraggableBottomPopup.__name as string, DraggableBottomPopup); //注册组件
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default DraggableBottomPopup;
|
package/HwBtn/HwBtn.vue
ADDED
package/HwBtn/index.ts
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import { HwBtn } from './HwBtn';
|
|
3
|
+
import { DraggableBottomPopup } from './DraggableBottomPopup';
|
|
4
|
+
|
|
5
|
+
export { HwBtn, DraggableBottomPopup };
|
|
6
|
+
|
|
7
|
+
export declare const hwCusUi: {
|
|
8
|
+
install: (app: App) => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default hwCusUi;
|
package/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import HwBtn from './HwBtn';
|
|
4
|
+
import DraggableBottomPopup from './DraggableBottomPopup';
|
|
5
|
+
|
|
6
|
+
// 所有组件列表
|
|
7
|
+
const components = [HwBtn, DraggableBottomPopup];
|
|
8
|
+
|
|
9
|
+
// 定义 install 方法
|
|
10
|
+
const install = (app: App): void => {
|
|
11
|
+
// 遍历注册所有组件
|
|
12
|
+
components.forEach((component) => app.component(component.__name as string, component));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { HwBtn, DraggableBottomPopup };
|
|
16
|
+
|
|
17
|
+
const hwCusUi = {
|
|
18
|
+
install
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default hwCusUi;
|
package/package.json
CHANGED
|
@@ -1,45 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "hw-cus-ui",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"
|
|
5
|
-
"main": "
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"files": [
|
|
16
|
-
"dist"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"dev": "vite",
|
|
20
|
-
"build": "vue-tsc -b && vite build && vue-tsc -p tsconfig.types.json",
|
|
21
|
-
"preview": "vite preview",
|
|
22
|
-
"lib": "vue-tsc -b && vite build --mode lib"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"vue": "^3.5.24"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@types/node": "^24.10.1",
|
|
29
|
-
"@vitejs/plugin-vue": "^6.0.1",
|
|
30
|
-
"@vue/tsconfig": "^0.8.1",
|
|
31
|
-
"typescript": "~5.9.3",
|
|
32
|
-
"vite": "npm:rolldown-vite@7.2.5",
|
|
33
|
-
"vue-tsc": "^3.1.4"
|
|
34
|
-
},
|
|
35
|
-
"resolutions": {
|
|
36
|
-
"vite": "npm:rolldown-vite@7.2.5"
|
|
37
|
-
},
|
|
38
|
-
"peerDependencies": {
|
|
39
|
-
"vue": "^3.5.24"
|
|
40
|
-
},
|
|
41
|
-
"description": "一个基于 Vue 3 的组件库,包含常用的UI组件。",
|
|
42
|
-
"keywords": [],
|
|
43
|
-
"author": "",
|
|
44
|
-
"license": "ISC"
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "hw-cus-ui",
|
|
3
|
+
"version": "1.0.24",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"type": "commonjs",
|
|
13
|
+
"types": "./index.d.ts"
|
|
14
|
+
}
|
package/README.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# hw-cus-ui
|
|
2
|
-
|
|
3
|
-
一个基于 Vue 3 的组件库,包含常用的UI组件。
|
|
4
|
-
|
|
5
|
-
## 安装
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @yourname/hw-cus-ui
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## 使用
|
|
12
|
-
|
|
13
|
-
### 全局注册
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import { createApp } from 'vue'
|
|
17
|
-
import App from './App.vue'
|
|
18
|
-
import hwCusUi from '@yourname/hw-cus-ui'
|
|
19
|
-
import '@yourname/hw-cus-ui/dist/hw-cus-ui.css'
|
|
20
|
-
|
|
21
|
-
const app = createApp(App)
|
|
22
|
-
|
|
23
|
-
app.use(hwCusUi)
|
|
24
|
-
app.mount('#app')
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### 按需引入
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { createApp } from 'vue'
|
|
31
|
-
import App from './App.vue'
|
|
32
|
-
import { HwBtn } from 'hw-cus-ui'
|
|
33
|
-
import '@yourname/hw-cus-ui/dist/hw-cus-ui.css'
|
|
34
|
-
|
|
35
|
-
const app = createApp(App)
|
|
36
|
-
|
|
37
|
-
app.component('HwBtn', HwBtn)
|
|
38
|
-
app.mount('#app')
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## 组件列表
|
|
42
|
-
|
|
43
|
-
- HwBtn (按钮组件)
|
|
44
|
-
|
|
45
|
-
## 开发
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
# 安装依赖
|
|
49
|
-
npm install
|
|
50
|
-
|
|
51
|
-
# 启动开发服务器
|
|
52
|
-
npm run dev
|
|
53
|
-
|
|
54
|
-
# 构建组件库
|
|
55
|
-
npm run build
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## 发布到npm
|
|
59
|
-
|
|
60
|
-
在发布前,请注意:
|
|
61
|
-
|
|
62
|
-
1. 将 package.json 中的 `@yourname/hw-cus-ui` 替换为你的实际npm用户名
|
|
63
|
-
2. 登录npm账户: `npm login`
|
|
64
|
-
3. 确保版本号更新
|
|
65
|
-
4. 运行构建命令: `npm run build`
|
|
66
|
-
5. 发布: `npm publish`
|
|
67
|
-
|
|
68
|
-
## License
|
|
69
|
-
|
|
70
|
-
MIT
|
package/dist/hw-cus-ui.css
DELETED
package/dist/hw-cus-ui.es.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { createElementBlock, openBlock } from "vue";
|
|
2
|
-
var __plugin_vue_export_helper_default = (e, s) => {
|
|
3
|
-
let c = e.__vccOpts || e;
|
|
4
|
-
for (let [e, l] of s) c[e] = l;
|
|
5
|
-
return c;
|
|
6
|
-
}, _sfc_main = {}, _hoisted_1 = { class: "btn" };
|
|
7
|
-
function _sfc_render(c, l) {
|
|
8
|
-
return openBlock(), createElementBlock("div", _hoisted_1, "我的按钮");
|
|
9
|
-
}
|
|
10
|
-
var HwBtn_default$1 = /* @__PURE__ */ __plugin_vue_export_helper_default(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-6693a7d0"]]);
|
|
11
|
-
HwBtn_default$1.install = (e) => {
|
|
12
|
-
e.component(HwBtn_default$1.__name, HwBtn_default$1);
|
|
13
|
-
};
|
|
14
|
-
var HwBtn_default = HwBtn_default$1, components = [HwBtn_default], components_default = { install: (e) => {
|
|
15
|
-
components.forEach((s) => e.component(s.__name, s));
|
|
16
|
-
} };
|
|
17
|
-
export { HwBtn_default as HwBtn, components_default as default };
|
package/dist/hw-cus-ui.umd.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`vue`)):typeof define==`function`&&define.amd?define([`exports`,`vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.hwCusUi={},e.Vue))})(this,function(e,t){Object.defineProperty(e,`__esModule`,{value:!0});var n=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},r={},i={class:`btn`};function a(e,n){return(0,t.openBlock)(),(0,t.createElementBlock)(`div`,i,`我的按钮`)}var o=n(r,[[`render`,a],[`__scopeId`,`data-v-6693a7d0`]]);o.install=e=>{e.component(o.__name,o)};var s=o,c=[s];e.HwBtn=s,e.default={install:e=>{c.forEach(t=>e.component(t.__name,t))}}});
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
package/dist/types/index.d.ts
DELETED
package/dist/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|