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.
Files changed (44) hide show
  1. package/README.md +5 -1
  2. package/dist/functional/assert.d.ts +1 -0
  3. package/dist/functional/key.d.ts +2 -0
  4. package/dist/functional/maybe.d.ts +6 -0
  5. package/dist/functional/maybe_promise.d.ts +1 -0
  6. package/dist/functional/shallow_equal.d.ts +2 -0
  7. package/dist/index.d.ts +20 -0
  8. package/dist/index.js +1373 -0
  9. package/dist/index.js.map +26 -0
  10. package/dist/internal/engine.d.ts +18 -0
  11. package/dist/internal/internal_view.d.ts +38 -0
  12. package/dist/internal/orchestrator.d.ts +16 -0
  13. package/dist/internal/wildcard.d.ts +1 -0
  14. package/dist/public/app.d.ts +19 -0
  15. package/dist/public/event_handle.d.ts +32 -0
  16. package/dist/public/primitive.d.ts +20 -0
  17. package/dist/public/primitives/primitives.d.ts +318 -0
  18. package/dist/public/state.d.ts +37 -0
  19. package/dist/public/store.d.ts +35 -0
  20. package/dist/public/view.d.ts +37 -0
  21. package/dist/render/canvas_render.d.ts +1 -0
  22. package/dist/render/html_render.d.ts +35 -0
  23. package/dist/render/json_render.d.ts +17 -0
  24. package/dist/render/render_interface.d.ts +7 -0
  25. package/dist/render/stream_render.d.ts +1 -0
  26. package/dist/render/string_render.d.ts +17 -0
  27. package/dist/structures/indexed_list.d.ts +46 -0
  28. package/dist/structures/list.d.ts +68 -0
  29. package/package.json +24 -7
  30. package/bun.lockb +0 -0
  31. package/index.html +0 -13
  32. package/src/main.ts +0 -13
  33. package/src/record/record.spec.ts +0 -146
  34. package/src/record/record.ts +0 -101
  35. package/src/style.css +0 -96
  36. package/src/tools/isRecordLike.spec.ts +0 -29
  37. package/src/tools/isRecordLike.ts +0 -3
  38. package/src/tools/optional.ts +0 -25
  39. package/src/ui/component.ts +0 -1
  40. package/src/ui/index.ts +0 -0
  41. package/src/ui/prop.ts +0 -13
  42. package/src/ui/state.ts +0 -0
  43. package/src/vite-env.d.ts +0 -1
  44. 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
- });
@@ -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
- });
@@ -1,3 +0,0 @@
1
- export function isRecordLike<T, K extends object>(value: T | K): value is K {
2
- return (typeof value === "object" || Array.isArray(value)) && value != null;
3
- }
@@ -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
- }
@@ -1 +0,0 @@
1
- function
package/src/ui/index.ts DELETED
File without changes
package/src/ui/prop.ts DELETED
@@ -1,13 +0,0 @@
1
- export const $prop = {
2
- ofString: () => {
3
- return {
4
-
5
- }
6
- },
7
- ofNumber: (prop: number) => {
8
-
9
- },
10
- of<T>: (prop: T) => {
11
-
12
- }
13
- }
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
- }