import { jsx, Fragment } from "react/jsx-runtime";
import { nestLists, LIST_NEST_MODE_HTML, isPortableTextToolkitList, isPortableTextListItemBlock, isPortableTextToolkitSpan, isPortableTextBlock, isPortableTextToolkitTextNode, spanToPlainText, buildMarksTree } from "@portabletext/toolkit";
import { toPlainText } from "@portabletext/toolkit";
import { useMemo } from "react";
const defaultLists = {
  number: ({ children }) => /* @__PURE__ */ jsx("ol", { children }),
  bullet: ({ children }) => /* @__PURE__ */ jsx("ul", { children })
}, DefaultListItem = ({ children }) => /* @__PURE__ */ jsx("li", { children }), link = ({ children, value }) => /* @__PURE__ */ jsx("a", { href: value == null ? void 0 : value.href, children }), underlineStyle = { textDecoration: "underline" }, defaultMarks = {
  em: ({ children }) => /* @__PURE__ */ jsx("em", { children }),
  strong: ({ children }) => /* @__PURE__ */ jsx("strong", { children }),
  code: ({ children }) => /* @__PURE__ */ jsx("code", { children }),
  underline: ({ children }) => /* @__PURE__ */ jsx("span", { style: underlineStyle, children }),
  "strike-through": ({ children }) => /* @__PURE__ */ jsx("del", { children }),
  link
}, getTemplate = (type, prop) => `[@portabletext/react] Unknown ${type}, specify a component for it in the \`components.${prop}\` prop`, unknownTypeWarning = (typeName) => getTemplate(`block type "${typeName}"`, "types"), unknownMarkWarning = (markType) => getTemplate(`mark type "${markType}"`, "marks"), unknownBlockStyleWarning = (blockStyle) => getTemplate(`block style "${blockStyle}"`, "block"), unknownListStyleWarning = (listStyle) => getTemplate(`list style "${listStyle}"`, "list"), unknownListItemStyleWarning = (listStyle) => getTemplate(`list item style "${listStyle}"`, "listItem");
function printWarning(message) {
  console.warn(message);
}
const hidden = { display: "none" }, DefaultUnknownType = ({
  value,
  isInline
}) => {
  const warning = unknownTypeWarning(value._type);
  return isInline ? /* @__PURE__ */ jsx("span", { style: hidden, children: warning }) : /* @__PURE__ */ jsx("div", { style: hidden, children: warning });
}, DefaultUnknownMark = ({
  markType,
  children
}) => /* @__PURE__ */ jsx("span", { className: `unknown__pt__mark__${markType}`, children }), DefaultUnknownBlockStyle = ({
  children
}) => /* @__PURE__ */ jsx("p", { children }), DefaultUnknownList = ({ children }) => /* @__PURE__ */ jsx("ul", { children }), DefaultUnknownListItem = ({
  children
}) => /* @__PURE__ */ jsx("li", { children }), DefaultHardBreak = () => /* @__PURE__ */ jsx("br", {}), defaultBlockStyles = {
  normal: ({ children }) => /* @__PURE__ */ jsx("p", { children }),
  blockquote: ({ children }) => /* @__PURE__ */ jsx("blockquote", { children }),
  h1: ({ children }) => /* @__PURE__ */ jsx("h1", { children }),
  h2: ({ children }) => /* @__PURE__ */ jsx("h2", { children }),
  h3: ({ children }) => /* @__PURE__ */ jsx("h3", { children }),
  h4: ({ children }) => /* @__PURE__ */ jsx("h4", { children }),
  h5: ({ children }) => /* @__PURE__ */ jsx("h5", { children }),
  h6: ({ children }) => /* @__PURE__ */ jsx("h6", { children })
}, defaultComponents = {
  types: {},
  block: defaultBlockStyles,
  marks: defaultMarks,
  list: defaultLists,
  listItem: DefaultListItem,
  hardBreak: DefaultHardBreak,
  unknownType: DefaultUnknownType,
  unknownMark: DefaultUnknownMark,
  unknownList: DefaultUnknownList,
  unknownListItem: DefaultUnknownListItem,
  unknownBlockStyle: DefaultUnknownBlockStyle
};
function mergeComponents(parent, overrides) {
  const { block, list, listItem, marks, types, ...rest } = overrides;
  return {
    ...parent,
    block: mergeDeeply(parent, overrides, "block"),
    list: mergeDeeply(parent, overrides, "list"),
    listItem: mergeDeeply(parent, overrides, "listItem"),
    marks: mergeDeeply(parent, overrides, "marks"),
    types: mergeDeeply(parent, overrides, "types"),
    ...rest
  };
}
function mergeDeeply(parent, overrides, key) {
  const override = overrides[key], parentVal = parent[key];
  return typeof override == "function" || override && typeof parentVal == "function" ? override : override ? { ...parentVal, ...override } : parentVal;
}
function PortableText({
  value: input,
  components: componentOverrides,
  listNestingMode,
  onMissingComponent: missingComponentHandler = printWarning
}) {
  const handleMissingComponent = missingComponentHandler || noop, blocks = Array.isArray(input) ? input : [input], nested = nestLists(blocks, listNestingMode || LIST_NEST_MODE_HTML), components = useMemo(() => componentOverrides ? mergeComponents(defaultComponents, componentOverrides) : defaultComponents, [componentOverrides]), renderNode = useMemo(
    () => getNodeRenderer(components, handleMissingComponent),
    [components, handleMissingComponent]
  ), rendered = nested.map(
    (node, index) => renderNode({ node, index, isInline: !1, renderNode })
  );
  return /* @__PURE__ */ jsx(Fragment, { children: rendered });
}
const getNodeRenderer = (components, handleMissingComponent) => {
  function renderNode(options) {
    const { node, index, isInline } = options, key = node._key || `node-${index}`;
    return isPortableTextToolkitList(node) ? renderList(node, index, key) : isPortableTextListItemBlock(node) ? renderListItem(node, index, key) : isPortableTextToolkitSpan(node) ? renderSpan(node, index, key) : hasCustomComponentForNode(node) ? renderCustomBlock(node, index, key, isInline) : isPortableTextBlock(node) ? renderBlock(node, index, key, isInline) : isPortableTextToolkitTextNode(node) ? renderText(node, key) : renderUnknownType(node, index, key, isInline);
  }
  function hasCustomComponentForNode(node) {
    return node._type in components.types;
  }
  function renderListItem(node, index, key) {
    const tree = serializeBlock({ node, index, isInline: !1, renderNode }), renderer = components.listItem, Li = (typeof renderer == "function" ? renderer : renderer[node.listItem]) || components.unknownListItem;
    if (Li === components.unknownListItem) {
      const style = node.listItem || "bullet";
      handleMissingComponent(unknownListItemStyleWarning(style), {
        type: style,
        nodeType: "listItemStyle"
      });
    }
    let children = tree.children;
    if (node.style && node.style !== "normal") {
      const { listItem, ...blockNode } = node;
      children = renderNode({ node: blockNode, index, isInline: !1 });
    }
    return /* @__PURE__ */ jsx(Li, { value: node, index, isInline: !1, renderNode, children }, key);
  }
  function renderList(node, index, key) {
    const children = node.children.map(
      (child, childIndex) => renderNode({
        node: child._key ? child : { ...child, _key: `li-${index}-${childIndex}` },
        index: childIndex,
        isInline: !1
      })
    ), component = components.list, List = (typeof component == "function" ? component : component[node.listItem]) || components.unknownList;
    if (List === components.unknownList) {
      const style = node.listItem || "bullet";
      handleMissingComponent(unknownListStyleWarning(style), { nodeType: "listStyle", type: style });
    }
    return /* @__PURE__ */ jsx(List, { value: node, index, isInline: !1, renderNode, children }, key);
  }
  function renderSpan(node, _index, key) {
    const { markDef, markType, markKey } = node, Span = components.marks[markType] || components.unknownMark, children = node.children.map(
      (child, childIndex) => renderNode({ node: child, index: childIndex, isInline: !0 })
    );
    return Span === components.unknownMark && handleMissingComponent(unknownMarkWarning(markType), { nodeType: "mark", type: markType }), /* @__PURE__ */ jsx(
      Span,
      {
        text: spanToPlainText(node),
        value: markDef,
        markType,
        markKey,
        renderNode,
        children
      },
      key
    );
  }
  function renderBlock(node, index, key, isInline) {
    const { _key, ...props } = serializeBlock({ node, index, isInline, renderNode }), style = props.node.style || "normal", Block = (typeof components.block == "function" ? components.block : components.block[style]) || components.unknownBlockStyle;
    return Block === components.unknownBlockStyle && handleMissingComponent(unknownBlockStyleWarning(style), {
      nodeType: "blockStyle",
      type: style
    }), /* @__PURE__ */ jsx(Block, { ...props, value: props.node, renderNode }, key);
  }
  function renderText(node, key) {
    if (node.text === `
`) {
      const HardBreak = components.hardBreak;
      return HardBreak ? /* @__PURE__ */ jsx(HardBreak, {}, key) : `
`;
    }
    return node.text;
  }
  function renderUnknownType(node, index, key, isInline) {
    const nodeOptions = {
      value: node,
      isInline,
      index,
      renderNode
    };
    handleMissingComponent(unknownTypeWarning(node._type), { nodeType: "block", type: node._type });
    const UnknownType = components.unknownType;
    return /* @__PURE__ */ jsx(UnknownType, { ...nodeOptions }, key);
  }
  function renderCustomBlock(node, index, key, isInline) {
    const nodeOptions = {
      value: node,
      isInline,
      index,
      renderNode
    }, Node = components.types[node._type];
    return Node ? /* @__PURE__ */ jsx(Node, { ...nodeOptions }, key) : null;
  }
  return renderNode;
};
function serializeBlock(options) {
  const { node, index, isInline, renderNode } = options, children = buildMarksTree(node).map(
    (child, i) => renderNode({ node: child, isInline: !0, index: i, renderNode })
  );
  return {
    _key: node._key || `block-${index}`,
    children,
    index,
    isInline,
    node
  };
}
function noop() {
}
export {
  PortableText,
  defaultComponents,
  mergeComponents,
  toPlainText
};
//# sourceMappingURL=index.js.map
