diff --git a/examples/basic/package.json b/examples/basic/package.json index adbff8cf..26cf29d4 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -14,9 +14,9 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@textea/dev-kit": "^0.12.16", - "@types/node": "^18.7.17", - "@types/react": "^18.0.19", + "@textea/dev-kit": "^0.13.4", + "@types/node": "^18.7.18", + "@types/react": "^18.0.20", "@types/react-dom": "^18.0.6", "next-transpile-modules": "^9.0.0", "typescript": "^4.8.3" diff --git a/examples/basic/pages/index.tsx b/examples/basic/pages/index.tsx index 8336e0b6..70942604 100644 --- a/examples/basic/pages/index.tsx +++ b/examples/basic/pages/index.tsx @@ -36,6 +36,11 @@ const loopArray = [ loopArray[1] = loopArray const longArray = Array.from({ length: 1000 }).map((_, i) => i) +const map = new Map() +map.set('foo', 1) +map.set('goo', 'hello') + +const set = new Set([1, 2, 3]) const example = { loopObject, @@ -48,6 +53,8 @@ const example = { [1, 2], [3, 4] ], + map, + set, float: 114.514, undefined, object: { diff --git a/package.json b/package.json index 4e83f10c..8de95585 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,8 @@ "dependencies": { "@emotion/react": "^11.10.4", "@emotion/styled": "^11.10.4", - "@mui/icons-material": "^5.10.3", - "@mui/material": "^5.10.5", + "@mui/icons-material": "^5.10.6", + "@mui/material": "^5.10.6", "copy-to-clipboard": "^3.3.2", "zustand": "^4.1.1" }, @@ -74,12 +74,12 @@ "@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-node-resolve": "^14.1.0", - "@swc/core": "^1.3.1", + "@swc/core": "^1.3.2", "@textea/dev-kit": "^0.13.4", "@types/node": "^18.7.18", "@types/react": "^18.0.20", "@types/react-dom": "^18.0.6", - "@types/web": "^0.0.72", + "@types/web": "^0.0.73", "husky": "^8.0.1", "lint-staged": "^13.0.3", "pinst": "^3.0.0", diff --git a/src/components/DataKeyPair.tsx b/src/components/DataKeyPair.tsx index 244be6d7..b1a087bb 100644 --- a/src/components/DataKeyPair.tsx +++ b/src/components/DataKeyPair.tsx @@ -19,6 +19,7 @@ import { DataBox } from './mui/DataBox' export type DataKeyPairProps = { value: unknown nestedIndex?: number + editable?: boolean path: (string | number)[] } @@ -28,7 +29,7 @@ const IconBox = styled(props => )` ` as typeof Box export const DataKeyPair: React.FC = (props) => { - const { value, path, nestedIndex } = props + const { value, path, nestedIndex, editable = true } = props const [tempValue, setTempValue] = useState(value) const depth = path.length const key = path[depth - 1] @@ -124,7 +125,7 @@ export const DataKeyPair: React.FC = (props) => { } {/* todo: support edit object */} - {Editor && + {(Editor && editable) && ( { @@ -142,14 +143,15 @@ export const DataKeyPair: React.FC = (props) => { } ) - }, [Editor, copied, copy, editing, onChange, path, tempValue, value]) + }, [Editor, copied, copy, editable, editing, onChange, path, tempValue, value]) const expandable = PreComponent && PostComponent const KeyRenderer = useJsonViewerStore(store => store.keyRenderer) return ( setHover(path, nestedIndex), [setHover, path, nestedIndex]) + useCallback(() => setHover(path, nestedIndex), + [setHover, path, nestedIndex]) } > = (props) => { {(isHover && expandable && inspect) && actionIcons} { - editing + (editing && editable) ? (Editor && ) : (Component) ? diff --git a/src/components/DataTypes/Object.tsx b/src/components/DataTypes/Object.tsx index f7a05e6c..0bd96d1d 100644 --- a/src/components/DataTypes/Object.tsx +++ b/src/components/DataTypes/Object.tsx @@ -14,12 +14,29 @@ const arrayLb = '[' const objectRb = '}' const arrayRb = ']' +function inspectMetadata (value: object) { + let length + let name = '' + if (Array.isArray(value)) { + length = value.length + } else if (value instanceof Map || value instanceof Set) { + name = value[Symbol.toStringTag] + length = value.size + } else { + length = Object.keys(value).length + } + if (Object.prototype.hasOwnProperty.call(value, Symbol.toStringTag)) { + name = (value as any)[Symbol.toStringTag] + } + return `${length} Items${name ? ` (${name})` : ''}` +} + export const PreObjectType: React.FC> = (props) => { const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04) const textColor = useTextColor() const isArray = useMemo(() => Array.isArray(props.value), [props.value]) const sizeOfValue = useMemo( - () => props.inspect ? `${Object.keys(props.value).length} Items` : '', + () => props.inspect ? inspectMetadata(props.value) : '', [props.inspect, props.value] ) const isTrap = useIsCycleReference(props.path, props.value) @@ -61,7 +78,7 @@ export const PostObjectType: React.FC> = (props) => { const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04) const isArray = useMemo(() => Array.isArray(props.value), [props.value]) const sizeOfValue = useMemo( - () => !props.inspect ? `${Object.keys(props.value).length} Items` : '', + () => !props.inspect ? inspectMetadata(props.value) : '', [props.inspect, props.value] ) return ( @@ -81,6 +98,10 @@ export const PostObjectType: React.FC> = (props) => { ) } +function getIterator (value: any): value is Iterable { + return typeof value?.[Symbol.iterator] === 'function' +} + export const ObjectType: React.FC> = (props) => { const keyColor = useTextColor() const groupArraysAfterLength = useJsonViewerStore( @@ -94,6 +115,32 @@ export const ObjectType: React.FC> = (props) => { return null } const value: unknown[] | object = props.value + const iterator = getIterator(value) + // Array also has iterator, we skip it and treat it as an array as normal. + if (iterator && !Array.isArray(value)) { + const elements = [] + if (value instanceof Map) { + let _count = 0 + for (const item of value) { + const [key, value] = item + elements.push( + + ) + _count++ + } + } else { + let count = 0 + for (const item of value) { + elements.push( + + ) + count++ + } + } + return elements + } if (Array.isArray(value)) { // unknown[] if (value.length <= groupArraysAfterLength) { @@ -169,7 +216,13 @@ export const ObjectType: React.FC> = (props) => { } return elements } - }, [props.inspect, props.value, props.path, groupArraysAfterLength, displayLength, keyColor]) + }, [ + props.inspect, + props.value, + props.path, + groupArraysAfterLength, + displayLength, + keyColor]) return (