@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.
Files changed (54) hide show
  1. package/dist/{abydon.full.js → abydon.full.mjs} +542 -234
  2. package/dist/constants.d.mts +37 -0
  3. package/dist/constants.mjs +44 -0
  4. package/dist/fragment-9qTBAvtR.d.mts +82 -0
  5. package/dist/fragment.d.mts +2 -0
  6. package/dist/{fragment.js → fragment.mjs} +35 -6
  7. package/dist/fragments.d.mts +16 -0
  8. package/dist/{fragments.js → fragments.mjs} +11 -6
  9. package/dist/helpers/dom.d.mts +7 -0
  10. package/dist/helpers/{dom.js → dom.mjs} +7 -2
  11. package/dist/helpers/index.d.mts +10 -0
  12. package/dist/helpers/{index.js → index.mjs} +5 -6
  13. package/dist/index.d.mts +21 -0
  14. package/dist/index.mjs +24 -0
  15. package/dist/models.d.mts +2 -0
  16. package/dist/models.mjs +1 -0
  17. package/dist/node/attribute/index.d.mts +6 -0
  18. package/dist/node/attribute/{index.js → index.mjs} +11 -4
  19. package/dist/node/attribute/value.d.mts +6 -0
  20. package/dist/node/attribute/{value.js → value.mjs} +13 -10
  21. package/dist/node/event.d.mts +4 -0
  22. package/dist/node/{event.js → event.mjs} +5 -3
  23. package/dist/node/index.d.mts +6 -0
  24. package/dist/node/{index.js → index.mjs} +9 -7
  25. package/dist/node/value.d.mts +7 -0
  26. package/dist/node/{value.js → value.mjs} +9 -6
  27. package/dist/parse.d.mts +6 -0
  28. package/dist/{parse.js → parse.mjs} +3 -1
  29. package/package.json +42 -41
  30. package/src/constants.ts +38 -4
  31. package/src/fragment.ts +2 -2
  32. package/src/fragments.ts +10 -4
  33. package/src/helpers/dom.ts +10 -0
  34. package/src/helpers/index.ts +13 -10
  35. package/src/node/attribute/index.ts +11 -1
  36. package/src/node/attribute/value.ts +18 -10
  37. package/src/node/event.ts +9 -4
  38. package/src/node/value.ts +3 -2
  39. package/dist/constants.js +0 -25
  40. package/dist/index.js +0 -11
  41. package/dist/models.js +0 -0
  42. package/types/constants.d.ts +0 -17
  43. package/types/fragment.d.ts +0 -38
  44. package/types/fragments.d.ts +0 -13
  45. package/types/helpers/dom.d.ts +0 -3
  46. package/types/helpers/index.d.ts +0 -5
  47. package/types/index.d.ts +0 -20
  48. package/types/models.d.ts +0 -41
  49. package/types/node/attribute/index.d.ts +0 -2
  50. package/types/node/attribute/value.d.ts +0 -2
  51. package/types/node/event.d.ts +0 -1
  52. package/types/node/index.d.ts +0 -2
  53. package/types/node/value.d.ts +0 -3
  54. package/types/parse.d.ts +0 -2
@@ -1,8 +1,10 @@
1
- import { compareArrays, isFragment } from "../helpers/index.js";
2
- import { createNodes, replaceNodes } from "../helpers/dom.js";
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 === "added");
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$1) => isFragment(item$1) && item$1.identifier != null);
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$1) => createNodes(item$1)) : templates.flatMap((template) => template.get()))
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$1) => item$1.nodes?.includes(comment));
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 };
@@ -0,0 +1,6 @@
1
+ import { r as FragmentData } from "./fragment-9qTBAvtR.mjs";
2
+
3
+ //#region src/parse.d.ts
4
+ declare function parse(data: FragmentData): string;
5
+ //#endregion
6
+ export { parse };
@@ -1,5 +1,6 @@
1
- import { EXPRESSION_ABYDON_ATTRIBUTE_FULL } from "./constants.js";
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
- "author": {
3
- "name": "Oscar Palmér",
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
- "module": "dist/index.js",
44
- "name": "@oscarpalmer/abydon",
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 clean && npx vite build && npm run rolldown:build && npx tsc",
51
- "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
52
- "rolldown:build": "npx rolldown -c",
53
- "rolldown:watch": "npx rolldown -c ./rolldown.config.js --watch",
54
- "test": "npx vitest --coverage",
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
- "type": "module",
58
- "types": "types/index.d.ts",
59
- "version": "0.16.0"
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: 'submit',
8
- SELECT: 'change',
9
- TEXTAREA: 'input',
27
+ FORM: EVENT_SUBMIT,
28
+ SELECT: EVENT_CHANGE,
29
+ TEXTAREA: EVENT_INPUT,
10
30
  };
11
31
 
12
- export const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?\w+)="<!--abydon.(\d+)-->"/g;
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 ('identifier' in actual) {
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 {NAME_FRAGMENTS} from './constants';
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 Error('Identifier cannot be null or undefined');
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(`Duplicate identifier found: "${key}"`);
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('Fragment function must return a Fragment instance');
82
+ throw new Error(ERROR_FRAGMENT);
77
83
  }
78
84
  }
79
85
 
@@ -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
 
@@ -1,21 +1,30 @@
1
1
  import type {PlainObject} from '@oscarpalmer/atoms/models';
2
- import {NAME_FRAGMENT, NAME_FRAGMENTS} from '../constants';
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
- ): 'added' | 'dissimilar' | 'removed' {
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 COMPARISON_DISSIMILAR;
24
+ return ARRAY_COMPARISON_DISSIMILAR;
16
25
  }
17
26
 
18
- return firstIsLarger ? COMPARISON_REMOVED : COMPARISON_ADDED;
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 {computed, isReactive} from '@oscarpalmer/mora';
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 setAttr,
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 === 'checked' ? updateChecked : updateProperty;
22
+ return name === PROPERTY_CHECKED ? updateChecked : updateProperty;
19
23
  }
20
24
 
21
- return name === 'value' ? updateValue : setAttr;
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('change', 'checked', element, name, value, value === true);
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
- setAttr(element, name, value);
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
- setProperty(element, name, value === true);
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 ? 'change' : 'input',
144
- 'value',
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 !== 'on') {
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 'change';
33
+ return EVENT_CHANGE;
29
34
  }
30
35
 
31
- return element.type === 'submit' ? 'submit' : 'input';
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 !== 'removed') {
75
- addToArray(identifiers, {...items, next}, nodes, comparison === 'added');
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
@@ -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";
@@ -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
- }
@@ -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;
@@ -1,3 +0,0 @@
1
- export declare function createNodes(value: unknown): ChildNode[];
2
- export declare function removeNodes(nodes: ChildNode[]): void;
3
- export declare function replaceNodes(from: ChildNode[], to: ChildNode[]): void;
@@ -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;