@manyducks.co/dolla 2.0.0-alpha.3 → 2.0.0-alpha.31
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 +31 -951
- package/dist/core/batch.d.ts +17 -0
- package/dist/core/context.d.ts +94 -0
- package/dist/core/dolla.d.ts +161 -0
- package/dist/core/markup.d.ts +91 -0
- package/dist/core/nodes/dom.d.ts +13 -0
- package/dist/core/nodes/html.d.ts +39 -0
- package/dist/core/nodes/observer.d.ts +30 -0
- package/dist/core/nodes/outlet.d.ts +19 -0
- package/dist/core/nodes/portal.d.ts +22 -0
- package/dist/core/nodes/repeat.d.ts +36 -0
- package/dist/core/nodes/view.d.ts +92 -0
- package/dist/core/ref.d.ts +29 -0
- package/dist/core/state.d.ts +126 -0
- package/dist/core/stats.d.ts +31 -0
- package/dist/core/store.d.ts +62 -0
- package/dist/core/symbols.d.ts +7 -0
- package/dist/index.d.ts +18 -11
- package/dist/index.js +1157 -1159
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/jsx-dev-runtime.js +2 -2
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +3 -3
- package/dist/jsx-runtime.js +2 -2
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/markup-D1i09ddt.js +1563 -0
- package/dist/markup-D1i09ddt.js.map +1 -0
- package/dist/modules/http.d.ts +5 -5
- package/dist/modules/i18n.d.ts +129 -0
- package/dist/modules/router.d.ts +37 -48
- package/dist/typeChecking.d.ts +2 -2
- package/dist/types.d.ts +12 -13
- package/dist/utils.d.ts +14 -2
- package/dist/views/default-crash-view.d.ts +1 -1
- package/dist/views/passthrough.d.ts +2 -2
- package/docs/http.md +29 -0
- package/docs/i18n.md +38 -0
- package/docs/index.md +10 -0
- package/docs/router.md +77 -0
- package/docs/setup.md +31 -0
- package/docs/state.md +141 -0
- package/docs/stores.md +62 -0
- package/docs/views.md +308 -0
- package/index.d.ts +2 -2
- package/notes/TODO.md +6 -0
- package/notes/context-vars.md +21 -0
- package/notes/readme-scratch.md +222 -0
- package/notes/route-middleware.md +42 -0
- package/notes/scratch.md +195 -7
- package/notes/stores.md +73 -0
- package/package.json +12 -14
- package/tests/{signals.test.js → state.test.js} +6 -6
- package/vite.config.js +0 -10
- package/dist/markup.d.ts +0 -100
- package/dist/modules/dolla.d.ts +0 -111
- package/dist/modules/language.d.ts +0 -41
- package/dist/modules/render.d.ts +0 -17
- package/dist/nodes/cond.d.ts +0 -26
- package/dist/nodes/html.d.ts +0 -26
- package/dist/nodes/observer.d.ts +0 -29
- package/dist/nodes/outlet.d.ts +0 -22
- package/dist/nodes/portal.d.ts +0 -19
- package/dist/nodes/repeat.d.ts +0 -34
- package/dist/nodes/text.d.ts +0 -19
- package/dist/passthrough-DrtCifRF.js +0 -1228
- package/dist/passthrough-DrtCifRF.js.map +0 -1
- package/dist/signals.d.ts +0 -101
- package/dist/view.d.ts +0 -50
- /package/dist/{routing.d.ts → modules/router.utils.d.ts} +0 -0
- /package/dist/{routing.test.d.ts → modules/router.utils.test.d.ts} +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Dolla } from "./dolla.js";
|
|
2
|
+
/**
|
|
3
|
+
* Batches DOM updates; reads before writes.
|
|
4
|
+
*/
|
|
5
|
+
export declare class Batch {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(dolla: Dolla);
|
|
8
|
+
/**
|
|
9
|
+
* Queues a callback that runs before the next batch of writes.
|
|
10
|
+
*/
|
|
11
|
+
read(callback: () => void): void;
|
|
12
|
+
/**
|
|
13
|
+
* Queues a callback to run in the next render batch.
|
|
14
|
+
* Always put DOM mutations in a write callback when possible to help Dolla batch them efficiently.
|
|
15
|
+
*/
|
|
16
|
+
write(callback: () => void, key?: string): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Emitter } from "@manyducks.co/emitter";
|
|
2
|
+
import type { Store, StoreFactory } from "./store";
|
|
3
|
+
import type { Dolla } from "./dolla";
|
|
4
|
+
interface ContextEmitterEvents {
|
|
5
|
+
[eventName: string | symbol]: [ContextEvent<any>];
|
|
6
|
+
}
|
|
7
|
+
export interface ElementContext {
|
|
8
|
+
/**
|
|
9
|
+
* The root Dolla instance this element belongs to.
|
|
10
|
+
*/
|
|
11
|
+
root: Dolla;
|
|
12
|
+
/**
|
|
13
|
+
* Storage for context variables.
|
|
14
|
+
*/
|
|
15
|
+
data: Record<string | symbol, unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Event emitter for this context.
|
|
18
|
+
*/
|
|
19
|
+
emitter: Emitter<ContextEmitterEvents>;
|
|
20
|
+
/**
|
|
21
|
+
* Stores attached to this context.
|
|
22
|
+
*/
|
|
23
|
+
stores: Map<string, Store<any, any>>;
|
|
24
|
+
/**
|
|
25
|
+
* A reference to the parent context.
|
|
26
|
+
*/
|
|
27
|
+
parent?: ElementContext;
|
|
28
|
+
/**
|
|
29
|
+
* Whether to create DOM nodes in the SVG namespace. An `<svg>` element will set this to true and pass it down to children.
|
|
30
|
+
*/
|
|
31
|
+
isSVG?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* The name of the nearest parent view.
|
|
34
|
+
*/
|
|
35
|
+
viewName?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Mapping of listener function passed to `.on` -> wrapped versions that discard eventName.
|
|
39
|
+
* Wrapping listeners is necessary because the context API's `.on` method does not pass the event name to "*" listeners while the emitter does.
|
|
40
|
+
* ContextEvent objects already have the event name stored as `event.type`.
|
|
41
|
+
*/
|
|
42
|
+
export type WildcardListenerMap = Map<(event: ContextEvent<any>) => void, (eventName: string | symbol, event: ContextEvent<any>) => void>;
|
|
43
|
+
export interface ComponentContext {
|
|
44
|
+
/**
|
|
45
|
+
* Sets a context variable and returns its value.
|
|
46
|
+
*/
|
|
47
|
+
set<T>(key: string | symbol, value: T): T;
|
|
48
|
+
/**
|
|
49
|
+
* Gets the value of a context variable. Returns null if the variable is not set.
|
|
50
|
+
*/
|
|
51
|
+
get<T>(key: string | symbol): T | null;
|
|
52
|
+
/**
|
|
53
|
+
* Adds a listener to be called when `eventName` is emitted.
|
|
54
|
+
*/
|
|
55
|
+
on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
56
|
+
/**
|
|
57
|
+
* Removes a listener from the list to be called when `eventName` is emitted.
|
|
58
|
+
*/
|
|
59
|
+
off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
60
|
+
/**
|
|
61
|
+
* Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.
|
|
62
|
+
*/
|
|
63
|
+
once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
64
|
+
/**
|
|
65
|
+
* Emits a new event to all listeners.
|
|
66
|
+
*/
|
|
67
|
+
emit<T = unknown>(eventName: string, detail: T): boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A context capable of hosting stores.
|
|
71
|
+
*/
|
|
72
|
+
export interface StorableContext extends ComponentContext {
|
|
73
|
+
/**
|
|
74
|
+
* Attaches a new store to this context.
|
|
75
|
+
*/
|
|
76
|
+
attachStore(store: Store<any, any>): void;
|
|
77
|
+
/**
|
|
78
|
+
* Gets the closest instance of a store. Throws an error if the store isn't provided higher in the tree.
|
|
79
|
+
*/
|
|
80
|
+
useStore<Value>(factory: StoreFactory<any, Value>): Value;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* An event emitted from and received by a Dolla context. These are separate from DOM events.
|
|
84
|
+
*/
|
|
85
|
+
export declare class ContextEvent<T> {
|
|
86
|
+
#private;
|
|
87
|
+
type: string;
|
|
88
|
+
detail: T;
|
|
89
|
+
get propagationStopped(): boolean;
|
|
90
|
+
constructor(type: string, detail: T);
|
|
91
|
+
stopPropagation(): void;
|
|
92
|
+
get [Symbol.toStringTag](): string;
|
|
93
|
+
}
|
|
94
|
+
export {};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { HTTP } from "../modules/http.js";
|
|
2
|
+
import { I18n } from "../modules/i18n.js";
|
|
3
|
+
import { type Router } from "../modules/router.js";
|
|
4
|
+
import { type CrashViewProps } from "../views/default-crash-view.js";
|
|
5
|
+
import { Batch } from "./batch.js";
|
|
6
|
+
import { ContextEvent, type StorableContext } from "./context.js";
|
|
7
|
+
import { type Markup, type MarkupElement } from "./markup.js";
|
|
8
|
+
import { type ViewElement, type ViewFunction } from "./nodes/view.js";
|
|
9
|
+
import { createRef, isRef } from "./ref.js";
|
|
10
|
+
import { createState, createWatcher, derive, isState, toState, toValue } from "./state.js";
|
|
11
|
+
import { type Store, type StoreFactory } from "./store.js";
|
|
12
|
+
export type Environment = "development" | "production";
|
|
13
|
+
/**
|
|
14
|
+
* Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.
|
|
15
|
+
*/
|
|
16
|
+
export type Loggles = {
|
|
17
|
+
info: boolean | Environment;
|
|
18
|
+
log: boolean | Environment;
|
|
19
|
+
warn: boolean | Environment;
|
|
20
|
+
error: boolean | Environment;
|
|
21
|
+
};
|
|
22
|
+
export interface Logger {
|
|
23
|
+
info(...args: any[]): void;
|
|
24
|
+
log(...args: any[]): void;
|
|
25
|
+
warn(...args: any[]): void;
|
|
26
|
+
error(...args: any[]): void;
|
|
27
|
+
crash(error: Error): void;
|
|
28
|
+
setName(name: string): Logger;
|
|
29
|
+
}
|
|
30
|
+
export interface LoggerErrorContext {
|
|
31
|
+
error: Error;
|
|
32
|
+
loggerName: string;
|
|
33
|
+
uid?: string;
|
|
34
|
+
}
|
|
35
|
+
export type LoggerOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* Console object to use for logging (mostly for testing). Uses window.console by default.
|
|
38
|
+
*/
|
|
39
|
+
console?: any;
|
|
40
|
+
/**
|
|
41
|
+
* Unique ID to print with logs. Makes it easier to track down messages from specific view instances.
|
|
42
|
+
*/
|
|
43
|
+
uid?: string;
|
|
44
|
+
};
|
|
45
|
+
export declare class Dolla implements StorableContext {
|
|
46
|
+
#private;
|
|
47
|
+
readonly batch: Batch;
|
|
48
|
+
private readonly stats;
|
|
49
|
+
readonly http: HTTP;
|
|
50
|
+
readonly i18n: I18n;
|
|
51
|
+
constructor();
|
|
52
|
+
watch: <I extends import("./state.js").MaybeState<any>[]>(states: [...I], fn: (...currentValues: import("./state.js").StateValues<I>) => void) => import("./state.js").StopFunction;
|
|
53
|
+
createState: typeof createState;
|
|
54
|
+
toState: typeof toState;
|
|
55
|
+
toValue: typeof toValue;
|
|
56
|
+
isState: typeof isState;
|
|
57
|
+
derive: typeof derive;
|
|
58
|
+
createWatcher: typeof createWatcher;
|
|
59
|
+
createRef: typeof createRef;
|
|
60
|
+
isRef: typeof isRef;
|
|
61
|
+
/**
|
|
62
|
+
* True when the app is connected to a DOM node and displayed to the user.
|
|
63
|
+
*/
|
|
64
|
+
get isMounted(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Get the current environment that this app is running in.
|
|
67
|
+
* Environment affects which log messages will print and how much debugging info is included in the DOM.
|
|
68
|
+
*/
|
|
69
|
+
getEnv(): Environment;
|
|
70
|
+
/**
|
|
71
|
+
* Sets the environment that this app is running in.
|
|
72
|
+
* Environment affects which log messages will print and how much debugging info is included in the DOM.
|
|
73
|
+
*/
|
|
74
|
+
setEnv(value: Environment): void;
|
|
75
|
+
/**
|
|
76
|
+
* Sets the view that will be shown when the `crash` method is called on any logger.
|
|
77
|
+
* When a crash is reported the app will be unmounted and replaced with this crash page.
|
|
78
|
+
*/
|
|
79
|
+
setCrashView(view: ViewFunction<CrashViewProps>): void;
|
|
80
|
+
/**
|
|
81
|
+
* Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.
|
|
82
|
+
*/
|
|
83
|
+
getRootElement(): Element | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.
|
|
86
|
+
*/
|
|
87
|
+
getRootView(): ViewElement | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Sets a context variable and returns its value. Context variables are accessible on the app and in child views.
|
|
90
|
+
*/
|
|
91
|
+
set<T>(key: string | symbol, value: T): T;
|
|
92
|
+
/**
|
|
93
|
+
* Gets the value of a context variable. Returns null if the variable is not set.
|
|
94
|
+
*/
|
|
95
|
+
get<T>(key: string | symbol): T | null;
|
|
96
|
+
/**
|
|
97
|
+
* Returns an object of all context variables stored at the app level.
|
|
98
|
+
*/
|
|
99
|
+
/**
|
|
100
|
+
* Adds a listener to be called when `eventName` is emitted.
|
|
101
|
+
*/
|
|
102
|
+
on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
103
|
+
/**
|
|
104
|
+
* Removes a listener from the list to be called when `eventName` is emitted.
|
|
105
|
+
*/
|
|
106
|
+
off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
107
|
+
/**
|
|
108
|
+
* Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.
|
|
109
|
+
*/
|
|
110
|
+
once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
111
|
+
/**
|
|
112
|
+
* Emits a new event to all listeners.
|
|
113
|
+
*/
|
|
114
|
+
emit<T = unknown>(eventName: string, detail: T): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Attaches a new store to this context.
|
|
117
|
+
*/
|
|
118
|
+
attachStore(store: Store<any, any>): void;
|
|
119
|
+
/**
|
|
120
|
+
* Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.
|
|
121
|
+
*/
|
|
122
|
+
useStore<Value>(factory: StoreFactory<any, Value>): Value;
|
|
123
|
+
mount(selector: string, router: Router): Promise<void>;
|
|
124
|
+
mount(selector: string, view: ViewFunction<any>): Promise<void>;
|
|
125
|
+
mount(element: Element, router: Router): Promise<void>;
|
|
126
|
+
mount(element: Element, view: ViewFunction<any>): Promise<void>;
|
|
127
|
+
unmount(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Registers a `callback` to run after `Dolla.mount` is called, before the app is mounted. If `callback` returns a Promise,
|
|
130
|
+
* it will be awaited before mounting finishes. Use this to perform initial setup before the app is displayed to the user.
|
|
131
|
+
*/
|
|
132
|
+
beforeMount(callback: () => void | Promise<void>): void;
|
|
133
|
+
/**
|
|
134
|
+
* Registers a `callback` to run after the app is mounted.
|
|
135
|
+
*/
|
|
136
|
+
onMount(callback: () => void): void;
|
|
137
|
+
/**
|
|
138
|
+
* Registers a `callback` to run after `Dolla.unmount` is called, before the app is unmounted. If `callback` returns a Promise,
|
|
139
|
+
* it will be awaited before unmounting finishes. Use this to perform cleanup.
|
|
140
|
+
*/
|
|
141
|
+
beforeUnmount(callback: () => void | Promise<void>): void;
|
|
142
|
+
/**
|
|
143
|
+
* Registers a `callback` to run after the app is unmounted.
|
|
144
|
+
*/
|
|
145
|
+
onUnmount(callback: () => void): void;
|
|
146
|
+
/**
|
|
147
|
+
* Update log type toggles. Values that are not passed will remain unchanged.
|
|
148
|
+
*/
|
|
149
|
+
setLoggles(options: Partial<Loggles>): void;
|
|
150
|
+
setLogFilter(filter: string | RegExp): void;
|
|
151
|
+
createLogger(name: string, options?: LoggerOptions): Logger;
|
|
152
|
+
/**
|
|
153
|
+
*
|
|
154
|
+
*/
|
|
155
|
+
constructView<P>(view: ViewFunction<P>, props: P, children?: Markup[]): ViewElement;
|
|
156
|
+
/**
|
|
157
|
+
*
|
|
158
|
+
*/
|
|
159
|
+
constructMarkup(markup: Markup | Markup[]): MarkupElement;
|
|
160
|
+
}
|
|
161
|
+
export declare function getDefaultConsole(): any;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Renderable } from "../types.js";
|
|
2
|
+
import type { ElementContext } from "./context.js";
|
|
3
|
+
import { type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
|
|
4
|
+
import { type MaybeState, type State } from "./state.js";
|
|
5
|
+
/**
|
|
6
|
+
* Markup is a set of element metadata that hasn't been constructed into a MarkupElement yet.
|
|
7
|
+
*/
|
|
8
|
+
export interface Markup {
|
|
9
|
+
/**
|
|
10
|
+
* In the case of a view, type will be the View function itself. It can also hold an identifier for special nodes like "$cond", "$repeat", etc.
|
|
11
|
+
* DOM nodes can be created by name, such as HTML elements like "div", "ul" or "span", SVG elements like ""
|
|
12
|
+
*/
|
|
13
|
+
type: string | ViewFunction<any>;
|
|
14
|
+
/**
|
|
15
|
+
* Data that will be passed to a new MarkupElement instance when it is constructed.
|
|
16
|
+
*/
|
|
17
|
+
props?: Record<string, any>;
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
children?: Markup[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A DOM node that has been constructed from a Markup object.
|
|
25
|
+
*/
|
|
26
|
+
export interface MarkupElement {
|
|
27
|
+
readonly node?: Node;
|
|
28
|
+
readonly isMounted: boolean;
|
|
29
|
+
mount(parent: Node, after?: Node): void;
|
|
30
|
+
/**
|
|
31
|
+
* Disconnect from the DOM and clean up. If parentIsUnmounting, DOM operations are skipped.
|
|
32
|
+
* parentIsUnmounting is set for all children by HTML nodes when they unmount.
|
|
33
|
+
*/
|
|
34
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
35
|
+
}
|
|
36
|
+
export declare function isMarkup(value: any): value is Markup;
|
|
37
|
+
export declare function isMarkupElement(value: any): value is MarkupElement;
|
|
38
|
+
export declare function toMarkup(renderables: Renderable | Renderable[]): Markup[];
|
|
39
|
+
export interface MarkupAttributes {
|
|
40
|
+
$text: {
|
|
41
|
+
value: any;
|
|
42
|
+
};
|
|
43
|
+
$repeat: {
|
|
44
|
+
$items: State<any[]>;
|
|
45
|
+
keyFn: (value: any, index: number) => string | number | symbol;
|
|
46
|
+
renderFn: ($item: State<any>, $index: State<number>, c: ViewContext) => ViewResult;
|
|
47
|
+
};
|
|
48
|
+
$observer: {
|
|
49
|
+
sources: MaybeState<any>[];
|
|
50
|
+
renderFn: (...items: any) => Renderable;
|
|
51
|
+
};
|
|
52
|
+
$outlet: {
|
|
53
|
+
$children: State<MarkupElement[]>;
|
|
54
|
+
};
|
|
55
|
+
$node: {
|
|
56
|
+
value: Node;
|
|
57
|
+
};
|
|
58
|
+
$portal: {
|
|
59
|
+
content: Renderable;
|
|
60
|
+
parent: Node;
|
|
61
|
+
};
|
|
62
|
+
[tag: string]: Record<string, any>;
|
|
63
|
+
}
|
|
64
|
+
export declare function createMarkup<T extends keyof MarkupAttributes>(type: T, attributes: MarkupAttributes[T], ...children: Renderable[]): Markup;
|
|
65
|
+
export declare function createMarkup<I>(type: ViewFunction<I>, attributes?: I, ...children: Renderable[]): Markup;
|
|
66
|
+
/**
|
|
67
|
+
* Generate markup with HTML in a tagged template literal.
|
|
68
|
+
*/
|
|
69
|
+
export declare const html: (strings: TemplateStringsArray, ...values: any[]) => Markup | Markup[];
|
|
70
|
+
/**
|
|
71
|
+
* Displays content conditionally. When `predicate` holds a truthy value, `thenContent` is displayed; when `predicate` holds a falsy value, `elseContent` is displayed.
|
|
72
|
+
*/
|
|
73
|
+
export declare function cond(predicate: MaybeState<any>, thenContent?: Renderable, elseContent?: Renderable): Markup;
|
|
74
|
+
/**
|
|
75
|
+
* Calls `renderFn` for each item in `items`. Dynamically adds and removes views as items change.
|
|
76
|
+
* The result of `keyFn` is used to compare items and decide if item was added, removed or updated.
|
|
77
|
+
*/
|
|
78
|
+
export declare function repeat<T>(items: MaybeState<T[]>, keyFn: (value: T, index: number) => string | number | symbol, renderFn: ($value: State<T>, $index: State<number>, ctx: ViewContext) => ViewResult): Markup;
|
|
79
|
+
/**
|
|
80
|
+
* Renders `content` into a `parent` node anywhere in the page, rather than its usual position in the view.
|
|
81
|
+
*/
|
|
82
|
+
export declare function portal(parent: Node, content: Renderable): Markup;
|
|
83
|
+
/**
|
|
84
|
+
* Construct Markup metadata into a set of MarkupElements.
|
|
85
|
+
*/
|
|
86
|
+
export declare function constructMarkup(elementContext: ElementContext, markup: Markup | Markup[]): MarkupElement[];
|
|
87
|
+
/**
|
|
88
|
+
* Combines one or more MarkupElements into a single MarkupElement.
|
|
89
|
+
*/
|
|
90
|
+
export declare function groupElements(elements: MarkupElement[]): MarkupElement;
|
|
91
|
+
export declare function isRenderable(value: unknown): value is Renderable;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MarkupElement } from "../markup";
|
|
2
|
+
import { IS_MARKUP_ELEMENT } from "../symbols";
|
|
3
|
+
/**
|
|
4
|
+
* Wraps any plain DOM node in a MarkupElement interface.
|
|
5
|
+
*/
|
|
6
|
+
export declare class DOMNode implements MarkupElement {
|
|
7
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
8
|
+
node: Node;
|
|
9
|
+
get isMounted(): boolean;
|
|
10
|
+
constructor(node: Node);
|
|
11
|
+
mount(parent: Node, after?: Node): void;
|
|
12
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ElementContext } from "../context.js";
|
|
2
|
+
import { type Markup, type MarkupElement } from "../markup.js";
|
|
3
|
+
import { type Ref } from "../ref.js";
|
|
4
|
+
import { type State, type StopFunction } from "../state.js";
|
|
5
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
6
|
+
type HTMLOptions = {
|
|
7
|
+
elementContext: ElementContext;
|
|
8
|
+
tag: string;
|
|
9
|
+
props: Record<string, any>;
|
|
10
|
+
children?: Markup[];
|
|
11
|
+
};
|
|
12
|
+
export declare class HTML implements MarkupElement {
|
|
13
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
14
|
+
node: HTMLElement | SVGElement;
|
|
15
|
+
props: Record<string, any>;
|
|
16
|
+
childMarkup: Markup[];
|
|
17
|
+
children: MarkupElement[];
|
|
18
|
+
stopCallbacks: StopFunction[];
|
|
19
|
+
elementContext: ElementContext;
|
|
20
|
+
uniqueId: string;
|
|
21
|
+
_batchWrite: (callback: () => void, key?: string) => void;
|
|
22
|
+
ref?: Ref<any>;
|
|
23
|
+
canClickAway: boolean;
|
|
24
|
+
get isMounted(): boolean;
|
|
25
|
+
constructor({ tag, props, children, elementContext }: HTMLOptions);
|
|
26
|
+
mount(parent: Node, after?: Node): void;
|
|
27
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
28
|
+
getUpdateKey(type: string, value: string | number): string;
|
|
29
|
+
_mutate(callback: () => any, updateKey?: string): void;
|
|
30
|
+
attachProp<T>(value: State<T> | T, callback: (value: T) => void, updateKey: string): void;
|
|
31
|
+
applyProps(element: HTMLElement | SVGElement, props: Record<string, unknown>): void;
|
|
32
|
+
applyStyles(element: HTMLElement | SVGElement, styles: unknown, stopCallbacks: StopFunction[]): () => void;
|
|
33
|
+
applyClasses(element: HTMLElement | SVGElement, classes: unknown, stopCallbacks: StopFunction[]): () => void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Converts a camelCase string to kebab-case.
|
|
37
|
+
*/
|
|
38
|
+
export declare function camelToKebab(value: string): string;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Renderable } from "../../types.js";
|
|
2
|
+
import type { ElementContext } from "../context.js";
|
|
3
|
+
import { type MarkupElement } from "../markup.js";
|
|
4
|
+
import { type MaybeState } from "../state.js";
|
|
5
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
6
|
+
interface ObserverOptions {
|
|
7
|
+
elementContext: ElementContext;
|
|
8
|
+
sources: MaybeState<any>[];
|
|
9
|
+
renderFn: (...values: any) => Renderable;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Displays dynamic children without a parent element.
|
|
13
|
+
* Used when a State is passed as a child in a view template.
|
|
14
|
+
*/
|
|
15
|
+
export declare class Observer implements MarkupElement {
|
|
16
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
17
|
+
node: Text;
|
|
18
|
+
children: MarkupElement[];
|
|
19
|
+
renderFn: (...values: any) => Renderable;
|
|
20
|
+
elementContext: ElementContext;
|
|
21
|
+
watcher: import("../state.js").StateWatcher;
|
|
22
|
+
sources: MaybeState<any>[];
|
|
23
|
+
get isMounted(): boolean;
|
|
24
|
+
constructor({ sources, renderFn, elementContext }: ObserverOptions);
|
|
25
|
+
mount(parent: Node, after?: Node): void;
|
|
26
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
27
|
+
cleanup(parentIsUnmounting: boolean): void;
|
|
28
|
+
update(children: Renderable[]): void;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type MarkupElement } from "../markup.js";
|
|
2
|
+
import { type MaybeState, type StopFunction } from "../state.js";
|
|
3
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
4
|
+
/**
|
|
5
|
+
* Manages several MarkupElements as one.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Outlet implements MarkupElement {
|
|
8
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
9
|
+
node: Text;
|
|
10
|
+
isMounted: boolean;
|
|
11
|
+
source: MaybeState<MarkupElement[]>;
|
|
12
|
+
elements: MarkupElement[];
|
|
13
|
+
stopCallback?: StopFunction;
|
|
14
|
+
constructor(source: MaybeState<MarkupElement[]>);
|
|
15
|
+
mount(parent: Node, after?: Node | undefined): void;
|
|
16
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
17
|
+
cleanup(parentIsUnmounting: boolean): void;
|
|
18
|
+
update(newElements: MarkupElement[]): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Renderable } from "../../types.js";
|
|
2
|
+
import type { ElementContext } from "../context.js";
|
|
3
|
+
import { type MarkupElement } from "../markup.js";
|
|
4
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
5
|
+
interface PortalConfig {
|
|
6
|
+
content: Renderable;
|
|
7
|
+
parent: Node;
|
|
8
|
+
elementContext: ElementContext;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Renders content into a specified parent node.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Portal implements MarkupElement {
|
|
14
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
15
|
+
config: PortalConfig;
|
|
16
|
+
element?: MarkupElement;
|
|
17
|
+
get isMounted(): boolean;
|
|
18
|
+
constructor(config: PortalConfig);
|
|
19
|
+
mount(_parent: Node, _after?: Node): void;
|
|
20
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type ElementContext } from "../context.js";
|
|
2
|
+
import { type MarkupElement } from "../markup.js";
|
|
3
|
+
import { type Setter, type State, type StopFunction } from "../state.js";
|
|
4
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
5
|
+
import { type ViewContext, type ViewResult } from "./view.js";
|
|
6
|
+
interface RepeatOptions<T> {
|
|
7
|
+
elementContext: ElementContext;
|
|
8
|
+
$items: State<T[]>;
|
|
9
|
+
keyFn: (value: T, index: number) => string | number | symbol;
|
|
10
|
+
renderFn: ($value: State<T>, $index: State<number>, ctx: ViewContext) => ViewResult;
|
|
11
|
+
}
|
|
12
|
+
type ConnectedItem<T> = {
|
|
13
|
+
key: any;
|
|
14
|
+
$value: State<T>;
|
|
15
|
+
setValue: Setter<T>;
|
|
16
|
+
$index: State<number>;
|
|
17
|
+
setIndex: Setter<number>;
|
|
18
|
+
element: MarkupElement;
|
|
19
|
+
};
|
|
20
|
+
export declare class Repeat<T> implements MarkupElement {
|
|
21
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
22
|
+
node: Text;
|
|
23
|
+
$items: State<T[]>;
|
|
24
|
+
stopCallback?: StopFunction;
|
|
25
|
+
connectedItems: ConnectedItem<T>[];
|
|
26
|
+
elementContext: ElementContext;
|
|
27
|
+
renderFn: (this: ViewContext, $value: State<T>, $index: State<number>, context: ViewContext) => ViewResult;
|
|
28
|
+
keyFn: (value: T, index: number) => string | number | symbol;
|
|
29
|
+
get isMounted(): boolean;
|
|
30
|
+
constructor({ elementContext, $items, renderFn, keyFn }: RepeatOptions<T>);
|
|
31
|
+
mount(parent: Node, after?: Node): void;
|
|
32
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
33
|
+
_cleanup(parentIsUnmounting: boolean): void;
|
|
34
|
+
_update(value: T[]): void;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Emitter } from "@manyducks.co/emitter";
|
|
2
|
+
import { type WildcardListenerMap, type ElementContext, type StorableContext } from "../context.js";
|
|
3
|
+
import type { Logger } from "../dolla.js";
|
|
4
|
+
import { type Markup, type MarkupElement } from "../markup.js";
|
|
5
|
+
import { type MaybeState, type State, type StateValues, type StopFunction } from "../state.js";
|
|
6
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
7
|
+
/**
|
|
8
|
+
* Any valid value that a View can return.
|
|
9
|
+
*/
|
|
10
|
+
export type ViewResult = Node | State<any> | Markup | Markup[] | null;
|
|
11
|
+
export type ViewFunction<P> = (this: ViewContext, props: P, context: ViewContext) => ViewResult;
|
|
12
|
+
/**
|
|
13
|
+
* A view that has been constructed into DOM nodes.
|
|
14
|
+
*/
|
|
15
|
+
export interface ViewElement extends MarkupElement {
|
|
16
|
+
/**
|
|
17
|
+
* Take a ViewFunction and render it as a child of this view.
|
|
18
|
+
*/
|
|
19
|
+
setChildView(view: ViewFunction<{}>): ViewElement;
|
|
20
|
+
}
|
|
21
|
+
export interface ViewContext extends Logger, StorableContext {
|
|
22
|
+
/**
|
|
23
|
+
* An ID unique to this view.
|
|
24
|
+
*/
|
|
25
|
+
readonly uid: string;
|
|
26
|
+
/**
|
|
27
|
+
* Returns an object of all variables stored on this context.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Sets the name of the view's built in logger.
|
|
31
|
+
*/
|
|
32
|
+
setName(name: string): ViewContext;
|
|
33
|
+
/**
|
|
34
|
+
* True while this view is connected to the DOM.
|
|
35
|
+
*/
|
|
36
|
+
readonly isMounted: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Registers a callback to run just before this view is mounted. DOM nodes are not yet attached to the page.
|
|
39
|
+
*/
|
|
40
|
+
beforeMount(callback: () => void): void;
|
|
41
|
+
/**
|
|
42
|
+
* Registers a callback to run just after this view is mounted.
|
|
43
|
+
*/
|
|
44
|
+
onMount(callback: () => void): void;
|
|
45
|
+
/**
|
|
46
|
+
* Registers a callback to run just before this view is unmounted. DOM nodes are still attached to the page.
|
|
47
|
+
*/
|
|
48
|
+
beforeUnmount(callback: () => void): void;
|
|
49
|
+
/**
|
|
50
|
+
* Registers a callback to run just after this view is unmounted.
|
|
51
|
+
*/
|
|
52
|
+
onUnmount(callback: () => void): void;
|
|
53
|
+
/**
|
|
54
|
+
* Watch a set of states. The callback is called when any of the states receive a new value.
|
|
55
|
+
* Watchers will be automatically stopped when this view is unmounted.
|
|
56
|
+
*/
|
|
57
|
+
watch<T extends MaybeState<any>[]>(states: [...T], callback: (...values: StateValues<T>) => void): StopFunction;
|
|
58
|
+
/**
|
|
59
|
+
* Returns a Markup element that displays this view's children.
|
|
60
|
+
*/
|
|
61
|
+
outlet(): Markup;
|
|
62
|
+
}
|
|
63
|
+
export declare function createView<Props extends Record<string, any> = Record<string, unknown>>(fn: ViewFunction<Props>): ViewFunction<Props>;
|
|
64
|
+
type ViewEvents = {
|
|
65
|
+
beforeMount: [];
|
|
66
|
+
mounted: [];
|
|
67
|
+
beforeUnmount: [];
|
|
68
|
+
unmounted: [];
|
|
69
|
+
};
|
|
70
|
+
export declare class View<P> implements ViewElement {
|
|
71
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
72
|
+
uniqueId: string;
|
|
73
|
+
_elementContext: ElementContext;
|
|
74
|
+
_logger: Logger;
|
|
75
|
+
_view: ViewFunction<P>;
|
|
76
|
+
_props: P;
|
|
77
|
+
_element?: MarkupElement;
|
|
78
|
+
_childMarkup: Markup[];
|
|
79
|
+
_$children: State<MarkupElement[]>;
|
|
80
|
+
_setChildren: import("../state.js").Setter<MarkupElement[], MarkupElement[]>;
|
|
81
|
+
_watcher: import("../state.js").StateWatcher;
|
|
82
|
+
_emitter: Emitter<ViewEvents>;
|
|
83
|
+
_wildcardListeners: WildcardListenerMap;
|
|
84
|
+
constructor(elementContext: ElementContext, view: ViewFunction<P>, props: P, children?: Markup[]);
|
|
85
|
+
get node(): Node;
|
|
86
|
+
isMounted: boolean;
|
|
87
|
+
mount(parent: Node, after?: Node): void;
|
|
88
|
+
unmount(parentIsUnmounting?: boolean): void;
|
|
89
|
+
setChildView(fn: ViewFunction<{}>): View<{}>;
|
|
90
|
+
private _initialize;
|
|
91
|
+
}
|
|
92
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `Ref` is a function that stores a value when called with a single argument,
|
|
3
|
+
* and returns the most recently stored value when called with no arguments.
|
|
4
|
+
*/
|
|
5
|
+
export interface Ref<T> {
|
|
6
|
+
/**
|
|
7
|
+
* Get: returns the current value stored in the ref (or undefined).
|
|
8
|
+
*/
|
|
9
|
+
(): T | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Set: stores a new `value` in the ref.
|
|
12
|
+
*/
|
|
13
|
+
<T>(value: T | undefined): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A Ref is a function that returns the last argument it was called with.
|
|
17
|
+
* Calling it with no arguments will simply return the latest value.
|
|
18
|
+
* Calling it with an argument will store that value and immediately return it.
|
|
19
|
+
*
|
|
20
|
+
* @param value - An (optional) initial value to store.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const ref = createRef(5);
|
|
24
|
+
* ref(); // 5
|
|
25
|
+
* ref(500);
|
|
26
|
+
* ref(); // 500
|
|
27
|
+
*/
|
|
28
|
+
export declare function createRef<T>(value?: T): Ref<T>;
|
|
29
|
+
export declare function isRef<T extends Node>(value: any): value is Ref<T>;
|