jaxs 0.3.1 → 0.4.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 (69) hide show
  1. package/dist/jaxs.d.ts +634 -0
  2. package/dist/jaxs.js +793 -1054
  3. package/dist/jaxs.umd.cjs +1 -0
  4. package/package.json +41 -30
  5. package/.env +0 -1
  6. package/README.md +0 -15
  7. package/bun.lockb +0 -0
  8. package/bundle.ts +0 -5
  9. package/bunfig.toml +0 -0
  10. package/cypress/e2e/add-remove-nested-children.cy.js +0 -39
  11. package/cypress/e2e/add-remove-root-children.cy.js +0 -37
  12. package/cypress/e2e/svg-renders.cy.js +0 -10
  13. package/cypress/jaxs-apps/add-remove-nested-children.html +0 -12
  14. package/cypress/jaxs-apps/add-remove-nested-children.jsx +0 -85
  15. package/cypress/jaxs-apps/add-remove-root-children.html +0 -15
  16. package/cypress/jaxs-apps/add-remove-root-children.jsx +0 -54
  17. package/cypress/jaxs-apps/dist/add-remove-nested-children.afcab974.js +0 -1022
  18. package/cypress/jaxs-apps/dist/add-remove-nested-children.afcab974.js.map +0 -1
  19. package/cypress/jaxs-apps/dist/add-remove-nested-children.html +0 -12
  20. package/cypress/jaxs-apps/dist/add-remove-root-children.3bb9b3f5.js +0 -1665
  21. package/cypress/jaxs-apps/dist/add-remove-root-children.3bb9b3f5.js.map +0 -1
  22. package/cypress/jaxs-apps/dist/add-remove-root-children.fbb4ec9b.js +0 -1011
  23. package/cypress/jaxs-apps/dist/add-remove-root-children.fbb4ec9b.js.map +0 -1
  24. package/cypress/jaxs-apps/dist/add-remove-root-children.html +0 -15
  25. package/cypress/jaxs-apps/dist/svg.04290504.js +0 -644
  26. package/cypress/jaxs-apps/dist/svg.04290504.js.map +0 -1
  27. package/cypress/jaxs-apps/dist/svg.html +0 -11
  28. package/cypress/jaxs-apps/svg.html +0 -11
  29. package/cypress/jaxs-apps/svg.jsx +0 -15
  30. package/cypress/support/commands.js +0 -25
  31. package/cypress/support/e2e.js +0 -20
  32. package/cypress.config.js +0 -10
  33. package/src/app.ts +0 -64
  34. package/src/debugging.js +0 -5
  35. package/src/jaxs.ts +0 -7
  36. package/src/jsx.js +0 -27
  37. package/src/messageBus.ts +0 -70
  38. package/src/navigation/findHref.js +0 -10
  39. package/src/navigation/routeState.js +0 -15
  40. package/src/navigation/setupHistory.js +0 -38
  41. package/src/navigation/setupNavigation.js +0 -25
  42. package/src/navigation.ts +0 -2
  43. package/src/rendering/change/compile.ts +0 -1
  44. package/src/rendering/change/instructions/attributes.ts +0 -81
  45. package/src/rendering/change/instructions/children.ts +0 -127
  46. package/src/rendering/change/instructions/element.ts +0 -49
  47. package/src/rendering/change/instructions/events.ts +0 -51
  48. package/src/rendering/change/instructions/generate.ts +0 -122
  49. package/src/rendering/change/instructions/idMap.js +0 -55
  50. package/src/rendering/change/instructions/node.ts +0 -55
  51. package/src/rendering/change/instructions/text.ts +0 -10
  52. package/src/rendering/change.ts +0 -139
  53. package/src/rendering/dom/attributesAndEvents.ts +0 -33
  54. package/src/rendering/dom/create.ts +0 -68
  55. package/src/rendering/dom/svg.ts +0 -18
  56. package/src/rendering/templates/bound.js +0 -56
  57. package/src/rendering/templates/children.ts +0 -99
  58. package/src/rendering/templates/root.ts +0 -55
  59. package/src/rendering/templates/tag.ts +0 -92
  60. package/src/rendering/templates/text.ts +0 -17
  61. package/src/state/equality.js +0 -36
  62. package/src/state/stores.js +0 -63
  63. package/src/state/testingTypes.js +0 -6
  64. package/src/state.js +0 -89
  65. package/src/types.ts +0 -152
  66. package/src/views/conditionals.jsx +0 -18
  67. package/src/views/link.jsx +0 -5
  68. package/src/views.js +0 -7
  69. package/tsconfig.json +0 -26
@@ -1,49 +0,0 @@
1
- import type { ExpandedElement, InputElement, Instructions } from '../../../types';
2
- import { changeValue } from './generate';
3
- import { compileForAttributes } from './attributes';
4
- import { compileForEvents } from './events';
5
-
6
- export const compileForElement = (
7
- source: ExpandedElement,
8
- target: ExpandedElement,
9
- ) => {
10
- const attributeInstructions = compileForAttributes(source, target);
11
- const eventInstructions = compileForEvents(source, target);
12
- const valueInstructions = compileForInputValue(source, target);
13
-
14
- return attributeInstructions
15
- .concat(eventInstructions)
16
- .concat(valueInstructions);
17
- };
18
-
19
- export const compileForSvg = (
20
- source: ExpandedElement,
21
- target: ExpandedElement,
22
- ) => {
23
- return compileForAttributes(source, target, true);
24
- }
25
-
26
- const compileForInputValue = (
27
- sourceElement: ExpandedElement,
28
- targetElement: ExpandedElement,
29
- ) => {
30
- const instructions = [] as Instructions;
31
- if (sourceElement.tagName !== 'INPUT') {
32
- return instructions;
33
- }
34
-
35
- const source = sourceElement as InputElement;
36
- const target = targetElement as InputElement;
37
-
38
- if (source.value !== target.value) {
39
- instructions.push(
40
- changeValue(
41
- source,
42
- target,
43
- { name: 'value', value: target.value },
44
- ),
45
- );
46
- }
47
-
48
- return instructions;
49
- };
@@ -1,51 +0,0 @@
1
- import type { ExpandedElement, Instructions } from '../../../types';
2
- import { addEvent, removeEvent, updateEvent } from './generate';
3
-
4
- export const compileForEvents = (
5
- source: ExpandedElement,
6
- target: ExpandedElement,
7
- ) => {
8
- const instructions = [] as Instructions;
9
- const sourceEventMaps = source.eventMaps;
10
- const targetEventMaps = target.eventMaps;
11
- const sourceDomEvents = Object.keys(sourceEventMaps);
12
- const targetDomEvents = Object.keys(targetEventMaps);
13
-
14
- sourceDomEvents.forEach((domEvent) => {
15
- const sourceEventMap = sourceEventMaps[domEvent];
16
- const targetEventMap = targetEventMaps[domEvent];
17
-
18
- if (!targetEventMap) {
19
- instructions.push(
20
- removeEvent(source, target, {
21
- name: sourceEventMap.domEvent,
22
- value: sourceEventMap.listener,
23
- }),
24
- );
25
- } else if (targetEventMap.busEvent !== sourceEventMap.busEvent) {
26
- instructions.push(
27
- updateEvent(source, target, {
28
- name: domEvent,
29
- targetValue: targetEventMap.listener,
30
- sourceValue: sourceEventMap.listener,
31
- }),
32
- );
33
- } // else events the same
34
- });
35
-
36
- targetDomEvents.forEach((domEvent) => {
37
- const sourceEventMap = sourceEventMaps[domEvent];
38
- const targetEventMap = targetEventMaps[domEvent];
39
-
40
- if (!sourceEventMap) {
41
- instructions.push(
42
- addEvent(source, target, {
43
- name: targetEventMap.domEvent,
44
- value: targetEventMap.listener,
45
- }),
46
- );
47
- }
48
- });
49
-
50
- return instructions;
51
- };
@@ -1,122 +0,0 @@
1
- import type {
2
- AttributeInstructionData,
3
- Dom,
4
- EventInstructionData,
5
- ExpandedElement,
6
- InputElement,
7
- InsertNodeData,
8
- Instruction,
9
- RemoveInstructionData,
10
- UpdateEventInstructionData,
11
- } from '../../../types';
12
- import { ChangeInstructions } from '../../../types'
13
-
14
- export const changeText = (source: Text, target: Text): Instruction => ({
15
- source,
16
- target,
17
- type: ChangeInstructions.changeText,
18
- data: {},
19
- });
20
-
21
- export const replaceNode = (source: Dom, target: Dom): Instruction => ({
22
- source,
23
- target,
24
- type: ChangeInstructions.replaceNode,
25
- data: {},
26
- });
27
-
28
- export const removeAttribute = (
29
- source: ExpandedElement,
30
- target: ExpandedElement,
31
- data: RemoveInstructionData,
32
- ): Instruction => ({
33
- source,
34
- target,
35
- data,
36
- type: ChangeInstructions.removeAttribute,
37
- });
38
-
39
- export const addAttribute = (
40
- source: ExpandedElement,
41
- target: ExpandedElement,
42
- data: AttributeInstructionData,
43
- ): Instruction => ({
44
- source,
45
- target,
46
- data,
47
- type: ChangeInstructions.addAttribute,
48
- });
49
-
50
- export const updateAttribute = (
51
- source: ExpandedElement,
52
- target: ExpandedElement,
53
- data: AttributeInstructionData,
54
- ): Instruction => ({
55
- source,
56
- target,
57
- data,
58
- type: ChangeInstructions.updateAttribute,
59
- });
60
-
61
- export const removeEvent = (
62
- source: ExpandedElement,
63
- target: ExpandedElement,
64
- data: EventInstructionData,
65
- ): Instruction => ({
66
- source,
67
- target,
68
- data,
69
- type: ChangeInstructions.removeEvent,
70
- });
71
-
72
- export const addEvent = (
73
- source: ExpandedElement,
74
- target: ExpandedElement,
75
- data: EventInstructionData,
76
- ): Instruction => ({
77
- source,
78
- target,
79
- data,
80
- type: ChangeInstructions.addEvent,
81
- });
82
-
83
- export const updateEvent = (
84
- source: ExpandedElement,
85
- target: ExpandedElement,
86
- data: UpdateEventInstructionData,
87
- ): Instruction => ({
88
- source,
89
- target,
90
- data,
91
- type: ChangeInstructions.updateEvent,
92
- });
93
-
94
- export const removeNode = (
95
- source: ExpandedElement,
96
- ) => ({
97
- source,
98
- target: source, // for type crap only
99
- type: ChangeInstructions.removeNode,
100
- data: {},
101
- });
102
-
103
- export const insertNode = (
104
- target: ExpandedElement,
105
- data: InsertNodeData,
106
- ) => ({
107
- target,
108
- source: target, // for type crap only
109
- type: ChangeInstructions.insertNode,
110
- data,
111
- });
112
-
113
- export const changeValue = (
114
- source: InputElement,
115
- target: InputElement,
116
- data: AttributeInstructionData,
117
- ) => ({
118
- source,
119
- target,
120
- type: ChangeInstructions.changeValue,
121
- data,
122
- });
@@ -1,55 +0,0 @@
1
- const nullMatch = { index: -1 }
2
-
3
- export class IdMap {
4
- constructor () {
5
- this.map = {}
6
- }
7
-
8
- populate (list) {
9
- list.forEach((element, i) => {
10
- const id = element.__jsx
11
- if (id) {
12
- this.map[id] = this.map[id] || []
13
- this.map[id].push({
14
- element,
15
- index: i
16
- })
17
- }
18
- })
19
- }
20
-
21
- pullMatch (element) {
22
- const id = element && element.__jsx
23
- if (!id) return nullMatch
24
- if (!(this.map[id] && this.map[id].length)) return nullMatch
25
-
26
- return this.map[id].shift()
27
- }
28
-
29
- clear (element) {
30
- const id = element && element.__jsx
31
- if (!(id && this.map[id] && this.map[id].length)) return
32
-
33
- const matches = this.map[id]
34
- this.map[id] = matches.reduce((collection, possibleMatch) => {
35
- if (possibleMatch.element !== element) collection.push(possibleMatch)
36
- return collection
37
- }, [])
38
- }
39
-
40
- check (element) {
41
- const id = element && element.__jsx
42
- if (!(id && this.map[id])) return false
43
- return this.map[id].length > 0
44
- }
45
-
46
- remaining () {
47
- return Object.values(this.map).flat()
48
- }
49
- }
50
-
51
- export const createIdMap = (list) => {
52
- const map = new IdMap()
53
- map.populate(list)
54
- return map
55
- }
@@ -1,55 +0,0 @@
1
- import type { Dom, ExpandedElement, Instructions } from '../../../types';
2
- import { compileForElement, compileForSvg } from './element';
3
- import { compileForText } from './text';
4
- import { isSvg } from '../../dom/svg'
5
-
6
- enum NodeTypes {
7
- ElementNode = 1,
8
- TextNode = 3,
9
- }
10
-
11
- export const compileForNodeGenerator =
12
- (compileForCollection: any) => (source: Dom, target: Dom) => {
13
- let instructions = [] as Instructions;
14
-
15
- if (source.nodeType === NodeTypes.ElementNode &&
16
- isSvg(source as SVGElement)) {
17
- const sourceElement = source as ExpandedElement;
18
- const targetElement = target as ExpandedElement;
19
- const baseInstructions = compileForSvg(
20
- sourceElement,
21
- targetElement
22
- )
23
-
24
- const childrenInstructions = compileForCollection(
25
- sourceElement.childNodes,
26
- targetElement.childNodes,
27
- sourceElement,
28
- );
29
-
30
- instructions = baseInstructions.concat(childrenInstructions);
31
- } else if (source.nodeType === NodeTypes.ElementNode) {
32
- const sourceElement = source as ExpandedElement;
33
- const targetElement = target as ExpandedElement;
34
-
35
- const baseInstructions = compileForElement(
36
- sourceElement,
37
- targetElement,
38
- );
39
-
40
- const childrenInstructions = compileForCollection(
41
- sourceElement.childNodes,
42
- targetElement.childNodes,
43
- sourceElement,
44
- );
45
-
46
- instructions = baseInstructions.concat(childrenInstructions);
47
- } else if (source.nodeType === NodeTypes.TextNode) {
48
- instructions = compileForText(
49
- source as Text,
50
- target as Text,
51
- );
52
- }
53
-
54
- return instructions;
55
- };
@@ -1,10 +0,0 @@
1
- import type { Instructions } from '../../../types';
2
- import { changeText } from './generate';
3
-
4
- export const compileForText = (source: Text, target: Text) => {
5
- if (source.textContent !== target.textContent) {
6
- return [changeText(source, target)];
7
- }
8
-
9
- return [] as Instructions;
10
- };
@@ -1,139 +0,0 @@
1
- import type {
2
- AttributeInstructionData,
3
- EventInstructionData,
4
- ExpandedElement,
5
- HtmlChildren,
6
- InputElement,
7
- InsertNodeData,
8
- Instruction,
9
- RemoveInstructionData,
10
- UpdateEventInstructionData,
11
- Updater,
12
- } from '../types';
13
- import { ChangeInstructions } from '../types'
14
- import { compileChange } from './change/compile';
15
- // import { debug } from '../debugging';
16
-
17
- export const change = (
18
- source: HtmlChildren,
19
- target: HtmlChildren,
20
- parent: ExpandedElement,
21
- ) => {
22
- const instructions = compileChange(source, target, parent);
23
-
24
- // debug('instructions', instructions.map((instruction) => instruction.type))
25
-
26
- instructions.forEach((instruction) => {
27
- performInstruction(instruction);
28
- });
29
- };
30
-
31
- const performInstruction = (instruction: Instruction) => {
32
- const performer = performers[instruction.type] || noop;
33
- performer(instruction);
34
- };
35
-
36
- const noop: Updater = (_instruction: Instruction) => {};
37
-
38
- const changeText: Updater = (instruction: Instruction) => {
39
- const { source, target } = instruction;
40
- source.nodeValue = target.textContent;
41
- };
42
-
43
- const removeNode: Updater = (instruction: Instruction) => {
44
- const { source } = instruction;
45
- source.remove();
46
- // debug('removeNode called on', source.nodeName)
47
- };
48
-
49
- const insertNode: Updater = (instruction: Instruction) => {
50
- const { target, data } = instruction;
51
- const { parent, index } = data as InsertNodeData;
52
- const sibling = parent.childNodes[index];
53
- if (!sibling) {
54
- parent.appendChild(target);
55
- } else if (sibling && sibling !== target) {
56
- parent.insertBefore(target, sibling);
57
- }
58
- // else case, sibling is target and so it is moving to the same place: no-op.
59
- };
60
-
61
- const replaceNode: Updater = (instruction: Instruction) => {
62
- const { source, target } = instruction;
63
- source.replaceWith(target);
64
- // debug('replaceNode called on', source.nodeName, 'with', target.nodeName)
65
- // debug('parent', source.parentElement)
66
- };
67
-
68
- const removeAttribute: Updater = (instruction: Instruction) => {
69
- const { source, data } = instruction;
70
- const { name, isSvg } = data as RemoveInstructionData;
71
-
72
- if (isSvg) {
73
- (source as SVGElement).removeAttributeNS(null, name)
74
- } else {
75
- (source as ExpandedElement).removeAttribute(name);
76
- }
77
- };
78
-
79
- const addAttribute: Updater = (instruction: Instruction) => {
80
- const { source, data } = instruction;
81
- const { name, value, isSvg } = data as AttributeInstructionData;
82
-
83
- if (isSvg) {
84
- (source as SVGElement).setAttributeNS(null, name, value)
85
- } else {
86
- (source as ExpandedElement).setAttribute(name, value);
87
- }
88
- };
89
-
90
- const updateAttribute: Updater = (instruction: Instruction) => {
91
- addAttribute(instruction);
92
- };
93
-
94
- const removeEvent: Updater = (instruction: Instruction) => {
95
- const data = instruction.data as EventInstructionData;
96
- const source = instruction.source as ExpandedElement;
97
- const { name, value } = data;
98
- (source as ExpandedElement).removeEventListener(name, value);
99
- };
100
-
101
- const addEvent: Updater = (instruction: Instruction) => {
102
- const data = instruction.data as EventInstructionData;
103
- const source = instruction.source as ExpandedElement;
104
- const { name, value } = data;
105
- (source as ExpandedElement).addEventListener(name, value);
106
- };
107
-
108
- const updateEvent: Updater = (instruction: Instruction) => {
109
- const data = instruction.data as UpdateEventInstructionData;
110
- const source = instruction.source as ExpandedElement;
111
-
112
- const { name, sourceValue, targetValue } = data;
113
-
114
- source.removeEventListener(name, sourceValue);
115
- source.addEventListener(name, targetValue);
116
- };
117
-
118
- const changeValue: Updater = (instruction: Instruction) => {
119
- const data = instruction.data as AttributeInstructionData;
120
- const source = instruction.source as InputElement;
121
-
122
- const { value } = data;
123
-
124
- source.value = value;
125
- };
126
-
127
- const performers = {
128
- [ChangeInstructions.changeText]: changeText,
129
- [ChangeInstructions.removeNode]: removeNode,
130
- [ChangeInstructions.insertNode]: insertNode,
131
- [ChangeInstructions.replaceNode]: replaceNode,
132
- [ChangeInstructions.removeAttribute]: removeAttribute,
133
- [ChangeInstructions.addAttribute]: addAttribute,
134
- [ChangeInstructions.updateAttribute]: updateAttribute,
135
- [ChangeInstructions.removeEvent]: removeEvent,
136
- [ChangeInstructions.addEvent]: addEvent,
137
- [ChangeInstructions.updateEvent]: updateEvent,
138
- [ChangeInstructions.changeValue]: changeValue,
139
- };
@@ -1,33 +0,0 @@
1
- import type { Attributes, AttributesAndEvents } from '../../types';
2
-
3
- export const separateAttrsAndEvents = (
4
- combined: Attributes,
5
- defaultValue = '',
6
- ): AttributesAndEvents => {
7
- const attributes: Attributes = {};
8
- const events: Attributes = {};
9
-
10
- for (const key in combined) {
11
- const value = combined[key];
12
- if (key.match(/^on.+/i)) {
13
- const eventKey = key.slice(2).toLowerCase();
14
- events[eventKey] = value;
15
- } else {
16
- attributes[key] = normalizeValueForKey(combined, key, defaultValue);
17
- }
18
- }
19
-
20
- return {
21
- attributes,
22
- events,
23
- };
24
- };
25
-
26
- const normalizeValueForKey = (
27
- object: Attributes,
28
- key: string,
29
- defaultValue = '',
30
- ) => {
31
- if (object[key] === undefined) return defaultValue;
32
- return object[key];
33
- };
@@ -1,68 +0,0 @@
1
- import type {
2
- Attributes,
3
- DomEventPublisher,
4
- EventAttributes,
5
- EventMaps,
6
- ExpandedElement,
7
- InputElement,
8
- RenderKit,
9
- } from '../../types';
10
-
11
- export const setAttributesOnElement = (
12
- element: Element,
13
- attributes: Attributes,
14
- ) => {
15
- for (const key in attributes) {
16
- if (key === '__self') continue;
17
- if (key === 'value') {
18
- (element as InputElement).value = attributes[key];
19
- } else {
20
- element.setAttribute(key, attributes[key]);
21
- }
22
- }
23
- };
24
-
25
- export const setEventsOnElement = (
26
- element: ExpandedElement,
27
- events: EventAttributes,
28
- publish: DomEventPublisher,
29
- ) => {
30
- const eventMaps = {} as EventMaps;
31
-
32
- for (const domEvent in events) {
33
- const eventName = events[domEvent];
34
- const listener = (event: Event) => publish(eventName, event);
35
- element.addEventListener(domEvent, listener);
36
-
37
- eventMaps[domEvent] = {
38
- domEvent: domEvent,
39
- busEvent: eventName,
40
- listener: listener,
41
- };
42
- }
43
-
44
- element.eventMaps = eventMaps;
45
- };
46
-
47
- export const createNode = (type: string, document: Document) => {
48
- document = document || window.document;
49
- return document.createElement(type);
50
- };
51
-
52
- export const createTextNode = (value: string, document: Document) => {
53
- document = document || window.document;
54
- return document.createTextNode(value);
55
- };
56
-
57
- export const createDecoratedNode = (
58
- type: string,
59
- attributes: Attributes,
60
- events: EventAttributes,
61
- renderKit: RenderKit,
62
- ) => {
63
- // deno-lint-ignore no-explicit-any
64
- const dom = createNode(type, renderKit.document) as any as ExpandedElement;
65
- setAttributesOnElement(dom, attributes);
66
- setEventsOnElement(dom, events, renderKit.publish);
67
- return dom;
68
- };
@@ -1,18 +0,0 @@
1
- import type { RenderKit, Attributes, ExpandedElement } from "../../types"
2
-
3
- export const namespace = 'http://www.w3.org/2000/svg'
4
- export const isSvgTag = (tagType: string) => tagType === 'svg'
5
- export const isSvg = (element: SVGElement) => element.namespaceURI === namespace
6
-
7
- export const createSvgNode = (type: string, attributes: Attributes, renderKit: RenderKit) => {
8
- const document = renderKit && renderKit.document || window.document;
9
- const node = document.createElementNS(namespace, type)
10
-
11
- for (const key in attributes) {
12
- if (key === '__self' || key === 'xmlns') continue;
13
- // adding namespace in as first argument makes it not really render!
14
- node.setAttributeNS(null, key, attributes[key]);
15
- }
16
-
17
- return node as unknown as ExpandedElement
18
- }
@@ -1,56 +0,0 @@
1
- import { eventName } from '../../state'
2
- import { change } from '../change'
3
-
4
- const passThroughViewModel = (state) => state
5
- export class Bound {
6
- constructor (TemplateClass, viewModel, subscriptions, attributes) {
7
- this.TemplateClass = TemplateClass
8
- this.viewModel = viewModel || passThroughViewModel
9
- this.attributes = attributes || {}
10
- this.subscriptions = subscriptions
11
- this.dom = []
12
- }
13
-
14
- render (renderKit) {
15
- this.parentElement = renderKit.parent
16
- this.renderKit = renderKit
17
- this.subscribeForRerender()
18
- this.dom = this._render(renderKit)
19
- return this.dom
20
- }
21
-
22
- _render (renderKit) {
23
- const props = {
24
- ...this.attributes,
25
- ...this.viewModel(renderKit.state.value())
26
- }
27
-
28
- const template = this.TemplateClass(props)
29
-
30
- const dom = !template ? [] : template.render(renderKit)
31
- return dom
32
- }
33
-
34
- rerender () {
35
- if (!this.parentElement) {
36
- this.parentElement = this.dom[0] && this.dom[0].parentElement
37
- }
38
- const newDom = this._render(this.renderKit)
39
- change(this.dom, newDom, this.parentElement)
40
-
41
- if (this.parentElement) {
42
- this.dom = Array.from(this.parentElement.childNodes)
43
- }
44
- }
45
-
46
- subscribeForRerender () {
47
- this.subscriptions.forEach((storeName) => {
48
- this.renderKit.subscribe(eventName(storeName), () => this.rerender())
49
- })
50
- }
51
- }
52
-
53
- export const bind = ({ Template, viewModel, subscriptions }) => {
54
- subscriptions = subscriptions || []
55
- return (attributes) => new Bound(Template, viewModel, subscriptions, attributes)
56
- }