creo 0.0.3-dev → 0.1.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.
- package/README.md +5 -1
- package/dist/functional/assert.d.ts +1 -0
- package/dist/functional/key.d.ts +2 -0
- package/dist/functional/maybe.d.ts +6 -0
- package/dist/functional/maybe_promise.d.ts +1 -0
- package/dist/functional/shallow_equal.d.ts +2 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +1373 -0
- package/dist/index.js.map +26 -0
- package/dist/internal/engine.d.ts +18 -0
- package/dist/internal/internal_view.d.ts +38 -0
- package/dist/internal/orchestrator.d.ts +16 -0
- package/dist/internal/wildcard.d.ts +1 -0
- package/dist/public/app.d.ts +19 -0
- package/dist/public/event_handle.d.ts +32 -0
- package/dist/public/primitive.d.ts +20 -0
- package/dist/public/primitives/primitives.d.ts +318 -0
- package/dist/public/state.d.ts +37 -0
- package/dist/public/store.d.ts +35 -0
- package/dist/public/view.d.ts +37 -0
- package/dist/render/canvas_render.d.ts +1 -0
- package/dist/render/html_render.d.ts +35 -0
- package/dist/render/json_render.d.ts +17 -0
- package/dist/render/render_interface.d.ts +7 -0
- package/dist/render/stream_render.d.ts +1 -0
- package/dist/render/string_render.d.ts +17 -0
- package/dist/structures/indexed_list.d.ts +46 -0
- package/dist/structures/list.d.ts +68 -0
- package/package.json +24 -7
- package/bun.lockb +0 -0
- package/index.html +0 -13
- package/src/main.ts +0 -13
- package/src/record/record.spec.ts +0 -146
- package/src/record/record.ts +0 -101
- package/src/style.css +0 -96
- package/src/tools/isRecordLike.spec.ts +0 -29
- package/src/tools/isRecordLike.ts +0 -3
- package/src/tools/optional.ts +0 -25
- package/src/ui/component.ts +0 -1
- package/src/ui/index.ts +0 -0
- package/src/ui/prop.ts +0 -13
- package/src/ui/state.ts +0 -0
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -23
package/index.html
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>Vite + TS</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="app"></div>
|
|
11
|
-
<script type="module" src="/src/main.ts"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|
package/src/main.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import "./style.css";
|
|
2
|
-
|
|
3
|
-
document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
|
|
4
|
-
<div>
|
|
5
|
-
<h1>Vite + TypeScript</h1>
|
|
6
|
-
<div class="card">
|
|
7
|
-
<button id="counter" type="button"></button>
|
|
8
|
-
</div>
|
|
9
|
-
<p class="read-the-docs">
|
|
10
|
-
Click on the Vite and TypeScript logos to learn more
|
|
11
|
-
</p>
|
|
12
|
-
</div>
|
|
13
|
-
`;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "bun:test";
|
|
2
|
-
import { record, onDidUpdate } from "./record";
|
|
3
|
-
|
|
4
|
-
test("Can define objects", () => {
|
|
5
|
-
const obj = record({
|
|
6
|
-
hello: "world",
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
expect(obj).toEqual({ hello: "world" });
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test("Notifies on object updates", async () => {
|
|
13
|
-
const obj = record({
|
|
14
|
-
hello: "world",
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
await expect(
|
|
18
|
-
new Promise((resolve) => {
|
|
19
|
-
onDidUpdate(obj, (updated) => resolve(updated));
|
|
20
|
-
|
|
21
|
-
obj.hello = "new world";
|
|
22
|
-
}),
|
|
23
|
-
).resolves.toEqual({
|
|
24
|
-
hello: "new world",
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("Notifies on object updates even if the listener was set after the change", async () => {
|
|
29
|
-
const obj = record({
|
|
30
|
-
hello: "world",
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
obj.hello = "new world";
|
|
34
|
-
|
|
35
|
-
await expect(
|
|
36
|
-
new Promise((resolve) => {
|
|
37
|
-
onDidUpdate(obj, (updated) => resolve(updated));
|
|
38
|
-
}),
|
|
39
|
-
).resolves.toEqual({
|
|
40
|
-
hello: "new world",
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("Implies updates immediately", async () => {
|
|
45
|
-
const obj = record({
|
|
46
|
-
hello: {
|
|
47
|
-
world: "foo",
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
expect(obj).toEqual({
|
|
52
|
-
hello: {
|
|
53
|
-
world: "foo",
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
obj.hello.world = "new";
|
|
58
|
-
|
|
59
|
-
expect(obj).toEqual({
|
|
60
|
-
hello: {
|
|
61
|
-
world: "new",
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("Handles nested object updates", async () => {
|
|
67
|
-
const obj = record({
|
|
68
|
-
hello: {
|
|
69
|
-
world: "foo",
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
obj.hello.world = "new";
|
|
74
|
-
|
|
75
|
-
await expect(
|
|
76
|
-
new Promise((resolve) => {
|
|
77
|
-
onDidUpdate(obj, (updated) => resolve(updated));
|
|
78
|
-
}),
|
|
79
|
-
).resolves.toEqual({
|
|
80
|
-
hello: {
|
|
81
|
-
world: "new",
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("Can unsubscribe from updates", async () => {
|
|
87
|
-
const obj = record({
|
|
88
|
-
hello: {
|
|
89
|
-
world: "foo",
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const unsubscribe = onDidUpdate(obj, (_updated) => {
|
|
94
|
-
throw Error("cannot get here");
|
|
95
|
-
});
|
|
96
|
-
// If you delete this line, the test gets broken:
|
|
97
|
-
unsubscribe();
|
|
98
|
-
|
|
99
|
-
obj.hello.world = "new";
|
|
100
|
-
|
|
101
|
-
await expect(
|
|
102
|
-
new Promise((resolve) => {
|
|
103
|
-
onDidUpdate(obj, (updated) => resolve(updated));
|
|
104
|
-
}),
|
|
105
|
-
).resolves.toEqual({
|
|
106
|
-
hello: {
|
|
107
|
-
world: "new",
|
|
108
|
-
},
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test("Supports arrays", async () => {
|
|
113
|
-
const obj = record({
|
|
114
|
-
hello: {
|
|
115
|
-
world: ["this", "is", "array"],
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
obj.hello.world.sort();
|
|
120
|
-
|
|
121
|
-
await expect(
|
|
122
|
-
new Promise((resolve) => {
|
|
123
|
-
onDidUpdate(obj, (updated) => resolve(JSON.stringify(updated)));
|
|
124
|
-
}),
|
|
125
|
-
).resolves.toEqual('{"hello":{"world":["array","is","this"]}}');
|
|
126
|
-
|
|
127
|
-
obj.hello.world.push("123");
|
|
128
|
-
|
|
129
|
-
await expect(
|
|
130
|
-
new Promise((resolve) => {
|
|
131
|
-
onDidUpdate(obj, (updated) => resolve(JSON.stringify(updated)));
|
|
132
|
-
}),
|
|
133
|
-
).resolves.toEqual('{"hello":{"world":["array","is","this","123"]}}');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test("Supports iterable", async () => {
|
|
137
|
-
const obj = record(["hello", "world"]);
|
|
138
|
-
|
|
139
|
-
function iterate(...args: string[]) {
|
|
140
|
-
const [a, b] = args;
|
|
141
|
-
expect(a).toBe("hello");
|
|
142
|
-
expect(b).toBe("world");
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
iterate(...obj);
|
|
146
|
-
});
|
package/src/record/record.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ideas:
|
|
3
|
-
* [x] didUpdate support
|
|
4
|
-
* [x] Proxy proxifies all children as well
|
|
5
|
-
* [ ] Keep track on updates, until there are no users on the old state
|
|
6
|
-
* [ ] Support symbol iterator
|
|
7
|
-
* [ ] Add js dispose tracker to automatically close listeners
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { isRecordLike } from "../tools/isRecordLike";
|
|
11
|
-
|
|
12
|
-
type Record<T extends object> = T;
|
|
13
|
-
type Wildcard = any;
|
|
14
|
-
type RecordDidChangeListener<T extends object> = (record: Record<T>) => void;
|
|
15
|
-
|
|
16
|
-
const didUpdateMap: WeakMap<
|
|
17
|
-
Record<Wildcard>,
|
|
18
|
-
Set<RecordDidChangeListener<Wildcard>>
|
|
19
|
-
> = new WeakMap();
|
|
20
|
-
|
|
21
|
-
const scheduledUpdatesNotifiers: Set<Record<Wildcard>> = new Set();
|
|
22
|
-
let shouldScheduleMicrotask = true;
|
|
23
|
-
function queuedNotifier() {
|
|
24
|
-
shouldScheduleMicrotask = true;
|
|
25
|
-
scheduledUpdatesNotifiers.forEach((record) => {
|
|
26
|
-
const listeners = didUpdateMap.get(record);
|
|
27
|
-
if (!listeners) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
listeners.forEach((listener) => {
|
|
31
|
-
listener(record);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function recordDidUpdate<T extends object>(record: Record<T>) {
|
|
36
|
-
scheduledUpdatesNotifiers.add(record);
|
|
37
|
-
shouldScheduleMicrotask && queueMicrotask(queuedNotifier);
|
|
38
|
-
shouldScheduleMicrotask = false;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function creoRecord<TNode extends object, T extends object>(
|
|
42
|
-
rootRecord: Record<TNode>,
|
|
43
|
-
value: T,
|
|
44
|
-
): Record<T> {
|
|
45
|
-
return new Proxy(value, {
|
|
46
|
-
// @ts-ignore we override `get` to improve typing
|
|
47
|
-
get<K extends keyof T>(target: T, property: K): T[K] {
|
|
48
|
-
const val = target[property];
|
|
49
|
-
if (isRecordLike(val)) {
|
|
50
|
-
// @ts-ignore we proxify all nested objects / arrays to ensure correct behaviour
|
|
51
|
-
return creoRecord(rootRecord, val);
|
|
52
|
-
}
|
|
53
|
-
return val;
|
|
54
|
-
},
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
set<K, TNewValue>(target: T, property: K, newValue: TNewValue) {
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
target[property] = newValue;
|
|
59
|
-
recordDidUpdate(rootRecord);
|
|
60
|
-
return true;
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function record<TNode extends object>(value: TNode): Record<TNode> {
|
|
66
|
-
const rootRecord = new Proxy(value, {
|
|
67
|
-
// @ts-ignore we override `get` to improve typing
|
|
68
|
-
get<K extends keyof T>(target: T, property: K): T[K] {
|
|
69
|
-
const val = target[property];
|
|
70
|
-
if (isRecordLike(val)) {
|
|
71
|
-
// @ts-ignore we proxify all nested objects / arrays to ensure correct behaviour
|
|
72
|
-
return creoRecord(rootRecord, val);
|
|
73
|
-
}
|
|
74
|
-
return val;
|
|
75
|
-
},
|
|
76
|
-
// @ts-ignore
|
|
77
|
-
set<K, TNewValue>(target: T, property: K, newValue: TNewValue) {
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
target[property] = newValue;
|
|
80
|
-
recordDidUpdate(rootRecord);
|
|
81
|
-
return true;
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
didUpdateMap.set(rootRecord, new Set());
|
|
85
|
-
return rootRecord;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function onDidUpdate<T extends object>(
|
|
89
|
-
record: Record<T>,
|
|
90
|
-
listener: (record: Record<T>) => void,
|
|
91
|
-
): () => void {
|
|
92
|
-
const listeners = didUpdateMap.get(record);
|
|
93
|
-
if (!listeners) {
|
|
94
|
-
// Safe-guard: Essentialy this path cannot happen
|
|
95
|
-
throw new TypeError(`Record ${record} was created without listener`);
|
|
96
|
-
}
|
|
97
|
-
listeners.add(listener);
|
|
98
|
-
return function unsubscribe() {
|
|
99
|
-
listeners.delete(listener);
|
|
100
|
-
};
|
|
101
|
-
}
|
package/src/style.css
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
-
line-height: 1.5;
|
|
4
|
-
font-weight: 400;
|
|
5
|
-
|
|
6
|
-
color-scheme: light dark;
|
|
7
|
-
color: rgba(255, 255, 255, 0.87);
|
|
8
|
-
background-color: #242424;
|
|
9
|
-
|
|
10
|
-
font-synthesis: none;
|
|
11
|
-
text-rendering: optimizeLegibility;
|
|
12
|
-
-webkit-font-smoothing: antialiased;
|
|
13
|
-
-moz-osx-font-smoothing: grayscale;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
a {
|
|
17
|
-
font-weight: 500;
|
|
18
|
-
color: #646cff;
|
|
19
|
-
text-decoration: inherit;
|
|
20
|
-
}
|
|
21
|
-
a:hover {
|
|
22
|
-
color: #535bf2;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
body {
|
|
26
|
-
margin: 0;
|
|
27
|
-
display: flex;
|
|
28
|
-
place-items: center;
|
|
29
|
-
min-width: 320px;
|
|
30
|
-
min-height: 100vh;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
h1 {
|
|
34
|
-
font-size: 3.2em;
|
|
35
|
-
line-height: 1.1;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
#app {
|
|
39
|
-
max-width: 1280px;
|
|
40
|
-
margin: 0 auto;
|
|
41
|
-
padding: 2rem;
|
|
42
|
-
text-align: center;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.logo {
|
|
46
|
-
height: 6em;
|
|
47
|
-
padding: 1.5em;
|
|
48
|
-
will-change: filter;
|
|
49
|
-
transition: filter 300ms;
|
|
50
|
-
}
|
|
51
|
-
.logo:hover {
|
|
52
|
-
filter: drop-shadow(0 0 2em #646cffaa);
|
|
53
|
-
}
|
|
54
|
-
.logo.vanilla:hover {
|
|
55
|
-
filter: drop-shadow(0 0 2em #3178c6aa);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.card {
|
|
59
|
-
padding: 2em;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.read-the-docs {
|
|
63
|
-
color: #888;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
button {
|
|
67
|
-
border-radius: 8px;
|
|
68
|
-
border: 1px solid transparent;
|
|
69
|
-
padding: 0.6em 1.2em;
|
|
70
|
-
font-size: 1em;
|
|
71
|
-
font-weight: 500;
|
|
72
|
-
font-family: inherit;
|
|
73
|
-
background-color: #1a1a1a;
|
|
74
|
-
cursor: pointer;
|
|
75
|
-
transition: border-color 0.25s;
|
|
76
|
-
}
|
|
77
|
-
button:hover {
|
|
78
|
-
border-color: #646cff;
|
|
79
|
-
}
|
|
80
|
-
button:focus,
|
|
81
|
-
button:focus-visible {
|
|
82
|
-
outline: 4px auto -webkit-focus-ring-color;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
@media (prefers-color-scheme: light) {
|
|
86
|
-
:root {
|
|
87
|
-
color: #213547;
|
|
88
|
-
background-color: #ffffff;
|
|
89
|
-
}
|
|
90
|
-
a:hover {
|
|
91
|
-
color: #747bff;
|
|
92
|
-
}
|
|
93
|
-
button {
|
|
94
|
-
background-color: #f9f9f9;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "bun:test";
|
|
2
|
-
import { isRecordLike } from "./isRecordLike";
|
|
3
|
-
|
|
4
|
-
test("Handles objects", () => {
|
|
5
|
-
expect(isRecordLike({})).toBe(true);
|
|
6
|
-
expect(isRecordLike({ foo: "bar" })).toBe(true);
|
|
7
|
-
expect(isRecordLike(new String())).toBe(true);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
test("Handles arrays", () => {
|
|
11
|
-
expect(isRecordLike([])).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("Fails nulls", () => {
|
|
15
|
-
expect(isRecordLike(null)).toBe(false);
|
|
16
|
-
expect(isRecordLike(undefined)).toBe(false);
|
|
17
|
-
expect(isRecordLike(NaN)).toBe(false);
|
|
18
|
-
expect(isRecordLike(0)).toBe(false);
|
|
19
|
-
expect(isRecordLike(false)).toBe(false);
|
|
20
|
-
expect(isRecordLike("")).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("Fails primitives", () => {
|
|
24
|
-
expect(isRecordLike(1)).toBe(false);
|
|
25
|
-
expect(isRecordLike("foo")).toBe(false);
|
|
26
|
-
// @ts-ignore
|
|
27
|
-
expect(isRecordLike()).toBe(false);
|
|
28
|
-
expect(isRecordLike(Symbol.for("test"))).toBe(false);
|
|
29
|
-
});
|
package/src/tools/optional.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export type None = null;
|
|
2
|
-
export type Just<T> = T;
|
|
3
|
-
export type Optional<T> = Just<T> | None;
|
|
4
|
-
|
|
5
|
-
export function isJust<T>(v: Optional<T>): v is Just<T> {
|
|
6
|
-
return v != null;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function isNone<T>(v: Optional<T>): v is None {
|
|
10
|
-
return v == null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function unwrap<T>(v: Optional<T>): Just<T> {
|
|
14
|
-
if (isJust(v)) {
|
|
15
|
-
return v;
|
|
16
|
-
}
|
|
17
|
-
throw new TypeError("Optional is none");
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function orDefault<T, K>(v: Optional<T>, alternative: K) {
|
|
21
|
-
if (isJust(v)) {
|
|
22
|
-
return v;
|
|
23
|
-
}
|
|
24
|
-
return alternative;
|
|
25
|
-
}
|
package/src/ui/component.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function
|
package/src/ui/index.ts
DELETED
|
File without changes
|
package/src/ui/prop.ts
DELETED
package/src/ui/state.ts
DELETED
|
File without changes
|
package/src/vite-env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|
package/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
|
|
9
|
-
/* Bundler mode */
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"resolveJsonModule": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"noEmit": true,
|
|
15
|
-
|
|
16
|
-
/* Linting */
|
|
17
|
-
"strict": true,
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true
|
|
21
|
-
},
|
|
22
|
-
"include": ["src"]
|
|
23
|
-
}
|