lynx-console 0.1.0 → 0.1.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/dist/assets/src/components/{ConsolePanel.css.ts.vanilla-DFvHPEyg.css → ConsolePanel.css.ts.vanilla-DWdhFBJq.css} +66 -69
- package/dist/assets/src/components/FadeList.css.ts.vanilla-sppTKMZj.css +12 -0
- package/dist/assets/src/components/{NetworkPanel.css.ts.vanilla-DFMduT0T.css → NetworkPanel.css.ts.vanilla-BSE4s40D.css} +2 -5
- package/dist/assets/src/components/{PerformancePanel.css.ts.vanilla-D35LuXlW.css → PerformancePanel.css.ts.vanilla-Bb3zG5G8.css} +2 -2
- package/dist/index.cjs +130 -101
- package/dist/index.mjs +130 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ConsolePanel.css.ts +12 -17
- package/src/components/FadeList.css.ts +16 -0
- package/src/components/FadeList.tsx +76 -0
- package/src/components/FloatingButton.tsx +21 -18
- package/src/components/LogPanel.tsx +18 -35
- package/src/components/NetworkPanel.css.ts +2 -5
- package/src/components/NetworkPanel.tsx +4 -4
- package/src/components/PerformancePanel.css.ts +2 -2
- package/src/components/PerformancePanel.tsx +5 -5
- package/src/hooks/useLongPressDrag.ts +3 -3
package/package.json
CHANGED
|
@@ -36,13 +36,6 @@ export const logHeader = style({
|
|
|
36
36
|
paddingBottom: 3,
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
export const fadeTop = style({
|
|
40
|
-
height: 20,
|
|
41
|
-
marginBottom: -20,
|
|
42
|
-
zIndex: 1,
|
|
43
|
-
background: `linear-gradient(to bottom, ${vars.$color.bg.layerDefault}, #ffffff00)`,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
39
|
export const filterWrapper = style({
|
|
47
40
|
position: "relative",
|
|
48
41
|
});
|
|
@@ -58,7 +51,7 @@ export const filterButton = style({
|
|
|
58
51
|
|
|
59
52
|
export const filterButtonText = style({
|
|
60
53
|
...typography("t3", "medium"),
|
|
61
|
-
color: vars.$color.fg.
|
|
54
|
+
color: vars.$color.fg.neutralMuted,
|
|
62
55
|
});
|
|
63
56
|
|
|
64
57
|
export const filterDropdown = style({
|
|
@@ -66,7 +59,7 @@ export const filterDropdown = style({
|
|
|
66
59
|
top: "100%",
|
|
67
60
|
left: 0,
|
|
68
61
|
marginTop: 4,
|
|
69
|
-
backgroundColor: vars.$color.bg.
|
|
62
|
+
backgroundColor: vars.$color.bg.layerFloating,
|
|
70
63
|
borderWidth: 1,
|
|
71
64
|
borderColor: vars.$color.stroke.neutralSubtle,
|
|
72
65
|
borderStyle: "solid",
|
|
@@ -138,6 +131,15 @@ export const searchInput = style({
|
|
|
138
131
|
caretColor: vars.$color.palette.green600,
|
|
139
132
|
});
|
|
140
133
|
|
|
134
|
+
export const searchClear = style({
|
|
135
|
+
padding: "2px 4px",
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export const searchClearText = style({
|
|
139
|
+
...typography("t3", "medium"),
|
|
140
|
+
color: vars.$color.fg.placeholder,
|
|
141
|
+
});
|
|
142
|
+
|
|
141
143
|
export const clearButton = style({
|
|
142
144
|
padding: "3px 6px",
|
|
143
145
|
backgroundColor: vars.$color.bg.neutralWeak,
|
|
@@ -146,7 +148,7 @@ export const clearButton = style({
|
|
|
146
148
|
|
|
147
149
|
export const clearButtonText = style({
|
|
148
150
|
...typography("t3", "medium"),
|
|
149
|
-
color: vars.$color.fg.
|
|
151
|
+
color: vars.$color.fg.neutralMuted,
|
|
150
152
|
});
|
|
151
153
|
|
|
152
154
|
export const logList = style({
|
|
@@ -311,13 +313,6 @@ export const argObjectJson = style({
|
|
|
311
313
|
color: vars.$color.fg.neutral,
|
|
312
314
|
});
|
|
313
315
|
|
|
314
|
-
export const fadeBottom = style({
|
|
315
|
-
height: 20,
|
|
316
|
-
marginTop: -20,
|
|
317
|
-
zIndex: 1,
|
|
318
|
-
background: `linear-gradient(to top, ${vars.$color.bg.layerDefault}, #ffffff00)`,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
316
|
export const replInputRow = style({
|
|
322
317
|
display: "flex",
|
|
323
318
|
flexDirection: "row",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { style } from "@vanilla-extract/css";
|
|
2
|
+
import { vars } from "../styles/vars";
|
|
3
|
+
|
|
4
|
+
export const fadeTop = style({
|
|
5
|
+
height: 20,
|
|
6
|
+
marginBottom: -20,
|
|
7
|
+
zIndex: 1,
|
|
8
|
+
background: `linear-gradient(to bottom, ${vars.$color.bg.layerFloating}, #ffffff00)`,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const fadeBottom = style({
|
|
12
|
+
height: 20,
|
|
13
|
+
marginTop: -20,
|
|
14
|
+
zIndex: 1,
|
|
15
|
+
background: `linear-gradient(to top, ${vars.$color.bg.layerFloating}, #ffffff00)`,
|
|
16
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useRef, useState } from "@lynx-js/react";
|
|
2
|
+
import type { BaseEvent, NodesRef } from "@lynx-js/types";
|
|
3
|
+
import { vars } from "../styles/vars";
|
|
4
|
+
import * as css from "./FadeList.css";
|
|
5
|
+
|
|
6
|
+
interface FadeListProps {
|
|
7
|
+
className?: string;
|
|
8
|
+
listRef?: React.RefObject<NodesRef>;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
"preload-buffer-count"?: number;
|
|
11
|
+
"initial-scroll-index"?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const FadeList = ({
|
|
15
|
+
className,
|
|
16
|
+
listRef: externalListRef,
|
|
17
|
+
children,
|
|
18
|
+
...listProps
|
|
19
|
+
}: FadeListProps) => {
|
|
20
|
+
const [fadeState, setFadeState] = useState({ atTop: true, atBottom: true });
|
|
21
|
+
const fadeRef = useRef({ atTop: true, atBottom: true });
|
|
22
|
+
const internalListRef = useRef<NodesRef>(null);
|
|
23
|
+
const listRef = externalListRef ?? internalListRef;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<view
|
|
28
|
+
className={css.fadeTop}
|
|
29
|
+
style={{
|
|
30
|
+
background: fadeState.atTop
|
|
31
|
+
? "linear-gradient(to bottom, #ffffff00, #ffffff00)"
|
|
32
|
+
: `linear-gradient(to bottom, ${vars.$color.bg.layerFloating}, #ffffff00)`,
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
<list
|
|
36
|
+
ref={listRef}
|
|
37
|
+
scroll-orientation="vertical"
|
|
38
|
+
className={className}
|
|
39
|
+
scroll-event-throttle={16}
|
|
40
|
+
bindscroll={(
|
|
41
|
+
e: BaseEvent<
|
|
42
|
+
"bindscroll",
|
|
43
|
+
{
|
|
44
|
+
scrollTop: number;
|
|
45
|
+
scrollHeight: number;
|
|
46
|
+
listHeight: number;
|
|
47
|
+
}
|
|
48
|
+
>,
|
|
49
|
+
) => {
|
|
50
|
+
const { scrollTop, scrollHeight, listHeight } = e.detail;
|
|
51
|
+
const atTop = scrollTop <= 10;
|
|
52
|
+
const atBottom = scrollTop + listHeight >= scrollHeight - 10;
|
|
53
|
+
if (
|
|
54
|
+
atTop !== fadeRef.current.atTop ||
|
|
55
|
+
atBottom !== fadeRef.current.atBottom
|
|
56
|
+
) {
|
|
57
|
+
fadeRef.current.atTop = atTop;
|
|
58
|
+
fadeRef.current.atBottom = atBottom;
|
|
59
|
+
setFadeState({ atTop, atBottom });
|
|
60
|
+
}
|
|
61
|
+
}}
|
|
62
|
+
{...listProps}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
</list>
|
|
66
|
+
<view
|
|
67
|
+
className={css.fadeBottom}
|
|
68
|
+
style={{
|
|
69
|
+
background: fadeState.atBottom
|
|
70
|
+
? "linear-gradient(to top, #ffffff00, #ffffff00)"
|
|
71
|
+
: `linear-gradient(to top, ${vars.$color.bg.layerFloating}, #ffffff00)`,
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
@@ -45,26 +45,29 @@ export const FloatingButton = ({
|
|
|
45
45
|
const isDragging = phase === "dragging";
|
|
46
46
|
|
|
47
47
|
return (
|
|
48
|
-
|
|
49
|
-
className={css.wrapper}
|
|
50
|
-
style={{
|
|
51
|
-
right: `${right}px`,
|
|
52
|
-
bottom: `${bottom}px`,
|
|
53
|
-
transform: isDragging ? "scale(1.05)" : "scale(1)",
|
|
54
|
-
}}
|
|
55
|
-
{...handlers}
|
|
56
|
-
>
|
|
57
|
-
<view className={css.button}>
|
|
58
|
-
{children}
|
|
59
|
-
<view className={css.shineOverlay} style={SHINE_STYLES[phase]} />
|
|
60
|
-
</view>
|
|
48
|
+
<>
|
|
61
49
|
<view
|
|
62
|
-
className={css.
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
className={css.wrapper}
|
|
51
|
+
consume-slide-event={[[-180, 180]]}
|
|
52
|
+
style={{
|
|
53
|
+
right: `${right}px`,
|
|
54
|
+
bottom: `${bottom}px`,
|
|
55
|
+
transform: isDragging ? "scale(1.05)" : "scale(1)",
|
|
56
|
+
}}
|
|
57
|
+
{...handlers}
|
|
65
58
|
>
|
|
66
|
-
<
|
|
59
|
+
<view className={css.button}>
|
|
60
|
+
{children}
|
|
61
|
+
<view className={css.shineOverlay} style={SHINE_STYLES[phase]} />
|
|
62
|
+
</view>
|
|
63
|
+
<view
|
|
64
|
+
className={css.reloadButton}
|
|
65
|
+
catchtouchstart={() => clearTimer()}
|
|
66
|
+
bindtap={handleReload}
|
|
67
|
+
>
|
|
68
|
+
<text className={css.reloadIcon}>{"\u21BB"}</text>
|
|
69
|
+
</view>
|
|
67
70
|
</view>
|
|
68
|
-
|
|
71
|
+
</>
|
|
69
72
|
);
|
|
70
73
|
};
|
|
@@ -2,8 +2,8 @@ import { useEffect, useMemo, useRef, useState } from "@lynx-js/react";
|
|
|
2
2
|
import type { BaseEvent, InputInputEvent, NodesRef } from "@lynx-js/types";
|
|
3
3
|
import { stringify } from "javascript-stringify";
|
|
4
4
|
import type { LogEntry, LogLevel } from "../types";
|
|
5
|
-
import { vars } from "../styles/vars";
|
|
6
5
|
import * as css from "./ConsolePanel.css";
|
|
6
|
+
import { FadeList } from "./FadeList";
|
|
7
7
|
|
|
8
8
|
const LOG_LEVELS: LogLevel[] = ["log", "info", "warn", "error"];
|
|
9
9
|
|
|
@@ -40,8 +40,6 @@ export const LogPanel = ({ logs, clearLogs }: LogPanelProps) => {
|
|
|
40
40
|
);
|
|
41
41
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
42
42
|
const [searchQuery, setSearchQuery] = useState(savedSearchQuery);
|
|
43
|
-
const [fadeState, setFadeState] = useState({ atTop: true, atBottom: true });
|
|
44
|
-
const fadeRef = useRef({ atTop: true, atBottom: true });
|
|
45
43
|
const inputRef = useRef<NodesRef>(null);
|
|
46
44
|
const searchInputRef = useRef<NodesRef>(null);
|
|
47
45
|
const listRef = useRef<NodesRef>(null);
|
|
@@ -269,38 +267,31 @@ export const LogPanel = ({ logs, clearLogs }: LogPanelProps) => {
|
|
|
269
267
|
setSearchQuery(e.detail.value)
|
|
270
268
|
}
|
|
271
269
|
/>
|
|
270
|
+
{searchQuery.length > 0 && (
|
|
271
|
+
<view
|
|
272
|
+
className={css.searchClear}
|
|
273
|
+
bindtap={() => {
|
|
274
|
+
setSearchQuery("");
|
|
275
|
+
searchInputRef.current
|
|
276
|
+
?.invoke({ method: "setValue", params: { value: "" } })
|
|
277
|
+
.exec();
|
|
278
|
+
}}
|
|
279
|
+
>
|
|
280
|
+
<text className={css.searchClearText}>✕</text>
|
|
281
|
+
</view>
|
|
282
|
+
)}
|
|
272
283
|
</view>
|
|
273
284
|
<view style={{ display: "flex", flexDirection: "row", gap: 8 }}>
|
|
274
285
|
<view className={css.clearButton} bindtap={clearLogs}>
|
|
275
|
-
<text className={css.clearButtonText}
|
|
286
|
+
<text className={css.clearButtonText}>🗑</text>
|
|
276
287
|
</view>
|
|
277
288
|
</view>
|
|
278
289
|
</view>
|
|
279
|
-
<
|
|
280
|
-
|
|
281
|
-
style={{
|
|
282
|
-
background: fadeState.atTop
|
|
283
|
-
? `linear-gradient(to bottom, #ffffff00, #ffffff00)`
|
|
284
|
-
: `linear-gradient(to bottom, ${vars.$color.bg.layerDefault}, #ffffff00)`,
|
|
285
|
-
}}
|
|
286
|
-
/>
|
|
287
|
-
<list
|
|
288
|
-
ref={listRef}
|
|
289
|
-
scroll-orientation="vertical"
|
|
290
|
+
<FadeList
|
|
291
|
+
listRef={listRef}
|
|
290
292
|
className={css.logList}
|
|
291
293
|
preload-buffer-count={10}
|
|
292
294
|
initial-scroll-index={Math.max(0, filteredLogs.length - 1)}
|
|
293
|
-
scroll-event-throttle={16}
|
|
294
|
-
bindscroll={(e: BaseEvent<"bindscroll", { scrollTop: number; scrollHeight: number; listHeight: number }>) => {
|
|
295
|
-
const { scrollTop, scrollHeight, listHeight } = e.detail;
|
|
296
|
-
const atTop = scrollTop <= 10;
|
|
297
|
-
const atBottom = scrollTop + listHeight >= scrollHeight - 10;
|
|
298
|
-
if (atTop !== fadeRef.current.atTop || atBottom !== fadeRef.current.atBottom) {
|
|
299
|
-
fadeRef.current.atTop = atTop;
|
|
300
|
-
fadeRef.current.atBottom = atBottom;
|
|
301
|
-
setFadeState({ atTop, atBottom });
|
|
302
|
-
}
|
|
303
|
-
}}
|
|
304
295
|
>
|
|
305
296
|
{filteredLogs.length === 0 ? (
|
|
306
297
|
<list-item item-key="empty-state">
|
|
@@ -342,15 +333,7 @@ export const LogPanel = ({ logs, clearLogs }: LogPanelProps) => {
|
|
|
342
333
|
);
|
|
343
334
|
})
|
|
344
335
|
)}
|
|
345
|
-
</
|
|
346
|
-
<view
|
|
347
|
-
className={css.fadeBottom}
|
|
348
|
-
style={{
|
|
349
|
-
background: fadeState.atBottom
|
|
350
|
-
? `linear-gradient(to top, #ffffff00, #ffffff00)`
|
|
351
|
-
: `linear-gradient(to top, ${vars.$color.bg.layerDefault}, #ffffff00)`,
|
|
352
|
-
}}
|
|
353
|
-
/>
|
|
336
|
+
</FadeList>
|
|
354
337
|
<view className={css.replInputRow}>
|
|
355
338
|
<text className={css.replPrompt}>{"›"}</text>
|
|
356
339
|
<input
|
|
@@ -17,9 +17,6 @@ export const header = style({
|
|
|
17
17
|
justifyContent: "space-between",
|
|
18
18
|
marginBottom: 8,
|
|
19
19
|
paddingBottom: 4,
|
|
20
|
-
borderBottomWidth: 1,
|
|
21
|
-
borderBottomColor: vars.$color.stroke.neutralSubtle,
|
|
22
|
-
borderBottomStyle: "solid",
|
|
23
20
|
});
|
|
24
21
|
|
|
25
22
|
export const count = style({
|
|
@@ -28,14 +25,14 @@ export const count = style({
|
|
|
28
25
|
});
|
|
29
26
|
|
|
30
27
|
export const clearButton = style({
|
|
31
|
-
padding: "6px
|
|
28
|
+
padding: "3px 6px",
|
|
32
29
|
backgroundColor: vars.$color.bg.neutralWeak,
|
|
33
30
|
borderRadius: 4,
|
|
34
31
|
});
|
|
35
32
|
|
|
36
33
|
export const clearButtonText = style({
|
|
37
34
|
...typography("t3", "medium"),
|
|
38
|
-
color: vars.$color.fg.
|
|
35
|
+
color: vars.$color.fg.neutralMuted,
|
|
39
36
|
});
|
|
40
37
|
|
|
41
38
|
export const list = style({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useState } from "@lynx-js/react";
|
|
2
2
|
import type { NetworkEntry } from "../types";
|
|
3
|
+
import { FadeList } from "./FadeList";
|
|
3
4
|
import { NetworkDetailSection } from "./NetworkDetailSection";
|
|
4
5
|
import * as css from "./NetworkPanel.css";
|
|
5
6
|
|
|
@@ -16,7 +17,6 @@ export const NetworkPanel = ({
|
|
|
16
17
|
}: NetworkPanelProps) => {
|
|
17
18
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
18
19
|
const [activeTab, setActiveTab] = useState<TabType>("general");
|
|
19
|
-
|
|
20
20
|
const formatDuration = (duration?: number): string => {
|
|
21
21
|
if (!duration) return "-";
|
|
22
22
|
if (duration < 1000) return `${duration}ms`;
|
|
@@ -71,7 +71,7 @@ export const NetworkPanel = ({
|
|
|
71
71
|
<view className={css.header}>
|
|
72
72
|
<text className={css.count}>Total: {networks.length} requests</text>
|
|
73
73
|
<view className={css.clearButton} bindtap={clearNetworks}>
|
|
74
|
-
<text className={css.clearButtonText}
|
|
74
|
+
<text className={css.clearButtonText}>🗑</text>
|
|
75
75
|
</view>
|
|
76
76
|
</view>
|
|
77
77
|
|
|
@@ -80,7 +80,7 @@ export const NetworkPanel = ({
|
|
|
80
80
|
<text className={css.placeholderText}>No network requests yet</text>
|
|
81
81
|
</view>
|
|
82
82
|
) : (
|
|
83
|
-
<
|
|
83
|
+
<FadeList className={css.list}>
|
|
84
84
|
{networks.map((network) => (
|
|
85
85
|
<list-item key={network.id} item-key={network.id}>
|
|
86
86
|
<view className={css.item({ status: network.status })}>
|
|
@@ -215,7 +215,7 @@ export const NetworkPanel = ({
|
|
|
215
215
|
</view>
|
|
216
216
|
</list-item>
|
|
217
217
|
))}
|
|
218
|
-
</
|
|
218
|
+
</FadeList>
|
|
219
219
|
)}
|
|
220
220
|
</view>
|
|
221
221
|
);
|
|
@@ -28,14 +28,14 @@ export const count = style({
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
export const clearButton = style({
|
|
31
|
-
padding: "6px
|
|
31
|
+
padding: "3px 6px",
|
|
32
32
|
backgroundColor: vars.$color.bg.neutralWeak,
|
|
33
33
|
borderRadius: 4,
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
export const clearButtonText = style({
|
|
37
37
|
...typography("t3", "medium"),
|
|
38
|
-
color: vars.$color.fg.
|
|
38
|
+
color: vars.$color.fg.neutralMuted,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
export const list = style({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState } from "@lynx-js/react";
|
|
2
2
|
import { stringify } from "javascript-stringify";
|
|
3
3
|
import type { PerformanceEntryData } from "../types";
|
|
4
|
+
import { FadeList } from "./FadeList";
|
|
4
5
|
import * as css from "./PerformancePanel.css";
|
|
5
6
|
|
|
6
7
|
interface PerformancePanelProps {
|
|
@@ -65,7 +66,6 @@ export const PerformancePanel = ({
|
|
|
65
66
|
clearPerformances,
|
|
66
67
|
}: PerformancePanelProps) => {
|
|
67
68
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
68
|
-
|
|
69
69
|
if (performances.length === 0) {
|
|
70
70
|
return (
|
|
71
71
|
<view className={css.container}>
|
|
@@ -80,7 +80,7 @@ export const PerformancePanel = ({
|
|
|
80
80
|
<text>Log</text>
|
|
81
81
|
</view>
|
|
82
82
|
<view bindtap={clearPerformances} className={css.clearButton}>
|
|
83
|
-
<text className={css.clearButtonText}
|
|
83
|
+
<text className={css.clearButtonText}>🗑</text>
|
|
84
84
|
</view>
|
|
85
85
|
</view>
|
|
86
86
|
<view className={css.placeholder}>
|
|
@@ -97,11 +97,11 @@ export const PerformancePanel = ({
|
|
|
97
97
|
<view className={css.header}>
|
|
98
98
|
<text className={css.count}>{performances.length} entries</text>
|
|
99
99
|
<view bindtap={clearPerformances} className={css.clearButton}>
|
|
100
|
-
<text className={css.clearButtonText}
|
|
100
|
+
<text className={css.clearButtonText}>🗑</text>
|
|
101
101
|
</view>
|
|
102
102
|
</view>
|
|
103
103
|
|
|
104
|
-
<
|
|
104
|
+
<FadeList className={css.list}>
|
|
105
105
|
{performances.map((perf) => {
|
|
106
106
|
const isMetricFcp = isMetricFcpEntry(perf);
|
|
107
107
|
const fcpMetrics = extractFcpMetrics(perf);
|
|
@@ -203,7 +203,7 @@ export const PerformancePanel = ({
|
|
|
203
203
|
</list-item>
|
|
204
204
|
);
|
|
205
205
|
})}
|
|
206
|
-
</
|
|
206
|
+
</FadeList>
|
|
207
207
|
</view>
|
|
208
208
|
);
|
|
209
209
|
};
|
|
@@ -87,9 +87,9 @@ export function useLongPressDrag(onTap: () => void) {
|
|
|
87
87
|
bottom: isDragging ? tempBottom : bottom,
|
|
88
88
|
clearTimer,
|
|
89
89
|
handlers: {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
catchtouchstart: handleTouchStart,
|
|
91
|
+
catchtouchmove: handleTouchMove,
|
|
92
|
+
catchtouchend: handleTouchEnd,
|
|
93
93
|
},
|
|
94
94
|
};
|
|
95
95
|
}
|