@manyducks.co/dolla 2.0.0-alpha.41 → 2.0.0-alpha.43

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 CHANGED
@@ -34,28 +34,93 @@ Dolla's goals include:
34
34
 
35
35
  A basic view. Note that the view function is called exactly once when the view is first mounted. All changes to DOM nodes thereafter happen as a result of `$state` values changing.
36
36
 
37
- ```js
37
+ ```jsx
38
38
  import Dolla, { atom, html } from "@manyducks.co/dolla";
39
39
 
40
40
  function Counter() {
41
41
  const count = atom(0);
42
42
 
43
+ this.effect(() => {
44
+ console.log(`Count is: ${count.get()}`);
45
+ });
46
+
47
+ function increment() {
48
+ count.set(count.get() + 1);
49
+ }
50
+
51
+ function decrement() {
52
+ // alternative to `set(get() - 1)`
53
+ count.update((value) => value - 1);
54
+ }
55
+
43
56
  return html`
44
57
  <div>
45
58
  <p>Counter: ${count}</p>
46
59
  <div>
47
- <button onclick=${() => count.value--}>-1</button>
48
- <button onclick=${() => count.value++}>+1</button>
60
+ <button onclick=${increment}>+1</button>
61
+ <button onclick=${decrement}>-1</button>
49
62
  </div>
50
63
  </div>
51
64
  `;
52
- });
65
+ }
53
66
 
54
67
  Dolla.mount(document.body, Counter);
55
68
  ```
56
69
 
57
70
  > TODO: Show small examples for routing and stores.
58
71
 
72
+ ```js
73
+ function MessageStore() {
74
+ const message = atom("message", "Hello world!");
75
+
76
+ this.effect(() => {
77
+ this.log(`Message is now: ${get(message)}`);
78
+ // Calling `get()` inside an effect (or compose) function will track that reactive value as a dependency.
79
+ // Effects will re-run when a dependency updates.
80
+ });
81
+ // `this` refers to the context object; StoreContext in a store and ViewContext in a view.
82
+ // Context objects contain methods for controlling the component, logging and attaching lifecycle hooks.
83
+
84
+ return {
85
+ message: compose("message:readonly", () => get(message)),
86
+ // Creates a read-only reactive of the message value.
87
+ // Composed values update when their dependencies update.
88
+
89
+ setMessage: set(message),
90
+ // Creates a setter function to update the original message atom.
91
+ };
92
+ }
93
+
94
+ function App() {
95
+ const { message, setMessage } = this.provide(MessageStore);
96
+ // Provides a MessageStore on this context and any child contexts.
97
+ // When a store is provided its value is returned right away.
98
+
99
+ return html`
100
+ <div>
101
+ <${MessageView} />
102
+ <${MessageView} />
103
+ <${MessageView} />
104
+
105
+ <input
106
+ type="text"
107
+ value=${message}
108
+ oninput=${(e) => {
109
+ setMessage(e.currentTarget.value);
110
+ }}
111
+ />
112
+ </div>
113
+ `;
114
+ }
115
+
116
+ function MessageView() {
117
+ const { message } = this.get(MessageStore);
118
+ // Gets the nearest instance of MessageStore. In this case the one provided at the parent.
119
+
120
+ return html`<span>${message}</span>`;
121
+ }
122
+ ```
123
+
59
124
  For more detail [check out the Docs](./docs/index.md).
60
125
 
61
126
  ---
@@ -24,7 +24,7 @@ export interface Markup {
24
24
  * A DOM node that has been constructed from a Markup object.
25
25
  */
26
26
  export interface MarkupElement {
27
- readonly node?: Node;
27
+ readonly domNode?: Node;
28
28
  readonly isMounted: boolean;
29
29
  mount(parent: Node, after?: Node): void;
30
30
  /**
@@ -5,7 +5,7 @@ import { IS_MARKUP_ELEMENT } from "../symbols";
5
5
  */
6
6
  export declare class DOMNode implements MarkupElement {
7
7
  [IS_MARKUP_ELEMENT]: boolean;
8
- node: Node;
8
+ domNode: Node;
9
9
  get isMounted(): boolean;
10
10
  constructor(node: Node);
11
11
  mount(parent: Node, after?: Node): void;
@@ -13,7 +13,7 @@ interface DynamicOptions {
13
13
  */
14
14
  export declare class Dynamic implements MarkupElement {
15
15
  [IS_MARKUP_ELEMENT]: boolean;
16
- node: Text;
16
+ domNode: Text;
17
17
  private children;
18
18
  private elementContext;
19
19
  private source;
@@ -9,7 +9,7 @@ type HTMLOptions = {
9
9
  };
10
10
  export declare class HTML implements MarkupElement {
11
11
  [IS_MARKUP_ELEMENT]: boolean;
12
- node: HTMLElement | SVGElement;
12
+ domNode: HTMLElement | SVGElement;
13
13
  private props;
14
14
  private childMarkup;
15
15
  private children;
@@ -11,7 +11,7 @@ interface ListOptions<T> {
11
11
  }
12
12
  export declare class List<T> implements MarkupElement {
13
13
  [IS_MARKUP_ELEMENT]: boolean;
14
- node: Text;
14
+ domNode: Text;
15
15
  private items;
16
16
  private unsubscribe;
17
17
  private connectedItems;
@@ -6,7 +6,7 @@ import { IS_MARKUP_ELEMENT } from "../symbols.js";
6
6
  */
7
7
  export declare class Outlet implements MarkupElement {
8
8
  [IS_MARKUP_ELEMENT]: boolean;
9
- node: Text;
9
+ domNode: Text;
10
10
  isMounted: boolean;
11
11
  private source;
12
12
  private elements;
@@ -69,7 +69,7 @@ export declare class View<P> implements ViewElement {
69
69
  unmount: (() => any)[];
70
70
  };
71
71
  constructor(elementContext: ElementContext, fn: ViewFunction<P>, props: P, children?: Markup[]);
72
- get node(): Node;
72
+ get domNode(): Node;
73
73
  isMounted: boolean;
74
74
  mount(parent: Node, after?: Node): void;
75
75
  unmount(parentIsUnmounting?: boolean): void;
@@ -13,15 +13,26 @@ export interface Signal<T = any> extends Dependency {
13
13
  * A readable reactive state object.
14
14
  */
15
15
  export interface Reactive<T> {
16
+ /**
17
+ * A name provided at the creation of this reactive.
18
+ */
19
+ readonly name?: string;
20
+ /**
21
+ * Returns the current value. Tracks this reactive as a dependency if called within `effect` or `compose`.
22
+ */
23
+ get(): T;
24
+ /**
25
+ * Returns the current value without tracking this reactive as a dependency when called within `effect` or `compose`.
26
+ */
27
+ peek(): T;
16
28
  /**
17
29
  * The current value.
30
+ * @deprecated use `get()` and `set()`
18
31
  */
19
32
  readonly value: T;
20
33
  }
21
34
  export type MaybeReactive<T> = Reactive<T> | T;
22
35
  export type UnsubscribeFunction = () => void;
23
- export declare function pauseTracking(): void;
24
- export declare function resumeTracking(): void;
25
36
  /**
26
37
  * A function to compare the current and next values. Returning `true` means the value has changed.
27
38
  */
@@ -38,9 +49,64 @@ export interface ReactiveOptions<T> {
38
49
  }
39
50
  export declare class Atom<T> implements Reactive<T> {
40
51
  #private;
41
- name?: string;
42
- constructor(signal: Signal<T>, options?: ReactiveOptions<T>);
52
+ readonly name?: string;
53
+ constructor(value: T, options?: ReactiveOptions<T>);
54
+ /**
55
+ * Returns the latest value. The signal is tracked as a dependency if called within `effect` or `compose`.
56
+ */
57
+ get(): T;
58
+ /**
59
+ * Returns the latest value. The signal is NOT tracked if called within `effect` or `compose`.
60
+ */
61
+ peek(): T;
62
+ /**
63
+ * Replaces the current value with `next`.
64
+ *
65
+ * @example
66
+ * const count = atom(0);
67
+ * count.set(2);
68
+ * count.set(count.get() + 1);
69
+ */
70
+ set(next: T): void;
71
+ /**
72
+ * Passes the current value to `fn` and sets the return value as the next value.
73
+ *
74
+ * @example
75
+ * const count = atom(0);
76
+ * count.update((current) => current + 1);
77
+ * count.update((current) => current * 5);
78
+ *
79
+ * // Also works very well with Immer `produce` for complex objects.
80
+ * const items = atom([{ name: "Alice", age: 26 }, { name: "Bob", age: 33 }]);
81
+ *
82
+ * // Without Immer:
83
+ * items.update((current) => {
84
+ * // Return a new array with Bob's age increased by 1.
85
+ * const newItems = [...current];
86
+ * newItems[1] = {
87
+ * ...newItems[1],
88
+ * age: newItems[1].age + 1
89
+ * };
90
+ * return newItems;
91
+ * });
92
+ *
93
+ * // With Immer:
94
+ * import { produce } from "immer";
95
+ *
96
+ * items.update(produce((draft) => {
97
+ * // Mutate draft to increase Bob's age by 1.
98
+ * // Results in a new object with this patch applied.
99
+ * draft[1].age++;
100
+ * }));
101
+ */
102
+ update(fn: (current: T) => T): void;
103
+ /**
104
+ * @deprecated use `get()`
105
+ */
43
106
  get value(): T;
107
+ /**
108
+ * @deprecated use `set()`
109
+ */
44
110
  set value(next: T);
45
111
  }
46
112
  /**
@@ -52,9 +118,9 @@ export declare function isReactive<T>(value: any): value is Reactive<T>;
52
118
  * Atom values can be read and updated with the `value` property
53
119
  *
54
120
  * @example
55
- * const count = atom(1);
56
- * count.value++;
57
- * count.value; // 2
121
+ * const count = atom<number>();
122
+ * count.set(5);
123
+ * count.get(); // 5
58
124
  */
59
125
  export declare function atom<T>(): Atom<T | undefined>;
60
126
  /**
@@ -63,8 +129,8 @@ export declare function atom<T>(): Atom<T | undefined>;
63
129
  *
64
130
  * @example
65
131
  * const count = atom(1);
66
- * count.value++;
67
- * count.value; // 2
132
+ * count.set(count.get() + 1);
133
+ * count.get(); // 2
68
134
  */
69
135
  export declare function atom<T>(value: T, options?: ReactiveOptions<T>): Atom<T>;
70
136
  /**
@@ -83,7 +149,7 @@ type ComposeCallback<T> = (previousValue?: T) => MaybeReactive<T>;
83
149
  *
84
150
  * @example
85
151
  * const count = atom(1);
86
- * const doubled = compose(() => get(count) * 2);
152
+ * const doubled = compose(() => count.get() * 2);
87
153
  */
88
154
  export declare function compose<T>(fn: ComposeCallback<T>, options?: ReactiveOptions<T>): Reactive<T>;
89
155
  /**
@@ -115,6 +181,11 @@ export declare function get<T>(value: MaybeReactive<T>): T;
115
181
  * });
116
182
  */
117
183
  export declare function peek<T>(value: MaybeReactive<T>): T;
184
+ export declare function untrack(fn: () => void): void;
185
+ /**
186
+ * Registers a callback that will receive a list of dependencies that were tracked within the scope this function was called in.
187
+ */
188
+ export declare function getTracked(fn: (tracked: Reactive<unknown>[]) => void): void;
118
189
  export type EffectCallback = () => void;
119
190
  /**
120
191
  * Creates a tracked scope that re-runs whenever the values of any tracked reactives changes.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { atom, compose, effect, get, set, peek } from "./core/signals.js";
1
+ export { atom, compose, effect, get, set, peek, untrack, getTracked } from "./core/signals.js";
2
2
  export type { Reactive, MaybeReactive, Atom } from "./core/signals.js";
3
3
  export { deepEqual, shallowEqual, strictEqual } from "./utils.js";
4
4
  export { ref, type Ref } from "./core/ref.js";
@@ -10,6 +10,8 @@ import { Dolla } from "./core/dolla.js";
10
10
  declare const dolla: Dolla;
11
11
  export default dolla;
12
12
  export declare const t: (selector: string, options?: import("./translate/index.js").TOptions) => import("./core/signals.js").Reactive<string>;
13
+ export declare const http: import("./http/index.js").HTTP;
14
+ export declare const createLogger: (name: string, options?: import("./core/dolla.js").LoggerOptions) => import("./core/dolla.js").Logger;
13
15
  export type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from "./core/dolla.js";
14
16
  export type { ViewContext, ViewElement, ViewFunction } from "./core/nodes/view.js";
15
17
  export type { InputType, Renderable } from "./types.js";