@oscarpalmer/abydon 0.16.0 → 0.19.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.js → abydon.full.mjs} +542 -234
- package/dist/constants.d.mts +37 -0
- package/dist/constants.mjs +44 -0
- package/dist/fragment-9qTBAvtR.d.mts +82 -0
- package/dist/fragment.d.mts +2 -0
- package/dist/{fragment.js → fragment.mjs} +35 -6
- package/dist/fragments.d.mts +16 -0
- package/dist/{fragments.js → fragments.mjs} +11 -6
- package/dist/helpers/dom.d.mts +7 -0
- package/dist/helpers/{dom.js → dom.mjs} +7 -2
- package/dist/helpers/index.d.mts +10 -0
- package/dist/helpers/{index.js → index.mjs} +5 -6
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +24 -0
- package/dist/models.d.mts +2 -0
- package/dist/models.mjs +1 -0
- package/dist/node/attribute/index.d.mts +6 -0
- package/dist/node/attribute/{index.js → index.mjs} +11 -4
- package/dist/node/attribute/value.d.mts +6 -0
- package/dist/node/attribute/{value.js → value.mjs} +13 -10
- package/dist/node/event.d.mts +4 -0
- package/dist/node/{event.js → event.mjs} +5 -3
- package/dist/node/index.d.mts +6 -0
- package/dist/node/{index.js → index.mjs} +9 -7
- package/dist/node/value.d.mts +7 -0
- package/dist/node/{value.js → value.mjs} +9 -6
- package/dist/parse.d.mts +6 -0
- package/dist/{parse.js → parse.mjs} +3 -1
- package/package.json +42 -41
- package/src/constants.ts +38 -4
- package/src/fragment.ts +2 -2
- package/src/fragments.ts +10 -4
- package/src/helpers/dom.ts +10 -0
- package/src/helpers/index.ts +13 -10
- package/src/node/attribute/index.ts +11 -1
- package/src/node/attribute/value.ts +18 -10
- package/src/node/event.ts +9 -4
- package/src/node/value.ts +3 -2
- package/dist/constants.js +0 -25
- package/dist/index.js +0 -11
- package/dist/models.js +0 -0
- package/types/constants.d.ts +0 -17
- package/types/fragment.d.ts +0 -38
- package/types/fragments.d.ts +0 -13
- package/types/helpers/dom.d.ts +0 -3
- package/types/helpers/index.d.ts +0 -5
- package/types/index.d.ts +0 -20
- package/types/models.d.ts +0 -41
- package/types/node/attribute/index.d.ts +0 -2
- package/types/node/attribute/value.d.ts +0 -2
- package/types/node/event.d.ts +0 -1
- package/types/node/index.d.ts +0 -2
- package/types/node/value.d.ts +0 -3
- package/types/parse.d.ts +0 -2
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ARRAY_COMPARISON_ADDED } from "../constants.mjs";
|
|
2
|
+
import { compareArrays, isFragment } from "../helpers/index.mjs";
|
|
3
|
+
import { createNodes, replaceNodes } from "../helpers/dom.mjs";
|
|
3
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
4
5
|
import { getString } from "@oscarpalmer/atoms/string";
|
|
5
6
|
import { isChildNode } from "@oscarpalmer/toretto/is";
|
|
7
|
+
//#region src/node/value.ts
|
|
6
8
|
function addToArray(identifiers, items, nodes, added) {
|
|
7
9
|
let position = nodes[0];
|
|
8
10
|
const before = added && !identifiers.previous.has(items.templates[0].identifier);
|
|
@@ -24,7 +26,7 @@ function handleArray(identifiers, items, nodes) {
|
|
|
24
26
|
if (comparison !== "removed") addToArray(identifiers, {
|
|
25
27
|
...items,
|
|
26
28
|
next
|
|
27
|
-
}, nodes, comparison ===
|
|
29
|
+
}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
28
30
|
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
29
31
|
const { length } = toRemove;
|
|
30
32
|
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
|
@@ -47,14 +49,14 @@ function replaceText(item, comment, isNullable) {
|
|
|
47
49
|
}
|
|
48
50
|
function setArray(item, comment, value) {
|
|
49
51
|
if (value.length === 0) return { nodes: setText(item, comment, value) };
|
|
50
|
-
let templates = value.filter((item
|
|
52
|
+
let templates = value.filter((item) => isFragment(item) && item.identifier != null);
|
|
51
53
|
const next = templates.map((fragment) => fragment.identifier);
|
|
52
54
|
const previous = item.fragments?.map((fragment) => fragment.identifier) ?? [];
|
|
53
55
|
if (new Set(next).size !== templates.length) templates = [];
|
|
54
56
|
const noTemplates = templates.length === 0;
|
|
55
57
|
if (noTemplates || item.nodes == null || previous.some((identifier) => identifier == null)) return {
|
|
56
58
|
fragments: noTemplates ? void 0 : templates,
|
|
57
|
-
nodes: setNodes(item, comment, noTemplates ? value.flatMap((item
|
|
59
|
+
nodes: setNodes(item, comment, noTemplates ? value.flatMap((item) => createNodes(item)) : templates.flatMap((template) => template.get()))
|
|
58
60
|
};
|
|
59
61
|
return handleArray({
|
|
60
62
|
next: new Set(next),
|
|
@@ -73,7 +75,7 @@ function setNodes(item, comment, next) {
|
|
|
73
75
|
return next;
|
|
74
76
|
}
|
|
75
77
|
function setReactiveValue(data, comment, reactive) {
|
|
76
|
-
let item = data.items.find((item
|
|
78
|
+
let item = data.items.find((item) => item.nodes?.includes(comment));
|
|
77
79
|
item ??= {};
|
|
78
80
|
item.text = new Text();
|
|
79
81
|
data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
@@ -110,4 +112,5 @@ function setText(item, comment, value) {
|
|
|
110
112
|
removeFragments(item.fragments);
|
|
111
113
|
if (result) return item.text == null ? [] : [item.text];
|
|
112
114
|
}
|
|
115
|
+
//#endregion
|
|
113
116
|
export { setReactiveValue };
|
package/dist/parse.d.mts
ADDED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { EXPRESSION_ABYDON_ATTRIBUTE_FULL } from "./constants.
|
|
1
|
+
import { EXPRESSION_ABYDON_ATTRIBUTE_FULL } from "./constants.mjs";
|
|
2
2
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
3
|
+
//#region src/parse.ts
|
|
3
4
|
function handleExpression(data, prefix, expression) {
|
|
4
5
|
if (Array.isArray(expression)) {
|
|
5
6
|
const { length } = expression;
|
|
@@ -26,4 +27,5 @@ function transformAttribute(_, name, index) {
|
|
|
26
27
|
function transformExpression(prefix, index) {
|
|
27
28
|
return `${prefix}<!--abydon.${index}-->`;
|
|
28
29
|
}
|
|
30
|
+
//#endregion
|
|
29
31
|
export { parse };
|
package/package.json
CHANGED
|
@@ -1,34 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
"url": "https://oscarpalmer.se"
|
|
5
|
-
},
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"@oscarpalmer/atoms": "^0.118",
|
|
8
|
-
"@oscarpalmer/mora": "^0.25",
|
|
9
|
-
"@oscarpalmer/toretto": "^0.32"
|
|
10
|
-
},
|
|
11
|
-
"devDependencies": {
|
|
12
|
-
"@oscarpalmer/oui": "^0.18",
|
|
13
|
-
"@types/node": "^25",
|
|
14
|
-
"@vitest/coverage-istanbul": "^4",
|
|
15
|
-
"jsdom": "^27.3",
|
|
16
|
-
"oxfmt": "^0.19",
|
|
17
|
-
"oxlint": "^1.34",
|
|
18
|
-
"rolldown": "1.0.0-beta.56",
|
|
19
|
-
"tslib": "^2.8",
|
|
20
|
-
"typescript": "^5.9",
|
|
21
|
-
"vite": "8.0.0-beta.2",
|
|
22
|
-
"vitest": "^4"
|
|
23
|
-
},
|
|
24
|
-
"exports": {
|
|
25
|
-
"./package.json": "./package.json",
|
|
26
|
-
".": {
|
|
27
|
-
"types": "./types/index.d.ts",
|
|
28
|
-
"default": "./dist/index.js"
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
"files": ["dist", "src", "types"],
|
|
2
|
+
"name": "@oscarpalmer/abydon",
|
|
3
|
+
"version": "0.19.0",
|
|
32
4
|
"keywords": [
|
|
33
5
|
"components",
|
|
34
6
|
"dom",
|
|
@@ -40,21 +12,50 @@
|
|
|
40
12
|
"vanilla"
|
|
41
13
|
],
|
|
42
14
|
"license": "MIT",
|
|
43
|
-
"
|
|
44
|
-
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Oscar Palmér",
|
|
17
|
+
"url": "https://oscarpalmer.se"
|
|
18
|
+
},
|
|
45
19
|
"repository": {
|
|
46
20
|
"type": "git",
|
|
47
21
|
"url": "git+https://github.com/oscarpalmer/abydon.git"
|
|
48
22
|
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"module": "./dist/index.mjs",
|
|
29
|
+
"types": "./dist/index.d.mts",
|
|
30
|
+
"exports": {
|
|
31
|
+
"./package.json": "./package.json",
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.mts",
|
|
34
|
+
"default": "./dist/index.mjs"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
49
37
|
"scripts": {
|
|
50
|
-
"build": "npm run
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"test": "npx
|
|
55
|
-
"watch": "npx vite build --watch"
|
|
38
|
+
"build": "npm run tsdown:build && npx vp pack",
|
|
39
|
+
"tsdown:build": "npx tsdown -c ./tsdown.config.ts",
|
|
40
|
+
"tsdown:watch": "npx tsdown -c ./tsdown.config.ts --watch",
|
|
41
|
+
"test": "npx vp test run --coverage",
|
|
42
|
+
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
56
43
|
},
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@oscarpalmer/atoms": "^0.165",
|
|
46
|
+
"@oscarpalmer/mora": "^0.27",
|
|
47
|
+
"@oscarpalmer/toretto": "^0.41"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@oscarpalmer/oui": "^0.19",
|
|
51
|
+
"@types/node": "^25.5",
|
|
52
|
+
"@vitest/coverage-istanbul": "^4.1",
|
|
53
|
+
"jsdom": "^28.1",
|
|
54
|
+
"tsdown": "^0.21",
|
|
55
|
+
"typescript": "^5.9",
|
|
56
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
57
|
+
"vite-plus": "latest",
|
|
58
|
+
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
|
59
|
+
},
|
|
60
|
+
"packageManager": "npm@11.11.1"
|
|
60
61
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,15 +1,41 @@
|
|
|
1
|
+
export const ARRAY_COMPARISON_ADDED = 'added';
|
|
2
|
+
|
|
3
|
+
export const ARRAY_COMPARISON_DISSIMILAR = 'dissimilar';
|
|
4
|
+
|
|
5
|
+
export const ARRAY_COMPARISON_REMOVED = 'removed';
|
|
6
|
+
|
|
1
7
|
export const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
2
8
|
|
|
9
|
+
export const ATTRIBUTE_NAME_DELIMITER = '.';
|
|
10
|
+
|
|
11
|
+
export const ERROR_FRAGMENT = 'Fragment function must return a Fragment instance';
|
|
12
|
+
|
|
13
|
+
export const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
|
|
14
|
+
|
|
15
|
+
export const ERROR_IDENTIFIER_TYPE = 'Identifier cannot be null or undefined';
|
|
16
|
+
|
|
17
|
+
export const EVENT_CHANGE = 'change';
|
|
18
|
+
|
|
19
|
+
export const EVENT_INPUT = 'input';
|
|
20
|
+
|
|
21
|
+
export const EVENT_SUBMIT = 'submit';
|
|
22
|
+
|
|
3
23
|
export const EVENT_DEFAULTS: Record<string, string> = {
|
|
4
24
|
A: 'click',
|
|
5
25
|
BUTTON: 'click',
|
|
6
26
|
DETAILS: 'toggle',
|
|
7
|
-
FORM:
|
|
8
|
-
SELECT:
|
|
9
|
-
TEXTAREA:
|
|
27
|
+
FORM: EVENT_SUBMIT,
|
|
28
|
+
SELECT: EVENT_CHANGE,
|
|
29
|
+
TEXTAREA: EVENT_INPUT,
|
|
10
30
|
};
|
|
11
31
|
|
|
12
|
-
export const
|
|
32
|
+
export const EVENT_ON_PREFIXED = '@on';
|
|
33
|
+
|
|
34
|
+
export const EVENT_ON_VALUE = 'on';
|
|
35
|
+
|
|
36
|
+
export const EVENT_OPTIONS_DELIMITER = ':';
|
|
37
|
+
|
|
38
|
+
export const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
|
|
13
39
|
|
|
14
40
|
export const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
15
41
|
|
|
@@ -38,3 +64,11 @@ export const EXPRESSION_PERIOD = /\./;
|
|
|
38
64
|
export const NAME_FRAGMENT = '$fragment';
|
|
39
65
|
|
|
40
66
|
export const NAME_FRAGMENTS = '$fragments';
|
|
67
|
+
|
|
68
|
+
export const PROPERTY_CHECKED = 'checked';
|
|
69
|
+
|
|
70
|
+
export const PROPERTY_IDENTIFIER = 'identifier';
|
|
71
|
+
|
|
72
|
+
export const PROPERTY_VALUE = 'value';
|
|
73
|
+
|
|
74
|
+
export const TEMPLATE_ITEM = '<>';
|
package/src/fragment.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import {html} from '@oscarpalmer/toretto/html';
|
|
3
|
-
import {NAME_FRAGMENT} from './constants';
|
|
3
|
+
import {NAME_FRAGMENT, PROPERTY_IDENTIFIER} from './constants';
|
|
4
4
|
import {handleFragments} from './fragments';
|
|
5
5
|
import {isFragments} from './helpers';
|
|
6
6
|
import {removeNodes} from './helpers/dom';
|
|
@@ -56,7 +56,7 @@ export class Fragment {
|
|
|
56
56
|
configure(configuration: FragmentConfiguration): Fragment {
|
|
57
57
|
const actual = isPlainObject(configuration) ? configuration : {};
|
|
58
58
|
|
|
59
|
-
if (
|
|
59
|
+
if (PROPERTY_IDENTIFIER in actual) {
|
|
60
60
|
this.#configuration.identifier = actual.identifier;
|
|
61
61
|
}
|
|
62
62
|
|
package/src/fragments.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
2
2
|
import {array, type ReactiveArray} from '@oscarpalmer/mora';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ERROR_FRAGMENT,
|
|
5
|
+
ERROR_IDENTIFIER_DUPLICATE,
|
|
6
|
+
ERROR_IDENTIFIER_TYPE,
|
|
7
|
+
NAME_FRAGMENTS,
|
|
8
|
+
TEMPLATE_ITEM,
|
|
9
|
+
} from './constants';
|
|
4
10
|
import type {Fragment} from './fragment';
|
|
5
11
|
import {isFragment, isFragments} from './helpers';
|
|
6
12
|
import type {FragmentsState} from './models';
|
|
@@ -58,13 +64,13 @@ function handleItems(state: FragmentsState, items: unknown[]): void {
|
|
|
58
64
|
const identifier = state.identify(item);
|
|
59
65
|
|
|
60
66
|
if (identifier == null) {
|
|
61
|
-
throw new
|
|
67
|
+
throw new TypeError(ERROR_IDENTIFIER_TYPE);
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
const key = getString(identifier);
|
|
65
71
|
|
|
66
72
|
if (keys.has(key)) {
|
|
67
|
-
throw new Error(
|
|
73
|
+
throw new Error(ERROR_IDENTIFIER_DUPLICATE.replace(TEMPLATE_ITEM, key));
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
let instance = state.instances[key];
|
|
@@ -73,7 +79,7 @@ function handleItems(state: FragmentsState, items: unknown[]): void {
|
|
|
73
79
|
instance = state.fragment(item);
|
|
74
80
|
|
|
75
81
|
if (!isFragment(instance)) {
|
|
76
|
-
throw new Error(
|
|
82
|
+
throw new Error(ERROR_FRAGMENT);
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
85
|
|
package/src/helpers/dom.ts
CHANGED
|
@@ -14,6 +14,16 @@ export function createNodes(value: unknown): ChildNode[] {
|
|
|
14
14
|
return [new Text(getString(value))];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export function isInputElement(
|
|
18
|
+
node: Node,
|
|
19
|
+
): node is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement {
|
|
20
|
+
return (
|
|
21
|
+
node instanceof HTMLInputElement ||
|
|
22
|
+
node instanceof HTMLSelectElement ||
|
|
23
|
+
node instanceof HTMLTextAreaElement
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
export function removeNodes(nodes: ChildNode[]): void {
|
|
18
28
|
const {length} = nodes;
|
|
19
29
|
|
package/src/helpers/index.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ARRAY_COMPARISON_ADDED,
|
|
4
|
+
ARRAY_COMPARISON_DISSIMILAR,
|
|
5
|
+
ARRAY_COMPARISON_REMOVED,
|
|
6
|
+
NAME_FRAGMENT,
|
|
7
|
+
NAME_FRAGMENTS,
|
|
8
|
+
} from '../constants';
|
|
3
9
|
import type {Fragment} from '../fragment';
|
|
4
10
|
import type {Fragments} from '../fragments';
|
|
5
11
|
|
|
6
12
|
export function compareArrays(
|
|
7
13
|
first: unknown[],
|
|
8
14
|
second: unknown[],
|
|
9
|
-
):
|
|
15
|
+
):
|
|
16
|
+
| typeof ARRAY_COMPARISON_ADDED
|
|
17
|
+
| typeof ARRAY_COMPARISON_DISSIMILAR
|
|
18
|
+
| typeof ARRAY_COMPARISON_REMOVED {
|
|
10
19
|
const firstIsLarger = first.length > second.length;
|
|
11
20
|
const from = firstIsLarger ? first : second;
|
|
12
21
|
const to = firstIsLarger ? second : first;
|
|
13
22
|
|
|
14
23
|
if (!from.filter(key => to.includes(key)).every((key, index) => to[index] === key)) {
|
|
15
|
-
return
|
|
24
|
+
return ARRAY_COMPARISON_DISSIMILAR;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
return firstIsLarger ?
|
|
27
|
+
return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
export function isFragment(value: unknown): value is Fragment {
|
|
@@ -34,9 +43,3 @@ function isNamed(value: unknown, name: string): boolean {
|
|
|
34
43
|
(value as PlainObject)[name] === true
|
|
35
44
|
);
|
|
36
45
|
}
|
|
37
|
-
|
|
38
|
-
const COMPARISON_ADDED = 'added';
|
|
39
|
-
|
|
40
|
-
const COMPARISON_DISSIMILAR = 'dissimilar';
|
|
41
|
-
|
|
42
|
-
const COMPARISON_REMOVED = 'removed';
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {
|
|
2
|
+
import {parse} from '@oscarpalmer/atoms/string';
|
|
3
|
+
import {computed, isReactive, isSignal} from '@oscarpalmer/mora';
|
|
3
4
|
import {
|
|
5
|
+
EVENT_ON_PREFIXED,
|
|
4
6
|
EXPRESSION_ABYDON_ATTRIBUTE_PREFIX,
|
|
5
7
|
EXPRESSION_ABYDON_CONTENT,
|
|
6
8
|
EXPRESSION_EVENT_PREFIX,
|
|
7
9
|
EXPRESSION_PERIOD,
|
|
10
|
+
PROPERTY_VALUE,
|
|
8
11
|
} from '../../constants';
|
|
12
|
+
import {isInputElement} from '../../helpers/dom';
|
|
9
13
|
import type {FragmentData} from '../../models';
|
|
10
14
|
import {mapEvent} from '../event';
|
|
11
15
|
import {setAttribute} from './value';
|
|
@@ -58,6 +62,12 @@ function mapValue(
|
|
|
58
62
|
} else {
|
|
59
63
|
setAttribute(data, element, name, value);
|
|
60
64
|
}
|
|
65
|
+
|
|
66
|
+
if (name === PROPERTY_VALUE && isInputElement(element) && isSignal(value)) {
|
|
67
|
+
mapEvent(element, EVENT_ON_PREFIXED, () => {
|
|
68
|
+
value.set(parse(element.value) ?? element.value);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
function setComputedAttribute(
|
|
@@ -2,23 +2,27 @@ import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
|
2
2
|
import {isReactive} from '@oscarpalmer/mora';
|
|
3
3
|
import {
|
|
4
4
|
isBooleanAttribute,
|
|
5
|
-
setAttribute as
|
|
6
|
-
setProperty,
|
|
5
|
+
setAttribute as setTorettoAttribute,
|
|
7
6
|
} from '@oscarpalmer/toretto/attribute';
|
|
8
7
|
import {
|
|
9
8
|
ATTRIBUTE_CLASS_PREFIX_LENGTH,
|
|
9
|
+
ATTRIBUTE_NAME_DELIMITER,
|
|
10
|
+
EVENT_CHANGE,
|
|
11
|
+
EVENT_INPUT,
|
|
10
12
|
EXPRESSION_ATTRIBUTE_CLASS,
|
|
11
13
|
EXPRESSION_ATTRIBUTE_STYLE_FULL,
|
|
12
14
|
EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
15
|
+
PROPERTY_CHECKED,
|
|
16
|
+
PROPERTY_VALUE,
|
|
13
17
|
} from '../../constants';
|
|
14
18
|
import type {FragmentData} from '../../models';
|
|
15
19
|
|
|
16
20
|
function getCallback(element: HTMLElement | SVGElement, name: string) {
|
|
17
21
|
if (isBooleanAttribute(name) && name in element) {
|
|
18
|
-
return name ===
|
|
22
|
+
return name === PROPERTY_CHECKED ? updateChecked : updateProperty;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
return name ===
|
|
25
|
+
return name === PROPERTY_VALUE ? updateValue : setTorettoAttribute;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export function setAttribute(
|
|
@@ -56,7 +60,7 @@ function setClasses(
|
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split(
|
|
63
|
+
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split(ATTRIBUTE_NAME_DELIMITER);
|
|
60
64
|
|
|
61
65
|
if (isReactive(value)) {
|
|
62
66
|
data.mora.subscribers.add(value.subscribe(update));
|
|
@@ -112,7 +116,7 @@ function setValue(
|
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
function updateChecked(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
115
|
-
updateElement(
|
|
119
|
+
updateElement(EVENT_CHANGE, PROPERTY_CHECKED, element, name, value, value === true);
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
function updateElement(
|
|
@@ -127,7 +131,11 @@ function updateElement(
|
|
|
127
131
|
return;
|
|
128
132
|
}
|
|
129
133
|
|
|
130
|
-
|
|
134
|
+
setTorettoAttribute(element, name, value);
|
|
135
|
+
|
|
136
|
+
if ((element as unknown as PlainObject)[property] === next) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
131
139
|
|
|
132
140
|
(element as unknown as PlainObject)[property] = next;
|
|
133
141
|
|
|
@@ -135,13 +143,13 @@ function updateElement(
|
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
function updateProperty(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
138
|
-
|
|
146
|
+
setTorettoAttribute(element, name, value === true);
|
|
139
147
|
}
|
|
140
148
|
|
|
141
149
|
function updateValue(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
142
150
|
updateElement(
|
|
143
|
-
element instanceof HTMLSelectElement ?
|
|
144
|
-
|
|
151
|
+
element instanceof HTMLSelectElement ? EVENT_CHANGE : EVENT_INPUT,
|
|
152
|
+
PROPERTY_VALUE,
|
|
145
153
|
element,
|
|
146
154
|
name,
|
|
147
155
|
value,
|
package/src/node/event.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {on} from '@oscarpalmer/toretto/event';
|
|
2
2
|
import {
|
|
3
|
+
EVENT_CHANGE,
|
|
3
4
|
EVENT_DEFAULTS,
|
|
5
|
+
EVENT_INPUT,
|
|
6
|
+
EVENT_ON_VALUE,
|
|
7
|
+
EVENT_OPTIONS_DELIMITER,
|
|
8
|
+
EVENT_SUBMIT,
|
|
4
9
|
EXPRESSION_EVENT_CHANGE_TYPES,
|
|
5
10
|
EXPRESSION_EVENT_NAME,
|
|
6
11
|
EXPRESSION_EVENT_OPTIONS_ACTIVE,
|
|
@@ -9,7 +14,7 @@ import {
|
|
|
9
14
|
} from '../constants';
|
|
10
15
|
|
|
11
16
|
function getOptions(options: string): AddEventListenerOptions {
|
|
12
|
-
const parts = options.split(
|
|
17
|
+
const parts = options.split(EVENT_OPTIONS_DELIMITER);
|
|
13
18
|
|
|
14
19
|
return {
|
|
15
20
|
capture: parts.some(part => EXPRESSION_EVENT_OPTIONS_CAPTURE.test(part)),
|
|
@@ -19,16 +24,16 @@ function getOptions(options: string): AddEventListenerOptions {
|
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
function getType(element: HTMLElement | SVGElement, type: string): string {
|
|
22
|
-
if (type !==
|
|
27
|
+
if (type !== EVENT_ON_VALUE) {
|
|
23
28
|
return type;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
if (element instanceof HTMLInputElement) {
|
|
27
32
|
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) {
|
|
28
|
-
return
|
|
33
|
+
return EVENT_CHANGE;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
return element.type ===
|
|
36
|
+
return element.type === EVENT_SUBMIT ? EVENT_SUBMIT : EVENT_INPUT;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
return EVENT_DEFAULTS[element.tagName] ?? type;
|
package/src/node/value.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
|
|
|
2
2
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
3
|
import type {Reactive} from '@oscarpalmer/mora';
|
|
4
4
|
import {isChildNode} from '@oscarpalmer/toretto/is';
|
|
5
|
+
import {ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_REMOVED} from '../constants';
|
|
5
6
|
import type {Fragment} from '../fragment';
|
|
6
7
|
import {compareArrays, isFragment} from '../helpers';
|
|
7
8
|
import {createNodes, replaceNodes} from '../helpers/dom';
|
|
@@ -71,8 +72,8 @@ function handleArray(
|
|
|
71
72
|
|
|
72
73
|
const comparison = compareArrays(items.fragments ?? [], items.templates);
|
|
73
74
|
|
|
74
|
-
if (comparison !==
|
|
75
|
-
addToArray(identifiers, {...items, next}, nodes, comparison ===
|
|
75
|
+
if (comparison !== ARRAY_COMPARISON_REMOVED) {
|
|
76
|
+
addToArray(identifiers, {...items, next}, nodes, comparison === ARRAY_COMPARISON_ADDED);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const toRemove =
|
package/dist/constants.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
2
|
-
const EVENT_DEFAULTS = {
|
|
3
|
-
A: "click",
|
|
4
|
-
BUTTON: "click",
|
|
5
|
-
DETAILS: "toggle",
|
|
6
|
-
FORM: "submit",
|
|
7
|
-
SELECT: "change",
|
|
8
|
-
TEXTAREA: "input"
|
|
9
|
-
};
|
|
10
|
-
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?\w+)="<!--abydon.(\d+)-->"/g;
|
|
11
|
-
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
12
|
-
const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
|
|
13
|
-
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
14
|
-
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
15
|
-
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
16
|
-
const EXPRESSION_EVENT_CHANGE_TYPES = /^(checkbox|radio)$/;
|
|
17
|
-
const EXPRESSION_EVENT_NAME = /^@([\w-]+)(?::([a-z:]+))?$/i;
|
|
18
|
-
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
19
|
-
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
20
|
-
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
21
|
-
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
22
|
-
const EXPRESSION_PERIOD = /\./;
|
|
23
|
-
const NAME_FRAGMENT = "$fragment";
|
|
24
|
-
const NAME_FRAGMENTS = "$fragments";
|
|
25
|
-
export { ATTRIBUTE_CLASS_PREFIX_LENGTH, EVENT_DEFAULTS, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS };
|
package/dist/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Fragments } from "./fragments.js";
|
|
2
|
-
import { Fragment } from "./fragment.js";
|
|
3
|
-
import "@oscarpalmer/mora";
|
|
4
|
-
export * from "@oscarpalmer/mora";
|
|
5
|
-
function fragments(array$1, identify, fragment) {
|
|
6
|
-
return new Fragments(array$1, identify, fragment);
|
|
7
|
-
}
|
|
8
|
-
function html(template, ...values) {
|
|
9
|
-
return new Fragment(template, values);
|
|
10
|
-
}
|
|
11
|
-
export { fragments, html };
|
package/dist/models.js
DELETED
|
File without changes
|
package/types/constants.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
2
|
-
export declare const EVENT_DEFAULTS: Record<string, string>;
|
|
3
|
-
export declare const EXPRESSION_ABYDON_ATTRIBUTE_FULL: RegExp;
|
|
4
|
-
export declare const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX: RegExp;
|
|
5
|
-
export declare const EXPRESSION_ABYDON_CONTENT: RegExp;
|
|
6
|
-
export declare const EXPRESSION_ATTRIBUTE_CLASS: RegExp;
|
|
7
|
-
export declare const EXPRESSION_ATTRIBUTE_STYLE_FULL: RegExp;
|
|
8
|
-
export declare const EXPRESSION_ATTRIBUTE_STYLE_PREFIX: RegExp;
|
|
9
|
-
export declare const EXPRESSION_EVENT_CHANGE_TYPES: RegExp;
|
|
10
|
-
export declare const EXPRESSION_EVENT_NAME: RegExp;
|
|
11
|
-
export declare const EXPRESSION_EVENT_OPTIONS_ACTIVE: RegExp;
|
|
12
|
-
export declare const EXPRESSION_EVENT_OPTIONS_CAPTURE: RegExp;
|
|
13
|
-
export declare const EXPRESSION_EVENT_OPTIONS_ONCE: RegExp;
|
|
14
|
-
export declare const EXPRESSION_EVENT_PREFIX: RegExp;
|
|
15
|
-
export declare const EXPRESSION_PERIOD: RegExp;
|
|
16
|
-
export declare const NAME_FRAGMENT = "$fragment";
|
|
17
|
-
export declare const NAME_FRAGMENTS = "$fragments";
|
package/types/fragment.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { FragmentConfiguration } from './models';
|
|
2
|
-
export declare class Fragment {
|
|
3
|
-
#private;
|
|
4
|
-
/**
|
|
5
|
-
* Fragment identifier
|
|
6
|
-
*/
|
|
7
|
-
get identifier(): unknown;
|
|
8
|
-
constructor(strings: TemplateStringsArray, expressions: unknown[]);
|
|
9
|
-
/**
|
|
10
|
-
* Append the fragment to the given element
|
|
11
|
-
* @param element Element to append to
|
|
12
|
-
*/
|
|
13
|
-
appendTo(element: Element): void;
|
|
14
|
-
/**
|
|
15
|
-
* Configure the fragment
|
|
16
|
-
* @param configuration Configuration options
|
|
17
|
-
* @returns Fragment
|
|
18
|
-
*/
|
|
19
|
-
configure(configuration: FragmentConfiguration): Fragment;
|
|
20
|
-
/**
|
|
21
|
-
* Get a list of the fragment's nodes
|
|
22
|
-
* @returns List of nodes
|
|
23
|
-
*/
|
|
24
|
-
get(): ChildNode[];
|
|
25
|
-
/**
|
|
26
|
-
* Set an identifier for the fragment
|
|
27
|
-
*
|
|
28
|
-
* _An identifier can be used to uniquely identify a fragment,
|
|
29
|
-
* which helps prevent re-rendering in certain scenarios._
|
|
30
|
-
* @param identifier Identifier
|
|
31
|
-
* @returns Fragment
|
|
32
|
-
*/
|
|
33
|
-
identify(identifier: unknown): Fragment;
|
|
34
|
-
/**
|
|
35
|
-
* Remove the fragment from the DOM
|
|
36
|
-
*/
|
|
37
|
-
remove(): void;
|
|
38
|
-
}
|
package/types/fragments.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type ReactiveArray } from '@oscarpalmer/mora';
|
|
2
|
-
import type { Fragment } from './fragment';
|
|
3
|
-
import type { FragmentsState } from './models';
|
|
4
|
-
export declare class Fragments {
|
|
5
|
-
#private;
|
|
6
|
-
/**
|
|
7
|
-
* Fragment items
|
|
8
|
-
*/
|
|
9
|
-
get items(): ReactiveArray<Fragment>;
|
|
10
|
-
constructor(items: ReactiveArray<unknown>, identify: (item: unknown) => unknown, fragment: (item: unknown) => Fragment);
|
|
11
|
-
}
|
|
12
|
-
export declare function handleFragments(item: Fragments | FragmentsState, remove: boolean): void;
|
|
13
|
-
export declare function initializeFragments(state: FragmentsState): void;
|
package/types/helpers/dom.d.ts
DELETED
package/types/helpers/index.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Fragment } from '../fragment';
|
|
2
|
-
import type { Fragments } from '../fragments';
|
|
3
|
-
export declare function compareArrays(first: unknown[], second: unknown[]): 'added' | 'dissimilar' | 'removed';
|
|
4
|
-
export declare function isFragment(value: unknown): value is Fragment;
|
|
5
|
-
export declare function isFragments(value: unknown): value is Fragments;
|