@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.
Two halves. The builders construct that vocabulary with the compiler
checking the names and shapes. validateFace checks a finished tree
against the protocol, so a face is wrong at build time rather than blank on
a phone.
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 |
|---|---|
archive() | Image bytes from a path inside the product’s executable archive. |
assertFaceValid() | validateFace, but throws on any error. |
background() | A background fill. Omitting the shape leaves it to the host. |
blendingMode() | How the node composites against what is behind it. |
border() | A border. Omitting the shape leaves it to the host. |
box() | Children stacked on top of one another. With no children and a background, a filled rectangle. |
bulletin() | Image bytes from a Bulletin chain blob, addressed by CID. |
button() | A pressable button. Give it a clickAction or it reports nothing. |
circle() | A circle. |
column() | Children stacked vertically. |
effect() | Applies an effect to its children. The only node with no modifiers of its own. |
fillHeight() | Fill the available height. |
fillWidth() | Fill the available width. |
height() | A fixed height. |
image() | An image the host fetches. Build the source with bulletin() or archive(). |
margin() | Outer spacing. Reads as padding does. |
marginEach() | Outer spacing with every edge named. |
minHeight() | A minimum height. |
minWidth() | A minimum width. |
nil() | Nothing. Draws no space. |
opacity() | Opacity, where 0 is transparent and 255 opaque. |
padding() | Inner spacing. padding(16) is 16 on every edge; padding(20, 24) is 20 |
paddingEach() | Inner spacing with every edge named. |
rounded() | Rounded corners of the given radius. |
row() | Children laid out horizontally. |
spacer() | Empty space of a fixed size. |
square() | Square corners. |
str() | A raw string node. text is what you usually want. |
text() | A line of text, wrapped in the String child the protocol requires. |
textField() | An editable field. Give it a valueChangeAction or it reports nothing. |
validateFace() | Check a face against the renderer protocol. |
width() | A fixed width. |
Interfaces
| Name | Summary |
|---|---|
BoxOptions | Options every node with modifiers accepts. |
ButtonOptions | Options every node with modifiers accepts. |
ColumnOptions | Options every node with modifiers accepts. |
Dimensions | Edge dimensions. bottom defaults to top and start to end when absent. |
FaceIssue | One thing wrong with a face, and where. |
FaceVerdict | — |
HostLimits | One host’s own bounds. |
ImageOptions | Options every node with modifiers accepts. |
NodeOptions | Options every node with modifiers accepts. |
RowOptions | Options every node with modifiers accepts. |
SpacerOptions | — |
TextFieldOptions | Options every node with modifiers accepts. |
TextOptions | Options every node with modifiers accepts. |
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. |
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. |
Classes
class FaceValidationError
Thrown by assertFaceValid. Carries the whole verdict, warnings included.
Extends: Error
Constructors
constructor
new FaceValidationError(verdict: FaceVerdict): FaceValidationErrorProperties
verdict
FaceVerdictFunctions
archive()
Image bytes from a path inside the product’s executable archive.
archive(path: string): ImageSourceassertFaceValid()
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 = {}): voidbackground()
A background fill. Omitting the shape leaves it to the host.
background(color: ColorToken, shape?: Shape): ModifierblendingMode()
How the node composites against what is behind it.
blendingMode(mode: BlendingMode): Modifierborder()
A border. Omitting the shape leaves it to the host.
border(width: Size, color: ColorToken, shape?: Shape): Modifierbox()
Children stacked on top of one another. With no children and a background, a filled rectangle.
box(children: RendererNode[], options: BoxOptions = {}): RendererNodebulletin()
Image bytes from a Bulletin chain blob, addressed by CID.
bulletin(cid: string): ImageSourcebutton()
A pressable button. Give it a clickAction or it reports nothing.
button(label: string, options: ButtonOptions = {}): RendererNodecircle()
A circle.
circle(): Shapecolumn()
Children stacked vertically.
column(children: RendererNode[], options: ColumnOptions = {}): RendererNodeeffect()
Applies an effect to its children. The only node with no modifiers of its own.
effect(applied: "Rainbow", children: RendererNode[]): RendererNodefillHeight()
Fill the available height.
fillHeight(value: boolean = true): ModifierfillWidth()
Fill the available width.
fillWidth(value: boolean = true): Modifierheight()
A fixed height.
height(value: Size): Modifierimage()
An image the host fetches. Build the source with bulletin() or archive().
image(source: ImageSource, options: ImageOptions = {}): RendererNodemargin()
Outer spacing. Reads as padding does.
margin(vertical: Size, horizontal: Size = vertical): ModifiermarginEach()
Outer spacing with every edge named.
marginEach(edges: Dimensions): ModifierminHeight()
A minimum height.
minHeight(value: Size): ModifierminWidth()
A minimum width.
minWidth(value: Size): Modifiernil()
Nothing. Draws no space.
nil(): RendererNodeopacity()
Opacity, where 0 is transparent and 255 opaque.
opacity(value: number): Modifierpadding()
Inner spacing. padding(16) is 16 on every edge; padding(20, 24) is 20
vertical and 24 horizontal.
The protocol’s Dimensions requires top and end and defaults bottom to
top and start to end, which is exactly a vertical/horizontal shorthand.
Naming it that way is what makes the missing-end error unreachable. Reach
for paddingEach when the four edges genuinely differ.
padding(vertical: Size, horizontal: Size = vertical): ModifierpaddingEach()
Inner spacing with every edge named.
paddingEach(edges: Dimensions): Modifierrounded()
Rounded corners of the given radius.
rounded(radius: Size): Shaperow()
Children laid out horizontally.
row(children: RendererNode[], options: RowOptions = {}): RendererNodespacer()
Empty space of a fixed size.
spacer(options: SpacerOptions): RendererNodesquare()
Square corners.
square(): Shapestr()
A raw string node. text is what you usually want.
str(content: string): RendererNodetext()
A line of text, wrapped in the String child the protocol requires.
text(content: string, options: TextOptions = {}): RendererNodetextField()
An editable field. Give it a valueChangeAction or it reports nothing.
textField(options: TextFieldOptions): RendererNodevalidateFace()
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 = {}): FaceVerdictwidth()
A fixed width.
width(value: Size): ModifierInterfaces
interface BoxOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
contentAlignment
ContentAlignmentinterface ButtonOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
clickAction
stringThe id the host reports when the button is pressed. A button without one is inert.
enabled
booleanloading
booleanvariant
ButtonVariantinterface ColumnOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
horizontalAlignment
HorizontalAlignmentverticalArrangement
Arrangementinterface 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 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 ImageOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
fit
ImageFitinterface NodeOptions
Options every node with modifiers accepts.
Properties
modifiers
Modifier[]interface RowOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
horizontalArrangement
ArrangementverticalAlignment
VerticalAlignmentinterface SpacerOptions
Properties
height
Sizewidth
Sizeinterface TextFieldOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
enabled
booleanlabel
stringplaceholder
stringtext
stringvalueChangeAction
stringThe id the host reports on every change, carrying the new value.
interface TextOptions
Options every node with modifiers accepts.
Extends: NodeOptions
Properties
color
ColorTokenstyle
TypographyStyleinterface 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 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[] = ...