UNPKG

tinacms

Version:

> The Fastest Way to Edit Next.js Content

490 lines (489 loc) • 18.7 kB
import React, { useContext, useState, useEffect, Suspense } from "react"; const TinaMarkdown = ({ content, components = {} }) => { if (!content) { return null; } const nodes = Array.isArray(content) ? content : content.children; if (!nodes) { return null; } return /* @__PURE__ */ React.createElement(React.Fragment, null, nodes.map((child, index) => { return /* @__PURE__ */ React.createElement(MemoNode, { components, key: index, child }); })); }; const Leaf = (props) => { if (props.bold) { const { bold, ...rest } = props; if (props.components.bold) { const Component = props.components.bold; return /* @__PURE__ */ React.createElement(Component, null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } return /* @__PURE__ */ React.createElement("strong", null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } if (props.italic) { const { italic, ...rest } = props; if (props.components.italic) { const Component = props.components.italic; return /* @__PURE__ */ React.createElement(Component, null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } return /* @__PURE__ */ React.createElement("em", null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } if (props.underline) { const { underline, ...rest } = props; if (props.components.underline) { const Component = props.components.underline; return /* @__PURE__ */ React.createElement(Component, null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } return /* @__PURE__ */ React.createElement("u", null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } if (props.strikethrough) { const { strikethrough, ...rest } = props; if (props.components.strikethrough) { const Component = props.components.strikethrough; return /* @__PURE__ */ React.createElement(Component, null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } return /* @__PURE__ */ React.createElement("s", null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } if (props.code) { const { code, ...rest } = props; if (props.components.code) { const Component = props.components.code; return /* @__PURE__ */ React.createElement(Component, null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } return /* @__PURE__ */ React.createElement("code", null, /* @__PURE__ */ React.createElement(Leaf, { ...rest })); } if (props.components.text) { const Component = props.components.text; return /* @__PURE__ */ React.createElement(Component, null, props.text); } return /* @__PURE__ */ React.createElement(React.Fragment, null, props.text); }; const MemoNode = (props) => { const MNode = React.useMemo( () => /* @__PURE__ */ React.createElement(Node, { ...props }), [JSON.stringify(props)] ); return MNode; }; const Node = ({ components, child }) => { var _a, _b, _c, _d, _e, _f; const { children, ...props } = child; switch (child.type) { case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": case "p": case "blockquote": case "ol": case "ul": case "li": if (components[child.type]) { const Component2 = components[child.type]; return /* @__PURE__ */ React.createElement(Component2, { ...props }, /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: children })); } return React.createElement(child.type, { children: /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: children }) }); case "lic": if (components.lic) { const Component2 = components.lic; return /* @__PURE__ */ React.createElement(Component2, { ...props }, /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: children })); } return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: child.children })); case "img": if (components[child.type]) { const Component2 = components[child.type]; return /* @__PURE__ */ React.createElement(Component2, { ...props }); } return /* @__PURE__ */ React.createElement("img", { src: child.url, alt: child.caption }); case "a": if (components[child.type]) { const Component2 = components[child.type]; return ( // @ts-ignore FIXME: TinaMarkdownContent needs to be a union of all possible node types /* @__PURE__ */ React.createElement(Component2, { ...props }, /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: children })) ); } return ( // @ts-ignore FIXME: TinaMarkdownContent needs to be a union of all possible node types /* @__PURE__ */ React.createElement("a", { href: child.url }, /* @__PURE__ */ React.createElement(TinaMarkdown, { components, content: children })) ); case "code_block": const value = child.value; if (components[child.type]) { const Component2 = components[child.type]; return ( // @ts-ignore FIXME: TinaMarkdownContent needs to be a union of all possible node types /* @__PURE__ */ React.createElement(Component2, { ...props }) ); } return /* @__PURE__ */ React.createElement("pre", null, /* @__PURE__ */ React.createElement("code", null, value)); case "hr": if (components[child.type]) { const Component2 = components[child.type]; return /* @__PURE__ */ React.createElement(Component2, { ...props }); } return /* @__PURE__ */ React.createElement("hr", null); case "break": if (components[child.type]) { const Component2 = components[child.type]; return /* @__PURE__ */ React.createElement(Component2, { ...props }); } return /* @__PURE__ */ React.createElement("br", null); case "text": return /* @__PURE__ */ React.createElement(Leaf, { components, ...child }); case "mdxJsxTextElement": case "mdxJsxFlowElement": const Component = components[child.name]; if (Component) { const props2 = child.props ? child.props : {}; return /* @__PURE__ */ React.createElement(Component, { ...props2 }); } else { if (child.name === "table") { const firstRowHeader = (_a = child.props) == null ? void 0 : _a.firstRowHeader; const rows = (firstRowHeader ? (_b = child.props) == null ? void 0 : _b.tableRows.filter((_, i) => i !== 0) : (_c = child.props) == null ? void 0 : _c.tableRows) || []; const header = (_e = (_d = child.props) == null ? void 0 : _d.tableRows) == null ? void 0 : _e.at(0); const TableComponent = components["table"] || ((props2) => /* @__PURE__ */ React.createElement("table", { ...props2 })); const TrComponent = components["tr"] || ((props2) => /* @__PURE__ */ React.createElement("tr", { ...props2 })); const ThComponent = components["th"] || ((props2) => /* @__PURE__ */ React.createElement("th", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 })); const TdComponent = components["td"] || ((props2) => /* @__PURE__ */ React.createElement("td", { style: { textAlign: (props2 == null ? void 0 : props2.align) || "auto" }, ...props2 })); const align = ((_f = child.props) == null ? void 0 : _f.align) || []; return /* @__PURE__ */ React.createElement(TableComponent, null, firstRowHeader && /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement(TrComponent, null, header.tableCells.map((c, i) => { return /* @__PURE__ */ React.createElement( TinaMarkdown, { key: i, components: { p: (props2) => /* @__PURE__ */ React.createElement(ThComponent, { align: align[i], ...props2 }) }, content: c.value } ); }))), /* @__PURE__ */ React.createElement("tbody", null, rows.map((row, i) => { var _a2; return /* @__PURE__ */ React.createElement(TrComponent, { key: i }, (_a2 = row == null ? void 0 : row.tableCells) == null ? void 0 : _a2.map((c, i2) => { return /* @__PURE__ */ React.createElement( TinaMarkdown, { key: i2, components: { p: (props2) => /* @__PURE__ */ React.createElement(TdComponent, { align: align[i2], ...props2 }) }, content: c.value } ); })); }))); } const ComponentMissing = components["component_missing"]; if (ComponentMissing) { return /* @__PURE__ */ React.createElement(ComponentMissing, { name: child.name }); } else { return /* @__PURE__ */ React.createElement("span", null, `No component provided for ${child.name}`); } } case "maybe_mdx": return null; case "html": case "html_inline": if (components[child.type]) { const Component2 = components[child.type]; return /* @__PURE__ */ React.createElement(Component2, { ...props }); } return child.value; case "invalid_markdown": return /* @__PURE__ */ React.createElement("pre", null, child.value); default: if (typeof child.text === "string") { return /* @__PURE__ */ React.createElement(Leaf, { components, ...child }); } } }; const tinaField = (object, property, index) => { var _a, _b, _c; if (!object) { return ""; } if (object._content_source) { if (!property) { return [ (_a = object._content_source) == null ? void 0 : _a.queryId, object._content_source.path.join(".") ].join("---"); } if (typeof index === "number") { return [ (_b = object._content_source) == null ? void 0 : _b.queryId, [...object._content_source.path, property, index].join(".") ].join("---"); } return [ (_c = object._content_source) == null ? void 0 : _c.queryId, [...object._content_source.path, property].join(".") ].join("---"); } return ""; }; const Explorer = (props) => { return /* @__PURE__ */ React.createElement("div", { className: "font-mono" }, /* @__PURE__ */ React.createElement(ObjectValueRenderer, { ...props })); }; const ObjectValueRenderer = (props) => { const subEntries = Object.entries(props.value).map(([keyName, subValue]) => { return /* @__PURE__ */ React.createElement("div", { key: keyName, className: "gap-2" }, /* @__PURE__ */ React.createElement( UnknownRenderer, { keyName, value: subValue, parentValue: props.value, parentKeyName: props.parentKeyName, renderValue: props.renderValue, renderRichText: props.renderRichText, showMetaFields: props.showMetaFields } )); }); return /* @__PURE__ */ React.createElement("div", null, subEntries); }; const UnknownRenderer = ({ keyName, value, parentValue, parentKeyName, renderValue, renderRichText, showMetaFields }) => { const typeOfValue = typeof value; const [expanded, setExpanded] = React.useState( /* @ts-ignore */ (value == null ? void 0 : value.type) === "root" ? false : true ); if (!showMetaFields) { if ([ // 'id', "_sys", "__typename", // '_tina_metadata', "_internalValues", "_internalSys" ].includes(keyName)) { return; } } if (Array.isArray(value)) { return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement( "button", { onClick: () => setExpanded((exp) => !exp), className: "min-w-[48px] flex justify-start gap-2" }, keyName, ": ", "[", !expanded && `...]` ), expanded && /* @__PURE__ */ React.createElement("div", { className: "pl-4" }, value.map((item, index) => /* @__PURE__ */ React.createElement( UnknownRenderer, { key: String(index), keyName: String(index), value: item, parentKeyName: keyName, parentValue, renderValue, renderRichText } ))), expanded && /* @__PURE__ */ React.createElement("div", null, "]")); } if (typeOfValue === "object") { if ((value == null ? void 0 : value.type) === "root" && renderRichText) { return /* @__PURE__ */ React.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React.createElement( "button", { onClick: () => setExpanded((exp) => !exp), className: "min-w-[48px] flex justify-start gap-2" }, keyName, ": ", !expanded && "{...}" ), /* @__PURE__ */ React.createElement("div", null, expanded && // @ts-ignore renderRichText({ value, keyName, parentValue, parentKeyName }))); } return /* @__PURE__ */ React.createElement( ObjectRenderer, { keyName, value, parentValue, parentKeyName, renderValue, renderRichText } ); } return /* @__PURE__ */ React.createElement( Value, { keyName, value, parentValue, parentKeyName, renderValue } ); }; const Value = ({ keyName, value, parentValue, parentKeyName, renderValue }) => { const keyDisplay = isNaN(Number(keyName)) ? `${keyName}: ` : ``; return /* @__PURE__ */ React.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React.createElement("div", null, keyDisplay), /* @__PURE__ */ React.createElement("div", null, renderValue({ value, keyName, parentValue, parentKeyName }))); }; const ObjectRenderer = ({ keyName, value, parentValue, parentKeyName, renderValue, renderRichText }) => { const { withDataTinaFieldState } = useContext(JsonContext); const [showMetaFields, setShowMetaFields] = React.useState(false); const [expanded, setExpanded] = React.useState(true); const v = value; const keyDisplay = isNaN(Number(keyName)) ? `${keyName}: ` : ``; if (value === null) { return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "" }, keyDisplay), /* @__PURE__ */ React.createElement("div", { className: "text-gray-400" }, "null"))); } else { const fieldName = tinaField(v); const extraProps = {}; if (fieldName !== "undefined#undefined" && withDataTinaFieldState) { extraProps["data-tina-field"] = fieldName; } return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "flex justify-between" }, /* @__PURE__ */ React.createElement( "button", { onClick: () => setExpanded((exp) => !exp), className: "min-w-[48px] flex justify-start gap-2" }, keyDisplay, "{", !expanded && `...}` ), expanded && /* @__PURE__ */ React.createElement( "button", { onClick: () => { setShowMetaFields((show) => !show); }, className: "min-w-[48px] text-sm text-gray-400" }, showMetaFields ? "Hide meta fields" : "Show meta fields" )), expanded && /* @__PURE__ */ React.createElement("div", { className: "pl-4", ...extraProps }, /* @__PURE__ */ React.createElement( ObjectValueRenderer, { value: v, parentValue, parentKeyName, renderValue, renderRichText, showMetaFields } )), expanded && /* @__PURE__ */ React.createElement("div", null, "}")); } }; const JsonContext = React.createContext({ withDataTinaFieldState: true }); function Json({ src, withDataTinaFieldState = true }) { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); if (!isClient) { return null; } return /* @__PURE__ */ React.createElement(Suspense, { fallback: /* @__PURE__ */ React.createElement("div", { className: "" }, "Loading...") }, /* @__PURE__ */ React.createElement( JsonContext.Provider, { value: { withDataTinaFieldState: withDataTinaFieldState === false ? false : true } }, /* @__PURE__ */ React.createElement("div", { className: "px-4" }, /* @__PURE__ */ React.createElement("div", { className: "mx-auto my-8 border rounded-lg p-8 shadow-lg max-w-5xl mx-auto shadow-lg" }, /* @__PURE__ */ React.createElement("div", { className: "h-full overflow-scroll" }, /* @__PURE__ */ React.createElement( Explorer, { value: src, renderRichText: ({ value, // @ts-ignore keyName, // @ts-ignore parentValue, // @ts-ignore parentKeyName }) => { let fieldName = ""; if (!isNaN(Number(keyName))) { fieldName = `${tinaField( parentValue, parentKeyName )}.${keyName}`; } else { fieldName = tinaField(parentValue, keyName); } const extraProps = {}; if (fieldName !== "undefined#undefined") { if (fieldName && withDataTinaFieldState) { extraProps["data-tina-field"] = fieldName; } } return /* @__PURE__ */ React.createElement( "div", { className: "font-sans px-2 border-l-2 bg-gray-50 w-full prose", ...extraProps }, /* @__PURE__ */ React.createElement(TinaMarkdown, { content: value }) ); }, renderValue: ({ value, keyName, parentValue, parentKeyName }) => { let fieldName = ""; if (!isNaN(Number(keyName))) { fieldName = `${tinaField( parentValue, // @ts-ignore parentKeyName )}.${keyName}`; } else { fieldName = tinaField(parentValue, keyName); } const extraProps = {}; if (fieldName !== "undefined#undefined") { if (fieldName && withDataTinaFieldState) { extraProps["data-tina-field"] = fieldName; } } return /* @__PURE__ */ React.createElement("span", { className: "text-orange-600", ...extraProps }, value); } } )))) )); } export { Explorer, Json };