@evgkch/reactive-dom 0.1.0 → 0.2.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 (41) hide show
  1. package/README.md +71 -92
  2. package/dist/create-element.js +2 -2
  3. package/dist/index.d.ts +2 -2
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/list.js +4 -4
  7. package/dist/log.d.ts +9 -14
  8. package/dist/log.d.ts.map +1 -1
  9. package/dist/log.js +20 -78
  10. package/dist/slot.js +4 -4
  11. package/dist/unmount.js +2 -2
  12. package/examples/index.html +4 -4
  13. package/examples/pages/console/index.css +73 -0
  14. package/examples/pages/console/index.html +13 -0
  15. package/examples/pages/console/index.ts +11 -0
  16. package/examples/pages/console/model/state.ts +25 -0
  17. package/examples/pages/console/ui/App.ts +57 -0
  18. package/examples/pages/console/ui/LineItem.ts +13 -0
  19. package/examples/pages/monitor/index.css +297 -0
  20. package/examples/pages/monitor/index.html +13 -0
  21. package/examples/pages/monitor/index.ts +24 -0
  22. package/examples/pages/monitor/model/state.ts +30 -0
  23. package/examples/pages/monitor/ui/App.ts +207 -0
  24. package/examples/pages/monitor/ui/TaskItem.ts +41 -0
  25. package/examples/{stream/styles.css → pages/stream/index.css} +1 -75
  26. package/examples/pages/stream/index.html +13 -0
  27. package/examples/pages/stream/index.ts +15 -0
  28. package/examples/pages/stream/model/state.ts +45 -0
  29. package/examples/pages/stream/ui/App.ts +70 -0
  30. package/examples/pages/stream/ui/LogLine.ts +27 -0
  31. package/examples/shared/lib/index.ts +19 -0
  32. package/examples/{console/styles.css → shared/styles/common.css} +5 -77
  33. package/examples/tsconfig.json +13 -0
  34. package/package.json +10 -8
  35. package/examples/console/app.js +0 -97
  36. package/examples/console/index.html +0 -23
  37. package/examples/monitor/app.js +0 -260
  38. package/examples/monitor/index.html +0 -23
  39. package/examples/monitor/styles.css +0 -425
  40. package/examples/stream/app.js +0 -136
  41. package/examples/stream/index.html +0 -23
@@ -0,0 +1,207 @@
1
+ import * as R from "@evgkch/reactive";
2
+ import * as UI from "@evgkch/reactive-dom";
3
+ import {
4
+ barClass,
5
+ cpu,
6
+ filter,
7
+ fmtUptime,
8
+ mem,
9
+ tasks,
10
+ uptime,
11
+ } from "../model/state.js";
12
+ import type { TaskEntry } from "../model/state.js";
13
+ import { TaskItem } from "./TaskItem.js";
14
+
15
+ export const App = UI.Struct(
16
+ `<div class="monitor">
17
+
18
+ <div class="titlebar">
19
+ <div class="titlebar-left">
20
+ <span class="dot dot-red"></span>
21
+ <span class="dot dot-yellow"></span>
22
+ <span class="dot dot-green"></span>
23
+ <span class="titlebar-title">SYS://TASK_MONITOR</span>
24
+ </div>
25
+ <div class="titlebar-right" data-ref="uptime">UP 00:00:00</div>
26
+ </div>
27
+
28
+ <div class="metrics">
29
+ <div class="metric">
30
+ <div class="metric-label">CPU</div>
31
+ <div class="metric-bar"><div class="metric-fill" data-ref="cpu-bar"></div></div>
32
+ <div class="metric-val" data-ref="cpu-val">0%</div>
33
+ </div>
34
+ <div class="metric">
35
+ <div class="metric-label">MEM</div>
36
+ <div class="metric-bar"><div class="metric-fill" data-ref="mem-bar"></div></div>
37
+ <div class="metric-val" data-ref="mem-val">0%</div>
38
+ </div>
39
+ <div class="metric">
40
+ <div class="metric-label">PROCS</div>
41
+ <div class="metric-bar"><div class="metric-fill" data-ref="procs-bar" style="background:#4488ff"></div></div>
42
+ <div class="metric-val" data-ref="procs-val">0</div>
43
+ </div>
44
+ </div>
45
+
46
+ <div class="input-row">
47
+ <span class="prompt">$</span>
48
+ <input class="new-input" data-ref="input" placeholder="spawn process..." />
49
+ <span class="kbd-hint">↵ enter</span>
50
+ </div>
51
+
52
+ <ul class="task-list" data-ref="list"></ul>
53
+ <p class="empty" data-ref="empty">no processes running</p>
54
+
55
+ <div class="statusbar">
56
+ <div class="status-left" data-ref="stats">
57
+ <span>procs: <span data-ref="total">0</span></span>
58
+ <span>running: <span data-ref="running">0</span></span>
59
+ <span>done: <span data-ref="done-count">0</span></span>
60
+ </div>
61
+ <div class="filters" data-ref="filters">
62
+ <button data-filter="all">all</button>
63
+ <button data-filter="active">running</button>
64
+ <button data-filter="done">done</button>
65
+ </div>
66
+ </div>
67
+
68
+ <div class="hotkeys">
69
+ <div class="hotkey"><kbd>↵</kbd> spawn</div>
70
+ <div class="hotkey"><kbd>1</kbd> all</div>
71
+ <div class="hotkey"><kbd>2</kbd> running</div>
72
+ <div class="hotkey"><kbd>3</kbd> done</div>
73
+ <div class="hotkey"><kbd>⌫</kbd> kill last</div>
74
+ <div class="hotkey"><kbd>ESC</kbd> clear</div>
75
+ </div>
76
+
77
+ </div>`,
78
+ (props, refs, ctx) => {
79
+ const input = refs.input as HTMLInputElement;
80
+
81
+ ctx.list(refs.list, tasks, (item) => ({ item }), TaskItem, {
82
+ onAdd: (el: Element) =>
83
+ el.animate(
84
+ [
85
+ { opacity: 0, transform: "translateX(-8px)" },
86
+ { opacity: 1, transform: "translateX(0)" },
87
+ ],
88
+ 160
89
+ ),
90
+ onRemove: (el: Element, done: () => void) =>
91
+ el
92
+ .animate(
93
+ [
94
+ { opacity: 1, transform: "translateX(0)" },
95
+ { opacity: 0, transform: "translateX(8px)" },
96
+ ],
97
+ 130
98
+ )
99
+ .finished.then(done),
100
+ });
101
+
102
+ ctx.batch(() => {
103
+ const v = cpu.get();
104
+ (refs["cpu-bar"] as HTMLElement).style.width = v + "%";
105
+ refs["cpu-bar"].className = "metric-fill " + barClass(v);
106
+ refs["cpu-val"].textContent = v + "%";
107
+ });
108
+
109
+ ctx.batch(() => {
110
+ const v = mem.get();
111
+ (refs["mem-bar"] as HTMLElement).style.width = v + "%";
112
+ refs["mem-bar"].className = "metric-fill " + barClass(v);
113
+ refs["mem-val"].textContent = v + "%";
114
+ });
115
+
116
+ ctx.batch(() => {
117
+ const total = tasks.length;
118
+ (refs["procs-bar"] as HTMLElement).style.width =
119
+ Math.min((total / 10) * 100, 100) + "%";
120
+ refs["procs-val"].textContent = String(total);
121
+ });
122
+
123
+ ctx.batch(() => {
124
+ refs.uptime.textContent = "UP " + fmtUptime(uptime.get());
125
+ });
126
+
127
+ ctx.batch(() => {
128
+ let running = 0;
129
+ tasks.forEach((t: TaskEntry) => {
130
+ if (!t.done) running++;
131
+ });
132
+ const total = tasks.length;
133
+ const done = total - running;
134
+ refs.total.textContent = String(total);
135
+ refs.running.textContent = String(running);
136
+ refs["done-count"].textContent = String(done);
137
+ (refs.empty as HTMLElement).style.display =
138
+ total === 0 ? "block" : "none";
139
+ });
140
+
141
+ ctx.batch(() => {
142
+ Array.from(refs.filters.querySelectorAll("[data-filter]")).forEach(
143
+ (btn) => {
144
+ btn.className =
145
+ filter.get() === btn.getAttribute("data-filter") ? "active" : "";
146
+ }
147
+ );
148
+ });
149
+
150
+ refs.filters.addEventListener("click", (e: Event) => {
151
+ const f = (e.target as HTMLElement)?.getAttribute?.("data-filter");
152
+ if (f) filter.set(f);
153
+ });
154
+
155
+ function addTask() {
156
+ const text = input.value.trim();
157
+ if (!text) return;
158
+ tasks.push(
159
+ R.Struct({ text, done: false }) as unknown as TaskEntry
160
+ );
161
+ input.value = "";
162
+ }
163
+
164
+ input.addEventListener("keydown", (e: KeyboardEvent) => {
165
+ if (e.key === "Enter") addTask();
166
+ });
167
+
168
+ document.addEventListener("keydown", (e: KeyboardEvent) => {
169
+ const inInput = document.activeElement === input;
170
+
171
+ if (e.key === "Escape") {
172
+ input.value = "";
173
+ input.blur();
174
+ return;
175
+ }
176
+
177
+ if (inInput) return;
178
+
179
+ if (e.key === "1") {
180
+ filter.set("all");
181
+ return;
182
+ }
183
+ if (e.key === "2") {
184
+ filter.set("active");
185
+ return;
186
+ }
187
+ if (e.key === "3") {
188
+ filter.set("done");
189
+ return;
190
+ }
191
+
192
+ if (e.key === "Backspace") {
193
+ for (let i = tasks.length - 1; i >= 0; i--) {
194
+ if (!tasks[i].done) {
195
+ tasks.splice(i, 1);
196
+ break;
197
+ }
198
+ }
199
+ return;
200
+ }
201
+
202
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
203
+ input.focus();
204
+ }
205
+ });
206
+ }
207
+ );
@@ -0,0 +1,41 @@
1
+ import * as UI from "@evgkch/reactive-dom";
2
+ import { filter, tasks } from "../model/state.js";
3
+ import type { TaskEntry } from "../model/state.js";
4
+
5
+ export const TaskItem = UI.List(
6
+ `<li>
7
+ <input type="checkbox" class="task-check" data-ref="check" />
8
+ <span class="task-text" data-ref="text"></span>
9
+ <span class="task-status" data-ref="status"></span>
10
+ <button class="task-remove" data-ref="remove">kill</button>
11
+ </li>`,
12
+ (props: { item: TaskEntry }, refs, ctx) => {
13
+ const check = refs.check as HTMLInputElement;
14
+ const el = refs.el as HTMLElement;
15
+ const removeBtn = refs.remove as HTMLButtonElement;
16
+
17
+ ctx.batch(() => {
18
+ refs.text.textContent = props.item.text;
19
+ check.checked = props.item.done;
20
+ refs.el.className = props.item.done ? "done" : "";
21
+ refs.status.textContent = props.item.done ? "DONE" : "RUNNING";
22
+
23
+ const f = filter.get();
24
+ el.style.display =
25
+ f === "all"
26
+ ? ""
27
+ : f === "active"
28
+ ? props.item.done
29
+ ? "none"
30
+ : ""
31
+ : props.item.done
32
+ ? ""
33
+ : "none";
34
+ });
35
+
36
+ check.onchange = () => {
37
+ props.item.done = check.checked;
38
+ };
39
+ removeBtn.onclick = () => tasks.splice(tasks.indexOf(props.item), 1);
40
+ }
41
+ );
@@ -1,38 +1,4 @@
1
- @import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap");
2
-
3
- *,
4
- *::before,
5
- *::after {
6
- box-sizing: border-box;
7
- margin: 0;
8
- padding: 0;
9
- }
10
-
11
- :root {
12
- --bg: #080808;
13
- --surface: #0f0f0f;
14
- --border: #2a2a2a;
15
- --ink: #d0d0d0;
16
- --muted: #666;
17
- --dim: #444;
18
- --accent: #39ff14;
19
- --red: #ff3333;
20
- --yellow: #ffcc00;
21
- --blue: #4488ff;
22
- }
23
-
24
- body {
25
- font-family: "JetBrains Mono", monospace;
26
- background: var(--bg);
27
- color: var(--ink);
28
- min-height: 100vh;
29
- display: flex;
30
- align-items: center;
31
- justify-content: center;
32
- padding: 2rem 1rem;
33
- font-size: 12px;
34
- line-height: 1.5;
35
- }
1
+ @import url("../../shared/styles/common.css");
36
2
 
37
3
  .panel {
38
4
  width: 560px;
@@ -44,46 +10,6 @@ body {
44
10
  flex-direction: column;
45
11
  }
46
12
 
47
- .titlebar {
48
- display: flex;
49
- align-items: center;
50
- justify-content: space-between;
51
- padding: 0.4rem 0.75rem;
52
- border-bottom: 1px solid var(--border);
53
- background: var(--bg);
54
- }
55
-
56
- .titlebar-left {
57
- display: flex;
58
- align-items: center;
59
- gap: 0.5rem;
60
- }
61
-
62
- .dot {
63
- width: 8px;
64
- height: 8px;
65
- border-radius: 50%;
66
- display: inline-block;
67
- }
68
-
69
- .dot-red { background: var(--red); }
70
- .dot-yellow { background: var(--yellow); }
71
- .dot-green { background: var(--accent); }
72
-
73
- .titlebar-title {
74
- font-size: 11px;
75
- font-weight: 700;
76
- color: var(--ink);
77
- letter-spacing: 0.1em;
78
- margin-left: 0.5rem;
79
- }
80
-
81
- .titlebar-right {
82
- font-size: 10px;
83
- color: var(--muted);
84
- letter-spacing: 0.05em;
85
- }
86
-
87
13
  .stream-toolbar {
88
14
  display: flex;
89
15
  align-items: center;
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Stream — reactive-dom</title>
7
+ <link rel="stylesheet" href="./index.css" />
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="./index.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,15 @@
1
+ import { configureLogging } from "../../shared/lib/index.js";
2
+ import { addRandomLog, logs, levelFilter } from "./model/state.js";
3
+ import { App } from "./ui/App.js";
4
+
5
+ configureLogging();
6
+
7
+ if (typeof document !== "undefined" && document.getElementById("app")) {
8
+ setInterval(addRandomLog, 800);
9
+ }
10
+
11
+ export { App, logs, levelFilter };
12
+
13
+ if (typeof document !== "undefined" && document.getElementById("app")) {
14
+ document.getElementById("app")!.appendChild(App({}));
15
+ }
@@ -0,0 +1,45 @@
1
+ import * as R from "@evgkch/reactive";
2
+
3
+ export interface LogEntry {
4
+ ts: number;
5
+ level: string;
6
+ msg: string;
7
+ }
8
+
9
+ export const levelFilter = R.Value("all");
10
+ export const logs = R.List([]) as unknown as LogEntry[] & { watch(fn: (p: unknown) => void): () => void };
11
+
12
+ export const LEVELS = ["info", "warn", "err"];
13
+ export const MESSAGES = [
14
+ "Connection established",
15
+ "Handshake complete",
16
+ "Buffer overflow risk",
17
+ "Retry attempt 3",
18
+ "Cache miss",
19
+ "Timeout after 2000ms",
20
+ "Invalid payload",
21
+ "Rate limit exceeded",
22
+ "Endpoint unreachable",
23
+ "Auth failed",
24
+ ];
25
+
26
+ export function fmtTime(ts: number): string {
27
+ const d = new Date(ts);
28
+ return (
29
+ String(d.getHours()).padStart(2, "0") +
30
+ ":" +
31
+ String(d.getMinutes()).padStart(2, "0") +
32
+ ":" +
33
+ String(d.getSeconds()).padStart(2, "0") +
34
+ "." +
35
+ String(Math.floor(d.getMilliseconds() / 100)).padStart(1, "0")
36
+ );
37
+ }
38
+
39
+ export function addRandomLog(): void {
40
+ const level = LEVELS[Math.floor(Math.random() * LEVELS.length)];
41
+ const msg = MESSAGES[Math.floor(Math.random() * MESSAGES.length)];
42
+ logs.push(
43
+ R.Struct({ ts: Date.now(), level, msg }) as unknown as LogEntry
44
+ );
45
+ }
@@ -0,0 +1,70 @@
1
+ import * as UI from "@evgkch/reactive-dom";
2
+ import { levelFilter, logs } from "../model/state.js";
3
+ import { LogLine } from "./LogLine.js";
4
+
5
+ export const App = UI.Struct(
6
+ `<div class="panel">
7
+ <div class="titlebar">
8
+ <div class="titlebar-left">
9
+ <span class="dot dot-red"></span>
10
+ <span class="dot dot-yellow"></span>
11
+ <span class="dot dot-green"></span>
12
+ <span class="titlebar-title">SYS://STREAM</span>
13
+ </div>
14
+ <div class="titlebar-right" data-ref="count">0 events</div>
15
+ </div>
16
+ <div class="stream-toolbar">
17
+ <div class="stream-filters" data-ref="filters">
18
+ <button data-level="all">all</button>
19
+ <button data-level="info">info</button>
20
+ <button data-level="warn">warn</button>
21
+ <button data-level="err">err</button>
22
+ </div>
23
+ <button class="stream-clear" data-ref="clear">clear</button>
24
+ </div>
25
+ <ul class="log-list" data-ref="list"></ul>
26
+ <p class="empty-logs" data-ref="empty">waiting for events...</p>
27
+ </div>`,
28
+ (props, refs, ctx) => {
29
+ ctx.list(refs.list, logs, (item) => ({ item }), LogLine, {
30
+ onAdd: (el: Element) => {
31
+ el.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 120 });
32
+ requestAnimationFrame(() => {
33
+ requestAnimationFrame(() => {
34
+ refs.list.scrollTop = refs.list.scrollHeight;
35
+ });
36
+ });
37
+ },
38
+ });
39
+
40
+ function updateCount(): void {
41
+ refs.count.textContent =
42
+ logs.length + " event" + (logs.length !== 1 ? "s" : "");
43
+ (refs.empty as HTMLElement).style.display =
44
+ logs.length === 0 ? "block" : "none";
45
+ }
46
+ updateCount();
47
+ ctx.watch(logs, updateCount);
48
+
49
+ function updateFilters(): void {
50
+ const current = levelFilter.get();
51
+ Array.from(refs.filters.querySelectorAll("[data-level]")).forEach(
52
+ (btn) => {
53
+ btn.className =
54
+ current === btn.getAttribute("data-level") ? "active" : "";
55
+ }
56
+ );
57
+ }
58
+ ctx.batch(updateFilters);
59
+ ctx.watch(levelFilter, updateFilters);
60
+
61
+ refs.filters.addEventListener("click", (e: Event) => {
62
+ const level = (e.target as HTMLElement)?.getAttribute?.("data-level");
63
+ if (level) levelFilter.set(level);
64
+ });
65
+
66
+ refs.clear.addEventListener("click", () => {
67
+ logs.splice(0, logs.length);
68
+ });
69
+ }
70
+ );
@@ -0,0 +1,27 @@
1
+ import * as UI from "@evgkch/reactive-dom";
2
+ import { levelFilter } from "../model/state.js";
3
+ import type { LogEntry } from "../model/state.js";
4
+ import { fmtTime } from "../model/state.js";
5
+
6
+ export const LogLine = UI.List(
7
+ `<li>
8
+ <span class="log-ts" data-ref="ts"></span>
9
+ <span class="log-level" data-ref="level"></span>
10
+ <span class="log-msg" data-ref="msg"></span>
11
+ </li>`,
12
+ (props: { item: LogEntry }, refs, ctx) => {
13
+ function sync(): void {
14
+ const { level, msg, ts } = props.item;
15
+ refs.ts.textContent = fmtTime(ts);
16
+ refs.level.textContent = level.toUpperCase();
17
+ refs.level.className = "log-level " + level;
18
+ refs.msg.textContent = msg;
19
+
20
+ const f = levelFilter.get();
21
+ (refs.el as HTMLElement).style.display =
22
+ f === "all" ? "" : f === level ? "" : "none";
23
+ }
24
+ ctx.batch(sync);
25
+ ctx.watch(levelFilter, sync);
26
+ }
27
+ );
@@ -0,0 +1,19 @@
1
+ import * as R from "@evgkch/reactive";
2
+ import * as UI from "@evgkch/reactive-dom";
3
+
4
+ export function configureLogging(): void {
5
+ if (typeof document !== "undefined" && document.getElementById("app")) {
6
+ R.configure({
7
+ log: {
8
+ logger: {
9
+ log(msg: string, meta?: unknown) {
10
+ console.log(msg, meta ?? "");
11
+ },
12
+ },
13
+ },
14
+ });
15
+ UI.configure({ log: true });
16
+ }
17
+ }
18
+
19
+ export { R, UI };
@@ -34,16 +34,6 @@ body {
34
34
  line-height: 1.5;
35
35
  }
36
36
 
37
- .panel {
38
- width: 560px;
39
- max-width: 100%;
40
- height: 400px;
41
- border: 1px solid var(--border);
42
- background: var(--surface);
43
- display: flex;
44
- flex-direction: column;
45
- }
46
-
47
37
  .titlebar {
48
38
  display: flex;
49
39
  align-items: center;
@@ -84,48 +74,6 @@ body {
84
74
  letter-spacing: 0.05em;
85
75
  }
86
76
 
87
- .output {
88
- flex: 1;
89
- min-height: 0;
90
- overflow-y: scroll;
91
- padding: 0.5rem 0.75rem;
92
- border-bottom: 1px solid var(--border);
93
- }
94
-
95
- .line {
96
- padding: 0.2rem 0;
97
- font-size: 12px;
98
- word-break: break-word;
99
- }
100
-
101
- .line.in {
102
- color: var(--accent);
103
- }
104
-
105
- .line.in::before {
106
- content: "> ";
107
- color: var(--muted);
108
- }
109
-
110
- .line.out {
111
- color: var(--ink);
112
- }
113
-
114
- .line.out::before {
115
- content: " ";
116
- }
117
-
118
- .line.err {
119
- color: var(--red);
120
- }
121
-
122
- .input-row {
123
- display: flex;
124
- align-items: center;
125
- padding: 0 0.75rem;
126
- background: var(--bg);
127
- }
128
-
129
77
  .prompt {
130
78
  color: var(--accent);
131
79
  font-weight: 700;
@@ -134,29 +82,9 @@ body {
134
82
  font-size: 12px;
135
83
  }
136
84
 
137
- .console-input {
138
- flex: 1;
139
- font-family: "JetBrains Mono", monospace;
140
- font-size: 12px;
141
- background: transparent;
142
- border: none;
143
- padding: 0.55rem 0;
144
- color: var(--ink);
145
- outline: none;
146
- caret-color: var(--accent);
147
- }
148
-
149
- .console-input::placeholder {
150
- color: var(--dim);
151
- }
152
-
153
- .empty {
154
- padding: 0.5rem 0;
155
- font-size: 11px;
156
- color: var(--dim);
157
- }
158
-
159
- .empty::before {
160
- content: "// type a command and press Enter";
161
- color: var(--border);
85
+ .input-row {
86
+ display: flex;
87
+ align-items: center;
88
+ padding: 0 0.75rem;
89
+ background: var(--bg);
162
90
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": false,
7
+ "noImplicitAny": false,
8
+ "noEmit": true,
9
+ "skipLibCheck": true,
10
+ "lib": ["ES2020", "DOM"]
11
+ },
12
+ "include": ["**/*.ts"]
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evgkch/reactive-dom",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "DOM bindings for @evgkch/reactive: Struct, List, Slot, ReactiveElement",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -19,19 +19,21 @@
19
19
  ],
20
20
  "scripts": {
21
21
  "build": "tsc",
22
- "build:gh-pages": "node scripts/prepare-gh-pages.js",
23
- "test": "npm run build && node --test test/*.spec.js",
24
- "examples": "serve . -p 5173",
22
+ "build:gh-pages": "npm run build && tsc -p examples --noEmit && vite build",
23
+ "test": "npm run build && node --import tsx --test test/*.spec.js",
24
+ "examples": "vite",
25
+ "examples:build": "vite build",
25
26
  "prepublishOnly": "npm run build"
26
27
  },
27
28
  "peerDependencies": {
28
- "@evgkch/reactive": "^1.0.3"
29
+ "@evgkch/reactive": "^1.1.0"
29
30
  },
30
31
  "devDependencies": {
31
- "@evgkch/reactive": "^1.0.3",
32
+ "@evgkch/reactive": "^1.1.0",
32
33
  "jsdom": "^25.0.1",
33
- "serve": "^14.2.0",
34
- "typescript": "^5.0.0"
34
+ "tsx": "^4.19.0",
35
+ "typescript": "^5.0.0",
36
+ "vite": "^6.0.0"
35
37
  },
36
38
  "author": "Evgenii Kucherenko",
37
39
  "license": "ISC",