diff --git a/packages/frontend-plugin-api/src/components/createComponentRef.test.tsx b/packages/frontend-plugin-api/src/components/createComponentRef.test.tsx
index 9a84fe08fa..e20a35ff84 100644
--- a/packages/frontend-plugin-api/src/components/createComponentRef.test.tsx
+++ b/packages/frontend-plugin-api/src/components/createComponentRef.test.tsx
@@ -22,4 +22,59 @@ describe('createComponentRef', () => {
expect(ref.id).toBe('foo');
expect(String(ref)).toBe('ComponentRef{id=foo}');
});
+
+ it('should allow defining a default component implementation', () => {
+ const Test = () =>
test
;
+
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ mode: 'sync',
+ defaultComponent: ({ bar }) => ,
+ });
+
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ mode: 'async',
+ defaultComponent: async () => ,
+ });
+
+ // @ts-expect-error - this should be an error as mode is sync
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ mode: 'sync',
+ defaultComponent: async ({ bar }) => ,
+ });
+
+ // todo: why do we have two errors here?
+ // @ts-expect-error - this should be an error as mode is async
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ mode: 'async',
+ defaultComponent: ({ bar }) => ,
+ });
+
+ // todo: why does this not work?
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ // @ts-expect-error - this should be an error as default mode is async
+ defaultComponent: ({ bar }) => ,
+ });
+
+ expect(Test).toBeDefined();
+ });
+
+ it('should allow transformings props', () => {
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ transformProps: props => ({ foo: props.bar }),
+ });
+
+ createComponentRef<{ foo: string }, { bar: string }>({
+ id: 'foo',
+ // @ts-expect-error - this should be an error as foo is not a string
+ transformProps: props => ({ foo: 1 }),
+ });
+
+ expect(true).toBe(true);
+ });
});
diff --git a/packages/frontend-plugin-api/src/components/createComponentRef.tsx b/packages/frontend-plugin-api/src/components/createComponentRef.tsx
index 88181dd079..9f36e7f21e 100644
--- a/packages/frontend-plugin-api/src/components/createComponentRef.tsx
+++ b/packages/frontend-plugin-api/src/components/createComponentRef.tsx
@@ -15,20 +15,82 @@
*/
/** @public */
-export type ComponentRef = {
+export type ComponentRef<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ TMode extends 'sync' | 'async' = 'async',
+> = {
id: string;
- T: T;
+ mode: TMode;
+ transformProps?: (props: TExternalComponentProps) => TInnerComponentProps;
+ defaultComponent?: TMode extends 'async'
+ ? (props: TExternalComponentProps) => Promise
+ : (props: TExternalComponentProps) => JSX.Element;
};
-/** @public */
-export function createComponentRef(options: {
+export interface ComponentRefOptions<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ TMode extends 'sync' | 'async' = 'async',
+> {
id: string;
-}): ComponentRef {
- const { id } = options;
+ mode?: TMode;
+ defaultComponent?: TMode extends 'async'
+ ? (props: TExternalComponentProps) => Promise
+ : (props: TExternalComponentProps) => JSX.Element;
+ transformProps?: (props: TExternalComponentProps) => TInnerComponentProps;
+}
+
+/**
+ * Creates a new component ref that is synchronous.
+ * @public
+ */
+export function createComponentRef<
+ TInnerComponentProps,
+ TExternalComponentProps,
+>(
+ options: ComponentRefOptions<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ 'sync'
+ >,
+): ComponentRef;
+
+/**
+ * Creates a new component ref that is asynchronous.
+ * @public
+ */
+export function createComponentRef<
+ TInnerComponentProps,
+ TExternalComponentProps,
+>(
+ options: ComponentRefOptions<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ 'async'
+ >,
+): ComponentRef;
+
+export function createComponentRef<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ TMode extends 'sync' | 'async',
+>(
+ options: ComponentRefOptions<
+ TInnerComponentProps,
+ TExternalComponentProps,
+ TMode
+ >,
+): ComponentRef {
+ const { id, mode = 'async', defaultComponent, transformProps } = options;
+
return {
id,
+ mode,
+ defaultComponent,
+ transformProps,
toString() {
return `ComponentRef{id=${id}}`;
},
- } as ComponentRef;
+ } as ComponentRef;
}