Skip to content

⬅️ Back to Table of Contents

📄 DataRenderer

📊 Analysis Summary

Metric Count
🔧 Functions 6
📦 Imports 19
💠 JSX Elements 25
📐 Interfaces 2

📚 Table of Contents

🛠️ File Location:

📂 packages/website/src/components/ast/DataRenderer.tsx

📦 Imports

Name Source
clsx clsx
useCallback react
useEffect react
useMemo react
React react
OnHoverNodeFn ./types
ParentNodeType ./types
useBool ../../hooks/useBool
Tooltip ../inputs/Tooltip
styles ./ASTViewer.module.css
HiddenItem ./HiddenItem
PropertyName ./PropertyName
PropertyValue ./PropertyValue
filterProperties ./utils
getNodeType ./utils
getRange ./utils
getTooltipLabel ./utils
getTypeName ./utils
isRecord ./utils

JSX Elements

Component Type Props Children
div element className={clsx( styles.expand, !expanded && styles.open, isActive && styles.... {field && ( <PropertyName className={styles.propName} onClick={toggleExpanded...
PropertyName component className={styles.propName}, onClick={toggleExpanded}, onHover={onHoverItem},... none
span element none text: ":"
PropertyName component className={styles.tokenName}, onClick={toggleExpanded}, onHover={onHoverItem}... none
span element none none
span element none {openBracket}
div element className={styles.subList} {data.map((dataElement, index) => ( <DataRender field={dataElement[0]} key={d...
DataRender component field={dataElement[0]}, key={dataElement[0]}, lastElement={index === lastInde... none
HiddenItem component isArray={openBracket === '['}, level={level}, value={data} none
span element none {closeBracket}
span element none text: ","
RenderExpandableObject component closeBracket="}", data={computed.value}, nodeType={computed.nodeType}, openBr... none
RenderExpandableObject component closeBracket="]", data={Object.entries(props.value)}, openBracket="[" none
RenderExpandableObject component closeBracket=")", data={Object.entries(props.value)}, openBracket="(" none
div element className={styles.valueBody}, role="listitem" {field && {field}: }, {tooltip ? ( <...
span element className={styles.propName} {field}, text: ":"
Tooltip component hover={true}, position="right", text={tooltip}
PropertyValue component value={value} none
PropertyValue component value={value} none
span element className={styles.label} text: ","
JsonArray component value={value} none
JsonObject component value={value} none
JsonIterable component typeName="Map", value={value} none
JsonIterable component typeName="Set", value={value} none
JsonPrimitiveValue component none none

Functions

DataRender(props: JsonRenderProps<unknown>): React.JSX.Element

Parameters:

  • props JsonRenderProps<unknown>

Returns: React.JSX.Element

Calls:

  • Array.isArray
  • isRecord (from ./utils)
Code
export default function DataRender(
  props: JsonRenderProps<unknown>,
): React.JSX.Element {
  const value = props.value;

  if (Array.isArray(value)) {
    return <JsonArray {...props} value={value} />;
  }

  if (isRecord(value)) {
    return <JsonObject {...props} value={value} />;
  }

  if (value instanceof Map) {
    return <JsonIterable typeName="Map" {...props} value={value} />;
  }

  if (value instanceof Set) {
    return <JsonIterable typeName="Set" {...props} value={value} />;
  }

  return <JsonPrimitiveValue {...props} />;
}

RenderExpandableObject({ closeBracket, data, field, la…: ExpandableRenderProps): React.JSX.Element

Parameters:

  • { closeBracket, data, field, lastElement, level, nodeType, onHover, openBracket, selectedPath, showTokens, typeName, value, } ExpandableRenderProps

Returns: React.JSX.Element

Calls:

  • useBool (from ../../hooks/useBool)
  • selectedPath?.startsWith
  • useMemo (from react)
  • useCallback (from react)
  • onHover
  • getRange (from ./utils)
  • useEffect (from react)
  • setExpanded
  • clsx (from clsx)
  • data.map
Code
function RenderExpandableObject({
  closeBracket,
  data,
  field,
  lastElement,
  level,
  nodeType,
  onHover,
  openBracket,
  selectedPath,
  showTokens,
  typeName,
  value,
}: ExpandableRenderProps): React.JSX.Element {
  const [expanded, toggleExpanded, setExpanded] = useBool(
    () => level === 'ast' || !!selectedPath?.startsWith(level),
  );

  const isActive = useMemo(
    () => level !== 'ast' && selectedPath === level,
    [selectedPath, level],
  );

  const onHoverItem = useCallback(
    (hover: boolean): void => {
      if (onHover) {
        if (hover) {
          onHover(getRange(value, nodeType));
        } else {
          onHover(undefined);
        }
      }
    },
    [onHover, value, nodeType],
  );

  useEffect(() => {
    const shouldOpen = !!selectedPath?.startsWith(level);
    if (shouldOpen) {
      setExpanded(current => current || shouldOpen);
    }
  }, [selectedPath, level, setExpanded]);

  const lastIndex = data.length - 1;

  return (
    <div
      className={clsx(
        styles.expand,
        !expanded && styles.open,
        isActive && styles.selected,
      )}
      data-level={level}
      role="list"
    >
      {field && (
        <PropertyName
          className={styles.propName}
          onClick={toggleExpanded}
          onHover={onHoverItem}
          value={field}
        />
      )}
      {field && <span>: </span>}
      {typeName && (
        <PropertyName
          className={styles.tokenName}
          onClick={toggleExpanded}
          onHover={onHoverItem}
          value={typeName}
        />
      )}
      {typeName && <span> </span>}
      <span>{openBracket}</span>

      {expanded ? (
        <div className={styles.subList}>
          {data.map((dataElement, index) => (
            <DataRender
              field={dataElement[0]}
              key={dataElement[0]}
              lastElement={index === lastIndex}
              level={`${level}.${dataElement[0]}`}
              nodeType={nodeType}
              onHover={onHover}
              selectedPath={selectedPath}
              showTokens={showTokens}
              value={dataElement[1]}
            />
          ))}
        </div>
      ) : (
        <HiddenItem isArray={openBracket === '['} level={level} value={data} />
      )}

      <span>{closeBracket}</span>
      {!lastElement && <span>,</span>}
    </div>
  );
}

JsonObject(props: JsonRenderProps<Record<string, unknown>>): React.JSX.Element

Parameters:

  • props JsonRenderProps<Record<string, unknown>>

Returns: React.JSX.Element

Calls:

  • useMemo (from react)
  • getNodeType (from ./utils)
  • getTypeName (from ./utils)
  • Object.entries(props.value).filter
  • filterProperties (from ./utils)
Code
function JsonObject(
  props: JsonRenderProps<Record<string, unknown>>,
): React.JSX.Element {
  const computed = useMemo(() => {
    const nodeType = getNodeType(props.value);
    return {
      nodeType,
      typeName: getTypeName(props.value, nodeType),
      value: Object.entries(props.value).filter(item =>
        filterProperties(item[0], item[1], nodeType, props.showTokens),
      ),
    };
  }, [props.value, props.showTokens]);

  return (
    <RenderExpandableObject
      {...props}
      closeBracket="}"
      data={computed.value}
      nodeType={computed.nodeType}
      openBracket="{"
      typeName={computed.typeName}
    />
  );
}

JsonArray(props: JsonRenderProps<unknown[]>): React.JSX.Element

Parameters:

  • props JsonRenderProps<unknown[]>

Returns: React.JSX.Element

Calls:

  • Object.entries
Code
function JsonArray(props: JsonRenderProps<unknown[]>): React.JSX.Element {
  return (
    <RenderExpandableObject
      {...props}
      closeBracket="]"
      data={Object.entries(props.value)}
      openBracket="["
    />
  );
}

JsonIterable(props: JsonRenderProps<Iterable<unknown>>): React.JSX.Element

Parameters:

  • props JsonRenderProps<Iterable<unknown>>

Returns: React.JSX.Element

Calls:

  • Object.entries
Code
function JsonIterable(
  props: JsonRenderProps<Iterable<unknown>>,
): React.JSX.Element {
  return (
    <RenderExpandableObject
      {...props}
      closeBracket=")"
      data={Object.entries(props.value)}
      openBracket="("
    />
  );
}

JsonPrimitiveValue({ field, lastElement, nodeType,…: JsonRenderProps<unknown>): React.JSX.Element

Parameters:

  • { field, lastElement, nodeType, value, } JsonRenderProps<unknown>

Returns: React.JSX.Element

Calls:

  • useMemo (from react)
  • getTooltipLabel (from ./utils)
Code
function JsonPrimitiveValue({
  field,
  lastElement,
  nodeType,
  value,
}: JsonRenderProps<unknown>): React.JSX.Element {
  const tooltip = useMemo(() => {
    if (field && nodeType) {
      return getTooltipLabel(value, field, nodeType);
    }
    return undefined;
  }, [value, field, nodeType]);

  return (
    <div className={styles.valueBody} role="listitem">
      {field && <span className={styles.propName}>{field}: </span>}
      {tooltip ? (
        <Tooltip hover={true} position="right" text={tooltip}>
          <PropertyValue value={value} />
        </Tooltip>
      ) : (
        <PropertyValue value={value} />
      )}
      {!lastElement && <span className={styles.label}>,</span>}
    </div>
  );
}

Interfaces

JsonRenderProps<T>

Interface Code
export interface JsonRenderProps<T> {
  readonly field?: string;
  readonly lastElement?: boolean;
  readonly level: string;
  readonly nodeType?: ParentNodeType;
  readonly onHover?: OnHoverNodeFn;
  readonly selectedPath?: string;
  readonly showTokens?: boolean;
  readonly typeName?: string;
  readonly value: T;
}

Properties

Name Type Optional Description
field string ✓ not shown
lastElement boolean ✓ not shown
level string ✗ not shown
nodeType ParentNodeType ✓ not shown
onHover OnHoverNodeFn ✓ not shown
selectedPath string ✓ not shown
showTokens boolean ✓ not shown
typeName string ✓ not shown
value T ✗ not shown

ExpandableRenderProps

Interface Code
export interface ExpandableRenderProps extends JsonRenderProps<
  object | unknown[]
> {
  readonly closeBracket: string;
  readonly data: [string, unknown][];
  readonly openBracket: string;
}

Properties

Name Type Optional Description
closeBracket string ✗ not shown
data [string, unknown][] ✗ not shown
openBracket string ✗ not shown

Generated by Syntax Scribe