@manyducks.co/dolla 2.0.0-alpha.26 → 2.0.0-alpha.28
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 +6 -93
- package/dist/core/context.d.ts +88 -0
- package/dist/core/dolla.d.ts +33 -13
- package/dist/core/markup.d.ts +6 -23
- package/dist/core/nodes/dom.d.ts +13 -0
- package/dist/core/nodes/html.d.ts +7 -4
- package/dist/core/nodes/observer.d.ts +4 -3
- package/dist/core/nodes/outlet.d.ts +2 -2
- package/dist/core/nodes/portal.d.ts +5 -4
- package/dist/core/nodes/repeat.d.ts +4 -3
- package/dist/core/nodes/view.d.ts +17 -19
- package/dist/core/ref.d.ts +29 -0
- package/dist/core/state.d.ts +11 -44
- package/dist/core/stats.d.ts +31 -0
- package/dist/core/store.d.ts +44 -0
- package/dist/core/symbols.d.ts +6 -5
- package/dist/index.d.ts +5 -2
- package/dist/index.js +722 -659
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.js +2 -2
- package/dist/jsx-runtime.js +2 -2
- package/dist/modules/http.d.ts +3 -5
- package/dist/passthrough-1MySicTa.js +1476 -0
- package/dist/passthrough-1MySicTa.js.map +1 -0
- package/dist/types.d.ts +1 -2
- package/docs/setup.md +2 -1
- package/docs/state.md +133 -0
- package/notes/stores.md +73 -0
- package/package.json +2 -1
- package/dist/core/nodes/text.d.ts +0 -21
- package/dist/passthrough-CACEgFx5.js +0 -1301
- package/dist/passthrough-CACEgFx5.js.map +0 -1
- package/docs/states.md +0 -41
package/README.md
CHANGED
|
@@ -7,102 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
Dolla is a batteries-included JavaScript frontend framework covering the needs of moderate-to-complex single page apps:
|
|
9
9
|
|
|
10
|
-
- ⚡ Reactive DOM updates with [State](). Inspired by Signals, but with more explicit tracking.
|
|
11
|
-
- 📦 Reusable components with [Views](
|
|
12
|
-
- 🔀 Built in [routing]() with nested routes and middleware support (check login status, preload data, etc).
|
|
13
|
-
- 🐕 Built in [HTTP]() client with middleware support (set auth headers, etc).
|
|
14
|
-
- 📍 Built in [localization]() system (store translated strings in JSON files and call the `t` function to get them).
|
|
15
|
-
- 🍳 Build system optional. Write views in JSX or use `html` tagged template literals.
|
|
10
|
+
- ⚡ Reactive DOM updates with [State](./docs/state.md). Inspired by Signals, but with more explicit tracking.
|
|
11
|
+
- 📦 Reusable components with [Views](./docs/views.md).
|
|
12
|
+
- 🔀 Built in [routing](./docs/router.md) with nested routes and middleware support (check login status, preload data, etc).
|
|
13
|
+
- 🐕 Built in [HTTP](./docs/http.md) client with middleware support (set auth headers, etc).
|
|
14
|
+
- 📍 Built in [localization](./docs/i18n.md) system (store translated strings in JSON files and call the `t` function to get them).
|
|
15
|
+
- 🍳 Build system optional. [Write views in JSX](./docs/setup.md) or use `html` tagged template literals.
|
|
16
16
|
|
|
17
17
|
Let's first get into some examples.
|
|
18
18
|
|
|
19
|
-
## State
|
|
20
|
-
|
|
21
|
-
### Basic State API
|
|
22
|
-
|
|
23
|
-
```js
|
|
24
|
-
import { createState, derive } from "@manyducks.co/dolla";
|
|
25
|
-
|
|
26
|
-
const [$count, setCount] = createState(72);
|
|
27
|
-
|
|
28
|
-
// Get value
|
|
29
|
-
$count.get(): // 72
|
|
30
|
-
|
|
31
|
-
// Replace the stored value with something else
|
|
32
|
-
setCount(300);
|
|
33
|
-
$count.get(); // 300
|
|
34
|
-
|
|
35
|
-
// You can also pass a function that takes the current value and returns a new one
|
|
36
|
-
setCount((current) => current + 1);
|
|
37
|
-
$count.get(); // 301
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Now that you have a state you can derive more states from that one. Derived states automatically stay in sync with the values of their dependencies.
|
|
41
|
-
|
|
42
|
-
```js
|
|
43
|
-
// Pass and array of one or more states followed by a function that computes a new value.
|
|
44
|
-
const $doubled = derive([$count], (count) => count * 2);
|
|
45
|
-
|
|
46
|
-
$doubled.get(); // 602
|
|
47
|
-
|
|
48
|
-
setCount(500);
|
|
49
|
-
|
|
50
|
-
$doubled.get(); // 1000
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### In Views
|
|
54
|
-
|
|
55
|
-
```jsx
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
States also come in a settable variety that includes the setter on the same object. Sometimes you want to pass around a two-way binding and this is what SettableState is for.
|
|
60
|
-
|
|
61
|
-
```jsx
|
|
62
|
-
import { createSettableState, fromSettable, toSettable } from "@manyducks.co/dolla";
|
|
63
|
-
|
|
64
|
-
// Settable states can be set by passing a value when they are called.
|
|
65
|
-
const $$value = createSettableState("Test");
|
|
66
|
-
$$value(); // "Test"
|
|
67
|
-
$$value("New Value");
|
|
68
|
-
$$value(); // "New Value"
|
|
69
|
-
|
|
70
|
-
// They can also be split into a State and Setter
|
|
71
|
-
const [$value, setValue] = fromSettableState($$value);
|
|
72
|
-
|
|
73
|
-
// And a State and Setter can be combined into a SettableState.
|
|
74
|
-
const $$otherValue = toSettableState($value, setValue);
|
|
75
|
-
|
|
76
|
-
// Or discard the setter and make it read-only using the good old toState function:
|
|
77
|
-
const $value = toState($$value);
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
You can also do weird proxy things like this:
|
|
81
|
-
|
|
82
|
-
```jsx
|
|
83
|
-
// Create an original place for the state to live
|
|
84
|
-
const [$value, setValue] = createState(5);
|
|
85
|
-
|
|
86
|
-
// Derive a state that doubles the value
|
|
87
|
-
const $doubled = derive([$value], (value) => value * 2);
|
|
88
|
-
|
|
89
|
-
// Create a setter that takes the doubled value and sets the original $value accordingly.
|
|
90
|
-
const setDoubled = createSetter($doubled, (next, current) => {
|
|
91
|
-
setValue(next / 2);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Bundle the derived state and setter into a SettableState to pass around.
|
|
95
|
-
const $$doubled = toSettableState($doubled, setDoubled);
|
|
96
|
-
|
|
97
|
-
// Setting the doubled state...
|
|
98
|
-
$$doubled(100);
|
|
99
|
-
|
|
100
|
-
// ... will be reflected everywhere.
|
|
101
|
-
$$doubled(); // 100
|
|
102
|
-
$doubled(); // 100
|
|
103
|
-
$value(); // 50
|
|
104
|
-
```
|
|
105
|
-
|
|
106
19
|
<h2 id="section-views">Views</h2>
|
|
107
20
|
|
|
108
21
|
A basic view:
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
export interface ComponentContext {
|
|
38
|
+
/**
|
|
39
|
+
* Sets a context variable and returns its value.
|
|
40
|
+
*/
|
|
41
|
+
set<T>(key: string | symbol, value: T): T;
|
|
42
|
+
/**
|
|
43
|
+
* Gets the value of a context variable. Returns null if the variable is not set.
|
|
44
|
+
*/
|
|
45
|
+
get<T>(key: string | symbol): T | null;
|
|
46
|
+
/**
|
|
47
|
+
* Adds a listener to be called when `eventName` is emitted.
|
|
48
|
+
*/
|
|
49
|
+
on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* Removes a listener from the list to be called when `eventName` is emitted.
|
|
52
|
+
*/
|
|
53
|
+
off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
54
|
+
/**
|
|
55
|
+
* Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.
|
|
56
|
+
*/
|
|
57
|
+
once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
58
|
+
/**
|
|
59
|
+
* Emits a new event to all listeners.
|
|
60
|
+
*/
|
|
61
|
+
emit<T = unknown>(eventName: string, detail: T): boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A context capable of hosting stores.
|
|
65
|
+
*/
|
|
66
|
+
export interface StorableContext extends ComponentContext {
|
|
67
|
+
/**
|
|
68
|
+
* Attaches a new store to this context.
|
|
69
|
+
*/
|
|
70
|
+
attachStore(store: Store<any, any>): void;
|
|
71
|
+
/**
|
|
72
|
+
* Gets the closest instance of a store. Throws an error if the store isn't provided higher in the tree.
|
|
73
|
+
*/
|
|
74
|
+
useStore<Value>(factory: StoreFactory<any, Value>): Value;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* An event emitted from and received by a Dolla context. These are separate from DOM events.
|
|
78
|
+
*/
|
|
79
|
+
export declare class ContextEvent<T> {
|
|
80
|
+
#private;
|
|
81
|
+
type: string;
|
|
82
|
+
detail: T;
|
|
83
|
+
get propagationStopped(): boolean;
|
|
84
|
+
constructor(type: string, detail: T);
|
|
85
|
+
stopPropagation(): void;
|
|
86
|
+
get [Symbol.toStringTag](): string;
|
|
87
|
+
}
|
|
88
|
+
export {};
|
package/dist/core/dolla.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { HTTP } from "../modules/http.js";
|
|
2
|
+
import { I18n } from "../modules/i18n.js";
|
|
3
|
+
import { Router } from "../modules/router.js";
|
|
1
4
|
import { type CrashViewProps } from "../views/default-crash-view.js";
|
|
2
5
|
import { Batch } from "./batch.js";
|
|
6
|
+
import { ContextEvent, type StorableContext } from "./context.js";
|
|
3
7
|
import { type Markup, type MarkupElement } from "./markup.js";
|
|
4
8
|
import { type ViewElement, type ViewFunction } from "./nodes/view.js";
|
|
5
|
-
import { createRef,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Router } from "../modules/router.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";
|
|
9
12
|
export type Environment = "development" | "production";
|
|
10
13
|
/**
|
|
11
14
|
* Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.
|
|
@@ -39,13 +42,10 @@ export type LoggerOptions = {
|
|
|
39
42
|
*/
|
|
40
43
|
uid?: string;
|
|
41
44
|
};
|
|
42
|
-
export
|
|
43
|
-
root: Dolla;
|
|
44
|
-
options: Options;
|
|
45
|
-
}
|
|
46
|
-
export declare class Dolla {
|
|
45
|
+
export declare class Dolla implements StorableContext {
|
|
47
46
|
#private;
|
|
48
47
|
readonly batch: Batch;
|
|
48
|
+
private readonly stats;
|
|
49
49
|
readonly http: HTTP;
|
|
50
50
|
readonly i18n: I18n;
|
|
51
51
|
readonly router: Router;
|
|
@@ -86,9 +86,6 @@ export declare class Dolla {
|
|
|
86
86
|
* Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.
|
|
87
87
|
*/
|
|
88
88
|
getRootView(): ViewElement | undefined;
|
|
89
|
-
/**
|
|
90
|
-
* Registers a Dolla module.
|
|
91
|
-
*/
|
|
92
89
|
/**
|
|
93
90
|
* Sets a context variable and returns its value. Context variables are accessible on the app and in child views.
|
|
94
91
|
*/
|
|
@@ -100,7 +97,30 @@ export declare class Dolla {
|
|
|
100
97
|
/**
|
|
101
98
|
* Returns an object of all context variables stored at the app level.
|
|
102
99
|
*/
|
|
103
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Adds a listener to be called when `eventName` is emitted.
|
|
102
|
+
*/
|
|
103
|
+
on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
104
|
+
/**
|
|
105
|
+
* Removes a listener from the list to be called when `eventName` is emitted.
|
|
106
|
+
*/
|
|
107
|
+
off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
108
|
+
/**
|
|
109
|
+
* Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.
|
|
110
|
+
*/
|
|
111
|
+
once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void;
|
|
112
|
+
/**
|
|
113
|
+
* Emits a new event to all listeners.
|
|
114
|
+
*/
|
|
115
|
+
emit<T = unknown>(eventName: string, detail: T): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Attaches a new store to this context.
|
|
118
|
+
*/
|
|
119
|
+
attachStore(store: Store<any, any>): void;
|
|
120
|
+
/**
|
|
121
|
+
* Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.
|
|
122
|
+
*/
|
|
123
|
+
useStore<Value>(factory: StoreFactory<any, Value>): Value;
|
|
104
124
|
mount(selector: string, view?: ViewFunction<any>): Promise<void>;
|
|
105
125
|
mount(element: HTMLElement, view?: ViewFunction<any>): Promise<void>;
|
|
106
126
|
unmount(): Promise<void>;
|
package/dist/core/markup.d.ts
CHANGED
|
@@ -1,25 +1,7 @@
|
|
|
1
|
-
import type { Renderable
|
|
2
|
-
import type {
|
|
1
|
+
import type { Renderable } from "../types.js";
|
|
2
|
+
import type { ElementContext } from "./context.js";
|
|
3
3
|
import { type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
|
|
4
|
-
import { MaybeState, type State } from "./state.js";
|
|
5
|
-
export interface ElementContext {
|
|
6
|
-
/**
|
|
7
|
-
* The root Dolla instance this element belongs to.
|
|
8
|
-
*/
|
|
9
|
-
root: Dolla;
|
|
10
|
-
/**
|
|
11
|
-
* Storage for context variables.
|
|
12
|
-
*/
|
|
13
|
-
data: Record<string | symbol, unknown>;
|
|
14
|
-
/**
|
|
15
|
-
* A reference to the parent context.
|
|
16
|
-
*/
|
|
17
|
-
parent?: ElementContext;
|
|
18
|
-
/**
|
|
19
|
-
* Whether to create DOM nodes in the SVG namespace. An `<svg>` element will set this to true and pass it down to children.
|
|
20
|
-
*/
|
|
21
|
-
isSVG?: boolean;
|
|
22
|
-
}
|
|
4
|
+
import { type MaybeState, type State } from "./state.js";
|
|
23
5
|
/**
|
|
24
6
|
* Markup is a set of element metadata that hasn't been constructed into a MarkupElement yet.
|
|
25
7
|
*/
|
|
@@ -47,6 +29,7 @@ export interface MarkupElement {
|
|
|
47
29
|
mount(parent: Node, after?: Node): void;
|
|
48
30
|
/**
|
|
49
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.
|
|
50
33
|
*/
|
|
51
34
|
unmount(parentIsUnmounting?: boolean): void;
|
|
52
35
|
}
|
|
@@ -55,7 +38,7 @@ export declare function isMarkupElement(value: any): value is MarkupElement;
|
|
|
55
38
|
export declare function toMarkup(renderables: Renderable | Renderable[]): Markup[];
|
|
56
39
|
export interface MarkupAttributes {
|
|
57
40
|
$text: {
|
|
58
|
-
value:
|
|
41
|
+
value: any;
|
|
59
42
|
};
|
|
60
43
|
$repeat: {
|
|
61
44
|
$items: State<any[]>;
|
|
@@ -94,7 +77,7 @@ export declare function cond(predicate: MaybeState<any>, thenContent?: Renderabl
|
|
|
94
77
|
*/
|
|
95
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;
|
|
96
79
|
/**
|
|
97
|
-
*
|
|
80
|
+
* Renders `content` into a `parent` node anywhere in the page, rather than its usual position in the view.
|
|
98
81
|
*/
|
|
99
82
|
export declare function portal(parent: Node, content: Renderable): Markup;
|
|
100
83
|
/**
|
|
@@ -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
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type ElementContext
|
|
2
|
-
import { type
|
|
3
|
-
import {
|
|
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";
|
|
4
6
|
type HTMLOptions = {
|
|
5
7
|
elementContext: ElementContext;
|
|
6
8
|
tag: string;
|
|
@@ -8,9 +10,10 @@ type HTMLOptions = {
|
|
|
8
10
|
children?: Markup[];
|
|
9
11
|
};
|
|
10
12
|
export declare class HTML implements MarkupElement {
|
|
11
|
-
[
|
|
13
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
12
14
|
node: HTMLElement | SVGElement;
|
|
13
15
|
props: Record<string, any>;
|
|
16
|
+
childMarkup: Markup[];
|
|
14
17
|
children: MarkupElement[];
|
|
15
18
|
stopCallbacks: StopFunction[];
|
|
16
19
|
elementContext: ElementContext;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Renderable } from "../../types.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { ElementContext } from "../context.js";
|
|
3
|
+
import { type MarkupElement } from "../markup.js";
|
|
3
4
|
import { type MaybeState } from "../state.js";
|
|
4
|
-
import {
|
|
5
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
5
6
|
interface ObserverOptions {
|
|
6
7
|
elementContext: ElementContext;
|
|
7
8
|
sources: MaybeState<any>[];
|
|
@@ -12,7 +13,7 @@ interface ObserverOptions {
|
|
|
12
13
|
* Used when a State is passed as a child in a view template.
|
|
13
14
|
*/
|
|
14
15
|
export declare class Observer implements MarkupElement {
|
|
15
|
-
[
|
|
16
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
16
17
|
node: Text;
|
|
17
18
|
children: MarkupElement[];
|
|
18
19
|
renderFn: (...values: any) => Renderable;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type MarkupElement } from "../markup.js";
|
|
2
2
|
import { type MaybeState, type StopFunction } from "../state.js";
|
|
3
|
-
import {
|
|
3
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
4
4
|
/**
|
|
5
5
|
* Manages several MarkupElements as one.
|
|
6
6
|
*/
|
|
7
7
|
export declare class Outlet implements MarkupElement {
|
|
8
|
-
[
|
|
8
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
9
9
|
node: Text;
|
|
10
10
|
isMounted: boolean;
|
|
11
11
|
source: MaybeState<MarkupElement[]>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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";
|
|
4
5
|
interface PortalConfig {
|
|
5
6
|
content: Renderable;
|
|
6
7
|
parent: Node;
|
|
@@ -10,7 +11,7 @@ interface PortalConfig {
|
|
|
10
11
|
* Renders content into a specified parent node.
|
|
11
12
|
*/
|
|
12
13
|
export declare class Portal implements MarkupElement {
|
|
13
|
-
[
|
|
14
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
14
15
|
config: PortalConfig;
|
|
15
16
|
element?: MarkupElement;
|
|
16
17
|
get isMounted(): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type ElementContext
|
|
1
|
+
import { type ElementContext } from "../context.js";
|
|
2
|
+
import { type MarkupElement } from "../markup.js";
|
|
2
3
|
import { type Setter, type State, type StopFunction } from "../state.js";
|
|
3
|
-
import {
|
|
4
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
4
5
|
import { type ViewContext, type ViewResult } from "./view.js";
|
|
5
6
|
interface RepeatOptions<T> {
|
|
6
7
|
elementContext: ElementContext;
|
|
@@ -17,7 +18,7 @@ type ConnectedItem<T> = {
|
|
|
17
18
|
element: MarkupElement;
|
|
18
19
|
};
|
|
19
20
|
export declare class Repeat<T> implements MarkupElement {
|
|
20
|
-
[
|
|
21
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
21
22
|
node: Text;
|
|
22
23
|
$items: State<T[]>;
|
|
23
24
|
stopCallback?: StopFunction;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { Emitter } from "@manyducks.co/emitter";
|
|
2
|
+
import { type ElementContext, type StorableContext } from "../context.js";
|
|
1
3
|
import type { Logger } from "../dolla.js";
|
|
2
|
-
import { type
|
|
4
|
+
import { type Markup, type MarkupElement } from "../markup.js";
|
|
3
5
|
import { type MaybeState, type State, type StateValues, type StopFunction } from "../state.js";
|
|
4
|
-
import {
|
|
6
|
+
import { IS_MARKUP_ELEMENT } from "../symbols.js";
|
|
5
7
|
/**
|
|
6
8
|
* Any valid value that a View can return.
|
|
7
9
|
*/
|
|
8
10
|
export type ViewResult = Node | State<any> | Markup | Markup[] | null;
|
|
9
|
-
export type ViewFunction<P> = (props: P, context: ViewContext) => ViewResult;
|
|
11
|
+
export type ViewFunction<P> = (this: ViewContext, props: P, context: ViewContext) => ViewResult;
|
|
10
12
|
/**
|
|
11
13
|
* A view that has been constructed into DOM nodes.
|
|
12
14
|
*/
|
|
@@ -16,23 +18,14 @@ export interface ViewElement extends MarkupElement {
|
|
|
16
18
|
*/
|
|
17
19
|
setChildView(view: ViewFunction<{}>): ViewElement;
|
|
18
20
|
}
|
|
19
|
-
export interface ViewContext extends Logger {
|
|
21
|
+
export interface ViewContext extends Logger, StorableContext {
|
|
20
22
|
/**
|
|
21
23
|
* An ID unique to this view.
|
|
22
24
|
*/
|
|
23
25
|
readonly uid: string;
|
|
24
|
-
/**
|
|
25
|
-
* Sets a context variable and returns its value. Context variables are accessible on the same context and from those of child views.
|
|
26
|
-
*/
|
|
27
|
-
set<T>(key: string | symbol, value: T): T;
|
|
28
|
-
/**
|
|
29
|
-
* Gets the value of a context variable. Returns null if the variable is not set.
|
|
30
|
-
*/
|
|
31
|
-
get<T>(key: string | symbol): T | null;
|
|
32
26
|
/**
|
|
33
27
|
* Returns an object of all variables stored on this context.
|
|
34
28
|
*/
|
|
35
|
-
getAll(): Record<string | symbol, unknown>;
|
|
36
29
|
/**
|
|
37
30
|
* Sets the name of the view's built in logger.
|
|
38
31
|
*/
|
|
@@ -63,8 +56,15 @@ export interface ViewContext extends Logger {
|
|
|
63
56
|
*/
|
|
64
57
|
outlet(): Markup;
|
|
65
58
|
}
|
|
59
|
+
export declare function createView<Props extends Record<string, any> = Record<string, unknown>>(fn: ViewFunction<Props>): ViewFunction<Props>;
|
|
60
|
+
type ViewEvents = {
|
|
61
|
+
beforeMount: [];
|
|
62
|
+
mounted: [];
|
|
63
|
+
beforeUnmount: [];
|
|
64
|
+
unmounted: [];
|
|
65
|
+
};
|
|
66
66
|
export declare class View<P> implements ViewElement {
|
|
67
|
-
[
|
|
67
|
+
[IS_MARKUP_ELEMENT]: boolean;
|
|
68
68
|
uniqueId: string;
|
|
69
69
|
_elementContext: ElementContext;
|
|
70
70
|
_logger: Logger;
|
|
@@ -75,15 +75,13 @@ export declare class View<P> implements ViewElement {
|
|
|
75
75
|
_$children: State<MarkupElement[]>;
|
|
76
76
|
_setChildren: import("../state.js").Setter<MarkupElement[], MarkupElement[]>;
|
|
77
77
|
_watcher: import("../state.js").StateWatcher;
|
|
78
|
-
|
|
79
|
-
_onMountCallbacks: (() => any)[];
|
|
80
|
-
_beforeUnmountCallbacks: (() => any)[];
|
|
81
|
-
_onUnmountCallbacks: (() => any)[];
|
|
78
|
+
_emitter: Emitter<ViewEvents>;
|
|
82
79
|
constructor(elementContext: ElementContext, view: ViewFunction<P>, props: P, children?: Markup[]);
|
|
83
80
|
get node(): Node;
|
|
84
81
|
isMounted: boolean;
|
|
85
82
|
mount(parent: Node, after?: Node): void;
|
|
86
83
|
unmount(parentIsUnmounting?: boolean): void;
|
|
87
84
|
setChildView(fn: ViewFunction<{}>): View<{}>;
|
|
88
|
-
|
|
85
|
+
private _initialize;
|
|
89
86
|
}
|
|
87
|
+
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>;
|
package/dist/core/state.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { strictEqual } from "../utils";
|
|
2
|
-
import {
|
|
2
|
+
import { IS_STATE } from "./symbols";
|
|
3
3
|
/**
|
|
4
4
|
* Stops the observer that created it when called.
|
|
5
5
|
*/
|
|
@@ -25,7 +25,7 @@ export interface CreateStateOptions<T> {
|
|
|
25
25
|
export interface WatchOptions<T> {
|
|
26
26
|
/**
|
|
27
27
|
* If true the watch callback will be called for the first time on the next change.
|
|
28
|
-
*
|
|
28
|
+
* Callback is immediately called with the state's current value by default.
|
|
29
29
|
*/
|
|
30
30
|
lazy?: boolean;
|
|
31
31
|
}
|
|
@@ -49,34 +49,7 @@ export type SetFunction<I, O = I> = (current: I) => O;
|
|
|
49
49
|
/** Callback that updates the value of a state. */
|
|
50
50
|
export type Setter<I, O = I> = (value: SetAction<I, O>) => void;
|
|
51
51
|
export type MaybeState<T> = State<T> | T;
|
|
52
|
-
/**
|
|
53
|
-
* A state and setter in one. Useful for passing states that are intended to be updated by subviews.
|
|
54
|
-
*/
|
|
55
|
-
export interface SettableState<I, O = I> extends State<I> {
|
|
56
|
-
/**
|
|
57
|
-
* Updates the state's value.
|
|
58
|
-
*/
|
|
59
|
-
set(next: O): void;
|
|
60
|
-
/**
|
|
61
|
-
* Takes a callback that recieves the state's current value and returns a new one.
|
|
62
|
-
*/
|
|
63
|
-
set(callback: (current: I) => O): void;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
*/
|
|
68
|
-
export interface Ref<T> {
|
|
69
|
-
/**
|
|
70
|
-
* Get: returns the current value stored in the ref (or undefined).
|
|
71
|
-
*/
|
|
72
|
-
(): T | undefined;
|
|
73
|
-
/**
|
|
74
|
-
* Set: stores a new `value` in the ref.
|
|
75
|
-
*/
|
|
76
|
-
<T>(value: T | undefined): void;
|
|
77
|
-
}
|
|
78
52
|
export declare function isState<T>(value: any): value is State<T>;
|
|
79
|
-
export declare function isRef<T extends Node>(value: any): value is Ref<T>;
|
|
80
53
|
/**
|
|
81
54
|
* Retrieves a plain value from a variable that may be a state.
|
|
82
55
|
*/
|
|
@@ -85,6 +58,11 @@ export declare function toValue<T>(source: MaybeState<T>): T;
|
|
|
85
58
|
* Ensures a variable that may be a state or plain value is a state.
|
|
86
59
|
*/
|
|
87
60
|
export declare function toState<T>(value: MaybeState<T>): State<T>;
|
|
61
|
+
/**
|
|
62
|
+
* ValueHolder implements the core functionality of a State.
|
|
63
|
+
* It holds a value, which can be retrieved with `get`, updated with `set` and observed with `watch`.
|
|
64
|
+
* The user-facing API splits up access into a read-only State and a setter function.
|
|
65
|
+
*/
|
|
88
66
|
export declare class ValueHolder<T> implements State<T> {
|
|
89
67
|
value: T;
|
|
90
68
|
watchers: ((value: T) => void)[];
|
|
@@ -94,8 +72,11 @@ export declare class ValueHolder<T> implements State<T> {
|
|
|
94
72
|
set(action: T | SetFunction<T>): void;
|
|
95
73
|
watch(callback: (value: T) => void, options?: WatchOptions<T>): () => void;
|
|
96
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Signal is the implementation of a read-only State.
|
|
77
|
+
*/
|
|
97
78
|
export declare class Signal<T> implements State<T> {
|
|
98
|
-
[
|
|
79
|
+
[IS_STATE]: boolean;
|
|
99
80
|
__value: State<T>;
|
|
100
81
|
constructor(value: State<T>);
|
|
101
82
|
get(): T;
|
|
@@ -128,20 +109,6 @@ export interface DeriveOptions {
|
|
|
128
109
|
* const $hello = derive([$greeting, name], (greeting, name) => `${greeting}, ${name}!`);
|
|
129
110
|
*/
|
|
130
111
|
export declare function derive<Sources extends MaybeState<any>[], T>(sources: [...Sources], fn: (...values: StateValues<Sources>) => T | State<T>, options?: DeriveOptions): State<T>;
|
|
131
|
-
/**
|
|
132
|
-
* A Ref is a function that returns the last argument it was called with.
|
|
133
|
-
* Calling it with no arguments will simply return the latest value.
|
|
134
|
-
* Calling it with an argument will store that value and immediately return it.
|
|
135
|
-
*
|
|
136
|
-
* @param value - An (optional) initial value to store.
|
|
137
|
-
*
|
|
138
|
-
* @example
|
|
139
|
-
* const ref = createRef(5);
|
|
140
|
-
* ref(); // 5
|
|
141
|
-
* ref(500);
|
|
142
|
-
* ref(); // 500
|
|
143
|
-
*/
|
|
144
|
-
export declare function createRef<T>(value?: T): Ref<T>;
|
|
145
112
|
export interface StateWatcher {
|
|
146
113
|
/**
|
|
147
114
|
* Watch one or more states, calling the provided `fn` each time one of their values changes.
|