chore: started initial work on implementing interal vs external props
Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
@@ -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 = () => <div>test</div>;
|
||||
|
||||
createComponentRef<{ foo: string }, { bar: string }>({
|
||||
id: 'foo',
|
||||
mode: 'sync',
|
||||
defaultComponent: ({ bar }) => <Test key={bar} />,
|
||||
});
|
||||
|
||||
createComponentRef<{ foo: string }, { bar: string }>({
|
||||
id: 'foo',
|
||||
mode: 'async',
|
||||
defaultComponent: async () => <Test />,
|
||||
});
|
||||
|
||||
// @ts-expect-error - this should be an error as mode is sync
|
||||
createComponentRef<{ foo: string }, { bar: string }>({
|
||||
id: 'foo',
|
||||
mode: 'sync',
|
||||
defaultComponent: async ({ bar }) => <Test key={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 }) => <Test key={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 }) => <Test key={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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,20 +15,82 @@
|
||||
*/
|
||||
|
||||
/** @public */
|
||||
export type ComponentRef<T extends {} = {}> = {
|
||||
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<JSX.Element>
|
||||
: (props: TExternalComponentProps) => JSX.Element;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export function createComponentRef<T extends {} = {}>(options: {
|
||||
export interface ComponentRefOptions<
|
||||
TInnerComponentProps,
|
||||
TExternalComponentProps,
|
||||
TMode extends 'sync' | 'async' = 'async',
|
||||
> {
|
||||
id: string;
|
||||
}): ComponentRef<T> {
|
||||
const { id } = options;
|
||||
mode?: TMode;
|
||||
defaultComponent?: TMode extends 'async'
|
||||
? (props: TExternalComponentProps) => Promise<JSX.Element>
|
||||
: (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<TInnerComponentProps, TExternalComponentProps, 'sync'>;
|
||||
|
||||
/**
|
||||
* Creates a new component ref that is asynchronous.
|
||||
* @public
|
||||
*/
|
||||
export function createComponentRef<
|
||||
TInnerComponentProps,
|
||||
TExternalComponentProps,
|
||||
>(
|
||||
options: ComponentRefOptions<
|
||||
TInnerComponentProps,
|
||||
TExternalComponentProps,
|
||||
'async'
|
||||
>,
|
||||
): ComponentRef<TInnerComponentProps, TExternalComponentProps, 'async'>;
|
||||
|
||||
export function createComponentRef<
|
||||
TInnerComponentProps,
|
||||
TExternalComponentProps,
|
||||
TMode extends 'sync' | 'async',
|
||||
>(
|
||||
options: ComponentRefOptions<
|
||||
TInnerComponentProps,
|
||||
TExternalComponentProps,
|
||||
TMode
|
||||
>,
|
||||
): ComponentRef<TInnerComponentProps, TExternalComponentProps, TMode> {
|
||||
const { id, mode = 'async', defaultComponent, transformProps } = options;
|
||||
|
||||
return {
|
||||
id,
|
||||
mode,
|
||||
defaultComponent,
|
||||
transformProps,
|
||||
toString() {
|
||||
return `ComponentRef{id=${id}}`;
|
||||
},
|
||||
} as ComponentRef<T>;
|
||||
} as ComponentRef<TInnerComponentProps, TExternalComponentProps, TMode>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user