@oscarpalmer/abydon 0.23.0 → 0.24.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.
- package/dist/abydon.full.mjs +1505 -1032
- package/dist/attribute/index.d.mts +4 -6
- package/dist/attribute/index.mjs +4 -5
- package/dist/attribute/value.d.mts +3 -5
- package/dist/attribute/value.mjs +2 -4
- package/dist/constants.d.mts +42 -38
- package/dist/constants.mjs +12 -7
- package/dist/fragment.d.mts +31 -57
- package/dist/fragment.mjs +83 -108
- package/dist/fragments.d.mts +28 -11
- package/dist/fragments.mjs +60 -33
- package/dist/helpers/dom.d.mts +4 -5
- package/dist/helpers/index.d.mts +8 -10
- package/dist/helpers/index.mjs +4 -2
- package/dist/index.d.mts +5 -47
- package/dist/index.mjs +4 -53
- package/dist/models.d.mts +84 -14
- package/dist/node/event.d.mts +2 -3
- package/dist/node/index.d.mts +3 -5
- package/dist/node/index.mjs +5 -8
- package/dist/node/value.d.mts +3 -5
- package/dist/node/value.mjs +8 -7
- package/dist/parse.d.mts +3 -5
- package/package.json +14 -14
- package/src/attribute/index.ts +13 -7
- package/src/attribute/value.ts +11 -7
- package/src/constants.ts +24 -8
- package/src/fragment.ts +154 -130
- package/src/fragments.ts +94 -45
- package/src/helpers/dom.ts +4 -0
- package/src/helpers/index.ts +12 -7
- package/src/index.ts +3 -67
- package/src/models.ts +97 -9
- package/src/node/event.ts +4 -0
- package/src/node/index.ts +17 -15
- package/src/node/value.ts +12 -10
- package/src/parse.ts +7 -3
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { FragmentState } from "../models.mjs";
|
|
3
2
|
//#region src/attribute/index.d.ts
|
|
4
|
-
declare function mapAttributeValue(data:
|
|
5
|
-
declare function mapAttributes(data:
|
|
6
|
-
//#endregion
|
|
7
|
-
export { mapAttributeValue, mapAttributes };
|
|
3
|
+
export declare function mapAttributeValue(data: FragmentState, element: HTMLElement | SVGElement, name: string, value: unknown): void;
|
|
4
|
+
export declare function mapAttributes(data: FragmentState, element: HTMLElement | SVGElement, ignoreValue: boolean): void;
|
|
5
|
+
//#endregion
|
package/dist/attribute/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSI
|
|
|
2
2
|
import { setComputedValue } from "../helpers/index.mjs";
|
|
3
3
|
import { mapEvent } from "../node/event.mjs";
|
|
4
4
|
import { setAttribute } from "./value.mjs";
|
|
5
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
6
|
import { isSignal } from "@oscarpalmer/mora";
|
|
6
7
|
import { isInputElement } from "@oscarpalmer/toretto/is";
|
|
7
8
|
//#region src/attribute/index.ts
|
|
@@ -25,16 +26,14 @@ function mapAttributes(data, element, ignoreValue) {
|
|
|
25
26
|
for (let index = 0; index < length; index += 1) {
|
|
26
27
|
const { name, value } = attributes[index];
|
|
27
28
|
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, "");
|
|
28
|
-
const actualValue = getValue(data, value);
|
|
29
29
|
if (actualName !== name) element.removeAttribute(name);
|
|
30
|
-
if (actualName === "value" && ignoreValue) continue;
|
|
30
|
+
if (isNullableOrWhitespace(value) || actualName === "value" && ignoreValue) continue;
|
|
31
|
+
const actualValue = getValue(data, value);
|
|
31
32
|
switch (true) {
|
|
32
33
|
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
33
34
|
mapEvent(element, actualName, actualValue);
|
|
34
35
|
break;
|
|
35
|
-
default:
|
|
36
|
-
mapAttributeValue(data, element, actualName, actualValue);
|
|
37
|
-
break;
|
|
36
|
+
default: mapAttributeValue(data, element, actualName, actualValue);
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { FragmentState } from "../models.mjs";
|
|
3
2
|
//#region src/attribute/value.d.ts
|
|
4
|
-
declare function setAttribute(data:
|
|
5
|
-
//#endregion
|
|
6
|
-
export { setAttribute };
|
|
3
|
+
export declare function setAttribute(data: FragmentState, element: HTMLElement | SVGElement, name: string, value: unknown): void;
|
|
4
|
+
//#endregion
|
package/dist/attribute/value.mjs
CHANGED
|
@@ -21,9 +21,7 @@ function setAttribute(data, element, name, value) {
|
|
|
21
21
|
case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
|
|
22
22
|
setStyleValues(data, element, name, value);
|
|
23
23
|
return;
|
|
24
|
-
default:
|
|
25
|
-
setValue(data, element, name, value);
|
|
26
|
-
break;
|
|
24
|
+
default: setValue(data, element, name, value);
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
function setClassValues(data, element, name, value) {
|
|
@@ -46,7 +44,7 @@ function setValue(data, element, name, value) {
|
|
|
46
44
|
});
|
|
47
45
|
}
|
|
48
46
|
function updateValue(data, value, updater) {
|
|
49
|
-
if (isReactive(value)) data.mora.
|
|
47
|
+
if (isReactive(value)) data.mora.subscriptions.add(value.subscribe(updater));
|
|
50
48
|
else updater(value);
|
|
51
49
|
}
|
|
52
50
|
//#endregion
|
package/dist/constants.d.mts
CHANGED
|
@@ -1,39 +1,43 @@
|
|
|
1
1
|
//#region src/constants.d.ts
|
|
2
|
-
declare const ARRAY_COMPARISON_ADDED = "added";
|
|
3
|
-
declare const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
4
|
-
declare const ARRAY_COMPARISON_REMOVED = "removed";
|
|
5
|
-
declare const ATTRIBUTE_CLASS_PREFIX_LENGTH: number;
|
|
6
|
-
declare const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
-
declare const CHANGE_INPUTS: Set<string>;
|
|
8
|
-
declare const
|
|
9
|
-
declare const
|
|
10
|
-
declare const
|
|
11
|
-
declare const
|
|
12
|
-
declare const
|
|
13
|
-
declare const
|
|
14
|
-
declare const
|
|
15
|
-
declare const
|
|
16
|
-
declare const
|
|
17
|
-
declare const
|
|
18
|
-
declare const
|
|
19
|
-
declare const
|
|
20
|
-
declare const
|
|
21
|
-
declare const
|
|
22
|
-
declare const
|
|
23
|
-
declare const
|
|
24
|
-
declare const
|
|
25
|
-
declare const
|
|
26
|
-
declare const
|
|
27
|
-
declare const
|
|
28
|
-
declare const
|
|
29
|
-
declare const
|
|
30
|
-
declare const
|
|
31
|
-
declare const
|
|
32
|
-
declare const
|
|
33
|
-
declare const
|
|
34
|
-
declare const
|
|
35
|
-
declare const
|
|
36
|
-
declare const
|
|
37
|
-
declare const
|
|
38
|
-
|
|
39
|
-
export
|
|
2
|
+
export declare const ARRAY_COMPARISON_ADDED = "added";
|
|
3
|
+
export declare const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
4
|
+
export declare const ARRAY_COMPARISON_REMOVED = "removed";
|
|
5
|
+
export declare const ATTRIBUTE_CLASS_PREFIX_LENGTH: number;
|
|
6
|
+
export declare const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
+
export declare const CHANGE_INPUTS: Set<string>;
|
|
8
|
+
export declare const EVENT_CHANGE = "change";
|
|
9
|
+
export declare const EVENT_INPUT = "input";
|
|
10
|
+
export declare const EVENT_SUBMIT = "submit";
|
|
11
|
+
export declare const EVENT_DEFAULTS: Record<string, string>;
|
|
12
|
+
export declare const EVENT_ON_VALUE = "on";
|
|
13
|
+
export declare const EVENT_OPTIONS_DELIMITER = ":";
|
|
14
|
+
export declare const EXPRESSION_ABYDON_ATTRIBUTE_FULL: RegExp;
|
|
15
|
+
export declare const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX: RegExp;
|
|
16
|
+
export declare const EXPRESSION_ABYDON_CONTENT: RegExp;
|
|
17
|
+
export declare const EXPRESSION_ATTRIBUTE_CLASS: RegExp;
|
|
18
|
+
export declare const EXPRESSION_ATTRIBUTE_STYLE_FULL: RegExp;
|
|
19
|
+
export declare const EXPRESSION_ATTRIBUTE_STYLE_PREFIX: RegExp;
|
|
20
|
+
export declare const EXPRESSION_ATTRIBUTE_STYLE_VARIABLE: RegExp;
|
|
21
|
+
export declare const EXPRESSION_EVENT_ATTRIBUTE: RegExp;
|
|
22
|
+
export declare const EXPRESSION_EVENT_NAME: RegExp;
|
|
23
|
+
export declare const EXPRESSION_EVENT_OPTIONS_ACTIVE: RegExp;
|
|
24
|
+
export declare const EXPRESSION_EVENT_OPTIONS_CAPTURE: RegExp;
|
|
25
|
+
export declare const EXPRESSION_EVENT_OPTIONS_ONCE: RegExp;
|
|
26
|
+
export declare const EXPRESSION_EVENT_PREFIX: RegExp;
|
|
27
|
+
export declare const EXPRESSION_TEXTAREA_VALUE: RegExp;
|
|
28
|
+
export declare const MESSAGE_FRAGMENT_VALUE = "Fragment template must be a string or a template strings array";
|
|
29
|
+
export declare const MESSAGE_FRAGMENTS_FRAGMENT_RESULT = "Fragment function must return a Fragment instance";
|
|
30
|
+
export declare const MESSAGE_FRAGMENTS_FRAGMENT_TYPE = "Fragment handler must be a function";
|
|
31
|
+
export declare const MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
32
|
+
export declare const MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_TYPE = "Identifier cannot be null or undefined";
|
|
33
|
+
export declare const MESSAGE_FRAGMENTS_IDENTIFIER_TYPE = "Identifier handler must be a function";
|
|
34
|
+
export declare const MESSAGE_FRAGMENTS_VALUE = "Fragments array must be a reactive array";
|
|
35
|
+
export declare const NAME_FRAGMENT = "fragment";
|
|
36
|
+
export declare const NAME_FRAGMENTS = "fragments";
|
|
37
|
+
export declare const PROPERTY_IDENTIFIER = "identifier";
|
|
38
|
+
export declare const PROPERTY_VALUE = "value";
|
|
39
|
+
export declare const SYMBOL: unique symbol;
|
|
40
|
+
export declare const TEMPLATE_ITEM = "<>";
|
|
41
|
+
export declare const VALUE_TRUE = "true";
|
|
42
|
+
export declare const WHITESPACE: RegExp;
|
|
43
|
+
//#endregion
|
package/dist/constants.mjs
CHANGED
|
@@ -4,10 +4,7 @@ const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
|
4
4
|
const ARRAY_COMPARISON_REMOVED = "removed";
|
|
5
5
|
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
6
6
|
const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
-
const CHANGE_INPUTS = new Set(["checkbox", "radio"]);
|
|
8
|
-
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
9
|
-
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
10
|
-
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
7
|
+
const CHANGE_INPUTS = /* @__PURE__ */ new Set(["checkbox", "radio"]);
|
|
11
8
|
const EVENT_CHANGE = "change";
|
|
12
9
|
const EVENT_INPUT = "input";
|
|
13
10
|
const EVENT_SUBMIT = "submit";
|
|
@@ -35,12 +32,20 @@ const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(?:apture)$/i;
|
|
|
35
32
|
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(?:nce)$/i;
|
|
36
33
|
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
37
34
|
const EXPRESSION_TEXTAREA_VALUE = /(?:<|<)!--abydon\.(\d+)--(?:>|>)/;
|
|
38
|
-
const
|
|
39
|
-
const
|
|
35
|
+
const MESSAGE_FRAGMENT_VALUE = "Fragment template must be a string or a template strings array";
|
|
36
|
+
const MESSAGE_FRAGMENTS_FRAGMENT_RESULT = "Fragment function must return a Fragment instance";
|
|
37
|
+
const MESSAGE_FRAGMENTS_FRAGMENT_TYPE = "Fragment handler must be a function";
|
|
38
|
+
const MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_DUPLICATE = "Duplicate identifier found: '<>'";
|
|
39
|
+
const MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_TYPE = "Identifier cannot be null or undefined";
|
|
40
|
+
const MESSAGE_FRAGMENTS_IDENTIFIER_TYPE = "Identifier handler must be a function";
|
|
41
|
+
const MESSAGE_FRAGMENTS_VALUE = "Fragments array must be a reactive array";
|
|
42
|
+
const NAME_FRAGMENT = "fragment";
|
|
43
|
+
const NAME_FRAGMENTS = "fragments";
|
|
40
44
|
const PROPERTY_IDENTIFIER = "identifier";
|
|
41
45
|
const PROPERTY_VALUE = "value";
|
|
46
|
+
const SYMBOL = Symbol("abydon");
|
|
42
47
|
const TEMPLATE_ITEM = "<>";
|
|
43
48
|
const VALUE_TRUE = "true";
|
|
44
49
|
const WHITESPACE = /\s+/g;
|
|
45
50
|
//#endregion
|
|
46
|
-
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS,
|
|
51
|
+
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, CHANGE_INPUTS, 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, MESSAGE_FRAGMENTS_FRAGMENT_RESULT, MESSAGE_FRAGMENTS_FRAGMENT_TYPE, MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_DUPLICATE, MESSAGE_FRAGMENTS_IDENTIFIER_RESULT_TYPE, MESSAGE_FRAGMENTS_IDENTIFIER_TYPE, MESSAGE_FRAGMENTS_VALUE, MESSAGE_FRAGMENT_VALUE, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_IDENTIFIER, PROPERTY_VALUE, SYMBOL, TEMPLATE_ITEM, VALUE_TRUE, WHITESPACE };
|
package/dist/fragment.d.mts
CHANGED
|
@@ -1,59 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Fragment } from "./models.mjs";
|
|
3
2
|
//#region src/fragment.d.ts
|
|
4
|
-
declare
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* Configure the _Fragment_
|
|
34
|
-
*
|
|
35
|
-
* _Returns the Fragment instance for chaining_
|
|
36
|
-
* @param configuration Configuration options
|
|
37
|
-
* @returns _Fragment_
|
|
38
|
-
*/
|
|
39
|
-
configure(configuration: FragmentConfiguration): Fragment;
|
|
40
|
-
/**
|
|
41
|
-
* Get a list of the _Fragment_'s nodes
|
|
42
|
-
* @returns List of nodes
|
|
43
|
-
*/
|
|
44
|
-
get(): ChildNode[];
|
|
45
|
-
/**
|
|
46
|
-
* Prepend the _Fragment_ to the given element
|
|
47
|
-
* @param element Element to prepend to
|
|
48
|
-
*/
|
|
49
|
-
prependTo(element: Element): void;
|
|
50
|
-
/**
|
|
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_
|
|
55
|
-
*/
|
|
56
|
-
remove(): void;
|
|
57
|
-
}
|
|
3
|
+
declare function Fragment(this: any, strings: TemplateStringsArray, expressions: unknown[]): void;
|
|
4
|
+
/**
|
|
5
|
+
* Create a _Fragment_ from a template
|
|
6
|
+
*
|
|
7
|
+
* _A Fragment can be used to efficiently render a template that may change over time, only updating the necessary parts of the DOM._
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const name = signal('World');
|
|
12
|
+
* const fragment = fragment`<p>Hello, ${name}!</p>`; // or `html`<p>Hello, ${name}!</p>`
|
|
13
|
+
* fragment.appendTo(document.body); // Renders '<p>Hello, World!</p>'
|
|
14
|
+
* name.set('Alice'); // Replaces 'World' with 'Alice'
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @returns _Fragment_
|
|
18
|
+
*/
|
|
19
|
+
export declare function fragment(template: TemplateStringsArray, ...values: unknown[]): Fragment;
|
|
20
|
+
/**
|
|
21
|
+
* Create a _Fragment_ from a simple template
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const fragment = fragment('<p>Hello, World!</p>'); // or `html`('<p>Hello, World!</p>')
|
|
26
|
+
* fragment.appendTo(document.body); // Renders '<p>Hello, World!</p>'
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @returns _Fragment_
|
|
30
|
+
*/
|
|
31
|
+
export declare function fragment(template: string): Fragment;
|
|
58
32
|
//#endregion
|
|
59
|
-
export {
|
|
33
|
+
export { fragment as html };
|
package/dist/fragment.mjs
CHANGED
|
@@ -1,130 +1,105 @@
|
|
|
1
|
-
import { NAME_FRAGMENT } from "./constants.mjs";
|
|
1
|
+
import { MESSAGE_FRAGMENT_VALUE, NAME_FRAGMENT, SYMBOL } from "./constants.mjs";
|
|
2
2
|
import { isFragments } from "./helpers/index.mjs";
|
|
3
3
|
import { handleFragments } from "./fragments.mjs";
|
|
4
4
|
import { removeNodes } from "./helpers/dom.mjs";
|
|
5
5
|
import { mapNodes } from "./node/index.mjs";
|
|
6
6
|
import { parse } from "./parse.mjs";
|
|
7
|
-
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
7
|
+
import { isNonTemplateStringsArray, isPlainObject } from "@oscarpalmer/atoms/is";
|
|
8
8
|
import { html } from "@oscarpalmer/toretto/html";
|
|
9
9
|
//#region src/fragment.ts
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
function Fragment(strings, expressions) {
|
|
11
|
+
this[SYMBOL] = {
|
|
12
|
+
expressions,
|
|
13
|
+
strings,
|
|
14
|
+
cache: true,
|
|
13
15
|
identifier: void 0,
|
|
14
|
-
|
|
16
|
+
items: [],
|
|
17
|
+
mora: {
|
|
18
|
+
subscriptions: /* @__PURE__ */ new Set(),
|
|
19
|
+
values: /* @__PURE__ */ new Set()
|
|
20
|
+
},
|
|
21
|
+
name: NAME_FRAGMENT,
|
|
22
|
+
values: []
|
|
15
23
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.#data = {
|
|
33
|
-
expressions,
|
|
34
|
-
strings,
|
|
35
|
-
items: [],
|
|
36
|
-
mora: {
|
|
37
|
-
subscribers: /* @__PURE__ */ new Set(),
|
|
38
|
-
values: /* @__PURE__ */ new Set()
|
|
39
|
-
},
|
|
40
|
-
values: []
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
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
|
|
52
|
-
* @param element Element to append to
|
|
53
|
-
*/
|
|
54
|
-
appendTo(element) {
|
|
55
|
-
element.append(...this.get());
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
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_
|
|
68
|
-
* @param configuration Configuration options
|
|
69
|
-
* @returns _Fragment_
|
|
70
|
-
*/
|
|
71
|
-
configure(configuration) {
|
|
72
|
-
const actual = isPlainObject(configuration) ? configuration : {};
|
|
73
|
-
if ("identifier" in actual) this.#configuration.identifier = actual.identifier;
|
|
74
|
-
if (typeof actual.cache === "boolean") this.#configuration.cache = actual.cache;
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Get a list of the _Fragment_'s nodes
|
|
79
|
-
* @returns List of nodes
|
|
80
|
-
*/
|
|
81
|
-
get() {
|
|
82
|
-
const data = this.#data;
|
|
83
|
-
if (data.items.length === 0) {
|
|
84
|
-
const templated = html(parse(data), { cache: this.#configuration.cache });
|
|
85
|
-
data.items.splice(0, data.items.length, ...templated.map((node) => ({ nodes: [node] })));
|
|
86
|
-
mapNodes(data, data.items.flatMap((item) => item.nodes));
|
|
87
|
-
}
|
|
88
|
-
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Prepend the _Fragment_ to the given element
|
|
92
|
-
* @param element Element to prepend to
|
|
93
|
-
*/
|
|
94
|
-
prependTo(element) {
|
|
95
|
-
element.prepend(...this.get());
|
|
24
|
+
}
|
|
25
|
+
Fragment.prototype.after = insertFragmentAfter;
|
|
26
|
+
Fragment.prototype.appendTo = appendFragmentTo;
|
|
27
|
+
Fragment.prototype.before = insertFragmentBefore;
|
|
28
|
+
Fragment.prototype.configure = configureFragment;
|
|
29
|
+
Fragment.prototype.get = getFragmentNodes;
|
|
30
|
+
Fragment.prototype.prependTo = prependFragmentTo;
|
|
31
|
+
Fragment.prototype.remove = removeFragment;
|
|
32
|
+
Object.defineProperties(Fragment.prototype, {
|
|
33
|
+
cache: {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
get: getFragmentCache
|
|
36
|
+
},
|
|
37
|
+
identifier: {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
get: getFragmentIdentifier
|
|
96
40
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
41
|
+
});
|
|
42
|
+
function appendFragmentTo(element) {
|
|
43
|
+
element.append(...this.get());
|
|
44
|
+
}
|
|
45
|
+
function configureFragment(configuration) {
|
|
46
|
+
const state = this[SYMBOL];
|
|
47
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
48
|
+
if ("identifier" in actual) state.identifier = actual.identifier;
|
|
49
|
+
if (typeof actual.cache === "boolean") state.cache = actual.cache;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
function fragment(template, ...values) {
|
|
53
|
+
if (typeof template !== "string" && isNonTemplateStringsArray(template)) throw new TypeError(MESSAGE_FRAGMENT_VALUE);
|
|
54
|
+
return new Fragment(template, values);
|
|
55
|
+
}
|
|
56
|
+
function getFragmentCache() {
|
|
57
|
+
return this[SYMBOL].cache;
|
|
58
|
+
}
|
|
59
|
+
function getFragmentIdentifier() {
|
|
60
|
+
return this[SYMBOL].identifier;
|
|
61
|
+
}
|
|
62
|
+
function getFragmentNodes() {
|
|
63
|
+
const state = this[SYMBOL];
|
|
64
|
+
if (state.items.length === 0) {
|
|
65
|
+
const parsed = parse(state);
|
|
66
|
+
const templated = html(parsed, { cache: state.cache });
|
|
67
|
+
state.items.splice(0, state.items.length, ...templated.map((node) => ({ nodes: [node] })));
|
|
68
|
+
mapNodes(state, state.items.flatMap((item) => item.nodes));
|
|
105
69
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
70
|
+
return state.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
|
|
71
|
+
}
|
|
72
|
+
function insertFragmentAfter(element) {
|
|
73
|
+
element.after(...this.get());
|
|
74
|
+
}
|
|
75
|
+
function insertFragmentBefore(element) {
|
|
76
|
+
element.before(...this.get());
|
|
77
|
+
}
|
|
78
|
+
function prependFragmentTo(element) {
|
|
79
|
+
element.prepend(...this.get());
|
|
80
|
+
}
|
|
81
|
+
function removeFragment() {
|
|
82
|
+
const state = this[SYMBOL];
|
|
83
|
+
removeMora(state);
|
|
84
|
+
let { length } = state.items;
|
|
110
85
|
for (let index = 0; index < length; index += 1) {
|
|
111
|
-
const { fragments, nodes } =
|
|
86
|
+
const { fragments, nodes } = state.items[index];
|
|
112
87
|
const fragmentsLength = fragments?.length ?? 0;
|
|
113
88
|
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
|
|
114
89
|
removeNodes(nodes);
|
|
115
90
|
}
|
|
116
|
-
|
|
117
|
-
length =
|
|
91
|
+
state.items.length = 0;
|
|
92
|
+
length = state.values.length;
|
|
118
93
|
for (let index = 0; index < length; index += 1) {
|
|
119
|
-
const value =
|
|
94
|
+
const value = state.values[index];
|
|
120
95
|
if (isFragments(value)) handleFragments(value, true);
|
|
121
96
|
}
|
|
122
97
|
}
|
|
123
|
-
function removeMora(
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
for (const
|
|
98
|
+
function removeMora(state) {
|
|
99
|
+
const subscriptions = [...state.mora.subscriptions];
|
|
100
|
+
state.mora.subscriptions.clear();
|
|
101
|
+
state.mora.values.clear();
|
|
102
|
+
for (const subscription of subscriptions) subscription.unsubscribe();
|
|
128
103
|
}
|
|
129
104
|
//#endregion
|
|
130
|
-
export {
|
|
105
|
+
export { fragment, fragment as html };
|
package/dist/fragments.d.mts
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
|
-
import { Fragment } from "./
|
|
2
|
-
import { FragmentsState } from "./models.mjs";
|
|
1
|
+
import { Fragment, Fragments } from "./models.mjs";
|
|
3
2
|
import { ReactiveArray } from "@oscarpalmer/mora";
|
|
4
|
-
|
|
5
3
|
//#region src/fragments.d.ts
|
|
6
|
-
declare
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
declare function Fragments(this: any, items: ReactiveArray<unknown>, identify: (item: unknown) => unknown, fragment: (item: unknown) => Fragment): void;
|
|
5
|
+
/**
|
|
6
|
+
* Create a _Fragments_ instance from a reactive array
|
|
7
|
+
*
|
|
8
|
+
* _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._
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const fruits = array(['Apple', 'Banana', 'Cherry']);
|
|
13
|
+
* const items = fragments(
|
|
14
|
+
* fruits,
|
|
15
|
+
* fruit => fruit, // Identifies a unique item
|
|
16
|
+
* fruit => html`<p>${fruit}</p>`, // Creates a Fragment from an item
|
|
17
|
+
* );
|
|
18
|
+
* html`${items}`.appendTo(document.body) // Renders '<p>Apple</p><p>Banana</p><p>Cherry</p>'
|
|
19
|
+
* fruits.push(['Date', 'Elderberry', 'Fig']); // Appends '<p>Date</p><p>Elderberry</p><p>Fig</p>'
|
|
20
|
+
* // without re-rendering the existing Fragments
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param array Reactive array
|
|
24
|
+
* @param identify Function to identify item uniquely _(non-nullable)_
|
|
25
|
+
* @param fragment Function to create _Fragment_ from item
|
|
26
|
+
* @returns _Fragments_
|
|
27
|
+
*/
|
|
28
|
+
export declare function fragments<Item>(array: ReactiveArray<Item>, identify: (item: Item) => unknown, fragment: (item: Item) => Fragment): Fragments;
|
|
29
|
+
export declare function handleFragments(instance: Fragments, remove: boolean): void;
|
|
30
|
+
//#endregion
|