shadow
Shadow is a dependency-free base class inheriting from HTMLElement - makes native Custom Elements simple and fun.
Quick Start
Compile example/my_example.ts
:
deno bundle --no-check example/my_example.ts > example/my_example.js
# Add a tsconfig.json with DOM types to enable type checking:
# deno bundle --config tsconfig.json example/my_example.ts > example/my_example.js
Serve the index.html
file:
deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts example/
Print the commented API:
deno doc mod.ts
Example
import {
css,
customElement,
html,
property,
Shadow,
} from "https://deno.land/x/shadow/mod.ts"
@customElement()
export class MyExample extends Shadow {
@property()
h1Content = 0
@property()
pContent = "some text"
clickHandler(e: MouseEvent) {
return this.h1Content++
}
static styles = css`
h1 {
color: blue;
}
#myButton {
color: green;
}
`
render() {
return html`
<h1>${this.h1Content}</h1>
<p>${this.pContent}</p>
<button @id="myButton click=${this.clickHandler}">Count</button>
`
}
}
API
function html(strings: TemplateStringsArray, ...expressions: AllowedExpressions[]): Html
The html
tag function parses html strings containing the special marker @
and various AllowedExpressions
. Putting an @
before id
or class
in your
html code has two effects:
- The element(s) matching the selector will be queried and added to the
this.dom object. All matching class elements or one id element. E.g. to the
button element of
<div><button @id="myButton"></button></div>
can be referred withthis.dom.id["myButton"]
. - This allows you to add EventListeners, e.g. click=${this.clickHandler},
which will be added with the native addEventListener method under the hood.
You don't need arrow functions because we use
bind(this)
.
function css(strings: TemplateStringsArray, ...values: (string | HTMLTemplateElement)[])
The css
tag function parses css strings which can contain expressions with the
type string or HTMLTemplateElements (containing a script element).
function customElement(tagName)
The customElement
decorator takes the tag name of the custom element and
registers the custom element. If no tag name is passed, the class name is used
instead through converting it from CamelCase to dash-case. The same tag name is
assigned to the static is
property.
function property({reflect, wait, assert}: PropertyOptions)
The property
decorator takes an optional object as argument with three
optional properties:
- Setting
reflect
to false would stop the element's attribute from synchronising. - If you plan to use properties instead of attributes as data input, setting
wait
to true would reduce the amount of renderings from 2 to 1 (you can just ignore it). - The
assert
boolean checks if the input has a truthy value.
class Shadow extends HTMLElement
This class is the reason why you are here.
constructor(init: ShadowRootInit)
readonly argsFromPropertyDecorator?: Required<PropertyAndPropertyOptions[]>
connected: boolean
This boolean will be true
when connectedCallback
has been called and all
explicitly awaited properties have been set (the waitingList
is empty).
shadowRoot: ShadowRoot
dom: Dom
In the dom object are the child elements stored which match the selectors you
marked with the @
sign in the html string.
static styles: HTMLTemplateElement[]
The return type of the function css
, which is an array of HTMLTemplateElements
containing a script element, is assigned to this static property.
static is?: string
The decorator customElement
- if used - sets this static property to the
custom element's tag name automatically.
connectedCallback()
A native custom elements'
lifecycle callback.
If you want to modify this callback you must call super.connectedCallback()
inside of it.
attributeChangedCallback(name: string, oldValue: Attribute, newValue: Attribute)
A native custom elements' lifecycle callback. Here, it manages the reflecting of properties to attributes.
init(properties: PropertyAndPropertyOptions[]): void
Assigns the accessors to the element's properties and initializes the lifecycle
while considering the conditions coming from the property
decorator. You will
never need to use this method if you use the property
decorator.
update(name: string, newValue: Attribute, isRendering): void
Reflects properties to attributes and calls actuallyRender
if the optional
boolean isRendering
is true (default: true).
getSlotElements(): HTMLElement[]
Returns an array of the slot elements of the custom element.
render(): Html
Is called by the method actuallyRender
which renders the custom element. It
must return the return type of the function html
.
firstUpdated()?: void
A modifiable lifecycle callback which is called after the first update which includes rendering.
updated()?: void
A modifiable lifecycle callback which is called after each update which includes rendering.