From c6594df7919014495b4ea9817d390387ea4bc1db Mon Sep 17 00:00:00 2001 From: Liam Tait Date: Wed, 16 Mar 2022 01:02:54 +1300 Subject: [PATCH 1/5] refactor(devtools): add types to Explorer (#2949) * refactor(devtools): add types to Explorer Add types to Explorer component with as minimal functional changes as possible while still getting type safety 2742 * remove unused set param from explorer toggle * Wrap Explorer toggle with useCallback * Rename Explorer toggle to toggleExpanded * Remove unused path * Move subEntryPages definition next to usage * Set type to be a string instead of string union * Remove unused depth prop * Move chunkArrays to own tested function * set handleEntry as required * Add LabelButton for accesibility * fix test * Remove shadowing * Set subEntries as empty array by default * Add type for property * Convert handleEntry function to react component with entry props * Use unknown for value * Set RenderProps to required where possible * Add required attributes to Explorer tests --- src/devtools/Explorer.tsx | 153 +++++++++++++++++---------- src/devtools/tests/Explorer.test.tsx | 57 ++++++++++ 2 files changed, 156 insertions(+), 54 deletions(-) create mode 100644 src/devtools/tests/Explorer.test.tsx diff --git a/src/devtools/Explorer.tsx b/src/devtools/Explorer.tsx index b409bc2ce0..7c97ae6f94 100644 --- a/src/devtools/Explorer.tsx +++ b/src/devtools/Explorer.tsx @@ -1,5 +1,3 @@ -// @ts-nocheck - import React from 'react' import { styled } from './utils' @@ -13,11 +11,15 @@ export const Entry = styled('div', { }) export const Label = styled('span', { + color: 'white', +}) + +export const LabelButton = styled('button', { cursor: 'pointer', color: 'white', }) -export const Value = styled('span', (props, theme) => ({ +export const Value = styled('span', (_props, theme) => ({ color: theme.danger, })) @@ -32,7 +34,12 @@ export const Info = styled('span', { fontSize: '.7em', }) -export const Expander = ({ expanded, style = {}, ...rest }) => ( +type ExpanderProps = { + expanded: boolean + style?: React.CSSProperties +} + +export const Expander = ({ expanded, style = {} }: ExpanderProps) => ( ( ) -const DefaultRenderer = ({ - handleEntry, +type Entry = { + label: string +} + +type RendererProps = { + HandleEntry: HandleEntryComponent + label?: string + value: unknown + subEntries: Entry[] + subEntryPages: Entry[][] + type: string + expanded: boolean + toggleExpanded: () => void + pageSize: number +} + +/** + * Chunk elements in the array by size + * + * when the array cannot be chunked evenly by size, the last chunk will be + * filled with the remaining elements + * + * @example + * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']] + */ +export function chunkArray(array: T[], size: number): T[][] { + if (size < 1) return [] + let i = 0 + const result: T[][] = [] + while (i < array.length) { + result.push(array.slice(i, i + size)) + i = i + size + } + return result +} + +type Renderer = (props: RendererProps) => JSX.Element + +export const DefaultRenderer: Renderer = ({ + HandleEntry, label, value, - // path, - subEntries, - subEntryPages, + subEntries = [], + subEntryPages = [], type, - // depth, - expanded, - toggle, + expanded = false, + toggleExpanded, pageSize, }) => { - const [expandedPages, setExpandedPages] = React.useState([]) + const [expandedPages, setExpandedPages] = React.useState([]) return ( {subEntryPages?.length ? ( <> -