@activecollab/components
Version:
ActiveCollab Components
181 lines (173 loc) • 6.59 kB
JavaScript
import React, { Fragment } from "react";
import { StyledCode, StyledCodeBlock, StyledDivider, StyledLink, StyledList, StyledTableBlock } from "./Styles";
import { isPortableTextMediaImageVariant } from "./types";
import { Media } from "../Media";
import { Table, Tbody, Thead } from "../Tables";
import { TitledText, titledTextHeadings } from "../TitledText";
import { Body1 } from "../Typography";
import { Typography } from "../Typography/Typography";
/**
* The default renderers for the universal set — everything a client renders
* without injection, and nothing more: no product element ever lands here.
* Injected {@link PortableTextComponents} maps take precedence entry by entry.
*/
export const portableTextDefaultMarkRenderers = {
strong: _ref => {
let children = _ref.children;
return /*#__PURE__*/React.createElement("strong", null, children);
},
em: _ref2 => {
let children = _ref2.children;
return /*#__PURE__*/React.createElement("em", null, children);
},
code: _ref3 => {
let children = _ref3.children;
return /*#__PURE__*/React.createElement(StyledCode, null, children);
},
link: _ref4 => {
let mark = _ref4.mark,
children = _ref4.children;
const href = mark == null ? void 0 : mark.href;
// A link mark without an href (authored as a plain string) has nowhere
// to go — keep the text, skip the anchor.
if (!href) {
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
}
return /*#__PURE__*/React.createElement(StyledLink, {
href: href,
target: "_blank",
rel: "noopener noreferrer"
}, children);
}
};
/** The semantic wire levels resolve to typography only here, in the renderer. */
const HEADING_LEVEL_VARIANTS = {
1: "title1",
2: "title2",
3: "header2"
};
/** The level `heading` and `titled-text` fall back to. */
const DEFAULT_HEADING_LEVEL = 3;
/**
* Resolve a semantic wire level to its typography variant. An absent level is
* the documented default; any other unrecognised level is a serializer bug on
* a fixed 1–3 scale, so it falls back to the default and is logged, per the
* contract's degradation rule.
*/
const headingVariantForLevel = level => {
if (level === undefined) {
return HEADING_LEVEL_VARIANTS[DEFAULT_HEADING_LEVEL];
}
const variant = HEADING_LEVEL_VARIANTS[level];
if (!variant) {
console.warn("PortableText: unknown heading level " + level + ", falling back to " + DEFAULT_HEADING_LEVEL + ".");
return HEADING_LEVEL_VARIANTS[DEFAULT_HEADING_LEVEL];
}
return variant;
};
/** Heading levels map to the same typography TitledText uses. */
const HeadingBlock = _ref5 => {
let block = _ref5.block,
children = _ref5.children;
const _ref6 = block,
level = _ref6.level,
id = _ref6.id;
const Heading = titledTextHeadings[headingVariantForLevel(level)];
return /*#__PURE__*/React.createElement(Heading, {
id: id
}, children);
};
export const portableTextDefaultBlockRenderers = {
paragraph: _ref7 => {
let children = _ref7.children;
return /*#__PURE__*/React.createElement(Body1, null, children);
},
heading: HeadingBlock,
list: _ref8 => {
let block = _ref8.block,
children = _ref8.children;
const ordered = block.style === "number";
return (
/*#__PURE__*/
// `data-portable-list` scopes the depth-marker rules in Styles.ts to
// design-system lists, and marks the ancestors those rules count.
React.createElement(StyledList, {
as: ordered ? "ol" : "ul",
$ordered: ordered,
"data-portable-list": ""
}, children)
);
},
"list-item": _ref9 => {
let children = _ref9.children;
return /*#__PURE__*/React.createElement(Typography, {
variant: "Body 1",
as: "li"
}, children);
},
media: _ref0 => {
let block = _ref0.block;
const _ref1 = block,
src = _ref1.src,
alt = _ref1.alt,
variant = _ref1.variant,
caption = _ref1.caption;
// Video (and future) variants carry service semantics, so their renderer
// is application-catalog territory — an injected `media` override. The
// universal set covers images only; anything else degrades and warns, per
// the contract's degradation rule.
if (variant !== undefined && !isPortableTextMediaImageVariant(variant)) {
console.warn("PortableText: no default renderer for media variant \"" + variant + "\".");
return null;
}
return /*#__PURE__*/React.createElement(Media, {
src: src,
alt: alt,
variant: variant,
caption: caption
});
},
"titled-text": _ref10 => {
let block = _ref10.block,
children = _ref10.children;
const _ref11 = block,
title = _ref11.title,
level = _ref11.level;
return /*#__PURE__*/React.createElement(TitledText, {
title: title,
variant: headingVariantForLevel(level)
}, children);
},
// No highlighter ships with the default set, so every language — known,
// unknown or absent — is plain preformatted text; the hint travels on
// data-language for surfaces that highlight.
"code-block": _ref12 => {
let block = _ref12.block;
const _ref13 = block,
code = _ref13.code,
language = _ref13.language;
return /*#__PURE__*/React.createElement(StyledCodeBlock, {
"data-language": language || undefined
}, /*#__PURE__*/React.createElement("code", null, code));
},
table: _ref14 => {
let block = _ref14.block,
renderSpans = _ref14.renderSpans;
const _ref15 = block,
header = _ref15.header,
rows = _ref15.rows;
// Standalone (engine-less) use has no span renderer — keep the raw text.
const cell = spans => renderSpans ? renderSpans(spans) : spans.map((span, index) => /*#__PURE__*/React.createElement(Fragment, {
key: index
}, span.text));
return /*#__PURE__*/React.createElement(StyledTableBlock, null, /*#__PURE__*/React.createElement(Table, null, /*#__PURE__*/React.createElement(Thead, null, /*#__PURE__*/React.createElement("tr", null, header.map((spans, index) => /*#__PURE__*/React.createElement("th", {
key: index
}, cell(spans))))), /*#__PURE__*/React.createElement(Tbody, null, rows.map((row, rowIndex) => /*#__PURE__*/React.createElement("tr", {
key: rowIndex
}, row.map((spans, cellIndex) => /*#__PURE__*/React.createElement("td", {
key: cellIndex
}, cell(spans))))))));
},
divider: () => /*#__PURE__*/React.createElement(StyledDivider, null)
};
//# sourceMappingURL=renderers.js.map