Surface creates surface contributions and renders surfaces. AppSurface holds the App Toolkit’s roles and the filters that
match them. Surfaces explains how matching works.
Surface.create takes an id, a filter, a component and a props mapper. AppSurface.object(role, Type) matches a role
when the data’s subject is an object of the type.
Role token for the article role. Subject defaults to any until narrowed
via
object
,
literal
, or
subject
. Extra passthrough
props are permitted.
Article,
classNote
Note),
8
component: React.ComponentType<{
role: string;
subject: Note & OfKind<EntityKind.Object>;
attendableId: string;
}>
Accepts any component type (not just a function) so a container re-exported through a
lazy() barrel as ComponentType<any> can be registered without a cast.
Maps the surface props onto the component's own props, so a plain container can be registered
directly instead of being wrapped in an adapter that unpacks data.
Prefer this over an inline component: ({ data }) => <Container … />: the mapper's input type
derives from the same filter that defines the surface's data shape, so the unpacking is
checked against the filter rather than restated by hand.
The resolved role NSID string (e.g. org.dxos.role.article). Present on
matched components only — multi-role containers can branch on this value
by comparing against a token's .role (e.g. role === AppSurface.Section.role).
Contribute surfaces from a module through Capabilities.ReactSurface. In a manifest, AppCapability.surface makes
that module and loads it when one of its roles is first requested.
Helper to define a capability module with explicit typing.
Wraps the default export function to provide better type inference and make the pattern explicit.
This helper provides explicit typing for the module activation function,
making it clear that the function should:
Access declared requires via yield* (or the ambient Capability.Service/Plugin.Service)
AppSurface.oneOf matches any of several filters, and AppSurface.allOf requires all of them. Other filters match a
literal value (AppSurface.literal), the object a companion panel is attached to (AppSurface.companion), or any
subject (AppSurface.subject).
1
import*as
import Surface
Surfacefrom'@dxos/app-framework/Surface';
2
import*as
import AppSurface
AppSurfacefrom'@dxos/app-toolkit/AppSurface';
3
4
exportconst
const NoteCardSurface: ReactDefinition<T>
NoteCardSurface =
import Surface
Surface.
constcreate: <(Omit<{
subject: any;
projection?: ProjectionModel;
ignorePaths?: ReadonlyArray<string>;
editable?: boolean;
extrinsic?: boolean;
}, "subject"> & {
subject: Note & OfKind<EntityKind.Object>;
}) | (Omit<{
attendableId: string;
nodeId?: string;
subject: any;
extrinsic?: boolean;
}, "subject"> & {
subject: Note & OfKind<EntityKind.Object>;
}), {
subject: Note & OfKind<EntityKind.Object>;
}, "card">(definition: Readonly<{
id: "card";
filter: Filter<(Omit<{
subject: any;
projection?: ProjectionModel;
ignorePaths?: ReadonlyArray<string>;
editable?: boolean;
extrinsic?: boolean;
}, "subject"> & {
...;
}) | (Omit<...> & {
...;
})>;
position?: Position;
component: React.ComponentType<...>;
props?: ((props: ComponentProps<...>) => {
...;
}) | undefined;
}>) =>ReactDefinition<(Omit<...> & {
subject: Note & OfKind<EntityKind.Object>;
}) | (Omit<...> & {
subject: Note & OfKind<EntityKind.Object>;
})>
Creates a React surface definition from a typed filter.
Accepts any component type (not just a function) so a container re-exported through a
lazy() barrel as ComponentType<any> can be registered without a cast.
component:
constNoteCard: ({ subject }: {
subject: Note;
}) =>React.JSX.Element
NoteCard,
11
props?: ((props: ComponentProps<(Omit<{
subject: any;
projection?: ProjectionModel;
ignorePaths?: ReadonlyArray<string>;
editable?: boolean;
extrinsic?: boolean;
}, "subject"> & {
subject: Note & OfKind<EntityKind.Object>;
}) | (Omit<{
attendableId: string;
nodeId?: string;
subject: any;
extrinsic?: boolean;
}, "subject"> & {
subject: Note & OfKind<EntityKind.Object>;
})>) => {
subject: Note & OfKind<EntityKind.Object>;
}) | undefined
Maps the surface props onto the component's own props, so a plain container can be registered
directly instead of being wrapped in an adapter that unpacks data.
Prefer this over an inline component: ({ data }) => <Container … />: the mapper's input type
derives from the same filter that defines the surface's data shape, so the unpacking is
checked against the filter rather than restated by hand.
When several surfaces match, position on the contribution orders them. Pass Position.first or Position.last from
@dxos/util to come before or after the rest.