Skip to content

Commit

Permalink
can return an array of elements
Browse files Browse the repository at this point in the history
  • Loading branch information
FredericHeem committed Nov 15, 2024
1 parent eee70fc commit cbcad94
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 18 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,6 @@ const bau = Bau();
const { div } = bau.tags;
```

- Bau reactive functions can return an array of elements, the equivalent of a React Fragment.
- Bau promotes only one paradigm: views derive from the state. Van could mix paradigms, imperative and state derived view. The imperative way is when your code directly maniplates the DOM, in the same way as vanilla js and jquery. This style of programming is error prone, therefore, preventing its use makes bau _hard to misuse_
- Bau supports undefined or null attribute, see [issue 39](https://github.com/vanjs-org/van/pull/39)
2 changes: 1 addition & 1 deletion bau/bau.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export type PropsAll<TElement extends HTMLElement> =

export type BindElementFunc = (input?: {
element: HTMLElement;
}) => HTMLElement | Primitive;
}) => HTMLElement | Primitive | (HTMLElement | Primitive)[];

export type ChildDom =
| Primitive
Expand Down
57 changes: 42 additions & 15 deletions bau/bau.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ let isFunction = (obj) => getType(obj) == "Function";
let isArrayOrObject = (obj) => ["Object", "Array"].includes(getType(obj));
let protoOf = Object.getPrototypeOf;
let toVal = (state) => (isState(state) ? state.val : state);
let toArray = (el) => (Array.isArray(el) ? el : [el]);
let isState = (state) => state?.__isState;
let METHODS = ["splice", "push", "pop", "shift", "unshift", "sort", "reverse"];

Expand Down Expand Up @@ -37,7 +38,10 @@ export default function Bau(input) {
if (!_debounce) {
_debounce = _window.requestAnimationFrame(() => {
stateSet.forEach((state) => {
state.bindings = state.bindings.filter((b) => b.element?.isConnected);
state.bindings = state.bindings.filter(
({ element }) =>
(Array.isArray(element) ? element[0] : element)?.isConnected
);
!state.bindings.length && !state.computed && stateSet.delete(state);
});
_debounce = undefined;
Expand Down Expand Up @@ -68,7 +72,21 @@ export default function Bau(input) {
})
: render({ element, renderItem })(...deps.map(toVal));
if (newElement !== element) {
element.replaceWith((binding.element = toDom(newElement)));
let newEls = toArray((binding.element = toDom(newElement)));
let oldEls = toArray(element);
let i = 0;
for (; i < oldEls.length && i < newEls.length; i++) {
oldEls[i].replaceWith(toDom(newEls[i]));
}
let newI = i;
while (newEls.length > newI) {
newEls[newI - 1].after(newEls[newI]);
newI++;
}
while (oldEls.length > i) {
oldEls[i].remove();
i++;
}
}
}
}
Expand Down Expand Up @@ -205,6 +223,8 @@ export default function Bau(input) {
return spanEl;
} else if (v.nodeType) {
return v;
} else if (Array.isArray(v)) {
return v.map(toDom);
} else {
return document.createTextNode(v);
}
Expand All @@ -230,22 +250,29 @@ export default function Bau(input) {
}
};

let add = (element, ...children) => {
if (children.length) {
let childrenDom = [];
for (let child of children.flat(Infinity))
child != null &&
childrenDom.push(
isState(child)
? bind({ deps: [child], render: () => (v) => v })
: isFunction(child)
? bindInferred({ renderInferred: child })
: toDom(child)
);
element.append(...childrenDom);
let _add = (childrenDom, children = []) => {
for (let child of children) {
if (Array.isArray(child)) {
_add(childrenDom, child);
} else if (child != null) {
const newChild = isState(child)
? bind({ deps: [child], render: () => (v) => v })
: isFunction(child)
? bindInferred({ renderInferred: child })
: toDom(child);
Array.isArray(newChild)
? childrenDom.push(...newChild)
: childrenDom.push(newChild);
}
}
};

let add = (element, ...children) => {
let childrenDom = [];
_add(childrenDom, children);
element.append(...childrenDom);
};

let isSettablePropCache = {};

let getPropDescriptor = (proto, key) =>
Expand Down
28 changes: 26 additions & 2 deletions bau/examples/bau-ts-test/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const {
span,
input,
h1,
h2,
p,
article,
label,
Expand Down Expand Up @@ -514,6 +515,29 @@ const TestDeriveText = () => {
)
);
};
const TestDeriveReturnArray = () => {
const showState = bau.state(true);

return article(
h1("Derive returns an array of element"),
button(
{
onclick: () => (showState.val = !showState.val),
},
"TOOGLE"
),
p("First element object, second is an array"),
div(() => (showState.val ? div("1") : [div("3"), div("4"), "Text node"])),
p("First element is an array, second is a smaller array"),
div(() =>
showState.val ? [div("A"), div("B"), "Text node"] : ["Other Text node"]
),
p("First element is an array, second is a object"),
div(() =>
showState.val ? [div("A"), div("B"), "Text node"] : "Other Text node"
)
);
};

const TestButtonClickInline = () => {
return section(
Expand Down Expand Up @@ -823,10 +847,10 @@ const App = ({}) => {
),
section(
h1("Derive"),
//
TestDerived(),
TestDerivedSideEffect(),
TestDeriveText()
TestDeriveText(),
TestDeriveReturnArray()
),

section(
Expand Down

0 comments on commit cbcad94

Please sign in to comment.