Skip to content

Commit

Permalink
Add ability to add children
Browse files Browse the repository at this point in the history
  • Loading branch information
ghivert committed Jul 18, 2024
1 parent 6a2ca5d commit bf125e9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 33 deletions.
29 changes: 24 additions & 5 deletions src/main.ffi.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect } from "react";
import runtime from "react/jsx-runtime";
import * as gleam from "./gleam.mjs";
import ReactDOM from "react-dom/client";
import runtime from "react/jsx-runtime";

export function createRoot(value) {
const node = document.getElementById(value);
Expand All @@ -11,10 +12,23 @@ export function render(root, children) {
return root.render(children);
}

// Extract children from props to give it to function.
export function addProxy(val) {
return new Proxy(val, {
apply(target, thisArg, argumentsList) {
const props = argumentsList[0];
return target(props, gleam.List.fromArray(props.children));
},
});
}

// Generate JSX
export function jsx(value, props_, children_) {
if (value === "text_") return children_;
let children = children_?.toArray() ?? [];
let isStatic = true;

// Keyed elements
if (Array.isArray(children[0])) {
children = children.map((c) => {
const [key, node] = c;
Expand All @@ -23,6 +37,8 @@ export function jsx(value, props_, children_) {
});
isStatic = false;
}

// Generate correct props
const props = {};
Object.assign(props, props_);
if (children.length > 0) props.children = children;
Expand All @@ -41,13 +57,16 @@ export function useTimeout(setter) {
}, []);
}

export function useHelloEffect(deps) {
export function useHelloEffect(deps, content) {
useEffect(() => {
console.log("hello");
console.log("");
console.log("hello", content);
}, deps.toArray());
}

export function strictMode(children) {
return jsx(React.StrictMode, { children: children.toArray() });
return jsx(React.StrictMode, {}, children);
}

export function fragment(children) {
return jsx(React.Fragment, {}, children);
}
47 changes: 33 additions & 14 deletions src/main.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gleam/dynamic
import gleam/int
import gleam/io
import gleam/list

pub type Root

Expand All @@ -19,16 +20,35 @@ fn render(root: Root, children: Component) -> Nil
@external(javascript, "./main.ffi.mjs", "jsx")
fn jsx(value: a, props: b, children: c) -> Component

@external(javascript, "./main.ffi.mjs", "fragment")
fn fragment(children: List(Component)) -> Component

pub fn main() {
let root = root()
create_root("root")
|> render(root([]))
|> render(strict_mode([root([])]))
// |> render(children())
}

@external(javascript, "./main.ffi.mjs", "strictMode")
pub fn strict_mode(children: List(Component)) -> Component

@external(javascript, "./main.ffi.mjs", "addProxy")
fn add_proxy(
a: fn(props, List(Component)) -> Component,
) -> fn(props, List(Component)) -> Component

pub fn component(
name: String,
component: fn(props, List(Component)) -> Component,
) -> fn(props, List(Component)) -> Component {
let component =
component
|> add_proxy
|> set_function_name(name)
fn(props, children) { jsx(component, props, children) }
}

pub type Props {
Props
}
Expand Down Expand Up @@ -63,7 +83,7 @@ pub fn text(content) -> Component {
@external(javascript, "./main.ffi.mjs", "setFunctionName")
fn set_function_name(a: a, name: String) -> a

pub fn component(
pub fn component_(
name: String,
val: fn(props) -> Component,
) -> fn(props) -> Component {
Expand All @@ -81,18 +101,15 @@ fn use_state_(default: a) -> #(a, fn(fn(a) -> a) -> Nil)
fn use_timeout(default: fn() -> Nil) -> Nil

@external(javascript, "./main.ffi.mjs", "useHelloEffect")
fn use_hello_effect(deps: List(a)) -> Nil
fn use_hello_effect(deps: List(a), content: String) -> Nil

pub fn root() {
let inside = mk_inside()
use props <- component("Root")
use props <- component_("Root")
let #(state, set_state) = use_state_(0)
use_timeout(fn() {
use state <- set_state()
state + 1
})
use_hello_effect([])
strict_mode([app(), inside(InsideProps(state))])
use_hello_effect([], "root")
use_timeout(fn() { set_state(fn(state) { state + 1 }) })
fragment([app(), inside(InsideProps(state))])
}

pub type InsideProps {
Expand All @@ -101,14 +118,16 @@ pub type InsideProps {

pub fn mk_inside() {
let inside = mk_inside_help()
use props: InsideProps <- component("Insider")
use props: InsideProps <- component_("Insider")
use_hello_effect([], "inside")
keyed(div([], _), [
#("inside", inside(props)),
#("inside", inside(props, [div([], [text("From Children!")])])),
#("text", div([], [text("inside " <> int.to_string(props.count))])),
])
}

pub fn mk_inside_help() {
use props: InsideProps <- component("InsiderHelp")
div([], [text("inside " <> int.to_string(props.count))])
use props: InsideProps, children <- component("InsiderHelp")
use_hello_effect([], "inside_help")
div([], [text("inside " <> int.to_string(props.count)), fragment(children)])
}
39 changes: 25 additions & 14 deletions src/main.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
import React from "react";
import React, { useEffect } from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
<Test />
<Test21 />
</React.StrictMode>,
);

export function useHelloEffect(content) {
useEffect(() => {
console.log("hello", content);
}, [content]);
}

export function App() {
useHelloEffect("app");
return <Test />;
}

export function Test() {
return (
<div>
<a>Muf</a>
<a>Muf</a>
<a>Muf</a>
<a>Muf</a>
</div>
);
useHelloEffect("test");
return <Test21 />;
// return (
// <div>
// <a>Muf</a>
// <a>Muf</a>
// <a>Muf</a>
// <a>Muf</a>
// </div>
// );
}

export function Test21() {
useHelloEffect("Test21");
return (
<div>
{new Array(5).fill(0).map(() => (
<a>Mumuf</a>
{new Array(5).fill(0).map((_, index) => (
<a key={index}>Mumuf</a>
))}
</div>
);
Expand Down

0 comments on commit bf125e9

Please sign in to comment.