Support rendering @motionone/solid components (#5233)

This commit is contained in:
Bjorn Lu 2022-10-28 22:42:37 +08:00 committed by GitHub
parent c6b149bc0a
commit 7f8987085c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Support rendering `@motionone/solid` components

View file

@ -57,7 +57,7 @@ export function isAstroComponent(obj: any): obj is AstroComponent {
}
export function isAstroComponentFactory(obj: any): obj is AstroComponentFactory {
return obj == null ? false : !!obj.isAstroComponentFactory;
return obj == null ? false : obj.isAstroComponentFactory === true;
}
export async function* renderAstroComponent(

View file

@ -56,7 +56,7 @@ export async function renderComponent(
_props: Record<string | number, any>,
slots: any = {}
): Promise<ComponentIterable> {
Component = await Component;
Component = (await Component) ?? Component;
switch (getComponentType(Component)) {
case 'fragment': {
@ -133,7 +133,14 @@ Did you mean to add ${formatList(probableRendererNames.map((r) => '`' + r + '`')
// If this component ran through `__astro_tag_component__`, we already know
// which renderer to match to and can skip the usual `check` calls.
// This will help us throw most relevant error message for modules with runtime errors
if (Component && (Component as any)[Renderer]) {
let isTagged = false;
try {
isTagged = Component && (Component as any)[Renderer];
} catch {
// Accessing `Component[Renderer]` may throw if `Component` is a Proxy that doesn't
// return the actual read-only value. In this case, ignore.
}
if (isTagged) {
const rendererName = (Component as any)[Renderer];
renderer = renderers.find(({ name }) => name === rendererName);
}

View file

@ -0,0 +1,16 @@
import { Dynamic } from 'solid-js/web'
const BaseComponent = ({ tag } = {}) => {
return <Dynamic id="proxy-component" component={tag || 'div'}>Hello world</Dynamic>;
}
// Motion uses a Proxy to support syntax like `<Motion.div />` and `<Motion.button />` etc
// https://cdn.jsdelivr.net/npm/@motionone/solid@10.14.2/dist/source/motion.jsx
const ProxyComponent = new Proxy(BaseComponent, {
get: (_, tag) => (props) => {
delete props.tag
return <BaseComponent {...props} tag={tag} />;
}
})
export default ProxyComponent;

View file

@ -2,6 +2,7 @@
import Hello from '../components/Hello.jsx';
import WithNewlines from '../components/WithNewlines.jsx';
import { Router } from "@solidjs/router";
import ProxyComponent from '../components/ProxyComponent.jsx';
---
<html>
<head><title>Solid</title></head>
@ -10,6 +11,7 @@ import { Router } from "@solidjs/router";
<Hello client:load />
<WithNewlines client:load />
<Router />
<ProxyComponent client:load />
</div>
</body>
</html>

View file

@ -22,6 +22,9 @@ describe('Solid component', () => {
// test 1: Works
expect($('.hello')).to.have.lengthOf(1);
// test 2: Support rendering proxy components
expect($('#proxy-component').text()).to.be.equal('Hello world');
});
});
@ -38,6 +41,17 @@ describe('Solid component', () => {
await devServer.stop();
});
it('Can load a component', async () => {
const html = await fixture.fetch('/').then((res) => res.text());
const $ = cheerio.load(html);
// test 1: Works
expect($('.hello')).to.have.lengthOf(1);
// test 2: Support rendering proxy components
expect($('#proxy-component').text()).to.be.equal('Hello world');
});
it('scripts proxy correctly', async () => {
const html = await fixture.fetch('/').then((res) => res.text());
const $ = cheerio.load(html);