@hrnec06/react_utils 1.2.0 → 1.2.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/package.json +1 -1
- package/src/debugger/Debugger.tsx +2 -2
- package/src/debugger/DebuggerScrollBar.tsx +3 -3
- package/src/debugger/DebuggerSymbols.tsx +1 -1
- package/src/debugger/parser/DebugParser.tsx +45 -0
- package/src/debugger/parser/DebugParserSimple.tsx +53 -0
- package/src/debugger/parser/ValueArray.tsx +143 -0
- package/src/debugger/parser/ValueBoolean.tsx +10 -0
- package/src/debugger/parser/ValueFunction.tsx +25 -0
- package/src/debugger/parser/ValueKeyword.tsx +12 -0
- package/src/debugger/parser/ValueNumber.tsx +12 -0
- package/src/debugger/parser/ValueObject.tsx +113 -0
- package/src/debugger/parser/ValueString.tsx +16 -0
- package/src/debugger/parser/ValueSymbol.tsx +20 -0
- package/src/debugger/DebugParser.tsx +0 -401
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import {DebuggerContext} from "./DebuggerContext";
|
|
4
4
|
import clsx from "clsx";
|
|
5
5
|
import ResizeBorder from "./DebuggerWindowResize";
|
|
6
|
-
import ParseValue from "./DebugParser";
|
|
7
6
|
import ScrollBar from "./DebuggerScrollBar";
|
|
8
7
|
import useKeyListener from "../hooks/useKeyListener";
|
|
9
8
|
import useUpdateEffect from "../hooks/useUpdateEffect";
|
|
10
9
|
import useUpdatedRef from "../hooks/useUpdatedRef";
|
|
10
|
+
import ParseValue from "./parser/DebugParser";
|
|
11
11
|
|
|
12
12
|
interface DebugProps {
|
|
13
13
|
value: unknown,
|
|
@@ -271,7 +271,7 @@ export default function Debug({
|
|
|
271
271
|
|
|
272
272
|
<div
|
|
273
273
|
onWheel={handleWheel}
|
|
274
|
-
className="bg-[#1f1f1f] shadow-lg rounded-md border border-
|
|
274
|
+
className="bg-[#1f1f1f] shadow-lg rounded-md border border-[#4b4b4b] w-full h-full overflow-hidden flex"
|
|
275
275
|
>
|
|
276
276
|
<div
|
|
277
277
|
ref={containerRef}
|
|
@@ -85,17 +85,17 @@ export default function ScrollBar({
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
return (
|
|
88
|
-
<div className="p-1 border-l border-l-
|
|
88
|
+
<div className="p-1 border-l border-l-[#2b2b2b]">
|
|
89
89
|
<div
|
|
90
90
|
onMouseDown={handleWraperMouseDown}
|
|
91
91
|
ref={wrapperRef}
|
|
92
|
-
className="h-full
|
|
92
|
+
className="h-full shrink-0"
|
|
93
93
|
>
|
|
94
94
|
{debug.scroll.isScrollable && wrapperHeight > 0 && (
|
|
95
95
|
<div
|
|
96
96
|
onMouseDown={handleMouseDown}
|
|
97
97
|
|
|
98
|
-
className="bg-
|
|
98
|
+
className="bg-[#3b3b3b] hover:bg-[#4b4b4b] w-2 rounded-lg"
|
|
99
99
|
style={{
|
|
100
100
|
transform: `translateY(${barTop}px)`,
|
|
101
101
|
height: `${barHeight}px`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import useDebugger from "../DebuggerContext";
|
|
2
|
+
import { matchPath } from "../DebuggerLogic";
|
|
3
|
+
import ValueArray from "./ValueArray";
|
|
4
|
+
import ValueBoolean from "./ValueBoolean";
|
|
5
|
+
import ValueFunction from "./ValueFunction";
|
|
6
|
+
import ValueKeyword from "./ValueKeyword";
|
|
7
|
+
import ValueNumber from "./ValueNumber";
|
|
8
|
+
import ValueObject from "./ValueObject";
|
|
9
|
+
import ValueString from "./ValueString";
|
|
10
|
+
import ValueSymbol from "./ValueSymbol";
|
|
11
|
+
|
|
12
|
+
interface ParseValueProps {
|
|
13
|
+
value: unknown,
|
|
14
|
+
path?: string[]
|
|
15
|
+
}
|
|
16
|
+
export default function ParseValue({
|
|
17
|
+
value,
|
|
18
|
+
path = []
|
|
19
|
+
}: ParseValueProps) {
|
|
20
|
+
const debug = useDebugger();
|
|
21
|
+
|
|
22
|
+
switch (typeof value) {
|
|
23
|
+
case 'string': return (<ValueString value={value} />);
|
|
24
|
+
case 'bigint':
|
|
25
|
+
case 'number': return (<ValueNumber value={value} />);
|
|
26
|
+
case 'boolean': return (<ValueBoolean value={value} />);
|
|
27
|
+
case 'undefined': return (<ValueKeyword value={"undefined"} />);
|
|
28
|
+
case 'function': return (<ValueFunction value={value} />);
|
|
29
|
+
case 'symbol': return (<ValueSymbol value={value} />)
|
|
30
|
+
case 'object': {
|
|
31
|
+
if (value === null)
|
|
32
|
+
return (<ValueKeyword value={"null"} />)
|
|
33
|
+
|
|
34
|
+
const isRootObject = path.length === 0;
|
|
35
|
+
|
|
36
|
+
const shouldBeExpanded = (isRootObject && debug.options.openRoot) || (matchPath(path, debug.paths.open) && !matchPath(path, debug.paths.exclude));
|
|
37
|
+
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
return <ValueArray value={value} path={path} defaultExpanded={shouldBeExpanded} />
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return <ValueObject value={value} path={path} defaultExpanded={shouldBeExpanded} />
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import ValueBoolean from "./ValueBoolean";
|
|
2
|
+
import ValueFunction from "./ValueFunction";
|
|
3
|
+
import ValueKeyword from "./ValueKeyword";
|
|
4
|
+
import ValueNumber from "./ValueNumber";
|
|
5
|
+
import ValueString from "./ValueString";
|
|
6
|
+
import ValueSymbol from "./ValueSymbol";
|
|
7
|
+
|
|
8
|
+
interface ParseValueSimpleProps {
|
|
9
|
+
value: unknown
|
|
10
|
+
}
|
|
11
|
+
export default function ParseValueSimple({
|
|
12
|
+
value
|
|
13
|
+
}: ParseValueSimpleProps): React.ReactNode {
|
|
14
|
+
const MAX_LENGTH = 16;
|
|
15
|
+
|
|
16
|
+
switch (typeof value) {
|
|
17
|
+
case 'bigint':
|
|
18
|
+
case 'number': {
|
|
19
|
+
const numStr = value.toString();
|
|
20
|
+
|
|
21
|
+
if (numStr.length > MAX_LENGTH)
|
|
22
|
+
return <ValueKeyword value={typeof value} />;
|
|
23
|
+
|
|
24
|
+
return <ValueNumber value={value} />
|
|
25
|
+
}
|
|
26
|
+
case 'boolean': return <ValueBoolean value={value} />
|
|
27
|
+
case 'function': return <ValueFunction value={value} />
|
|
28
|
+
case 'object': {
|
|
29
|
+
if (value === null)
|
|
30
|
+
return <ValueKeyword value="null" />
|
|
31
|
+
|
|
32
|
+
const className = Object.getPrototypeOf(value) !== Object.prototype ? value.constructor.name : null;
|
|
33
|
+
|
|
34
|
+
if (className === null || className.length > MAX_LENGTH)
|
|
35
|
+
return <ValueKeyword value="object" />
|
|
36
|
+
|
|
37
|
+
return className;
|
|
38
|
+
}
|
|
39
|
+
case 'string': {
|
|
40
|
+
if (value.length > MAX_LENGTH)
|
|
41
|
+
return <ValueString value="string" noEncase />
|
|
42
|
+
|
|
43
|
+
return <ValueString value={value} />;
|
|
44
|
+
}
|
|
45
|
+
case 'symbol': {
|
|
46
|
+
if (!value.description || value.description.length > MAX_LENGTH)
|
|
47
|
+
return <ValueKeyword value="Symbol" />
|
|
48
|
+
|
|
49
|
+
return <ValueSymbol value={value} />
|
|
50
|
+
}
|
|
51
|
+
case 'undefined': return <ValueKeyword value="undefined" />
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import React, { useLayoutEffect, useMemo, useState } from "react";
|
|
2
|
+
import useDebugger from "../DebuggerContext";
|
|
3
|
+
import { Char_Bracket, Char_Comma, Chevron_Toggle } from "../DebuggerSymbols";
|
|
4
|
+
import ParseValueSimple from "./DebugParserSimple";
|
|
5
|
+
import ParseValue from "./DebugParser";
|
|
6
|
+
|
|
7
|
+
interface ValueArrayProps {
|
|
8
|
+
value: unknown[],
|
|
9
|
+
path: string[],
|
|
10
|
+
defaultExpanded?: boolean
|
|
11
|
+
}
|
|
12
|
+
export default function ValueArray({
|
|
13
|
+
value,
|
|
14
|
+
path,
|
|
15
|
+
defaultExpanded = false
|
|
16
|
+
}: ValueArrayProps) {
|
|
17
|
+
const debug = useDebugger();
|
|
18
|
+
|
|
19
|
+
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
20
|
+
|
|
21
|
+
const children = useMemo(() => {
|
|
22
|
+
const children: React.ReactNode[] = [];
|
|
23
|
+
|
|
24
|
+
let ix = 0;
|
|
25
|
+
|
|
26
|
+
while (ix < value.length) {
|
|
27
|
+
const nextTarget = Math.min(ix + debug.options.compactArrays, value.length);
|
|
28
|
+
|
|
29
|
+
children.push(
|
|
30
|
+
<li key={ix}>
|
|
31
|
+
{
|
|
32
|
+
(() => {
|
|
33
|
+
const children: React.ReactNode[] = [];
|
|
34
|
+
|
|
35
|
+
for (;ix < nextTarget; ix++) {
|
|
36
|
+
children.push(
|
|
37
|
+
<CompactArrayItem
|
|
38
|
+
key={ix}
|
|
39
|
+
value={value[ix]}
|
|
40
|
+
path={[...path, `${ix}`]}
|
|
41
|
+
isLast={ix < value.length - 1}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return children;
|
|
47
|
+
})()
|
|
48
|
+
}
|
|
49
|
+
</li>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
ix = nextTarget;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return children;
|
|
56
|
+
}, [debug.options.compactArrays, value]);
|
|
57
|
+
|
|
58
|
+
const collapsedPreview = useMemo(() => {
|
|
59
|
+
const children: React.ReactNode[] = [];
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < Math.min(value.length, 6); i++) {
|
|
62
|
+
children.push(
|
|
63
|
+
<CompactArrayItem
|
|
64
|
+
key={i}
|
|
65
|
+
value={value[i]}
|
|
66
|
+
path={path}
|
|
67
|
+
isLast={i < value.length - 1}
|
|
68
|
+
simple
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (value.length > 6)
|
|
74
|
+
children.push(<span key={'rest'} className="text-zinc-500">...</span>);
|
|
75
|
+
|
|
76
|
+
return children;
|
|
77
|
+
}, [value]);
|
|
78
|
+
|
|
79
|
+
useLayoutEffect(() => {
|
|
80
|
+
debug.event.expand(path, expanded);
|
|
81
|
+
}, [expanded]);
|
|
82
|
+
|
|
83
|
+
const handleExpand = (state: boolean) => {
|
|
84
|
+
setExpanded(state);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<Chevron_Toggle expanded={expanded} onToggle={handleExpand} />
|
|
90
|
+
|
|
91
|
+
<span className="text-white" >{`(${value.length}) `}</span>
|
|
92
|
+
{
|
|
93
|
+
expanded ? (
|
|
94
|
+
<>
|
|
95
|
+
<Char_Bracket text="[" />
|
|
96
|
+
|
|
97
|
+
<ul className="pl-4 ml-1 border-l border-l-[#4b4b4b]">
|
|
98
|
+
{children}
|
|
99
|
+
</ul>
|
|
100
|
+
|
|
101
|
+
<Char_Bracket text="]" />
|
|
102
|
+
</>
|
|
103
|
+
) : (
|
|
104
|
+
<div
|
|
105
|
+
className="inline-block cursor-pointer"
|
|
106
|
+
onClick={() => setExpanded(true)}
|
|
107
|
+
>
|
|
108
|
+
<Char_Bracket text="[" />
|
|
109
|
+
{/* <span className="text-zinc-500">...</span> */}
|
|
110
|
+
{collapsedPreview}
|
|
111
|
+
<Char_Bracket text="]" />
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface CompactArrayItemProps {
|
|
120
|
+
value: unknown,
|
|
121
|
+
isLast: boolean,
|
|
122
|
+
path: string[],
|
|
123
|
+
simple?: boolean
|
|
124
|
+
}
|
|
125
|
+
function CompactArrayItem({
|
|
126
|
+
value,
|
|
127
|
+
isLast,
|
|
128
|
+
path,
|
|
129
|
+
simple
|
|
130
|
+
}: CompactArrayItemProps)
|
|
131
|
+
{
|
|
132
|
+
return (
|
|
133
|
+
<>
|
|
134
|
+
{
|
|
135
|
+
!simple
|
|
136
|
+
? <ParseValue value={value} path={path} />
|
|
137
|
+
: <ParseValueSimple value={value} />
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
{isLast && (<Char_Comma />)}
|
|
141
|
+
</>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface ValueFunctionProps {
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
3
|
+
value: Function
|
|
4
|
+
}
|
|
5
|
+
export default function ValueFunction({
|
|
6
|
+
value
|
|
7
|
+
}: ValueFunctionProps) {
|
|
8
|
+
const argsMatch = value.toString().match(/^[^(]*\(\s*([^)]*)\)/);
|
|
9
|
+
let args: string = '';
|
|
10
|
+
|
|
11
|
+
if (argsMatch && argsMatch.length > 1) {
|
|
12
|
+
args = argsMatch[1]!;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
<span className="text-[#f2824a]">
|
|
18
|
+
{'ƒ '}
|
|
19
|
+
</span>
|
|
20
|
+
<span>
|
|
21
|
+
{`${value.name}(${args})`}
|
|
22
|
+
</span>
|
|
23
|
+
</>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { useLayoutEffect, useMemo, useState } from "react";
|
|
2
|
+
import useDebugger from "../DebuggerContext";
|
|
3
|
+
import { entries, keys } from "@hrnec06/util";
|
|
4
|
+
import { Char_Bracket, Char_Colon, Char_Comma, Chevron_Toggle } from "../DebuggerSymbols";
|
|
5
|
+
import ParseValue from "./DebugParser";
|
|
6
|
+
|
|
7
|
+
interface ValueObjectProps {
|
|
8
|
+
value: object,
|
|
9
|
+
path: string[],
|
|
10
|
+
defaultExpanded?: boolean
|
|
11
|
+
}
|
|
12
|
+
export default function ValueObject({
|
|
13
|
+
value,
|
|
14
|
+
path,
|
|
15
|
+
defaultExpanded = false
|
|
16
|
+
}: ValueObjectProps) {
|
|
17
|
+
const debug = useDebugger();
|
|
18
|
+
|
|
19
|
+
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
20
|
+
|
|
21
|
+
const objectEntries = entries(value);
|
|
22
|
+
|
|
23
|
+
const collapsedPreview = useMemo(() => {
|
|
24
|
+
const children: React.ReactNode[] = [];
|
|
25
|
+
const keyList = keys(value);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < Math.min(keyList.length, 6); i++) {
|
|
28
|
+
children.push(
|
|
29
|
+
<React.Fragment key={i}>
|
|
30
|
+
<ValueObjectKey text={keyList[i]!} />
|
|
31
|
+
{i < keyList.length - 1 && <Char_Comma />}
|
|
32
|
+
</React.Fragment>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (keyList.length > 6)
|
|
37
|
+
children.push(<span key={'rest'} className="text-zinc-500">...</span>);
|
|
38
|
+
|
|
39
|
+
return children;
|
|
40
|
+
}, [value]);
|
|
41
|
+
|
|
42
|
+
useLayoutEffect(() => {
|
|
43
|
+
debug.event.expand(path, expanded);
|
|
44
|
+
}, [expanded]);
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
const handleExpand = (state: boolean) => {
|
|
48
|
+
setExpanded(state);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<>
|
|
53
|
+
<Chevron_Toggle expanded={expanded} onToggle={handleExpand} />
|
|
54
|
+
|
|
55
|
+
{
|
|
56
|
+
Object.getPrototypeOf(value) !== Object.prototype && <span>({value.constructor.name}) </span>
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
expanded ? (
|
|
61
|
+
<>
|
|
62
|
+
<Char_Bracket text="{" />
|
|
63
|
+
|
|
64
|
+
<ul className="pl-4 ml-1 border-l border-l-[#4b4b4b]">
|
|
65
|
+
{
|
|
66
|
+
objectEntries.map(([key, value], ix) => {
|
|
67
|
+
return (
|
|
68
|
+
<li key={ix}>
|
|
69
|
+
<ValueObjectKey text={key} />
|
|
70
|
+
<Char_Colon />
|
|
71
|
+
|
|
72
|
+
<ParseValue value={value} path={[...path, `${key}`]} />
|
|
73
|
+
|
|
74
|
+
{ix < objectEntries.length - 1 && (
|
|
75
|
+
<Char_Comma />
|
|
76
|
+
)}
|
|
77
|
+
</li>
|
|
78
|
+
);
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
</ul>
|
|
82
|
+
|
|
83
|
+
<Char_Bracket text="}" />
|
|
84
|
+
</>
|
|
85
|
+
) : (
|
|
86
|
+
<div
|
|
87
|
+
className="inline-block cursor-pointer"
|
|
88
|
+
onClick={() => setExpanded(true)}
|
|
89
|
+
>
|
|
90
|
+
<Char_Bracket text="{" />
|
|
91
|
+
{' '}
|
|
92
|
+
{collapsedPreview}
|
|
93
|
+
{' '}
|
|
94
|
+
<Char_Bracket text="}" />
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
</>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface ValueObjectKeyProps {
|
|
103
|
+
text: string,
|
|
104
|
+
}
|
|
105
|
+
function ValueObjectKey({
|
|
106
|
+
text
|
|
107
|
+
}: ValueObjectKeyProps) {
|
|
108
|
+
return (
|
|
109
|
+
<span className="text-[#9CDCF0]">
|
|
110
|
+
{text}
|
|
111
|
+
</span>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { padString } from "@hrnec06/util"
|
|
2
|
+
|
|
3
|
+
interface ValueStringProps {
|
|
4
|
+
value: string,
|
|
5
|
+
noEncase?: boolean
|
|
6
|
+
}
|
|
7
|
+
export default function ValueString({
|
|
8
|
+
value,
|
|
9
|
+
noEncase = false
|
|
10
|
+
}: ValueStringProps) {
|
|
11
|
+
return (
|
|
12
|
+
<span className="text-[#ce9178]">
|
|
13
|
+
{padString(value, noEncase ? 0 : 1, '"')}
|
|
14
|
+
</span>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Char_Bracket } from "../DebuggerSymbols"
|
|
2
|
+
import ValueKeyword from "./ValueKeyword"
|
|
3
|
+
|
|
4
|
+
interface ValueSymbolProps {
|
|
5
|
+
value: symbol
|
|
6
|
+
}
|
|
7
|
+
export default function ValueSymbol({
|
|
8
|
+
value
|
|
9
|
+
}: ValueSymbolProps) {
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<ValueKeyword value="Symbol" />
|
|
13
|
+
<Char_Bracket text="(" />
|
|
14
|
+
<span>
|
|
15
|
+
{value.description}
|
|
16
|
+
</span>
|
|
17
|
+
<Char_Bracket text=")" />
|
|
18
|
+
</>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
import { useLayoutEffect, useMemo, useState } from "react";
|
|
2
|
-
import useDebugger from "./DebuggerContext";
|
|
3
|
-
import { matchPath } from "./DebuggerLogic";
|
|
4
|
-
import { entries, keys, padString } from "@hrnec06/util";
|
|
5
|
-
import React from "react";
|
|
6
|
-
import { Char_Bracket, Char_Colon, Char_Comma, Chevron_Toggle } from "./DebuggerSymbols";
|
|
7
|
-
|
|
8
|
-
interface ParseValueProps {
|
|
9
|
-
value: unknown,
|
|
10
|
-
path?: string[]
|
|
11
|
-
}
|
|
12
|
-
export default function ParseValue({
|
|
13
|
-
value,
|
|
14
|
-
path = []
|
|
15
|
-
}: ParseValueProps) {
|
|
16
|
-
const debug = useDebugger();
|
|
17
|
-
|
|
18
|
-
switch (typeof value) {
|
|
19
|
-
case 'string': return (<Value_String value={value} />);
|
|
20
|
-
case 'bigint':
|
|
21
|
-
case 'number': return (<Value_Number value={value} />);
|
|
22
|
-
case 'boolean': return (<Value_Boolean value={value} />);
|
|
23
|
-
case 'undefined': return (<Value_Keyword value={"undefined"} />);
|
|
24
|
-
case 'function': return (<Value_Function value={value} />);
|
|
25
|
-
case 'symbol': return (<Value_Symbol value={value} />)
|
|
26
|
-
case 'object': {
|
|
27
|
-
if (value === null)
|
|
28
|
-
return (<Value_Keyword value={"null"} />)
|
|
29
|
-
|
|
30
|
-
const isRootObject = path.length === 0;
|
|
31
|
-
|
|
32
|
-
const shouldBeExpanded = (isRootObject && debug.options.openRoot) || (matchPath(path, debug.paths.open) && !matchPath(path, debug.paths.exclude));
|
|
33
|
-
|
|
34
|
-
if (Array.isArray(value)) {
|
|
35
|
-
return <Value_Array value={value} path={path} defaultExpanded={shouldBeExpanded} />
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return <Value_Object value={value} path={path} defaultExpanded={shouldBeExpanded} />
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface Value_String_Props {
|
|
44
|
-
value: string,
|
|
45
|
-
noEncase?: boolean
|
|
46
|
-
}
|
|
47
|
-
function Value_String({
|
|
48
|
-
value,
|
|
49
|
-
noEncase = false
|
|
50
|
-
}: Value_String_Props) {
|
|
51
|
-
return (
|
|
52
|
-
<span className="text-[#ce9178]">
|
|
53
|
-
{padString(value, noEncase ? 0 : 1, '"')}
|
|
54
|
-
</span>
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
interface Value_Number_Props {
|
|
59
|
-
value: number | bigint
|
|
60
|
-
}
|
|
61
|
-
function Value_Number({
|
|
62
|
-
value
|
|
63
|
-
}: Value_Number_Props) {
|
|
64
|
-
return (
|
|
65
|
-
<span className="text-[#a7ce9b]">
|
|
66
|
-
{value}
|
|
67
|
-
</span>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface Value_Boolean_Props {
|
|
72
|
-
value: boolean
|
|
73
|
-
}
|
|
74
|
-
function Value_Boolean({
|
|
75
|
-
value
|
|
76
|
-
}: Value_Boolean_Props) {
|
|
77
|
-
return <Value_Keyword value={value ? 'true' : 'false'} />
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface Value_Function_Props {
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
82
|
-
value: Function
|
|
83
|
-
}
|
|
84
|
-
function Value_Function({
|
|
85
|
-
value
|
|
86
|
-
}: Value_Function_Props) {
|
|
87
|
-
const argsMatch = value.toString().match(/^[^(]*\(\s*([^)]*)\)/);
|
|
88
|
-
let args: string = '';
|
|
89
|
-
|
|
90
|
-
if (argsMatch && argsMatch.length > 1) {
|
|
91
|
-
args = argsMatch[1]!;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<>
|
|
96
|
-
<span className="text-[#f2824a]">
|
|
97
|
-
{'ƒ '}
|
|
98
|
-
</span>
|
|
99
|
-
<span>
|
|
100
|
-
{`${value.name}(${args})`}
|
|
101
|
-
</span>
|
|
102
|
-
</>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
interface Value_Keyword_Props {
|
|
107
|
-
value: string
|
|
108
|
-
}
|
|
109
|
-
function Value_Keyword({
|
|
110
|
-
value
|
|
111
|
-
}: Value_Keyword_Props) {
|
|
112
|
-
return (
|
|
113
|
-
<span className="text-[#439ccb]">
|
|
114
|
-
{value}
|
|
115
|
-
</span>
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
interface Value_Object_Props {
|
|
120
|
-
value: object,
|
|
121
|
-
path: string[],
|
|
122
|
-
defaultExpanded?: boolean
|
|
123
|
-
}
|
|
124
|
-
function Value_Object({
|
|
125
|
-
value,
|
|
126
|
-
path,
|
|
127
|
-
defaultExpanded = false
|
|
128
|
-
}: Value_Object_Props) {
|
|
129
|
-
const debug = useDebugger();
|
|
130
|
-
|
|
131
|
-
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
132
|
-
|
|
133
|
-
const objectEntries = entries(value);
|
|
134
|
-
|
|
135
|
-
const collapsedPreview = useMemo(() => {
|
|
136
|
-
const children: React.ReactNode[] = [];
|
|
137
|
-
const keyList = keys(value);
|
|
138
|
-
|
|
139
|
-
for (let i = 0; i < Math.min(keyList.length, 6); i++) {
|
|
140
|
-
children.push(
|
|
141
|
-
<React.Fragment key={i}>
|
|
142
|
-
<Value_Object_Key text={keyList[i]!} />
|
|
143
|
-
{i < keyList.length - 1 && <Char_Comma />}
|
|
144
|
-
</React.Fragment>
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (keyList.length > 6)
|
|
149
|
-
children.push(<span key={'rest'} className="text-zinc-500">...</span>);
|
|
150
|
-
|
|
151
|
-
return children;
|
|
152
|
-
}, [value]);
|
|
153
|
-
|
|
154
|
-
useLayoutEffect(() => {
|
|
155
|
-
debug.event.expand(path, expanded);
|
|
156
|
-
}, [expanded]);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const handleExpand = (state: boolean) => {
|
|
160
|
-
setExpanded(state);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<>
|
|
165
|
-
<Chevron_Toggle expanded={expanded} onToggle={handleExpand} />
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
Object.getPrototypeOf(value) !== Object.prototype && <span>({value.constructor.name}) </span>
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
{
|
|
172
|
-
expanded ? (
|
|
173
|
-
<>
|
|
174
|
-
<Char_Bracket text="{" />
|
|
175
|
-
|
|
176
|
-
<ul className="pl-4 ml-1 border-l border-l-primary-400">
|
|
177
|
-
{
|
|
178
|
-
objectEntries.map(([key, value], ix) => {
|
|
179
|
-
return (
|
|
180
|
-
<li key={ix}>
|
|
181
|
-
<Value_Object_Key text={key} />
|
|
182
|
-
<Char_Colon />
|
|
183
|
-
|
|
184
|
-
<ParseValue value={value} path={[...path, `${key}`]} />
|
|
185
|
-
|
|
186
|
-
{ix < objectEntries.length - 1 && (
|
|
187
|
-
<Char_Comma />
|
|
188
|
-
)}
|
|
189
|
-
</li>
|
|
190
|
-
);
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
</ul>
|
|
194
|
-
|
|
195
|
-
<Char_Bracket text="}" />
|
|
196
|
-
</>
|
|
197
|
-
) : (
|
|
198
|
-
<div
|
|
199
|
-
className="inline-block cursor-pointer"
|
|
200
|
-
onClick={() => setExpanded(true)}
|
|
201
|
-
>
|
|
202
|
-
<Char_Bracket text="{" />
|
|
203
|
-
{' '}
|
|
204
|
-
{collapsedPreview}
|
|
205
|
-
{' '}
|
|
206
|
-
<Char_Bracket text="}" />
|
|
207
|
-
</div>
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
</>
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
interface Value_Array_Props {
|
|
215
|
-
value: unknown[],
|
|
216
|
-
path: string[],
|
|
217
|
-
defaultExpanded?: boolean
|
|
218
|
-
}
|
|
219
|
-
function Value_Array({
|
|
220
|
-
value,
|
|
221
|
-
path,
|
|
222
|
-
defaultExpanded = false
|
|
223
|
-
}: Value_Array_Props) {
|
|
224
|
-
const debug = useDebugger();
|
|
225
|
-
|
|
226
|
-
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
227
|
-
|
|
228
|
-
const children = useMemo(() => {
|
|
229
|
-
const children: React.ReactNode[] = [];
|
|
230
|
-
|
|
231
|
-
let ix = 0;
|
|
232
|
-
|
|
233
|
-
while (ix < value.length) {
|
|
234
|
-
const nextTarget = Math.min(ix + debug.options.compactArrays, value.length);
|
|
235
|
-
|
|
236
|
-
children.push(
|
|
237
|
-
<li key={ix}>
|
|
238
|
-
{
|
|
239
|
-
(() => {
|
|
240
|
-
const children: React.ReactNode[] = [];
|
|
241
|
-
|
|
242
|
-
for (;ix < nextTarget; ix++) {
|
|
243
|
-
children.push(
|
|
244
|
-
<React.Fragment key={ix}>
|
|
245
|
-
<ParseValue value={value[ix]} path={[...path, `${ix}`]} />
|
|
246
|
-
{ix < value.length - 1 && (
|
|
247
|
-
<Char_Comma />
|
|
248
|
-
)}
|
|
249
|
-
</React.Fragment>
|
|
250
|
-
)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return children;
|
|
254
|
-
})()
|
|
255
|
-
}
|
|
256
|
-
</li>
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
ix = nextTarget;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return children;
|
|
263
|
-
}, [debug.options.compactArrays, value]);
|
|
264
|
-
|
|
265
|
-
const collapsedPreview = useMemo(() => {
|
|
266
|
-
const children: React.ReactNode[] = [];
|
|
267
|
-
|
|
268
|
-
for (let i = 0; i < Math.min(value.length, 6); i++) {
|
|
269
|
-
children.push(
|
|
270
|
-
<React.Fragment key={i}>
|
|
271
|
-
<ParseValue_ToSimple value={value[i]} />
|
|
272
|
-
|
|
273
|
-
{i < value.length - 1 && <Char_Comma />}
|
|
274
|
-
</React.Fragment>
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (value.length > 6)
|
|
279
|
-
children.push(<span key={'rest'} className="text-zinc-500">...</span>);
|
|
280
|
-
|
|
281
|
-
return children;
|
|
282
|
-
}, [value]);
|
|
283
|
-
|
|
284
|
-
useLayoutEffect(() => {
|
|
285
|
-
debug.event.expand(path, expanded);
|
|
286
|
-
}, [expanded]);
|
|
287
|
-
|
|
288
|
-
const handleExpand = (state: boolean) => {
|
|
289
|
-
setExpanded(state);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return (
|
|
293
|
-
<>
|
|
294
|
-
<Chevron_Toggle expanded={expanded} onToggle={handleExpand} />
|
|
295
|
-
|
|
296
|
-
<span>{`(${value.length}) `}</span>
|
|
297
|
-
{
|
|
298
|
-
expanded ? (
|
|
299
|
-
<>
|
|
300
|
-
<Char_Bracket text="[" />
|
|
301
|
-
|
|
302
|
-
<ul className="pl-4 ml-1 border-l border-l-primary-400">
|
|
303
|
-
{children}
|
|
304
|
-
</ul>
|
|
305
|
-
|
|
306
|
-
<Char_Bracket text="]" />
|
|
307
|
-
</>
|
|
308
|
-
) : (
|
|
309
|
-
<div
|
|
310
|
-
className="inline-block cursor-pointer"
|
|
311
|
-
onClick={() => setExpanded(true)}
|
|
312
|
-
>
|
|
313
|
-
<Char_Bracket text="[" />
|
|
314
|
-
{/* <span className="text-zinc-500">...</span> */}
|
|
315
|
-
{collapsedPreview}
|
|
316
|
-
<Char_Bracket text="]" />
|
|
317
|
-
</div>
|
|
318
|
-
)
|
|
319
|
-
}
|
|
320
|
-
</>
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
interface Value_Object_Key_Props {
|
|
326
|
-
text: string,
|
|
327
|
-
}
|
|
328
|
-
function Value_Object_Key({
|
|
329
|
-
text
|
|
330
|
-
}: Value_Object_Key_Props) {
|
|
331
|
-
return (
|
|
332
|
-
<span className="text-[#9CDCF0]">
|
|
333
|
-
{text}
|
|
334
|
-
</span>
|
|
335
|
-
)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
interface Value_SymbolProps {
|
|
339
|
-
value: symbol
|
|
340
|
-
}
|
|
341
|
-
function Value_Symbol({
|
|
342
|
-
value
|
|
343
|
-
}: Value_SymbolProps) {
|
|
344
|
-
return (
|
|
345
|
-
<>
|
|
346
|
-
<Value_Keyword value="Symbol" />
|
|
347
|
-
<Char_Bracket text="(" />
|
|
348
|
-
<span>
|
|
349
|
-
{value.description}
|
|
350
|
-
</span>
|
|
351
|
-
<Char_Bracket text=")" />
|
|
352
|
-
</>
|
|
353
|
-
)
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
interface ParseValue_ToSimpleProps {
|
|
357
|
-
value: unknown
|
|
358
|
-
}
|
|
359
|
-
function ParseValue_ToSimple({
|
|
360
|
-
value
|
|
361
|
-
}: ParseValue_ToSimpleProps): React.ReactNode {
|
|
362
|
-
const MAX_LENGTH = 16;
|
|
363
|
-
|
|
364
|
-
switch (typeof value) {
|
|
365
|
-
case 'bigint':
|
|
366
|
-
case 'number': {
|
|
367
|
-
const numStr = value.toString();
|
|
368
|
-
|
|
369
|
-
if (numStr.length > MAX_LENGTH)
|
|
370
|
-
return <Value_Keyword value={typeof value} />;
|
|
371
|
-
|
|
372
|
-
return <Value_Number value={value} />
|
|
373
|
-
}
|
|
374
|
-
case 'boolean': return <Value_Boolean value={value} />
|
|
375
|
-
case 'function': return <Value_Function value={value} />
|
|
376
|
-
case 'object': {
|
|
377
|
-
if (value === null)
|
|
378
|
-
return <Value_Keyword value="null" />
|
|
379
|
-
|
|
380
|
-
const className = Object.getPrototypeOf(value) !== Object.prototype ? value.constructor.name : null;
|
|
381
|
-
|
|
382
|
-
if (className === null || className.length > MAX_LENGTH)
|
|
383
|
-
return <Value_Keyword value="object" />
|
|
384
|
-
|
|
385
|
-
return className;
|
|
386
|
-
}
|
|
387
|
-
case 'string': {
|
|
388
|
-
if (value.length > MAX_LENGTH)
|
|
389
|
-
return <Value_String value="string" noEncase />
|
|
390
|
-
|
|
391
|
-
return <Value_String value={value} />;
|
|
392
|
-
}
|
|
393
|
-
case 'symbol': {
|
|
394
|
-
if (!value.description || value.description.length > MAX_LENGTH)
|
|
395
|
-
return <Value_Keyword value="Symbol" />
|
|
396
|
-
|
|
397
|
-
return <Value_Symbol value={value} />
|
|
398
|
-
}
|
|
399
|
-
case 'undefined': return <Value_Keyword value="undefined" />
|
|
400
|
-
}
|
|
401
|
-
}
|