@oscarpalmer/abydon 0.22.0 → 0.23.1
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/dist/abydon.full.mjs +223 -161
- package/dist/attribute/index.d.mts +3 -2
- package/dist/attribute/index.mjs +23 -17
- package/dist/attribute/value.mjs +18 -28
- package/dist/constants.d.mts +4 -8
- package/dist/constants.mjs +6 -10
- package/dist/fragment.d.mts +27 -14
- package/dist/fragment.mjs +32 -16
- package/dist/fragments.d.mts +1 -2
- package/dist/fragments.mjs +2 -2
- package/dist/helpers/dom.d.mts +2 -3
- package/dist/helpers/dom.mjs +2 -4
- package/dist/helpers/index.d.mts +9 -5
- package/dist/helpers/index.mjs +11 -5
- package/dist/index.d.mts +33 -6
- package/dist/index.mjs +33 -6
- package/dist/models.d.mts +6 -4
- package/dist/node/index.mjs +18 -33
- package/dist/node/value.mjs +67 -50
- package/package.json +2 -2
- package/src/attribute/index.ts +43 -35
- package/src/attribute/value.ts +20 -53
- package/src/constants.ts +6 -14
- package/src/fragment.ts +34 -17
- package/src/fragments.ts +4 -2
- package/src/helpers/dom.ts +3 -5
- package/src/helpers/index.ts +19 -5
- package/src/index.ts +33 -6
- package/src/models.ts +6 -4
- package/src/node/index.ts +25 -63
- package/src/node/value.ts +117 -85
- package/src/parse.ts +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FragmentData } from "../models.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/attribute/index.d.ts
|
|
4
|
-
declare function
|
|
4
|
+
declare function mapAttributeValue(data: FragmentData, element: HTMLElement | SVGElement, name: string, value: unknown): void;
|
|
5
|
+
declare function mapAttributes(data: FragmentData, element: HTMLElement | SVGElement, ignoreValue: boolean): void;
|
|
5
6
|
//#endregion
|
|
6
|
-
export { mapAttributes };
|
|
7
|
+
export { mapAttributeValue, mapAttributes };
|
package/dist/attribute/index.mjs
CHANGED
|
@@ -1,42 +1,48 @@
|
|
|
1
1
|
import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX } from "../constants.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { setComputedValue } from "../helpers/index.mjs";
|
|
3
3
|
import { mapEvent } from "../node/event.mjs";
|
|
4
4
|
import { setAttribute } from "./value.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
6
|
+
import { isSignal } from "@oscarpalmer/mora";
|
|
7
|
+
import { isInputElement } from "@oscarpalmer/toretto/is";
|
|
6
8
|
//#region src/attribute/index.ts
|
|
9
|
+
function compareAttributes(first, second) {
|
|
10
|
+
return first.name.localeCompare(second.name);
|
|
11
|
+
}
|
|
7
12
|
function getValue(data, original) {
|
|
8
13
|
const matches = EXPRESSION_ABYDON_CONTENT.exec(original);
|
|
9
14
|
return matches == null ? original : data.values[+matches[1]];
|
|
10
15
|
}
|
|
11
|
-
function
|
|
12
|
-
|
|
16
|
+
function mapAttributeValue(data, element, name, value) {
|
|
17
|
+
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
18
|
+
else setAttribute(data, element, name, value);
|
|
19
|
+
if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
|
|
20
|
+
value.set(element[name]);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function mapAttributes(data, element, ignoreValue) {
|
|
24
|
+
const attributes = [...element.attributes].sort(compareAttributes);
|
|
13
25
|
const { length } = attributes;
|
|
14
26
|
for (let index = 0; index < length; index += 1) {
|
|
15
27
|
const { name, value } = attributes[index];
|
|
16
28
|
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, "");
|
|
17
|
-
const actualValue = getValue(data, value);
|
|
18
29
|
if (actualName !== name) element.removeAttribute(name);
|
|
30
|
+
if (isNullableOrWhitespace(value) || actualName === "value" && ignoreValue) continue;
|
|
31
|
+
const actualValue = getValue(data, value);
|
|
19
32
|
switch (true) {
|
|
20
33
|
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
21
34
|
mapEvent(element, actualName, actualValue);
|
|
22
35
|
break;
|
|
23
36
|
default:
|
|
24
|
-
|
|
37
|
+
mapAttributeValue(data, element, actualName, actualValue);
|
|
25
38
|
break;
|
|
26
39
|
}
|
|
27
40
|
}
|
|
28
41
|
}
|
|
29
|
-
function mapValue(data, element, name, value) {
|
|
30
|
-
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
31
|
-
else setAttribute(data, element, name, value);
|
|
32
|
-
if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
|
|
33
|
-
value.set(element[name]);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
42
|
function setComputedAttribute(data, element, name, callback) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
setComputedValue(data, callback, (computation) => {
|
|
44
|
+
setAttribute(data, element, name, computation);
|
|
45
|
+
});
|
|
40
46
|
}
|
|
41
47
|
//#endregion
|
|
42
|
-
export { mapAttributes };
|
|
48
|
+
export { mapAttributeValue, mapAttributes };
|
package/dist/attribute/value.mjs
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
1
|
+
import { EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_ATTRIBUTE_STYLE_VARIABLE } from "../constants.mjs";
|
|
2
2
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
3
3
|
import { getString } from "@oscarpalmer/atoms/string";
|
|
4
4
|
import { isReactive } from "@oscarpalmer/mora";
|
|
5
|
-
import { camelCase } from "@oscarpalmer/atoms/string/case";
|
|
6
5
|
import { setAttribute as setAttribute$1 } from "@oscarpalmer/toretto/attribute";
|
|
7
6
|
import { setStyle } from "@oscarpalmer/toretto/style";
|
|
8
7
|
//#region src/attribute/value.ts
|
|
9
|
-
function getStyleValue(value, unit,
|
|
10
|
-
if (removeStyleValue(value, unit,
|
|
8
|
+
function getStyleValue(value, unit, isVariable) {
|
|
9
|
+
if (removeStyleValue(value, unit, isVariable)) return;
|
|
11
10
|
return value === true || value === "true" ? unit : `${getString(value)}${unit ?? ""}`;
|
|
12
11
|
}
|
|
13
|
-
function removeStyleValue(value, unit,
|
|
14
|
-
if (value == null || value === false ||
|
|
12
|
+
function removeStyleValue(value, unit, isVariable) {
|
|
13
|
+
if (value == null || value === false || isVariable && isNullableOrWhitespace(value)) return true;
|
|
15
14
|
return unit == null && (value === true || value === "true");
|
|
16
15
|
}
|
|
17
16
|
function setAttribute(data, element, name, value) {
|
|
@@ -28,36 +27,27 @@ function setAttribute(data, element, name, value) {
|
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
function setClassValues(data, element, name, value) {
|
|
31
|
-
|
|
30
|
+
const classes = name.slice(6).split(".");
|
|
31
|
+
updateValue(data, value, (value) => {
|
|
32
32
|
if (value === true || value === "true") element.classList.add(...classes);
|
|
33
33
|
else element.classList.remove(...classes);
|
|
34
|
-
}
|
|
35
|
-
const classes = name.slice(6).split(".");
|
|
36
|
-
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
37
|
-
else update(value);
|
|
34
|
+
});
|
|
38
35
|
}
|
|
39
36
|
function setStyleValues(data, element, name, value) {
|
|
40
37
|
let [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name);
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
setStyle(element, property, getStyleValue(value, unit, isProperty));
|
|
46
|
-
}
|
|
47
|
-
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
48
|
-
else update(value);
|
|
38
|
+
const isVariable = EXPRESSION_ATTRIBUTE_STYLE_VARIABLE.test(name);
|
|
39
|
+
updateValue(data, value, (value) => {
|
|
40
|
+
setStyle(element, property, getStyleValue(value, unit, isVariable));
|
|
41
|
+
});
|
|
49
42
|
}
|
|
50
43
|
function setValue(data, element, name, value) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
setAttribute$1(element, name, next);
|
|
55
|
-
}));
|
|
56
|
-
else setAttribute$1(element, name, value);
|
|
44
|
+
updateValue(data, value, (value) => {
|
|
45
|
+
setAttribute$1(element, name, value);
|
|
46
|
+
});
|
|
57
47
|
}
|
|
58
|
-
function
|
|
59
|
-
if (
|
|
60
|
-
|
|
48
|
+
function updateValue(data, value, updater) {
|
|
49
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(updater));
|
|
50
|
+
else updater(value);
|
|
61
51
|
}
|
|
62
52
|
//#endregion
|
|
63
53
|
export { setAttribute };
|
package/dist/constants.d.mts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
declare const ARRAY_COMPARISON_ADDED = "added";
|
|
3
3
|
declare const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
4
4
|
declare const ARRAY_COMPARISON_REMOVED = "removed";
|
|
5
|
-
declare const ATTRIBUTE_CLASS_PREFIX_LENGTH
|
|
5
|
+
declare const ATTRIBUTE_CLASS_PREFIX_LENGTH: number;
|
|
6
6
|
declare const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
7
|
declare const CHANGE_INPUTS: Set<string>;
|
|
8
8
|
declare const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
9
|
-
declare const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '
|
|
9
|
+
declare const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
10
10
|
declare const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
11
11
|
declare const EVENT_CHANGE = "change";
|
|
12
12
|
declare const EVENT_INPUT = "input";
|
|
@@ -20,24 +20,20 @@ declare const EXPRESSION_ABYDON_CONTENT: RegExp;
|
|
|
20
20
|
declare const EXPRESSION_ATTRIBUTE_CLASS: RegExp;
|
|
21
21
|
declare const EXPRESSION_ATTRIBUTE_STYLE_FULL: RegExp;
|
|
22
22
|
declare const EXPRESSION_ATTRIBUTE_STYLE_PREFIX: RegExp;
|
|
23
|
-
declare const
|
|
23
|
+
declare const EXPRESSION_ATTRIBUTE_STYLE_VARIABLE: RegExp;
|
|
24
24
|
declare const EXPRESSION_EVENT_ATTRIBUTE: RegExp;
|
|
25
25
|
declare const EXPRESSION_EVENT_NAME: RegExp;
|
|
26
26
|
declare const EXPRESSION_EVENT_OPTIONS_ACTIVE: RegExp;
|
|
27
27
|
declare const EXPRESSION_EVENT_OPTIONS_CAPTURE: RegExp;
|
|
28
28
|
declare const EXPRESSION_EVENT_OPTIONS_ONCE: RegExp;
|
|
29
29
|
declare const EXPRESSION_EVENT_PREFIX: RegExp;
|
|
30
|
-
declare const EXPRESSION_PERIOD: RegExp;
|
|
31
30
|
declare const EXPRESSION_TEXTAREA_VALUE: RegExp;
|
|
32
|
-
declare const INPUT_TYPE_CHECKBOX = "checkbox";
|
|
33
|
-
declare const INPUT_TYPE_RADIO = "radio";
|
|
34
31
|
declare const NAME_FRAGMENT = "$fragment";
|
|
35
32
|
declare const NAME_FRAGMENTS = "$fragments";
|
|
36
|
-
declare const PROPERTY_CHECKED = "checked";
|
|
37
33
|
declare const PROPERTY_IDENTIFIER = "identifier";
|
|
38
34
|
declare const PROPERTY_VALUE = "value";
|
|
39
35
|
declare const TEMPLATE_ITEM = "<>";
|
|
40
36
|
declare const VALUE_TRUE = "true";
|
|
41
37
|
declare const WHITESPACE: RegExp;
|
|
42
38
|
//#endregion
|
|
43
|
-
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
39
|
+
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_ATTRIBUTE_STYLE_VARIABLE, EXPRESSION_EVENT_ATTRIBUTE, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_TEXTAREA_VALUE, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM, VALUE_TRUE, WHITESPACE };
|
package/dist/constants.mjs
CHANGED
|
@@ -6,7 +6,7 @@ const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
|
6
6
|
const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
7
|
const CHANGE_INPUTS = new Set(["checkbox", "radio"]);
|
|
8
8
|
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
9
|
-
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '
|
|
9
|
+
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
10
10
|
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
11
11
|
const EVENT_CHANGE = "change";
|
|
12
12
|
const EVENT_INPUT = "input";
|
|
@@ -27,24 +27,20 @@ const EXPRESSION_ABYDON_CONTENT = /^abydon\.(\d+)$/;
|
|
|
27
27
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
28
28
|
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
29
29
|
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
30
|
-
const
|
|
30
|
+
const EXPRESSION_ATTRIBUTE_STYLE_VARIABLE = /^style\.--/;
|
|
31
31
|
const EXPRESSION_EVENT_ATTRIBUTE = /^@([\w-]+)(?::([a-z:]+))?="$/i;
|
|
32
32
|
const EXPRESSION_EVENT_NAME = /^@?([\w-]+)(?::([a-z:]+))?$/i;
|
|
33
|
-
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
34
|
-
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
35
|
-
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
33
|
+
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(?:ctive)$/i;
|
|
34
|
+
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(?:apture)$/i;
|
|
35
|
+
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(?:nce)$/i;
|
|
36
36
|
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
37
|
-
const EXPRESSION_PERIOD = /\./;
|
|
38
37
|
const EXPRESSION_TEXTAREA_VALUE = /(?:<|<)!--abydon\.(\d+)--(?:>|>)/;
|
|
39
|
-
const INPUT_TYPE_CHECKBOX = "checkbox";
|
|
40
|
-
const INPUT_TYPE_RADIO = "radio";
|
|
41
38
|
const NAME_FRAGMENT = "$fragment";
|
|
42
39
|
const NAME_FRAGMENTS = "$fragments";
|
|
43
|
-
const PROPERTY_CHECKED = "checked";
|
|
44
40
|
const PROPERTY_IDENTIFIER = "identifier";
|
|
45
41
|
const PROPERTY_VALUE = "value";
|
|
46
42
|
const TEMPLATE_ITEM = "<>";
|
|
47
43
|
const VALUE_TRUE = "true";
|
|
48
44
|
const WHITESPACE = /\s+/g;
|
|
49
45
|
//#endregion
|
|
50
|
-
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
46
|
+
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_ON_VALUE, EVENT_OPTIONS_DELIMITER, EVENT_SUBMIT, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_ATTRIBUTE_STYLE_VARIABLE, EXPRESSION_EVENT_ATTRIBUTE, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_TEXTAREA_VALUE, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM, VALUE_TRUE, WHITESPACE };
|
package/dist/fragment.d.mts
CHANGED
|
@@ -6,39 +6,52 @@ declare class Fragment {
|
|
|
6
6
|
/**
|
|
7
7
|
* Is template caching enabled?
|
|
8
8
|
*/
|
|
9
|
-
get
|
|
9
|
+
get cache(): boolean;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Identifier for the _Fragment_
|
|
12
|
+
*
|
|
13
|
+
* _An identifier can be used to uniquely identify a Fragment, which helps prevent re-rendering in reactive arrays and Fragments_
|
|
12
14
|
*/
|
|
13
15
|
get identifier(): unknown;
|
|
14
16
|
constructor(strings: TemplateStringsArray, expressions: unknown[]);
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
18
|
+
* Insert the _Fragment_ after the given element
|
|
19
|
+
* @param element Element to insert after
|
|
20
|
+
*/
|
|
21
|
+
after(element: Element): void;
|
|
22
|
+
/**
|
|
23
|
+
* Append the _Fragment_ to the given element
|
|
17
24
|
* @param element Element to append to
|
|
18
25
|
*/
|
|
19
26
|
appendTo(element: Element): void;
|
|
20
27
|
/**
|
|
21
|
-
*
|
|
28
|
+
* Insert the _Fragment_ before the given element
|
|
29
|
+
* @param element Element to insert before
|
|
30
|
+
*/
|
|
31
|
+
before(element: Element): void;
|
|
32
|
+
/**
|
|
33
|
+
* Configure the _Fragment_
|
|
34
|
+
*
|
|
35
|
+
* _Returns the Fragment instance for chaining_
|
|
22
36
|
* @param configuration Configuration options
|
|
23
|
-
* @returns
|
|
37
|
+
* @returns _Fragment_
|
|
24
38
|
*/
|
|
25
39
|
configure(configuration: FragmentConfiguration): Fragment;
|
|
26
40
|
/**
|
|
27
|
-
* Get a list of the
|
|
41
|
+
* Get a list of the _Fragment_'s nodes
|
|
28
42
|
* @returns List of nodes
|
|
29
43
|
*/
|
|
30
44
|
get(): ChildNode[];
|
|
31
45
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* _An identifier can be used to uniquely identify a fragment,
|
|
35
|
-
* which helps prevent re-rendering in certain scenarios._
|
|
36
|
-
* @param identifier Identifier
|
|
37
|
-
* @returns Fragment
|
|
46
|
+
* Prepend the _Fragment_ to the given element
|
|
47
|
+
* @param element Element to prepend to
|
|
38
48
|
*/
|
|
39
|
-
|
|
49
|
+
prependTo(element: Element): void;
|
|
40
50
|
/**
|
|
41
|
-
* Remove the
|
|
51
|
+
* Remove the _Fragment_ _(and all its descendants)_ from the _DOM_
|
|
52
|
+
*
|
|
53
|
+
* - _Any events, reactive values, and Fragments will also be cleaned up and removed_
|
|
54
|
+
* - _After being removed, the Fragment can be re-inserted into the DOM_
|
|
42
55
|
*/
|
|
43
56
|
remove(): void;
|
|
44
57
|
}
|
package/dist/fragment.mjs
CHANGED
|
@@ -16,11 +16,13 @@ var Fragment = class {
|
|
|
16
16
|
/**
|
|
17
17
|
* Is template caching enabled?
|
|
18
18
|
*/
|
|
19
|
-
get
|
|
19
|
+
get cache() {
|
|
20
20
|
return this.#configuration.cache;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Identifier for the _Fragment_
|
|
24
|
+
*
|
|
25
|
+
* _An identifier can be used to uniquely identify a Fragment, which helps prevent re-rendering in reactive arrays and Fragments_
|
|
24
26
|
*/
|
|
25
27
|
get identifier() {
|
|
26
28
|
return this.#configuration.identifier;
|
|
@@ -39,16 +41,32 @@ var Fragment = class {
|
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
|
-
*
|
|
44
|
+
* Insert the _Fragment_ after the given element
|
|
45
|
+
* @param element Element to insert after
|
|
46
|
+
*/
|
|
47
|
+
after(element) {
|
|
48
|
+
element.after(...this.get());
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Append the _Fragment_ to the given element
|
|
43
52
|
* @param element Element to append to
|
|
44
53
|
*/
|
|
45
54
|
appendTo(element) {
|
|
46
55
|
element.append(...this.get());
|
|
47
56
|
}
|
|
48
57
|
/**
|
|
49
|
-
*
|
|
58
|
+
* Insert the _Fragment_ before the given element
|
|
59
|
+
* @param element Element to insert before
|
|
60
|
+
*/
|
|
61
|
+
before(element) {
|
|
62
|
+
element.before(...this.get());
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Configure the _Fragment_
|
|
66
|
+
*
|
|
67
|
+
* _Returns the Fragment instance for chaining_
|
|
50
68
|
* @param configuration Configuration options
|
|
51
|
-
* @returns
|
|
69
|
+
* @returns _Fragment_
|
|
52
70
|
*/
|
|
53
71
|
configure(configuration) {
|
|
54
72
|
const actual = isPlainObject(configuration) ? configuration : {};
|
|
@@ -57,7 +75,7 @@ var Fragment = class {
|
|
|
57
75
|
return this;
|
|
58
76
|
}
|
|
59
77
|
/**
|
|
60
|
-
* Get a list of the
|
|
78
|
+
* Get a list of the _Fragment_'s nodes
|
|
61
79
|
* @returns List of nodes
|
|
62
80
|
*/
|
|
63
81
|
get() {
|
|
@@ -70,19 +88,17 @@ var Fragment = class {
|
|
|
70
88
|
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
|
|
71
89
|
}
|
|
72
90
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* _An identifier can be used to uniquely identify a fragment,
|
|
76
|
-
* which helps prevent re-rendering in certain scenarios._
|
|
77
|
-
* @param identifier Identifier
|
|
78
|
-
* @returns Fragment
|
|
91
|
+
* Prepend the _Fragment_ to the given element
|
|
92
|
+
* @param element Element to prepend to
|
|
79
93
|
*/
|
|
80
|
-
|
|
81
|
-
this
|
|
82
|
-
return this;
|
|
94
|
+
prependTo(element) {
|
|
95
|
+
element.prepend(...this.get());
|
|
83
96
|
}
|
|
84
97
|
/**
|
|
85
|
-
* Remove the
|
|
98
|
+
* Remove the _Fragment_ _(and all its descendants)_ from the _DOM_
|
|
99
|
+
*
|
|
100
|
+
* - _Any events, reactive values, and Fragments will also be cleaned up and removed_
|
|
101
|
+
* - _After being removed, the Fragment can be re-inserted into the DOM_
|
|
86
102
|
*/
|
|
87
103
|
remove() {
|
|
88
104
|
removeFragment(this.#data);
|
package/dist/fragments.d.mts
CHANGED
|
@@ -8,7 +8,6 @@ declare class Fragments {
|
|
|
8
8
|
constructor(items: ReactiveArray<unknown>, identify: (item: unknown) => unknown, fragment: (item: unknown) => Fragment);
|
|
9
9
|
}
|
|
10
10
|
declare function handleFragments(item: Fragments | FragmentsState, remove: boolean): void;
|
|
11
|
-
declare function initializeFragments(state: FragmentsState): void;
|
|
12
11
|
declare const fragmentsStates: WeakMap<Fragments, FragmentsState>;
|
|
13
12
|
//#endregion
|
|
14
|
-
export { Fragments, fragmentsStates, handleFragments
|
|
13
|
+
export { Fragments, fragmentsStates, handleFragments };
|
package/dist/fragments.mjs
CHANGED
|
@@ -38,7 +38,7 @@ function handleItems(state, items) {
|
|
|
38
38
|
instance = state.fragment(item);
|
|
39
39
|
if (!isFragment(instance)) throw new Error(ERROR_FRAGMENT);
|
|
40
40
|
}
|
|
41
|
-
instance.
|
|
41
|
+
instance.configure({ identifier: key });
|
|
42
42
|
state.instances[key] = instance;
|
|
43
43
|
keys.add(key);
|
|
44
44
|
mapped.push(instance);
|
|
@@ -71,4 +71,4 @@ function updateFragments(state, active) {
|
|
|
71
71
|
}
|
|
72
72
|
const fragmentsStates = /* @__PURE__ */ new WeakMap();
|
|
73
73
|
//#endregion
|
|
74
|
-
export { Fragments, fragmentsStates, handleFragments
|
|
74
|
+
export { Fragments, fragmentsStates, handleFragments };
|
package/dist/helpers/dom.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
//#region src/helpers/dom.d.ts
|
|
2
2
|
declare function createNodes(value: unknown): ChildNode[];
|
|
3
|
-
declare function isInputElement(node: Node): node is HTMLInputElement | HTMLSelectElement;
|
|
4
3
|
declare function removeNodes(nodes: ChildNode[]): void;
|
|
5
|
-
declare function replaceNodes(from: ChildNode[], to: ChildNode[]):
|
|
4
|
+
declare function replaceNodes(from: ChildNode[], to: ChildNode[]): ChildNode[];
|
|
6
5
|
//#endregion
|
|
7
|
-
export { createNodes,
|
|
6
|
+
export { createNodes, removeNodes, replaceNodes };
|
package/dist/helpers/dom.mjs
CHANGED
|
@@ -7,9 +7,6 @@ function createNodes(value) {
|
|
|
7
7
|
if (isChildNode(value)) return [value];
|
|
8
8
|
return [new Text(getString(value))];
|
|
9
9
|
}
|
|
10
|
-
function isInputElement(node) {
|
|
11
|
-
return node instanceof HTMLInputElement || node instanceof HTMLSelectElement;
|
|
12
|
-
}
|
|
13
10
|
function removeNodes(nodes) {
|
|
14
11
|
const { length } = nodes;
|
|
15
12
|
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
@@ -18,6 +15,7 @@ function replaceNodes(from, to) {
|
|
|
18
15
|
from[0]?.replaceWith(...to);
|
|
19
16
|
const { length } = from;
|
|
20
17
|
for (let index = 1; index < length; index += 1) from[index].remove();
|
|
18
|
+
return to;
|
|
21
19
|
}
|
|
22
20
|
//#endregion
|
|
23
|
-
export { createNodes,
|
|
21
|
+
export { createNodes, removeNodes, replaceNodes };
|
package/dist/helpers/index.d.mts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { Fragment } from "../fragment.mjs";
|
|
2
|
+
import { FragmentData } from "../models.mjs";
|
|
2
3
|
import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED } from "../constants.mjs";
|
|
3
4
|
import { Fragments } from "../fragments.mjs";
|
|
5
|
+
import { Computed } from "@oscarpalmer/mora";
|
|
6
|
+
import { GenericCallback } from "@oscarpalmer/atoms/models";
|
|
4
7
|
|
|
5
8
|
//#region src/helpers/index.d.ts
|
|
6
9
|
declare function compareArrays(first: unknown[], second: unknown[]): typeof ARRAY_COMPARISON_ADDED | typeof ARRAY_COMPARISON_DISSIMILAR | typeof ARRAY_COMPARISON_REMOVED;
|
|
7
10
|
/**
|
|
8
|
-
* Is the value a
|
|
11
|
+
* Is the value a _Fragment_?
|
|
9
12
|
* @param value Value to check
|
|
10
|
-
* @returns `true` if the value is a
|
|
13
|
+
* @returns `true` if the value is a _Fragment_, otherwise `false`
|
|
11
14
|
*/
|
|
12
15
|
declare function isFragment(value: unknown): value is Fragment;
|
|
13
16
|
/**
|
|
14
|
-
* Is the value a
|
|
17
|
+
* Is the value a _Fragments_ instance?
|
|
15
18
|
* @param value Value to check
|
|
16
|
-
* @returns `true` if the value is a
|
|
19
|
+
* @returns `true` if the value is a _Fragments_ instance, otherwise `false`
|
|
17
20
|
*/
|
|
18
21
|
declare function isFragments(value: unknown): value is Fragments;
|
|
22
|
+
declare function setComputedValue(data: FragmentData, callback: GenericCallback, after: (computation: Computed<unknown>) => void): void;
|
|
19
23
|
//#endregion
|
|
20
|
-
export { compareArrays, isFragment, isFragments };
|
|
24
|
+
export { compareArrays, isFragment, isFragments, setComputedValue };
|
package/dist/helpers/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, NAME_FRAGMENT, NAME_FRAGMENTS } from "../constants.mjs";
|
|
2
|
+
import { computed } from "@oscarpalmer/mora";
|
|
2
3
|
//#region src/helpers/index.ts
|
|
3
4
|
function compareArrays(first, second) {
|
|
4
5
|
const firstIsLarger = first.length > second.length;
|
|
@@ -8,17 +9,17 @@ function compareArrays(first, second) {
|
|
|
8
9
|
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
|
-
* Is the value a
|
|
12
|
+
* Is the value a _Fragment_?
|
|
12
13
|
* @param value Value to check
|
|
13
|
-
* @returns `true` if the value is a
|
|
14
|
+
* @returns `true` if the value is a _Fragment_, otherwise `false`
|
|
14
15
|
*/
|
|
15
16
|
function isFragment(value) {
|
|
16
17
|
return isNamed(value, NAME_FRAGMENT);
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
19
|
-
* Is the value a
|
|
20
|
+
* Is the value a _Fragments_ instance?
|
|
20
21
|
* @param value Value to check
|
|
21
|
-
* @returns `true` if the value is a
|
|
22
|
+
* @returns `true` if the value is a _Fragments_ instance, otherwise `false`
|
|
22
23
|
*/
|
|
23
24
|
function isFragments(value) {
|
|
24
25
|
return isNamed(value, NAME_FRAGMENTS);
|
|
@@ -26,5 +27,10 @@ function isFragments(value) {
|
|
|
26
27
|
function isNamed(value, name) {
|
|
27
28
|
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
28
29
|
}
|
|
30
|
+
function setComputedValue(data, callback, after) {
|
|
31
|
+
const computation = computed(callback);
|
|
32
|
+
data.mora.values.add(computation);
|
|
33
|
+
after(computation);
|
|
34
|
+
}
|
|
29
35
|
//#endregion
|
|
30
|
-
export { compareArrays, isFragment, isFragments };
|
|
36
|
+
export { compareArrays, isFragment, isFragments, setComputedValue };
|
package/dist/index.d.mts
CHANGED
|
@@ -6,16 +6,43 @@ export * from "@oscarpalmer/mora";
|
|
|
6
6
|
|
|
7
7
|
//#region src/index.d.ts
|
|
8
8
|
/**
|
|
9
|
-
* Create a
|
|
9
|
+
* Create a _Fragments_ instance from a reactive array
|
|
10
|
+
*
|
|
11
|
+
* _A Fragments instance can be used to efficiently render a list of items that may change over time, using unique identifiers to track each item, only adding, removing, or updating each related Fragment._
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const fruits = array(['Apple', 'Banana', 'Cherry']);
|
|
16
|
+
* const items = fragments(
|
|
17
|
+
* fruits,
|
|
18
|
+
* fruit => fruit, // Identifies a unique item
|
|
19
|
+
* fruit => html`<p>${fruit}</p>`, // Creates a Fragment from an item
|
|
20
|
+
* );
|
|
21
|
+
* html`${items}`.appendTo(document.body) // Renders '<p>Apple</p><p>Banana</p><p>Cherry</p>'
|
|
22
|
+
* fruits.push(['Date', 'Elderberry', 'Fig']); // Appends '<p>Date</p><p>Elderberry</p><p>Fig</p>'
|
|
23
|
+
* // without re-rendering the existing Fragments
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
10
26
|
* @param array Reactive array
|
|
11
|
-
* @param identify Function to identify item
|
|
12
|
-
* @param fragment Function to create
|
|
13
|
-
* @returns
|
|
27
|
+
* @param identify Function to identify item uniquely _(non-nullable)_
|
|
28
|
+
* @param fragment Function to create _Fragment_ from item
|
|
29
|
+
* @returns _Fragments_
|
|
14
30
|
*/
|
|
15
31
|
declare function fragments<Item>(array: ReactiveArray<Item>, identify: (item: Item) => unknown, fragment: (item: Item) => Fragment): Fragments;
|
|
16
32
|
/**
|
|
17
|
-
* Create a
|
|
18
|
-
*
|
|
33
|
+
* Create a _Fragment_ from a template
|
|
34
|
+
*
|
|
35
|
+
* _A Fragment can be used to efficiently render a template that may change over time, only updating the necessary parts of the DOM._
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const name = signal('World');
|
|
40
|
+
* const fragment = html`<p>Hello, ${name}!</p>`;
|
|
41
|
+
* fragment.appendTo(document.body); // Renders '<p>Hello, World!</p>'
|
|
42
|
+
* name.set('Alice'); // Replaces 'World' with 'Alice'
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @returns _Fragment_
|
|
19
46
|
*/
|
|
20
47
|
declare function html(template: TemplateStringsArray, ...values: unknown[]): Fragment;
|
|
21
48
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -5,11 +5,27 @@ import { isArray } from "@oscarpalmer/mora";
|
|
|
5
5
|
export * from "@oscarpalmer/mora";
|
|
6
6
|
//#region src/index.ts
|
|
7
7
|
/**
|
|
8
|
-
* Create a
|
|
8
|
+
* Create a _Fragments_ instance from a reactive array
|
|
9
|
+
*
|
|
10
|
+
* _A Fragments instance can be used to efficiently render a list of items that may change over time, using unique identifiers to track each item, only adding, removing, or updating each related Fragment._
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const fruits = array(['Apple', 'Banana', 'Cherry']);
|
|
15
|
+
* const items = fragments(
|
|
16
|
+
* fruits,
|
|
17
|
+
* fruit => fruit, // Identifies a unique item
|
|
18
|
+
* fruit => html`<p>${fruit}</p>`, // Creates a Fragment from an item
|
|
19
|
+
* );
|
|
20
|
+
* html`${items}`.appendTo(document.body) // Renders '<p>Apple</p><p>Banana</p><p>Cherry</p>'
|
|
21
|
+
* fruits.push(['Date', 'Elderberry', 'Fig']); // Appends '<p>Date</p><p>Elderberry</p><p>Fig</p>'
|
|
22
|
+
* // without re-rendering the existing Fragments
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
9
25
|
* @param array Reactive array
|
|
10
|
-
* @param identify Function to identify item
|
|
11
|
-
* @param fragment Function to create
|
|
12
|
-
* @returns
|
|
26
|
+
* @param identify Function to identify item uniquely _(non-nullable)_
|
|
27
|
+
* @param fragment Function to create _Fragment_ from item
|
|
28
|
+
* @returns _Fragments_
|
|
13
29
|
*/
|
|
14
30
|
function fragments(array, identify, fragment) {
|
|
15
31
|
if (!isArray(array)) throw new TypeError("Fragments array must be a reactive array");
|
|
@@ -18,8 +34,19 @@ function fragments(array, identify, fragment) {
|
|
|
18
34
|
return new Fragments(array, identify, fragment);
|
|
19
35
|
}
|
|
20
36
|
/**
|
|
21
|
-
* Create a
|
|
22
|
-
*
|
|
37
|
+
* Create a _Fragment_ from a template
|
|
38
|
+
*
|
|
39
|
+
* _A Fragment can be used to efficiently render a template that may change over time, only updating the necessary parts of the DOM._
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const name = signal('World');
|
|
44
|
+
* const fragment = html`<p>Hello, ${name}!</p>`;
|
|
45
|
+
* fragment.appendTo(document.body); // Renders '<p>Hello, World!</p>'
|
|
46
|
+
* name.set('Alice'); // Replaces 'World' with 'Alice'
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @returns _Fragment_
|
|
23
50
|
*/
|
|
24
51
|
function html(template, ...values) {
|
|
25
52
|
return new Fragment(template, values);
|
package/dist/models.d.mts
CHANGED
|
@@ -2,16 +2,18 @@ import { Fragment } from "./fragment.mjs";
|
|
|
2
2
|
import { Reactive, ReactiveArray, Unsubscribe } from "@oscarpalmer/mora";
|
|
3
3
|
|
|
4
4
|
//#region src/models.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for a _Fragment_
|
|
7
|
+
*/
|
|
5
8
|
type FragmentConfiguration = {
|
|
6
9
|
/**
|
|
7
10
|
* Should the template be cached? _(defaults to `true`)_
|
|
8
11
|
*/
|
|
9
12
|
cache?: boolean;
|
|
10
13
|
/**
|
|
11
|
-
* Identifier for the
|
|
14
|
+
* Identifier for the _Fragment_
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
* which helps prevent re-rendering in certain scenarios)_
|
|
16
|
+
* _An identifier can be used to uniquely identify a Fragment, which helps prevent re-rendering in reactive arrays and Fragments_
|
|
15
17
|
*/
|
|
16
18
|
identifier?: unknown;
|
|
17
19
|
};
|
|
@@ -19,7 +21,7 @@ type FragmentData = {
|
|
|
19
21
|
expressions: unknown[];
|
|
20
22
|
items: FragmentItem[];
|
|
21
23
|
mora: MoraData;
|
|
22
|
-
strings: TemplateStringsArray;
|
|
24
|
+
strings: TemplateStringsArray | string[];
|
|
23
25
|
template?: string;
|
|
24
26
|
values: unknown[];
|
|
25
27
|
};
|