@gm-pc/tour 1.26.2-beta.0 → 1.27.1-beta.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/README.md +11 -11
- package/package.json +5 -5
- package/src/components/action.tsx +29 -29
- package/src/components/guide.tsx +140 -140
- package/src/components/index.ts +1 -1
- package/src/components/portal.tsx +23 -23
- package/src/components/svg_mask.tsx +168 -168
- package/src/hook.ts +19 -19
- package/src/index.ts +2 -2
- package/src/reducer.ts +55 -55
- package/src/stories.tsx +310 -310
- package/src/tour.tsx +276 -276
- package/src/types.ts +52 -52
- package/src/utils.ts +172 -172
package/src/utils.ts
CHANGED
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
import { ReactText } from 'react'
|
|
2
|
-
import _ from 'lodash'
|
|
3
|
-
|
|
4
|
-
const isNumeric = (n: ReactText): boolean =>
|
|
5
|
-
!isNaN(parseFloat(n as string)) && isFinite(n as number)
|
|
6
|
-
|
|
7
|
-
const setPosition = (
|
|
8
|
-
begin: number,
|
|
9
|
-
end: number,
|
|
10
|
-
elapsed: number,
|
|
11
|
-
duration: number
|
|
12
|
-
): number => {
|
|
13
|
-
const easeInOutCubic = (t: number) =>
|
|
14
|
-
t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
|
|
15
|
-
return elapsed > duration
|
|
16
|
-
? end
|
|
17
|
-
: begin + (end - begin) * easeInOutCubic(elapsed / duration)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const calcEndPoint = (
|
|
21
|
-
target: ReactText | HTMLElement,
|
|
22
|
-
context: HTMLElement | Window = window,
|
|
23
|
-
offset = 0
|
|
24
|
-
): number => {
|
|
25
|
-
if (isNumeric(target as ReactText)) {
|
|
26
|
-
return parseInt(`${target}`) + offset
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const elementContext = context as HTMLElement
|
|
30
|
-
|
|
31
|
-
const y =
|
|
32
|
-
context === window || context === document.documentElement
|
|
33
|
-
? window.pageYOffset
|
|
34
|
-
: elementContext.scrollTop - elementContext.getBoundingClientRect().top
|
|
35
|
-
const distance =
|
|
36
|
-
(target as HTMLElement).nodeName.toLowerCase() === 'html'
|
|
37
|
-
? -y
|
|
38
|
-
: (target as HTMLElement).getBoundingClientRect().top + y
|
|
39
|
-
return distance + offset
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const scrollSmooth = (
|
|
43
|
-
target: ReactText | HTMLElement,
|
|
44
|
-
options: {
|
|
45
|
-
duration: number
|
|
46
|
-
context: Window | HTMLElement
|
|
47
|
-
offset: number
|
|
48
|
-
callback(target: ReactText | HTMLElement): void
|
|
49
|
-
} = {
|
|
50
|
-
duration: 500,
|
|
51
|
-
context: window,
|
|
52
|
-
offset: 0,
|
|
53
|
-
callback: _.noop,
|
|
54
|
-
}
|
|
55
|
-
) => {
|
|
56
|
-
const { duration, context, offset, callback } = options
|
|
57
|
-
const start = (context as HTMLElement).scrollTop ?? window.pageYOffset
|
|
58
|
-
const end = calcEndPoint(target, context, offset)
|
|
59
|
-
const clock = window.performance.now()
|
|
60
|
-
const rAF = window.requestAnimationFrame
|
|
61
|
-
|
|
62
|
-
const tick = () => {
|
|
63
|
-
const elapsed = window.performance.now() - clock
|
|
64
|
-
const pos = setPosition(start, end, elapsed, duration)
|
|
65
|
-
if (context !== window) {
|
|
66
|
-
;(context as HTMLElement).scrollTop = pos
|
|
67
|
-
} else {
|
|
68
|
-
window.scroll(0, pos)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (elapsed > duration) {
|
|
72
|
-
callback(target)
|
|
73
|
-
} else {
|
|
74
|
-
rAF(tick)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
tick()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const regex = /(auto|scroll)/
|
|
82
|
-
|
|
83
|
-
const parents = function (node: Element, ps: Element[]): Element[] {
|
|
84
|
-
if (_.isNil(node.parentNode)) {
|
|
85
|
-
return ps
|
|
86
|
-
}
|
|
87
|
-
return parents(node.parentNode as Element, ps.concat([node]))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const style = function (node: Element, prop: string): string {
|
|
91
|
-
return window.getComputedStyle(node, null).getPropertyValue(prop)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const overflow = function (node: Element): string {
|
|
95
|
-
return `${style(node, 'overflow')} ${style(node, 'overflow-y')} ${style(
|
|
96
|
-
node,
|
|
97
|
-
'overflow-x'
|
|
98
|
-
)}`
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const scroll = function (node: Element): boolean {
|
|
102
|
-
return regex.test(overflow(node))
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export const scrollParent = function (node: Element) {
|
|
106
|
-
if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
|
|
107
|
-
return
|
|
108
|
-
}
|
|
109
|
-
const ps = parents(node.parentNode as Element, [])
|
|
110
|
-
for (let i = 0; i < ps.length; i += 1) {
|
|
111
|
-
if (scroll(ps[i])) {
|
|
112
|
-
return ps[i]
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return document.scrollingElement ?? document.documentElement
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface GetNodeRectOptions {
|
|
119
|
-
top: number
|
|
120
|
-
right: number
|
|
121
|
-
bottom: number
|
|
122
|
-
left: number
|
|
123
|
-
width: number
|
|
124
|
-
height: number
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function getNodeRect(node: HTMLElement): GetNodeRectOptions {
|
|
128
|
-
const { top, right, bottom, left, width, height } = node.getBoundingClientRect()
|
|
129
|
-
return { top, right, bottom, left, width, height }
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function inView({
|
|
133
|
-
top,
|
|
134
|
-
right,
|
|
135
|
-
bottom,
|
|
136
|
-
left,
|
|
137
|
-
w,
|
|
138
|
-
h,
|
|
139
|
-
}: {
|
|
140
|
-
top: number
|
|
141
|
-
right: number
|
|
142
|
-
bottom: number
|
|
143
|
-
left: number
|
|
144
|
-
w: number
|
|
145
|
-
h: number
|
|
146
|
-
}) {
|
|
147
|
-
return top >= 0 && left >= 0 && bottom <= h && right <= w
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function isBody(node: HTMLElement) {
|
|
151
|
-
return (
|
|
152
|
-
node === document.querySelector('body') || node === document.querySelector('html')
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export const isHoriz = (pos: string) => /(left|right)/.test(pos)
|
|
157
|
-
export const isOutsideX = (val: number, windowWidth: number) => val > windowWidth
|
|
158
|
-
export const isOutsideY = (val: number, windowHeight: number) => val > windowHeight
|
|
159
|
-
export const safe = (sum: number) => (sum < 0 ? 0 : sum)
|
|
160
|
-
|
|
161
|
-
export function bestPositionOf(positions: { [key: string]: number }) {
|
|
162
|
-
return Object.keys(positions)
|
|
163
|
-
.map((p) => ({ position: p, value: positions[p] }))
|
|
164
|
-
.sort((a, b) => b.value - a.value)
|
|
165
|
-
.map((p) => p.position)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function getWindow() {
|
|
169
|
-
const w = Math.max(document.documentElement.clientWidth, window.innerWidth ?? 0)
|
|
170
|
-
const h = Math.max(document.documentElement.clientHeight, window.innerHeight ?? 0)
|
|
171
|
-
return { w, h }
|
|
172
|
-
}
|
|
1
|
+
import { ReactText } from 'react'
|
|
2
|
+
import _ from 'lodash'
|
|
3
|
+
|
|
4
|
+
const isNumeric = (n: ReactText): boolean =>
|
|
5
|
+
!isNaN(parseFloat(n as string)) && isFinite(n as number)
|
|
6
|
+
|
|
7
|
+
const setPosition = (
|
|
8
|
+
begin: number,
|
|
9
|
+
end: number,
|
|
10
|
+
elapsed: number,
|
|
11
|
+
duration: number
|
|
12
|
+
): number => {
|
|
13
|
+
const easeInOutCubic = (t: number) =>
|
|
14
|
+
t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
|
|
15
|
+
return elapsed > duration
|
|
16
|
+
? end
|
|
17
|
+
: begin + (end - begin) * easeInOutCubic(elapsed / duration)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const calcEndPoint = (
|
|
21
|
+
target: ReactText | HTMLElement,
|
|
22
|
+
context: HTMLElement | Window = window,
|
|
23
|
+
offset = 0
|
|
24
|
+
): number => {
|
|
25
|
+
if (isNumeric(target as ReactText)) {
|
|
26
|
+
return parseInt(`${target}`) + offset
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const elementContext = context as HTMLElement
|
|
30
|
+
|
|
31
|
+
const y =
|
|
32
|
+
context === window || context === document.documentElement
|
|
33
|
+
? window.pageYOffset
|
|
34
|
+
: elementContext.scrollTop - elementContext.getBoundingClientRect().top
|
|
35
|
+
const distance =
|
|
36
|
+
(target as HTMLElement).nodeName.toLowerCase() === 'html'
|
|
37
|
+
? -y
|
|
38
|
+
: (target as HTMLElement).getBoundingClientRect().top + y
|
|
39
|
+
return distance + offset
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const scrollSmooth = (
|
|
43
|
+
target: ReactText | HTMLElement,
|
|
44
|
+
options: {
|
|
45
|
+
duration: number
|
|
46
|
+
context: Window | HTMLElement
|
|
47
|
+
offset: number
|
|
48
|
+
callback(target: ReactText | HTMLElement): void
|
|
49
|
+
} = {
|
|
50
|
+
duration: 500,
|
|
51
|
+
context: window,
|
|
52
|
+
offset: 0,
|
|
53
|
+
callback: _.noop,
|
|
54
|
+
}
|
|
55
|
+
) => {
|
|
56
|
+
const { duration, context, offset, callback } = options
|
|
57
|
+
const start = (context as HTMLElement).scrollTop ?? window.pageYOffset
|
|
58
|
+
const end = calcEndPoint(target, context, offset)
|
|
59
|
+
const clock = window.performance.now()
|
|
60
|
+
const rAF = window.requestAnimationFrame
|
|
61
|
+
|
|
62
|
+
const tick = () => {
|
|
63
|
+
const elapsed = window.performance.now() - clock
|
|
64
|
+
const pos = setPosition(start, end, elapsed, duration)
|
|
65
|
+
if (context !== window) {
|
|
66
|
+
;(context as HTMLElement).scrollTop = pos
|
|
67
|
+
} else {
|
|
68
|
+
window.scroll(0, pos)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (elapsed > duration) {
|
|
72
|
+
callback(target)
|
|
73
|
+
} else {
|
|
74
|
+
rAF(tick)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
tick()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const regex = /(auto|scroll)/
|
|
82
|
+
|
|
83
|
+
const parents = function (node: Element, ps: Element[]): Element[] {
|
|
84
|
+
if (_.isNil(node.parentNode)) {
|
|
85
|
+
return ps
|
|
86
|
+
}
|
|
87
|
+
return parents(node.parentNode as Element, ps.concat([node]))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const style = function (node: Element, prop: string): string {
|
|
91
|
+
return window.getComputedStyle(node, null).getPropertyValue(prop)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const overflow = function (node: Element): string {
|
|
95
|
+
return `${style(node, 'overflow')} ${style(node, 'overflow-y')} ${style(
|
|
96
|
+
node,
|
|
97
|
+
'overflow-x'
|
|
98
|
+
)}`
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const scroll = function (node: Element): boolean {
|
|
102
|
+
return regex.test(overflow(node))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const scrollParent = function (node: Element) {
|
|
106
|
+
if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
const ps = parents(node.parentNode as Element, [])
|
|
110
|
+
for (let i = 0; i < ps.length; i += 1) {
|
|
111
|
+
if (scroll(ps[i])) {
|
|
112
|
+
return ps[i]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return document.scrollingElement ?? document.documentElement
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface GetNodeRectOptions {
|
|
119
|
+
top: number
|
|
120
|
+
right: number
|
|
121
|
+
bottom: number
|
|
122
|
+
left: number
|
|
123
|
+
width: number
|
|
124
|
+
height: number
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function getNodeRect(node: HTMLElement): GetNodeRectOptions {
|
|
128
|
+
const { top, right, bottom, left, width, height } = node.getBoundingClientRect()
|
|
129
|
+
return { top, right, bottom, left, width, height }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function inView({
|
|
133
|
+
top,
|
|
134
|
+
right,
|
|
135
|
+
bottom,
|
|
136
|
+
left,
|
|
137
|
+
w,
|
|
138
|
+
h,
|
|
139
|
+
}: {
|
|
140
|
+
top: number
|
|
141
|
+
right: number
|
|
142
|
+
bottom: number
|
|
143
|
+
left: number
|
|
144
|
+
w: number
|
|
145
|
+
h: number
|
|
146
|
+
}) {
|
|
147
|
+
return top >= 0 && left >= 0 && bottom <= h && right <= w
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function isBody(node: HTMLElement) {
|
|
151
|
+
return (
|
|
152
|
+
node === document.querySelector('body') || node === document.querySelector('html')
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const isHoriz = (pos: string) => /(left|right)/.test(pos)
|
|
157
|
+
export const isOutsideX = (val: number, windowWidth: number) => val > windowWidth
|
|
158
|
+
export const isOutsideY = (val: number, windowHeight: number) => val > windowHeight
|
|
159
|
+
export const safe = (sum: number) => (sum < 0 ? 0 : sum)
|
|
160
|
+
|
|
161
|
+
export function bestPositionOf(positions: { [key: string]: number }) {
|
|
162
|
+
return Object.keys(positions)
|
|
163
|
+
.map((p) => ({ position: p, value: positions[p] }))
|
|
164
|
+
.sort((a, b) => b.value - a.value)
|
|
165
|
+
.map((p) => p.position)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function getWindow() {
|
|
169
|
+
const w = Math.max(document.documentElement.clientWidth, window.innerWidth ?? 0)
|
|
170
|
+
const h = Math.max(document.documentElement.clientHeight, window.innerHeight ?? 0)
|
|
171
|
+
return { w, h }
|
|
172
|
+
}
|