Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 2x 2x 6x 6x 5x 6x 7x 7x 7x | import {useEffect, useState} from 'react';
/** Humanize a camelCase / snake_case field name for display. */
export function humanize(key: string): string {
return key
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
.replace(/[_-]+/g, ' ')
.replace(/\b\w/g, c => c.toUpperCase());
}
/**
* Resolve a viewer's content: prefer the `data` prop, else the `fetch` result,
* else the leaf `node` itself. `fetch` is called once and its result cached.
*/
export function useViewerContent(
node: Record<string, unknown>,
fetch: ((params?: Record<string, unknown>) => Promise<unknown>) | undefined,
data: unknown,
): unknown {
const [fetched, setFetched] = useState<unknown>(undefined);
useEffect(() => {
Eif (!fetch || data !== undefined) return;
let cancelled = false;
void fetch().then(result => {
if (!cancelled) setFetched(result);
});
return () => {
cancelled = true;
};
}, [data, fetch]);
return data !== undefined ? data : (fetched ?? node);
}
export const viewerRowStyle = {
display: 'flex',
gap: '0.5rem',
padding: '0.25rem 0',
borderBottom: '1px solid var(--surface-border)',
} as const;
export const viewerLabelStyle = {
fontWeight: 600,
minWidth: '10rem',
color: 'var(--text-color-secondary)',
} as const;
export const viewerValueStyle = {wordBreak: 'break-all'} as const;
|