elegance-js 2.1.22 → 2.1.24
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/dist/client/effect.d.ts +27 -0
- package/dist/client/effect.js +37 -0
- package/dist/client/eventListener.d.ts +39 -0
- package/dist/client/eventListener.js +52 -0
- package/dist/client/loadHook.d.ts +34 -0
- package/dist/client/loadHook.js +52 -0
- package/dist/client/observer.d.ts +36 -0
- package/dist/client/observer.js +66 -0
- package/dist/client/runtime.d.ts +105 -0
- package/dist/client/runtime.js +620 -0
- package/dist/client/state.d.ts +40 -0
- package/dist/client/state.js +110 -0
- package/dist/compilation/compiler.d.ts +155 -0
- package/dist/compilation/compiler.js +1153 -0
- package/dist/components/ClientComponent.d.ts +22 -0
- package/dist/components/ClientComponent.js +55 -0
- package/dist/components/Link.d.ts +16 -1
- package/dist/components/Link.js +22 -0
- package/dist/components/Portal.d.ts +2 -0
- package/dist/components/Portal.js +2 -0
- package/dist/elements/element.d.ts +87 -0
- package/dist/elements/element.js +33 -0
- package/dist/elements/element_list.d.ts +7 -0
- package/dist/elements/element_list.js +65 -0
- package/dist/elements/raw.d.ts +14 -0
- package/dist/elements/raw.js +78 -0
- package/dist/elements/specific_props.d.ts +750 -0
- package/dist/global.d.ts +221 -327
- package/dist/index.d.ts +15 -3
- package/dist/index.js +11 -0
- package/dist/server/layout.d.ts +34 -3
- package/dist/server/layout.js +6 -0
- package/dist/server/log.d.ts +12 -0
- package/dist/server/log.js +64 -0
- package/dist/server/page.d.ts +32 -0
- package/dist/server/page.js +6 -0
- package/dist/server/runtime.d.ts +6 -0
- package/dist/server/runtime.js +72 -0
- package/dist/server/server.d.ts +103 -11
- package/dist/server/server.js +709 -0
- package/package.json +13 -13
- package/scripts/bootstrap.js +37 -273
- package/scripts/bootstrap_files/elegance.txt +40 -0
- package/scripts/bootstrap_files/index.txt +3 -0
- package/scripts/bootstrap_files/layout.txt +46 -0
- package/scripts/bootstrap_files/middleware.txt +18 -0
- package/scripts/bootstrap_files/page.txt +123 -0
- package/scripts/bootstrap_files/route.txt +6 -0
- package/scripts/elegance_dev.ts +40 -0
- package/scripts/elegance_prod.ts +40 -0
- package/scripts/elegance_static.ts +24 -0
- package/scripts/prod.js +9 -26
- package/scripts/run.js +13 -0
- package/scripts/static.js +13 -0
- package/dist/build.d.ts +0 -2
- package/dist/build.mjs +0 -202
- package/dist/client/client.d.ts +0 -1
- package/dist/client/client.mjs +0 -574
- package/dist/client/processPageElements.d.ts +0 -1
- package/dist/client/processPageElements.mjs +0 -117
- package/dist/client/render.d.ts +0 -1
- package/dist/client/render.mjs +0 -40
- package/dist/client/watcher.d.ts +0 -1
- package/dist/client/watcher.mjs +0 -26
- package/dist/compilation/compilation.d.ts +0 -139
- package/dist/compilation/compilation.mjs +0 -746
- package/dist/compilation/compiler_process.d.ts +0 -3
- package/dist/compilation/compiler_process.mjs +0 -102
- package/dist/compilation/dynamic_compiler.d.ts +0 -10
- package/dist/compilation/dynamic_compiler.mjs +0 -93
- package/dist/compile_docs.mjs +0 -34
- package/dist/components/Link.mjs +0 -65
- package/dist/global.mjs +0 -0
- package/dist/helpers/ObjectAttributeType.d.ts +0 -7
- package/dist/helpers/ObjectAttributeType.mjs +0 -11
- package/dist/helpers/camelToKebab.d.ts +0 -1
- package/dist/helpers/camelToKebab.mjs +0 -6
- package/dist/index.mjs +0 -3
- package/dist/internal/deprecate.d.ts +0 -1
- package/dist/internal/deprecate.mjs +0 -7
- package/dist/log.d.ts +0 -10
- package/dist/log.mjs +0 -38
- package/dist/server/generateHTMLTemplate.d.ts +0 -12
- package/dist/server/generateHTMLTemplate.mjs +0 -41
- package/dist/server/layout.mjs +0 -19
- package/dist/server/loadHook.d.ts +0 -30
- package/dist/server/loadHook.mjs +0 -50
- package/dist/server/observe.d.ts +0 -19
- package/dist/server/observe.mjs +0 -16
- package/dist/server/render.d.ts +0 -5
- package/dist/server/render.mjs +0 -61
- package/dist/server/server.mjs +0 -429
- package/dist/server/state.d.ts +0 -61
- package/dist/server/state.mjs +0 -146
- package/dist/shared/bindServerElements.mjs +0 -3
- package/dist/shared/serverElements.d.ts +0 -11
- package/dist/shared/serverElements.mjs +0 -164
- package/scripts/dev.js +0 -33
- package/scripts/export.js +0 -20
- package/scripts/ts-arc-dev.js +0 -9
- package/scripts/ts-arc-prod.js +0 -9
- /package/dist/{compile_docs.d.ts → elements/specific_props.js} +0 -0
- /package/dist/{shared/bindServerElements.d.ts → global.js} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ServerSubject } from "./state";
|
|
2
|
+
import type { ClientSubject } from "./runtime";
|
|
3
|
+
type EffectCallback<D extends readonly ServerSubject<unknown>[]> = (...dependencies: {
|
|
4
|
+
[K in keyof D]: ClientSubject<D[K]["value"]>;
|
|
5
|
+
}) => any;
|
|
6
|
+
declare class Effect<const T extends readonly ServerSubject<unknown>[]> {
|
|
7
|
+
callback: EffectCallback<T>;
|
|
8
|
+
dependencies: string[];
|
|
9
|
+
id: string;
|
|
10
|
+
constructor(callback: EffectCallback<T>, dependencies: [...T], id: string);
|
|
11
|
+
serialize(): string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a browser-side callback that is called upon navigation to a given page.
|
|
15
|
+
* It may return a cleanup function which will be called when the Effect goes out of scope.
|
|
16
|
+
* If it is declared within a layout, is it pathname scoped, and it's cleanupFunction will be called when the layout is no longer active.
|
|
17
|
+
* Eg. Navigation from /recipes/cake to /recipes will call the cleanup of /recipes/cake's page, and it's layout, but not /recipes, since it's pathname is in the new pathname we're navigating to.
|
|
18
|
+
*
|
|
19
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
20
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
21
|
+
*
|
|
22
|
+
* @param callback The browser-side contextless code the Effect will run.
|
|
23
|
+
* @param dependencies A dependency of state that will be passed into this Effect
|
|
24
|
+
*/
|
|
25
|
+
declare function effect<const T extends readonly ServerSubject<unknown>[]>(callback: EffectCallback<T>, dependencies: [...T]): void;
|
|
26
|
+
export { effect, Effect };
|
|
27
|
+
export type { EffectCallback, };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { compilerStore } from "../compilation/compiler.js";
|
|
2
|
+
class Effect {
|
|
3
|
+
constructor(callback, dependencies, id) {
|
|
4
|
+
this.callback = callback;
|
|
5
|
+
this.dependencies = dependencies.map(d => d.id);
|
|
6
|
+
this.id = id;
|
|
7
|
+
}
|
|
8
|
+
serialize() {
|
|
9
|
+
let result = "{";
|
|
10
|
+
result += `callback:${this.callback.toString()},`;
|
|
11
|
+
result += `dependencies:[${this.dependencies.map(d => `"${d}"`).join(",")}],`;
|
|
12
|
+
result += `id:"${this.id}",`;
|
|
13
|
+
result += "}";
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a browser-side callback that is called upon navigation to a given page.
|
|
19
|
+
* It may return a cleanup function which will be called when the Effect goes out of scope.
|
|
20
|
+
* If it is declared within a layout, is it pathname scoped, and it's cleanupFunction will be called when the layout is no longer active.
|
|
21
|
+
* Eg. Navigation from /recipes/cake to /recipes will call the cleanup of /recipes/cake's page, and it's layout, but not /recipes, since it's pathname is in the new pathname we're navigating to.
|
|
22
|
+
*
|
|
23
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
24
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
25
|
+
*
|
|
26
|
+
* @param callback The browser-side contextless code the Effect will run.
|
|
27
|
+
* @param dependencies A dependency of state that will be passed into this Effect
|
|
28
|
+
*/
|
|
29
|
+
function effect(callback, dependencies) {
|
|
30
|
+
const store = compilerStore.getStore();
|
|
31
|
+
if (!store)
|
|
32
|
+
throw new Error("Illegal invocation of effect(). Ensure that the effect() function is only called inside components, and never at the top-level of a page or layout.");
|
|
33
|
+
const id = store.generateId();
|
|
34
|
+
const effect = new Effect(callback, dependencies, id);
|
|
35
|
+
store.addClientToken(effect);
|
|
36
|
+
}
|
|
37
|
+
export { effect, Effect };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { EleganceElement, SpecialElementOption } from "../elements/element";
|
|
2
|
+
import { ServerSubject } from "./state";
|
|
3
|
+
import { ClientSubject } from "./runtime";
|
|
4
|
+
type SetEvent<E extends Event = Event, T extends EventTarget = EventTarget> = E & {
|
|
5
|
+
target: T;
|
|
6
|
+
currentTarget: T;
|
|
7
|
+
};
|
|
8
|
+
type ToClientTuple<T extends readonly ServerSubject<any>[]> = {
|
|
9
|
+
[K in keyof T]: T[K] extends ServerSubject<infer V> ? ClientSubject<V> : never;
|
|
10
|
+
};
|
|
11
|
+
type EventListenerCallback<T extends readonly ServerSubject<any>[]> = (event: SetEvent, ...dependencies: ToClientTuple<T>) => void;
|
|
12
|
+
declare class EventListenerOption extends SpecialElementOption {
|
|
13
|
+
id: string;
|
|
14
|
+
constructor(id: string);
|
|
15
|
+
mutate(element: EleganceElement<any, any>, optionName: string): void;
|
|
16
|
+
serialize(optionName: string, elementKey: string): string;
|
|
17
|
+
}
|
|
18
|
+
declare class EventListener<T extends readonly ServerSubject<any>[]> {
|
|
19
|
+
id: string;
|
|
20
|
+
callback: EventListenerCallback<T>;
|
|
21
|
+
dependencies: string[];
|
|
22
|
+
constructor(id: string, callback: EventListenerCallback<T>, dependencies: [...T]);
|
|
23
|
+
serialize(): string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates, an event listener, which is a callback that is called when the event that it is attached to, is triggered.
|
|
27
|
+
* If you intend to use the same eventListener many times, declare it once, and use the returned special element option as the reference to it.
|
|
28
|
+
* This ships less code to the browser.
|
|
29
|
+
*
|
|
30
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
31
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
32
|
+
*
|
|
33
|
+
* @param callback The function to be called when the event that this eventListener is attached to is triggered.
|
|
34
|
+
* @param dependencies An array of ServerSubject's that should be passed into the callback when it is run.
|
|
35
|
+
* @returns A special element option that you can use as a value on an option of an EleganceElement.
|
|
36
|
+
*/
|
|
37
|
+
declare function eventListener<T extends readonly ServerSubject<any>[]>(callback: EventListenerCallback<T>, dependencies: [...T]): EventListenerOption;
|
|
38
|
+
export { eventListener, EventListenerOption, EventListener };
|
|
39
|
+
export type { EventListenerCallback, SetEvent, ToClientTuple };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SpecialElementOption } from "../elements/element.js";
|
|
2
|
+
import { compilerStore } from "../compilation/compiler.js";
|
|
3
|
+
class EventListenerOption extends SpecialElementOption {
|
|
4
|
+
constructor(id) {
|
|
5
|
+
super();
|
|
6
|
+
this.id = id;
|
|
7
|
+
}
|
|
8
|
+
mutate(element, optionName) {
|
|
9
|
+
// this cast is fine
|
|
10
|
+
delete element.options[optionName];
|
|
11
|
+
}
|
|
12
|
+
serialize(optionName, elementKey) {
|
|
13
|
+
let result = "{";
|
|
14
|
+
result += `option:"${optionName.toLowerCase()}",`;
|
|
15
|
+
result += `key:"${elementKey}",`;
|
|
16
|
+
result += `id:"${this.id}"`;
|
|
17
|
+
result += "}";
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class EventListener {
|
|
22
|
+
constructor(id, callback, dependencies) {
|
|
23
|
+
this.id = id;
|
|
24
|
+
this.callback = callback;
|
|
25
|
+
this.dependencies = dependencies.map(d => d.id);
|
|
26
|
+
}
|
|
27
|
+
serialize() {
|
|
28
|
+
return `{id:\"${this.id}\",callback:${this.callback.toString()},dependencies:[${this.dependencies.map(d => `"${d}"`).join(",")}]}`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates, an event listener, which is a callback that is called when the event that it is attached to, is triggered.
|
|
33
|
+
* If you intend to use the same eventListener many times, declare it once, and use the returned special element option as the reference to it.
|
|
34
|
+
* This ships less code to the browser.
|
|
35
|
+
*
|
|
36
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
37
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
38
|
+
*
|
|
39
|
+
* @param callback The function to be called when the event that this eventListener is attached to is triggered.
|
|
40
|
+
* @param dependencies An array of ServerSubject's that should be passed into the callback when it is run.
|
|
41
|
+
* @returns A special element option that you can use as a value on an option of an EleganceElement.
|
|
42
|
+
*/
|
|
43
|
+
function eventListener(callback, dependencies) {
|
|
44
|
+
const store = compilerStore.getStore();
|
|
45
|
+
if (!store)
|
|
46
|
+
throw new Error("Illegal invocation of eventListener(). Ensure that the eventListener() function is only called inside components, and never at the top-level of a page or layout.");
|
|
47
|
+
const id = store.generateId();
|
|
48
|
+
const listener = new EventListener(id, callback, dependencies);
|
|
49
|
+
store.addClientToken(listener);
|
|
50
|
+
return new EventListenerOption(id);
|
|
51
|
+
}
|
|
52
|
+
export { eventListener, EventListenerOption, EventListener };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ServerSubject } from "./state";
|
|
2
|
+
import type { ClientSubject } from "./runtime";
|
|
3
|
+
declare enum LoadHookKind {
|
|
4
|
+
LAYOUT_LOADHOOK = 0,
|
|
5
|
+
PAGE_LOADHOOK = 1
|
|
6
|
+
}
|
|
7
|
+
type LoadHookCleanupFunction = (() => void);
|
|
8
|
+
type LoadHookCallback<D extends readonly ServerSubject<unknown>[]> = (...dependencies: {
|
|
9
|
+
[K in keyof D]: ClientSubject<D[K]["value"]>;
|
|
10
|
+
}) => LoadHookCleanupFunction | void;
|
|
11
|
+
declare class LoadHook<const T extends readonly ServerSubject<unknown>[]> {
|
|
12
|
+
pathname?: string;
|
|
13
|
+
kind: LoadHookKind;
|
|
14
|
+
callback: LoadHookCallback<T>;
|
|
15
|
+
dependencies: string[];
|
|
16
|
+
id: string;
|
|
17
|
+
constructor(callback: LoadHookCallback<T>, dependencies: [...T], kind: LoadHookKind, id: string, pathname?: string);
|
|
18
|
+
serialize(): string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a browser-side callback that is called upon navigation to a given page.
|
|
22
|
+
* It may return a cleanup function which will be called when the loadHook goes out of scope.
|
|
23
|
+
* If it is declared within a layout, is it pathname scoped, and it's cleanupFunction will be called when the layout is no longer active.
|
|
24
|
+
* Eg. Navigation from /recipes/cake to /recipes will call the cleanup of /recipes/cake's page, and it's layout, but not /recipes, since it's pathname is in the new pathname we're navigating to.
|
|
25
|
+
*
|
|
26
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
27
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
28
|
+
*
|
|
29
|
+
* @param callback The browser-side contextless code the loadHook will run.
|
|
30
|
+
* @param dependencies A dependency of state that will be passed into this loadHook
|
|
31
|
+
*/
|
|
32
|
+
declare function loadHook<const T extends readonly ServerSubject<unknown>[]>(callback: LoadHookCallback<T>, dependencies: [...T]): void;
|
|
33
|
+
export { loadHook, LoadHook };
|
|
34
|
+
export type { LoadHookCallback, LoadHookCleanupFunction, LoadHookKind, };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { compilerStore } from "../compilation/compiler.js";
|
|
2
|
+
var LoadHookKind;
|
|
3
|
+
(function (LoadHookKind) {
|
|
4
|
+
LoadHookKind[LoadHookKind["LAYOUT_LOADHOOK"] = 0] = "LAYOUT_LOADHOOK";
|
|
5
|
+
LoadHookKind[LoadHookKind["PAGE_LOADHOOK"] = 1] = "PAGE_LOADHOOK";
|
|
6
|
+
})(LoadHookKind || (LoadHookKind = {}));
|
|
7
|
+
;
|
|
8
|
+
class LoadHook {
|
|
9
|
+
constructor(callback, dependencies, kind, id, pathname) {
|
|
10
|
+
this.pathname = pathname;
|
|
11
|
+
this.callback = callback;
|
|
12
|
+
this.kind = kind;
|
|
13
|
+
this.dependencies = dependencies.map(d => d.id);
|
|
14
|
+
this.id = id;
|
|
15
|
+
}
|
|
16
|
+
serialize() {
|
|
17
|
+
let result = "{";
|
|
18
|
+
result += `callback:${this.callback.toString()},`;
|
|
19
|
+
result += `dependencies:[${this.dependencies.map(d => `"${d}"`).join(",")}],`;
|
|
20
|
+
result += `id:"${this.id}",`;
|
|
21
|
+
result += `kind:${this.kind}`;
|
|
22
|
+
if (this.kind === LoadHookKind.LAYOUT_LOADHOOK && this.pathname) {
|
|
23
|
+
result += `,pathname:"${this.pathname}"`;
|
|
24
|
+
}
|
|
25
|
+
result += "}";
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a browser-side callback that is called upon navigation to a given page.
|
|
31
|
+
* It may return a cleanup function which will be called when the loadHook goes out of scope.
|
|
32
|
+
* If it is declared within a layout, is it pathname scoped, and it's cleanupFunction will be called when the layout is no longer active.
|
|
33
|
+
* Eg. Navigation from /recipes/cake to /recipes will call the cleanup of /recipes/cake's page, and it's layout, but not /recipes, since it's pathname is in the new pathname we're navigating to.
|
|
34
|
+
*
|
|
35
|
+
* **IMPORTANT**: The callback is *browser-code*, and thus does not have any context of your page.ts or layout.ts file.
|
|
36
|
+
* The callback function is sent *literally* to the browser, as-is.
|
|
37
|
+
*
|
|
38
|
+
* @param callback The browser-side contextless code the loadHook will run.
|
|
39
|
+
* @param dependencies A dependency of state that will be passed into this loadHook
|
|
40
|
+
*/
|
|
41
|
+
function loadHook(callback, dependencies) {
|
|
42
|
+
const store = compilerStore.getStore();
|
|
43
|
+
if (!store)
|
|
44
|
+
throw new Error("Illegal invocation of loadHook(). Ensure that the loadHook() function is only called inside components, and never at the top-level of a page or layout.");
|
|
45
|
+
const isLayoutLoadHook = store.compilationContext.kind === "layout";
|
|
46
|
+
const loadHookKind = isLayoutLoadHook === true ? LoadHookKind.LAYOUT_LOADHOOK : LoadHookKind.PAGE_LOADHOOK;
|
|
47
|
+
const pathname = loadHookKind === LoadHookKind.LAYOUT_LOADHOOK ? store.compilationContext.pathname : undefined;
|
|
48
|
+
const id = store.generateId();
|
|
49
|
+
const loadHook = new LoadHook(callback, dependencies, loadHookKind, id, pathname);
|
|
50
|
+
store.addClientToken(loadHook);
|
|
51
|
+
}
|
|
52
|
+
export { loadHook, LoadHook };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { EleganceElement, SpecialElementOption } from "../elements/element";
|
|
2
|
+
import { ServerSubject } from "./state";
|
|
3
|
+
import { ClientSubject } from "./runtime";
|
|
4
|
+
type ObserverCallback<T extends readonly ServerSubject<unknown>[]> = (this: HTMLElement, ...dependencies: {
|
|
5
|
+
[K in keyof T]: ClientSubject<T[K]["value"]>["value"];
|
|
6
|
+
}) => string | boolean | number | Record<string, unknown>;
|
|
7
|
+
declare class ObserverOption extends SpecialElementOption {
|
|
8
|
+
id: string;
|
|
9
|
+
constructor(id: string);
|
|
10
|
+
mutate(element: EleganceElement<any, any>, optionName: string): void;
|
|
11
|
+
serialize(optionName: string, elementKey: string): string;
|
|
12
|
+
}
|
|
13
|
+
declare class ServerObserver<const T extends readonly ServerSubject<unknown>[]> {
|
|
14
|
+
id: string;
|
|
15
|
+
callback: ObserverCallback<T>;
|
|
16
|
+
dependencies: string[];
|
|
17
|
+
constructor(id: string, callback: ObserverCallback<T>, dependencies: [...T]);
|
|
18
|
+
serialize(): string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create an observer.
|
|
22
|
+
*
|
|
23
|
+
* [Read More](https://elegance.js.org/observers)
|
|
24
|
+
* @param callbackOrSubject A callback to call whenever any of the `dependencies` changes.
|
|
25
|
+
* @param dependencies An array of dependencies to watch.
|
|
26
|
+
* @returns A special element option you attach to any attribute of an element.
|
|
27
|
+
*/
|
|
28
|
+
declare function observer<T extends ServerSubject<unknown>>(subject: T): ObserverOption;
|
|
29
|
+
declare function observer<const T extends readonly ServerSubject<unknown>[]>(callback: ObserverCallback<T>, dependencies: [...T]): ObserverOption;
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @returns The HTML Element this observer is attached to.
|
|
33
|
+
*/
|
|
34
|
+
declare const getSelf: () => HTMLElement;
|
|
35
|
+
export { observer, ServerObserver, ObserverOption, getSelf, };
|
|
36
|
+
export type { ObserverCallback, };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { SpecialElementOption } from "../elements/element.js";
|
|
2
|
+
import { compilerStore } from "../compilation/compiler.js";
|
|
3
|
+
class ObserverOption extends SpecialElementOption {
|
|
4
|
+
constructor(id) {
|
|
5
|
+
super();
|
|
6
|
+
this.id = id;
|
|
7
|
+
}
|
|
8
|
+
mutate(element, optionName) {
|
|
9
|
+
delete element.options[optionName];
|
|
10
|
+
}
|
|
11
|
+
serialize(optionName, elementKey) {
|
|
12
|
+
let result = "{";
|
|
13
|
+
result += `option:"${optionName}",`;
|
|
14
|
+
result += `key:"${elementKey}",`;
|
|
15
|
+
result += `id:"${this.id}"`;
|
|
16
|
+
result += "}";
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class ServerObserver {
|
|
21
|
+
constructor(id, callback, dependencies) {
|
|
22
|
+
this.id = id;
|
|
23
|
+
this.callback = callback;
|
|
24
|
+
this.dependencies = dependencies.map(d => d.id);
|
|
25
|
+
}
|
|
26
|
+
serialize() {
|
|
27
|
+
let result = "{";
|
|
28
|
+
result += `id:"${this.id}",`;
|
|
29
|
+
result += `callback:${this.callback.toString()},`;
|
|
30
|
+
result += `dependencies:[${this.dependencies.map(d => `"${d}"`).join(",")}],`;
|
|
31
|
+
result += "}";
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function observer(callbackOrSubject, dependencies) {
|
|
36
|
+
const store = compilerStore.getStore();
|
|
37
|
+
if (!store) {
|
|
38
|
+
throw new Error("Illegal invocation of observer(). Ensure that the observer() function is only called inside components, and never at the top-level of a page or layout.");
|
|
39
|
+
}
|
|
40
|
+
let callback;
|
|
41
|
+
let deps;
|
|
42
|
+
if (dependencies) {
|
|
43
|
+
callback = callbackOrSubject;
|
|
44
|
+
deps = dependencies;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const subject = callbackOrSubject;
|
|
48
|
+
callback = (s) => `${s.value}`;
|
|
49
|
+
deps = [subject];
|
|
50
|
+
}
|
|
51
|
+
const id = store.generateId();
|
|
52
|
+
const listener = new ServerObserver(id, callback, deps);
|
|
53
|
+
store.addClientToken(listener);
|
|
54
|
+
return new ObserverOption(id);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @returns The HTML Element this observer is attached to.
|
|
59
|
+
*/
|
|
60
|
+
const getSelf = function () {
|
|
61
|
+
// this is just a stub, the implementation exists only in the browser,
|
|
62
|
+
// but we need typescript to sh
|
|
63
|
+
//@ts-ignore
|
|
64
|
+
return "CLIENT_SIDE_FUNCTION";
|
|
65
|
+
};
|
|
66
|
+
export { observer, ServerObserver, ObserverOption, getSelf, };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { EventListener, EventListenerCallback } from "./eventListener";
|
|
2
|
+
import type { LoadHook } from "./loadHook";
|
|
3
|
+
import type { ServerObserver } from "./observer";
|
|
4
|
+
import type { ServerSubject } from "./state";
|
|
5
|
+
import type { Effect } from "./effect";
|
|
6
|
+
/**
|
|
7
|
+
* A ServerSubject that has been serialized, shipped to the browser, and re-created as it's final form.
|
|
8
|
+
*
|
|
9
|
+
* Setting the `value` of this ClientSubject will trigger it's observers callbacks.
|
|
10
|
+
*
|
|
11
|
+
* To listen for changes in `value`, you may call the `observe()` method.
|
|
12
|
+
*/
|
|
13
|
+
declare class ClientSubject<T> {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
private _value;
|
|
16
|
+
private readonly observers;
|
|
17
|
+
constructor(id: string, value: T);
|
|
18
|
+
get value(): T;
|
|
19
|
+
set value(newValue: T);
|
|
20
|
+
/**
|
|
21
|
+
* Manually trigger each of this subject's observers, with the subject's current value.
|
|
22
|
+
*
|
|
23
|
+
* Useful if you're mutating for example fields of an object, or pushing to an array.
|
|
24
|
+
*/
|
|
25
|
+
triggerObservers(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Add a new observer to this subject, `callback` is called whenever the value setter is called on this subject.
|
|
28
|
+
*
|
|
29
|
+
* Note: if an ID is already in use it's callback will just be overwritten with whatever you give it.
|
|
30
|
+
*
|
|
31
|
+
* Note: this triggers `callback` with the current value of this subject.
|
|
32
|
+
*
|
|
33
|
+
* @param id The unique id of this observer
|
|
34
|
+
* @param callback Called whenever the value of this subject changes.
|
|
35
|
+
*/
|
|
36
|
+
observe(id: string, callback: (newValue: T) => void): void;
|
|
37
|
+
/**
|
|
38
|
+
* Remove an observer from this subject.
|
|
39
|
+
* @param id The unique id of the observer.
|
|
40
|
+
*/
|
|
41
|
+
unobserve(id: string): void;
|
|
42
|
+
}
|
|
43
|
+
declare class StateManager {
|
|
44
|
+
private readonly subjects;
|
|
45
|
+
constructor();
|
|
46
|
+
loadValues(values: ServerSubject<any>[], doOverwrite?: boolean): void;
|
|
47
|
+
get(id: string): ClientSubject<any> | undefined;
|
|
48
|
+
getAll(ids: string[]): Array<ClientSubject<any>>;
|
|
49
|
+
}
|
|
50
|
+
type ClientEventListenerOption = {
|
|
51
|
+
/** The html attribute name this option should be attached to */
|
|
52
|
+
option: string;
|
|
53
|
+
/** The key of the element this option should be attached to. */
|
|
54
|
+
key: string;
|
|
55
|
+
/** The event listener id this option is referencing. */
|
|
56
|
+
id: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* An event listener after it has been generated on the server, processed into pagedata, and reconstructed on the client.
|
|
60
|
+
*/
|
|
61
|
+
declare class ClientEventListener {
|
|
62
|
+
id: string;
|
|
63
|
+
callback: EventListenerCallback<any>;
|
|
64
|
+
dependencies: string[];
|
|
65
|
+
constructor(id: string, callback: EventListenerCallback<any>, depencencies: string[]);
|
|
66
|
+
call(ev: Event): void;
|
|
67
|
+
}
|
|
68
|
+
declare class EventListenerManager {
|
|
69
|
+
private readonly eventListeners;
|
|
70
|
+
constructor();
|
|
71
|
+
loadValues(serverEventListeners: EventListener<any>[], doOverride?: boolean): void;
|
|
72
|
+
hookCallbacks(eventListenerOptions: ClientEventListenerOption[]): void;
|
|
73
|
+
get(id: string): ClientEventListener | undefined;
|
|
74
|
+
}
|
|
75
|
+
type ClientObserverOption = {
|
|
76
|
+
/** The html attribute name this option should be attached to */
|
|
77
|
+
option: string;
|
|
78
|
+
/** The key of the element this option should be attached to. */
|
|
79
|
+
key: string;
|
|
80
|
+
/** The event listener id this option is referencing. */
|
|
81
|
+
id: string;
|
|
82
|
+
};
|
|
83
|
+
declare class ObserverManager {
|
|
84
|
+
private readonly clientObservers;
|
|
85
|
+
constructor();
|
|
86
|
+
loadValues(serverObservers: ServerObserver<any>[], doOverride?: boolean): void;
|
|
87
|
+
hookCallbacks(observerOptions: ClientObserverOption[]): void;
|
|
88
|
+
/**
|
|
89
|
+
* Take the results of ServerSubject.generateObserverNode(), replace their HTML placeins for text nodes, and turn those into observers.
|
|
90
|
+
*/
|
|
91
|
+
transformSubjectObserverNodes(): void;
|
|
92
|
+
}
|
|
93
|
+
declare class EffectManager {
|
|
94
|
+
private activeEffects;
|
|
95
|
+
private cleanupProcedures;
|
|
96
|
+
loadValues(effects: Effect<any>[]): void;
|
|
97
|
+
}
|
|
98
|
+
declare class LoadHookManager {
|
|
99
|
+
private cleanupProcedures;
|
|
100
|
+
private activeLoadHooks;
|
|
101
|
+
constructor();
|
|
102
|
+
loadValues(loadHooks: LoadHook<any>[]): void;
|
|
103
|
+
callCleanupFunctions(): void;
|
|
104
|
+
}
|
|
105
|
+
export { ClientSubject, StateManager, ObserverManager, LoadHookManager, EventListenerManager, EffectManager, };
|