import { useState, useRef, createElement, useEffect } from 'react';

const isBoolean = data => {
  return typeof data === 'boolean' || data instanceof Boolean;
};
const isNumber = data => {
  return typeof data === 'number' || data instanceof Number;
};
const isBigInt = data => {
  return typeof data === 'bigint' || data instanceof BigInt;
};
const isDate = data => {
  return !!data && data instanceof Date;
};
const isString = data => {
  return typeof data === 'string' || data instanceof String;
};
const isArray = data => {
  return Array.isArray(data);
};
const isObject = data => {
  return data instanceof Object && data !== null;
};

function useBool(initialValueCreator) {
  const [value, setValue] = useState(initialValueCreator());
  const tooggle = () => setValue(currentValue => !currentValue);
  return [value, tooggle, setValue];
}
let componentId = 1;
const generateNextId = () => componentId++;
function useComponentId() {
  const componentId = useRef();
  if (componentId.current === undefined) {
    componentId.current = `:jsnvw:${generateNextId()}:`;
  }
  return componentId.current;
}

function ExpandableObject(_ref) {
  let {
    field,
    value,
    data,
    lastElement,
    openBracket,
    closeBracket,
    level,
    style,
    shouldExpandNode
  } = _ref;
  const shouldExpandNodeCalledRef = useRef(false);
  const [expanded, toggleExpanded, setExpanded] = useBool(() => shouldExpandNode(level, value, field));
  useEffect(() => {
    if (!shouldExpandNodeCalledRef.current) {
      shouldExpandNodeCalledRef.current = true;
    } else {
      setExpanded(shouldExpandNode(level, value, field));
    }
  }, [shouldExpandNode]);
  const expanderIconStyle = expanded ? style.collapseIcon : style.expandIcon;
  const ariaLabel = expanded ? 'collapse JSON' : 'expand JSON';
  const contentsId = useComponentId();
  const childLevel = level + 1;
  const lastIndex = data.length - 1;
  const onKeyDown = e => {
    if (e.key === ' ') {
      toggleExpanded();
    }
  };
  return /*#__PURE__*/createElement("div", {
    className: style.basicChildStyle,
    role: 'list'
  }, /*#__PURE__*/createElement("span", {
    className: expanderIconStyle,
    onClick: toggleExpanded,
    onKeyDown: onKeyDown,
    role: 'button',
    tabIndex: 0,
    "aria-label": ariaLabel,
    "aria-expanded": expanded,
    "aria-controls": expanded ? contentsId : undefined
  }), field && /*#__PURE__*/createElement("span", {
    className: style.label
  }, field, ":"), /*#__PURE__*/createElement("span", {
    className: style.punctuation
  }, openBracket), expanded ? /*#__PURE__*/createElement("div", {
    id: contentsId
  }, data.map((dataElement, index) => /*#__PURE__*/createElement(DataRender, {
    key: dataElement[0] || index,
    field: dataElement[0],
    value: dataElement[1],
    style: style,
    lastElement: index === lastIndex,
    level: childLevel,
    shouldExpandNode: shouldExpandNode
  }))) : /*#__PURE__*/createElement("span", {
    className: style.collapsedContent,
    onClick: toggleExpanded,
    onKeyDown: onKeyDown,
    role: 'button',
    tabIndex: -1,
    "aria-hidden": true,
    "aria-label": ariaLabel,
    "aria-expanded": expanded
  }), /*#__PURE__*/createElement("span", {
    className: style.punctuation
  }, closeBracket), !lastElement && /*#__PURE__*/createElement("span", {
    className: style.punctuation
  }, ","));
}
function JsonObject(_ref2) {
  let {
    field,
    value,
    style,
    lastElement,
    shouldExpandNode,
    level
  } = _ref2;
  return ExpandableObject({
    field,
    value,
    lastElement: lastElement || false,
    level,
    openBracket: '{',
    closeBracket: '}',
    style,
    shouldExpandNode,
    data: Object.keys(value).map(key => [key, value[key]])
  });
}
function JsonArray(_ref3) {
  let {
    field,
    value,
    style,
    lastElement,
    level,
    shouldExpandNode
  } = _ref3;
  return ExpandableObject({
    field,
    value,
    lastElement: lastElement || false,
    level,
    openBracket: '[',
    closeBracket: ']',
    style,
    shouldExpandNode,
    data: value.map(element => [undefined, element])
  });
}
function JsonPrimitiveValue(_ref4) {
  let {
    field,
    value,
    style,
    lastElement
  } = _ref4;
  let stringValue = value;
  let valueStyle = style.otherValue;
  if (value === null) {
    stringValue = 'null';
    valueStyle = style.nullValue;
  } else if (value === undefined) {
    stringValue = 'undefined';
    valueStyle = style.undefinedValue;
  } else if (isString(value)) {
    stringValue = `"${value}"`;
    valueStyle = style.stringValue;
  } else if (isBoolean(value)) {
    stringValue = value ? 'true' : 'false';
    valueStyle = style.booleanValue;
  } else if (isNumber(value)) {
    stringValue = value.toString();
    valueStyle = style.numberValue;
  } else if (isBigInt(value)) {
    stringValue = `${value.toString()}n`;
    valueStyle = style.numberValue;
  } else if (isDate(value)) {
    stringValue = value.toISOString();
  } else {
    stringValue = value.toString();
  }
  if (field === '') {
    field = '""';
  }
  return /*#__PURE__*/createElement("div", {
    className: style.basicChildStyle,
    role: 'listitem'
  }, field && /*#__PURE__*/createElement("span", {
    className: style.label
  }, field, ":"), /*#__PURE__*/createElement("span", {
    className: valueStyle
  }, stringValue), !lastElement && /*#__PURE__*/createElement("span", {
    className: style.punctuation
  }, ","));
}
function DataRender(props) {
  const value = props.value;
  if (isArray(value)) {
    return /*#__PURE__*/createElement(JsonArray, Object.assign({}, props));
  }
  if (isObject(value) && !isDate(value)) {
    return /*#__PURE__*/createElement(JsonObject, Object.assign({}, props));
  }
  return /*#__PURE__*/createElement(JsonPrimitiveValue, Object.assign({}, props));
}

var styles = {"container-base":"_GzYRV","punctuation-base":"_3eOF8","pointer":"_1MFti","expander-base":"_f10Tu _1MFti","expand-icon":"_1UmXx","collapse-icon":"_1LId0","collapsed-content-base":"_1pNG9 _1MFti","container-light":"_2IvMF _GzYRV","basic-element-style":"_2bkNM","label-light":"_1MGIk","punctuation-light":"_3uHL6 _3eOF8","value-null-light":"_2T6PJ","value-undefined-light":"_1Gho6","value-string-light":"_vGjyY","value-number-light":"_1bQdo","value-boolean-light":"_3zQKs","value-other-light":"_1xvuR","collapse-icon-light":"_oLqym _f10Tu _1MFti _1LId0","expand-icon-light":"_2AXVT _f10Tu _1MFti _1UmXx","collapsed-content-light":"_2KJWg _1pNG9 _1MFti","container-dark":"_11RoI _GzYRV","expand-icon-dark":"_17H2C _f10Tu _1MFti _1UmXx","collapse-icon-dark":"_3QHg2 _f10Tu _1MFti _1LId0","collapsed-content-dark":"_3fDAz _1pNG9 _1MFti","label-dark":"_2bSDX","punctuation-dark":"_gsbQL _3eOF8","value-null-dark":"_LaAZe","value-undefined-dark":"_GTKgm","value-string-dark":"_Chy1W","value-number-dark":"_2bveF","value-boolean-dark":"_2vRm-","value-other-dark":"_1prJR"};

const defaultStyles = {
  container: styles['container-light'],
  basicChildStyle: styles['basic-element-style'],
  label: styles['label-light'],
  nullValue: styles['value-null-light'],
  undefinedValue: styles['value-undefined-light'],
  stringValue: styles['value-string-light'],
  booleanValue: styles['value-boolean-light'],
  numberValue: styles['value-number-light'],
  otherValue: styles['value-other-light'],
  punctuation: styles['punctuation-light'],
  collapseIcon: styles['collapse-icon-light'],
  expandIcon: styles['expand-icon-light'],
  collapsedContent: styles['collapsed-content-light']
};
const darkStyles = {
  container: styles['container-dark'],
  basicChildStyle: styles['basic-element-style'],
  label: styles['label-dark'],
  nullValue: styles['value-null-dark'],
  undefinedValue: styles['value-undefined-dark'],
  stringValue: styles['value-string-dark'],
  booleanValue: styles['value-boolean-dark'],
  numberValue: styles['value-number-dark'],
  otherValue: styles['value-other-dark'],
  punctuation: styles['punctuation-dark'],
  collapseIcon: styles['collapse-icon-dark'],
  expandIcon: styles['expand-icon-dark'],
  collapsedContent: styles['collapsed-content-dark']
};
const allExpanded = () => true;
const collapseAllNested = level => level < 1;
const JsonView = _ref => {
  let {
    data,
    style = defaultStyles,
    shouldExpandNode = allExpanded
  } = _ref;
  return /*#__PURE__*/createElement("div", {
    className: style.container
  }, /*#__PURE__*/createElement(DataRender, {
    value: data,
    style: style,
    lastElement: true,
    level: 0,
    shouldExpandNode: shouldExpandNode
  }));
};

export { JsonView, allExpanded, collapseAllNested, darkStyles, defaultStyles };
//# sourceMappingURL=index.modern.js.map
