@knowark/componarkjs 1.14.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/base/component/README.md +127 -0
- package/package.json +1 -1
- package/lib/base/component/README.rst +0 -113
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Component
|
|
2
|
+
|
|
3
|
+
`Component` is the base class for Componark custom elements. It extends `HTMLElement` with:
|
|
4
|
+
|
|
5
|
+
- Declarative event bindings (`listen` + `on-*` attributes)
|
|
6
|
+
- Attribute-to-property reflection
|
|
7
|
+
- Dependency resolution through bubbling `resolve` events
|
|
8
|
+
- Cleanup registration for disconnect lifecycle
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```javascript
|
|
13
|
+
import { Component } from 'base/component'
|
|
14
|
+
|
|
15
|
+
class MyComponent extends Component {
|
|
16
|
+
reflectedProperties () {
|
|
17
|
+
return ['title']
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
init (context = {}) {
|
|
21
|
+
this.local.count = this.local.count ?? 0
|
|
22
|
+
return super.init(context)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
increment () {
|
|
26
|
+
this.local.count += 1
|
|
27
|
+
this.render()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
render () {
|
|
31
|
+
this.content = `
|
|
32
|
+
<button listen on-click="increment">
|
|
33
|
+
${this.title}: ${this.local.count}
|
|
34
|
+
</button>
|
|
35
|
+
`
|
|
36
|
+
return super.render()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async load (_context = {}) {
|
|
40
|
+
// Optional async work after render.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Component.define('my-component', MyComponent)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Lifecycle
|
|
48
|
+
|
|
49
|
+
1. `constructor()`
|
|
50
|
+
- Initializes internal state (`binding`, `local`, cleanup registry, etc.).
|
|
51
|
+
- Applies reflected properties using `reflectedProperties()`.
|
|
52
|
+
2. `connectedCallback()`
|
|
53
|
+
- Marks the component as connected.
|
|
54
|
+
- Calls `init({})` only when `local` is empty.
|
|
55
|
+
- Calls `render()`.
|
|
56
|
+
- Calls `load({})` (sync or async).
|
|
57
|
+
3. `disconnectedCallback()`
|
|
58
|
+
- Marks the component as disconnected.
|
|
59
|
+
- Runs registered cleanup callbacks.
|
|
60
|
+
|
|
61
|
+
Errors from `init`/`render`, `load`, and cleanup callbacks are emitted as bubbling `error` events. Enhanced errors include:
|
|
62
|
+
|
|
63
|
+
- `phase`: `init-render`, `load`, or `cleanup`
|
|
64
|
+
- `component`: current tag name (for example, `MY-COMPONENT`)
|
|
65
|
+
|
|
66
|
+
## Public API
|
|
67
|
+
|
|
68
|
+
### Static API
|
|
69
|
+
|
|
70
|
+
| Method | Description |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `Component.define(tagName, element, styles?)` | Registers a custom element. If `styles` are provided, they are registered for that tag. |
|
|
73
|
+
|
|
74
|
+
### Instance API
|
|
75
|
+
|
|
76
|
+
| Member | Returns | Description |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `init(context = {})` | `this` | Component state initialization hook. |
|
|
79
|
+
| `reflectedProperties()` | `string[]` | Attribute names to expose as reflected properties. |
|
|
80
|
+
| `slots` | `Record<string, HTMLElement[]>` | Child elements grouped by `slot` (`general` by default). |
|
|
81
|
+
| `content` | `string` | Proxy for `innerHTML`. Setting it flags listeners for re-binding. |
|
|
82
|
+
| `render()` | `this` | Adds the tag-name class and binds declarative listeners when needed. |
|
|
83
|
+
| `load(context = {})` | `void \| Promise<void>` | Async hook called after `render()`. |
|
|
84
|
+
| `registerCleanup(callback)` | `() => void` | Registers disconnect cleanup and returns an unregister function. |
|
|
85
|
+
| `select(selector)` | `Component` | `querySelector` helper. |
|
|
86
|
+
| `selectAll(selector)` | `NodeListOf<Component>` | `querySelectorAll` helper. |
|
|
87
|
+
| `emit(type, detail)` | `void` | Dispatches a bubbling, cancelable event with `detail`. |
|
|
88
|
+
| `resolve(resource)` | `any` | Requests a dependency through a bubbling `resolve` event. |
|
|
89
|
+
| `styleNames(styleMap)` | `string` | Returns truthy class names from an object map. |
|
|
90
|
+
|
|
91
|
+
## Declarative listeners
|
|
92
|
+
|
|
93
|
+
`render()` triggers listener wiring on descendants marked with `listen`.
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<input listen on-input="{{ local.query = data }}">
|
|
97
|
+
<input listen on-input="{{ local.total = data | number }}">
|
|
98
|
+
<button listen on-click="submit"></button>
|
|
99
|
+
<button listen on-click="submit@#child"></button>
|
|
100
|
+
<div listen on-change="replaceChildren%detail.name@#target"></div>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Rules:
|
|
104
|
+
|
|
105
|
+
- Use `on-<event>` attributes to define handlers.
|
|
106
|
+
- `{{ ... }}` expressions perform state assignment.
|
|
107
|
+
- Pipes support `string`, `number`, `boolean`, and `object`.
|
|
108
|
+
- `handler@<selector>` routes execution to another element/component.
|
|
109
|
+
- Handler failures emit bubbling `error` events.
|
|
110
|
+
|
|
111
|
+
## Dependency resolution
|
|
112
|
+
|
|
113
|
+
`resolve(resource)` dispatches a bubbling `resolve` event with `{ resource }`. Ancestors can provide values by implementing `provide(resource)`.
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
class ParentComponent extends Component {
|
|
117
|
+
provide (resource) {
|
|
118
|
+
if (resource === 'state') return this.local
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Then in a child:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
const state = this.resolve('state')
|
|
127
|
+
```
|
package/package.json
CHANGED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
Component
|
|
2
|
-
*********
|
|
3
|
-
|
|
4
|
-
This is the base class for the *Componark* library of web components. It might
|
|
5
|
-
be used in application code as well as to create new custom elements, which can
|
|
6
|
-
of course use the pre-built components in this library in their composition.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Reference
|
|
10
|
-
=========
|
|
11
|
-
|
|
12
|
-
Usage
|
|
13
|
-
-----
|
|
14
|
-
|
|
15
|
-
A new component (i.e. custom element) should be created by just extending the
|
|
16
|
-
*Component* base class.
|
|
17
|
-
|
|
18
|
-
.. code:: javascript
|
|
19
|
-
|
|
20
|
-
import { Component } from 'base/component'
|
|
21
|
-
|
|
22
|
-
class MyComponent extends Component {
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Lifecycle
|
|
28
|
-
---------
|
|
29
|
-
|
|
30
|
-
The lifecycle of the Componark's base component overlaps with that of the
|
|
31
|
-
standard `custom elements specification <https://developer.mozilla.org/en-US/
|
|
32
|
-
docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks>`_.
|
|
33
|
-
Howerver, the *Component* base class provides additional extension points to
|
|
34
|
-
simplify state management and the rendering process.
|
|
35
|
-
|
|
36
|
-
- constructor()
|
|
37
|
-
- **init(context: object)**
|
|
38
|
-
- connectedCallback()
|
|
39
|
-
- **async update()**
|
|
40
|
-
- **render()**
|
|
41
|
-
- **async load()**
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Methods
|
|
45
|
-
-------
|
|
46
|
-
|
|
47
|
-
constructor()
|
|
48
|
-
^^^^^^^^^^^^^
|
|
49
|
-
|
|
50
|
-
This is a custom element *standard* method. The constructor *must not*
|
|
51
|
-
receive any parameters and is invoked every time a new instance of a
|
|
52
|
-
*Component* is **created**. The default constructor implementation calls the
|
|
53
|
-
**init()** method with an empty object and that is the place in which custom
|
|
54
|
-
initialization of state should be performed when using componark. The automatic
|
|
55
|
-
syncronization between reflected properties and attributes is also done inside
|
|
56
|
-
the constructor.
|
|
57
|
-
|
|
58
|
-
init(context: object)
|
|
59
|
-
^^^^^^^^^^^^^^^^^^^^^
|
|
60
|
-
|
|
61
|
-
The **init()** method is the place where state initialization of the component
|
|
62
|
-
should be made. It is called without context arguments by the constructor on
|
|
63
|
-
component creation and thus, should resiliently handle any form of attributes
|
|
64
|
-
received to set the state of the component before **rendering**. The *init()*
|
|
65
|
-
method should be called as well in parent components, for *updating* the
|
|
66
|
-
state of the nested component and then explicitly invoking **render()** to
|
|
67
|
-
present those changes in the user interface. The **init()** method returns the
|
|
68
|
-
current instance (i.e. *this*) to enable chaining, so don't forget to return
|
|
69
|
-
*super.init()* when extending this method.
|
|
70
|
-
|
|
71
|
-
connectedCallback()
|
|
72
|
-
^^^^^^^^^^^^^^^^^^^
|
|
73
|
-
|
|
74
|
-
The *connectedCallback()* method is one of the default lifecycle callbacks or
|
|
75
|
-
reactions of the `custom elements specification
|
|
76
|
-
<https://developer.mozilla.org/en-US/docs/Web/Web_Components/
|
|
77
|
-
Using_custom_elements#using_the_lifecycle_callbacks>`_. This method shouldn't
|
|
78
|
-
be extended directly by Componark's components as there are other methods in
|
|
79
|
-
this reference which are better suited to provide customization and extension.
|
|
80
|
-
The **connectedCallback()** is invoked every time a *Component* is inserted
|
|
81
|
-
into the *DOM* (i.e. injected in the page).
|
|
82
|
-
|
|
83
|
-
async update()
|
|
84
|
-
^^^^^^^^^^^^^^
|
|
85
|
-
|
|
86
|
-
The *update()* method is an *asynchronous* consolidation method whose purpose
|
|
87
|
-
is to simultaneously call **render()** and **load()**. The *update()* method is
|
|
88
|
-
called by the *connectedCallback()* standard reaction and after first injection
|
|
89
|
-
might also be called explicitly by user code.
|
|
90
|
-
|
|
91
|
-
render()
|
|
92
|
-
^^^^^^^^
|
|
93
|
-
|
|
94
|
-
This method should be extended by every component to set its visual
|
|
95
|
-
representation (i.e. html) based on its current state. The produced document
|
|
96
|
-
string should be assigned to the **content** property of the *Component*
|
|
97
|
-
which in turn will inject it into the *DOM*. Conditionals, loops and any kind
|
|
98
|
-
of logic can be used inside the *render()* method to dynamically set the
|
|
99
|
-
*Components* presentation based on its attributes, properties or any other
|
|
100
|
-
environmental state. The **render()** method returns the current instance
|
|
101
|
-
(i.e. *this*) to enable chaining, so don't forget to return *super.render()*
|
|
102
|
-
when extending this method.
|
|
103
|
-
|
|
104
|
-
async load()
|
|
105
|
-
^^^^^^^^^^^^
|
|
106
|
-
|
|
107
|
-
The *load()* lifecycle asynchronous method is the place where custom data
|
|
108
|
-
fetching or other kinds of asynchronous operations should be performed. This
|
|
109
|
-
method is invoked by *connectedCallback()* every time the *Component* is
|
|
110
|
-
injected into the DOM (in an indirect manner through *update()*). After
|
|
111
|
-
finishing its asynchronous tasks (e.g. obtaining some requested external data)
|
|
112
|
-
the *load()* method might change the component's state and presentation and
|
|
113
|
-
even explicitly call *render()*.
|