Skip to content

Commit

Permalink
Support rendering @motionone/solid components (#5233)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Oct 28, 2022
1 parent c6b149b commit 7f89870
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-donuts-reply.md
@@ -0,0 +1,5 @@
---
'astro': patch
---

Support rendering `@motionone/solid` components
2 changes: 1 addition & 1 deletion packages/astro/src/runtime/server/render/astro.ts
Expand Up @@ -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(
Expand Down
11 changes: 9 additions & 2 deletions packages/astro/src/runtime/server/render/component.ts
Expand Up @@ -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': {
Expand Down Expand Up @@ -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);
}
Expand Down
@@ -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;
Expand Up @@ -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>
Expand All @@ -10,6 +11,7 @@ import { Router } from "@solidjs/router";
<Hello client:load />
<WithNewlines client:load />
<Router />
<ProxyComponent client:load />
</div>
</body>
</html>
14 changes: 14 additions & 0 deletions packages/astro/test/solid-component.test.js
Expand Up @@ -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');
});
});

Expand All @@ -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);
Expand Down

0 comments on commit 7f89870

Please sign in to comment.