@wapri/ghooks 1.0.0 → 1.1.0

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 wapri contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wapri contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @wapri/ghooks
2
+
3
+ Vue 3 Hooks 工具库,内置导出 `vue-hooks-plus` 的全量 hooks,并额外提供 `useVh100`、`useLandscape`、`useLottie`。
4
+
5
+ ## 在线文档
6
+
7
+ https://sdmu-gaoqi.github.io/wapri/hooks
@@ -1,36 +1,36 @@
1
- /**
2
- * lottie-api 未提供类型声明,这里按仓库实际用到的 API 补充。
3
- * 上游实现参考:https://github.com/bodymovin/lottie-api
4
- */
5
- declare module 'lottie-api' {
6
- import type { AnimationItem } from 'lottie-web'
7
-
8
- /** keyPath 命中的单个图层元素,canvas 与 svg 渲染器暴露的字段不同 */
9
- export interface LottieApiElement {
10
- element: {
11
- /** canvas 渲染器下的 Image 元素 */
12
- img?: { src: string }
13
- /** svg 渲染器下的 <image> 元素 */
14
- innerElem?: Element
15
- }
16
- }
17
-
18
- /** 一个 keyPath 命中的图层集合 */
19
- export interface LottieApiKeyPath {
20
- getElements: () => LottieApiElement[]
21
- }
22
-
23
- /** createAnimationApi 返回的操作句柄 */
24
- export interface LottieApi {
25
- /** 按图层名/keyPath 取元素 */
26
- getKeyPath: (keyPath: string) => LottieApiKeyPath
27
- /** 当前渲染器类型 */
28
- getRendererType: () => string
29
- }
30
-
31
- const lottieApi: {
32
- createAnimationApi: (animation: AnimationItem) => LottieApi
33
- }
34
-
35
- export default lottieApi
36
- }
1
+ /**
2
+ * lottie-api 未提供类型声明,这里按仓库实际用到的 API 补充。
3
+ * 上游实现参考:https://github.com/bodymovin/lottie-api
4
+ */
5
+ declare module 'lottie-api' {
6
+ import type { AnimationItem } from 'lottie-web'
7
+
8
+ /** keyPath 命中的单个图层元素,canvas 与 svg 渲染器暴露的字段不同 */
9
+ export interface LottieApiElement {
10
+ element: {
11
+ /** canvas 渲染器下的 Image 元素 */
12
+ img?: { src: string }
13
+ /** svg 渲染器下的 <image> 元素 */
14
+ innerElem?: Element
15
+ }
16
+ }
17
+
18
+ /** 一个 keyPath 命中的图层集合 */
19
+ export interface LottieApiKeyPath {
20
+ getElements: () => LottieApiElement[]
21
+ }
22
+
23
+ /** createAnimationApi 返回的操作句柄 */
24
+ export interface LottieApi {
25
+ /** 按图层名/keyPath 取元素 */
26
+ getKeyPath: (keyPath: string) => LottieApiKeyPath
27
+ /** 当前渲染器类型 */
28
+ getRendererType: () => string
29
+ }
30
+
31
+ const lottieApi: {
32
+ createAnimationApi: (animation: AnimationItem) => LottieApi
33
+ }
34
+
35
+ export default lottieApi
36
+ }
@@ -1,29 +1,29 @@
1
- <template>
2
- <div>
3
- <p>
4
- 当前屏幕方向:
5
- <strong>{{ isLandscape ? '横屏' : '竖屏' }}</strong>
6
- </p>
7
- <p>当前视口尺寸:{{ width }} × {{ height }}</p>
8
- <p style="color: #999">调整窗口宽度(宽>高即为横屏)可实时观察状态变化</p>
9
- </div>
10
- </template>
11
-
12
- <script setup lang="ts">
13
- import { ref, onUnmounted } from 'vue'
14
- import { useLandscape } from '@wapri/ghooks'
15
-
16
- const isLandscape = useLandscape()
17
- const width = ref(window.innerWidth)
18
- const height = ref(window.innerHeight)
19
-
20
- const updateSize = () => {
21
- width.value = window.innerWidth
22
- height.value = window.innerHeight
23
- }
24
-
25
- window.addEventListener('resize', updateSize)
26
- onUnmounted(() => {
27
- window.removeEventListener('resize', updateSize)
28
- })
29
- </script>
1
+ <template>
2
+ <div>
3
+ <p>
4
+ 当前屏幕方向:
5
+ <strong>{{ isLandscape ? '横屏' : '竖屏' }}</strong>
6
+ </p>
7
+ <p>当前视口尺寸:{{ width }} × {{ height }}</p>
8
+ <p style="color: #999">调整窗口宽度(宽>高即为横屏)可实时观察状态变化</p>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { ref, onUnmounted } from 'vue'
14
+ import { useLandscape } from '@wapri/ghooks'
15
+
16
+ const isLandscape = useLandscape()
17
+ const width = ref(window.innerWidth)
18
+ const height = ref(window.innerHeight)
19
+
20
+ const updateSize = () => {
21
+ width.value = window.innerWidth
22
+ height.value = window.innerHeight
23
+ }
24
+
25
+ window.addEventListener('resize', updateSize)
26
+ onUnmounted(() => {
27
+ window.removeEventListener('resize', updateSize)
28
+ })
29
+ </script>
@@ -1,29 +1,29 @@
1
- <template>
2
- <div>
3
- <p>
4
- 当前屏幕方向:
5
- <strong>{{ isLandscape ? '横屏' : '竖屏' }}</strong>
6
- </p>
7
- <p style="color: #999">将窗口拉宽至横屏(宽>高),页面立即被遮罩覆盖并提示旋转屏幕;恢复竖屏后遮罩自动消失</p>
8
- <div class="content-box">业务内容区域(仅在竖屏时可见)</div>
9
- </div>
10
- </template>
11
-
12
- <script setup lang="ts">
13
- import { useLandscape } from '@wapri/ghooks'
14
- import { os } from '@wapri/gbase'
15
-
16
- const isLandscape = useLandscape({
17
- lock: !os.isIpad() && !os.isPC(),
18
- tip: '请旋转您的屏幕,切换至竖屏模式',
19
- })
20
- </script>
21
-
22
- <style scoped>
23
- .content-box {
24
- padding: 24px;
25
- border: 1px dashed #ccc;
26
- border-radius: 4px;
27
- color: #666;
28
- }
29
- </style>
1
+ <template>
2
+ <div>
3
+ <p>
4
+ 当前屏幕方向:
5
+ <strong>{{ isLandscape ? '横屏' : '竖屏' }}</strong>
6
+ </p>
7
+ <p style="color: #999">将窗口拉宽至横屏(宽>高),页面立即被遮罩覆盖并提示旋转屏幕;恢复竖屏后遮罩自动消失</p>
8
+ <div class="content-box">业务内容区域(仅在竖屏时可见)</div>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { useLandscape } from '@wapri/ghooks'
14
+ import { os } from '@wapri/gbase'
15
+
16
+ const isLandscape = useLandscape({
17
+ lock: !os.isIpad() && !os.isPC(),
18
+ tip: '请旋转您的屏幕,切换至竖屏模式',
19
+ })
20
+ </script>
21
+
22
+ <style scoped>
23
+ .content-box {
24
+ padding: 24px;
25
+ border: 1px dashed #ccc;
26
+ border-radius: 4px;
27
+ color: #666;
28
+ }
29
+ </style>
@@ -1,150 +1,150 @@
1
- <script setup lang="ts">
2
- import { ref } from 'vue'
3
- import { useLottie } from '@wapri/ghooks'
4
- import animationData from './包邮.json'
5
-
6
- const container = ref<HTMLElement>()
7
- const status = ref('等待加载')
8
-
9
- const { instance, play, pause, stop, playSegments, playAnimation, setLoop, getDuration } = useLottie(
10
- container,
11
- animationData,
12
- {
13
- loop: true,
14
- onReady: (item) => {
15
- status.value = `加载完成,共 ${item.totalFrames} 帧`
16
- },
17
- },
18
- )
19
-
20
- /** 一次播放两段区间 */
21
- const handleSegmentPlay = () => {
22
- setLoop(true)
23
- status.value = '区间播放:[0,24] + [24,72]'
24
- playSegments([
25
- [0, 24],
26
- [24, 72],
27
- ])
28
- }
29
-
30
- /** 关闭循环后按顺序异步播放两段,每段结束才进入下一段 */
31
- const handleAsyncPlay = async () => {
32
- setLoop(false)
33
- status.value = '第一段开始'
34
- await playAnimation([[0, 24]], true)
35
- status.value = '第一段结束'
36
- await new Promise((resolve) => setTimeout(resolve, 600))
37
- status.value = '第二段开始'
38
- await playAnimation([24, 72])
39
- status.value = '第二段结束'
40
- }
41
- </script>
42
-
43
- <template>
44
- <div class="lottie-demo">
45
- <div
46
- ref="container"
47
- class="lottie-demo__stage"
48
- />
49
-
50
- <div class="lottie-demo__panel">
51
- <div class="lottie-demo__actions">
52
- <button
53
- type="button"
54
- @click="play"
55
- >
56
- 播放
57
- </button>
58
- <button
59
- type="button"
60
- @click="pause"
61
- >
62
- 暂停
63
- </button>
64
- <button
65
- type="button"
66
- @click="stop"
67
- >
68
- 停止
69
- </button>
70
- <button
71
- type="button"
72
- @click="handleSegmentPlay"
73
- >
74
- 帧播放
75
- </button>
76
- <button
77
- type="button"
78
- @click="handleAsyncPlay"
79
- >
80
- 异步多段动画
81
- </button>
82
- </div>
83
-
84
- <p class="lottie-demo__status">{{ status }}</p>
85
- <p class="lottie-demo__status">
86
- {{ instance ? `实例已就绪,总时长 ${getDuration(false).toFixed(2)}s` : '实例加载中…' }}
87
- </p>
88
- </div>
89
- </div>
90
- </template>
91
-
92
- <style scoped>
93
- .lottie-demo {
94
- display: flex;
95
- max-width: 760px;
96
- flex-wrap: wrap;
97
- align-items: center;
98
- gap: 20px;
99
- padding: 20px;
100
- border: 1px solid #e5e7eb;
101
- border-radius: 8px;
102
- color: #1f2937;
103
- }
104
-
105
- .lottie-demo__stage {
106
- width: 240px;
107
- height: 240px;
108
- flex: 0 0 auto;
109
- border-radius: 8px;
110
- background: #f8fafc;
111
- }
112
-
113
- .lottie-demo__panel {
114
- flex: 1;
115
- min-width: 260px;
116
- }
117
-
118
- .lottie-demo__actions {
119
- display: flex;
120
- flex-wrap: wrap;
121
- gap: 8px;
122
- }
123
-
124
- .lottie-demo__actions button {
125
- height: 32px;
126
- padding: 0 14px;
127
- border: 1px solid #d1d5db;
128
- border-radius: 4px;
129
- background: #fff;
130
- color: inherit;
131
- font: inherit;
132
- font-size: 14px;
133
- cursor: pointer;
134
- transition:
135
- border-color 0.2s,
136
- color 0.2s;
137
- }
138
-
139
- .lottie-demo__actions button:hover {
140
- border-color: #f97316;
141
- color: #ea580c;
142
- }
143
-
144
- .lottie-demo__status {
145
- margin: 14px 0 0;
146
- color: #6b7280;
147
- font-size: 13px;
148
- line-height: 1.8;
149
- }
150
- </style>
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { useLottie } from '@wapri/ghooks'
4
+ import animationData from './包邮.json'
5
+
6
+ const container = ref<HTMLElement>()
7
+ const status = ref('等待加载')
8
+
9
+ const { instance, play, pause, stop, playSegments, playAnimation, setLoop, getDuration } = useLottie(
10
+ container,
11
+ animationData,
12
+ {
13
+ loop: true,
14
+ onReady: (item) => {
15
+ status.value = `加载完成,共 ${item.totalFrames} 帧`
16
+ },
17
+ },
18
+ )
19
+
20
+ /** 一次播放两段区间 */
21
+ const handleSegmentPlay = () => {
22
+ setLoop(true)
23
+ status.value = '区间播放:[0,24] + [24,72]'
24
+ playSegments([
25
+ [0, 24],
26
+ [24, 72],
27
+ ])
28
+ }
29
+
30
+ /** 关闭循环后按顺序异步播放两段,每段结束才进入下一段 */
31
+ const handleAsyncPlay = async () => {
32
+ setLoop(false)
33
+ status.value = '第一段开始'
34
+ await playAnimation([[0, 24]], true)
35
+ status.value = '第一段结束'
36
+ await new Promise((resolve) => setTimeout(resolve, 600))
37
+ status.value = '第二段开始'
38
+ await playAnimation([24, 72])
39
+ status.value = '第二段结束'
40
+ }
41
+ </script>
42
+
43
+ <template>
44
+ <div class="lottie-demo">
45
+ <div
46
+ ref="container"
47
+ class="lottie-demo__stage"
48
+ />
49
+
50
+ <div class="lottie-demo__panel">
51
+ <div class="lottie-demo__actions">
52
+ <button
53
+ type="button"
54
+ @click="play"
55
+ >
56
+ 播放
57
+ </button>
58
+ <button
59
+ type="button"
60
+ @click="pause"
61
+ >
62
+ 暂停
63
+ </button>
64
+ <button
65
+ type="button"
66
+ @click="stop"
67
+ >
68
+ 停止
69
+ </button>
70
+ <button
71
+ type="button"
72
+ @click="handleSegmentPlay"
73
+ >
74
+ 帧播放
75
+ </button>
76
+ <button
77
+ type="button"
78
+ @click="handleAsyncPlay"
79
+ >
80
+ 异步多段动画
81
+ </button>
82
+ </div>
83
+
84
+ <p class="lottie-demo__status">{{ status }}</p>
85
+ <p class="lottie-demo__status">
86
+ {{ instance ? `实例已就绪,总时长 ${getDuration(false).toFixed(2)}s` : '实例加载中…' }}
87
+ </p>
88
+ </div>
89
+ </div>
90
+ </template>
91
+
92
+ <style scoped>
93
+ .lottie-demo {
94
+ display: flex;
95
+ max-width: 760px;
96
+ flex-wrap: wrap;
97
+ align-items: center;
98
+ gap: 20px;
99
+ padding: 20px;
100
+ border: 1px solid #e5e7eb;
101
+ border-radius: 8px;
102
+ color: #1f2937;
103
+ }
104
+
105
+ .lottie-demo__stage {
106
+ width: 240px;
107
+ height: 240px;
108
+ flex: 0 0 auto;
109
+ border-radius: 8px;
110
+ background: #f8fafc;
111
+ }
112
+
113
+ .lottie-demo__panel {
114
+ flex: 1;
115
+ min-width: 260px;
116
+ }
117
+
118
+ .lottie-demo__actions {
119
+ display: flex;
120
+ flex-wrap: wrap;
121
+ gap: 8px;
122
+ }
123
+
124
+ .lottie-demo__actions button {
125
+ height: 32px;
126
+ padding: 0 14px;
127
+ border: 1px solid #d1d5db;
128
+ border-radius: 4px;
129
+ background: #fff;
130
+ color: inherit;
131
+ font: inherit;
132
+ font-size: 14px;
133
+ cursor: pointer;
134
+ transition:
135
+ border-color 0.2s,
136
+ color 0.2s;
137
+ }
138
+
139
+ .lottie-demo__actions button:hover {
140
+ border-color: #f97316;
141
+ color: #ea580c;
142
+ }
143
+
144
+ .lottie-demo__status {
145
+ margin: 14px 0 0;
146
+ color: #6b7280;
147
+ font-size: 13px;
148
+ line-height: 1.8;
149
+ }
150
+ </style>