diff --git a/src/__tests__/attributes.test.ts b/src/__tests__/attributes.test.ts
index 1fb664d..3d66c0b 100644
--- a/src/__tests__/attributes.test.ts
+++ b/src/__tests__/attributes.test.ts
@@ -34,4 +34,12 @@ describe('attributes.ts', () => {
expect(el.value).toBe('test');
});
+
+ test("doesn't add `mounted` as an attribute", () => {
+ const el = document.createElement('div');
+
+ addAttribute(el, 'mounted', 'test');
+
+ expect(el.hasAttribute('mounted')).toBe(false);
+ });
});
diff --git a/src/__tests__/main.test.ts b/src/__tests__/main.test.ts
deleted file mode 100644
index 8c2109b..0000000
--- a/src/__tests__/main.test.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Component, mount, tags } from '../main';
-
-describe('main', () => {
- test('`null` element', () => {
- const el = document.querySelector('.not-defined');
-
- expect(mount(el, {} as Component)).toBe(undefined);
- });
-
- test('setting an unknown state property', () => {
- const el = document.createElement('div');
-
- expect(() =>
- mount(el, {
- state: { count: 0 },
- view: ({ state }) =>
- tags.div('', { mounted: () => state['unknown']++ }),
- }),
- ).toThrow();
- });
-
- test('setting a state property to the same value', () => {
- const el = document.createElement('div');
-
- expect(() =>
- mount(el, {
- state: { count: 0 },
- view: ({ state }) => tags.div('', { mounted: () => (state.count = 0) }),
- }),
- ).not.toThrow();
- });
-});
diff --git a/src/__tests__/tags.test.ts b/src/__tests__/tags.test.ts
index ce810ab..89ef009 100644
--- a/src/__tests__/tags.test.ts
+++ b/src/__tests__/tags.test.ts
@@ -68,4 +68,12 @@ describe('tags.ts', () => {
expect(el.$tent.attributes['data-bar']).toBe('baz');
expect(el.$tent.attributes['onclick']).toBe(fn);
});
+
+ test('mounted', () => {
+ const fn = jest.fn();
+ const el = createTag(['div', 'test', { mounted: fn }]);
+
+ expect(fn).toHaveBeenCalledTimes(1);
+ expect(fn).toHaveBeenCalledWith({ el });
+ });
});
diff --git a/src/attributes.ts b/src/attributes.ts
index 1529e2e..bafe1db 100644
--- a/src/attributes.ts
+++ b/src/attributes.ts
@@ -1,10 +1,14 @@
-import { type TentNode, type Attrs } from './types';
+import { type TentNode, type Attrs, type TagAttrsValues } from './types';
function addAttribute(
el: TentNode | HTMLElement,
key: string,
- value: string | boolean | number,
+ value: TagAttrsValues,
) {
+ if (key === 'mounted') {
+ return;
+ }
+
if (typeof value === 'boolean') {
if (value) {
el.setAttribute(key, '');
diff --git a/src/tags.ts b/src/tags.ts
index 0edfee3..c8ca138 100644
--- a/src/tags.ts
+++ b/src/tags.ts
@@ -26,6 +26,8 @@ function createTag(context: Context) {
el.append(typeof children === 'number' ? children.toString() : children);
}
+ attributes?.mounted?.({ el });
+
return el;
}
diff --git a/src/types.ts b/src/types.ts
index fc6e146..c16b87d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -23,9 +23,13 @@ export type TentNode = Node &
};
export type Children = string | number | TentNode | (Node | string | Context)[];
-export type Context = [string, Children, object | undefined];
+export type Context = [string, Children, TagAttrs | undefined];
+export type TagAttrsValues = string | boolean | number | Function;
+type TagAttrs = Record & {
+ mounted?: ({ el }: { el: TentNode }) => void;
+};
export type Tags = Record<
string,
- (children: Children, attrs?: object) => TentNode
+ (children: Children, attrs?: TagAttrs) => TentNode
>;
diff --git a/src/walker.ts b/src/walker.ts
index a68a739..fc3dd29 100644
--- a/src/walker.ts
+++ b/src/walker.ts
@@ -19,6 +19,12 @@ function walker(oldNode: TentNode, newNode: TentNode) {
return;
}
+ if (oldNode.$tent == null || newNode.$tent == null) {
+ oldNode.replaceWith(newNode);
+
+ return;
+ }
+
// Remove attributes that are not present in the new node
for (const key in oldNode.$tent.attributes) {
if (newNode.$tent.attributes[key] == null) {