@manyducks.co/dolla 2.0.0-alpha.22 → 2.0.0-alpha.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,8 +20,8 @@ Let's first get into some examples.
20
20
 
21
21
  ### Basic State API
22
22
 
23
- ```jsx
24
- import { createState, toState, valueOf, derive, createWatcher } from "@manyducks.co/dolla";
23
+ ```js
24
+ import { createState, derive } from "@manyducks.co/dolla";
25
25
 
26
26
  const [$count, setCount] = createState(72);
27
27
 
@@ -35,26 +35,24 @@ $count.get(); // 300
35
35
  // You can also pass a function that takes the current value and returns a new one
36
36
  setCount((current) => current + 1);
37
37
  $count.get(); // 301
38
+ ```
38
39
 
39
- // Derive a new state from one or more other states. Whenever $count changes, $doubled will follow.
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.
40
44
  const $doubled = derive([$count], (count) => count * 2);
41
- const $sum = derive([$count, $doubled], (count, doubled) => count + doubled);
42
45
 
43
- // Returns the value of a state. If the value is not a state it is returned as is.
44
- const count = valueOf($count);
45
- const bool = valueOf(true);
46
+ $doubled.get(); // 602
46
47
 
47
- // Creates a state from a value. If the value is already a state it is returned as is.
48
- const $bool = toState(true);
49
- const $anotherCount = toState($count);
48
+ setCount(500);
50
49
 
51
- const watcher = createWatcher();
50
+ $doubled.get(); // 1000
51
+ ```
52
+
53
+ ### In Views
52
54
 
53
- // Watch for changes to the value
54
- const stop = watcher.watch([$count], (value) => [
55
- // This function is called immediately with the current value, then again each time the value changes.
56
- ]);
57
- stop(); // Stop watching for changes
55
+ ```jsx
58
56
 
59
57
  ```
60
58
 
@@ -105,12 +103,12 @@ $doubled(); // 100
105
103
  $value(); // 50
106
104
  ```
107
105
 
108
- ## Views [id="section-views"]
106
+ <h2 id="section-views">Views</h2>
109
107
 
110
108
  A basic view:
111
109
 
112
110
  ```js
113
- import Dolla, { createState, html } from "@manyducks.co/dolla";
111
+ import Dolla, { createState } from "@manyducks.co/dolla";
114
112
 
115
113
  function Counter(props, ctx) {
116
114
  const [$count, setCount] = createState(0);
@@ -119,12 +117,24 @@ function Counter(props, ctx) {
119
117
  setCount((count) => count + 1);
120
118
  }
121
119
 
122
- return html`
120
+ function decrement() {
121
+ setCount((count) => count - 1);
122
+ }
123
+
124
+ function reset() {
125
+ setCount(0);
126
+ }
127
+
128
+ return (
123
129
  <div>
124
- <p>Clicks: ${$count}</p>
125
- <button onclick=${increment}>+1</button>
130
+ <p>Clicks: {$count}</p>
131
+ <div>
132
+ <button onClick={decrement}>-1</button>
133
+ <button onClick={reset}>0</button>
134
+ <button onClick={increment}>-1</button>
135
+ </div>
126
136
  </div>
127
- `;
137
+ );
128
138
  }
129
139
 
130
140
  Dolla.mount(document.body, Counter);
@@ -1,8 +1,8 @@
1
- import { type Markup, type MarkupElement } from "./markup.js";
2
- import { createRef, createSettableState, createState, createWatcher, derive, isRef, toSettableState, toState, valueOf } from "./state.js";
3
- import { type ViewElement, type ViewFunction } from "./view.js";
4
1
  import { type CrashViewProps } from "../views/default-crash-view.js";
5
2
  import { Batch } from "./batch.js";
3
+ import { type Markup, type MarkupElement } from "./markup.js";
4
+ import { type ViewElement, type ViewFunction } from "./nodes/view.js";
5
+ import { createRef, createSettableState, createState, createWatcher, derive, isRef, toSettableState, toState, valueOf } from "./state.js";
6
6
  import { HTTP } from "../modules/http.js";
7
7
  import { I18n } from "../modules/i18n.js";
8
8
  import { Router } from "../modules/router.js";
@@ -39,6 +39,10 @@ export type LoggerOptions = {
39
39
  */
40
40
  uid?: string;
41
41
  };
42
+ export interface DollaModuleConfig<Options = never> {
43
+ root: Dolla;
44
+ options: Options;
45
+ }
42
46
  export declare class Dolla {
43
47
  #private;
44
48
  readonly batch: Batch;
@@ -75,6 +79,17 @@ export declare class Dolla {
75
79
  * When a crash is reported the app will be unmounted and replaced with this crash page.
76
80
  */
77
81
  setCrashView(view: ViewFunction<CrashViewProps>): void;
82
+ /**
83
+ * Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.
84
+ */
85
+ getRootElement(): HTMLElement | undefined;
86
+ /**
87
+ * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.
88
+ */
89
+ getRootView(): ViewElement | undefined;
90
+ /**
91
+ * Registers a Dolla module.
92
+ */
78
93
  /**
79
94
  * Sets a context variable and returns its value. Context variables are accessible on the app and in child views.
80
95
  */
@@ -123,3 +138,4 @@ export declare class Dolla {
123
138
  */
124
139
  constructMarkup(markup: Markup | Markup[]): MarkupElement;
125
140
  }
141
+ export declare function getDefaultConsole(): any;
@@ -1,7 +1,7 @@
1
+ import type { Renderable, Stringable } from "../types.js";
1
2
  import type { Dolla } from "./dolla.js";
3
+ import { type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
2
4
  import { MaybeState, type State } from "./state.js";
3
- import type { Renderable, Stringable } from "../types.js";
4
- import { type ViewContext, type ViewFunction, type ViewResult } from "./view.js";
5
5
  export interface ElementContext {
6
6
  /**
7
7
  * The root Dolla instance this element belongs to.
@@ -50,8 +50,8 @@ export interface MarkupElement {
50
50
  */
51
51
  unmount(parentIsUnmounting?: boolean): void;
52
52
  }
53
- export declare function isMarkup(value: unknown): value is Markup;
54
- export declare function isMarkupElement(value: unknown): value is MarkupElement;
53
+ export declare function isMarkup(value: any): value is Markup;
54
+ export declare function isMarkupElement(value: any): value is MarkupElement;
55
55
  export declare function toMarkup(renderables: Renderable | Renderable[]): Markup[];
56
56
  export interface MarkupAttributes {
57
57
  $text: {
@@ -109,5 +109,5 @@ export declare function constructMarkup(elementContext: ElementContext, markup:
109
109
  /**
110
110
  * Combines one or more MarkupElements into a single MarkupElement.
111
111
  */
112
- export declare function groupElements(nodes: MarkupElement[]): MarkupElement;
112
+ export declare function groupElements(elements: MarkupElement[]): MarkupElement;
113
113
  export declare function isRenderable(value: unknown): value is Renderable;
@@ -1,6 +1,7 @@
1
- import { type MarkupElement, type ElementContext, type Markup } from "../markup.js";
2
- import { type State, type StopFunction } from "../state.js";
3
1
  import { type Renderable } from "../../types.js";
2
+ import { type ElementContext, type Markup, type MarkupElement } from "../markup.js";
3
+ import { type State, type StopFunction } from "../state.js";
4
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
4
5
  export interface ConditionalConfig {
5
6
  $predicate: State<any>;
6
7
  thenContent?: Renderable;
@@ -8,6 +9,7 @@ export interface ConditionalConfig {
8
9
  elementContext: ElementContext;
9
10
  }
10
11
  export declare class Conditional implements MarkupElement {
12
+ [TYPE_MARKUP_ELEMENT]: boolean;
11
13
  node: Node;
12
14
  endNode: Node;
13
15
  $predicate: State<any>;
@@ -1,5 +1,6 @@
1
1
  import { type ElementContext, type Markup, type MarkupElement } from "../markup.js";
2
2
  import { type Ref, type State, type StopFunction } from "../state.js";
3
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
3
4
  type HTMLOptions = {
4
5
  elementContext: ElementContext;
5
6
  tag: string;
@@ -7,12 +8,14 @@ type HTMLOptions = {
7
8
  children?: Markup[];
8
9
  };
9
10
  export declare class HTML implements MarkupElement {
11
+ [TYPE_MARKUP_ELEMENT]: boolean;
10
12
  node: HTMLElement | SVGElement;
11
13
  props: Record<string, any>;
12
14
  children: MarkupElement[];
13
15
  stopCallbacks: StopFunction[];
14
16
  elementContext: ElementContext;
15
17
  uniqueId: string;
18
+ _batchWrite: (callback: () => void, key?: string) => void;
16
19
  ref?: Ref<any>;
17
20
  canClickAway: boolean;
18
21
  get isMounted(): boolean;
@@ -20,6 +23,7 @@ export declare class HTML implements MarkupElement {
20
23
  mount(parent: Node, after?: Node): void;
21
24
  unmount(parentIsUnmounting?: boolean): void;
22
25
  getUpdateKey(type: string, value: string | number): string;
26
+ _mutate(callback: () => any, updateKey?: string): void;
23
27
  attachProp<T>(value: State<T> | T, callback: (value: T) => void, updateKey: string): void;
24
28
  applyProps(element: HTMLElement | SVGElement, props: Record<string, unknown>): void;
25
29
  applyStyles(element: HTMLElement | SVGElement, styles: unknown, stopCallbacks: StopFunction[]): () => void;
@@ -1,6 +1,7 @@
1
+ import type { Renderable } from "../../types.js";
1
2
  import { type ElementContext, type MarkupElement } from "../markup.js";
2
3
  import { type State } from "../state.js";
3
- import type { Renderable } from "../../types.js";
4
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
4
5
  interface ObserverOptions {
5
6
  elementContext: ElementContext;
6
7
  states: State<any>[];
@@ -8,8 +9,10 @@ interface ObserverOptions {
8
9
  }
9
10
  /**
10
11
  * Displays dynamic children without a parent element.
12
+ * Used when a State is passed as a child in a view template.
11
13
  */
12
14
  export declare class Observer implements MarkupElement {
15
+ [TYPE_MARKUP_ELEMENT]: boolean;
13
16
  node: Node;
14
17
  endNode: Node;
15
18
  connectedViews: MarkupElement[];
@@ -1,21 +1,17 @@
1
- import { type MarkupElement, type ElementContext } from "../markup.js";
2
- import { type State, type StopFunction } from "../state.js";
3
- export interface OutletConfig {
4
- $children: State<MarkupElement[]>;
5
- elementContext: ElementContext;
6
- }
1
+ import { type MarkupElement } from "../markup.js";
2
+ import { MaybeState, type StopFunction } from "../state.js";
3
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
7
4
  /**
8
- * Manages an array of DOMHandles.
5
+ * Manages several MarkupElements as one.
9
6
  */
10
7
  export declare class Outlet implements MarkupElement {
11
- node: Node;
12
- endNode: Node;
13
- $children: State<MarkupElement[]>;
8
+ [TYPE_MARKUP_ELEMENT]: boolean;
9
+ node: Text;
10
+ isMounted: boolean;
11
+ elements: MaybeState<MarkupElement[]>;
12
+ children: MarkupElement[];
14
13
  stopCallback?: StopFunction;
15
- mountedChildren: MarkupElement[];
16
- elementContext: ElementContext;
17
- constructor(config: OutletConfig);
18
- get isMounted(): boolean;
14
+ constructor(elements: MaybeState<MarkupElement[]>);
19
15
  mount(parent: Node, after?: Node | undefined): void;
20
16
  unmount(parentIsUnmounting?: boolean): void;
21
17
  update(newChildren: MarkupElement[]): void;
@@ -1,5 +1,6 @@
1
- import { type MarkupElement, type ElementContext } from "../markup.js";
2
1
  import { type Renderable } from "../../types.js";
2
+ import { type ElementContext, type MarkupElement } from "../markup.js";
3
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
3
4
  interface PortalConfig {
4
5
  content: Renderable;
5
6
  parent: Node;
@@ -9,6 +10,7 @@ interface PortalConfig {
9
10
  * Renders content into a specified parent node.
10
11
  */
11
12
  export declare class Portal implements MarkupElement {
13
+ [TYPE_MARKUP_ELEMENT]: boolean;
12
14
  config: PortalConfig;
13
15
  element?: MarkupElement;
14
16
  get isMounted(): boolean;
@@ -1,6 +1,7 @@
1
- import { type MarkupElement, type ElementContext } from "../markup.js";
2
- import { type State, type Setter, type StopFunction } from "../state.js";
3
- import { type ViewContext, type ViewResult } from "../view.js";
1
+ import { type ElementContext, type MarkupElement } from "../markup.js";
2
+ import { type Setter, type State, type StopFunction } from "../state.js";
3
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
4
+ import { type ViewContext, type ViewResult } from "./view.js";
4
5
  interface RepeatOptions<T> {
5
6
  elementContext: ElementContext;
6
7
  $items: State<T[]>;
@@ -16,6 +17,7 @@ type ConnectedItem<T> = {
16
17
  element: MarkupElement;
17
18
  };
18
19
  export declare class Repeat<T> implements MarkupElement {
20
+ [TYPE_MARKUP_ELEMENT]: boolean;
19
21
  node: Node;
20
22
  endNode: Node;
21
23
  $items: State<T[]>;
@@ -1,5 +1,6 @@
1
1
  import { type MarkupElement } from "../markup.js";
2
2
  import { type MaybeState, type StopFunction } from "../state.js";
3
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
3
4
  interface Stringable {
4
5
  toString(): string;
5
6
  }
@@ -7,6 +8,7 @@ interface TextOptions {
7
8
  value: MaybeState<Stringable>;
8
9
  }
9
10
  export declare class Text implements MarkupElement {
11
+ [TYPE_MARKUP_ELEMENT]: boolean;
10
12
  node: globalThis.Text;
11
13
  value: MaybeState<Stringable>;
12
14
  stopCallback?: StopFunction;
@@ -1,6 +1,7 @@
1
- import type { Logger } from "./dolla.js";
2
- import { type ElementContext, type Markup, type MarkupElement } from "./markup.js";
3
- import { type MaybeState, State, type StateValues, type StopFunction } from "./state.js";
1
+ import type { Logger } from "../dolla.js";
2
+ import { type ElementContext, type Markup, type MarkupElement } from "../markup.js";
3
+ import { type MaybeState, type State, type StateValues, type StopFunction } from "../state.js";
4
+ import { TYPE_MARKUP_ELEMENT } from "../symbols.js";
4
5
  /**
5
6
  * Any valid value that a View can return.
6
7
  */
@@ -17,7 +18,7 @@ export interface ViewElement extends MarkupElement {
17
18
  }
18
19
  export interface ViewContext extends Logger {
19
20
  /**
20
- * A string ID unique to this view.
21
+ * An ID unique to this view.
21
22
  */
22
23
  readonly uid: string;
23
24
  /**
@@ -63,6 +64,7 @@ export interface ViewContext extends Logger {
63
64
  outlet(): Markup;
64
65
  }
65
66
  export declare class View<P> implements ViewElement {
67
+ [TYPE_MARKUP_ELEMENT]: boolean;
66
68
  uniqueId: string;
67
69
  _elementContext: ElementContext;
68
70
  _logger: Logger;
@@ -70,8 +72,8 @@ export declare class View<P> implements ViewElement {
70
72
  _props: P;
71
73
  _element?: MarkupElement;
72
74
  _$children: State<MarkupElement[]>;
73
- _setChildren: import("./state.js").Setter<MarkupElement[], MarkupElement[]>;
74
- _watcher: import("./state.js").StateWatcher;
75
+ _setChildren: import("../state.js").Setter<MarkupElement[], MarkupElement[]>;
76
+ _watcher: import("../state.js").StateWatcher;
75
77
  _beforeMountCallbacks: (() => any)[];
76
78
  _onMountCallbacks: (() => any)[];
77
79
  _beforeUnmountCallbacks: (() => any)[];
@@ -1,3 +1,5 @@
1
+ import { strictEqual } from "../utils";
2
+ import { TYPE_SETTABLE_STATE, TYPE_STATE } from "./symbols";
1
3
  /**
2
4
  * Stops the observer that created it when called.
3
5
  */
@@ -63,8 +65,6 @@ export interface SettableState<I, O = I> extends State<I> {
63
65
  export interface Ref<T extends Node> extends State<T | undefined> {
64
66
  node: T | undefined;
65
67
  }
66
- declare const TYPE_STATE: unique symbol;
67
- declare const TYPE_SETTABLE_STATE: unique symbol;
68
68
  export declare function isState<T>(value: any): value is State<T>;
69
69
  export declare function isSettableState<T>(value: any): value is SettableState<T>;
70
70
  export declare function isRef<T extends Node>(value: any): value is Ref<T>;
@@ -77,10 +77,9 @@ export declare function valueOf<T>(value: MaybeState<T>): T;
77
77
  */
78
78
  export declare function toState<T>(value: MaybeState<T>): State<T>;
79
79
  export declare class ValueHolder<T> implements State<T> {
80
- static defaultEquals(next: any, current: any): boolean;
81
80
  value: T;
82
81
  watchers: ((value: T) => void)[];
83
- equals: typeof ValueHolder.defaultEquals;
82
+ equals: typeof strictEqual;
84
83
  constructor(value: T, options?: CreateStateOptions<T>);
85
84
  get(): T;
86
85
  set(action: T | SetFunction<T>): void;
@@ -0,0 +1,5 @@
1
+ export declare const TYPE_STATE: unique symbol;
2
+ export declare const TYPE_SETTABLE_STATE: unique symbol;
3
+ export declare const TYPE_REF: unique symbol;
4
+ export declare const TYPE_MARKUP: unique symbol;
5
+ export declare const TYPE_MARKUP_ELEMENT: unique symbol;
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ export declare function getDevDebug(): boolean;
12
12
  export type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from "./core/dolla.js";
13
13
  export type { HTTPRequest, HTTPResponse } from "./modules/http.js";
14
14
  export type { InputType, Renderable } from "./types.js";
15
- export type { ViewContext, ViewFunction, ViewElement as ViewNode } from "./core/view.js";
15
+ export type { ViewContext, ViewFunction, ViewElement as ViewNode } from "./core/nodes/view.js";
16
16
  export type { CrashViewProps } from "./views/default-crash-view.js";
17
17
  import type { IntrinsicElements as Elements } from "./types";
18
18
  declare global {