Skip to content

Commit 06c886c

Browse files
authored
feat: support inspect Map and Set (#31)
1 parent 498efe2 commit 06c886c

File tree

6 files changed

+194
-187
lines changed

6 files changed

+194
-187
lines changed

examples/basic/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
"react-dom": "^18.2.0"
1515
},
1616
"devDependencies": {
17-
"@textea/dev-kit": "^0.12.16",
18-
"@types/node": "^18.7.17",
19-
"@types/react": "^18.0.19",
17+
"@textea/dev-kit": "^0.13.4",
18+
"@types/node": "^18.7.18",
19+
"@types/react": "^18.0.20",
2020
"@types/react-dom": "^18.0.6",
2121
"next-transpile-modules": "^9.0.0",
2222
"typescript": "^4.8.3"

examples/basic/pages/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ const loopArray = [
3636
loopArray[1] = loopArray
3737

3838
const longArray = Array.from({ length: 1000 }).map((_, i) => i)
39+
const map = new Map<string, any>()
40+
map.set('foo', 1)
41+
map.set('goo', 'hello')
42+
43+
const set = new Set([1, 2, 3])
3944

4045
const example = {
4146
loopObject,
@@ -48,6 +53,8 @@ const example = {
4853
[1, 2],
4954
[3, 4]
5055
],
56+
map,
57+
set,
5158
float: 114.514,
5259
undefined,
5360
object: {

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
"dependencies": {
5656
"@emotion/react": "^11.10.4",
5757
"@emotion/styled": "^11.10.4",
58-
"@mui/icons-material": "^5.10.3",
59-
"@mui/material": "^5.10.5",
58+
"@mui/icons-material": "^5.10.6",
59+
"@mui/material": "^5.10.6",
6060
"copy-to-clipboard": "^3.3.2",
6161
"zustand": "^4.1.1"
6262
},
@@ -74,12 +74,12 @@
7474
"@rollup/plugin-alias": "^3.1.9",
7575
"@rollup/plugin-commonjs": "^22.0.2",
7676
"@rollup/plugin-node-resolve": "^14.1.0",
77-
"@swc/core": "^1.3.1",
77+
"@swc/core": "^1.3.2",
7878
"@textea/dev-kit": "^0.13.4",
7979
"@types/node": "^18.7.18",
8080
"@types/react": "^18.0.20",
8181
"@types/react-dom": "^18.0.6",
82-
"@types/web": "^0.0.72",
82+
"@types/web": "^0.0.73",
8383
"husky": "^8.0.1",
8484
"lint-staged": "^13.0.3",
8585
"pinst": "^3.0.0",

src/components/DataKeyPair.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { DataBox } from './mui/DataBox'
1919
export type DataKeyPairProps = {
2020
value: unknown
2121
nestedIndex?: number
22+
editable?: boolean
2223
path: (string | number)[]
2324
}
2425

@@ -28,7 +29,7 @@ const IconBox = styled(props => <Box {...props} component='span'/>)`
2829
` as typeof Box
2930

3031
export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
31-
const { value, path, nestedIndex } = props
32+
const { value, path, nestedIndex, editable = true } = props
3233
const [tempValue, setTempValue] = useState(value)
3334
const depth = path.length
3435
const key = path[depth - 1]
@@ -124,7 +125,7 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
124125
}
125126
</IconBox>
126127
{/* todo: support edit object */}
127-
{Editor &&
128+
{(Editor && editable) &&
128129
(
129130
<IconBox
130131
onClick={event => {
@@ -142,14 +143,15 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
142143
}
143144
</>
144145
)
145-
}, [Editor, copied, copy, editing, onChange, path, tempValue, value])
146+
}, [Editor, copied, copy, editable, editing, onChange, path, tempValue, value])
146147

147148
const expandable = PreComponent && PostComponent
148149
const KeyRenderer = useJsonViewerStore(store => store.keyRenderer)
149150
return (
150151
<Box className='data-key-pair'
151152
onMouseEnter={
152-
useCallback(() => setHover(path, nestedIndex), [setHover, path, nestedIndex])
153+
useCallback(() => setHover(path, nestedIndex),
154+
[setHover, path, nestedIndex])
153155
}
154156
>
155157
<DataBox
@@ -189,7 +191,7 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
189191
{(isHover && expandable && inspect) && actionIcons}
190192
</DataBox>
191193
{
192-
editing
194+
(editing && editable)
193195
? (Editor && <Editor value={tempValue} setValue={setTempValue}/>)
194196
: (Component)
195197
? <Component {...downstreamProps} />

src/components/DataTypes/Object.tsx

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,29 @@ const arrayLb = '['
1414
const objectRb = '}'
1515
const arrayRb = ']'
1616

17+
function inspectMetadata (value: object) {
18+
let length
19+
let name = ''
20+
if (Array.isArray(value)) {
21+
length = value.length
22+
} else if (value instanceof Map || value instanceof Set) {
23+
name = value[Symbol.toStringTag]
24+
length = value.size
25+
} else {
26+
length = Object.keys(value).length
27+
}
28+
if (Object.prototype.hasOwnProperty.call(value, Symbol.toStringTag)) {
29+
name = (value as any)[Symbol.toStringTag]
30+
}
31+
return `${length} Items${name ? ` (${name})` : ''}`
32+
}
33+
1734
export const PreObjectType: React.FC<DataItemProps<object>> = (props) => {
1835
const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04)
1936
const textColor = useTextColor()
2037
const isArray = useMemo(() => Array.isArray(props.value), [props.value])
2138
const sizeOfValue = useMemo(
22-
() => props.inspect ? `${Object.keys(props.value).length} Items` : '',
39+
() => props.inspect ? inspectMetadata(props.value) : '',
2340
[props.inspect, props.value]
2441
)
2542
const isTrap = useIsCycleReference(props.path, props.value)
@@ -61,7 +78,7 @@ export const PostObjectType: React.FC<DataItemProps<object>> = (props) => {
6178
const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04)
6279
const isArray = useMemo(() => Array.isArray(props.value), [props.value])
6380
const sizeOfValue = useMemo(
64-
() => !props.inspect ? `${Object.keys(props.value).length} Items` : '',
81+
() => !props.inspect ? inspectMetadata(props.value) : '',
6582
[props.inspect, props.value]
6683
)
6784
return (
@@ -81,6 +98,10 @@ export const PostObjectType: React.FC<DataItemProps<object>> = (props) => {
8198
)
8299
}
83100

101+
function getIterator (value: any): value is Iterable<unknown> {
102+
return typeof value?.[Symbol.iterator] === 'function'
103+
}
104+
84105
export const ObjectType: React.FC<DataItemProps<object>> = (props) => {
85106
const keyColor = useTextColor()
86107
const groupArraysAfterLength = useJsonViewerStore(
@@ -94,6 +115,32 @@ export const ObjectType: React.FC<DataItemProps<object>> = (props) => {
94115
return null
95116
}
96117
const value: unknown[] | object = props.value
118+
const iterator = getIterator(value)
119+
// Array also has iterator, we skip it and treat it as an array as normal.
120+
if (iterator && !Array.isArray(value)) {
121+
const elements = []
122+
if (value instanceof Map) {
123+
let _count = 0
124+
for (const item of value) {
125+
const [key, value] = item
126+
elements.push(
127+
<DataKeyPair key={key} path={[...props.path, key]} value={value}
128+
editable={false}/>
129+
)
130+
_count++
131+
}
132+
} else {
133+
let count = 0
134+
for (const item of value) {
135+
elements.push(
136+
<DataKeyPair key={count} path={[...props.path, `iterator:${count}`]}
137+
value={item} nestedIndex={count} editable={false}/>
138+
)
139+
count++
140+
}
141+
}
142+
return elements
143+
}
97144
if (Array.isArray(value)) {
98145
// unknown[]
99146
if (value.length <= groupArraysAfterLength) {
@@ -169,7 +216,13 @@ export const ObjectType: React.FC<DataItemProps<object>> = (props) => {
169216
}
170217
return elements
171218
}
172-
}, [props.inspect, props.value, props.path, groupArraysAfterLength, displayLength, keyColor])
219+
}, [
220+
props.inspect,
221+
props.value,
222+
props.path,
223+
groupArraysAfterLength,
224+
displayLength,
225+
keyColor])
173226
return (
174227
<Box
175228
className='data-object'

0 commit comments

Comments
 (0)