mi-element 0.0.1 → 0.1.0

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.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @typedef {object} HostController controller
3
+ * @property {() => void} hostConnected is called when host element is added to
4
+ * the DOM, usually with connectedCallback()
5
+ * @property {() => void} hostDisconnected is called when host element is
6
+ * removed from the DOM, usually with disconnectedCallback()
7
+ */
8
+ /**
9
+ * class extening HTMLElement to enable deferred rendering on attribute changes
10
+ * either via `setAttribute(name, value)` or `this[name] = value`.
11
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
12
+ * @example
13
+ * ```js
14
+ * class Example extends MiElement {
15
+ * // define all observed attributes with its default value.
16
+ * // attributes are accessible via `this[prop]`
17
+ * // avoid using attributes which are HTMLElement properties e.g. className
18
+ * static get attributes () {
19
+ * return { text: 'Hi' }
20
+ * }
21
+ * render() {
22
+ * this.renderRoot.innerHTML = `<div></div>`
23
+ * this.refs = {
24
+ * div: this.renderRoot.querySelector('div')
25
+ * }
26
+ * }
27
+ * // render method called every time an attribute changes
28
+ * update() {
29
+ * this.refs.div.textContent = this.text
30
+ * }
31
+ * }
32
+ * // create a custom element with the `define` function (see below)
33
+ * define('x-example', Example)
34
+ * // create a DOM node and re-render via attribute or property changes
35
+ * const elem = document.createElement('x-example')
36
+ * elem.setAttribute('text', 'set attribute')
37
+ * // or if change is triggered by property
38
+ * elem.text = 'set property'
39
+ * ```
40
+ */
41
+ export class MiElement extends HTMLElement {
42
+ /**
43
+ * Default options used when calling `attachShadow`. Used in
44
+ * `connectedCallback()`.
45
+ * If override is `null`, no shadow-root will be attached.
46
+ */
47
+ static shadowRootOptions: {
48
+ mode: string
49
+ }
50
+ __attr: {}
51
+ __attrLc: Map<any, any>
52
+ __types: Map<any, any>
53
+ __disposers: Set<any>
54
+ __controllers: Set<any>
55
+ __changedAttr: {}
56
+ /**
57
+ * requests update on component when property changes
58
+ */
59
+ __observedAttributes(): void
60
+ /**
61
+ * return camelCased value instead of possible lowercased
62
+ * @param {string} name
63
+ * @returns
64
+ */
65
+ __getName(name: string): any
66
+ __getType(name: any): any
67
+ /**
68
+ * creates the element's renderRoot, sets up styling
69
+ * @category lifecycle
70
+ */
71
+ connectedCallback(): void
72
+ renderRoot: any
73
+ /**
74
+ * unsubscribe from all events and disconnect controllers
75
+ */
76
+ disconnectedCallback(): void
77
+ /**
78
+ * @param {string} name change attribute
79
+ * @param {any} _oldValue
80
+ * @param {any} newValue new value
81
+ */
82
+ attributeChangedCallback(name: string, _oldValue: any, newValue: any): void
83
+ /**
84
+ * Set string and number attributes on element only. Set all other values as
85
+ * properties to avoid type conversion to and from string
86
+ * @param {string} name
87
+ * @param {any} newValue
88
+ */
89
+ setAttribute(name: string, newValue: any): void
90
+ /**
91
+ * request rendering
92
+ */
93
+ requestUpdate(): void
94
+ /**
95
+ * initial rendering
96
+ */
97
+ render(): void
98
+ /**
99
+ * controls if component shall be updated
100
+ * @param {Record<string,any>} _changedAttributes changed attributes
101
+ * @returns {boolean}
102
+ */
103
+ shouldUpdate(_changedAttributes: Record<string, any>): boolean
104
+ /**
105
+ * called every time the components needs a render update
106
+ * @param {Record<string,any>} _changedAttributes changed attributes
107
+ */
108
+ update(_changedAttributes: Record<string, any>): void
109
+ /**
110
+ * Adds listener function for eventName. listener is removed before component
111
+ * disconnects
112
+ * @param {string} eventName
113
+ * @param {EventListenerOrEventListenerObject} listener
114
+ * @param {Node|Document|Window} [node=this]
115
+ */
116
+ on(
117
+ eventName: string,
118
+ listener: EventListenerOrEventListenerObject,
119
+ node?: Node | Document | Window | undefined
120
+ ): void
121
+ /**
122
+ * Adds one-time listener function for eventName. The next time eventName is
123
+ * triggered, this listener is removed and then invoked.
124
+ * @param {string} eventName
125
+ * @param {EventListenerOrEventListenerObject} listener
126
+ * @param {Node|Document|Window} node
127
+ */
128
+ once(
129
+ eventName: string,
130
+ listener: EventListenerOrEventListenerObject,
131
+ node?: Node | Document | Window
132
+ ): void
133
+ /**
134
+ * Unsubscribe a listener function for disposal on disconnectedCallback()
135
+ * @param {function} listener
136
+ */
137
+ dispose(listener: Function): void
138
+ /**
139
+ * adds a connected controller
140
+ * @param {HostController} controller
141
+ */
142
+ addController(controller: HostController): void
143
+ /**
144
+ * removes a connected controller
145
+ * @param {HostController} controller
146
+ */
147
+ removeController(controller: HostController): void
148
+ }
149
+ export function define(
150
+ name: string,
151
+ element: typeof MiElement,
152
+ options?: object
153
+ ): void
154
+ export function convertType(any: any, type: any): any
155
+ /**
156
+ * controller
157
+ */
158
+ export type HostController = {
159
+ /**
160
+ * is called when host element is added to
161
+ * the DOM, usually with connectedCallback()
162
+ */
163
+ hostConnected: () => void
164
+ /**
165
+ * is called when host element is
166
+ * removed from the DOM, usually with disconnectedCallback()
167
+ */
168
+ hostDisconnected: () => void
169
+ }
@@ -0,0 +1,3 @@
1
+ export function escHtml(string: string): string
2
+ export function escAttr(string: string): string
3
+ export function esc(strings: string[], ...vars: any[]): string
@@ -0,0 +1,14 @@
1
+ export type Context = import('./context.js').Context
2
+ export type HostController = import('./element.js').HostController
3
+ export type Callback = import('./signal.js').Callback
4
+ export type Action = import('./store.js').Action
5
+ export {
6
+ ContextConsumer,
7
+ ContextProvider,
8
+ ContextRequestEvent
9
+ } from './context.js'
10
+ export { MiElement, convertType, define } from './element.js'
11
+ export { esc, escAttr, escHtml } from './escape.js'
12
+ export { refsById, refsBySelector } from './refs.js'
13
+ export { Signal, createSignal, isSignalLike } from './signal.js'
14
+ export { Store, subscribeToStore } from './store.js'
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Helper function to find `id` attributes in `container`s node tree
3
+ * @param {Element} container root element
4
+ * @returns {Record<string, Node>|{}} record of found references
5
+ * @example
6
+ * el.innerHTML = `<p id>unnamed <span id="named">and named</span> reference</p>`
7
+ * references = refs(el)
8
+ * //> references = { p: <p>, named: <span> }
9
+ */
10
+ export function refsById(container: Element): Record<string, Node> | {}
11
+ /**
12
+ * Helper function to gather references by a map of selectors
13
+ * @param {Element} container root element
14
+ * @param {Record<string, string>} selectors
15
+ * @returns {Record<string, Node>|{}}
16
+ * @example
17
+ * el.innerHTML = `<p>some <span>and other</span> reference</p>`
18
+ * references = refs(el, { p: 'p', named: 'p > span' })
19
+ * //> references = { p: <p>, named: <span> }
20
+ */
21
+ export function refsBySelector(
22
+ container: Element,
23
+ selectors: Record<string, string>
24
+ ): Record<string, Node> | {}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @typedef {(value: any) => void} Callback
3
+ */
4
+ export class Signal {
5
+ /**
6
+ * creates a new signal with an initial value
7
+ * @param {any} [initialValue]
8
+ */
9
+ constructor(initialValue?: any)
10
+ _subscribers: Set<any>
11
+ _value: any
12
+ /**
13
+ * set new value on signal;
14
+ * if value has changed all subscribers are called
15
+ * @param {any} newValue
16
+ */
17
+ set value(newValue: any)
18
+ /**
19
+ * return current value
20
+ * @returns {any}
21
+ */
22
+ get value(): any
23
+ /**
24
+ * notify all subscribers on current value
25
+ */
26
+ notify(): void
27
+ /**
28
+ * subscribe to signal to receive value updates
29
+ * @param {Callback} callback
30
+ * @returns {() => void} unsubscribe function
31
+ */
32
+ subscribe(callback: Callback): () => void
33
+ }
34
+ export function createSignal(initialValue?: any): Signal
35
+ export function isSignalLike(possibleSignal: any): boolean
36
+ export type Callback = (value: any) => void
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @typedef {import('./element.js').MiElement} MiElement
3
+ */
4
+ /**
5
+ * @typedef {(state: any, data?: any) => any} Action
6
+ */
7
+ /**
8
+ * Store implementing [Flux](https://www.npmjs.com/package/flux) pattern based
9
+ * on Signals
10
+ */
11
+ export class Store extends Signal {
12
+ /**
13
+ * @param {Record<string, Action>} actions
14
+ * @param {any} [initialValue]
15
+ * @example
16
+ * ```js
17
+ * const actions = { increment: (by = 1) => (current) => current + by }
18
+ * const initialValue = 1
19
+ * const store = new Store(actions, initialValue)
20
+ * // subscribe with a callback function
21
+ * const unsubscribe = store.subscribe((value) => console.log(`count is ${value}`))
22
+ * // change the store
23
+ * store.increment(2) // increment by 2
24
+ * //> count is 3
25
+ * unsubscribe()
26
+ * ```
27
+ *
28
+ * if `initialValue` is an object, the object's reference must be changed
29
+ * using the spread operator, in order to notify on state changes, e.g.
30
+ * ```js
31
+ * const initialValue = { count: 0, other: 'foo' }
32
+ * const actions = {
33
+ * increment: (by = 1) => (state) => ({...state, count: state.count + by})
34
+ * }
35
+ * ```
36
+ */
37
+ constructor(actions: Record<string, Action>, initialValue?: any)
38
+ }
39
+ export function subscribeToStore(
40
+ element: MiElement,
41
+ store: Store,
42
+ prop: string | string[]
43
+ ): void
44
+ export type MiElement = import('./element.js').MiElement
45
+ export type Action = (state: any, data?: any) => any
46
+ import { Signal } from './signal.js'