@manyducks.co/dolla 2.0.0-alpha.60 → 2.0.0-alpha.62

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 (53) hide show
  1. package/dist/core/context.d.ts +23 -6
  2. package/dist/core/context.test.d.ts +1 -0
  3. package/dist/core/index.d.ts +6 -5
  4. package/dist/core/logger.test.d.ts +0 -0
  5. package/dist/core/markup.d.ts +12 -39
  6. package/dist/core/markup.test.d.ts +0 -0
  7. package/dist/core/mount.test.d.ts +0 -0
  8. package/dist/core/nodes/_markup.d.ts +36 -0
  9. package/dist/core/nodes/dom.d.ts +5 -6
  10. package/dist/core/nodes/dynamic.d.ts +6 -13
  11. package/dist/core/nodes/{html.d.ts → element.d.ts} +9 -8
  12. package/dist/core/nodes/portal.d.ts +6 -7
  13. package/dist/core/nodes/repeat.d.ts +8 -6
  14. package/dist/core/nodes/view.d.ts +6 -5
  15. package/dist/core/ref.test.d.ts +1 -0
  16. package/dist/core/signals.d.ts +17 -2
  17. package/dist/core/views/default-crash-view.d.ts +5 -2
  18. package/dist/core/views/for.d.ts +23 -0
  19. package/dist/core/views/show.d.ts +26 -0
  20. package/dist/hooks/index.d.ts +64 -0
  21. package/dist/hooks/index.test.d.ts +1 -0
  22. package/dist/hooks.js +69 -0
  23. package/dist/hooks.js.map +1 -0
  24. package/dist/i18n.js +49 -49
  25. package/dist/i18n.js.map +1 -1
  26. package/dist/index.js +61 -58
  27. package/dist/index.js.map +1 -1
  28. package/dist/jsx-dev-runtime.js +1 -1
  29. package/dist/jsx-runtime.js +1 -1
  30. package/dist/logger-Bl496yfY.js +91 -0
  31. package/dist/logger-Bl496yfY.js.map +1 -0
  32. package/dist/markup-UzKSsawX.js +1037 -0
  33. package/dist/markup-UzKSsawX.js.map +1 -0
  34. package/dist/ref-BD79iqlg.js +15 -0
  35. package/dist/ref-BD79iqlg.js.map +1 -0
  36. package/dist/router/router.d.ts +33 -18
  37. package/dist/{router-BpuJQ6OA.js → router-BXBX8lnO.js} +217 -190
  38. package/dist/router-BXBX8lnO.js.map +1 -0
  39. package/dist/router.js +1 -1
  40. package/dist/signals-gCwiIe5X.js +450 -0
  41. package/dist/signals-gCwiIe5X.js.map +1 -0
  42. package/dist/types.d.ts +1 -1
  43. package/docs/hooks.md +211 -0
  44. package/docs/i18n.md +1 -1
  45. package/notes/scratch.md +23 -1
  46. package/package.json +5 -1
  47. package/vite.config.js +1 -0
  48. package/dist/core/symbols.d.ts +0 -2
  49. package/dist/logger-MPwl-Xqu.js +0 -524
  50. package/dist/logger-MPwl-Xqu.js.map +0 -1
  51. package/dist/markup-BGlfQYQk.js +0 -996
  52. package/dist/markup-BGlfQYQk.js.map +0 -1
  53. package/dist/router-BpuJQ6OA.js.map +0 -1
@@ -52,6 +52,22 @@ declare class ContextLifecycle {
52
52
  */
53
53
  private notify;
54
54
  }
55
+ export interface ContextGetStateOptions<T> {
56
+ fallback?: T;
57
+ /**
58
+ * Only check this context; skip parent contexts.
59
+ */
60
+ immediate?: boolean;
61
+ }
62
+ export interface ContextGetStateOptionsWithFallbackValue<T> extends ContextGetStateOptions<T> {
63
+ fallback: T;
64
+ }
65
+ export interface ContextGetStateMapOptions {
66
+ /**
67
+ * Only include state from this context; skip parent contexts.
68
+ */
69
+ immediate?: boolean;
70
+ }
55
71
  export interface ContextOptions {
56
72
  logger?: LoggerOptions;
57
73
  }
@@ -118,17 +134,20 @@ export declare class Context implements Logger {
118
134
  onUnmount(listener: LifecycleListener): () => void;
119
135
  effect(callback: EffectFn): UnsubscribeFn;
120
136
  /**
121
- * Gets the value stored at `key`, or returns the `defaultValue` if none is set.
137
+ * Gets the value stored at `key`, or returns `options.fallback` if none is set.
122
138
  */
123
- getState<T>(key: any, defaultValue: T): T;
139
+ getState<T>(key: any, options: ContextGetStateOptionsWithFallbackValue<T>): T;
124
140
  /**
125
141
  * Gets the value stored at `key`, or throws an error if none is set.
126
142
  */
127
- getState<T>(key: any): T;
143
+ getState<T>(key: any, options?: ContextGetStateOptions<T>): T;
128
144
  /**
129
145
  * Returns a Map containing all state values available to this context.
146
+ *
147
+ * Pass `options.immediate` to only include state stored on this context.
148
+ * By default all state stored on parent contexts is also included.
130
149
  */
131
- getState(): Map<any, any>;
150
+ getStateMap(options?: ContextGetStateMapOptions): Map<any, any>;
132
151
  /**
133
152
  * Stores `value` at `key` in this context's state.
134
153
  */
@@ -139,6 +158,4 @@ export declare class Context implements Logger {
139
158
  setState(entries: [key: any, value: any][]): void;
140
159
  }
141
160
  export declare function createContext(name: MaybeSignal<string>, options?: ContextOptions): Context;
142
- export declare class StoreError extends Error {
143
- }
144
161
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,16 +1,17 @@
1
- export { $, effect, get, untracked, batch } from "./signals.js";
1
+ export { $, batch, effect, get, untracked } from "./signals.js";
2
2
  export type { MaybeSignal, Signal, Source } from "./signals.js";
3
3
  export { createContext } from "./context.js";
4
4
  export type { Context } from "./context.js";
5
- export { m, portal, render, repeat, unless, when } from "./markup.js";
6
- export type { MarkupNode } from "./markup.js";
5
+ export { m, MarkupNode, portal, render, repeat, unless, when } from "./markup.js";
7
6
  export { ref, type Ref } from "./ref.js";
7
+ export { For, type ForProps } from "./views/for.js";
8
+ export { Show, type ShowProps } from "./views/show.js";
8
9
  export { mount, type UnmountFn } from "./mount.js";
9
10
  export { deepEqual, shallowEqual, strictEqual } from "../utils.js";
10
11
  export { getEnv, setEnv } from "./env.js";
11
- export { createLogger, setLogFilter, setLogLevels, onLoggerCrash } from "./logger.js";
12
+ export { createLogger, onLoggerCrash, setLogFilter, setLogLevels } from "./logger.js";
12
13
  export type { Logger, LoggerCrashProps, LoggerOptions, LogLevels } from "./logger.js";
13
- export type { View, Store, Mixin, InputType, Renderable, Env, CSSProperties } from "../types.js";
14
+ export type { CSSProperties, Env, InputType, Mixin, Renderable, Store, View } from "../types.js";
14
15
  export type { CrashViewProps } from "./views/default-crash-view.js";
15
16
  import type { IntrinsicElements as Elements } from "../types.js";
16
17
  declare global {
File without changes
@@ -1,9 +1,11 @@
1
1
  import type { IntrinsicElements, Renderable, View } from "../types.js";
2
2
  import { Context } from "./context.js";
3
+ import { MarkupNode } from "./nodes/_markup.js";
3
4
  import { KeyFn, RenderFn } from "./nodes/repeat.js";
4
5
  import { type MaybeSignal, type Signal } from "./signals.js";
6
+ export { MarkupNode };
5
7
  /**
6
- * Markup is a set of element metadata that hasn't been constructed into a MarkupElement yet.
8
+ * `Markup` is a set of metadata that will be constructed into a `MarkupNode`.
7
9
  */
8
10
  export declare class Markup<P = any> {
9
11
  /**
@@ -18,38 +20,6 @@ export declare class Markup<P = any> {
18
20
  props: P | undefined;
19
21
  constructor(type: string | View<P>, props?: P);
20
22
  }
21
- /**
22
- * A mountable node that has been constructed from Markup metadata.
23
- */
24
- export interface MarkupNode {
25
- /**
26
- *
27
- */
28
- readonly root?: Node;
29
- /**
30
- * Returns true when this MarkupNode is mounted.
31
- */
32
- isMounted(): boolean;
33
- /**
34
- * Mount this MarkupNode to a `parent` element.
35
- * If passed, this MarkupNode will be mounted as the next sibling of `after`.
36
- */
37
- mount(parent: Element, after?: Node): void;
38
- /**
39
- * Unmount this MarkupNode from its parent element.
40
- *
41
- * The `skipDOM` option can be passed as an optimization when unmounting a parent node.
42
- * A value of `true` indicates that no DOM operations need to happen because the parent is already being unmounted.
43
- *
44
- * @param skipDOM - No DOM updates will be performed when true. Lifecycle methods will be called regardless.
45
- */
46
- unmount(skipDOM?: boolean): void;
47
- /**
48
- * Moves a node without unmounting and remounting (if the browser supports Element.moveBefore).
49
- */
50
- move(parent: Element, after?: Node): void;
51
- }
52
- export declare function isMarkupNode(value: any): value is MarkupNode;
53
23
  export declare enum MarkupType {
54
24
  DOM = "$dom",
55
25
  Dynamic = "$dynamic",
@@ -80,25 +50,25 @@ export interface MarkupCustomElementProps {
80
50
  [tag: `${string}-${string}`]: Record<string, any>;
81
51
  }
82
52
  /**
83
- * Creates a Markup element that defines an HTML element.
53
+ * Creates a `Markup` element that defines an HTML element.
84
54
  */
85
55
  export declare function m<T extends keyof IntrinsicElements>(tag: T, attrs: IntrinsicElements[T] & {
86
56
  children?: Renderable;
87
57
  }): Markup;
88
58
  /**
89
- * Creates a Markup element that defines an HTML custom element.
59
+ * Creates a `Markup` element that defines an HTML custom element.
90
60
  */
91
61
  export declare function m<T extends keyof MarkupCustomElementProps>(type: T, props: MarkupCustomElementProps[T]): Markup;
92
62
  /**
93
- * Creates a Markup element that defines a MarkupNode.
63
+ * Creates a `Markup` element that defines a `MarkupNode`.
94
64
  */
95
65
  export declare function m<T extends keyof MarkupNodeProps>(type: T, props: MarkupNodeProps[T]): Markup;
96
66
  /**
97
- * Creates a Markup element that defines a view.
67
+ * Creates a `Markup` element that defines a view.
98
68
  */
99
69
  export declare function m<P extends {}>(type: View<P>, props?: P): Markup;
100
70
  /**
101
- * Creates a Markup element that defines a view.
71
+ * Creates a `Markup` element that defines a view.
102
72
  */
103
73
  export declare function m<P>(type: View<P>, props: P): Markup;
104
74
  /**
@@ -118,8 +88,11 @@ export declare function repeat<T>(items: MaybeSignal<T[]>, key: KeyFn<T>, render
118
88
  * Renders `content` into a `parent` node anywhere in the page, rather than its usual position in the view.
119
89
  */
120
90
  export declare function portal(parent: Element, content: Renderable): Markup;
91
+ /**
92
+ * Takes any `Renderable` value and returns a `MarkupNode` that will display it.
93
+ */
121
94
  export declare function render(content: Renderable, context?: Context): MarkupNode;
122
95
  /**
123
- * Convert basically anything into a set of MarkupElements.
96
+ * Convert basically anything into a set of `MarkupNode`s.
124
97
  */
125
98
  export declare function toMarkupNodes(context: Context, ...content: any[]): MarkupNode[];
File without changes
File without changes
@@ -0,0 +1,36 @@
1
+ /**
2
+ * A node that can be mounted by the Markup layout engine. Can be extended to create new custom node types.
3
+ *
4
+ * A `MarkupNode` instance can be passed anywhere a `Renderable` is required.
5
+ */
6
+ export declare abstract class MarkupNode {
7
+ /**
8
+ * Returns a single DOM node to represent this MarkupNode's position in the DOM.
9
+ * Usually the parent element, but it can be an empty Text node used as a marker.
10
+ *
11
+ * It only needs to be defined while the node is mounted, so it can be created in the `mount` function.
12
+ */
13
+ getRoot(): Node | undefined;
14
+ /**
15
+ * Returns true while this node is mounted.
16
+ */
17
+ isMounted(): boolean;
18
+ /**
19
+ * Mount this node to a `parent` element.
20
+ * If passed, this node will be mounted as the next sibling of `after`.
21
+ */
22
+ mount(parent: Element, after?: Node): void;
23
+ /**
24
+ * Unmount this MarkupNode from its parent element.
25
+ *
26
+ * The `skipDOM` option can be passed as an optimization when unmounting a parent node.
27
+ * A value of `true` indicates that no DOM operations need to happen because the parent is already being unmounted.
28
+ *
29
+ * @param skipDOM - No DOM updates will be performed when true. Lifecycle methods will be called regardless.
30
+ */
31
+ unmount(skipDOM?: boolean): void;
32
+ /**
33
+ * Moves a node without unmounting and remounting (if the browser supports Element.moveBefore).
34
+ */
35
+ move(parent: Element, after?: Node): void;
36
+ }
@@ -1,12 +1,11 @@
1
- import type { MarkupNode } from "../markup";
2
- import { TYPE } from "../symbols";
1
+ import { MarkupNode } from "./_markup";
3
2
  /**
4
- * Lightweight MarkupNode wrapper for a plain DOM node.
3
+ * A lightweight MarkupNode wrapper for a plain DOM node.
5
4
  */
6
- export declare class DOMNode implements MarkupNode {
7
- [TYPE]: symbol;
8
- root: Node;
5
+ export declare class DOMNode extends MarkupNode {
6
+ private root;
9
7
  constructor(node: Node);
8
+ getRoot(): Node;
10
9
  isMounted(): boolean;
11
10
  mount(parent: Element, after?: Node): void;
12
11
  unmount(skipDOM?: boolean): void;
@@ -1,29 +1,22 @@
1
1
  import type { Context } from "../context.js";
2
- import { type MarkupNode } from "../markup.js";
3
2
  import { type Signal } from "../signals.js";
4
- import { TYPE } from "../symbols.js";
3
+ import { MarkupNode } from "./_markup.js";
5
4
  /**
6
- * Displays dynamic children without a parent element.
7
- * Renders a Reactive value via a render function.
8
- *
9
- * This is probably the most used element type aside from HTML.
5
+ * Renders any kind of content; markup, signals, DOM nodes, etc.
6
+ * If it can be rendered by Dolla then Dynamic will do it.
10
7
  */
11
- export declare class Dynamic implements MarkupNode {
12
- [TYPE]: symbol;
13
- root: Text;
8
+ export declare class DynamicNode extends MarkupNode {
9
+ private root;
14
10
  private children;
15
11
  private context;
16
12
  private $slot;
17
13
  private unsubscribe?;
18
14
  constructor(context: Context, $slot: Signal<any>);
15
+ getRoot(): Text;
19
16
  isMounted(): boolean;
20
17
  mount(parent: Node, after?: Node): void;
21
18
  unmount(skipDOM?: boolean): void;
22
19
  move(parent: Element, after?: Node): void;
23
20
  private cleanup;
24
21
  private update;
25
- /**
26
- * Move marker node to end of children.
27
- */
28
- private moveMarker;
29
22
  }
@@ -1,18 +1,19 @@
1
1
  import { Context } from "../context.js";
2
- import { type MarkupNode } from "../markup.js";
3
- import { TYPE } from "../symbols.js";
4
- export declare class HTML implements MarkupNode {
5
- [TYPE]: symbol;
6
- root: HTMLElement | SVGElement;
7
- private parentContext;
2
+ import { MarkupNode } from "./_markup.js";
3
+ /**
4
+ * Renders an HTML or SVG element.
5
+ */
6
+ export declare class ElementNode extends MarkupNode {
7
+ private root;
8
+ readonly tag: string;
9
+ readonly props: Record<string, any>;
8
10
  private context;
9
- tag: string;
10
- props: Record<string, any>;
11
11
  private childNodes;
12
12
  private unsubscribers;
13
13
  private ref?;
14
14
  private canClickAway;
15
15
  constructor(context: Context, tag: string, props: Record<string, any>);
16
+ getRoot(): HTMLElement | SVGElement;
16
17
  isMounted(): boolean;
17
18
  mount(parent: Node, after?: Node): void;
18
19
  unmount(skipDOM?: boolean): void;
@@ -1,17 +1,16 @@
1
1
  import type { Renderable } from "../../types.js";
2
2
  import { Context } from "../context.js";
3
- import { type MarkupNode } from "../markup.js";
4
- import { TYPE } from "../symbols.js";
3
+ import { MarkupNode } from "./_markup.js";
5
4
  /**
6
5
  * Renders content into a specified parent node.
7
6
  */
8
- export declare class Portal implements MarkupNode {
9
- [TYPE]: symbol;
7
+ export declare class PortalNode extends MarkupNode {
10
8
  private context;
11
- private content;
9
+ private value;
12
10
  private parent;
13
- private element?;
14
- constructor(context: Context, content: Renderable, parent: Element);
11
+ private node?;
12
+ constructor(context: Context, value: Renderable, parent: Element);
13
+ getRoot(): Node | undefined;
15
14
  isMounted(): boolean;
16
15
  mount(_parent: Element, _after?: Node): void;
17
16
  unmount(skipDOM?: boolean): void;
@@ -1,14 +1,15 @@
1
1
  import type { Renderable } from "../../types.js";
2
2
  import type { Context } from "../context.js";
3
- import type { MarkupNode } from "../markup.js";
4
3
  import { type Signal } from "../signals.js";
5
- import { TYPE } from "../symbols.js";
6
- export type Key = string | number | symbol;
4
+ import { MarkupNode } from "./_markup.js";
5
+ export type Key = any;
7
6
  export type KeyFn<T> = (item: T, index: number) => Key;
8
7
  export type RenderFn<T> = (item: Signal<T>, index: Signal<number>, ctx: Context) => Renderable;
9
- export declare class Repeat<T> implements MarkupNode {
10
- [TYPE]: symbol;
11
- root: Text;
8
+ /**
9
+ * Renders a list of items.
10
+ */
11
+ export declare class RepeatNode<T> extends MarkupNode {
12
+ private root;
12
13
  private context;
13
14
  private items;
14
15
  private key;
@@ -16,6 +17,7 @@ export declare class Repeat<T> implements MarkupNode {
16
17
  private unsubscribe;
17
18
  private connectedItems;
18
19
  constructor(context: Context, items: Signal<T[]>, key: KeyFn<T>, render: RenderFn<T>);
20
+ getRoot(): Text;
19
21
  isMounted(): boolean;
20
22
  mount(parent: Element, after?: Node): void;
21
23
  unmount(skipDOM?: boolean): void;
@@ -1,22 +1,23 @@
1
1
  import type { View } from "../../types.js";
2
2
  import { Context } from "../context.js";
3
- import { type MarkupNode } from "../markup.js";
4
- import { TYPE } from "../symbols.js";
3
+ import { MarkupNode } from "./_markup.js";
5
4
  export declare const VIEW: unique symbol;
6
- export declare class ViewInstance<P> implements MarkupNode {
7
- [TYPE]: symbol;
5
+ /**
6
+ * Renders a View.
7
+ */
8
+ export declare class ViewNode<P> extends MarkupNode {
8
9
  uniqueId: string;
9
10
  context: Context;
10
11
  props: P;
11
12
  view: View<P>;
12
13
  node?: MarkupNode;
13
- get root(): Node;
14
14
  /**
15
15
  * @param context - Parent contenxt to link to.
16
16
  * @param view - View function to mount.
17
17
  * @param props - Props to pass to view function.
18
18
  */
19
19
  constructor(context: Context, view: View<P>, props: P);
20
+ getRoot(): Node | undefined;
20
21
  isMounted(): boolean;
21
22
  mount(parent: Element, after?: Node): void;
22
23
  unmount(skipDOM?: boolean): void;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,9 @@
1
+ import { Context } from "./context";
2
+ interface ComputedGetterState<T> {
3
+ value?: T;
4
+ }
5
+ export declare function getCurrentContext(): Context | undefined;
6
+ export declare function setCurrentContext(context: Context | undefined): Context | undefined;
1
7
  /**
2
8
  * A getter that returns the current value held within the signal.
3
9
  * If called inside a trackable scope this signal will be tracked as a dependency.
@@ -20,9 +26,17 @@ export interface SignalOptions<T> {
20
26
  */
21
27
  equals?: EqualityFn<T>;
22
28
  }
23
- export declare function isSource<T>(value: MaybeSignal<T>): value is Source<T>;
29
+ /**
30
+ * Suspends effects during `fn`. Effects for all updated Signal values are called at the end of the batch.
31
+ */
24
32
  export declare function batch(fn: () => void): void;
33
+ /**
34
+ * Call a Signal function without tracking its value.
35
+ */
25
36
  export declare function untracked<T>(value: MaybeSignal<T>): T;
37
+ /**
38
+ * Unwraps the plain value from a Signal. If the value is not a Signal it is returned as-is.
39
+ */
26
40
  export declare function get<T>(value: MaybeSignal<T>): T;
27
41
  /**
28
42
  * Function to be invoked for the effect. Can return an optional cleanup function to be called between invocations.
@@ -37,7 +51,8 @@ export type UnsubscribeFn = () => void;
37
51
  * If you are using an effect inside a View or Store, use `ctx.effect` instead, which cleans up automatically when the component unmounts.
38
52
  */
39
53
  export declare function effect(fn: EffectFn): UnsubscribeFn;
40
- export declare function $<T>(compute: (previousValue: T) => MaybeSignal<T>, options?: SignalOptions<T>): Signal<T>;
54
+ export declare function $<T>(compute: (this: ComputedGetterState<T>) => MaybeSignal<T>, options?: SignalOptions<T>): Signal<T>;
41
55
  export declare function $<T>(value: T, options?: SignalOptions<T>): Source<T>;
42
56
  export declare function $<T>(value: undefined, options?: SignalOptions<T>): Source<T | undefined>;
43
57
  export declare function $<T>(): Source<T | undefined>;
58
+ export {};
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Props passed to the crash view when a crash occurs.
3
3
  */
4
- export type CrashViewProps = {
4
+ export interface CrashViewProps {
5
5
  /**
6
6
  * JavaScript Error object.
7
7
  */
@@ -18,5 +18,8 @@ export type CrashViewProps = {
18
18
  * Label for the tag.
19
19
  */
20
20
  tagName?: string;
21
- };
21
+ }
22
+ /**
23
+ * The crash view displayed unless you specify your own.
24
+ */
22
25
  export declare function DefaultCrashView(props: CrashViewProps): import("../markup.js").Markup<any>;
@@ -0,0 +1,23 @@
1
+ import type { Renderable } from "../../types";
2
+ import type { Context } from "../context";
3
+ import { type Key, RepeatNode } from "../nodes/repeat";
4
+ import { type Signal } from "../signals";
5
+ export interface ForProps<T> {
6
+ /**
7
+ * An array of items to render.
8
+ */
9
+ each: Signal<T[]>;
10
+ /**
11
+ * A function to extract a unique key that identifies each item.
12
+ * If no `key` function is passed, object identity (===) will be used.
13
+ */
14
+ key?: (item: T, index: number) => Key;
15
+ /**
16
+ * A render function. Takes the item and its index in signal form and returns something to display for each item.
17
+ */
18
+ children: ($item: Signal<T>, $index: Signal<number>, ctx: Context) => Renderable;
19
+ }
20
+ /**
21
+ *
22
+ */
23
+ export declare function For<T>(props: ForProps<T>, context: Context): RepeatNode<T>;
@@ -0,0 +1,26 @@
1
+ import type { Renderable } from "../../types";
2
+ import type { Context } from "../context";
3
+ import { DynamicNode } from "../nodes/dynamic";
4
+ import { type Signal } from "../signals";
5
+ export interface ShowProps {
6
+ /**
7
+ * If present, children will be rendered only when this signal holds a truthy value.
8
+ */
9
+ when?: Signal<any>;
10
+ /**
11
+ * If present, children will be rendered only when this signal holds a falsy value.
12
+ */
13
+ unless?: Signal<any>;
14
+ /**
15
+ * Content to render if conditions permit.
16
+ */
17
+ children: Renderable;
18
+ /**
19
+ * Content to render when conditions don't permit `children` to render.
20
+ */
21
+ fallback?: Renderable;
22
+ }
23
+ /**
24
+ * Conditionally display children.
25
+ */
26
+ export declare function Show(props: ShowProps, context: Context): DynamicNode;
@@ -0,0 +1,64 @@
1
+ import { Context, Logger, type Ref, type Store } from "../core";
2
+ import { type EffectFn, MaybeSignal, type Signal } from "../core/signals";
3
+ /**
4
+ * Returns the Context object of the View, Store or Mixin this hook is called in.
5
+ */
6
+ export declare function useContext(): Context;
7
+ /**
8
+ * Returns a logger. If a name is passed it will be used as a prefix for all console messages.
9
+ * Otherwise the default name of the context will be used.
10
+ */
11
+ export declare function useLogger(name?: MaybeSignal<string>): Logger;
12
+ /**
13
+ * Sets the value of the Signal it is bound to.
14
+ */
15
+ export interface Setter<T> {
16
+ (value: T): void;
17
+ (fn: (current: T) => T): void;
18
+ }
19
+ /**
20
+ * Creates a new read-only Signal and a bound Setter function.
21
+ */
22
+ export declare function useState<T>(value: T): [Signal<T>, Setter<T>];
23
+ /**
24
+ * Creates a new read-only Signal and a bound Setter function.
25
+ */
26
+ export declare function useState<T>(): [Signal<T | undefined>, Setter<T | undefined>];
27
+ export declare function useMemo<T>(compute: (current?: T) => MaybeSignal<T>, deps?: Signal<any>[]): Signal<T>;
28
+ export declare function useEffect(fn: EffectFn, deps?: Signal<any>[]): void;
29
+ /**
30
+ * Takes the current state and a dispatched action. Returns a new state based on the action.
31
+ * Typically the body of this function will be a large switch statement.
32
+ */
33
+ export type ReducerFn<State, Action> = (state: State, action: Action) => State;
34
+ /**
35
+ * Dispatches an action to this reducer, causing the state to update.
36
+ */
37
+ export type DispatchFn<Action> = (action: Action) => void;
38
+ /**
39
+ *
40
+ */
41
+ export declare function useReducer<State, Action>(reducer: ReducerFn<State, Action>, initialState: State): [Signal<State>, DispatchFn<Action>];
42
+ /**
43
+ * Uses a previously added Store. Takes the Store function itself and returns the nearest instance.
44
+ */
45
+ export declare function useStore<T>(store: Store<any, T>): T;
46
+ /**
47
+ * A hybrid Ref which is both a function ref and a React-style object ref with a `current` property.
48
+ * Both the `current` property and the function syntax access the same value.
49
+ */
50
+ export interface HybridRef<T> extends Ref<T> {
51
+ current: T;
52
+ }
53
+ /**
54
+ * Creates a Ref. Useful for getting references to DOM nodes.
55
+ */
56
+ export declare function useRef<T>(initialValue?: T): HybridRef<T>;
57
+ /**
58
+ * Calls `callback` when the context is mounted. If `callback` returns a function, that function is called when the context is unmounted.
59
+ */
60
+ export declare function useMount(callback: () => void | (() => void)): void;
61
+ /**
62
+ * Calls `callback` when the context is unmounted.
63
+ */
64
+ export declare function useUnmount(callback: () => void): void;
@@ -0,0 +1 @@
1
+ export {};
package/dist/hooks.js ADDED
@@ -0,0 +1,69 @@
1
+ import { $ as u, g as c, u as s, c as a } from "./signals-gCwiIe5X.js";
2
+ import { r as x } from "./ref-BD79iqlg.js";
3
+ function o() {
4
+ const t = a();
5
+ if (!t)
6
+ throw new Error("No context found; hooks can only be called in the body of a View, Store or Mixin.");
7
+ return t;
8
+ }
9
+ function m(t) {
10
+ const e = o();
11
+ return t && e.setName(t), e;
12
+ }
13
+ function l(t) {
14
+ o();
15
+ const e = u(t);
16
+ return [() => e(), e];
17
+ }
18
+ function p(t, e) {
19
+ return o(), e ? u(function() {
20
+ for (const n of e) c(n);
21
+ return s(() => t(this.value));
22
+ }) : u(function() {
23
+ return t(this.value);
24
+ });
25
+ }
26
+ function S(t, e) {
27
+ const n = o();
28
+ e ? n.effect(() => {
29
+ for (const r of e) c(r);
30
+ s(t);
31
+ }) : n.effect(t);
32
+ }
33
+ function v(t, e) {
34
+ const [n, r] = l(e);
35
+ return [n, (f) => {
36
+ r((i) => t(i, f));
37
+ }];
38
+ }
39
+ function M(t) {
40
+ return o().getStore(t);
41
+ }
42
+ function b(...t) {
43
+ o();
44
+ const e = x(...t);
45
+ return Object.defineProperty(e, "current", { get: e, set: e }), e;
46
+ }
47
+ function w(t) {
48
+ const e = o();
49
+ e.onMount(() => {
50
+ const n = t();
51
+ n && e.onUnmount(n);
52
+ });
53
+ }
54
+ function y(t) {
55
+ o().onUnmount(t);
56
+ }
57
+ export {
58
+ o as useContext,
59
+ S as useEffect,
60
+ m as useLogger,
61
+ p as useMemo,
62
+ w as useMount,
63
+ v as useReducer,
64
+ b as useRef,
65
+ l as useState,
66
+ M as useStore,
67
+ y as useUnmount
68
+ };
69
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sources":["../src/hooks/index.ts"],"sourcesContent":["import { Context, Logger, ref, type Ref, type Store } from \"../core\";\nimport { $, type EffectFn, get, getCurrentContext, MaybeSignal, type Signal, untracked } from \"../core/signals\";\n\n/**\n * Returns the Context object of the View, Store or Mixin this hook is called in.\n */\nexport function useContext(): Context {\n const context = getCurrentContext();\n if (!context) {\n throw new Error(`No context found; hooks can only be called in the body of a View, Store or Mixin.`);\n }\n return context;\n}\n\n/**\n * Returns a logger. If a name is passed it will be used as a prefix for all console messages.\n * Otherwise the default name of the context will be used.\n */\nexport function useLogger(name?: MaybeSignal<string>): Logger {\n const context = useContext();\n if (name) context.setName(name);\n return context;\n}\n\n/**\n * Sets the value of the Signal it is bound to.\n */\nexport interface Setter<T> {\n (value: T): void;\n (fn: (current: T) => T): void;\n}\n\n/**\n * Creates a new read-only Signal and a bound Setter function.\n */\nexport function useState<T>(value: T): [Signal<T>, Setter<T>];\n\n/**\n * Creates a new read-only Signal and a bound Setter function.\n */\nexport function useState<T>(): [Signal<T | undefined>, Setter<T | undefined>];\n\nexport function useState<T>(value?: T): [Signal<T>, Setter<T>] {\n useContext(); // assert that we're in a valid context\n const $value = $(value);\n return [() => $value() as T, $value];\n}\n\nexport function useMemo<T>(compute: (current?: T) => MaybeSignal<T>, deps?: Signal<any>[]): Signal<T> {\n useContext(); // assert that we're in a valid context\n if (deps) {\n return $(function () {\n // Track deps and run `compute` untracked.\n for (const dep of deps) get(dep);\n return untracked(() => compute(this.value));\n });\n } else {\n return $(function () {\n return compute(this.value);\n });\n }\n}\n\nexport function useEffect(fn: EffectFn, deps?: Signal<any>[]): void {\n const context = useContext();\n if (deps) {\n context.effect(() => {\n // Track deps and run `fn` untracked.\n for (const dep of deps) get(dep);\n untracked(fn);\n });\n } else {\n context.effect(fn);\n }\n}\n\n// TODO: What would layout effect even mean in dolla?\n// export function useLayoutEffect() {}\n\n/**\n * Takes the current state and a dispatched action. Returns a new state based on the action.\n * Typically the body of this function will be a large switch statement.\n */\nexport type ReducerFn<State, Action> = (state: State, action: Action) => State;\n\n/**\n * Dispatches an action to this reducer, causing the state to update.\n */\nexport type DispatchFn<Action> = (action: Action) => void;\n\n/**\n *\n */\nexport function useReducer<State, Action>(\n reducer: ReducerFn<State, Action>,\n initialState: State,\n): [Signal<State>, DispatchFn<Action>] {\n const [state, setState] = useState(initialState);\n const dispatch = (action: Action) => {\n setState((current) => reducer(current, action));\n };\n return [state, dispatch];\n}\n\n/**\n * Uses a previously added Store. Takes the Store function itself and returns the nearest instance.\n */\nexport function useStore<T>(store: Store<any, T>): T {\n const context = useContext();\n return context.getStore(store);\n}\n\n/**\n * A hybrid Ref which is both a function ref and a React-style object ref with a `current` property.\n * Both the `current` property and the function syntax access the same value.\n */\nexport interface HybridRef<T> extends Ref<T> {\n current: T;\n}\n\n/**\n * Creates a Ref. Useful for getting references to DOM nodes.\n */\nexport function useRef<T>(initialValue?: T): HybridRef<T>;\n\nexport function useRef<T>(...value: [T]): HybridRef<T> {\n useContext(); // assert that we're in a valid context\n const valueRef = ref(...value);\n Object.defineProperty(valueRef, \"current\", { get: valueRef, set: valueRef });\n return valueRef as HybridRef<T>;\n}\n\n/**\n * Calls `callback` when the context is mounted. If `callback` returns a function, that function is called when the context is unmounted.\n */\nexport function useMount(callback: () => void | (() => void)): void {\n const context = useContext();\n context.onMount(() => {\n const result = callback();\n if (result) context.onUnmount(result);\n });\n}\n\n/**\n * Calls `callback` when the context is unmounted.\n */\nexport function useUnmount(callback: () => void): void {\n const context = useContext();\n context.onUnmount(callback);\n}\n"],"names":["useContext","context","getCurrentContext","useLogger","name","useState","value","$value","$","useMemo","compute","deps","dep","get","untracked","useEffect","fn","useReducer","reducer","initialState","state","setState","action","current","useStore","store","useRef","valueRef","ref","useMount","callback","result","useUnmount"],"mappings":";;AAMO,SAASA,IAAsB;AACpC,QAAMC,IAAUC,EAAkB;AAClC,MAAI,CAACD;AACG,UAAA,IAAI,MAAM,mFAAmF;AAE9F,SAAAA;AACT;AAMO,SAASE,EAAUC,GAAoC;AAC5D,QAAMH,IAAUD,EAAW;AACvB,SAAAI,KAAcH,EAAA,QAAQG,CAAI,GACvBH;AACT;AAoBO,SAASI,EAAYC,GAAmC;AAClD,EAAAN,EAAA;AACL,QAAAO,IAASC,EAAEF,CAAK;AACtB,SAAO,CAAC,MAAMC,EAAO,GAAQA,CAAM;AACrC;AAEgB,SAAAE,EAAWC,GAA0CC,GAAiC;AAEpG,SADWX,EAAA,GACPW,IACKH,EAAE,WAAY;AAER,eAAAI,KAAOD,EAAM,CAAAE,EAAID,CAAG;AAC/B,WAAOE,EAAU,MAAMJ,EAAQ,KAAK,KAAK,CAAC;AAAA,EAAA,CAC3C,IAEMF,EAAE,WAAY;AACZ,WAAAE,EAAQ,KAAK,KAAK;AAAA,EAAA,CAC1B;AAEL;AAEgB,SAAAK,EAAUC,GAAcL,GAA4B;AAClE,QAAMV,IAAUD,EAAW;AAC3B,EAAIW,IACFV,EAAQ,OAAO,MAAM;AAER,eAAAW,KAAOD,EAAM,CAAAE,EAAID,CAAG;AAC/B,IAAAE,EAAUE,CAAE;AAAA,EAAA,CACb,IAEDf,EAAQ,OAAOe,CAAE;AAErB;AAmBgB,SAAAC,EACdC,GACAC,GACqC;AACrC,QAAM,CAACC,GAAOC,CAAQ,IAAIhB,EAASc,CAAY;AAIxC,SAAA,CAACC,GAHS,CAACE,MAAmB;AACnC,IAAAD,EAAS,CAACE,MAAYL,EAAQK,GAASD,CAAM,CAAC;AAAA,EAChD,CACuB;AACzB;AAKO,SAASE,EAAYC,GAAyB;AAE5C,SADSzB,EAAW,EACZ,SAASyB,CAAK;AAC/B;AAeO,SAASC,KAAapB,GAA0B;AAC1C,EAAAN,EAAA;AACL,QAAA2B,IAAWC,EAAI,GAAGtB,CAAK;AACtB,gBAAA,eAAeqB,GAAU,WAAW,EAAE,KAAKA,GAAU,KAAKA,GAAU,GACpEA;AACT;AAKO,SAASE,EAASC,GAA2C;AAClE,QAAM7B,IAAUD,EAAW;AAC3B,EAAAC,EAAQ,QAAQ,MAAM;AACpB,UAAM8B,IAASD,EAAS;AACpB,IAAAC,KAAgB9B,EAAA,UAAU8B,CAAM;AAAA,EAAA,CACrC;AACH;AAKO,SAASC,EAAWF,GAA4B;AAErD,EADgB9B,EAAW,EACnB,UAAU8B,CAAQ;AAC5B;"}