@oscarpalmer/abydon 0.19.0 → 0.21.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.
@@ -27,6 +27,8 @@ declare const EXPRESSION_EVENT_OPTIONS_CAPTURE: RegExp;
27
27
  declare const EXPRESSION_EVENT_OPTIONS_ONCE: RegExp;
28
28
  declare const EXPRESSION_EVENT_PREFIX: RegExp;
29
29
  declare const EXPRESSION_PERIOD: RegExp;
30
+ declare const EXPRESSION_TEXTAREA_VALUE: RegExp;
31
+ declare const INPUT_TYPE_CHECKBOX = "checkbox";
30
32
  declare const NAME_FRAGMENT = "$fragment";
31
33
  declare const NAME_FRAGMENTS = "$fragments";
32
34
  declare const PROPERTY_CHECKED = "checked";
@@ -34,4 +36,4 @@ declare const PROPERTY_IDENTIFIER = "identifier";
34
36
  declare const PROPERTY_VALUE = "value";
35
37
  declare const TEMPLATE_ITEM = "<>";
36
38
  //#endregion
37
- 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, EVENT_ON_PREFIXED, 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_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, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
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, EVENT_ON_PREFIXED, 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_EVENT_CHANGE_TYPES, 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, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
@@ -34,6 +34,8 @@ const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
34
34
  const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
35
35
  const EXPRESSION_EVENT_PREFIX = /^@/;
36
36
  const EXPRESSION_PERIOD = /\./;
37
+ const EXPRESSION_TEXTAREA_VALUE = /<!--abydon\.(\d+)-->/;
38
+ const INPUT_TYPE_CHECKBOX = "checkbox";
37
39
  const NAME_FRAGMENT = "$fragment";
38
40
  const NAME_FRAGMENTS = "$fragments";
39
41
  const PROPERTY_CHECKED = "checked";
@@ -41,4 +43,4 @@ const PROPERTY_IDENTIFIER = "identifier";
41
43
  const PROPERTY_VALUE = "value";
42
44
  const TEMPLATE_ITEM = "<>";
43
45
  //#endregion
44
- 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, EVENT_ON_PREFIXED, 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_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, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
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, EVENT_ON_PREFIXED, 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_EVENT_CHANGE_TYPES, 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, NAME_FRAGMENT, NAME_FRAGMENTS, PROPERTY_CHECKED, PROPERTY_IDENTIFIER, PROPERTY_VALUE, TEMPLATE_ITEM };
@@ -1,2 +1,42 @@
1
- import { t as Fragment } from "./fragment-9qTBAvtR.mjs";
1
+ import { FragmentConfiguration } from "./models.mjs";
2
+
3
+ //#region src/fragment.d.ts
4
+ declare class Fragment {
5
+ #private;
6
+ /**
7
+ * Fragment identifier
8
+ */
9
+ get identifier(): unknown;
10
+ constructor(strings: TemplateStringsArray, expressions: unknown[]);
11
+ /**
12
+ * Append the fragment to the given element
13
+ * @param element Element to append to
14
+ */
15
+ appendTo(element: Element): void;
16
+ /**
17
+ * Configure the fragment
18
+ * @param configuration Configuration options
19
+ * @returns Fragment
20
+ */
21
+ configure(configuration: FragmentConfiguration): Fragment;
22
+ /**
23
+ * Get a list of the fragment's nodes
24
+ * @returns List of nodes
25
+ */
26
+ get(): ChildNode[];
27
+ /**
28
+ * Set an identifier for the fragment
29
+ *
30
+ * _An identifier can be used to uniquely identify a fragment,
31
+ * which helps prevent re-rendering in certain scenarios._
32
+ * @param identifier Identifier
33
+ * @returns Fragment
34
+ */
35
+ identify(identifier: unknown): Fragment;
36
+ /**
37
+ * Remove the fragment from the DOM
38
+ */
39
+ remove(): void;
40
+ }
41
+ //#endregion
2
42
  export { Fragment };
@@ -1,4 +1,5 @@
1
- import { a as FragmentsState, t as Fragment } from "./fragment-9qTBAvtR.mjs";
1
+ import { FragmentsState } from "./models.mjs";
2
+ import { Fragment } from "./fragment.mjs";
2
3
  import { ReactiveArray } from "@oscarpalmer/mora";
3
4
 
4
5
  //#region src/fragments.d.ts
@@ -1,6 +1,6 @@
1
1
  //#region src/helpers/dom.d.ts
2
2
  declare function createNodes(value: unknown): ChildNode[];
3
- declare function isInputElement(node: Node): node is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
3
+ declare function isInputElement(node: Node): node is HTMLInputElement | HTMLSelectElement;
4
4
  declare function removeNodes(nodes: ChildNode[]): void;
5
5
  declare function replaceNodes(from: ChildNode[], to: ChildNode[]): void;
6
6
  //#endregion
@@ -8,7 +8,7 @@ function createNodes(value) {
8
8
  return [new Text(getString(value))];
9
9
  }
10
10
  function isInputElement(node) {
11
- return node instanceof HTMLInputElement || node instanceof HTMLSelectElement || node instanceof HTMLTextAreaElement;
11
+ return node instanceof HTMLInputElement || node instanceof HTMLSelectElement;
12
12
  }
13
13
  function removeNodes(nodes) {
14
14
  const { length } = nodes;
@@ -1,5 +1,5 @@
1
1
  import { ARRAY_COMPARISON_ADDED, ARRAY_COMPARISON_DISSIMILAR, ARRAY_COMPARISON_REMOVED } from "../constants.mjs";
2
- import { t as Fragment } from "../fragment-9qTBAvtR.mjs";
2
+ import { Fragment } from "../fragment.mjs";
3
3
  import { Fragments } from "../fragments.mjs";
4
4
 
5
5
  //#region src/helpers/index.d.ts
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as Fragment } from "./fragment-9qTBAvtR.mjs";
1
+ import { Fragment } from "./fragment.mjs";
2
2
  import { Fragments } from "./fragments.mjs";
3
3
  import { ReactiveArray } from "@oscarpalmer/mora";
4
4
  export * from "@oscarpalmer/mora";
package/dist/models.d.mts CHANGED
@@ -1,2 +1,44 @@
1
- import { a as FragmentsState, i as FragmentItem, n as FragmentConfiguration, r as FragmentData } from "./fragment-9qTBAvtR.mjs";
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 };
@@ -1,4 +1,4 @@
1
- import { r as FragmentData } from "../../fragment-9qTBAvtR.mjs";
1
+ import { FragmentData } from "../../models.mjs";
2
2
 
3
3
  //#region src/node/attribute/index.d.ts
4
4
  declare function mapAttributes(data: FragmentData, element: HTMLElement | SVGElement): void;
@@ -1,4 +1,4 @@
1
- import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD } from "../../constants.mjs";
1
+ import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, PROPERTY_CHECKED, PROPERTY_VALUE } from "../../constants.mjs";
2
2
  import { isInputElement } from "../../helpers/dom.mjs";
3
3
  import { mapEvent } from "../event.mjs";
4
4
  import { setAttribute } from "./value.mjs";
@@ -33,8 +33,13 @@ function mapAttributes(data, element) {
33
33
  function mapValue(data, element, name, value) {
34
34
  if (typeof value === "function") setComputedAttribute(data, element, name, value);
35
35
  else setAttribute(data, element, name, value);
36
- if (name === "value" && isInputElement(element) && isSignal(value)) mapEvent(element, "@on", () => {
37
- value.set(parse(element.value) ?? element.value);
36
+ if (!isInputElement(element) || !isSignal(value)) return;
37
+ let property;
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);
38
43
  });
39
44
  }
40
45
  function setComputedAttribute(data, element, name, callback) {
@@ -1,4 +1,4 @@
1
- import { r as FragmentData } from "../../fragment-9qTBAvtR.mjs";
1
+ import { FragmentData } from "../../models.mjs";
2
2
 
3
3
  //#region src/node/attribute/value.d.ts
4
4
  declare function setAttribute(data: FragmentData, element: HTMLElement | SVGElement, name: string, value: unknown): void;
@@ -1,4 +1,4 @@
1
- import { r as FragmentData } from "../fragment-9qTBAvtR.mjs";
1
+ import { FragmentData } from "../models.mjs";
2
2
 
3
3
  //#region src/node/index.d.ts
4
4
  declare function mapNodes(data: FragmentData, nodes: ChildNode[]): void;
@@ -1,10 +1,11 @@
1
- import { EXPRESSION_ABYDON_CONTENT } from "../constants.mjs";
1
+ import { EXPRESSION_ABYDON_CONTENT, EXPRESSION_TEXTAREA_VALUE } from "../constants.mjs";
2
2
  import { isFragment, isFragments } from "../helpers/index.mjs";
3
3
  import { handleFragments } from "../fragments.mjs";
4
4
  import { createNodes } from "../helpers/dom.mjs";
5
+ import { mapEvent } from "./event.mjs";
5
6
  import { mapAttributes } from "./attribute/index.mjs";
6
7
  import { setReactiveValue } from "./value.mjs";
7
- import { computed, isReactive } from "@oscarpalmer/mora";
8
+ import { computed, isComputed, isReactive, isSignal } from "@oscarpalmer/mora";
8
9
  import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
9
10
  //#region src/node/index.ts
10
11
  function mapNode(data, comment) {
@@ -20,10 +21,31 @@ function mapNodes(data, nodes) {
20
21
  mapNode(data, node);
21
22
  continue;
22
23
  }
24
+ if (node instanceof HTMLTextAreaElement) mapTextarea(data, node);
23
25
  if (isHTMLOrSVGElement(node)) mapAttributes(data, node);
24
26
  if (node.hasChildNodes()) mapNodes(data, [...node.childNodes]);
25
27
  }
26
28
  }
29
+ function mapTextarea(data, element) {
30
+ const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
31
+ if (index == null) return;
32
+ element.value = "";
33
+ const value = data.values[Number.parseInt(index, 10)];
34
+ if (isSignal(value)) {
35
+ element.value = String(value.peek());
36
+ mapEvent(element, "@on", () => {
37
+ value.set(element.value);
38
+ });
39
+ return;
40
+ }
41
+ let reactive;
42
+ if (typeof value === "function") reactive = computed(value);
43
+ else if (isComputed(value)) reactive = value;
44
+ if (reactive == null) element.value = String(value);
45
+ else data.mora.subscribers.add(reactive.subscribe((value) => {
46
+ element.value = String(value);
47
+ }));
48
+ }
27
49
  function mapValue(data, comment, value) {
28
50
  switch (true) {
29
51
  case typeof value === "function":
@@ -1,4 +1,4 @@
1
- import { r as FragmentData } from "../fragment-9qTBAvtR.mjs";
1
+ import { FragmentData } from "../models.mjs";
2
2
  import { Reactive } from "@oscarpalmer/mora";
3
3
 
4
4
  //#region src/node/value.d.ts
package/dist/parse.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as FragmentData } from "./fragment-9qTBAvtR.mjs";
1
+ import { FragmentData } from "./models.mjs";
2
2
 
3
3
  //#region src/parse.d.ts
4
4
  declare function parse(data: FragmentData): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oscarpalmer/abydon",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "keywords": [
5
5
  "components",
6
6
  "dom",
@@ -42,15 +42,15 @@
42
42
  "test:leak": "npx vp test run --detect-async-leaks --coverage"
43
43
  },
44
44
  "dependencies": {
45
- "@oscarpalmer/atoms": "^0.165",
46
- "@oscarpalmer/mora": "^0.27",
47
- "@oscarpalmer/toretto": "^0.41"
45
+ "@oscarpalmer/atoms": "^0.183",
46
+ "@oscarpalmer/mora": "^0.28",
47
+ "@oscarpalmer/toretto": "^0.42"
48
48
  },
49
49
  "devDependencies": {
50
- "@oscarpalmer/oui": "^0.19",
51
- "@types/node": "^25.5",
50
+ "@oscarpalmer/oui": "^0.20",
51
+ "@types/node": "^25.6",
52
52
  "@vitest/coverage-istanbul": "^4.1",
53
- "jsdom": "^28.1",
53
+ "jsdom": "^29",
54
54
  "tsdown": "^0.21",
55
55
  "typescript": "^5.9",
56
56
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
package/src/constants.ts CHANGED
@@ -61,6 +61,10 @@ export const EXPRESSION_EVENT_PREFIX = /^@/;
61
61
 
62
62
  export const EXPRESSION_PERIOD = /\./;
63
63
 
64
+ export const EXPRESSION_TEXTAREA_VALUE = /<!--abydon\.(\d+)-->/;
65
+
66
+ export const INPUT_TYPE_CHECKBOX = 'checkbox';
67
+
64
68
  export const NAME_FRAGMENT = '$fragment';
65
69
 
66
70
  export const NAME_FRAGMENTS = '$fragments';
@@ -14,14 +14,8 @@ 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
- );
17
+ export function isInputElement(node: Node): node is HTMLInputElement | HTMLSelectElement {
18
+ return node instanceof HTMLInputElement || node instanceof HTMLSelectElement;
25
19
  }
26
20
 
27
21
  export function removeNodes(nodes: ChildNode[]): void {
@@ -7,6 +7,8 @@ import {
7
7
  EXPRESSION_ABYDON_CONTENT,
8
8
  EXPRESSION_EVENT_PREFIX,
9
9
  EXPRESSION_PERIOD,
10
+ INPUT_TYPE_CHECKBOX,
11
+ PROPERTY_CHECKED,
10
12
  PROPERTY_VALUE,
11
13
  } from '../../constants';
12
14
  import {isInputElement} from '../../helpers/dom';
@@ -63,9 +65,23 @@ function mapValue(
63
65
  setAttribute(data, element, name, value);
64
66
  }
65
67
 
66
- if (name === PROPERTY_VALUE && isInputElement(element) && isSignal(value)) {
68
+ if (!isInputElement(element) || !isSignal(value)) {
69
+ return;
70
+ }
71
+
72
+ let property: string | undefined;
73
+
74
+ if (name === PROPERTY_CHECKED && element.type === INPUT_TYPE_CHECKBOX) {
75
+ property = PROPERTY_CHECKED;
76
+ } else if (name === PROPERTY_VALUE) {
77
+ property = PROPERTY_VALUE;
78
+ }
79
+
80
+ if (property != null) {
67
81
  mapEvent(element, EVENT_ON_PREFIXED, () => {
68
- value.set(parse(element.value) ?? element.value);
82
+ const next = element[property as keyof typeof element];
83
+
84
+ value.set(parse(String(next)) ?? next);
69
85
  });
70
86
  }
71
87
  }
package/src/node/index.ts CHANGED
@@ -1,13 +1,21 @@
1
1
  import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import {computed, isReactive, type Reactive} from '@oscarpalmer/mora';
2
+ import {
3
+ computed,
4
+ isComputed,
5
+ isReactive,
6
+ isSignal,
7
+ type Computed,
8
+ type Reactive,
9
+ } from '@oscarpalmer/mora';
3
10
  import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
4
- import {EXPRESSION_ABYDON_CONTENT} from '../constants';
11
+ import {EXPRESSION_ABYDON_CONTENT, EXPRESSION_TEXTAREA_VALUE} from '../constants';
5
12
  import {handleFragments} from '../fragments';
6
13
  import {isFragment, isFragments} from '../helpers';
7
14
  import {createNodes} from '../helpers/dom';
8
15
  import type {FragmentData} from '../models';
9
16
  import {mapAttributes} from './attribute';
10
17
  import {setReactiveValue} from './value';
18
+ import {mapEvent} from './event';
11
19
 
12
20
  function mapNode(data: FragmentData, comment: Comment): void {
13
21
  const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent ?? '');
@@ -30,6 +38,10 @@ export function mapNodes(data: FragmentData, nodes: ChildNode[]): void {
30
38
  continue;
31
39
  }
32
40
 
41
+ if (node instanceof HTMLTextAreaElement) {
42
+ mapTextarea(data, node);
43
+ }
44
+
33
45
  if (isHTMLOrSVGElement(node)) {
34
46
  mapAttributes(data, node);
35
47
  }
@@ -40,6 +52,46 @@ export function mapNodes(data: FragmentData, nodes: ChildNode[]): void {
40
52
  }
41
53
  }
42
54
 
55
+ function mapTextarea(data: FragmentData, element: HTMLTextAreaElement): void {
56
+ const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
57
+
58
+ if (index == null) {
59
+ return;
60
+ }
61
+
62
+ element.value = '';
63
+
64
+ const value = data.values[Number.parseInt(index, 10)];
65
+
66
+ if (isSignal(value)) {
67
+ element.value = String(value.peek());
68
+
69
+ mapEvent(element, '@on', () => {
70
+ value.set(element.value);
71
+ });
72
+
73
+ return;
74
+ }
75
+
76
+ let reactive: Computed<unknown> | undefined;
77
+
78
+ if (typeof value === 'function') {
79
+ reactive = computed(value as GenericCallback);
80
+ } else if (isComputed(value)) {
81
+ reactive = value;
82
+ }
83
+
84
+ if (reactive == null) {
85
+ element.value = String(value);
86
+ } else {
87
+ data.mora.subscribers.add(
88
+ reactive.subscribe(value => {
89
+ element.value = String(value);
90
+ }),
91
+ );
92
+ }
93
+ }
94
+
43
95
  function mapValue(data: FragmentData, comment: Comment, value: unknown): void {
44
96
  switch (true) {
45
97
  case typeof value === 'function':
@@ -1,82 +0,0 @@
1
- import { Reactive, ReactiveArray, Unsubscribe } from "@oscarpalmer/mora";
2
-
3
- //#region src/models.d.ts
4
- type FragmentConfiguration = {
5
- /**
6
- * Should the template be cached? _(defaults to `true`)_
7
- */
8
- cache?: boolean;
9
- /**
10
- * Identifier for the fragment
11
- *
12
- * _(An identifier can be used to uniquely identify a fragment,
13
- * which helps prevent re-rendering in certain scenarios)_
14
- */
15
- identifier?: unknown;
16
- };
17
- type FragmentData = {
18
- expressions: unknown[];
19
- items: FragmentItem[];
20
- mora: MoraData;
21
- strings: TemplateStringsArray;
22
- template?: string;
23
- values: unknown[];
24
- };
25
- type FragmentItem = {
26
- fragments?: Fragment[];
27
- nodes?: ChildNode[];
28
- text?: Text;
29
- };
30
- type FragmentsState = {
31
- array: ReactiveArray<unknown>;
32
- fragment: (item: unknown) => Fragment;
33
- identify: (item: unknown) => unknown;
34
- instances: Record<string, Fragment>;
35
- mapped: ReactiveArray<Fragment>;
36
- subscriber: Unsubscribe | undefined;
37
- };
38
- type MoraData = {
39
- subscribers: Set<() => void>;
40
- values: Set<Reactive<unknown>>;
41
- };
42
- //#endregion
43
- //#region src/fragment.d.ts
44
- declare class Fragment {
45
- #private;
46
- /**
47
- * Fragment identifier
48
- */
49
- get identifier(): unknown;
50
- constructor(strings: TemplateStringsArray, expressions: unknown[]);
51
- /**
52
- * Append the fragment to the given element
53
- * @param element Element to append to
54
- */
55
- appendTo(element: Element): void;
56
- /**
57
- * Configure the fragment
58
- * @param configuration Configuration options
59
- * @returns Fragment
60
- */
61
- configure(configuration: FragmentConfiguration): Fragment;
62
- /**
63
- * Get a list of the fragment's nodes
64
- * @returns List of nodes
65
- */
66
- get(): ChildNode[];
67
- /**
68
- * Set an identifier for the fragment
69
- *
70
- * _An identifier can be used to uniquely identify a fragment,
71
- * which helps prevent re-rendering in certain scenarios._
72
- * @param identifier Identifier
73
- * @returns Fragment
74
- */
75
- identify(identifier: unknown): Fragment;
76
- /**
77
- * Remove the fragment from the DOM
78
- */
79
- remove(): void;
80
- }
81
- //#endregion
82
- export { FragmentsState as a, FragmentItem as i, FragmentConfiguration as n, FragmentData as r, Fragment as t };