@azothjs/maya
Advanced tools
Comparing version 0.4.0 to 0.4.1
@@ -1,1 +0,2 @@ | ||
export * from './KeyedBlock.js'; | ||
export * from './KeyedBlock.js'; | ||
export * from './Toggle.js'; |
@@ -46,5 +46,3 @@ export const IGNORE = Symbol.for('azoth.compose.IGNORE'); | ||
// unlike create or compose element | ||
let out = slottable | ||
? input(props, slottable) | ||
: props ? input(props) : input(); | ||
let out = input(props, slottable); | ||
compose(anchor, out, keepLast); | ||
@@ -91,29 +89,17 @@ break; | ||
export function composeComponent(anchor, [Constructor, props, slottable]) { | ||
// if(anchor.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { | ||
// const fragment = anchor; | ||
// anchor = document.createComment('0'); | ||
// fragment.appen | ||
// } | ||
create(Constructor, props, slottable, anchor); | ||
createCompose(Constructor, props, slottable, anchor); | ||
} | ||
export function createComponent(Constructor, props, slottable, topLevel = false) { | ||
const result = create(Constructor, props, slottable); | ||
if(!topLevel) return result; | ||
export function createCompose(Constructor, props, slottable, anchor) { | ||
const out = create(Constructor, props, slottable, anchor); | ||
if(out !== anchor) compose(anchor, out); | ||
} | ||
// result is returned to caller, not composed by Azoth, | ||
// force to be of type Node or null: | ||
// strings and numbers into text nodes | ||
// non-values to null | ||
const type = typeof result; | ||
switch(true) { | ||
case type === 'string': | ||
case type === 'number': | ||
export function createComponent(Constructor, props, slottable) { | ||
const result = create(Constructor, props, slottable, null); | ||
switch(typeof result) { | ||
case 'string': | ||
case 'number': | ||
return document.createTextNode(result); | ||
case result === undefined: | ||
case result === null: | ||
case result === true: | ||
case result === false: | ||
case result === IGNORE: | ||
return null; | ||
default: | ||
@@ -126,2 +112,3 @@ return result; | ||
const type = typeof input; | ||
switch(true) { | ||
@@ -132,3 +119,6 @@ case input instanceof Node: | ||
case type === 'string': | ||
return input; | ||
case type === 'number': | ||
case type === 'bigint': | ||
return `${input}`; | ||
case input === undefined: | ||
@@ -140,9 +130,12 @@ case input === null: | ||
case input === IGNORE: | ||
return anchor ? void compose(anchor, input) : input; | ||
return null; | ||
// class and function(){} | ||
case !!(input.prototype?.constructor): { | ||
// eslint-disable-next-line new-cap | ||
return create(new input(props, slottable), null, null, anchor); | ||
return new input(props, slottable); | ||
} | ||
case type === 'function': | ||
return create(input(props, slottable), null, null, anchor); | ||
// arrow () => {} | ||
case type === 'function': { | ||
return input(props, slottable) ?? null; | ||
} | ||
case type !== 'object': { | ||
@@ -153,8 +146,16 @@ throwTypeError(input, type); | ||
case isRenderObject(input): | ||
return create(input.render(props, slottable), null, null, anchor); | ||
return input.render(props, slottable) ?? null; | ||
default: { | ||
// these inputs require a comment anchor to which they can render | ||
if(!anchor) anchor = document.createComment('0'); | ||
let container = anchor; | ||
if(!container) { | ||
anchor = document.createComment('0'); | ||
container = document.createDocumentFragment(); | ||
container.append(anchor); | ||
} | ||
if(input[Symbol.asyncIterator]) { | ||
if(input instanceof SyncAsync) { | ||
createCompose(input.sync, props, slottable, anchor); | ||
createCompose(input.async, props, slottable, anchor); | ||
} | ||
else if(input[Symbol.asyncIterator]) { | ||
composeAsyncIterator(anchor, input, false, props, slottable); | ||
@@ -164,18 +165,9 @@ } | ||
input.then(value => { | ||
create(value, props, slottable, anchor); | ||
createCompose(value, props, slottable, anchor); | ||
}); | ||
} | ||
else if(Array.isArray(input)) { | ||
// TODO: map to createCompose | ||
composeArray(anchor, input, false); | ||
} | ||
else if(input instanceof SyncAsync) { | ||
// REASSIGN anchor! sync input will compose _before_ | ||
// anchor is appended to DOM, need container until then | ||
const commentAnchor = anchor; | ||
anchor = document.createDocumentFragment(); | ||
anchor.append(commentAnchor); | ||
create(input.sync, props, slottable, commentAnchor); | ||
create(input.async, props, slottable, commentAnchor); | ||
} | ||
else { | ||
@@ -185,3 +177,3 @@ throwTypeErrorForObject(input, type); | ||
return anchor; | ||
return container; | ||
} | ||
@@ -259,4 +251,12 @@ } | ||
try { | ||
const fnName = obj.constructor?.name; | ||
if(fnName === 'Object') { | ||
message += `\n\nDid you mean to include a "render" method?`; | ||
} | ||
else if(fnName) { | ||
message += `\n\nDid you forget to return a value from "${fnName}"\ | ||
if a function, or a "render" method if a class?`; | ||
} | ||
const json = JSON.stringify(obj, null, 2); | ||
message = `\n\nReceived as:\n\n${json}\n\n`; | ||
message += `\n\nReceived as:\n\n${json}\n\n`; | ||
} | ||
@@ -263,0 +263,0 @@ catch(ex) { |
{ | ||
"name": "@azothjs/maya", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "Azoth runtime", | ||
@@ -34,4 +34,4 @@ "author": "Marty Nelson", | ||
"devDependencies": { | ||
"test-utils": "^1.0.0" | ||
"test-utils": "^0.0.0" | ||
} | ||
} |
@@ -26,3 +26,3 @@ import { DOMRenderer } from './dom-renderer.js'; | ||
const bindings = new Map(); // cache | ||
const bindings = new WeakMap(); // cache | ||
// TODO: implement cleanup actions on nodes | ||
@@ -105,10 +105,9 @@ export function clearBind(node) { | ||
export class Updater extends Controller { | ||
#node = null; | ||
ref = null; | ||
render(props) { | ||
return this.#node ?? (this.#node = super.render(props)); | ||
return this.ref ?? (this.ref = super.render(props)); | ||
} | ||
update(props) { | ||
const node = this.#node; | ||
node ? super.update(node, props) : this.render(props); | ||
this.ref ? super.update(this.ref, props) : this.render(props); | ||
} | ||
} |
11
17910
482