@portabletext/react
Advanced tools
Comparing version 3.1.0-canary.0 to 3.1.0-canary.1
/// <reference types="react" /> | ||
import type {ArbitraryTypedObject} from '@portabletext/types' | ||
import {ArbitraryTypedObject} from '@portabletext/types' | ||
import type {ComponentType} from 'react' | ||
import {ToolkitListNestMode as ListNestMode} from '@portabletext/toolkit' | ||
import {MemoExoticComponent} from 'react' | ||
import {PortableTextBlock} from '@portabletext/types' | ||
@@ -10,2 +11,4 @@ import type {PortableTextBlockStyle} from '@portabletext/types' | ||
import type {PortableTextListItemType} from '@portabletext/types' | ||
import type {PortableTextMarkDefinition} from '@portabletext/types' | ||
import type {PortableTextSpan} from '@portabletext/types' | ||
import type {ReactNode} from 'react' | ||
@@ -42,8 +45,17 @@ import type {ToolkitPortableTextList} from '@portabletext/toolkit' | ||
export declare function PortableText<B extends TypedObject = PortableTextBlock>({ | ||
value: input, | ||
components: componentOverrides, | ||
listNestingMode, | ||
onMissingComponent: missingComponentHandler, | ||
}: PortableTextProps<B>): JSX.Element | ||
export declare const PortableText: MemoExoticComponent< | ||
< | ||
B extends TypedObject = PortableTextBlock< | ||
PortableTextMarkDefinition, | ||
ArbitraryTypedObject | PortableTextSpan, | ||
string, | ||
string | ||
>, | ||
>({ | ||
value, | ||
components, | ||
listNestingMode, | ||
onMissingComponent: missingComponentHandler, | ||
}: PortableTextProps<B>) => JSX.Element | ||
> | ||
@@ -50,0 +62,0 @@ export {PortableTextBlock} |
@@ -12,5 +12,5 @@ const _excluded = ["block", "list", "listItem", "marks", "types"], | ||
import { jsx, Fragment } from "react/jsx-runtime"; | ||
import { nestLists, LIST_NEST_MODE_HTML, isPortableTextToolkitList, isPortableTextListItemBlock, isPortableTextToolkitSpan, isPortableTextBlock, isPortableTextToolkitTextNode, spanToPlainText, buildMarksTree } from "@portabletext/toolkit"; | ||
import { LIST_NEST_MODE_HTML, nestLists, isPortableTextToolkitList, isPortableTextListItemBlock, isPortableTextToolkitSpan, isPortableTextBlock, isPortableTextToolkitTextNode, spanToPlainText, buildMarksTree } from "@portabletext/toolkit"; | ||
import { toPlainText } from "@portabletext/toolkit"; | ||
import { useMemo } from "react"; | ||
import { memo, useMemo } from "react"; | ||
const defaultLists = { | ||
@@ -197,14 +197,22 @@ number: ({ | ||
} | ||
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({ | ||
const PortableText = memo(function ({ | ||
value, | ||
components, | ||
listNestingMode, | ||
onMissingComponent: missingComponentHandler = printWarning | ||
}) { | ||
const blocks = useMemo(() => Array.isArray(value) ? value : [value], [value]), | ||
renderNode = useMemo(() => getNodeRenderer(components ? mergeComponents(defaultComponents, components) : defaultComponents, missingComponentHandler || noop), [components, missingComponentHandler]); | ||
return /* @__PURE__ */jsx(PortableTextRenderer, { | ||
listNestingMode: listNestingMode || LIST_NEST_MODE_HTML, | ||
renderNode, | ||
value: blocks | ||
}); | ||
}), | ||
PortableTextRenderer = memo(function ({ | ||
listNestingMode, | ||
renderNode, | ||
value | ||
}) { | ||
const rendered = nestLists(value, listNestingMode).map((node, index) => renderNode({ | ||
node, | ||
@@ -215,186 +223,184 @@ index, | ||
})); | ||
return /* @__PURE__ */jsx(Fragment, { | ||
children: rendered | ||
}); | ||
} | ||
const getNodeRenderer = (components, handleMissingComponent) => { | ||
function renderNode(options) { | ||
return /* @__PURE__ */jsx(Fragment, { | ||
children: rendered | ||
}); | ||
}), | ||
getNodeRenderer = (components, handleMissingComponent) => { | ||
const 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); | ||
}, | ||
hasCustomComponentForNode = node => node._type in components.types, | ||
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 | ||
} = node, | ||
blockNode = _objectWithoutProperties(node, _excluded2); | ||
children = renderNode({ | ||
node: blockNode, | ||
index, | ||
isInline: !1, | ||
renderNode | ||
}); | ||
} | ||
return /* @__PURE__ */jsx(Li, { | ||
value: node, | ||
index, | ||
isInline: !1, | ||
renderNode, | ||
children | ||
}, key); | ||
}, | ||
renderList = (node, index, key) => { | ||
const children = node.children.map((child, childIndex) => renderNode({ | ||
node: child._key ? child : _objectSpread(_objectSpread({}, child), {}, { | ||
_key: `li-${index}-${childIndex}` | ||
}), | ||
index: childIndex, | ||
isInline: !1, | ||
renderNode | ||
})), | ||
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); | ||
}, | ||
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, | ||
renderNode | ||
})); | ||
return Span === components.unknownMark && handleMissingComponent(unknownMarkWarning(markType), { | ||
nodeType: "mark", | ||
type: markType | ||
}), /* @__PURE__ */jsx(Span, { | ||
text: spanToPlainText(node), | ||
value: markDef, | ||
markType, | ||
markKey, | ||
renderNode, | ||
children | ||
}, key); | ||
}, | ||
renderBlock = (node, index, key, isInline) => { | ||
const _serializeBlock = serializeBlock({ | ||
node, | ||
index, | ||
isInline, | ||
renderNode | ||
}), | ||
{ | ||
_key | ||
} = _serializeBlock, | ||
props = _objectWithoutProperties(_serializeBlock, _excluded3), | ||
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, _objectSpread(_objectSpread({}, props), {}, { | ||
value: props.node, | ||
renderNode | ||
}), key); | ||
}, | ||
renderText = (node, key) => { | ||
if (node.text === ` | ||
`) { | ||
const HardBreak = components.hardBreak; | ||
return HardBreak ? /* @__PURE__ */jsx(HardBreak, {}, key) : ` | ||
`; | ||
} | ||
return node.text; | ||
}, | ||
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, _objectSpread({}, nodeOptions), key); | ||
}, | ||
renderCustomBlock = (node, index, key, isInline) => { | ||
const nodeOptions = { | ||
value: node, | ||
isInline, | ||
index, | ||
renderNode | ||
}, | ||
Node = components.types[node._type]; | ||
return Node ? /* @__PURE__ */jsx(Node, _objectSpread({}, nodeOptions), key) : null; | ||
}; | ||
return renderNode; | ||
}, | ||
serializeBlock = options => { | ||
const { | ||
node, | ||
index, | ||
isInline | ||
isInline, | ||
renderNode | ||
} = 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 | ||
} = node, | ||
blockNode = _objectWithoutProperties(node, _excluded2); | ||
children = renderNode({ | ||
node: blockNode, | ||
index, | ||
isInline: !1, | ||
renderNode | ||
}); | ||
} | ||
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 : _objectSpread(_objectSpread({}, child), {}, { | ||
_key: `li-${index}-${childIndex}` | ||
}), | ||
index: childIndex, | ||
isInline: !1, | ||
renderNode | ||
})), | ||
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({ | ||
children = buildMarksTree(node).map((child, i) => renderNode({ | ||
node: child, | ||
index: childIndex, | ||
isInline: !0, | ||
index: i, | ||
renderNode | ||
})); | ||
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 _serializeBlock = serializeBlock({ | ||
node, | ||
index, | ||
isInline, | ||
renderNode | ||
}), | ||
{ | ||
_key | ||
} = _serializeBlock, | ||
props = _objectWithoutProperties(_serializeBlock, _excluded3), | ||
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, _objectSpread(_objectSpread({}, 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, | ||
return { | ||
_key: node._key || `block-${index}`, | ||
children, | ||
index, | ||
isInline, | ||
index, | ||
renderNode | ||
node | ||
}; | ||
handleMissingComponent(unknownTypeWarning(node._type), { | ||
nodeType: "block", | ||
type: node._type | ||
}); | ||
const UnknownType = components.unknownType; | ||
return /* @__PURE__ */jsx(UnknownType, _objectSpread({}, 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, _objectSpread({}, 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 |
{ | ||
"name": "@portabletext/react", | ||
"version": "3.1.0-canary.0", | ||
"version": "3.1.0-canary.1", | ||
"description": "Render Portable Text with React", | ||
@@ -23,2 +23,6 @@ "keywords": [ | ||
"source": "./src/index.ts", | ||
"react-compiler": { | ||
"source": "./src/index.ts", | ||
"default": "./dist/index.compiled.js" | ||
}, | ||
"import": "./dist/index.js", | ||
@@ -66,2 +70,5 @@ "require": "./dist/index.cjs", | ||
}, | ||
"plugins": [ | ||
"react-compiler" | ||
], | ||
"extends": [ | ||
@@ -74,2 +81,3 @@ "sanity", | ||
"rules": { | ||
"react-compiler/react-compiler": "error", | ||
"react/prop-types": "off" | ||
@@ -86,7 +94,7 @@ }, | ||
"devDependencies": { | ||
"@babel/plugin-proposal-object-rest-spread": "^7.20.7", | ||
"@babel/plugin-transform-object-rest-spread": "^7.24.7", | ||
"@commitlint/cli": "^19.3.0", | ||
"@commitlint/config-conventional": "^19.2.2", | ||
"@sanity/pkg-utils": "^6.8.18", | ||
"@sanity/ui": "^2.1.13", | ||
"@sanity/pkg-utils": "^6.10.0", | ||
"@sanity/ui": "^2.4.0", | ||
"@types/leaflet": "^1.9.12", | ||
@@ -97,8 +105,8 @@ "@types/react": "^18.3.3", | ||
"@types/ws": "^8.5.10", | ||
"@typescript-eslint/eslint-plugin": "^7.11.0", | ||
"@typescript-eslint/parser": "^7.11.0", | ||
"@vitejs/plugin-react": "^4.3.0", | ||
"@typescript-eslint/eslint-plugin": "^7.13.1", | ||
"@typescript-eslint/parser": "^7.13.1", | ||
"@vitejs/plugin-react": "^4.3.1", | ||
"commitizen": "^4.3.0", | ||
"cz-conventional-changelog": "^3.3.0", | ||
"esbuild": "^0.21.4", | ||
"esbuild": "^0.21.5", | ||
"esbuild-register": "^3.5.0", | ||
@@ -108,3 +116,4 @@ "eslint": "^8.57.0", | ||
"eslint-config-sanity": "^7.1.2", | ||
"eslint-plugin-react": "^7.34.2", | ||
"eslint-plugin-react": "^7.34.3", | ||
"eslint-plugin-react-compiler": "0.0.0-experimental-c8b3f72-20240517", | ||
"eslint-plugin-react-hooks": "^4.6.2", | ||
@@ -114,3 +123,3 @@ "husky": "^8.0.3", | ||
"npm-run-all2": "^5.0.2", | ||
"prettier": "^3.2.5", | ||
"prettier": "^3.3.2", | ||
"prettier-plugin-packagejson": "^2.5.0", | ||
@@ -127,3 +136,3 @@ "react": "^18.3.1", | ||
"typescript": "^5.4.5", | ||
"vite": "^5.2.11", | ||
"vite": "^5.3.1", | ||
"vitest": "^1.6.0" | ||
@@ -130,0 +139,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
197365
20
2283
0
40