@oscarpalmer/abydon 0.20.0 → 0.22.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/README.md +2 -0
- package/dist/abydon.full.mjs +787 -276
- package/dist/attribute/index.d.mts +6 -0
- package/dist/{node/attribute → attribute}/index.mjs +10 -19
- package/dist/{node/attribute → attribute}/value.d.mts +2 -2
- package/dist/attribute/value.mjs +63 -0
- package/dist/constants.d.mts +7 -3
- package/dist/constants.mjs +12 -8
- package/dist/fragment.d.mts +45 -1
- package/dist/fragment.mjs +9 -3
- package/dist/fragments.d.mts +4 -6
- package/dist/fragments.mjs +5 -11
- package/dist/helpers/index.d.mts +11 -1
- package/dist/helpers/index.mjs +10 -0
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +8 -4
- package/dist/models.d.mts +43 -1
- package/dist/node/event.mjs +9 -4
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +19 -10
- package/dist/node/value.d.mts +1 -1
- package/dist/node/value.mjs +9 -12
- package/dist/parse.d.mts +1 -1
- package/dist/parse.mjs +6 -4
- package/package.json +8 -7
- package/src/{node/attribute → attribute}/index.ts +16 -33
- package/src/attribute/value.ts +140 -0
- package/src/constants.ts +16 -8
- package/src/fragment.ts +10 -5
- package/src/fragments.ts +4 -13
- package/src/helpers/index.ts +10 -0
- package/src/index.ts +16 -3
- package/src/node/event.ts +12 -5
- package/src/node/index.ts +31 -13
- package/src/node/value.ts +10 -25
- package/src/parse.ts +14 -4
- package/dist/fragment-9qTBAvtR.d.mts +0 -82
- package/dist/node/attribute/index.d.mts +0 -6
- package/dist/node/attribute/value.mjs +0 -65
- package/src/node/attribute/value.ts +0 -158
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX
|
|
2
|
-
import { isInputElement } from "
|
|
3
|
-
import { mapEvent } from "../event.mjs";
|
|
1
|
+
import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX } from "../constants.mjs";
|
|
2
|
+
import { isInputElement } from "../helpers/dom.mjs";
|
|
3
|
+
import { mapEvent } from "../node/event.mjs";
|
|
4
4
|
import { setAttribute } from "./value.mjs";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
//#region src/node/attribute/index.ts
|
|
5
|
+
import { computed, isSignal } from "@oscarpalmer/mora";
|
|
6
|
+
//#region src/attribute/index.ts
|
|
8
7
|
function getValue(data, original) {
|
|
9
|
-
const matches = EXPRESSION_ABYDON_CONTENT.exec(original
|
|
8
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(original);
|
|
10
9
|
return matches == null ? original : data.values[+matches[1]];
|
|
11
10
|
}
|
|
12
11
|
function mapAttributes(data, element) {
|
|
13
|
-
const attributes = [...element.attributes];
|
|
12
|
+
const attributes = [...element.attributes].sort((first, second) => first.name.localeCompare(second.name));
|
|
14
13
|
const { length } = attributes;
|
|
15
14
|
for (let index = 0; index < length; index += 1) {
|
|
16
15
|
const { name, value } = attributes[index];
|
|
@@ -21,25 +20,17 @@ function mapAttributes(data, element) {
|
|
|
21
20
|
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
22
21
|
mapEvent(element, actualName, actualValue);
|
|
23
22
|
break;
|
|
24
|
-
|
|
25
|
-
case typeof actualValue === "function":
|
|
26
|
-
case isReactive(actualValue):
|
|
23
|
+
default:
|
|
27
24
|
mapValue(data, element, actualName, actualValue);
|
|
28
25
|
break;
|
|
29
|
-
default: break;
|
|
30
26
|
}
|
|
31
27
|
}
|
|
32
28
|
}
|
|
33
29
|
function mapValue(data, element, name, value) {
|
|
34
30
|
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
35
31
|
else setAttribute(data, element, name, value);
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
if (name === "checked" && element.type === "checkbox") property = PROPERTY_CHECKED;
|
|
39
|
-
else if (name === "value") property = PROPERTY_VALUE;
|
|
40
|
-
if (property != null) mapEvent(element, "@on", () => {
|
|
41
|
-
const next = element[property];
|
|
42
|
-
value.set(parse(String(next)) ?? next);
|
|
32
|
+
if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
|
|
33
|
+
value.set(element[name]);
|
|
43
34
|
});
|
|
44
35
|
}
|
|
45
36
|
function setComputedAttribute(data, element, name, callback) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FragmentData } from "../models.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/attribute/value.d.ts
|
|
4
4
|
declare function setAttribute(data: FragmentData, element: HTMLElement | SVGElement, name: string, value: unknown): void;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { setAttribute };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_ATTRIBUTE_STYLE_PROPERTY } from "../constants.mjs";
|
|
2
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
3
|
+
import { getString } from "@oscarpalmer/atoms/string";
|
|
4
|
+
import { isReactive } from "@oscarpalmer/mora";
|
|
5
|
+
import { camelCase } from "@oscarpalmer/atoms/string/case";
|
|
6
|
+
import { setAttribute as setAttribute$1 } from "@oscarpalmer/toretto/attribute";
|
|
7
|
+
import { setStyle } from "@oscarpalmer/toretto/style";
|
|
8
|
+
//#region src/attribute/value.ts
|
|
9
|
+
function getStyleValue(value, unit, isProperty) {
|
|
10
|
+
if (removeStyleValue(value, unit, isProperty)) return;
|
|
11
|
+
return value === true || value === "true" ? unit : `${getString(value)}${unit ?? ""}`;
|
|
12
|
+
}
|
|
13
|
+
function removeStyleValue(value, unit, isProperty) {
|
|
14
|
+
if (value == null || value === false || isProperty && isNullableOrWhitespace(value)) return true;
|
|
15
|
+
return unit == null && (value === true || value === "true");
|
|
16
|
+
}
|
|
17
|
+
function setAttribute(data, element, name, value) {
|
|
18
|
+
switch (true) {
|
|
19
|
+
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
20
|
+
setClassValues(data, element, name, value);
|
|
21
|
+
return;
|
|
22
|
+
case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
|
|
23
|
+
setStyleValues(data, element, name, value);
|
|
24
|
+
return;
|
|
25
|
+
default:
|
|
26
|
+
setValue(data, element, name, value);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function setClassValues(data, element, name, value) {
|
|
31
|
+
function update(value) {
|
|
32
|
+
if (value === true || value === "true") element.classList.add(...classes);
|
|
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);
|
|
38
|
+
}
|
|
39
|
+
function setStyleValues(data, element, name, value) {
|
|
40
|
+
let [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name);
|
|
41
|
+
const isProperty = EXPRESSION_ATTRIBUTE_STYLE_PROPERTY.test(name);
|
|
42
|
+
property = camelCase(property);
|
|
43
|
+
if (isProperty) property = `--${property}`;
|
|
44
|
+
function update(value) {
|
|
45
|
+
setStyle(element, property, getStyleValue(value, unit, isProperty));
|
|
46
|
+
}
|
|
47
|
+
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
48
|
+
else update(value);
|
|
49
|
+
}
|
|
50
|
+
function setValue(data, element, name, value) {
|
|
51
|
+
const isReactiveValue = isReactive(value);
|
|
52
|
+
unsetValue(element, name, isReactiveValue ? value.peek() : value);
|
|
53
|
+
if (isReactiveValue) data.mora.subscribers.add(value.subscribe((next) => {
|
|
54
|
+
setAttribute$1(element, name, next);
|
|
55
|
+
}));
|
|
56
|
+
else setAttribute$1(element, name, value);
|
|
57
|
+
}
|
|
58
|
+
function unsetValue(element, name, value) {
|
|
59
|
+
if (name === "checked") element.checked = !(value === true || value === "true");
|
|
60
|
+
if (name === "value") element.value = element.value === "" ? "_" : "";
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { setAttribute };
|
package/dist/constants.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ declare const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
|
|
|
4
4
|
declare const ARRAY_COMPARISON_REMOVED = "removed";
|
|
5
5
|
declare const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
6
6
|
declare const ATTRIBUTE_NAME_DELIMITER = ".";
|
|
7
|
+
declare const CHANGE_INPUTS: Set<string>;
|
|
7
8
|
declare const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
8
9
|
declare const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
9
10
|
declare const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
@@ -11,7 +12,6 @@ declare const EVENT_CHANGE = "change";
|
|
|
11
12
|
declare const EVENT_INPUT = "input";
|
|
12
13
|
declare const EVENT_SUBMIT = "submit";
|
|
13
14
|
declare const EVENT_DEFAULTS: Record<string, string>;
|
|
14
|
-
declare const EVENT_ON_PREFIXED = "@on";
|
|
15
15
|
declare const EVENT_ON_VALUE = "on";
|
|
16
16
|
declare const EVENT_OPTIONS_DELIMITER = ":";
|
|
17
17
|
declare const EXPRESSION_ABYDON_ATTRIBUTE_FULL: RegExp;
|
|
@@ -20,7 +20,8 @@ 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_PROPERTY: RegExp;
|
|
24
|
+
declare const EXPRESSION_EVENT_ATTRIBUTE: RegExp;
|
|
24
25
|
declare const EXPRESSION_EVENT_NAME: RegExp;
|
|
25
26
|
declare const EXPRESSION_EVENT_OPTIONS_ACTIVE: RegExp;
|
|
26
27
|
declare const EXPRESSION_EVENT_OPTIONS_CAPTURE: RegExp;
|
|
@@ -29,11 +30,14 @@ declare const EXPRESSION_EVENT_PREFIX: RegExp;
|
|
|
29
30
|
declare const EXPRESSION_PERIOD: RegExp;
|
|
30
31
|
declare const EXPRESSION_TEXTAREA_VALUE: RegExp;
|
|
31
32
|
declare const INPUT_TYPE_CHECKBOX = "checkbox";
|
|
33
|
+
declare const INPUT_TYPE_RADIO = "radio";
|
|
32
34
|
declare const NAME_FRAGMENT = "$fragment";
|
|
33
35
|
declare const NAME_FRAGMENTS = "$fragments";
|
|
34
36
|
declare const PROPERTY_CHECKED = "checked";
|
|
35
37
|
declare const PROPERTY_IDENTIFIER = "identifier";
|
|
36
38
|
declare const PROPERTY_VALUE = "value";
|
|
37
39
|
declare const TEMPLATE_ITEM = "<>";
|
|
40
|
+
declare const VALUE_TRUE = "true";
|
|
41
|
+
declare const WHITESPACE: RegExp;
|
|
38
42
|
//#endregion
|
|
39
|
-
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT,
|
|
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, EXPRESSION_ATTRIBUTE_STYLE_PROPERTY, EXPRESSION_EVENT_ATTRIBUTE, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, EXPRESSION_TEXTAREA_VALUE, INPUT_TYPE_CHECKBOX, INPUT_TYPE_RADIO, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM, VALUE_TRUE, WHITESPACE };
|
package/dist/constants.mjs
CHANGED
|
@@ -4,6 +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"]);
|
|
7
8
|
const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
|
|
8
9
|
const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
9
10
|
const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
|
|
@@ -18,29 +19,32 @@ const EVENT_DEFAULTS = {
|
|
|
18
19
|
SELECT: EVENT_CHANGE,
|
|
19
20
|
TEXTAREA: EVENT_INPUT
|
|
20
21
|
};
|
|
21
|
-
const EVENT_ON_PREFIXED = "@on";
|
|
22
22
|
const EVENT_ON_VALUE = "on";
|
|
23
23
|
const EVENT_OPTIONS_DELIMITER = ":";
|
|
24
|
-
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
|
|
25
|
-
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^
|
|
26
|
-
const EXPRESSION_ABYDON_CONTENT =
|
|
24
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-.]+(?::[a-z:]+)?)="<!--abydon.(\d+)-->"/g;
|
|
25
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^abydon-/;
|
|
26
|
+
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
|
|
31
|
-
const
|
|
30
|
+
const EXPRESSION_ATTRIBUTE_STYLE_PROPERTY = /^style\.--/;
|
|
31
|
+
const EXPRESSION_EVENT_ATTRIBUTE = /^@([\w-]+)(?::([a-z:]+))?="$/i;
|
|
32
|
+
const EXPRESSION_EVENT_NAME = /^@?([\w-]+)(?::([a-z:]+))?$/i;
|
|
32
33
|
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
33
34
|
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
34
35
|
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
35
36
|
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
36
37
|
const EXPRESSION_PERIOD = /\./;
|
|
37
|
-
const EXPRESSION_TEXTAREA_VALUE =
|
|
38
|
+
const EXPRESSION_TEXTAREA_VALUE = /(?:<|<)!--abydon\.(\d+)--(?:>|>)/;
|
|
38
39
|
const INPUT_TYPE_CHECKBOX = "checkbox";
|
|
40
|
+
const INPUT_TYPE_RADIO = "radio";
|
|
39
41
|
const NAME_FRAGMENT = "$fragment";
|
|
40
42
|
const NAME_FRAGMENTS = "$fragments";
|
|
41
43
|
const PROPERTY_CHECKED = "checked";
|
|
42
44
|
const PROPERTY_IDENTIFIER = "identifier";
|
|
43
45
|
const PROPERTY_VALUE = "value";
|
|
44
46
|
const TEMPLATE_ITEM = "<>";
|
|
47
|
+
const VALUE_TRUE = "true";
|
|
48
|
+
const WHITESPACE = /\s+/g;
|
|
45
49
|
//#endregion
|
|
46
|
-
export { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED, ATTRIBUTE_CLASS_PREFIX_LENGTH, ATTRIBUTE_NAME_DELIMITER, ERROR_FRAGMENT, ERROR_IDENTIFIER_DUPLICATE, ERROR_IDENTIFIER_TYPE, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT,
|
|
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, EXPRESSION_ATTRIBUTE_STYLE_PROPERTY, EXPRESSION_EVENT_ATTRIBUTE, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, EXPRESSION_TEXTAREA_VALUE, INPUT_TYPE_CHECKBOX, INPUT_TYPE_RADIO, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM, VALUE_TRUE, WHITESPACE };
|
package/dist/fragment.d.mts
CHANGED
|
@@ -1,2 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FragmentConfiguration } from "./models.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/fragment.d.ts
|
|
4
|
+
declare class Fragment {
|
|
5
|
+
#private;
|
|
6
|
+
/**
|
|
7
|
+
* Is template caching enabled?
|
|
8
|
+
*/
|
|
9
|
+
get caching(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Fragment identifier
|
|
12
|
+
*/
|
|
13
|
+
get identifier(): unknown;
|
|
14
|
+
constructor(strings: TemplateStringsArray, expressions: unknown[]);
|
|
15
|
+
/**
|
|
16
|
+
* Append the fragment to the given element
|
|
17
|
+
* @param element Element to append to
|
|
18
|
+
*/
|
|
19
|
+
appendTo(element: Element): void;
|
|
20
|
+
/**
|
|
21
|
+
* Configure the fragment
|
|
22
|
+
* @param configuration Configuration options
|
|
23
|
+
* @returns Fragment
|
|
24
|
+
*/
|
|
25
|
+
configure(configuration: FragmentConfiguration): Fragment;
|
|
26
|
+
/**
|
|
27
|
+
* Get a list of the fragment's nodes
|
|
28
|
+
* @returns List of nodes
|
|
29
|
+
*/
|
|
30
|
+
get(): ChildNode[];
|
|
31
|
+
/**
|
|
32
|
+
* Set an identifier for the fragment
|
|
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
|
|
38
|
+
*/
|
|
39
|
+
identify(identifier: unknown): Fragment;
|
|
40
|
+
/**
|
|
41
|
+
* Remove the fragment from the DOM
|
|
42
|
+
*/
|
|
43
|
+
remove(): void;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
2
46
|
export { Fragment };
|
package/dist/fragment.mjs
CHANGED
|
@@ -14,6 +14,12 @@ var Fragment = class {
|
|
|
14
14
|
cache: true
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
|
+
* Is template caching enabled?
|
|
18
|
+
*/
|
|
19
|
+
get caching() {
|
|
20
|
+
return this.#configuration.cache;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
17
23
|
* Fragment identifier
|
|
18
24
|
*/
|
|
19
25
|
get identifier() {
|
|
@@ -59,9 +65,9 @@ var Fragment = class {
|
|
|
59
65
|
if (data.items.length === 0) {
|
|
60
66
|
const templated = html(parse(data), { cache: this.#configuration.cache });
|
|
61
67
|
data.items.splice(0, data.items.length, ...templated.map((node) => ({ nodes: [node] })));
|
|
62
|
-
mapNodes(data, data.items.flatMap((item) => item.
|
|
68
|
+
mapNodes(data, data.items.flatMap((item) => item.nodes));
|
|
63
69
|
}
|
|
64
|
-
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes
|
|
70
|
+
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
|
|
65
71
|
}
|
|
66
72
|
/**
|
|
67
73
|
* Set an identifier for the fragment
|
|
@@ -89,7 +95,7 @@ function removeFragment(data) {
|
|
|
89
95
|
const { fragments, nodes } = data.items[index];
|
|
90
96
|
const fragmentsLength = fragments?.length ?? 0;
|
|
91
97
|
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
|
|
92
|
-
removeNodes(nodes
|
|
98
|
+
removeNodes(nodes);
|
|
93
99
|
}
|
|
94
100
|
data.items.length = 0;
|
|
95
101
|
length = data.values.length;
|
package/dist/fragments.d.mts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from "./fragment.mjs";
|
|
2
|
+
import { FragmentsState } from "./models.mjs";
|
|
2
3
|
import { ReactiveArray } from "@oscarpalmer/mora";
|
|
3
4
|
|
|
4
5
|
//#region src/fragments.d.ts
|
|
5
6
|
declare class Fragments {
|
|
6
7
|
#private;
|
|
7
|
-
/**
|
|
8
|
-
* Fragment items
|
|
9
|
-
*/
|
|
10
|
-
get items(): ReactiveArray<Fragment>;
|
|
11
8
|
constructor(items: ReactiveArray<unknown>, identify: (item: unknown) => unknown, fragment: (item: unknown) => Fragment);
|
|
12
9
|
}
|
|
13
10
|
declare function handleFragments(item: Fragments | FragmentsState, remove: boolean): void;
|
|
14
11
|
declare function initializeFragments(state: FragmentsState): void;
|
|
12
|
+
declare const fragmentsStates: WeakMap<Fragments, FragmentsState>;
|
|
15
13
|
//#endregion
|
|
16
|
-
export { Fragments, handleFragments, initializeFragments };
|
|
14
|
+
export { Fragments, fragmentsStates, handleFragments, initializeFragments };
|
package/dist/fragments.mjs
CHANGED
|
@@ -5,12 +5,6 @@ import { array } from "@oscarpalmer/mora";
|
|
|
5
5
|
//#region src/fragments.ts
|
|
6
6
|
var Fragments = class {
|
|
7
7
|
#state;
|
|
8
|
-
/**
|
|
9
|
-
* Fragment items
|
|
10
|
-
*/
|
|
11
|
-
get items() {
|
|
12
|
-
return this.#state.mapped;
|
|
13
|
-
}
|
|
14
8
|
constructor(items, identify, fragment) {
|
|
15
9
|
Object.defineProperty(this, NAME_FRAGMENTS, { value: true });
|
|
16
10
|
this.#state = {
|
|
@@ -21,13 +15,13 @@ var Fragments = class {
|
|
|
21
15
|
mapped: array([]),
|
|
22
16
|
subscriber: void 0
|
|
23
17
|
};
|
|
24
|
-
|
|
18
|
+
fragmentsStates.set(this, this.#state);
|
|
25
19
|
initializeFragments(this.#state);
|
|
26
20
|
}
|
|
27
21
|
};
|
|
28
22
|
function handleFragments(item, remove) {
|
|
29
|
-
const state = isFragments(item) ?
|
|
30
|
-
|
|
23
|
+
const state = isFragments(item) ? fragmentsStates.get(item) : item;
|
|
24
|
+
(remove ? removeFragments : initializeFragments)(state);
|
|
31
25
|
}
|
|
32
26
|
function handleItems(state, items) {
|
|
33
27
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -75,6 +69,6 @@ function updateFragments(state, active) {
|
|
|
75
69
|
state.instances = next;
|
|
76
70
|
active?.clear();
|
|
77
71
|
}
|
|
78
|
-
const
|
|
72
|
+
const fragmentsStates = /* @__PURE__ */ new WeakMap();
|
|
79
73
|
//#endregion
|
|
80
|
-
export { Fragments, handleFragments, initializeFragments };
|
|
74
|
+
export { Fragments, fragmentsStates, handleFragments, initializeFragments };
|
package/dist/helpers/index.d.mts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { Fragment } from "../fragment.mjs";
|
|
1
2
|
import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED } from "../constants.mjs";
|
|
2
|
-
import { t as Fragment } from "../fragment-9qTBAvtR.mjs";
|
|
3
3
|
import { Fragments } from "../fragments.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/helpers/index.d.ts
|
|
6
6
|
declare function compareArrays(first: unknown[], second: unknown[]): typeof ARRAY_COMPARISON_ADDED | typeof ARRAY_COMPARISON_DISSIMILAR | typeof ARRAY_COMPARISON_REMOVED;
|
|
7
|
+
/**
|
|
8
|
+
* Is the value a Fragment?
|
|
9
|
+
* @param value Value to check
|
|
10
|
+
* @returns `true` if the value is a Fragment, otherwise `false`
|
|
11
|
+
*/
|
|
7
12
|
declare function isFragment(value: unknown): value is Fragment;
|
|
13
|
+
/**
|
|
14
|
+
* Is the value a Fragments?
|
|
15
|
+
* @param value Value to check
|
|
16
|
+
* @returns `true` if the value is a Fragments, otherwise `false`
|
|
17
|
+
*/
|
|
8
18
|
declare function isFragments(value: unknown): value is Fragments;
|
|
9
19
|
//#endregion
|
|
10
20
|
export { compareArrays, isFragment, isFragments };
|
package/dist/helpers/index.mjs
CHANGED
|
@@ -7,9 +7,19 @@ function compareArrays(first, second) {
|
|
|
7
7
|
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return ARRAY_COMPARISON_DISSIMILAR;
|
|
8
8
|
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Is the value a Fragment?
|
|
12
|
+
* @param value Value to check
|
|
13
|
+
* @returns `true` if the value is a Fragment, otherwise `false`
|
|
14
|
+
*/
|
|
10
15
|
function isFragment(value) {
|
|
11
16
|
return isNamed(value, NAME_FRAGMENT);
|
|
12
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Is the value a Fragments?
|
|
20
|
+
* @param value Value to check
|
|
21
|
+
* @returns `true` if the value is a Fragments, otherwise `false`
|
|
22
|
+
*/
|
|
13
23
|
function isFragments(value) {
|
|
14
24
|
return isNamed(value, NAME_FRAGMENTS);
|
|
15
25
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from "./fragment.mjs";
|
|
2
2
|
import { Fragments } from "./fragments.mjs";
|
|
3
|
+
import { isFragment, isFragments } from "./helpers/index.mjs";
|
|
3
4
|
import { ReactiveArray } from "@oscarpalmer/mora";
|
|
4
5
|
export * from "@oscarpalmer/mora";
|
|
5
6
|
|
|
6
7
|
//#region src/index.d.ts
|
|
7
8
|
/**
|
|
8
|
-
* Create Fragments from a reactive array
|
|
9
|
+
* Create a Fragments from a reactive array
|
|
9
10
|
* @param array Reactive array
|
|
10
11
|
* @param identify Function to identify item
|
|
11
12
|
* @param fragment Function to create fragment from item
|
|
@@ -13,9 +14,9 @@ export * from "@oscarpalmer/mora";
|
|
|
13
14
|
*/
|
|
14
15
|
declare function fragments<Item>(array: ReactiveArray<Item>, identify: (item: Item) => unknown, fragment: (item: Item) => Fragment): Fragments;
|
|
15
16
|
/**
|
|
16
|
-
* Create Fragment from a template
|
|
17
|
+
* Create a Fragment from a template
|
|
17
18
|
* @returns Fragment
|
|
18
19
|
*/
|
|
19
20
|
declare function html(template: TemplateStringsArray, ...values: unknown[]): Fragment;
|
|
20
21
|
//#endregion
|
|
21
|
-
export { type Fragment, type Fragments, fragments, html };
|
|
22
|
+
export { type Fragment, type Fragments, fragments, html, isFragment, isFragments };
|
package/dist/index.mjs
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
+
import { isFragment, isFragments } from "./helpers/index.mjs";
|
|
1
2
|
import { Fragments } from "./fragments.mjs";
|
|
2
3
|
import { Fragment } from "./fragment.mjs";
|
|
3
|
-
import "@oscarpalmer/mora";
|
|
4
|
+
import { isArray } from "@oscarpalmer/mora";
|
|
4
5
|
export * from "@oscarpalmer/mora";
|
|
5
6
|
//#region src/index.ts
|
|
6
7
|
/**
|
|
7
|
-
* Create Fragments from a reactive array
|
|
8
|
+
* Create a Fragments from a reactive array
|
|
8
9
|
* @param array Reactive array
|
|
9
10
|
* @param identify Function to identify item
|
|
10
11
|
* @param fragment Function to create fragment from item
|
|
11
12
|
* @returns Fragments
|
|
12
13
|
*/
|
|
13
14
|
function fragments(array, identify, fragment) {
|
|
15
|
+
if (!isArray(array)) throw new TypeError("Fragments array must be a reactive array");
|
|
16
|
+
if (typeof identify !== "function") throw new TypeError("Fragments identify must be a function");
|
|
17
|
+
if (typeof fragment !== "function") throw new TypeError("Fragments fragment must be a function");
|
|
14
18
|
return new Fragments(array, identify, fragment);
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
|
-
* Create Fragment from a template
|
|
21
|
+
* Create a Fragment from a template
|
|
18
22
|
* @returns Fragment
|
|
19
23
|
*/
|
|
20
24
|
function html(template, ...values) {
|
|
21
25
|
return new Fragment(template, values);
|
|
22
26
|
}
|
|
23
27
|
//#endregion
|
|
24
|
-
export { fragments, html };
|
|
28
|
+
export { fragments, html, isFragment, isFragments };
|
package/dist/models.d.mts
CHANGED
|
@@ -1,2 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from "./fragment.mjs";
|
|
2
|
+
import { Reactive, ReactiveArray, Unsubscribe } from "@oscarpalmer/mora";
|
|
3
|
+
|
|
4
|
+
//#region src/models.d.ts
|
|
5
|
+
type FragmentConfiguration = {
|
|
6
|
+
/**
|
|
7
|
+
* Should the template be cached? _(defaults to `true`)_
|
|
8
|
+
*/
|
|
9
|
+
cache?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Identifier for the fragment
|
|
12
|
+
*
|
|
13
|
+
* _(An identifier can be used to uniquely identify a fragment,
|
|
14
|
+
* which helps prevent re-rendering in certain scenarios)_
|
|
15
|
+
*/
|
|
16
|
+
identifier?: unknown;
|
|
17
|
+
};
|
|
18
|
+
type FragmentData = {
|
|
19
|
+
expressions: unknown[];
|
|
20
|
+
items: FragmentItem[];
|
|
21
|
+
mora: MoraData;
|
|
22
|
+
strings: TemplateStringsArray;
|
|
23
|
+
template?: string;
|
|
24
|
+
values: unknown[];
|
|
25
|
+
};
|
|
26
|
+
type FragmentItem = {
|
|
27
|
+
fragments?: Fragment[];
|
|
28
|
+
nodes?: ChildNode[];
|
|
29
|
+
text?: Text;
|
|
30
|
+
};
|
|
31
|
+
type FragmentsState = {
|
|
32
|
+
array: ReactiveArray<unknown>;
|
|
33
|
+
fragment: (item: unknown) => Fragment;
|
|
34
|
+
identify: (item: unknown) => unknown;
|
|
35
|
+
instances: Record<string, Fragment>;
|
|
36
|
+
mapped: ReactiveArray<Fragment>;
|
|
37
|
+
subscriber: Unsubscribe | undefined;
|
|
38
|
+
};
|
|
39
|
+
type MoraData = {
|
|
40
|
+
subscribers: Set<() => void>;
|
|
41
|
+
values: Set<Reactive<unknown>>;
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
2
44
|
export { FragmentConfiguration, FragmentData, FragmentItem, FragmentsState };
|
package/dist/node/event.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_SUBMIT,
|
|
1
|
+
import { CHANGE_INPUTS, EVENT_CHANGE, EVENT_DEFAULTS, EVENT_INPUT, EVENT_SUBMIT, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE } from "../constants.mjs";
|
|
2
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
3
3
|
//#region src/node/event.ts
|
|
4
4
|
function getOptions(options) {
|
|
@@ -12,14 +12,19 @@ function getOptions(options) {
|
|
|
12
12
|
function getType(element, type) {
|
|
13
13
|
if (type !== "on") return type;
|
|
14
14
|
if (element instanceof HTMLInputElement) {
|
|
15
|
-
if (
|
|
15
|
+
if (CHANGE_INPUTS.has(element.type)) return EVENT_CHANGE;
|
|
16
16
|
return element.type === "submit" ? EVENT_SUBMIT : EVENT_INPUT;
|
|
17
17
|
}
|
|
18
18
|
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
19
19
|
}
|
|
20
20
|
function mapEvent(element, name, value) {
|
|
21
|
-
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name)
|
|
22
|
-
|
|
21
|
+
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name);
|
|
22
|
+
const values = Array.isArray(value) ? value : [value];
|
|
23
|
+
const { length } = values;
|
|
24
|
+
for (let index = 0; index < length; index += 1) {
|
|
25
|
+
const item = values[index];
|
|
26
|
+
if (typeof item === "function") on(element, getType(element, type), item, getOptions(options ?? ""));
|
|
27
|
+
}
|
|
23
28
|
}
|
|
24
29
|
//#endregion
|
|
25
30
|
export { mapEvent };
|
package/dist/node/index.d.mts
CHANGED
package/dist/node/index.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { EXPRESSION_ABYDON_CONTENT, EXPRESSION_TEXTAREA_VALUE } from "../constants.mjs";
|
|
2
2
|
import { isFragment, isFragments } from "../helpers/index.mjs";
|
|
3
|
-
import { handleFragments } from "../fragments.mjs";
|
|
3
|
+
import { fragmentsStates, handleFragments } from "../fragments.mjs";
|
|
4
4
|
import { createNodes } from "../helpers/dom.mjs";
|
|
5
5
|
import { mapEvent } from "./event.mjs";
|
|
6
|
-
import { mapAttributes } from "
|
|
6
|
+
import { mapAttributes } from "../attribute/index.mjs";
|
|
7
7
|
import { setReactiveValue } from "./value.mjs";
|
|
8
|
+
import { getString } from "@oscarpalmer/atoms/string";
|
|
8
9
|
import { computed, isComputed, isReactive, isSignal } from "@oscarpalmer/mora";
|
|
9
10
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
10
11
|
//#region src/node/index.ts
|
|
11
12
|
function mapNode(data, comment) {
|
|
12
|
-
const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent
|
|
13
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent);
|
|
13
14
|
const value = matches == null ? null : data.values[+matches[1]];
|
|
14
15
|
if (value != null) mapValue(data, comment, value);
|
|
15
16
|
}
|
|
@@ -27,23 +28,27 @@ function mapNodes(data, nodes) {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
function mapTextarea(data, element) {
|
|
30
|
-
const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
|
|
31
|
+
const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.textContent) ?? EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
|
|
31
32
|
if (index == null) return;
|
|
33
|
+
element.textContent = "";
|
|
32
34
|
element.value = "";
|
|
33
35
|
const value = data.values[Number.parseInt(index, 10)];
|
|
34
36
|
if (isSignal(value)) {
|
|
35
|
-
element.value =
|
|
36
|
-
mapEvent(element, "
|
|
37
|
+
element.value = getString(value.peek());
|
|
38
|
+
mapEvent(element, "on", () => {
|
|
37
39
|
value.set(element.value);
|
|
38
40
|
});
|
|
41
|
+
data.mora.subscribers.add(value.subscribe((value) => {
|
|
42
|
+
element.value = getString(value);
|
|
43
|
+
}));
|
|
39
44
|
return;
|
|
40
45
|
}
|
|
41
46
|
let reactive;
|
|
42
47
|
if (typeof value === "function") reactive = computed(value);
|
|
43
48
|
else if (isComputed(value)) reactive = value;
|
|
44
|
-
if (reactive == null) element.value =
|
|
49
|
+
if (reactive == null) element.value = "";
|
|
45
50
|
else data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
46
|
-
element.value =
|
|
51
|
+
element.value = getString(value);
|
|
47
52
|
}));
|
|
48
53
|
}
|
|
49
54
|
function mapValue(data, comment, value) {
|
|
@@ -52,8 +57,7 @@ function mapValue(data, comment, value) {
|
|
|
52
57
|
setComputedValue(data, comment, value);
|
|
53
58
|
break;
|
|
54
59
|
case isFragments(value):
|
|
55
|
-
|
|
56
|
-
setReactiveValue(data, comment, value.items);
|
|
60
|
+
setFragmentsValue(data, comment, value);
|
|
57
61
|
break;
|
|
58
62
|
case isReactive(value):
|
|
59
63
|
setReactiveValue(data, comment, value);
|
|
@@ -77,5 +81,10 @@ function setComputedValue(data, comment, callback) {
|
|
|
77
81
|
data.mora.values.add(value);
|
|
78
82
|
setReactiveValue(data, comment, value);
|
|
79
83
|
}
|
|
84
|
+
function setFragmentsValue(data, comment, fragments) {
|
|
85
|
+
const state = fragmentsStates.get(fragments);
|
|
86
|
+
handleFragments(state, false);
|
|
87
|
+
setReactiveValue(data, comment, state.mapped);
|
|
88
|
+
}
|
|
80
89
|
//#endregion
|
|
81
90
|
export { mapNodes };
|
package/dist/node/value.d.mts
CHANGED