@manyducks.co/dolla 2.0.0-alpha.33 → 2.0.0-alpha.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +12 -14
  2. package/dist/core/{batch.d.ts → _batch.d.ts} +4 -0
  3. package/dist/core/context.d.ts +20 -17
  4. package/dist/core/dolla.d.ts +7 -48
  5. package/dist/core/markup.d.ts +9 -31
  6. package/dist/core/nodes/{observer.d.ts → dynamic.d.ts} +8 -10
  7. package/dist/core/nodes/html.d.ts +5 -7
  8. package/dist/core/nodes/{repeat.d.ts → list.d.ts} +12 -14
  9. package/dist/core/nodes/outlet.d.ts +4 -4
  10. package/dist/core/nodes/view.d.ts +22 -18
  11. package/dist/core/ref.d.ts +16 -0
  12. package/dist/core/signals.d.ts +128 -0
  13. package/dist/core/store.d.ts +9 -7
  14. package/dist/core/symbols.d.ts +0 -2
  15. package/dist/{views → core/views}/default-crash-view.d.ts +1 -1
  16. package/dist/{views → core/views}/passthrough.d.ts +2 -2
  17. package/dist/{modules/http.d.ts → http/index.d.ts} +1 -2
  18. package/dist/index.d.ts +8 -11
  19. package/dist/index.js +709 -846
  20. package/dist/index.js.map +1 -1
  21. package/dist/jsx-dev-runtime.d.ts +1 -1
  22. package/dist/jsx-dev-runtime.js +2 -2
  23. package/dist/jsx-dev-runtime.js.map +1 -1
  24. package/dist/jsx-runtime.d.ts +1 -1
  25. package/dist/jsx-runtime.js +2 -2
  26. package/dist/jsx-runtime.js.map +1 -1
  27. package/dist/markup-BWJWLvDF.js +1634 -0
  28. package/dist/markup-BWJWLvDF.js.map +1 -0
  29. package/dist/{modules/router.d.ts → router/index.d.ts} +5 -5
  30. package/dist/router/router.utils.test.d.ts +1 -0
  31. package/dist/{modules/i18n.d.ts → translate/index.d.ts} +20 -16
  32. package/dist/types.d.ts +9 -9
  33. package/docs/signals.md +149 -0
  34. package/docs/views.md +1 -1
  35. package/notes/atomic.md +146 -0
  36. package/package.json +11 -7
  37. package/vite.config.js +3 -0
  38. package/dist/core/state.d.ts +0 -126
  39. package/dist/core/stats.d.ts +0 -31
  40. package/dist/markup-Dbw-610R.js +0 -1525
  41. package/dist/markup-Dbw-610R.js.map +0 -1
  42. package/notes/viewstate.md +0 -15
  43. package/tests/state.test.js +0 -135
  44. /package/dist/{modules/router.utils.test.d.ts → core/signals.test.d.ts} +0 -0
  45. /package/dist/{modules → router}/router.utils.d.ts +0 -0
package/README.md CHANGED
@@ -7,7 +7,7 @@
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](./docs/state.md). Inspired by Signals, but with explicit tracking.
10
+ - ⚡ Reactive DOM updates with [Signals](./docs/state.md).
11
11
  - 📦 Reusable components with [Views](./docs/views.md).
12
12
  - 💾 Reusable state management with [Stores](./docs/stores.md).
13
13
  - 🔀 Built-in [routing](./docs/router.md) with nested routes and middleware support (check login status, preload data, etc).
@@ -35,22 +35,20 @@ Dolla's goals include:
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
37
  ```js
38
- import Dolla, { createState } from "@manyducks.co/dolla";
38
+ import Dolla, { atom, html } from "@manyducks.co/dolla";
39
39
 
40
40
  function Counter() {
41
- const [$count, setCount] = createState(0);
41
+ const count = atom(0);
42
42
 
43
- function increment() {
44
- setCount((count) => count + 1);
45
- }
46
-
47
- function decrement() {
48
- setCount((count) => count - 1);
49
- }
50
-
51
- function reset() {
52
- setCount(0);
53
- }
43
+ return html`
44
+ <div>
45
+ <p>Counter: ${count}</p>
46
+ <div>
47
+ <button onclick=${() => count.value--}>-1</button>
48
+ <button onclick=${() => count.value++}>+1</button>
49
+ </div>
50
+ </div>
51
+ `;
54
52
 
55
53
  return (
56
54
  <div>
@@ -7,11 +7,15 @@ export declare class Batch {
7
7
  constructor(dolla: Dolla);
8
8
  /**
9
9
  * Queues a callback that runs before the next batch of writes.
10
+ *
11
+ * @deprecated
10
12
  */
11
13
  read(callback: () => void): void;
12
14
  /**
13
15
  * Queues a callback to run in the next render batch.
14
16
  * Always put DOM mutations in a write callback when possible to help Dolla batch them efficiently.
17
+ *
18
+ * @deprecated
15
19
  */
16
20
  write(callback: () => void, key?: string): void;
17
21
  }
@@ -1,8 +1,14 @@
1
1
  import type { Emitter } from "@manyducks.co/emitter";
2
2
  import type { Dolla } from "./dolla";
3
3
  import type { Store, StoreFunction } from "./store";
4
- interface ContextEmitterEvents {
5
- [eventName: string | symbol]: [ContextEvent, ...args: any[]];
4
+ export interface GenericEvents {
5
+ [type: string]: [...args: any[]];
6
+ }
7
+ export interface GenericContextData {
8
+ [key: string | symbol]: any;
9
+ }
10
+ export interface ContextEmitterEvents {
11
+ [type: string | symbol]: [ContextEvent, ...args: any[]];
6
12
  }
7
13
  export interface ElementContext {
8
14
  /**
@@ -40,36 +46,32 @@ export interface ElementContext {
40
46
  * ContextEvent objects already have the event name stored as `event.type`.
41
47
  */
42
48
  export type WildcardListenerMap = Map<(event: ContextEvent, ...args: any[]) => void, (eventName: string | symbol, event: ContextEvent, ...args: any[]) => void>;
43
- export interface ComponentContext {
49
+ export interface ComponentContext<Events extends GenericEvents = GenericEvents> {
44
50
  /**
45
- * Sets a context variable and returns its value.
51
+ * A name for debugging purposes. Prepended to log messages.
46
52
  */
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;
53
+ name: string;
52
54
  /**
53
55
  * Adds a listener to be called when an event with a matching `type` is emitted.
54
56
  */
55
- on<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
57
+ on<T extends keyof Events>(type: T, listener: (event: ContextEvent, ...args: Events[T]) => void): void;
56
58
  /**
57
59
  * Removes a listener from the list to be called when an event with a matching `type` is emitted.
58
60
  */
59
- off<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
61
+ off(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
60
62
  /**
61
63
  * Adds a listener to be called when an event with a matching `type` is emitted. The listener is immediately removed after being called once.
62
64
  */
63
- once<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
65
+ once<T extends keyof Events>(type: T, listener: (event: ContextEvent, ...args: Events[T]) => void): void;
64
66
  /**
65
67
  * Emits a new event to all listeners.
66
68
  */
67
- emit<T = unknown>(type: string, ...args: any[]): boolean;
69
+ emit<T extends keyof Events>(type: T, ...args: Events[T]): boolean;
68
70
  }
69
71
  /**
70
- * A context capable of hosting stores.
72
+ * A context capable of providing stores.
71
73
  */
72
- export interface StorableContext extends ComponentContext {
74
+ export interface StoreProviderContext {
73
75
  /**
74
76
  * Attaches a new store to this context and returns it.
75
77
  */
@@ -82,10 +84,12 @@ export interface StorableContext extends ComponentContext {
82
84
  * Attaches a new store to this context and returns it.
83
85
  */
84
86
  provide<Options, Value>(store: StoreFunction<Options, Value>, options: Options): Value;
87
+ }
88
+ export interface StoreConsumerContext {
85
89
  /**
86
90
  * Gets the closest instance of a store. Throws an error if the store isn't provided higher in the tree.
87
91
  */
88
- use<Value>(store: StoreFunction<any, Value>): Value;
92
+ get<Value>(store: StoreFunction<any, Value>): Value;
89
93
  }
90
94
  /**
91
95
  * An event emitted from and received by a Dolla context. These are separate from DOM events.
@@ -98,4 +102,3 @@ export declare class ContextEvent {
98
102
  stop(): void;
99
103
  get [Symbol.toStringTag](): string;
100
104
  }
101
- export {};
@@ -1,13 +1,10 @@
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";
1
+ import { HTTP } from "../http/index.js";
2
+ import { I18n } from "../translate/index.js";
3
+ import { type Router } from "../router/index.js";
4
+ import { type CrashViewProps } from "./views/default-crash-view.js";
5
+ import { type StoreProviderContext, type StoreConsumerContext } from "./context.js";
7
6
  import { type Markup, type MarkupElement } from "./markup.js";
8
7
  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
8
  import { StoreFunction } from "./store.js";
12
9
  export type Environment = "development" | "production";
13
10
  /**
@@ -42,22 +39,11 @@ export type LoggerOptions = {
42
39
  */
43
40
  uid?: string;
44
41
  };
45
- export declare class Dolla implements StorableContext {
42
+ export declare class Dolla implements StoreProviderContext, StoreConsumerContext {
46
43
  #private;
47
- readonly batch: Batch;
48
- private readonly stats;
49
44
  readonly http: HTTP;
50
45
  readonly i18n: I18n;
51
46
  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
47
  /**
62
48
  * True when the app is connected to a DOM node and displayed to the user.
63
49
  */
@@ -85,33 +71,6 @@ export declare class Dolla implements StorableContext {
85
71
  * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.
86
72
  */
87
73
  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 an event with a matching `type` is emitted.
101
- */
102
- on<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
103
- /**
104
- * Removes a listener from the list to be called when an event with a matching `type` is emitted.
105
- */
106
- off<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
107
- /**
108
- * Adds a listener to be called when an event with a matching `type` is emitted. The listener is immediately removed after being called once.
109
- */
110
- once<T = unknown>(type: string, listener: (event: ContextEvent, ...args: any[]) => void): void;
111
- /**
112
- * Emits a new event to all listeners.
113
- */
114
- emit<T = unknown>(type: string, ...args: any[]): boolean;
115
74
  /**
116
75
  * Attaches a new store to this context.
117
76
  */
@@ -127,7 +86,7 @@ export declare class Dolla implements StorableContext {
127
86
  /**
128
87
  * Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.
129
88
  */
130
- use<Value>(store: StoreFunction<any, Value>): Value;
89
+ get<Value>(store: StoreFunction<any, Value>): Value;
131
90
  mount(selector: string, router: Router): Promise<void>;
132
91
  mount(selector: string, view: ViewFunction<any>): Promise<void>;
133
92
  mount(element: Element, router: Router): Promise<void>;
@@ -1,28 +1,7 @@
1
1
  import type { Renderable } from "../types.js";
2
2
  import type { ElementContext } from "./context.js";
3
3
  import { type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
4
- import { type MaybeState, type State } from "./state.js";
5
- import { IS_MARKUP } from "./symbols.js";
6
- export declare class _Markup implements Markup {
7
- [IS_MARKUP]: boolean;
8
- static text(value: MaybeState<string>): _Markup;
9
- static from(renderable: Renderable): Markup;
10
- /**
11
- * 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.
12
- * DOM nodes can be created by name, such as HTML elements like "div", "ul" or "span", SVG elements like ""
13
- */
14
- type: string | ViewFunction<any>;
15
- /**
16
- * Data that will be passed to a new MarkupElement instance when it is constructed.
17
- */
18
- props: Record<string, any> | undefined;
19
- /**
20
- *
21
- */
22
- children: Markup[];
23
- constructor(type: string | ViewFunction<any>, props?: Record<string, any>, children?: Renderable[]);
24
- toElement(context: ElementContext): MarkupElement;
25
- }
4
+ import { MaybeReactive, type Reactive } from "./signals.js";
26
5
  /**
27
6
  * Markup is a set of element metadata that hasn't been constructed into a MarkupElement yet.
28
7
  */
@@ -61,17 +40,16 @@ export interface MarkupAttributes {
61
40
  $text: {
62
41
  value: any;
63
42
  };
64
- $repeat: {
65
- $items: State<any[]>;
43
+ $list: {
44
+ items: Reactive<any[]>;
66
45
  keyFn: (value: any, index: number) => string | number | symbol;
67
- renderFn: ($item: State<any>, $index: State<number>, c: ViewContext) => ViewResult;
46
+ renderFn: (item: Reactive<any>, index: Reactive<number>, ctx: ViewContext) => ViewResult;
68
47
  };
69
- $observer: {
70
- sources: MaybeState<any>[];
71
- renderFn: (...items: any) => Renderable;
48
+ $dynamic: {
49
+ source: Reactive<Renderable>;
72
50
  };
73
51
  $outlet: {
74
- $children: State<MarkupElement[]>;
52
+ children: MaybeReactive<MarkupElement[]>;
75
53
  };
76
54
  $node: {
77
55
  value: Node;
@@ -91,12 +69,12 @@ export declare const html: (strings: TemplateStringsArray, ...values: any[]) =>
91
69
  /**
92
70
  * Displays content conditionally. When `condition` holds a truthy value, `thenContent` is displayed; when `condition` holds a falsy value, `elseContent` is displayed.
93
71
  */
94
- export declare function cond(condition: MaybeState<any>, thenContent?: Renderable, elseContent?: Renderable): Markup;
72
+ export declare function cond(condition: MaybeReactive<any>, thenContent?: Renderable, elseContent?: Renderable): Markup;
95
73
  /**
96
74
  * Calls `renderFn` for each item in `items`. Dynamically adds and removes views as items change.
97
75
  * The result of `keyFn` is used to compare items and decide if item was added, removed or updated.
98
76
  */
99
- 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;
77
+ export declare function list<T>(items: MaybeReactive<T[]>, keyFn: (value: T, index: number) => string | number | symbol, renderFn: (item: Reactive<T>, index: Reactive<number>, ctx: ViewContext) => ViewResult): Markup;
100
78
  /**
101
79
  * Renders `content` into a `parent` node anywhere in the page, rather than its usual position in the view.
102
80
  */
@@ -1,27 +1,25 @@
1
1
  import type { Renderable } from "../../types.js";
2
2
  import type { ElementContext } from "../context.js";
3
3
  import { type MarkupElement } from "../markup.js";
4
- import { type MaybeState } from "../state.js";
4
+ import { type Reactive, type UnsubscribeFunction } from "../signals.js";
5
5
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
6
- interface ObserverOptions {
6
+ interface DynamicOptions {
7
+ source: Reactive<Renderable>;
7
8
  elementContext: ElementContext;
8
- sources: MaybeState<any>[];
9
- renderFn: (...values: any) => Renderable;
10
9
  }
11
10
  /**
12
11
  * Displays dynamic children without a parent element.
13
- * Used when a State is passed as a child in a view template.
12
+ * Renders a Reactive value via a render function.
14
13
  */
15
- export declare class Observer implements MarkupElement {
14
+ export declare class Dynamic implements MarkupElement {
16
15
  [IS_MARKUP_ELEMENT]: boolean;
17
16
  node: Text;
18
17
  children: MarkupElement[];
19
- renderFn: (...values: any) => Renderable;
20
18
  elementContext: ElementContext;
21
- watcher: import("../state.js").StateWatcher;
22
- sources: MaybeState<any>[];
19
+ source: Reactive<Renderable>;
20
+ unsubscribe?: UnsubscribeFunction;
23
21
  get isMounted(): boolean;
24
- constructor({ sources, renderFn, elementContext }: ObserverOptions);
22
+ constructor(options: DynamicOptions);
25
23
  mount(parent: Node, after?: Node): void;
26
24
  unmount(parentIsUnmounting?: boolean): void;
27
25
  cleanup(parentIsUnmounting: boolean): void;
@@ -1,7 +1,7 @@
1
1
  import { type ElementContext } from "../context.js";
2
2
  import { type Markup, type MarkupElement } from "../markup.js";
3
3
  import { type Ref } from "../ref.js";
4
- import { type State, type StopFunction } from "../state.js";
4
+ import { type MaybeReactive, type UnsubscribeFunction } from "../signals.js";
5
5
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
6
6
  type HTMLOptions = {
7
7
  elementContext: ElementContext;
@@ -15,10 +15,9 @@ export declare class HTML implements MarkupElement {
15
15
  props: Record<string, any>;
16
16
  childMarkup: Markup[];
17
17
  children: MarkupElement[];
18
- stopCallbacks: StopFunction[];
18
+ unsubscribers: UnsubscribeFunction[];
19
19
  elementContext: ElementContext;
20
20
  uniqueId: string;
21
- _batchWrite: (callback: () => void, key?: string) => void;
22
21
  ref?: Ref<any>;
23
22
  canClickAway: boolean;
24
23
  get isMounted(): boolean;
@@ -26,11 +25,10 @@ export declare class HTML implements MarkupElement {
26
25
  mount(parent: Node, after?: Node): void;
27
26
  unmount(parentIsUnmounting?: boolean): void;
28
27
  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;
28
+ attachProp<T>(value: MaybeReactive<T>, callback: (value: T) => void): void;
31
29
  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;
30
+ applyStyles(element: HTMLElement | SVGElement, styles: unknown, unsubscribers: UnsubscribeFunction[]): () => void;
31
+ applyClasses(element: HTMLElement | SVGElement, classes: unknown, unsubscribers: UnsubscribeFunction[]): () => void;
34
32
  }
35
33
  /**
36
34
  * Converts a camelCase string to kebab-case.
@@ -1,33 +1,31 @@
1
1
  import { type ElementContext } from "../context.js";
2
2
  import { type MarkupElement } from "../markup.js";
3
- import { type Setter, type State, type StopFunction } from "../state.js";
3
+ import { type Atom, type Reactive, type UnsubscribeFunction } from "../signals.js";
4
4
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
5
5
  import { type ViewContext, type ViewResult } from "./view.js";
6
- interface RepeatOptions<T> {
6
+ interface ListOptions<T> {
7
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;
8
+ items: Reactive<T[]>;
9
+ keyFn: (item: T, index: number) => string | number | symbol;
10
+ renderFn: (item: Reactive<T>, index: Reactive<number>, ctx: ViewContext) => ViewResult;
11
11
  }
12
12
  type ConnectedItem<T> = {
13
13
  key: any;
14
- $value: State<T>;
15
- setValue: Setter<T>;
16
- $index: State<number>;
17
- setIndex: Setter<number>;
14
+ item: Atom<T>;
15
+ index: Atom<number>;
18
16
  element: MarkupElement;
19
17
  };
20
- export declare class Repeat<T> implements MarkupElement {
18
+ export declare class List<T> implements MarkupElement {
21
19
  [IS_MARKUP_ELEMENT]: boolean;
22
20
  node: Text;
23
- $items: State<T[]>;
24
- stopCallback?: StopFunction;
21
+ items: Reactive<T[]>;
22
+ unsubscribe: UnsubscribeFunction | null;
25
23
  connectedItems: ConnectedItem<T>[];
26
24
  elementContext: ElementContext;
27
- renderFn: (this: ViewContext, $value: State<T>, $index: State<number>, context: ViewContext) => ViewResult;
25
+ renderFn: (this: ViewContext, value: Reactive<T>, index: Reactive<number>, context: ViewContext) => ViewResult;
28
26
  keyFn: (value: T, index: number) => string | number | symbol;
29
27
  get isMounted(): boolean;
30
- constructor({ elementContext, $items, renderFn, keyFn }: RepeatOptions<T>);
28
+ constructor({ elementContext, items, renderFn, keyFn }: ListOptions<T>);
31
29
  mount(parent: Node, after?: Node): void;
32
30
  unmount(parentIsUnmounting?: boolean): void;
33
31
  _cleanup(parentIsUnmounting: boolean): void;
@@ -1,5 +1,5 @@
1
1
  import { type MarkupElement } from "../markup.js";
2
- import { type MaybeState, type StopFunction } from "../state.js";
2
+ import { type MaybeReactive, type UnsubscribeFunction } from "../signals.js";
3
3
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
4
4
  /**
5
5
  * Manages several MarkupElements as one.
@@ -8,10 +8,10 @@ export declare class Outlet implements MarkupElement {
8
8
  [IS_MARKUP_ELEMENT]: boolean;
9
9
  node: Text;
10
10
  isMounted: boolean;
11
- source: MaybeState<MarkupElement[]>;
11
+ source: MaybeReactive<MarkupElement[]>;
12
12
  elements: MarkupElement[];
13
- stopCallback?: StopFunction;
14
- constructor(source: MaybeState<MarkupElement[]>);
13
+ unsubscribe?: UnsubscribeFunction;
14
+ constructor(source: MaybeReactive<MarkupElement[]>);
15
15
  mount(parent: Node, after?: Node | undefined): void;
16
16
  unmount(parentIsUnmounting?: boolean): void;
17
17
  cleanup(parentIsUnmounting: boolean): void;
@@ -1,13 +1,13 @@
1
1
  import { Emitter } from "@manyducks.co/emitter";
2
- import { type ElementContext, type StorableContext, type WildcardListenerMap } from "../context.js";
2
+ import { type ComponentContext, type ElementContext, type GenericEvents, type StoreConsumerContext, type StoreProviderContext, type WildcardListenerMap } from "../context.js";
3
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";
4
+ import { cond, list, portal, type Markup, type MarkupElement } from "../markup.js";
5
+ import { type EffectCallback, type Reactive, type UnsubscribeFunction } from "../signals.js";
6
6
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
7
7
  /**
8
8
  * Any valid value that a View can return.
9
9
  */
10
- export type ViewResult = Node | State<any> | Markup | Markup[] | null;
10
+ export type ViewResult = Node | Reactive<any> | Markup | Markup[] | null;
11
11
  export type ViewFunction<P> = (this: ViewContext, props: P, context: ViewContext) => ViewResult;
12
12
  /**
13
13
  * A view that has been constructed into DOM nodes.
@@ -18,18 +18,11 @@ export interface ViewElement extends MarkupElement {
18
18
  */
19
19
  setChildView(view: ViewFunction<{}>): ViewElement;
20
20
  }
21
- export interface ViewContext extends Logger, StorableContext {
21
+ export interface ViewContext<Events extends GenericEvents = GenericEvents> extends Omit<Logger, "setName">, ComponentContext<Events>, StoreProviderContext, StoreConsumerContext {
22
22
  /**
23
23
  * An ID unique to this view.
24
24
  */
25
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
26
  /**
34
27
  * True while this view is connected to the DOM.
35
28
  */
@@ -51,14 +44,26 @@ export interface ViewContext extends Logger, StorableContext {
51
44
  */
52
45
  onUnmount(callback: () => void): void;
53
46
  /**
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.
47
+ * Passes a getter function to `callback` that will track reactive states and return their current values.
48
+ * Callback will be run each time a tracked state gets a new value.
49
+ */
50
+ effect(callback: EffectCallback): UnsubscribeFunction;
51
+ /**
52
+ * Renders a list of reactive items.
53
+ */
54
+ list: typeof list;
55
+ /**
56
+ * Creates a reactive conditional; the second argument is displayed when the condition is true and the third is displayed when the condition is false.
56
57
  */
57
- watch<T extends MaybeState<any>[]>(states: [...T], callback: (...values: StateValues<T>) => void): StopFunction;
58
+ if: typeof cond;
58
59
  /**
59
60
  * Returns a Markup element that displays this view's children.
60
61
  */
61
62
  outlet(): Markup;
63
+ /**
64
+ * Displays an element as a child of another DOM node, rather than the position it would normally be mounted at.
65
+ */
66
+ portal: typeof portal;
62
67
  }
63
68
  type ViewEvents = {
64
69
  beforeMount: [];
@@ -75,9 +80,8 @@ export declare class View<P> implements ViewElement {
75
80
  _props: P;
76
81
  _element?: MarkupElement;
77
82
  _childMarkup: Markup[];
78
- _$children: State<MarkupElement[]>;
79
- _setChildren: import("../state.js").Setter<MarkupElement[], MarkupElement[]>;
80
- _watcher: import("../state.js").StateWatcher;
83
+ _children: import("../signals.js").Atom<MarkupElement[]>;
84
+ _unsubscribes: UnsubscribeFunction[];
81
85
  _emitter: Emitter<ViewEvents>;
82
86
  _wildcardListeners: WildcardListenerMap;
83
87
  constructor(elementContext: ElementContext, view: ViewFunction<P>, props: P, children?: Markup[]);
@@ -19,6 +19,8 @@ export interface Ref<T> {
19
19
  *
20
20
  * @param value - An (optional) initial value to store.
21
21
  *
22
+ * @deprecated
23
+ *
22
24
  * @example
23
25
  * const ref = createRef(5);
24
26
  * ref(); // 5
@@ -26,4 +28,18 @@ export interface Ref<T> {
26
28
  * ref(); // 500
27
29
  */
28
30
  export declare function createRef<T>(value?: T): Ref<T>;
31
+ /**
32
+ * A Ref is a function that returns the last argument it was called with.
33
+ * Calling it with no arguments will simply return the latest value.
34
+ * Calling it with an argument will store that value and immediately return it.
35
+ *
36
+ * @param value - An (optional) initial value to store.
37
+ *
38
+ * @example
39
+ * const number = ref(5);
40
+ * number(); // 5
41
+ * number(500);
42
+ * number(); // 500
43
+ */
44
+ export declare function ref<T>(value?: T): Ref<T>;
29
45
  export declare function isRef<T extends Node>(value: any): value is Ref<T>;