Created
July 28, 2022 20:22
-
-
Save kapunahelewong/7f5af890697fa062beaee1df3e7fcaf6 to your computer and use it in GitHub Desktop.
Builder Custom Component with Children
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import { Switch, Route, BrowserRouter, Link } from 'react-router-dom'; | |
import { BuilderComponent } from '@builder.io/react'; | |
import { Builder, withChildren } from '@builder.io/react'; | |
// for tabs | |
import { useState } from 'react'; | |
import { BuilderBlocks } from '@builder.io/react'; | |
import './index.css'; | |
function App() { | |
return ( | |
<BrowserRouter> | |
<header> | |
<div className="logo">MY SITE</div> | |
<div className="links"> | |
<Link className="link" to="/"> | |
Home | |
</Link> | |
<Link className="link" to="/about"> | |
About | |
</Link> | |
<Link className="link" to="/page-1"> | |
Page 1 | |
</Link> | |
<Link className="link" to="/page-2"> | |
Page 2 | |
</Link> | |
<Link className="link" to="/404"> | |
404 | |
</Link> | |
</div> | |
</header> | |
<div className="App"> | |
<Switch> | |
<Route path="/" exact component={Home} /> | |
<Route path="/about" exact component={About} /> | |
<Route render={({ location }) => <CatchallPage key={location.key} />} /> | |
</Switch> | |
</div> | |
</BrowserRouter> | |
); | |
} | |
class CatchallPage extends React.Component { | |
state = { notFound: false }; | |
render() { | |
return !this.state.notFound ? ( | |
<BuilderComponent | |
apiKey="36b55672551d40f49426c8a2712817a6" | |
model="page" | |
contentLoaded={content => { | |
if (!content) { | |
this.setState({ notFound: true }); | |
} | |
}} | |
> | |
<div className="loading">Loading...</div> | |
</BuilderComponent> | |
) : ( | |
<NotFound /> // Your 404 content | |
); | |
} | |
} | |
const Home = () => <h1>I am the homepage!</h1>; | |
const About = () => <h1>I am the about page!</h1>; | |
const NotFound = () => <h1>No page found for this URL, did you publish it?</h1>; | |
const rootElement = document.getElementById('root'); | |
ReactDOM.render(<App />, rootElement); | |
export const Hero = props => | |
<div>{props.children}</div> | |
const HeroWithBuilderChildren = withChildren(Hero) | |
Builder.registerComponent(HeroWithBuilderChildren, { | |
name: 'Hero', | |
// Adding defaults is important for easy usability | |
defaultChildren: [ | |
{ | |
'@type': '@builder.io/sdk:Element', | |
component: { name: 'Text', options: { text: 'I am child text block!' } } | |
} | |
] | |
}) | |
// Tabs | |
// 2. Create your component. | |
// This is a tabs component with some basic styles. When the user clicks on a tab, that content becomes active. | |
function Tabs(props) { | |
const [activeTab, setActiveTab] = useState(0); | |
return ( | |
<> | |
<div | |
style={{ | |
display: 'flex', | |
overflow: 'auto', | |
}} | |
> | |
{props.tabs?.map((item, index) => ( | |
<span | |
key={index} | |
style={{ | |
padding: 20, | |
color: activeTab === index ? 'blue' : '#000', | |
}} | |
onClick={() => { | |
setActiveTab(index); | |
}} | |
> | |
{item.label} | |
</span> | |
))} | |
</div> | |
{/* // This section tells BuilderBlocks what to expect: | |
// the parent id, the path to the child component, | |
// and what the blocks should be made of. | |
// Here, the blocks are made of the content of the active tab */} | |
{props.tabs?.length && ( | |
<BuilderBlocks | |
parentElementId={props.builderBlock.id} | |
dataPath={`component.options.tabs.${activeTab}.content`} | |
blocks={props.tabs[activeTab].content} | |
/> | |
)} | |
</> | |
); | |
} | |
// Register your component. This component is called Tabs, is of type list and contains two subFields as children: a label and the content. | |
// As a best practice, provide a defaultValue. The default label is "Tab 1" and the content is an empty array. | |
Builder.registerComponent(Tabs, { | |
name: 'Tabs', | |
inputs: [ | |
{ | |
name: 'tabs', | |
type: 'list', | |
subFields: [ | |
{ | |
name: 'label', | |
type: 'text', | |
defaultValue: 'New tab', | |
}, | |
{ | |
name: 'content', | |
type: 'uiBlocks', | |
defaultValue: [], | |
}, | |
], | |
defaultValue: [ | |
{ | |
label: 'Tab 1', | |
content: [], | |
}, | |
], | |
}, | |
], | |
}); | |
const Heading = props => ( | |
<h1>{props.title}</h1> | |
) | |
Builder.registerComponent(Heading, { | |
name: 'Heading', | |
hideFromInsertMenu: true, | |
inputs: [{ | |
name: 'title', | |
type: 'text', | |
defaultValue: 'I\'m version 1' }] | |
}) | |
Builder.registerComponent(Heading, { | |
name: 'Heading', | |
inputs: [{ | |
name: 'title', | |
type: 'text', | |
defaultValue: 'I\'m version 2' }] | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment