Skip to content

Commit

Permalink
fix: nested component property forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinBLT committed Jan 10, 2024
1 parent 676c3d8 commit d2fbc59
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 24 deletions.
5 changes: 4 additions & 1 deletion packages/@hec.js/ui/example/nested-component/a.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
<div>{{ text }}</div>
<c-b text="text"></c-b>


<c-b text="e.text" data-for="let e of list"></c-b>
<c-c person="e" data-for="let e of list"></c-c>
4 changes: 3 additions & 1 deletion packages/@hec.js/ui/example/nested-component/a.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { component, templateByName } from '../../lib/index.js';

component('c-a', { text: 'Hi' }, (props) => {

const list = Array.from({ length: 2 }, () => ({ text: props.text }));

return templateByName('./a.html', props);
return templateByName('./a.html', { list, text: props.text });
});
4 changes: 3 additions & 1 deletion packages/@hec.js/ui/example/nested-component/b.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ import { component, templateByName } from '../../lib/index.js';

component('c-b', { text: '' }, (props) => {

return templateByName('./b.html', props);
return templateByName('./b.html', {
text: () => props.text()
});
});
1 change: 1 addition & 0 deletions packages/@hec.js/ui/example/nested-component/c.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div>Hi nested object named: {{ text }}</div>
8 changes: 8 additions & 0 deletions packages/@hec.js/ui/example/nested-component/c.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { component, templateByName } from '../../lib/index.js';

component('c-c', { person: { text: '' } }, (props) => {

return templateByName('./c.html', {
text: () => props.person().text
});
});
1 change: 1 addition & 0 deletions packages/@hec.js/ui/example/nested-component/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<title>hec.js :: Component</title>
<script type="module" async src="./a.js"></script>
<script type="module" async src="./b.js"></script>
<script type="module" async src="./c.js"></script>
</head>
<body>

Expand Down
18 changes: 8 additions & 10 deletions packages/@hec.js/ui/lib/src/component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { notifyVisible } from "./notify/visible.js";
import { f, nodeProps, prop, propsOf } from "./props.js";
import { deletePropsOf, f, prop, propsOf, setPropsOf } from "./props.js";
import { isSignal, signal } from "./signal.js";

/**
Expand Down Expand Up @@ -72,19 +72,17 @@ export function component(name, props, fn) {

/** @param { Node } node */
const append = (node) => {
const exProps = nodeProps.get(this);

nodeProps.set(
this, Object.assign(propsOf(node), (typeof exProps === 'object' ? exProps : null) ?? {})
);
console.log(this.localName);

setPropsOf(this, propsOf(node));

this.dispatchEvent(new CustomEvent('::loaded', { bubbles: true }));

shadow.append(node);

this.#aborts['::attributes'] = new AbortController();

for (const k in this.#signals) {
for (const k in props) {

if (!this.hasAttribute(k)) {
this.setAttribute(k, props[k].toString());
Expand All @@ -102,7 +100,7 @@ export function component(name, props, fn) {
}

disconnectedCallback() {
nodeProps.delete(this);
deletePropsOf(this);

for (const k in this.#aborts) {
this.#aborts[k].abort();
Expand Down Expand Up @@ -138,8 +136,8 @@ export function component(name, props, fn) {

if (value.startsWith('@parent.')) { // @ts-ignore
const parent = this.parentNode.host || this.parentNode,
parentProps = propsOf(parent),
parentProp = prop(parentProps, value.slice(8));
key = value.slice(8),
parentProp = prop(propsOf(parent), key) ?? prop(propsOf(this), key);

if (isSignal(parentProp)) {
this.#aborts[p]?.abort();
Expand Down
1 change: 0 additions & 1 deletion packages/@hec.js/ui/lib/src/plugins/data-for.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export const dataForPlugin = {
});

done.add(c);

n.after(templateByNode(c, p));
n = n.nextSibling;
}
Expand Down
47 changes: 45 additions & 2 deletions packages/@hec.js/ui/lib/src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@ import { isSignal, signal } from "./signal.js";
* @template T
* @type { WeakMap<Node, { [key: string]: any }> }
*/
export const nodeProps = new WeakMap();
const nodeProps = new WeakMap();

/** @param { Node } node */
export const propsOf = (node) => nodeProps.get(node);
export const deletePropsOf = (node) => nodeProps.delete(node);

export const setPropsOf = (node, props) => {
const existing = propsOf(node);

if (existing && typeof existing === 'object' ) {
nodeProps.set(node, Object.assign(existing, props));
} else {
nodeProps.set(node, props);
}

}

/**
* @param { any | function(): any} v
Expand Down Expand Up @@ -63,10 +75,41 @@ export function prop(props, key) {

} else if (typeof props === 'function') {
props = f(props);
} else {
} else if (typeof props[p] !== 'undefined') {
props = props[p];
} else {
return null;
}
}

return props;
}

/**
* @param { {[key: string]: any} } props
* @param { string } key
* @returns { boolean }
*/
export function hasProp(props, key) {
const chain = key.split('.');

if (!key) {
return false;
}

for (const p of chain) {

if (['loading', 'error'].includes(p) && props?.loading && props?.error) {
return props[p];
} else if (typeof props === 'function') {
props = f(props);
} else if (typeof props[p] !== 'undefined') {
props = props[p];
} else {
return false;
}

}

return true;
}
12 changes: 4 additions & 8 deletions packages/@hec.js/ui/lib/src/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expression } from './expression.js';
import { pipes } from './pipes.js';
import { plugins } from './plugins.js';
import { isSignal } from './signal.js';
import { f, nodeProps, prop } from './props.js';
import { f, setPropsOf, prop, hasProp } from './props.js';

/** @type {{ [key: string]: Promise<HTMLTemplateElement> }} */
const templatesLoading = {}
Expand Down Expand Up @@ -63,10 +63,6 @@ export function templateByString(template, props = {}) {
*/
export function templateByNode(template, props = {}) {

if (nodeProps.has(template)) {
return;
}

/**
* @param { string } text
* @param { function(string): void } update
Expand Down Expand Up @@ -142,12 +138,12 @@ export function templateByNode(template, props = {}) {
let stopFlag = false;

if (node.nodeName == '#document-fragment') {
nodeProps.set(node, props);
setPropsOf(node, props);
}

if (node instanceof HTMLElement) {

nodeProps.set(node, props);
setPropsOf(node, props);

for (const plugin of plugins) {
if (node.matches(plugin.select)) {
Expand All @@ -170,7 +166,7 @@ export function templateByNode(template, props = {}) {
node.setAttribute(attributeName, text.trim().replace(/ +/, ' '))
});

} else if (node.localName.includes('-') && props[attribute]) {
} else if (node.localName.includes('-') && hasProp(props, attribute)) {
node.setAttribute(attributeName, `@parent.${attribute}`);
}
}
Expand Down

0 comments on commit d2fbc59

Please sign in to comment.