typed-dom
Advanced tools
Comparing version 0.0.257 to 0.0.258
@@ -1,2 +0,2 @@ | ||
/*! typed-dom v0.0.257 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */ | ||
/*! typed-dom v0.0.258 https://github.com/falsandtru/typed-dom | (c) 2016, falsandtru | (Apache-2.0 AND MPL-2.0) License */ | ||
require = function () { | ||
@@ -664,4 +664,4 @@ function r(e, n, t) { | ||
return { | ||
apply(target, _, [prop, ...args]) { | ||
return this.get(target, prop, target)(...args); | ||
apply(target, _, [tag, ...args]) { | ||
return this.get(target, tag, target)(...args); | ||
}, | ||
@@ -697,4 +697,4 @@ get: (target, prop) => target[prop] || prop in target || typeof prop !== 'string' ? target[prop] : target[prop] = builder(prop, baseFactory) | ||
const el = factory ? (0, dom_1.define)(factory(baseFactory, tag, attrs, children), attrs) : baseFactory(tag, attrs); | ||
if (tag !== el.tagName.toLowerCase()) | ||
throw new Error(`TypedDOM: Expected tag name is "${ tag }" but actually "${ el.tagName.toLowerCase() }".`); | ||
if (tag.toLowerCase() !== el.tagName.toLowerCase()) | ||
throw new Error(`TypedDOM: Expected tag name is "${ tag.toLowerCase() }" but actually "${ el.tagName.toLowerCase() }".`); | ||
return el; | ||
@@ -826,3 +826,3 @@ } | ||
[privates.scope](child) { | ||
if (child.element.tagName !== 'STYLE') | ||
if (child.element.tagName.toUpperCase() !== 'STYLE') | ||
return; | ||
@@ -837,8 +837,7 @@ const target = /(^|[,}]|\*\/)(\s*)\$scope(?=[\s~+[{:>,])/g; | ||
[(_d = privates.isObserverUpdate, privates.observe)](children) { | ||
const descs = {}; | ||
for (const name of (0, alias_1.ObjectKeys)(children)) { | ||
return (0, alias_1.ObjectDefineProperties)(children, (0, alias_1.ObjectKeys)(children).reduce((obj, name) => { | ||
if (name in {}) | ||
throw new Error(`TypedDOM: Child names must be different from the object property names.`); | ||
let child = children[name]; | ||
descs[name] = { | ||
obj[name] = { | ||
configurable: true, | ||
@@ -858,4 +857,4 @@ enumerable: true, | ||
}; | ||
} | ||
return (0, alias_1.ObjectDefineProperties)(children, descs); | ||
return obj; | ||
}, {})); | ||
} | ||
@@ -906,4 +905,10 @@ get children() { | ||
} | ||
container.replaceChildren(...sourceChildren.map(c => c.element)); | ||
this[privates.children] = children; | ||
if (container.firstChild) { | ||
container.replaceChildren(...sourceChildren.map(c => c.element)); | ||
} else { | ||
for (let i = 0; i < sourceChildren.length; ++i) { | ||
container.appendChild(sourceChildren[i].element); | ||
} | ||
} | ||
this[privates.children] = sourceChildren; | ||
for (let i = 0; i < targetChildren.length; ++i) { | ||
@@ -1098,3 +1103,11 @@ const oldChild = targetChildren[i]; | ||
return node; | ||
node.replaceChildren(...typeof children === 'string' ? [children] : children); | ||
if (typeof children === 'string') { | ||
node.textContent = children; | ||
} else if (node.firstChild) { | ||
node.replaceChildren(...children); | ||
} else { | ||
for (const child of children) { | ||
typeof child === 'object' ? node.appendChild(child) : node.append(child); | ||
} | ||
} | ||
return node; | ||
@@ -1101,0 +1114,0 @@ } |
14
dom.ts
@@ -149,3 +149,15 @@ import { Symbol, document } from 'spica/global'; | ||
if (children === void 0) return node; | ||
node.replaceChildren(...typeof children === 'string' ? [children] : children); | ||
if (typeof children === 'string') { | ||
node.textContent = children; | ||
} | ||
else if (node.firstChild) { | ||
node.replaceChildren(...children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.appendChild(child) | ||
: node.append(child); | ||
} | ||
} | ||
return node; | ||
@@ -152,0 +164,0 @@ } |
{ | ||
"name": "typed-dom", | ||
"version": "0.0.257", | ||
"version": "0.0.258", | ||
"description": "A DOM component builder creating type-level DOM structures.", | ||
@@ -5,0 +5,0 @@ "private": false, |
@@ -7,3 +7,3 @@ # typed-dom | ||
**Visualize** DOM structures and **Assist** DOM access by static types of TypeScript. | ||
**Visualize** DOM structures and **Assist** DOM access by static types. | ||
@@ -160,3 +160,3 @@ ## APIs | ||
style: HTML.style(`$scope ul { width: 100px; }`), | ||
title: HTML.h1(`title`), | ||
title: HTML.h1(`Title`), | ||
content: HTML.ul([ | ||
@@ -185,3 +185,4 @@ HTML.li(`item`), | ||
readonly element: E; | ||
children: C; | ||
get children(): El.Getter<C>; | ||
set children(children: El.Setter<C>); | ||
} | ||
@@ -195,3 +196,3 @@ export namespace El { | ||
export namespace Children { | ||
export type Void = undefined; | ||
export type Void = void; | ||
export type Text = string; | ||
@@ -201,2 +202,8 @@ export type Array = readonly El[]; | ||
} | ||
export type Getter<C extends El.Children> = | ||
C extends readonly unknown[] ? C : | ||
C; | ||
export type Setter<C extends El.Children> = | ||
C extends readonly unknown[] ? C : | ||
Partial<C>; | ||
} | ||
@@ -209,26 +216,27 @@ ``` | ||
```ts | ||
// inspect | ||
component.element.outerHTML; // '<article class="RANDOM"><style>.RANDOM ul { width: 100px; }</style><h1>title</h1><ul><li>item</li><li>item</li></ul></article>' | ||
component.children.title.element.outerHTML; // '<h1>title</h1>' | ||
component.children.title.children; // 'title' | ||
// Inspect | ||
component.element.outerHTML; // '<article class="RANDOM"><style>.RANDOM ul { width: 100px; }</style><h1>Title</h1><ul><li>item</li><li>item</li></ul></article>' | ||
component.children.title.element.outerHTML; // '<h1>Title</h1>' | ||
component.children.title.children; // 'Title' | ||
component.children.content.element.outerHTML; // '<ul><li>item</li><li>item</li></ul>' | ||
component.children.content.children[0].children; // 'item' | ||
// update | ||
// - text | ||
component.children.title.children = 'Title'; | ||
component.children.title.element.outerHTML; // '<h1>Title</h1>' | ||
// Update | ||
// - Text | ||
component.children.title.children = 'Text'; | ||
component.children.title.element.outerHTML; // '<h1>Text</h1>' | ||
// - collection | ||
// - Array | ||
component.children.content.children = [ | ||
HTML.li('Item'), | ||
HTML.li('Array'), | ||
]; | ||
component.children.content.element.outerHTML; // '<ul><li>Item</li></ul>' | ||
component.children.content.element.outerHTML; // '<ul><li>Array</li></ul>' | ||
// - HTML | ||
component.children.title = HTML.h1('Title!'); | ||
component.children.content = HTML.ul([ | ||
HTML.li('Item!'), | ||
]); | ||
component.element.outerHTML; // '<article class="RANDOM>"><style>.RANDOM ul { width: 100px; }</style><h1>Title!</h1><ul><li>Item!</li></ul></article>' | ||
// - Struct | ||
component.children = { | ||
title: HTML.h1('Struct'), | ||
}; | ||
component.children.title.element.outerHTML; // '<h1>Struct</h1>' | ||
component.children.title = HTML.h1('title'); | ||
component.children.title.element.outerHTML; // '<h1>title</h1>' | ||
``` | ||
@@ -235,0 +243,0 @@ |
@@ -57,4 +57,4 @@ import { Symbol } from 'spica/global'; | ||
return { | ||
apply(target, _, [prop, ...args]) { | ||
return this.get!(target, prop, target)(...args); | ||
apply(target, _, [tag, ...args]) { | ||
return this.get!(target, tag, target)(...args); | ||
}, | ||
@@ -96,3 +96,3 @@ get: (target, prop) => | ||
: baseFactory(tag, attrs) as unknown as Element; | ||
if (tag !== el.tagName.toLowerCase()) throw new Error(`TypedDOM: Expected tag name is "${tag}" but actually "${el.tagName.toLowerCase()}".`); | ||
if (tag.toLowerCase() !== el.tagName.toLowerCase()) throw new Error(`TypedDOM: Expected tag name is "${tag.toLowerCase()}" but actually "${el.tagName.toLowerCase()}".`); | ||
return el; | ||
@@ -99,0 +99,0 @@ } |
@@ -16,3 +16,5 @@ import { Event } from 'spica/global'; | ||
readonly element: E; | ||
children: C; | ||
//get children(): C; | ||
get children(): El.Getter<C>; | ||
set children(children: El.Setter<C>); | ||
} | ||
@@ -31,2 +33,8 @@ export namespace El { | ||
} | ||
export type Getter<C extends El.Children> = | ||
C extends readonly unknown[] ? C : | ||
C; | ||
export type Setter<C extends El.Children> = | ||
C extends readonly unknown[] ? C : | ||
Partial<C>; | ||
} | ||
@@ -59,5 +67,5 @@ const enum ElChildType { | ||
export class Elem< | ||
T extends string, | ||
E extends Element, | ||
C extends El.Children, | ||
T extends string = string, | ||
E extends Element = Element, | ||
C extends El.Children = El.Children, | ||
> implements El<T, E, C> { | ||
@@ -99,3 +107,3 @@ constructor( | ||
case ElChildType.Text: | ||
this.children = children as C; | ||
this.children = children as El.Setter<C>; | ||
this[privates.isInit] = false; | ||
@@ -105,3 +113,3 @@ return; | ||
this[privates.children] = [] as El.Children.Array as C; | ||
this.children = children; | ||
this.children = children as El.Setter<C>; | ||
this[privates.isInit] = false; | ||
@@ -111,3 +119,3 @@ return; | ||
this[privates.children] = this[privates.observe](children as El.Children.Struct) as C; | ||
this.children = children; | ||
this.children = children as El.Setter<C>; | ||
this[privates.isInit] = false; | ||
@@ -152,3 +160,3 @@ return; | ||
private [privates.scope](child: El): void { | ||
if (child.element.tagName !== 'STYLE') return; | ||
if (child.element.tagName.toUpperCase() !== 'STYLE') return; | ||
const target = /(^|[,}]|\*\/)(\s*)\$scope(?=[\s~+[{:>,])/g; | ||
@@ -162,8 +170,7 @@ const style = child.element.innerHTML; | ||
private [privates.isObserverUpdate] = false; | ||
private [privates.observe](children: El.Children.Struct): C { | ||
const descs: PropertyDescriptorMap = {}; | ||
for (const name of ObjectKeys(children)) { | ||
private [privates.observe](children: El.Children.Struct): El.Children.Struct { | ||
return ObjectDefineProperties(children, ObjectKeys(children).reduce((obj, name) => { | ||
if (name in {}) throw new Error(`TypedDOM: Child names must be different from the object property names.`); | ||
let child = children[name]; | ||
descs[name] = { | ||
obj[name] = { | ||
configurable: true, | ||
@@ -176,3 +183,3 @@ enumerable: true, | ||
if (!this[privates.isObserverUpdate]) { | ||
this.children = { [name]: newChild } as C; | ||
this.children = { [name]: newChild } as El.Setter<C>; | ||
} | ||
@@ -185,4 +192,4 @@ else { | ||
}; | ||
} | ||
return ObjectDefineProperties(children, descs) as C; | ||
return obj; | ||
}, {})); | ||
} | ||
@@ -193,11 +200,11 @@ private readonly [privates.type]: ElChildType; | ||
private [privates.children]: C; | ||
public get children(): C { | ||
public get children(): El.Getter<C> { | ||
switch (this[privates.type]) { | ||
case ElChildType.Text: | ||
return this[privates.container].textContent as C; | ||
return this[privates.container].textContent as El.Getter<C>; | ||
default: | ||
return this[privates.children] as C; | ||
return this[privates.children] as El.Getter<C>; | ||
} | ||
} | ||
public set children(children: C) { | ||
public set children(children: El.Setter<C>) { | ||
assert(!this[privates.isObserverUpdate]); | ||
@@ -238,4 +245,11 @@ const container = this[privates.container]; | ||
} | ||
container.replaceChildren(...sourceChildren.map(c => c.element)); | ||
this[privates.children] = children; | ||
if (container.firstChild) { | ||
container.replaceChildren(...sourceChildren.map(c => c.element)); | ||
} | ||
else { | ||
for (let i = 0; i < sourceChildren.length; ++i) { | ||
container.appendChild(sourceChildren[i].element); | ||
} | ||
} | ||
this[privates.children] = sourceChildren as C; | ||
for (let i = 0; i < targetChildren.length; ++i) { | ||
@@ -316,3 +330,3 @@ const oldChild = targetChildren[i]; | ||
function events(child: El): Elem<string, Element, El.Children>[typeof privates.events] | undefined { | ||
function events(child: El): Elem[typeof privates.events] | undefined { | ||
return child[privates.events] ?? child.element[proxy]?.[privates.events]; | ||
@@ -319,0 +333,0 @@ } |
@@ -149,3 +149,15 @@ import { Symbol, document } from 'spica/global'; | ||
if (children === void 0) return node; | ||
node.replaceChildren(...typeof children === 'string' ? [children] : children); | ||
if (typeof children === 'string') { | ||
node.textContent = children; | ||
} | ||
else if (node.firstChild) { | ||
node.replaceChildren(...children); | ||
} | ||
else { | ||
for (const child of children) { | ||
typeof child === 'object' | ||
? node.appendChild(child) | ||
: node.append(child); | ||
} | ||
} | ||
return node; | ||
@@ -152,0 +164,0 @@ } |
@@ -60,2 +60,4 @@ import { API, Shadow, HTML, SVG, El, shadow, html } from '../..'; | ||
const dom = HTML.p(`a`); | ||
// @ts-expect-error | ||
() => dom.children = undefined; | ||
dom.children = 'b'; | ||
@@ -129,2 +131,4 @@ assert(dom.element.outerHTML === '<p>b</p>'); | ||
//assert.throws(() => dom.children.length = 0); | ||
// @ts-expect-error | ||
() => dom.children = [undefined]; | ||
assert(dom.children.length === 1); | ||
@@ -144,5 +148,5 @@ assert(dom.children.every(({ element }, i) => element === dom.element.children[i])); | ||
title: HTML.h1(`title`), | ||
content: HTML.p([HTML.a()]) | ||
content: HTML.p() | ||
}); | ||
assert(dom.element.outerHTML === '<article><h1>title</h1><p><a></a></p></article>'); | ||
assert(dom.element.outerHTML === '<article><h1>title</h1><p></p></article>'); | ||
assert(dom.children.title.element === dom.element.firstChild); | ||
@@ -159,3 +163,3 @@ assert(dom.children.content.element === dom.element.lastChild); | ||
const dom = HTML.article({ | ||
title: HTML.h1(`a`) | ||
title: HTML.h1(`a`), | ||
}); | ||
@@ -177,3 +181,4 @@ assert.doesNotThrow(() => dom.children = dom.children); | ||
const dom = HTML.article({ | ||
title: HTML.h1(`a`) | ||
title: HTML.h1(`a`), | ||
content: HTML.p() | ||
}); | ||
@@ -193,2 +198,14 @@ assert.doesNotThrow(() => dom.children.title = dom.children.title); | ||
assert(dom.children.title.children === 'c'); | ||
dom.children = { | ||
title: HTML.h1(`d`), | ||
}; | ||
assert(dom.children.title.element === dom.element.firstChild); | ||
assert(dom.children.title.element.textContent === 'd'); | ||
assert(dom.children.title.children === 'd'); | ||
dom.children = { | ||
title: HTML.h1(`e`), | ||
content: undefined, | ||
}; | ||
assert(dom.children.content.element === dom.element.lastChild); | ||
assert(dom.element.outerHTML === '<article><h1>e</h1><p></p></article>'); | ||
}); | ||
@@ -195,0 +212,0 @@ |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
659063
15574
356