tinacms
Version:
> The Fastest Way to Edit Next.js Content
490 lines (489 loc) • 18.7 kB
JavaScript
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
};