Skip to content

Commit 0085a51

Browse files
Merge pull request #22 from efflore/v0.8.5-docs
V0.8.5 docs
2 parents 90b9294 + b024b71 commit 0085a51

17 files changed

+1178
-893
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
UIElement - the "look ma, no JS framework!" library bringing signals-based reactivity to vanilla Web Components
44

5-
Version 0.8.4
5+
Version 0.8.5
66

77
## What is UIElement?
88

docs/installation-setup.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ <h2>Installing with NPM</h2>
155155
</p>
156156
</section>
157157

158-
<!-- <section>
158+
<section>
159159
<h2>Creating Your First Component</h2>
160160
<p>
161161
Let's verify your setup by creating an interactive <code>HelloWorld</code> component that updates based on user input.
@@ -178,7 +178,7 @@ <h2>Creating Your First Component</h2>
178178
&lt;input type="text" id="name-input" /&gt;
179179
&lt;p&gt;Hello, &lt;span class="greeting"&gt;World&lt;/span&gt;!&lt;/p&gt;
180180
&lt;/hello-world&gt;</code></pre>
181-
</section> -->
181+
</section>
182182

183183
<section>
184184
<h2>Verifying Installation</h2>

index.js

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const isString = isOfType('string');
44
const isObject = isOfType('object');
55
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
66
const isFunction = isOfType('function');
7+
const isNull = (value) => value === null;
78
const isNullish = (value) => value == null;
89
const isDefined = (value) => value != null;
910
const isDefinedObject = (value) => isDefined(value) && (isObject(value) || isFunction(value));
@@ -266,7 +267,7 @@ const initContext = (host) => {
266267
if (!provided.includes(context) || !isFunction(callback))
267268
return;
268269
e.stopPropagation();
269-
callback(host.get(String(context)));
270+
callback(host.signal(String(context)));
270271
});
271272
};
272273

@@ -338,7 +339,7 @@ const off = (event, handler) =>
338339
*
339340
* @since 0.8.3
340341
* @param {string} event - event name to dispatch
341-
* @param {StateLike} state - state key
342+
* @param {StateLike<unknown>} state - state key
342343
*/
343344
const emit = (event, state = event) =>
344345
/**
@@ -414,19 +415,25 @@ const asJSON = (value) => {
414415
*
415416
* @since 0.8.0
416417
* @param {UI} ui - UI object of host UIElement and target element to update properties
417-
* @param {StateLike} state - state to be set to the host element
418+
* @param {StateLike<T>} state - state to be set to the host element
418419
* @param {string} prop - property name to be updated
419-
* @param {T} fallback - fallback value to be used if state is not defined
420-
* @param {(element: E) => () => void} onNothing - callback to be executed when state is not defined
421-
* @param {(value: T) => (element: E) => () => void} onSomething - callback to be executed when state is defined
420+
* @param {() => T} getter - getter function to retrieve current value in the DOM
421+
* @param {(value: T) => (element: E) => () => void} setter - callback to be executed when state is changed
422422
* @returns {UI} object with host and target
423423
*/
424-
const autoEffect = (ui, state, prop, fallback, onNothing, onSomething) => {
424+
const autoEffect = (ui, state, prop, getter, setter, remover) => {
425+
const fallback = getter();
425426
if (!isFunction(state))
426427
ui.host.set(state, isString(state) && isString(fallback) ? parse(ui.host, state, fallback) : fallback, false);
427428
effect((enqueue) => {
428-
const value = isFunction(state) ? state() : ui.host.get(state);
429-
enqueue(ui.target, prop, isNullish(value) ? onNothing : onSomething(value));
429+
const current = getter();
430+
const value = isFunction(state) ? state(current) : ui.host.get(state);
431+
if (!Object.is(value, current))
432+
enqueue(ui.target, prop, remover && isNull(value)
433+
? remover
434+
: isNullish(value)
435+
? setter(fallback)
436+
: setter(value));
430437
});
431438
return ui;
432439
};
@@ -435,64 +442,54 @@ const autoEffect = (ui, state, prop, fallback, onNothing, onSomething) => {
435442
* Set text content of an element
436443
*
437444
* @since 0.8.0
438-
* @param {StateLike} state - state bounded to the text content
439-
*/
440-
const setText = (state) => (ui) => {
441-
const fallback = ui.target.textContent || '';
442-
const setter = (value) => (element) => () => {
443-
Array.from(element.childNodes)
444-
.filter(isComment)
445-
.forEach(match => match.remove());
446-
element.append(document.createTextNode(value));
447-
};
448-
return autoEffect(ui, state, 't', fallback, setter(fallback), setter);
449-
};
445+
* @param {StateLike<string>} state - state bounded to the text content
446+
*/
447+
const setText = (state) => (ui) => autoEffect(ui, state, 't', () => ui.target.textContent || '', (value) => (element) => () => {
448+
Array.from(element.childNodes)
449+
.filter(isComment)
450+
.forEach(match => match.remove());
451+
element.append(document.createTextNode(value));
452+
});
450453
/**
451454
* Set property of an element
452455
*
453456
* @since 0.8.0
454457
* @param {PropertyKey} key - name of property to be set
455-
* @param {StateLike} state - state bounded to the property value
458+
* @param {StateLike<unknown>} state - state bounded to the property value
456459
*/
457-
const setProperty = (key, state = key) => (ui) => {
458-
const setter = (value) => (element) => () => element[key] = value;
459-
return autoEffect(ui, state, `p-${String(key)}`, ui.target[key], setter(null), setter);
460-
};
460+
const setProperty = (key, state = key) => (ui) => autoEffect(ui, state, `p-${String(key)}`, () => ui.target[key], (value) => (element) => () => element[key] = value);
461461
/**
462462
* Set attribute of an element
463463
*
464464
* @since 0.8.0
465465
* @param {string} name - name of attribute to be set
466-
* @param {StateLike} state - state bounded to the attribute value
466+
* @param {StateLike<string>} state - state bounded to the attribute value
467467
*/
468-
const setAttribute = (name, state = name) => (ui) => autoEffect(ui, state, `a-${name}`, ui.target.getAttribute(name), (element) => () => element.removeAttribute(name), (value) => (element) => () => element.setAttribute(name, value));
468+
const setAttribute = (name, state = name) => (ui) => autoEffect(ui, state, `a-${name}`, () => ui.target.getAttribute(name), (value) => (element) => () => element.setAttribute(name, value), (element) => () => element.removeAttribute(name));
469469
/**
470470
* Toggle a boolan attribute of an element
471471
*
472472
* @since 0.8.0
473473
* @param {string} name - name of attribute to be toggled
474-
* @param {StateLike} state - state bounded to the attribute existence
474+
* @param {StateLike<boolean>} state - state bounded to the attribute existence
475475
*/
476-
const toggleAttribute = (name, state = name) => (ui) => {
477-
const setter = (value) => (element) => () => element.toggleAttribute(name, value);
478-
return autoEffect(ui, state, `a-${name}`, ui.target.hasAttribute(name), setter(false), setter);
479-
};
476+
const toggleAttribute = (name, state = name) => (ui) => autoEffect(ui, state, `a-${name}`, () => ui.target.hasAttribute(name), (value) => (element) => () => element.toggleAttribute(name, value));
480477
/**
481478
* Toggle a classList token of an element
482479
*
483480
* @since 0.8.0
484481
* @param {string} token - class token to be toggled
485-
* @param {StateLike} state - state bounded to the class existence
482+
* @param {StateLike<boolean>} state - state bounded to the class existence
486483
*/
487-
const toggleClass = (token, state = token) => (ui) => autoEffect(ui, state, `c-${token}`, ui.target.classList.contains(token), (element) => () => element.classList.remove(token), (value) => (element) => () => element.classList.toggle(token, value));
484+
const toggleClass = (token, state = token) => (ui) => autoEffect(ui, state, `c-${token}`, () => ui.target.classList.contains(token), (value) => (element) => () => element.classList.toggle(token, value));
488485
/**
489486
* Set a style property of an element
490487
*
491488
* @since 0.8.0
492489
* @param {string} prop - name of style property to be set
493-
* @param {StateLike} state - state bounded to the style property value
490+
* @param {StateLike<string>} state - state bounded to the style property value
494491
*/
495-
const setStyle = (prop, state = prop) => (ui) => autoEffect(ui, state, `s-${prop}`, ui.target.style[prop], (element) => () => element.style.removeProperty(prop), (value) => (element) => () => element.style[prop] = value);
492+
const setStyle = (prop, state = prop) => (ui) => autoEffect(ui, state, `s-${prop}`, () => ui.target.style.getPropertyValue(prop), (value) => (element) => () => element.style.setProperty(prop, value), (element) => () => element.style.removeProperty(prop));
496493

497494
/* === Exported Class and Functions === */
498495
/**

index.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { setAttribute, setProperty, setStyle, setText, toggleAttribute, toggleCl
99

1010
/**
1111
* @name UIElement
12-
* @version 0.8.4
12+
* @version 0.8.5
1313
*/
1414

1515
export {

src/core/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const initContext = (host: UIElement) => {
106106
const { context, callback } = e
107107
if (!provided.includes(context) || !isFunction(callback)) return
108108
e.stopPropagation()
109-
callback(host.get(String(context)))
109+
callback(host.signal(String(context)))
110110
})
111111
}
112112

0 commit comments

Comments
 (0)