@tanstack/react-query-devtools
Advanced tools
| import * as React from 'react'; | ||
| export declare const Entry: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>; | ||
| export declare const Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>; | ||
| export declare const LabelButton: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "key" | keyof React.ButtonHTMLAttributes<HTMLButtonElement>> & React.RefAttributes<HTMLButtonElement>>; | ||
| export declare const ExpandButton: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "key" | keyof React.ButtonHTMLAttributes<HTMLButtonElement>> & React.RefAttributes<HTMLButtonElement>>; | ||
| export declare const LabelButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>; | ||
| export declare const ExpandButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>; | ||
| export declare const CopyButton: ({ value }: { | ||
| value: unknown; | ||
| }) => JSX.Element; | ||
| }) => React.JSX.Element; | ||
| export declare const Value: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>; | ||
@@ -16,3 +16,3 @@ export declare const SubEntries: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>; | ||
| }; | ||
| export declare const Expander: ({ expanded, style }: ExpanderProps) => JSX.Element; | ||
| export declare const Expander: ({ expanded, style }: ExpanderProps) => React.JSX.Element; | ||
| declare type Entry = { | ||
@@ -22,3 +22,3 @@ label: string; | ||
| declare type RendererProps = { | ||
| handleEntry: (entry: Entry) => JSX.Element; | ||
| handleEntry: (entry: Entry) => React.JSX.Element; | ||
| label?: string; | ||
@@ -44,3 +44,3 @@ value: unknown; | ||
| export declare function chunkArray<T>(array: T[], size: number): T[][]; | ||
| declare type Renderer = (props: RendererProps) => JSX.Element; | ||
| declare type Renderer = (props: RendererProps) => React.JSX.Element; | ||
| export declare const DefaultRenderer: Renderer; | ||
@@ -52,4 +52,4 @@ declare type ExplorerProps = Partial<RendererProps> & { | ||
| }; | ||
| export default function Explorer({ value, defaultExpanded, renderer, pageSize, copyable, ...rest }: ExplorerProps): JSX.Element; | ||
| export default function Explorer({ value, defaultExpanded, renderer, pageSize, copyable, ...rest }: ExplorerProps): React.JSX.Element; | ||
| export {}; | ||
| //# sourceMappingURL=Explorer.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Explorer.esm.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;"} | ||
| {"version":3,"file":"Explorer.esm.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => React.JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => React.JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Explorer.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;;;;;;;;;;;;"} | ||
| {"version":3,"file":"Explorer.js","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => React.JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => React.JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;;;;;;;;;;;;"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Explorer.mjs","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;"} | ||
| {"version":3,"file":"Explorer.mjs","sources":["../../src/Explorer.tsx"],"sourcesContent":["'use client'\nimport * as React from 'react'\n\nimport superjson from 'superjson'\nimport { displayValue, styled } from './utils'\n\nexport const Entry = styled('div', {\n fontFamily: 'Menlo, monospace',\n fontSize: '1em',\n lineHeight: '1.7',\n outline: 'none',\n wordBreak: 'break-word',\n})\n\nexport const Label = styled('span', {\n color: 'white',\n})\n\nexport const LabelButton = styled('button', {\n cursor: 'pointer',\n color: 'white',\n})\n\nexport const ExpandButton = styled('button', {\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n})\n\ntype CopyState = 'NoCopy' | 'SuccessCopy' | 'ErrorCopy'\n\nexport const CopyButton = ({ value }: { value: unknown }) => {\n const [copyState, setCopyState] = React.useState<CopyState>('NoCopy')\n\n return (\n <button\n onClick={\n copyState === 'NoCopy'\n ? () => {\n navigator.clipboard.writeText(superjson.stringify(value)).then(\n () => {\n setCopyState('SuccessCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n (err) => {\n console.error('Failed to copy: ', err)\n setCopyState('ErrorCopy')\n setTimeout(() => {\n setCopyState('NoCopy')\n }, 1500)\n },\n )\n }\n : undefined\n }\n style={{\n cursor: 'pointer',\n color: 'inherit',\n font: 'inherit',\n outline: 'inherit',\n background: 'transparent',\n border: 'none',\n padding: 0,\n }}\n >\n {copyState === 'NoCopy' ? (\n <Copier />\n ) : copyState === 'SuccessCopy' ? (\n <CopiedCopier />\n ) : (\n <ErrorCopier />\n )}\n </button>\n )\n}\n\nexport const Value = styled('span', (_props, theme) => ({\n color: theme.danger,\n}))\n\nexport const SubEntries = styled('div', {\n marginLeft: '.1em',\n paddingLeft: '1em',\n borderLeft: '2px solid rgba(0,0,0,.15)',\n})\n\nexport const Info = styled('span', {\n color: 'grey',\n fontSize: '.7em',\n})\n\ntype ExpanderProps = {\n expanded: boolean\n style?: React.CSSProperties\n}\n\nexport const Expander = ({ expanded, style = {} }: ExpanderProps) => (\n <span\n style={{\n display: 'inline-block',\n transition: 'all .1s ease',\n transform: `rotate(${expanded ? 90 : 0}deg) ${style.transform || ''}`,\n ...style,\n }}\n >\n ▶\n </span>\n)\n\nconst Copier = () => (\n <span\n aria-label=\"Copy object to clipboard\"\n title=\"Copy object to clipboard\"\n style={{\n paddingLeft: '1em',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\">\n <path\n fill=\"currentColor\"\n d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\"\n ></path>\n <path\n fill=\"currentColor\"\n d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\"\n ></path>\n </svg>\n </span>\n)\n\nconst ErrorCopier = () => (\n <span\n aria-label=\"Failed copying to clipboard\"\n title=\"Failed copying to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'flex',\n alignItems: 'center',\n }}\n >\n <svg height=\"12\" viewBox=\"0 0 16 12\" width=\"10\" display=\"block\">\n <path\n fill=\"red\"\n d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\"\n ></path>\n </svg>\n <span\n style={{\n color: 'red',\n fontSize: '12px',\n paddingLeft: '4px',\n position: 'relative',\n top: '2px',\n }}\n >\n See console\n </span>\n </span>\n)\n\nconst CopiedCopier = () => (\n <span\n aria-label=\"Object copied to clipboard\"\n title=\"Object copied to clipboard\"\n style={{\n paddingLeft: '1em',\n display: 'inline-block',\n verticalAlign: 'middle',\n }}\n >\n <svg height=\"16\" viewBox=\"0 0 16 16\" width=\"16\" display=\"block\">\n <path\n fill=\"green\"\n d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\"\n ></path>\n </svg>\n </span>\n)\n\ntype Entry = {\n label: string\n}\n\ntype RendererProps = {\n handleEntry: (entry: Entry) => React.JSX.Element\n label?: string\n value: unknown\n subEntries: Entry[]\n subEntryPages: Entry[][]\n type: string\n expanded: boolean\n copyable: boolean\n toggleExpanded: () => void\n pageSize: number\n}\n\n/**\n * Chunk elements in the array by size\n *\n * when the array cannot be chunked evenly by size, the last chunk will be\n * filled with the remaining elements\n *\n * @example\n * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']]\n */\nexport function chunkArray<T>(array: T[], size: number): T[][] {\n if (size < 1) return []\n let i = 0\n const result: T[][] = []\n while (i < array.length) {\n result.push(array.slice(i, i + size))\n i = i + size\n }\n return result\n}\n\ntype Renderer = (props: RendererProps) => React.JSX.Element\n\nexport const DefaultRenderer: Renderer = ({\n handleEntry,\n label,\n value,\n subEntries = [],\n subEntryPages = [],\n type,\n expanded = false,\n copyable = false,\n toggleExpanded,\n pageSize,\n}) => {\n const [expandedPages, setExpandedPages] = React.useState<number[]>([])\n\n return (\n <Entry key={label}>\n {subEntryPages.length ? (\n <>\n <ExpandButton onClick={() => toggleExpanded()}>\n <Expander expanded={expanded} /> {label}{' '}\n <Info>\n {String(type).toLowerCase() === 'iterable' ? '(Iterable) ' : ''}\n {subEntries.length} {subEntries.length > 1 ? `items` : `item`}\n </Info>\n </ExpandButton>\n {copyable ? <CopyButton value={value} /> : null}\n {expanded ? (\n subEntryPages.length === 1 ? (\n <SubEntries>{subEntries.map(handleEntry)}</SubEntries>\n ) : (\n <SubEntries>\n {subEntryPages.map((entries, index) => (\n <div key={index}>\n <Entry>\n <LabelButton\n onClick={() =>\n setExpandedPages((old) =>\n old.includes(index)\n ? old.filter((d) => d !== index)\n : [...old, index],\n )\n }\n >\n <Expander expanded={expanded} /> [{index * pageSize} ...{' '}\n {index * pageSize + pageSize - 1}]\n </LabelButton>\n {expandedPages.includes(index) ? (\n <SubEntries>{entries.map(handleEntry)}</SubEntries>\n ) : null}\n </Entry>\n </div>\n ))}\n </SubEntries>\n )\n ) : null}\n </>\n ) : (\n <>\n <Label>{label}:</Label> <Value>{displayValue(value)}</Value>\n </>\n )}\n </Entry>\n )\n}\n\ntype ExplorerProps = Partial<RendererProps> & {\n renderer?: Renderer\n defaultExpanded?: true | Record<string, boolean>\n copyable?: boolean\n}\n\ntype Property = {\n defaultExpanded?: boolean | Record<string, boolean>\n label: string\n value: unknown\n}\n\nfunction isIterable(x: any): x is Iterable<unknown> {\n return Symbol.iterator in x\n}\n\nexport default function Explorer({\n value,\n defaultExpanded,\n renderer = DefaultRenderer,\n pageSize = 100,\n copyable = false,\n ...rest\n}: ExplorerProps) {\n const [expanded, setExpanded] = React.useState(Boolean(defaultExpanded))\n const toggleExpanded = React.useCallback(() => setExpanded((old) => !old), [])\n\n let type: string = typeof value\n let subEntries: Property[] = []\n\n const makeProperty = (sub: { label: string; value: unknown }): Property => {\n const subDefaultExpanded =\n defaultExpanded === true\n ? { [sub.label]: true }\n : defaultExpanded?.[sub.label]\n return {\n ...sub,\n defaultExpanded: subDefaultExpanded,\n }\n }\n\n if (Array.isArray(value)) {\n type = 'array'\n subEntries = value.map((d, i) =>\n makeProperty({\n label: i.toString(),\n value: d,\n }),\n )\n } else if (\n value !== null &&\n typeof value === 'object' &&\n isIterable(value) &&\n typeof value[Symbol.iterator] === 'function'\n ) {\n type = 'Iterable'\n subEntries = Array.from(value, (val, i) =>\n makeProperty({\n label: i.toString(),\n value: val,\n }),\n )\n } else if (typeof value === 'object' && value !== null) {\n type = 'object'\n subEntries = Object.entries(value).map(([key, val]) =>\n makeProperty({\n label: key,\n value: val,\n }),\n )\n }\n\n const subEntryPages = chunkArray(subEntries, pageSize)\n\n return renderer({\n handleEntry: (entry) => (\n <Explorer\n key={entry.label}\n value={value}\n renderer={renderer}\n copyable={copyable}\n {...rest}\n {...entry}\n />\n ),\n type,\n subEntries,\n subEntryPages,\n value,\n expanded,\n copyable,\n toggleExpanded,\n pageSize,\n ...rest,\n })\n}\n"],"names":["fontFamily","fontSize","lineHeight","outline","wordBreak","color","cursor","font","background","border","padding","value","navigator","setTimeout","console","marginLeft","paddingLeft","borderLeft","style","display","transition","transform","alignItems","position","top","verticalAlign","result","subEntries","subEntryPages","expanded","copyable","pageSize","renderer","defaultExpanded","type","label","handleEntry"],"mappings":";;;;;;;AAOEA;AACAC;AACAC;AACAC;AACAC;AALiC;;AASjCC;AADkC;;AAKlCC;AACAD;AAF0C;;AAM1CC;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAP2C;AAYtC;AAAsBC;AAAF;;;AAKrB;AAGQC;;AAGIC;;;;AAKAC;;AAEAD;;;;AAKL;AAGP;AACEP;AACAD;AACAE;AACAJ;AACAK;AACAC;AACAC;AAPK;AAtBT;AAyCH;AAEM;;AAAiD;;AAKtDK;AACAC;AACAC;AAHsC;;AAOtCZ;AACAJ;AAFiC;AAU5B;;AAA8BiB;AAAZ;AAErB;AACEC;AACAC;AACAC;;AAHK;AADT;;AAYF;AAEI;AACA;AACA;AACEL;AADK;AAHT;AAOO;AAAY;AAAoB;AAArC;AAEI;AACA;AAFF;AAKE;AACA;AAFF;;AAQN;AAEI;AACA;AACA;AACEA;AACAG;AACAG;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;AAMA;AACEjB;AACAJ;AACAe;AACAO;AACAC;AALK;AADT;;AAcJ;AAEI;AACA;AACA;AACER;AACAG;AACAM;AAHK;AAHT;AASO;AAAY;AAAoB;AAAW;AAAhD;AAEI;AACA;AAFF;;AAyBN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACL;;;;AAGA;AACEC;;AAED;;AACD;AACD;AAIM;;;;AAILC;AACAC;;AAEAC;AACAC;;AAEAC;AAVwC;;AAcxC;AACS;AAAP;;AAGM;AACY;AAAV;AAMsB;AAAZ;AAOC;AAAL;AAGM;AADF;AASY;;AAoBjC;;AAcD;AACE;AACD;;AAEc;;;AAGbC;AACAD;AACAD;;AAL+B;AAQ/B;AACA;;;;;AAME;;;;AAMEG;;;;AAIJ;AACEC;;AAGIC;AACAxB;AAFW;;AAWfuB;AACAP;AAEIQ;AACAxB;AAFW;;AAMfuB;AACAP;AAEIQ;AACAxB;AAFW;AAKhB;;AAED;AAEA;AACEyB;;AAGI;AACA;AACA;;;;;;;;;;;AANU;AAqBjB;;"} |
@@ -1,3 +0,3 @@ | ||
| /// <reference types="react" /> | ||
| export default function Logo(props: any): JSX.Element; | ||
| import * as React from 'react'; | ||
| export default function Logo(props: any): React.JSX.Element; | ||
| //# sourceMappingURL=Logo.d.ts.map |
@@ -1,5 +0,5 @@ | ||
| /// <reference types="react" /> | ||
| import * as React from 'react'; | ||
| export default function ScreenReader({ text }: { | ||
| text: string; | ||
| }): JSX.Element; | ||
| }): React.JSX.Element; | ||
| //# sourceMappingURL=screenreader.d.ts.map |
| /// <reference types="react" /> | ||
| export declare const Panel: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>; | ||
| export declare const ActiveQueryPanel: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>; | ||
| export declare const Button: import("react").ForwardRefExoticComponent<Pick<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "key" | keyof import("react").ButtonHTMLAttributes<HTMLButtonElement>> & import("react").RefAttributes<HTMLButtonElement>>; | ||
| export declare const Button: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>; | ||
| export declare const QueryKeys: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>; | ||
| export declare const QueryKey: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>; | ||
| export declare const Code: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>; | ||
| export declare const Input: import("react").ForwardRefExoticComponent<Pick<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof import("react").InputHTMLAttributes<HTMLInputElement>> & import("react").RefAttributes<HTMLInputElement>>; | ||
| export declare const Select: import("react").ForwardRefExoticComponent<Pick<import("react").DetailedHTMLProps<import("react").SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, "key" | keyof import("react").SelectHTMLAttributes<HTMLSelectElement>> & import("react").RefAttributes<HTMLSelectElement>>; | ||
| export declare const Input: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & import("react").RefAttributes<HTMLInputElement>>; | ||
| export declare const Select: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, "ref"> & import("react").RefAttributes<HTMLSelectElement>>; | ||
| //# sourceMappingURL=styledComponents.d.ts.map |
@@ -21,3 +21,3 @@ import * as React from 'react'; | ||
| } | ||
| export declare function ThemeProvider({ theme, ...rest }: ProviderProps): JSX.Element; | ||
| export declare function ThemeProvider({ theme, ...rest }: ProviderProps): React.JSX.Element; | ||
| export declare function useTheme(): { | ||
@@ -24,0 +24,0 @@ readonly background: "#0b1521"; |
+11
-9
| { | ||
| "name": "@tanstack/react-query-devtools", | ||
| "version": "4.41.0", | ||
| "version": "4.42.0", | ||
| "description": "Developer tools to interact with and visualize the TanStack/react-query cache", | ||
@@ -45,11 +45,13 @@ "author": "tannerlinsley", | ||
| "devDependencies": { | ||
| "@types/react": "^18.0.14", | ||
| "@types/react-dom": "^18.0.5", | ||
| "@types/react": "^19.1.9", | ||
| "@types/react-dom": "^19.1.7", | ||
| "@types/use-sync-external-store": "^0.0.3", | ||
| "react": "^18.2.0", | ||
| "react": "^19.1.1", | ||
| "react-17": "npm:react@^17.0.2", | ||
| "react-dom": "^18.2.0", | ||
| "react-18": "npm:react@^18.2.0", | ||
| "react-dom": "^19.1.1", | ||
| "react-dom-17": "npm:react-dom@^17.0.2", | ||
| "react-dom-18": "npm:react-dom@^18.2.0", | ||
| "react-error-boundary": "^3.1.4", | ||
| "@tanstack/react-query": "4.41.0" | ||
| "@tanstack/react-query": "4.42.0" | ||
| }, | ||
@@ -62,7 +64,7 @@ "dependencies": { | ||
| "peerDependencies": { | ||
| "react": "^16.8.0 || ^17.0.0 || ^18.0.0", | ||
| "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", | ||
| "@tanstack/react-query": "^4.41.0" | ||
| "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", | ||
| "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", | ||
| "@tanstack/react-query": "^4.42.0" | ||
| }, | ||
| "scripts": {} | ||
| } |
@@ -934,3 +934,3 @@ import * as React from 'react' | ||
| function Parent({ children }: { children: React.ReactElement }) { | ||
| function Parent({ children }: { children: React.ReactNode }) { | ||
| return ( | ||
@@ -937,0 +937,0 @@ <div data-testid={parentElementTestid} style={parentPaddings}> |
+2
-2
@@ -191,3 +191,3 @@ 'use client' | ||
| type RendererProps = { | ||
| handleEntry: (entry: Entry) => JSX.Element | ||
| handleEntry: (entry: Entry) => React.JSX.Element | ||
| label?: string | ||
@@ -224,3 +224,3 @@ value: unknown | ||
| type Renderer = (props: RendererProps) => JSX.Element | ||
| type Renderer = (props: RendererProps) => React.JSX.Element | ||
@@ -227,0 +227,0 @@ export const DefaultRenderer: Renderer = ({ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
1581138
011
22.22%16622
-0.02%