LCOV - code coverage report
Current view: top level - dashql-app/src/ui/json - json_view.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 97.6 % 82 80
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : import * as styles from './json_view.module.css';
       3              : 
       4              : import { JsonViewerState, JsonViewerStateProvider } from './json_view_state.js';
       5              : import { JsonValue } from './json_value.js';
       6              : 
       7              : export * from './json_view_state.js';
       8              : export * from './json_nested_state.js';
       9              : export * from './json_tool_state.js';
      10              : export * from './json_arrow_symbol.js';
      11              : 
      12              : export type ShouldExpandNodeInitially = (
      13              :     isExpanded: boolean,
      14              :     props: { keyName?: string | number; value?: object; parentValue?: object; keyPath: (number | string)[]; level: number },
      15              : ) => boolean;
      16              : 
      17              : /// How the viewer renders values.
      18              : /// `json` shows the JSON syntax, `explorer` shows an object explorer without brackets, quotes or colons.
      19              : export type JsonViewVariant = 'json' | 'explorer';
      20              : 
      21              : export interface JsonViewProps
      22              :     extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
      23              :     /// This property contains your input JSON
      24              :     value: object;
      25              :     /// Render the JSON syntax or an object explorer @default 'json'
      26              :     variant?: JsonViewVariant;
      27              :     /// Define the root node name. @default undefined
      28              :     keyName?: string | number;
      29              :     /// Whether sort keys through `String.prototype.localeCompare()` @default false
      30              :     objectSortKeys?: boolean | ((keyA: string, keyB: string, valueA: object, valueB: object) => number);
      31              :     /// Set the indent-width for nested objects @default 15
      32              :     indentWidth?: number;
      33              :     /// Render arrays incrementally in pages of this size. Set to `0` to render all items. @default 0
      34              :     arrayPageSize?: number;
      35              :     /// When set to `true`, `objects` and `arrays` are labeled with size @default true
      36              :     displayObjectSize?: boolean;
      37              :     /// The user can copy objects and arrays to clipboard by clicking on the clipboard icon. @default true
      38              :     enableClipboard?: boolean;
      39              :     ///
      40              :     /// When set to true, all nodes will be collapsed by default. Use an integer value to collapse at a specific depth. @default false
      41              :     /// collapsed takes precedence over shouldExpandNodeInitially.
      42              :     /// @see {@link shouldExpandNodeInitially} for more details on how the initial expansion works.
      43              :     ///
      44              :     collapsed?: boolean | number;
      45              :     ///
      46              :     /// Determines whether the node should be expanded on the first render, or you can use collapsed to control the level of expansion (by default, the root is expanded).
      47              :     /// If both collapsed and shouldExpandNodeInitially are set, the value of collapsed takes precedence.
      48              :     /// @see {@link collapsed} for more details on how this works.
      49              :     ///
      50              :     shouldExpandNodeInitially?: ShouldExpandNodeInitially;
      51              :     /// Whether to highlight updates. @default true
      52              :     highlightUpdates?: boolean;
      53              :     /// Shorten long JSON strings, Set to `0` to disable this feature @default 30
      54              :     shortenTextAfterLength?: number;
      55              :     /// When the text exceeds the length, `...` will be displayed. Currently, this `...` can be customized. @default "..."
      56              :     stringEllipsis?: number;
      57              :     /// Callback function for when a treeNode is expanded or collapsed
      58              :     onExpand?: (props: { expand: boolean; value?: object; keyName?: string | number }) => void;
      59              :     /// Fires event when you copy
      60              :     onCopied?: (text: string, value?: object) => void;
      61              :     /// Transform the text before copying to clipboard
      62              :     beforeCopy?: (
      63              :         copyText: string,
      64              :         keyName?: string | number,
      65              :         value?: object,
      66              :         parentValue?: object,
      67              :         expandKey?: string,
      68              :         keyPath?: (number | string)[],
      69              :     ) => string;
      70              : }
      71              : 
      72              : type JsonViewComponent = React.FC<React.PropsWithRef<JsonViewProps>>;
      73              : 
      74            1 : export const AlwaysExpand: ShouldExpandNodeInitially = () => true;
      75            1 : export const AlwaysCollapse = () => false;
      76              : 
      77            1 : export const JsonView: JsonViewComponent = React.memo(React.forwardRef<HTMLDivElement, JsonViewProps>((props, ref) => {
      78            1 :     const {
      79            1 :         value,
      80            1 :         variant,
      81            1 :         keyName: _keyName,
      82            1 :         objectSortKeys,
      83            1 :         indentWidth,
      84            1 :         arrayPageSize,
      85            1 :         displayObjectSize,
      86            1 :         enableClipboard,
      87            1 :         collapsed,
      88            1 :         shouldExpandNodeInitially,
      89            1 :         highlightUpdates: _highlightUpdates,
      90            1 :         shortenTextAfterLength,
      91            1 :         stringEllipsis,
      92            1 :         onExpand,
      93            1 :         onCopied,
      94            1 :         beforeCopy,
      95            1 :         children,
      96            1 :         className,
      97            1 :         ...containerProps
      98            1 :     } = props;
      99              :     // Collapse nested values below a numeric depth, unless the caller decides explicitly
     100            1 :     const expandNodeInitially = React.useMemo<ShouldExpandNodeInitially>(() => {
     101            1 :         if (collapsed === true) {
     102            0 :             return AlwaysCollapse;
     103            1 :         } else if (shouldExpandNodeInitially) {
     104            0 :             return shouldExpandNodeInitially;
     105            1 :         } else if (typeof collapsed === 'number') {
     106            1 :             return (_isExpanded, { level }) => level <= collapsed;
     107              :         } else {
     108            1 :             return AlwaysExpand;
     109              :         }
     110            1 :     }, [collapsed, shouldExpandNodeInitially]);
     111              :     // Memoize the state to not re-render the whole tree when the parent re-renders
     112            1 :     const initialState: JsonViewerState = React.useMemo(() => ({
     113            1 :         value,
     114            1 :         variant: variant ?? 'json',
     115            1 :         objectSortKeys,
     116            1 :         indentWidth: indentWidth ?? 15,
     117            1 :         arrayPageSize: arrayPageSize ?? 0,
     118            1 :         shouldExpandNodeInitially: expandNodeInitially,
     119            1 :         displayObjectSize: displayObjectSize ?? true,
     120            1 :         collapsed: collapsed ?? false,
     121            1 :         enableClipboard,
     122            1 :         shortenTextAfterLength: shortenTextAfterLength ?? 30,
     123            1 :         stringEllipsis,
     124            1 :         onCopied,
     125            1 :         onExpand,
     126            1 :         beforeCopy,
     127            1 :     }), [
     128            1 :         value,
     129            1 :         variant,
     130            1 :         objectSortKeys,
     131            1 :         indentWidth,
     132            1 :         arrayPageSize,
     133            1 :         expandNodeInitially,
     134            1 :         displayObjectSize,
     135            1 :         collapsed,
     136            1 :         enableClipboard,
     137            1 :         shortenTextAfterLength,
     138            1 :         stringEllipsis,
     139            1 :         onCopied,
     140            1 :         onExpand,
     141            1 :         beforeCopy,
     142            1 :     ]);
     143            1 :     return (
     144            1 :         <JsonViewerStateProvider initialState={initialState}>
     145            1 :             <div
     146            1 :                 {...containerProps}
     147            1 :                 ref={ref}
     148            1 :                 className={`${styles.viewer}${variant === 'explorer' ? ` ${styles.viewer_explorer}` : ''}${className ? ` ${className}` : ''}`}
     149            1 :                 data-electron-drag-region="false"
     150              :             >
     151            1 :                 <JsonValue
     152            1 :                     value={value}
     153            1 :                     initialValue={value}
     154            1 :                     level={0}
     155            1 :                     keyName={undefined}
     156            1 :                     keyPath={[]}
     157            1 :                 />
     158            1 :                 {children}
     159            1 :             </div>
     160            1 :         </JsonViewerStateProvider>
     161              :     );
     162            1 : })) as unknown as JsonViewComponent;
     163              : 
     164              : export default JsonView;
        

Generated by: LCOV version 2.0-1