Skip to content
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

builder widgets implemented in mitosis #2338

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/sdks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
"dependencies": {
"@builder.io/mitosis": "^0.0.106",
"@builder.io/mitosis-cli": "^0.0.64",
"@glidejs/glide": "^3.6.0",
"masonry-layout": "^4.2.2",
"node-fetch": "^2.6.1",
"seedrandom": "^3.0.5",
"traverse": "^0.6.6"
Expand Down
120 changes: 120 additions & 0 deletions packages/sdks/src/widgets/Accordion/accordion-item.lite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Show, useStore, useContext, For } from '@builder.io/mitosis';
import type { BuilderElement } from '../../types/element';
import RenderBlocks from '../../components/render-blocks.lite';
import RenderBlock from '../../components/render-block/render-block.lite';
import BuilderContext from '../../context/builder.context.lite';

export interface AccordionItem {
state: any;
titleBlocks: BuilderElement[];
detailBlocks: BuilderElement[];
index: number;
openGridItemOrder: number | null;
onlyOneAtATime: boolean;
fromChildren: boolean;
}

export default function AccordionItem(props: any) {
const state = useStore({
isOpen: props.state.open.indexOf(props.index) !== -1,
});
const context = useContext(BuilderContext);
return (
<div key={props.index}>
<div
className={`builder-accordion-title builder-accordion-title-${
state.isOpen ? 'open' : 'closed'
}`}
css={{
cursor: 'pointer',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
// ...(props.grid && {
// width: props.gridRowWidth,
// ...(typeof props.openGridItemOrder === 'number' && {
// order:
// props.index < props.openGridItemOrder
// ? props.index
// : props.index + 1,
// }),
// }),
}}
data-index={props.index}
onClick={() => {
if (state.isOpen) {
props.state.open = props.onlyOneAtATime
? []
: props.state.open.filter((item: any) => item !== props.index);
} else {
props.state.open = props.onlyOneAtATime
? [props.index]
: props.state.open.concat(props.index);
}
}}
>
<Show
when={props.fromChildren && props.titleBlocks.length}
else={
<RenderBlocks
blocks={props.titleBlocks}
path={`items.${props.index}.title`}
/>
}
>
<For each={props.titleBlocks}>
{(block: any, index) => (
<RenderBlock
key={index}
block={{
...block,
repeat: null,
}}
context={context}
/>
)}
</For>
</Show>
</div>
<Show when={state.isOpen}>
<div
className={`builder-accordion-detail builder-accordion-detail-${
state.isOpen ? 'open' : 'closed'
}`}
// css={{
// order:
// typeof props.openGridItemOrder === 'number'
// ? props.openGridItemOrder
// : undefined,
// ...(props.grid && {
// width: '100%',
// }),
// }}
>
<Show
when={props.fromChildren && props.detailBlocks.length}
else={
<RenderBlocks
blocks={props.detailBlocks}
path={`items.${props.index}.detail`}
/>
}
>
<For each={props.detailBlocks}>
{(block: any, index) => (
<RenderBlock
key={index}
block={{
...block,
repeat: null,
}}
context={context}
/>
)}
</For>
</Show>
</div>
</Show>
</div>
);
}
131 changes: 131 additions & 0 deletions packages/sdks/src/widgets/Accordion/accordion.lite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import type { BuilderElement } from '../../types/element';
import { useStore, Show, For } from '@builder.io/mitosis';
import AccordionItem from './accordion-item.lite';

interface AccordionProps {
items: {
title: BuilderElement[];
detail: BuilderElement[];
}[];
oneAtATime?: boolean;
grid?: boolean;
defaultOpen?: any; // does not exist in accordion.config
builderBlock?: BuilderElement; // does not exist in accordion.config
// TODO: gridRowWidth
gridRowWidth?: number;
useChildrenForItems?: boolean;
}

export interface AccordionState {
open: any;
onlyOneAtATime: boolean;
getOpenGridItemPosition: number | boolean | undefined;
openGridItemOrder: number | null;
}

export default function Accordion(props: AccordionProps) {
const state = useStore<AccordionState>({
open: [],
onlyOneAtATime: Boolean(props.grid || props.oneAtATime),
getOpenGridItemPosition: props.grid && open.length,
openGridItemOrder: null,
});

// if (state.getOpenGridItemPosition) {
// const openItemIndex = state.open[0]
// const openItem = document.querySelector(
// `.builder-accordion-title[data-index="${openItemIndex}"]`
// )

// let subjectItem = openItem
// state.openGridItemOrder = openItemIndex

// if (subjectItem) {
// let prevItemRect = subjectItem.getBoundingClientRect()

// while (
// (subjectItem = subjectItem && subjectItem.nextElementSibling)
// ) {
// if (subjectItem) {
// if (
// subjectItem.classList.contains(
// 'builder-accordion-detail'
// )
// ) {
// continue
// }
// const subjectItemRect = subjectItem.getBoundingClientRect()
// if (subjectItemRect.left > prevItemRect.left) {
// const index = parseInt(
// subjectItem.getAttribute('data-index') || '',
// 10
// )
// if (!isNaN(index)) {
// prevItemRect = subjectItemRect
// // @ts-ignore
// state.openGridItemOrder = index
// }
// } else {
// break
// }
// }
// }
// }
// }

// if (typeof state.openGridItemOrder === 'number') {
// state.openGridItemOrder = state.openGridItemOrder + 1
// }

return (
<div
className="builder-accordion"
css={{
display: 'flex',
alignItems: 'stretch',
flexDirection: 'column',
// ...(grid && {
// flexDirection: 'row',
// alignItems: 'flex-start',
// flexWrap: 'wrap',
// }),
}}
>
<Show
when={
props.useChildrenForItems &&
props.builderBlock &&
props.builderBlock.children
}
>
<For each={props.builderBlock.children}>
{(block: any, index) => (
<AccordionItem
state={state}
titleBlocks={block.children ? block.children[0] : []}
detailBlocks={block.children ? block.children[1] : []}
index={index}
openGridItemOrder={state.openGridItemOrder}
onlyOneAtATime={state.onlyOneAtATime}
fromChildren={true}
/>
)}
</For>
</Show>
<Show when={!props.useChildrenForItems && props.items}>
<For each={props.items}>
{(item, index) => (
<AccordionItem
state={state}
titleBlocks={item.title}
detailBlocks={item.detail}
index={index}
openGridItemOrder={state.openGridItemOrder}
onlyOneAtATime={state.onlyOneAtATime}
/>
)}
</For>
</Show>
</div>
);
}
31 changes: 31 additions & 0 deletions packages/sdks/src/widgets/Carousel/carousel.lite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Slider from './slider.lite';
import type { BuilderElement } from '../../types/element';
type BuilderBlockType = BuilderElement;

interface CarouselProps {
slides: Array<any | { content: BuilderBlockType[] }>;
builderBlock: BuilderBlockType;
nextButton?: BuilderBlockType[];
prevButton?: BuilderBlockType[];
autoplay?: boolean;
autoplaySpeed?: number;
hideDots?: boolean;
useChildrenForSlides?: boolean;
}

export default function Carousel(props: CarouselProps) {
return (
<Slider
builderBlock={props.builderBlock}
useChildrenForSlides={props.useChildrenForSlides}
slides={props.slides}
autoplay={props.autoplay}
autoplaySpeed={
props.autoplaySpeed ? props.autoplaySpeed * 1000 : undefined
}
dots={!props.hideDots}
prevArrow={props.prevButton}
frontArrow={props.nextButton}
/>
);
}