@parity/product-sdk-renderer
Build and validate renderer trees.
The host draws a Pocket card face, and a rendered chat body, from a
RendererNode: a closed vocabulary of layout and design tokens resolved by
the host’s own theme. A product names structure, never markup, colours or
URLs.
This package is the protocol as data, plus a checker. validateFace
holds a finished tree against the vocabulary, so a face is wrong at build
time rather than blank on a phone, and NODE_SCHEMA lets anything that
builds trees hold its own coverage against the protocol.
To write a face, reach for @parity/product-sdk-react-renderer, which
authors one in JSX. Nothing here is specific to Pocket, and nothing here
talks to a host.
npm install @parity/product-sdk-rendererExports
Classes
| Name | Summary |
|---|---|
FaceValidationError | Thrown by assertFaceValid. Carries the whole verdict, warnings included. |
Functions
| Name | Summary |
|---|---|
assertFaceValid() | validateFace, but throws on any error. |
validateFace() | Check a face against the renderer protocol. |
Interfaces
| Name | Summary |
|---|---|
Dimensions | Edge dimensions. bottom defaults to top and start to end when absent. |
FaceIssue | One thing wrong with a face, and where. |
FaceVerdict | — |
Field | — |
HostLimits | One host’s own bounds. |
NodeSchema | — |
ValidateFaceOptions | — |
Type Aliases
| Name | Summary |
|---|---|
Arrangement | Main-axis distribution of children. |
Arrangement | Main-axis distribution of children. |
BlendingMode | How a node composites with what is behind it. The values are those common |
BlendingMode | How a node composites with what is behind it. The values are those common |
ButtonVariant | Button emphasis. |
ButtonVariant | Button emphasis. |
ColorToken | Semantic color tokens, resolved by the host’s theme. |
ColorToken | Semantic color tokens, resolved by the host’s theme. |
ContentAlignment | Placement of content within a Box. |
ContentAlignment | Placement of content within a Box. |
Dimensions | The protocol’s own vocabulary types, re-exported so one import covers a face. |
Effect | A visual effect. Each variant names one effect and carries its parameters. |
Effect | A visual effect. Each variant names one effect and carries its parameters. |
FaceIssueCode | What is wrong with a face. |
FieldKind | What a single field may hold. |
HorizontalAlignment | Cross-axis alignment of Column children. |
HorizontalAlignment | Cross-axis alignment of Column children. |
ImageFit | How an image meets the box its modifiers size. |
ImageFit | How an image meets the box its modifiers size. |
ImageSource | Where image bytes come from. The host fetches them; the tree carries no URL. |
ImageSource | Where image bytes come from. The host fetches them; the tree carries no URL. |
Modifier | Layout and styling applied to one node. |
Modifier | Layout and styling applied to one node. |
RendererNode | A node in a product-rendered tree. Container variants recurse through |
RendererNode | A node in a product-rendered tree. Container variants recurse through |
Shape | Outline of a background or border. |
Shape | Outline of a background or border. |
Size | A size in logical pixels, SCALE-encoded as Compact<u64>. |
Size | A size in logical pixels, SCALE-encoded as Compact<u64>. |
TypographyStyle | Typography presets, resolved by the host’s design system. |
TypographyStyle | Typography presets, resolved by the host’s design system. |
VerticalAlignment | Cross-axis alignment of Row children. |
VerticalAlignment | Cross-axis alignment of Row children. |
Variables
| Name | Summary |
|---|---|
androidLimits | The Polkadot Android app. |
KNOWN_HOST_LIMITS | Every host whose bounds we know. |
MODIFIER_SCHEMA | The modifiers, keyed by their tag, each mapped to what its value holds. |
NODE_SCHEMA | The node types, keyed by their tag. Typing the key requires every one of them. |
Classes
class FaceValidationError
Thrown by assertFaceValid. Carries the whole verdict, warnings included.
Extends: Error
Constructors
constructor
new FaceValidationError(verdict: FaceVerdict): FaceValidationErrorProperties
verdict
FaceVerdictFunctions
assertFaceValid()
validateFace, but throws on any error.
For a build step that should stop. Warnings do not throw: a build that failed on advice would teach people to switch it off.
assertFaceValid(face: unknown, options: ValidateFaceOptions = {}): voidvalidateFace()
Check a face against the renderer protocol.
Errors are what the protocol forbids: no host can draw them. Warnings are shapes the protocol allows and a product almost certainly did not mean, such as a misspelled prop name, which every host silently ignores.
Pass options.host when you are about to ship to one host and want its own
bounds enforced rather than merely reported.
A host’s cap on face size is measured against what you pass. A string is measured as it stands, and a tree is measured as compact JSON. If you write a preview file with indentation, pass the text you are about to write rather than the tree, or the check will measure something smaller than the file.
validateFace(face: unknown, options: ValidateFaceOptions = {}): FaceVerdictInterfaces
interface Dimensions
Edge dimensions. bottom defaults to top and start to end when absent.
Properties
bottom
SizeBottom edge; defaults to top.
end
SizeEnd edge.
start
SizeStart edge; defaults to end.
top
SizeTop edge.
interface FaceIssue
One thing wrong with a face, and where.
Properties
code
FaceIssueCodemessage
stringpath
stringWhere in the tree, as .value.children[2].value.props.style. Empty for the face itself.
interface FaceVerdict
Properties
errors
FaceIssue[]What the protocol forbids. No host can draw a face with any of these.
ok
booleanTrue when there are no errors. Warnings never make a face invalid.
warnings
FaceIssue[]What the protocol allows and no product means.
interface Field
Properties
required
booleantype
FieldKindinterface HostLimits
One host’s own bounds.
Properties
maxBytes
numberLargest face, measured as JSON text in bytes.
maxDepth
numberDeepest tree the host will decode, counting the root as level 1.
maxSizeValue
numberLargest value a Size may carry.
name
stringNamed in every message about these bounds, so advice says who is asking.
interface NodeSchema
Properties
children
booleanvalue.children is part of this node.
fields
Record<string, Field>Fields directly under value. Only String has any.
modifiers
booleanvalue.modifiers is part of this node.
props
Record<string, Field>Fields under value.props.
interface ValidateFaceOptions
Properties
host
HostLimitsCheck against one host’s own bounds and report a breach as an error. Left out, every known host’s bounds are checked and a breach is a warning naming that host.
Type Aliases
type Arrangement
Main-axis distribution of children.
type Arrangement = Codec<Arrangement>type Arrangement
Main-axis distribution of children.
type Arrangement = "Start" | "End" | "Center" | "SpaceBetween" | "SpaceAround" | "SpaceEvenly"type BlendingMode
How a node composites with what is behind it. The values are those common
to CSS mix-blend-mode, SwiftUI BlendMode and Compose BlendMode.
type BlendingMode = Codec<BlendingMode>type BlendingMode
How a node composites with what is behind it. The values are those common
to CSS mix-blend-mode, SwiftUI BlendMode and Compose BlendMode.
type BlendingMode = "Normal" | "Multiply" | "Screen" | "Overlay" | "Darken" | "Lighten" | "ColorDodge" | "ColorBurn" | "HardLight" | "SoftLight" | "Difference" | "Exclusion" | "Hue" | "Saturation" | "Color" | "Luminosity"type ButtonVariant
Button emphasis.
type ButtonVariant = Codec<ButtonVariant>type ButtonVariant
Button emphasis.
type ButtonVariant = "Primary" | "Secondary" | "Text"type ColorToken
Semantic color tokens, resolved by the host’s theme.
type ColorToken = Codec<ColorToken>type ColorToken
Semantic color tokens, resolved by the host’s theme.
type ColorToken = "FgPrimary" | "FgSecondary" | "FgTertiary" | "BgSurfaceMain" | "BgSurfaceContainer" | "BgSurfaceNested" | "FgSuccess" | "FgError" | "FgWarning"type ContentAlignment
Placement of content within a Box.
type ContentAlignment = Codec<ContentAlignment>type ContentAlignment
Placement of content within a Box.
type ContentAlignment = "TopStart" | "TopCenter" | "TopEnd" | "CenterStart" | "Center" | "CenterEnd" | "BottomStart" | "BottomCenter" | "BottomEnd"type Dimensions
The protocol’s own vocabulary types, re-exported so one import covers a face.
type Dimensions = Codec<Dimensions>type Effect
A visual effect. Each variant names one effect and carries its parameters.
type Effect = Codec<"Rainbow">type Effect
A visual effect. Each variant names one effect and carries its parameters.
type Effect = "Rainbow"type FaceIssueCode
What is wrong with a face.
type FaceIssueCode = "invalid-json" | "not-an-object" | "missing-tag" | "unknown-node" | "unknown-modifier" | "unknown-shape" | "unknown-image-source" | "unknown-enum" | "missing-field" | "wrong-type" | "size-not-integer" | "size-negative" | "size-too-large" | "opacity-out-of-range" | "tree-too-deep" | "unknown-field" | "button-without-action" | "text-field-without-action" | "text-without-content" | "host-limit-depth" | "host-limit-size" | "host-limit-bytes"type FieldKind
What a single field may hold.
type FieldKind = { kind: "string" } | { kind: "boolean" } | { kind: "size" } | { kind: "opacity" } | { kind: "dimensions" } | { kind: "background" } | { kind: "border" } | { kind: "imageSource" } | { kind: "enum"; members: readonly string[] }type HorizontalAlignment
Cross-axis alignment of Column children.
type HorizontalAlignment = Codec<HorizontalAlignment>type HorizontalAlignment
Cross-axis alignment of Column children.
type HorizontalAlignment = "Start" | "Center" | "End"type ImageFit
How an image meets the box its modifiers size.
type ImageFit = Codec<ImageFit>type ImageFit
How an image meets the box its modifiers size.
type ImageFit = "None" | "Fill" | "Cover" | "Contain" | "ScaleDown"type ImageSource
Where image bytes come from. The host fetches them; the tree carries no URL.
type ImageSource = Codec<ImageSource>type ImageSource
Where image bytes come from. The host fetches them; the tree carries no URL.
type ImageSource = { tag: "Bulletin"; value: string } | { tag: "Archive"; value: string }type Modifier
Layout and styling applied to one node.
type Modifier = Codec<Modifier>type Modifier
Layout and styling applied to one node.
type Modifier = { tag: "Margin"; value: Dimensions } | { tag: "Padding"; value: Dimensions } | { tag: "Background"; value: Background } | { tag: "Border"; value: BorderStyle } | { tag: "Height"; value: Size } | { tag: "Width"; value: Size } | { tag: "MinWidth"; value: Size } | { tag: "MinHeight"; value: Size } | { tag: "FillWidth"; value: boolean } | { tag: "FillHeight"; value: boolean } | { tag: "Opacity"; value: number } | { tag: "BlendingMode"; value: BlendingMode }type RendererNode
A node in a product-rendered tree. Container variants recurse through
children.
type RendererNode = Codec<RendererNode>type RendererNode
A node in a product-rendered tree. Container variants recurse through
children.
type RendererNode = { tag: "Nil"; value?: undefined } | { tag: "String"; value: { text: string } } | { tag: "Box"; value: { children: RendererNode[]; modifiers: Modifier[]; props: BoxProps } } | { tag: "Column"; value: { children: RendererNode[]; modifiers: Modifier[]; props: ColumnProps } } | { tag: "Row"; value: { children: RendererNode[]; modifiers: Modifier[]; props: RowProps } } | { tag: "Spacer"; value: { modifiers: Modifier[] } } | { tag: "Text"; value: { children: RendererNode[]; modifiers: Modifier[]; props: TextProps } } | { tag: "Button"; value: { children: RendererNode[]; modifiers: Modifier[]; props: ButtonProps } } | { tag: "TextField"; value: { modifiers: Modifier[]; props: TextFieldProps } } | { tag: "Image"; value: { modifiers: Modifier[]; props: ImageProps } } | { tag: "Effect"; value: { children: RendererNode[]; props: EffectProps } }type Shape
Outline of a background or border.
type Shape = Codec<Shape>type Shape
Outline of a background or border.
type Shape = { tag: "Rounded"; value: Size } | { tag: "Circle"; value?: undefined } | { tag: "Square"; value?: undefined }type Size
A size in logical pixels, SCALE-encoded as Compact<u64>.
type Size = Codec<Size>type Size
A size in logical pixels, SCALE-encoded as Compact<u64>.
type Size = number | biginttype TypographyStyle
Typography presets, resolved by the host’s design system.
type TypographyStyle = Codec<TypographyStyle>type TypographyStyle
Typography presets, resolved by the host’s design system.
type TypographyStyle = "HeadlineLarge" | "TitleMediumRegular" | "BodyLargeRegular" | "BodyMediumRegular" | "BodySmallRegular"type VerticalAlignment
Cross-axis alignment of Row children.
type VerticalAlignment = Codec<VerticalAlignment>type VerticalAlignment
Cross-axis alignment of Row children.
type VerticalAlignment = "Top" | "Center" | "Bottom"Variables
androidLimits
The Polkadot Android app.
maxDepth and maxSizeValue come from its RendererNodeJsonDecoder, where
the size ceiling is Int.MAX_VALUE because the tree maps into Compose, which
reads a size back as an Int. maxBytes is its MAX_FACE_BYTES, applied
both to a streamed face and to a preview file in the worker archive.
let androidLimits: HostLimits = ...KNOWN_HOST_LIMITS
Every host whose bounds we know.
A caller who names no host is checked against all of these, as advice. The iOS app has no renderer yet; it joins this list when it does.
let KNOWN_HOST_LIMITS: readonly HostLimits[] = ...MODIFIER_SCHEMA
The modifiers, keyed by their tag, each mapped to what its value holds.
let MODIFIER_SCHEMA: Record<ModifierTag, FieldKind> = ...NODE_SCHEMA
The node types, keyed by their tag. Typing the key requires every one of them.
let NODE_SCHEMA: Record<NodeTag, NodeSchema> = ...