Add further documentation for skooma.js
This commit is contained in:
parent
b088905988
commit
c9b85b112c
2 changed files with 141 additions and 2 deletions
|
@ -13,7 +13,7 @@ class CodeBlock extends HTMLElement {
|
|||
let content = this.innerHTML.replace(/^\s*\n/, "").replace(/\n\s*$/, "")
|
||||
let prefix = new RegExp(`${content.match(/^\t*/)}`, "g")
|
||||
content = content.replace(prefix, "").replace(/&.*;/g, str => escapes[str] ?? str)
|
||||
this.replaceChildren(html.pre(html.code(template(hljs.highlightAuto(content).value))))
|
||||
this.replaceChildren(html.pre(html.code(template(hljs.highlight(content, {language: 'javascript'}).value))))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
141
page/skooma.html
141
page/skooma.html
|
@ -94,7 +94,7 @@
|
|||
return button
|
||||
</code-block>
|
||||
|
||||
<p>Adding a <strong>shadow-root</strong> to the new element can be done witht he <code>shadowRoot</code> property.</p>
|
||||
<p>Adding a <strong>shadow-root</strong> to the new element can be done with the magic <code>shadowRoot</code> property.</p>
|
||||
<p></p>
|
||||
<code-block>
|
||||
return html.div({
|
||||
|
@ -109,5 +109,144 @@
|
|||
div.innerText = "Light-DOM text content"
|
||||
return div
|
||||
</code-block>
|
||||
|
||||
<p>Object can be <strong>styled</strong> inline via the magic <code>style</code> property.</p>
|
||||
<p>Meanwhile in Vanilla JS styling properties have to be added one by one</p>
|
||||
<code-block>
|
||||
return html.div("Hello, World!" {
|
||||
class: 'button', style: {
|
||||
color, // some constant
|
||||
border: '1px solid currentcolor
|
||||
}
|
||||
})
|
||||
</code-block>
|
||||
<code-block>
|
||||
let div = document.createElement("div")
|
||||
div.innerHTML = "Hello, World!"
|
||||
div.style.color: color // some constant
|
||||
div.style.border: '1px solid currentcolor'
|
||||
return div
|
||||
</code-block>
|
||||
|
||||
<p>Custom elements with hyphenated names can be created easily</p>
|
||||
<p></p>
|
||||
<code-block>
|
||||
return html.myComponent()
|
||||
</code-block>
|
||||
<code-block>
|
||||
return document.createElement("my-component")
|
||||
</code-block>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>The <code>text</code> helper</h2>
|
||||
<div class="columns">
|
||||
<p>The <code>text</code> helper provides a convenient wrapper around the
|
||||
<code>document.createTextNode</code> function</p>
|
||||
<p>In its simplest form, it's only a shorthand for its vanilla counterpart</p>
|
||||
<code-block>
|
||||
return text("Hello, World!")
|
||||
</code-block>
|
||||
<code-block>
|
||||
return document.createTextNode("Hello, World!")
|
||||
</code-block>
|
||||
|
||||
<p>However, you don't need to pass an argument to it.</p>
|
||||
<p></p>
|
||||
<code-block>
|
||||
return text()
|
||||
</code-block>
|
||||
<code-block>
|
||||
return document.createTextNode("")
|
||||
</code-block>
|
||||
|
||||
<p>It also acts as a tag function for template literals, returning a
|
||||
document fragment containing a list of text nodes.</p>
|
||||
<p></p>
|
||||
<code-block>
|
||||
return text`Hello, ${name}!`
|
||||
</code-block>
|
||||
<code-block>
|
||||
let fragment = new DocumentFragment()
|
||||
fragment.append("Hello, ")
|
||||
fragment.append(name)
|
||||
fragment.append("!")
|
||||
return fragment
|
||||
</code-block>
|
||||
|
||||
<p>You can even interpolate actual DOM nodes in the string</p>
|
||||
<p></p>
|
||||
<code-block>
|
||||
return text`Hello, ${html.b(name)}!`
|
||||
</code-block>
|
||||
<code-block>
|
||||
let fragment = new DocumentFragment()
|
||||
fragment.append("Hello, ")
|
||||
let bold = document.createElement("b")
|
||||
bold.innerHTML = name
|
||||
fragment.append(bold)
|
||||
fragment.append("!")
|
||||
return fragment
|
||||
</code-block>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>The <code>bind</code> helper</h2>
|
||||
|
||||
<p>
|
||||
<dl>
|
||||
<dt>Callback registration function</dt>
|
||||
<dd>
|
||||
A function that takes a callback as its single argument and returns
|
||||
an initial state as an array of elements. The inital state will be
|
||||
used to generate the bound element for the first time. The callback
|
||||
function should be called whenever an update in the UI is desired
|
||||
and the new state should be passed as its argument.
|
||||
</dd>
|
||||
<dt>Transform function</dt>
|
||||
<dd>
|
||||
A function that takes the initial or updated state and returns a new
|
||||
HTML element.
|
||||
<details><summary>Planned feature</summary>
|
||||
When no HTML element is returned, nothing happens. This can be
|
||||
used to update the existing element instead; however, the
|
||||
function currently provides no means to access the old element in
|
||||
the transform function.
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Imagine <code>counter</code> to be an object with a <code>count</code>
|
||||
attribute representing the current count and <code>onIncrement</code> to
|
||||
be a function to register a callback to be called whenever the counter
|
||||
gets updated.
|
||||
</p>
|
||||
<div class="columns">
|
||||
<h3>Creating a new Element</h3>
|
||||
<h3>Updating the old Element</h3>
|
||||
<code-block>
|
||||
let counterMessage = count =>
|
||||
text`Current count: ${html.b(count)}`
|
||||
// onIncrement doesn't return an initial
|
||||
// state, so we have to wrap it:
|
||||
let onIncrement = bind(callback =>
|
||||
counter.onIncrement(callback) || counter.count)
|
||||
|
||||
return boundElement = onIncrement(counterMessage)
|
||||
</code-block>
|
||||
<code-block>
|
||||
// Not yet implemented
|
||||
</code-block>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
When an element gets replaced with a newer version of itself, any variable
|
||||
containing the old element will become "stale". For this reason, the
|
||||
function injects a <code>current</code> property into every element it
|
||||
creates that will always point to the newest version of the element.
|
||||
</p>
|
||||
</section>
|
||||
|
|
Loading…
Reference in a new issue