-
Notifications
You must be signed in to change notification settings - Fork 950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EDU-159: Remix Gen1 - Advanced child sub components #3750
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// routes/advanced-child.tsx | ||
import { Builder, BuilderComponent, builder } from '@builder.io/react'; | ||
import type { LoaderFunctionArgs } from '@remix-run/node'; | ||
import { useLoaderData } from '@remix-run/react'; | ||
import CustomTabs from './components/CustomTabs'; | ||
|
||
builder.init('ee9f13b4981e489a9a1209887695ef2b'); | ||
|
||
Builder.registerComponent(CustomTabs, { | ||
name: 'TabFields', | ||
inputs: [ | ||
{ | ||
name: 'tabList', | ||
type: 'array', | ||
defaultValue: [], | ||
subFields: [ | ||
{ | ||
name: 'tabName', | ||
type: 'string', | ||
}, | ||
{ | ||
name: 'blocks', | ||
type: 'uiBlocks', | ||
hideFromUI: true, | ||
defaultValue: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}); | ||
|
||
export const loader = async ({ request }: LoaderFunctionArgs) => { | ||
const page = await builder | ||
.get('advanced-child', { | ||
userAttributes: { | ||
urlPath: `/${request.url.split('/').pop()}`, | ||
}, | ||
}) | ||
.toPromise(); | ||
|
||
return { page }; | ||
}; | ||
|
||
export default function AdvancedChildPage() { | ||
const { page } = useLoaderData<typeof loader>(); | ||
|
||
return <BuilderComponent model="advanced-child" content={page} />; | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,25 @@ | ||||||
import { BuilderBlocks, BuilderElement } from '@builder.io/react'; | ||||||
|
||||||
interface CustomColumnsProps { | ||||||
column1: { blocks: React.ReactNode }; | ||||||
column2: { blocks: React.ReactNode }; | ||||||
builderBlock: BuilderElement; | ||||||
} | ||||||
|
||||||
export const CustomColumns = (props: CustomColumnsProps) => { | ||||||
return ( | ||||||
<> | ||||||
<BuilderBlocks | ||||||
parentElementId={props.builderBlock.id} | ||||||
dataPath={`column1.blocks`} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
blocks={props.column1?.blocks} | ||||||
/> | ||||||
|
||||||
<BuilderBlocks | ||||||
parentElementId={props.builderBlock.id} | ||||||
dataPath={`column2.blocks`} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
blocks={props.column2?.blocks} | ||||||
/> | ||||||
</> | ||||||
); | ||||||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,14 @@ | ||||||||||||||||||||||
import { ReactNode } from 'react'; | ||||||||||||||||||||||
|
||||||||||||||||||||||
interface CustomHeroProps { | ||||||||||||||||||||||
children: ReactNode; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
export const CustomHero = (props: CustomHeroProps) => { | ||||||||||||||||||||||
Comment on lines
+1
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
return ( | ||||||||||||||||||||||
<> | ||||||||||||||||||||||
<div>This is your component's text</div> | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||
{props.children} | ||||||||||||||||||||||
</> | ||||||||||||||||||||||
); | ||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { BuilderBlocks, BuilderElement } from '@builder.io/react'; | ||
|
||
import { useState } from 'react'; | ||
|
||
type TabProps = { | ||
tabList: { tabName: string; blocks: React.ReactNode[] }[]; | ||
builderBlock: BuilderElement; | ||
}; | ||
|
||
export default function CustomTabs({ tabList, builderBlock }: TabProps) { | ||
const [activeTab, setActiveTab] = useState(0); | ||
|
||
if (!tabList?.length) return null; | ||
|
||
return ( | ||
<> | ||
<div className="tab-buttons"> | ||
{tabList.map((tab, index) => ( | ||
<button | ||
key={index} | ||
className={`tab-button ${activeTab === index ? 'active' : ''}`} | ||
onClick={() => setActiveTab(index)} | ||
> | ||
{tab.tabName} | ||
</button> | ||
))} | ||
</div> | ||
|
||
<BuilderBlocks | ||
parentElementId={builderBlock?.id} | ||
dataPath={`tabList.${activeTab}.blocks`} | ||
blocks={tabList[activeTab].blocks} | ||
/> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Builder, builder, BuilderComponent } from '@builder.io/react'; | ||
|
||
import { LoaderFunctionArgs } from '@remix-run/node'; | ||
import { useLoaderData } from '@remix-run/react'; | ||
import { CustomHero } from './components/CustomHero'; | ||
|
||
builder.init('ee9f13b4981e489a9a1209887695ef2b'); | ||
|
||
Builder.registerComponent(CustomHero, { | ||
name: 'CustomHero', | ||
inputs: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need to provide an empty array, we can drop this altogether. If you can confirm that, go ahead and remove all empty |
||
canHaveChildren: true, | ||
defaultChildren: [ | ||
{ | ||
'@type': '@builder.io/sdk:Element', | ||
component: { | ||
name: 'Text', | ||
options: { | ||
text: 'This is Builder text', | ||
}, | ||
}, | ||
}, | ||
], | ||
}); | ||
|
||
export const loader = async ({ request }: LoaderFunctionArgs) => { | ||
const page = await builder | ||
.get('custom-child', { | ||
userAttributes: { | ||
urlPath: `/${request.url.split('/').pop()}`, | ||
}, | ||
}) | ||
.toPromise(); | ||
|
||
return { page }; | ||
}; | ||
|
||
export default function CustomChildPage() { | ||
const { page } = useLoaderData<typeof loader>(); | ||
|
||
return <BuilderComponent model="custom-child" content={page} />; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||||||||||||||||||
// routes/advanced-child.tsx | ||||||||||||||||||||||||||||||||||||||||||
import { Builder, BuilderComponent, builder } from "@builder.io/react"; | ||||||||||||||||||||||||||||||||||||||||||
import type { LoaderFunctionArgs } from "@remix-run/node"; | ||||||||||||||||||||||||||||||||||||||||||
import { useLoaderData } from "@remix-run/react"; | ||||||||||||||||||||||||||||||||||||||||||
import { CustomColumns } from "./components/CustomColumns"; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
builder.init("ee9f13b4981e489a9a1209887695ef2b"); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
Builder.registerComponent(CustomColumns, { | ||||||||||||||||||||||||||||||||||||||||||
name: "MyColumns", | ||||||||||||||||||||||||||||||||||||||||||
inputs: [ | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
name: "column1", | ||||||||||||||||||||||||||||||||||||||||||
type: "uiBlocks", | ||||||||||||||||||||||||||||||||||||||||||
broadcast: true, | ||||||||||||||||||||||||||||||||||||||||||
hideFromUI: true, | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't think we need |
||||||||||||||||||||||||||||||||||||||||||
defaultValue: { | ||||||||||||||||||||||||||||||||||||||||||
blocks: [], | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
name: "column2", | ||||||||||||||||||||||||||||||||||||||||||
type: "uiBlocks", | ||||||||||||||||||||||||||||||||||||||||||
broadcast: true, | ||||||||||||||||||||||||||||||||||||||||||
hideFromUI: true, | ||||||||||||||||||||||||||||||||||||||||||
defaultValue: { | ||||||||||||||||||||||||||||||||||||||||||
blocks: [], | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export const loader = async ({ request }: LoaderFunctionArgs) => { | ||||||||||||||||||||||||||||||||||||||||||
const page = await builder | ||||||||||||||||||||||||||||||||||||||||||
.get("editable-regions", { | ||||||||||||||||||||||||||||||||||||||||||
userAttributes: { | ||||||||||||||||||||||||||||||||||||||||||
urlPath: `/${request.url.split("/").pop()}`, | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of builder/packages/sdks/e2e/remix/app/routes/($slug).tsx Lines 44 to 53 in b346d87
by naming the file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do it in the snippets already too. See: builder/packages/sdks/snippets/gen1-remix/app/routes/announcements.$slug.tsx Lines 12 to 21 in b346d87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i just realized this suggestion of mine doesn't work because the routes you added in this PR are hardcoded with exact URLs 🤔 forget what i said for now, and let's stick with your approach |
||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||
.toPromise(); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
return { page }; | ||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
export default function EditableRegionsPage() { | ||||||||||||||||||||||||||||||||||||||||||
const { page } = useLoaderData<typeof loader>(); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
return <BuilderComponent model="editable-regions" content={page} />; | ||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does remix gen1= have its own special test here? why aren't we enabling the existing tests in this spec for remix?