Skip to content

Commit

Permalink
feat: support groupArraysAfterLength (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
himself65 authored Sep 17, 2022
1 parent 28cc881 commit 6568d91
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 34 deletions.
24 changes: 23 additions & 1 deletion examples/basic/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ const example = {
string: 'this is a string',
integer: 42,
array: [19, 19, 810, 'test', NaN],
nestedArray: [
[1, 2],
[3, 4]
],
float: 114.514,
undefined,
object: {
Expand All @@ -30,6 +34,7 @@ const example = {

const IndexPage: React.FC = () => {
const [indent, setIndent] = useState(2)
const [groupArraysAfterLength, setGroupArraysAfterLength] = useState(100)
const [src, setSrc] = useState(() => example)
useEffect(() => {
const loop = () => {
Expand Down Expand Up @@ -57,13 +62,30 @@ const IndexPage: React.FC = () => {
}
}
/>
<TextField
value={groupArraysAfterLength}
type='number'
onChange={
event => {
const groupArraysAfterLength = parseInt(event.target.value)
if (groupArraysAfterLength > -1 && groupArraysAfterLength < 500) {
setGroupArraysAfterLength(groupArraysAfterLength)
}
}
}
/>
<JsonViewer
value={src}
indentWidth={indent}
groupArraysAfterLength={groupArraysAfterLength}
onChange={
useCallback<JsonViewerOnChange>(
(path, oldValue, newValue) => {
setSrc(src => applyValue(src, path, newValue))
setSrc(src => {
const newSrc = applyValue(src, path, newValue)
console.log(newSrc, newSrc === src)
return src
})
}, []
)
}
Expand Down
27 changes: 18 additions & 9 deletions src/components/DataKeyPair.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import { DataBox } from './mui/DataBox'

export type DataKeyPairProps = {
value: unknown
path: string[]
nested?: boolean
path: (string | number)[]
}

const IconBox = styled(props => <Box {...props} component='span'/>)`
Expand All @@ -42,17 +43,18 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
const keyColor = useTextColor()
const numberKeyColor = useJsonViewerStore(
store => store.colorNamespace.base0C)
const { Component, PreComponent, PostComponent, Editor } = useTypeComponents(value)
const { Component, PreComponent, PostComponent, Editor } = useTypeComponents(
value)
const rootName = useJsonViewerStore(store => store.rootName)
const isRoot = useJsonViewerStore(store => store.value) === value
const isNumberKey = Number.isInteger(Number(key))
const displayKey = isRoot ? rootName : key
const downstreamProps: DataItemProps = {
const downstreamProps: DataItemProps = useMemo(() => ({
path,
inspect,
setInspect,
value
}
}), [inspect, path, value])
const actionIcons = useMemo(() => {
if (editing) {
return (
Expand Down Expand Up @@ -151,12 +153,19 @@ export const DataKeyPair: React.FC<DataKeyPairProps> = (props) => {
}, [])
}
>
{isNumberKey
? <Box component='span'
style={{ color: numberKeyColor }}>{displayKey}</Box>
: <>&quot;{displayKey}&quot;</>
{
!props.nested && (
isNumberKey
? <Box component='span'
style={{ color: numberKeyColor }}>{displayKey}</Box>
: <>&quot;{displayKey}&quot;</>
)
}
{
!props.nested && (
<DataBox sx={{ mx: 0.5 }}>:</DataBox>
)
}
<DataBox sx={{ mx: 0.5 }}>:</DataBox>
{PreComponent && <PreComponent {...downstreamProps}/>}
{(isHover && expandable && inspect) && actionIcons}
</DataBox>
Expand Down
113 changes: 113 additions & 0 deletions src/components/DataTypes/Array.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { Box } from '@mui/material'
import React, { useMemo } from 'react'

import { useTextColor } from '../../hooks/useColor'
import { useJsonViewerStore } from '../../stores/JsonViewerStore'
import type { DataItemProps } from '../../type'
import { DataKeyPair } from '../DataKeyPair'

const arrayLb = '['
const arrayRb = ']'

export const PreArrayType: React.FC<DataItemProps<unknown[]>> = (props) => {
const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04)
const sizeOfValue = useMemo(
() => props.inspect ? `${Object.keys(props.value).length} Items` : '',
[props.inspect, props.value]
)
return (
<Box
component='span' className='data-array-start'
sx={{
letterSpacing: 0.5
}}
>
{arrayLb}
<Box
component='span'
sx={{
pl: 0.5,
fontStyle: 'italic',
color: metadataColor
}}
>
{sizeOfValue}
</Box>
</Box>
)
}

export const PostArrayType: React.FC<DataItemProps<unknown[]>> = (props) => {
const metadataColor = useJsonViewerStore(store => store.colorNamespace.base04)
const sizeOfValue = useMemo(
() => !props.inspect ? `${Object.keys(props.value).length} Items` : '',
[props.inspect, props.value]
)
return (
<Box component='span' className='data-array-end'>
{arrayRb}
<Box
component='span'
sx={{
pl: 0.5,
fontStyle: 'italic',
color: metadataColor
}}
>
{sizeOfValue}
</Box>
</Box>
)
}

export const ArrayType: React.FC<DataItemProps<unknown[]>> = (props) => {
const keyColor = useTextColor()
const groupArraysAfterLength = useJsonViewerStore(store => store.groupArraysAfterLength)
const elements = useMemo(() => {
if (props.value.length <= groupArraysAfterLength) {
return props.value.map((value, index) => {
const path = [...props.path, index]
return (
<DataKeyPair key={index} path={path} value={value}/>
)
})
}
const value = props.value.reduce<unknown[][]>((array, value, index) => {
const target = Math.floor(index / groupArraysAfterLength)
if (array[target]) {
array[target].push(value)
} else {
array[target] = [value]
}
return array
}, [])
console.log('value', value)

return value.map((list, index) => {
const path = [...props.path]
return (
<DataKeyPair key={index} path={path} value={list} nested/>
)
})
}, [props.path, props.value, groupArraysAfterLength])
return (
<Box
className='data-array'
sx={{
display: props.inspect ? 'block' : 'inline-block',
pl: props.inspect ? 2 : 0,
color: keyColor
}}
>
{
props.inspect
? elements
: (
<Box component='span' className='data-array-body'>
...
</Box>
)
}
</Box>
)
}
29 changes: 17 additions & 12 deletions src/components/DataTypes/Object.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import { useJsonViewerStore } from '../../stores/JsonViewerStore'
import type { DataItemProps } from '../../type'
import { DataKeyPair } from '../DataKeyPair'

const lb = '{'
const rb = '}'
const objectLb = '{'
const arrayLb = '['
const objectRb = '}'
const arrayRb = ']'

export const PreObjectType: React.FC<DataItemProps<object>> = (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, props.value]
Expand All @@ -22,7 +25,7 @@ export const PreObjectType: React.FC<DataItemProps<object>> = (props) => {
letterSpacing: 0.5
}}
>
{lb}
{isArray ? arrayLb : objectLb}
<Box
component='span'
sx={{
Expand All @@ -39,13 +42,14 @@ export const PreObjectType: React.FC<DataItemProps<object>> = (props) => {

export const PostObjectType: React.FC<DataItemProps<object>> = (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, props.value]
)
return (
<Box component='span' className='data-object-end'>
{rb}
{isArray ? arrayRb : objectRb}
<Box
component='span'
sx={{
Expand All @@ -62,6 +66,14 @@ export const PostObjectType: React.FC<DataItemProps<object>> = (props) => {

export const ObjectType: React.FC<DataItemProps<object>> = (props) => {
const keyColor = useTextColor()
const elements = useMemo(() => (
Object.entries(props.value).map(([key, value]) => {
const path = [...props.path, key]
return (
<DataKeyPair key={key} path={path} value={value}/>
)
})
), [props.path, props.value])
return (
<Box
className='data-object'
Expand All @@ -73,14 +85,7 @@ export const ObjectType: React.FC<DataItemProps<object>> = (props) => {
>
{
props.inspect
? (
Object.entries(props.value).map(([key, value]) => {
const path = [...props.path, key]
return (
<DataKeyPair key={key} path={path} value={value}/>
)
})
)
? elements
: (
<Box component='span' className='data-object-body'>
...
Expand Down
7 changes: 4 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { applyValue } from './utils'

export { applyValue }

export type JsonViewerOnChange = <U = unknown>(path: string[], oldValue: U, newValue: U) => void
export type JsonViewerOnChange = <U = unknown>(path: (string | number)[], oldValue: U, newValue: U) => void

const JsonViewerInner: React.FC<JsonViewerProps> = (props) => {
const api = useJsonViewerStoreApi()
Expand All @@ -26,9 +26,10 @@ const JsonViewerInner: React.FC<JsonViewerProps> = (props) => {
value: props.value,
indentWidth: props.indentWidth,
defaultCollapsed: props.defaultCollapsed,
onChange: props.onChange
onChange: props.onChange,
groupArraysAfterLength: props.groupArraysAfterLength
}))
}, [api, props.defaultCollapsed, props.indentWidth, props.onChange, props.value])
}, [api, props.defaultCollapsed, props.groupArraysAfterLength, props.indentWidth, props.onChange, props.value])

const value = useJsonViewerStore(store => store.value)
const setHover = useJsonViewerStore(store => store.setHover)
Expand Down
6 changes: 4 additions & 2 deletions src/stores/JsonViewerStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export const darkNamespace: ColorNamespace = {
}

export type JsonViewerState = {
hoverPath: string[] | null
hoverPath: (string | number)[] | null
groupArraysAfterLength: number
defaultCollapsed: number | boolean
colorNamespace: ColorNamespace
expanded: string[]
Expand All @@ -72,7 +73,7 @@ export type JsonViewerState = {
}

export type JsonViewerActions = {
setHover: (path: string[] | null) => void
setHover: (path: (string | number)[] | null) => void
}

// todo
Expand All @@ -81,6 +82,7 @@ export const createJsonViewerStore = () =>
combine<JsonViewerState, JsonViewerActions>(
{
hoverPath: null,
groupArraysAfterLength: 100,
rootName: 'root',
defaultCollapsed: false,
colorNamespace: defaultColorNamespace,
Expand Down
14 changes: 14 additions & 0 deletions src/stores/typeRegistry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { Box } from '@mui/material'
import { DevelopmentError } from '@textea/dev-kit/utils'
import React, { useMemo } from 'react'

import {
ArrayType,
PostArrayType,
PreArrayType
} from '../components/DataTypes/Array'
import { createEasyType } from '../components/DataTypes/createEasyType'
import {
FunctionType, PostFunctionType,
Expand Down Expand Up @@ -200,6 +205,15 @@ registerType<number>(
}
)

registerType<unknown[]>(
{
is: (value): value is unknown[] => Array.isArray(value),
Component: ArrayType,
PreComponent: PreArrayType,
PostComponent: PostArrayType
}
)

// fallback for all data like 'object'
registerType<object>(
{
Expand Down
Loading

0 comments on commit 6568d91

Please sign in to comment.