Skip to content

Commit 428cfeb

Browse files
authored
feat wip render components (#18)
* chore: cleanup build * feat: render components * fix: single app builder * fix: live demo * refactor: const out of each loop * chore: rebuild
1 parent cc98f6a commit 428cfeb

13 files changed

+918
-591
lines changed

dist/kasper.js

+164-61
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/kasper.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

live/debug.html

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<title>Debug KasperJs</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1" />
8+
<script src="../dist/kasper.js"></script>
9+
</head>
10+
<body>
11+
<template id="kasper-app">
12+
<h1 class="title" data-title="{{attr}}-something-{{appTitle}}">
13+
{{appTitle}}
14+
</h1>
15+
<app-menu>{{menuTitle}}</app-menu>
16+
<app-content @:title="hello">
17+
<app-template-only></app-template-only>
18+
</app-content>
19+
</template>
20+
<template id="app-menu"> app menu </template>
21+
<template id="app-content">
22+
<h2>{{args.title}}</h2>
23+
<div>{{"app-content"}}</div>
24+
<button @on:click="onClick()">click me</button><span>{{counter}}</span>
25+
</template>
26+
<template id="app-template-only">
27+
<div>template only</div>
28+
template only no class {{22 + 33}}
29+
</template>
30+
<script>
31+
class AppMain extends Component {
32+
appTitle = "Title of the App";
33+
attr = "attrib";
34+
}
35+
36+
class AppMenu extends Component {
37+
menuTitle = "Title of the Menu";
38+
}
39+
40+
class AppContent extends Component {
41+
counter = $state(1);
42+
constructor({ args, ref }) {
43+
super({ args, ref });
44+
console.log(args, ref);
45+
}
46+
onClick = () => {
47+
this.counter.set(this.counter.value + 1);
48+
};
49+
}
50+
51+
const registry = {
52+
"kasper-app": {
53+
selector: "template#kasper-app",
54+
component: AppMain,
55+
},
56+
"app-menu": {
57+
selector: "template#app-menu",
58+
component: AppMenu,
59+
},
60+
"app-content": {
61+
selector: "template#app-content",
62+
component: AppContent,
63+
},
64+
"app-template-only": {
65+
selector: "template#app-template-only",
66+
},
67+
};
68+
kasper.App({
69+
registry,
70+
root: "body",
71+
});
72+
</script>
73+
</body>
74+
</html>

live/demo.html

+11-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
66
<title>Blog with KasperJs</title>
77
<meta name="viewport" content="width=device-width, initial-scale=1" />
8-
<script src="../dist/kasper.min.js"></script>
8+
<script src="../dist/kasper.js"></script>
99
<script src="https://cdn.tailwindcss.com"></script>
1010
<script>
1111
tailwind.config = {
@@ -23,7 +23,8 @@
2323
</script>
2424
</head>
2525
<body>
26-
<template>
26+
<kasper-app></kasper-app>
27+
<template id="kasper-app">
2728
<div class="w-dvw h-dvh flex text-gray-50">
2829
<div class="w-96 flex-none bg-gray-900 p-6 h-full overflow-y-scroll">
2930
<div class="flex flex-col gap-4">
@@ -43,17 +44,17 @@
4344
</div>
4445
<div class="flex-grow bg-gray-700 p-6">
4546
<div @if="post.value && user.value">
46-
<kvoid @let="u = user.value">
47+
<void @let="u = user.value">
4748
<div class="text-lg">Author</div>
4849
<div class="flex flex-col pb-4">
4950
<div class="text-lg font-bold">{{u.name}}</div>
5051
<div class="text-sm text-gray-400">{{u.email}}</div>
5152
</div>
52-
</kvoid>
53-
<kvoid @let="p = post.value">
53+
</void>
54+
<void @let="p = post.value">
5455
<div class="text-2xl font-bold">{{p.title}}</div>
5556
<div class="text-sm text-gray-400">{{p.body}}</div>
56-
</kvoid>
57+
</void>
5758
</div>
5859
</div>
5960
</div>
@@ -80,14 +81,15 @@
8081
return await response.json();
8182
}
8283

83-
class MyTodoApp extends KasperApp {
84+
class TodoApp extends Component {
8485
posts = $state([]);
8586
user = $state(null);
8687
post = $state(null);
8788

8889
$onInit = async () => {
8990
const posts = await fetchPosts();
9091
this.posts.set(posts);
92+
console.log(this.posts);
9193
};
9294

9395
onOpenPost = async (post) => {
@@ -96,7 +98,8 @@
9698
this.user.set(user);
9799
};
98100
}
99-
Kasper(MyTodoApp);
101+
102+
Kasper(TodoApp);
100103
</script>
101104
</body>
102105
</html>

live/index.html

+12-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap"
1010
rel="stylesheet"
1111
/>
12-
<script src="../dist/kasper.js"></script>
12+
<script src="../dist/kasper.min.js"></script>
1313
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.9/ace.js"></script>
1414
<script src="https://cdn.tailwindcss.com"></script>
1515
<script>
@@ -41,7 +41,7 @@ <h4>{{person.profession}}</h4>
4141
<!-- iterating over arrays -->
4242
<h4>Hobbies ({{person.hobbies.length}}):</h4>
4343
<ul class="list-disc">
44-
<li @each="const hobby with index of person.hobbies" class="text-red">
44+
<li @each="hobby with index of person.hobbies" class="text-red">
4545
{{index + 1}}: {{hobby}}
4646
</li>
4747
</ul>
@@ -62,7 +62,7 @@ <h4>Hobbies ({{person.hobbies.length}}):</h4>
6262
</div>
6363
6464
<!-- foreach loop with objects -->
65-
<span @each="const item of Object.entries({a: 1, b: 2, c: 3 })">
65+
<span @each="item of Object.entries({a: 1, b: 2, c: 3 })">
6666
{{item[0]}}:{{item[1]}},
6767
</span>
6868
@@ -75,11 +75,11 @@ <h4>Hobbies ({{person.hobbies.length}}):</h4>
7575
7676
<!-- void elements -->
7777
<div>
78-
<kvoid @let="index = 0">
79-
<kvoid @while="index < 3">
78+
<void @let="index = 0">
79+
<void @while="index < 3">
8080
{{index = index + 1}}
81-
</kvoid>
82-
</kvoid>
81+
</void>
82+
</void>
8383
</div>
8484
8585
<!-- complex expressions -->
@@ -205,11 +205,11 @@ <h3>Try it out!</h3>
205205
entries.alert = function (value) {
206206
alert(value);
207207
};
208-
const node = kasper.transpile(source, entries);
209-
document.getElementById("render").innerHTML = "";
210-
document.getElementById("render").appendChild(node);
211-
212-
// output.setValue(result.split("},{").join("},\n{"));
208+
const node = kasper.transpile(
209+
source,
210+
entries,
211+
document.getElementById("render")
212+
);
213213
});
214214
</script>
215215
</body>

demo/template.html live/template.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ <h1>{{this.user.firstName + this.user.lastName}}</h1>
5252
<input type="email" @on:input="{{(email) => this.email = $args[0]" />
5353

5454
<!-- rendering child content -->
55-
<kvoid @inlet />
55+
<void @inlet />
5656

5757
<!-- templates -->
58-
<kvoid @outlet="my-template" />
59-
<kvoid @template="my-template"> template content </kvoid>
58+
<void @outlet="my-template" />
59+
<void @template="my-template"> template content </void>
6060
</void>

readme.md

+4
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,7 @@ text + list[0] * dict.value;
136136
```
137137
console.log('something');
138138
```
139+
140+
## Todo
141+
142+
- fix state re-render

src/component.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Transpiler } from "./transpiler";
2+
import { KNode } from "./types/nodes";
3+
4+
interface ComponentArgs {
5+
args: Record<string, any>;
6+
ref?: Node;
7+
transpiler?: Transpiler;
8+
}
9+
10+
export class Component {
11+
args: Record<string, any> = {};
12+
ref?: Node;
13+
transpiler?: Transpiler;
14+
$onInit = () => {};
15+
$onRender = () => {};
16+
$onChanges = () => {};
17+
$onDestroy = () => {};
18+
19+
constructor(props?: ComponentArgs) {
20+
if (!props) {
21+
this.args = {};
22+
return;
23+
}
24+
if (props.args) {
25+
this.args = props.args || {};
26+
}
27+
if (props.ref) {
28+
this.ref = props.ref;
29+
}
30+
if (props.transpiler) {
31+
this.transpiler = props.transpiler;
32+
}
33+
}
34+
35+
$doRender() {
36+
if (!this.transpiler) {
37+
return;
38+
}
39+
//this.transpiler?.createComponent(this);
40+
}
41+
}
42+
43+
export type KasperEntity = Component | Record<string, any> | null | undefined;
44+
45+
export type ComponentClass = { new (args?: ComponentArgs): Component };
46+
export interface ComponentRegistry {
47+
[tagName: string]: {
48+
selector: string;
49+
component: ComponentClass;
50+
template: Element;
51+
nodes: KNode[];
52+
};
53+
}

0 commit comments

Comments
 (0)