@manyducks.co/dolla 0.67.0

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/README.md +643 -0
  2. package/build.js +34 -0
  3. package/index.d.ts +12 -0
  4. package/jsx-dev-runtime.d.ts +1 -0
  5. package/jsx-runtime.d.ts +1 -0
  6. package/lib/app.d.ts +138 -0
  7. package/lib/classes/CrashCollector.d.ts +30 -0
  8. package/lib/classes/DebugHub.d.ts +60 -0
  9. package/lib/index.d.ts +23 -0
  10. package/lib/index.js +4062 -0
  11. package/lib/index.js.map +7 -0
  12. package/lib/jsx/jsx-dev-runtime.d.ts +3 -0
  13. package/lib/jsx/jsx-dev-runtime.js +20 -0
  14. package/lib/jsx/jsx-dev-runtime.js.map +7 -0
  15. package/lib/jsx/jsx-runtime.d.ts +10 -0
  16. package/lib/jsx/jsx-runtime.js +22 -0
  17. package/lib/jsx/jsx-runtime.js.map +7 -0
  18. package/lib/markup.d.ts +81 -0
  19. package/lib/nodes/cond.d.ts +28 -0
  20. package/lib/nodes/html.d.ts +30 -0
  21. package/lib/nodes/observer.d.ts +33 -0
  22. package/lib/nodes/outlet.d.ts +26 -0
  23. package/lib/nodes/portal.d.ts +22 -0
  24. package/lib/nodes/repeat.d.ts +36 -0
  25. package/lib/nodes/text.d.ts +20 -0
  26. package/lib/spring.d.ts +40 -0
  27. package/lib/state.d.ts +84 -0
  28. package/lib/store.d.ts +67 -0
  29. package/lib/stores/dialog.d.ts +30 -0
  30. package/lib/stores/document.d.ts +10 -0
  31. package/lib/stores/http.d.ts +60 -0
  32. package/lib/stores/language.d.ts +39 -0
  33. package/lib/stores/render.d.ts +18 -0
  34. package/lib/stores/router.d.ts +118 -0
  35. package/lib/testing/classes/MockHTTP.d.ts +10 -0
  36. package/lib/testing/index.d.ts +4 -0
  37. package/lib/testing/makeMockDOMNode.d.ts +10 -0
  38. package/lib/testing/makeMockFetch.d.ts +36 -0
  39. package/lib/testing/makeMockFetch.test.d.ts +1 -0
  40. package/lib/testing/stores/dialog.d.ts +6 -0
  41. package/lib/testing/stores/http.d.ts +13 -0
  42. package/lib/testing/stores/page.d.ts +7 -0
  43. package/lib/testing/stores/router.d.ts +12 -0
  44. package/lib/testing/wrapStore.d.ts +8 -0
  45. package/lib/testing/wrapStore.test.d.ts +1 -0
  46. package/lib/testing/wrapView.d.ts +0 -0
  47. package/lib/types.d.ts +3388 -0
  48. package/lib/utils.d.ts +14 -0
  49. package/lib/view.d.ts +80 -0
  50. package/lib/views/fragment.d.ts +2 -0
  51. package/lib/views/store-scope.d.ts +10 -0
  52. package/package.json +56 -0
  53. package/tests/state.test.js +290 -0
@@ -0,0 +1,3 @@
1
+ export function jsxDEV(element: any, props: any, key: any, isStaticChildren: any, source: any, self: any): import("../markup.js").Markup;
2
+ export { Fragment };
3
+ import { Fragment } from "../index.js";
@@ -0,0 +1,20 @@
1
+ import { m, Fragment } from "../index.js";
2
+ function jsxDEV(element, props, key, isStaticChildren, source, self) {
3
+ const attributes = { ...omit(["children", "key"], props) };
4
+ const children = Array.isArray(props.children) ? props.children : [props.children];
5
+ return m(element, attributes, ...children);
6
+ }
7
+ function omit(keys, object) {
8
+ const result = {};
9
+ for (const key in object) {
10
+ if (!keys.includes(key)) {
11
+ result[key] = object[key];
12
+ }
13
+ }
14
+ return result;
15
+ }
16
+ export {
17
+ Fragment,
18
+ jsxDEV
19
+ };
20
+ //# sourceMappingURL=jsx-dev-runtime.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/jsx/jsx-dev-runtime.js"],
4
+ "sourcesContent": ["// This import makes sense when built\nimport { m, Fragment } from \"../index.js\";\n\nexport { Fragment };\n\nexport function jsxDEV(element, props, key, isStaticChildren, source, self) {\n const attributes = { ...omit([\"children\", \"key\"], props) };\n const children = Array.isArray(props.children) ? props.children : [props.children];\n\n return m(element, attributes, ...children);\n}\n\nfunction omit(keys, object) {\n const result = {};\n for (const key in object) {\n if (!keys.includes(key)) {\n result[key] = object[key];\n }\n }\n return result;\n}\n"],
5
+ "mappings": "AACA,SAAS,GAAG,gBAAgB;AAIrB,SAAS,OAAO,SAAS,OAAO,KAAK,kBAAkB,QAAQ,MAAM;AAC1E,QAAM,aAAa,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,GAAG,KAAK,EAAE;AACzD,QAAM,WAAW,MAAM,QAAQ,MAAM,QAAQ,IAAI,MAAM,WAAW,CAAC,MAAM,QAAQ;AAEjF,SAAO,EAAE,SAAS,YAAY,GAAG,QAAQ;AAC3C;AAEA,SAAS,KAAK,MAAM,QAAQ;AAC1B,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * JSX function for elements with dynamic children.
3
+ */
4
+ export function jsx(element: any, props: any, key: any): import("../markup.js").Markup;
5
+ /**
6
+ * JSX function for elements with static children.
7
+ */
8
+ export function jsxs(element: any, props: any, key: any): import("../markup.js").Markup;
9
+ export { Fragment };
10
+ import { Fragment } from "../index.js";
@@ -0,0 +1,22 @@
1
+ import { m, Fragment } from "../index.js";
2
+ function jsx(element, props, key) {
3
+ return m(element, props ? { ...omit(["children", "key"], props) } : void 0, ...[props.children]);
4
+ }
5
+ function jsxs(element, props, key) {
6
+ return m(element, props ? { ...omit(["children", "key"], props) } : void 0, props.children);
7
+ }
8
+ function omit(keys, object) {
9
+ const result = {};
10
+ for (const key in object) {
11
+ if (!keys.includes(key)) {
12
+ result[key] = object[key];
13
+ }
14
+ }
15
+ return result;
16
+ }
17
+ export {
18
+ Fragment,
19
+ jsx,
20
+ jsxs
21
+ };
22
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/jsx/jsx-runtime.js"],
4
+ "sourcesContent": ["// This import makes sense when built\nimport { m, Fragment } from \"../index.js\";\n\nexport { Fragment };\n\n/**\n * JSX function for elements with dynamic children.\n */\nexport function jsx(element, props, key) {\n return m(element, props ? { ...omit([\"children\", \"key\"], props) } : undefined, ...[props.children]);\n}\n\n/**\n * JSX function for elements with static children.\n */\nexport function jsxs(element, props, key) {\n return m(element, props ? { ...omit([\"children\", \"key\"], props) } : undefined, props.children);\n}\n\nfunction omit(keys, object) {\n const result = {};\n for (const key in object) {\n if (!keys.includes(key)) {\n result[key] = object[key];\n }\n }\n return result;\n}\n"],
5
+ "mappings": "AACA,SAAS,GAAG,gBAAgB;AAOrB,SAAS,IAAI,SAAS,OAAO,KAAK;AACvC,SAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,GAAG,KAAK,EAAE,IAAI,QAAW,GAAG,CAAC,MAAM,QAAQ,CAAC;AACpG;AAKO,SAAS,KAAK,SAAS,OAAO,KAAK;AACxC,SAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,KAAK,CAAC,YAAY,KAAK,GAAG,KAAK,EAAE,IAAI,QAAW,MAAM,QAAQ;AAC/F;AAEA,SAAS,KAAK,MAAM,QAAQ;AAC1B,QAAM,SAAS,CAAC;AAChB,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,aAAO,GAAG,IAAI,OAAO,GAAG;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,81 @@
1
+ import { type AppContext, type ElementContext } from "./app.js";
2
+ import { type Readable } from "./state.js";
3
+ import type { Renderable, Stringable } from "./types.js";
4
+ import { type View, type ViewContext, type ViewResult } from "./view.js";
5
+ /**
6
+ * Markup is a set of element metadata that hasn't been rendered to a DOMHandle yet.
7
+ */
8
+ export interface Markup {
9
+ type: string | View<any>;
10
+ props?: Record<string, any>;
11
+ children?: Markup[];
12
+ }
13
+ /**
14
+ * DOMHandle is the generic interface for an element that can be manipulated by the framework.
15
+ */
16
+ export interface DOMHandle {
17
+ readonly node?: Node;
18
+ readonly connected: boolean;
19
+ connect(parent: Node, after?: Node): void;
20
+ disconnect(): void;
21
+ setChildren(children: DOMHandle[]): void;
22
+ }
23
+ export declare function isMarkup(value: unknown): value is Markup;
24
+ export declare function isDOMHandle(value: unknown): value is DOMHandle;
25
+ export declare function toMarkup(renderables: Renderable | Renderable[]): Markup[];
26
+ export interface MarkupAttributes {
27
+ $text: {
28
+ value: Stringable | Readable<Stringable>;
29
+ };
30
+ $cond: {
31
+ $predicate: Readable<any>;
32
+ thenContent?: Renderable;
33
+ elseContent?: Renderable;
34
+ };
35
+ $repeat: {
36
+ $items: Readable<any[]>;
37
+ keyFn: (value: any, index: number) => string | number | symbol;
38
+ renderFn: ($item: Readable<any>, $index: Readable<number>, c: ViewContext) => ViewResult;
39
+ };
40
+ $observer: {
41
+ readables: Readable<any>[];
42
+ renderFn: (...items: any) => Renderable;
43
+ };
44
+ $outlet: {
45
+ $children: Readable<DOMHandle[]>;
46
+ };
47
+ $node: {
48
+ value: Node;
49
+ };
50
+ $portal: {
51
+ content: Renderable;
52
+ parent: Node;
53
+ };
54
+ [tag: string]: Record<string, any>;
55
+ }
56
+ export declare function m<T extends keyof MarkupAttributes>(type: T, attributes: MarkupAttributes[T], ...children: Renderable[]): Markup;
57
+ export declare function m<I>(type: View<I>, attributes?: I, ...children: Renderable[]): Markup;
58
+ /**
59
+ * Displays content conditionally. When `predicate` holds a truthy value, `thenContent` is displayed; when `predicate` holds a falsy value, `elseContent` is displayed.
60
+ */
61
+ export declare function cond(predicate: any | Readable<any>, thenContent?: Renderable, elseContent?: Renderable): Markup;
62
+ /**
63
+ * Calls `renderFn` for each item in `items`. Dynamically adds and removes views as items change.
64
+ * The result of `keyFn` is used to compare items and decide if item was added, removed or updated.
65
+ */
66
+ export declare function repeat<T>(items: Readable<T[]> | T[], keyFn: (value: T, index: number) => string | number | symbol, renderFn: ($value: Readable<T>, $index: Readable<number>, ctx: ViewContext) => ViewResult): Markup;
67
+ /**
68
+ * Render `content` into a `parent` node anywhere in the page, rather than at its position in the view.
69
+ */
70
+ export declare function portal(content: Renderable, parent: Node): Markup;
71
+ interface RenderContext {
72
+ appContext: AppContext;
73
+ elementContext: ElementContext;
74
+ }
75
+ export declare function renderMarkupToDOM(markup: Markup | Markup[], ctx: RenderContext): DOMHandle[];
76
+ /**
77
+ * Combines one or more DOMHandles into a single DOMHandle.
78
+ */
79
+ export declare function getRenderHandle(handles: DOMHandle[]): DOMHandle;
80
+ export declare function isRenderable(value: unknown): value is Renderable;
81
+ export {};
@@ -0,0 +1,28 @@
1
+ import { type AppContext, type ElementContext } from "../app.js";
2
+ import { type DOMHandle, type Markup } from "../markup.js";
3
+ import { type Readable, type StopFunction } from "../state.js";
4
+ import { type Renderable } from "../types.js";
5
+ export interface ConditionalConfig {
6
+ $predicate: Readable<any>;
7
+ thenContent?: Renderable;
8
+ elseContent?: Renderable;
9
+ appContext: AppContext;
10
+ elementContext: ElementContext;
11
+ }
12
+ export declare class Conditional implements DOMHandle {
13
+ node: Node;
14
+ endNode: Node;
15
+ $predicate: Readable<any>;
16
+ stopCallback?: StopFunction;
17
+ thenContent?: Markup[];
18
+ elseContent?: Markup[];
19
+ connectedContent: DOMHandle[];
20
+ appContext: AppContext;
21
+ elementContext: ElementContext;
22
+ constructor(config: ConditionalConfig);
23
+ get connected(): boolean;
24
+ connect(parent: Node, after?: Node | undefined): void;
25
+ disconnect(): void;
26
+ update(value: any): void;
27
+ setChildren(children: DOMHandle[]): Promise<void>;
28
+ }
@@ -0,0 +1,30 @@
1
+ import { type AppContext, type ElementContext } from "../app.js";
2
+ import { type DOMHandle, type Markup } from "../markup.js";
3
+ import { type StopFunction } from "../state.js";
4
+ type HTMLOptions = {
5
+ appContext: AppContext;
6
+ elementContext: ElementContext;
7
+ tag: string;
8
+ props?: any;
9
+ children?: Markup[];
10
+ };
11
+ export declare class HTML implements DOMHandle {
12
+ node: HTMLElement | SVGElement;
13
+ props: Record<string, any>;
14
+ children: DOMHandle[];
15
+ stopCallbacks: StopFunction[];
16
+ appContext: AppContext;
17
+ elementContext: ElementContext;
18
+ uniqueId: string;
19
+ canClickAway: boolean;
20
+ get connected(): boolean;
21
+ constructor({ tag, props, children, appContext, elementContext }: HTMLOptions);
22
+ connect(parent: Node, after?: Node): void;
23
+ disconnect(): void;
24
+ setChildren(next: DOMHandle[]): void;
25
+ getUpdateKey(type: string, value: string | number): string;
26
+ applyProps(element: HTMLElement | SVGElement, props: Record<string, unknown>): void;
27
+ applyStyles(element: HTMLElement | SVGElement, styles: Record<string, any>, stopCallbacks: StopFunction[]): () => void;
28
+ applyClasses(element: HTMLElement | SVGElement, classes: unknown, stopCallbacks: StopFunction[]): () => void;
29
+ }
30
+ export {};
@@ -0,0 +1,33 @@
1
+ import { type AppContext, type ElementContext } from "../app.js";
2
+ import type { Renderable } from "../types.js";
3
+ import { type DOMHandle } from "../markup.js";
4
+ import { type Readable } from "../state.js";
5
+ interface ObserverOptions {
6
+ appContext: AppContext;
7
+ elementContext: ElementContext;
8
+ readables: Readable<any>[];
9
+ renderFn: (...values: any) => Renderable;
10
+ }
11
+ /**
12
+ * Displays dynamic children without a parent element.
13
+ */
14
+ export declare class Observer implements DOMHandle {
15
+ node: Node;
16
+ endNode: Node;
17
+ connectedViews: DOMHandle[];
18
+ renderFn: (...values: any) => Renderable;
19
+ appContext: AppContext;
20
+ elementContext: ElementContext;
21
+ observerControls: {
22
+ start: () => void;
23
+ stop: () => void;
24
+ };
25
+ get connected(): boolean;
26
+ constructor({ readables, renderFn, appContext, elementContext }: ObserverOptions);
27
+ connect(parent: Node, after?: Node): void;
28
+ disconnect(): void;
29
+ setChildren(): Promise<void>;
30
+ cleanup(): void;
31
+ update(...children: Renderable[]): void;
32
+ }
33
+ export {};
@@ -0,0 +1,26 @@
1
+ import { type ElementContext, type AppContext } from "../app.js";
2
+ import { type DOMHandle } from "../markup.js";
3
+ import { type Readable, type StopFunction } from "../state.js";
4
+ export interface OutletConfig {
5
+ $children: Readable<DOMHandle[]>;
6
+ appContext: AppContext;
7
+ elementContext: ElementContext;
8
+ }
9
+ /**
10
+ * Manages an array of DOMHandles.
11
+ */
12
+ export declare class Outlet implements DOMHandle {
13
+ node: Node;
14
+ endNode: Node;
15
+ $children: Readable<DOMHandle[]>;
16
+ stopCallback?: StopFunction;
17
+ connectedChildren: DOMHandle[];
18
+ appContext: AppContext;
19
+ elementContext: ElementContext;
20
+ constructor(config: OutletConfig);
21
+ get connected(): boolean;
22
+ connect(parent: Node, after?: Node | undefined): void;
23
+ disconnect(): void;
24
+ update(newChildren: DOMHandle[]): void;
25
+ setChildren(children: DOMHandle[]): void;
26
+ }
@@ -0,0 +1,22 @@
1
+ import { type AppContext, type ElementContext } from "../app.js";
2
+ import { type DOMHandle } from "../markup.js";
3
+ import { type Renderable } from "../types.js";
4
+ interface PortalConfig {
5
+ content: Renderable;
6
+ parent: Node;
7
+ appContext: AppContext;
8
+ elementContext: ElementContext;
9
+ }
10
+ /**
11
+ * Renders content into a specified parent node.
12
+ */
13
+ export declare class Portal implements DOMHandle {
14
+ config: PortalConfig;
15
+ handle?: DOMHandle;
16
+ get connected(): boolean;
17
+ constructor(config: PortalConfig);
18
+ connect(_parent: Node, _after?: Node): void;
19
+ disconnect(): void;
20
+ setChildren(children: DOMHandle[]): void;
21
+ }
22
+ export {};
@@ -0,0 +1,36 @@
1
+ import { type AppContext, type ElementContext } from "../app.js";
2
+ import { type DOMHandle } from "../markup.js";
3
+ import { type Readable, type StopFunction, type Writable } from "../state.js";
4
+ import { type ViewContext, type ViewResult } from "../view.js";
5
+ interface RepeatOptions<T> {
6
+ appContext: AppContext;
7
+ elementContext: ElementContext;
8
+ $items: Readable<T[]>;
9
+ keyFn: (value: T, index: number) => string | number | symbol;
10
+ renderFn: ($value: Readable<T>, $index: Readable<number>, ctx: ViewContext) => ViewResult;
11
+ }
12
+ type ConnectedItem<T> = {
13
+ key: any;
14
+ $$value: Writable<T>;
15
+ $$index: Writable<number>;
16
+ handle: DOMHandle;
17
+ };
18
+ export declare class Repeat<T> implements DOMHandle {
19
+ node: Node;
20
+ endNode: Node;
21
+ $items: Readable<T[]>;
22
+ stopCallback?: StopFunction;
23
+ connectedItems: ConnectedItem<T>[];
24
+ appContext: AppContext;
25
+ elementContext: ElementContext;
26
+ renderFn: ($value: Readable<T>, $index: Readable<number>, ctx: ViewContext) => ViewResult;
27
+ keyFn: (value: T, index: number) => string | number | symbol;
28
+ get connected(): boolean;
29
+ constructor({ appContext, elementContext, $items, renderFn, keyFn }: RepeatOptions<T>);
30
+ connect(parent: Node, after?: Node): void;
31
+ disconnect(): void;
32
+ setChildren(): void;
33
+ _cleanup(): void;
34
+ _update(value: T[]): void;
35
+ }
36
+ export {};
@@ -0,0 +1,20 @@
1
+ import { type Readable, type StopFunction } from "../state.js";
2
+ import { type DOMHandle } from "../markup.js";
3
+ interface Stringable {
4
+ toString(): string;
5
+ }
6
+ interface TextOptions {
7
+ value: Stringable | Readable<Stringable>;
8
+ }
9
+ export declare class Text implements DOMHandle {
10
+ node: globalThis.Text;
11
+ value: Stringable | Readable<Stringable>;
12
+ stopCallback?: StopFunction;
13
+ get connected(): boolean;
14
+ constructor({ value }: TextOptions);
15
+ connect(parent: Node, after?: Node | null): Promise<void>;
16
+ disconnect(): Promise<void>;
17
+ update(value?: Stringable): void;
18
+ setChildren(): Promise<void>;
19
+ }
20
+ export {};
@@ -0,0 +1,40 @@
1
+ import { type Readable, type Writable } from "./state.js";
2
+ export interface SpringParameters {
3
+ /**
4
+ * How heavy the spring is.
5
+ */
6
+ mass: number | Readable<number>;
7
+ /**
8
+ * Amount of stiffness or tension in the spring.
9
+ */
10
+ stiffness: number | Readable<number>;
11
+ /**
12
+ * Amount of smoothing. Affects the speed of transitions.
13
+ */
14
+ damping: number | Readable<number>;
15
+ /**
16
+ * How much force the spring's motion begins with.
17
+ */
18
+ velocity: number | Readable<number>;
19
+ }
20
+ interface SpringOptions extends Partial<SpringParameters> {
21
+ /**
22
+ * Difference in average amplitude across the last several frames before the animation is considered done.
23
+ * The exact number of frames to average is specified by `endWindow`.
24
+ */
25
+ endAmplitude?: number | Readable<number>;
26
+ /**
27
+ * Specifies the number of frames across which to measure the average amplitude to determine when the animation is considered done.
28
+ * The maximum amplitude is specified by `endAmplitude`.
29
+ */
30
+ endWindow?: number | Readable<number>;
31
+ }
32
+ export interface Spring extends Writable<number> {
33
+ /**
34
+ * Takes a new value and animates to it. Returns a promise that resolves when the animation ends.
35
+ * Optionally takes a set of override spring options to animate with.
36
+ */
37
+ animateTo(newValue: number, options?: SpringOptions): Promise<void>;
38
+ }
39
+ export declare function spring(initialValue: number, options?: SpringOptions): Spring;
40
+ export {};
package/lib/state.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ export declare const OBSERVE: unique symbol;
2
+ /**
3
+ * Stops the observer that created it when called.
4
+ */
5
+ export type StopFunction = () => void;
6
+ type ObserveMethod<T> = (callback: (currentValue: T, previousValue?: T) => void) => StopFunction;
7
+ /**
8
+ * Extracts value types from an array of Readables.
9
+ */
10
+ export type ReadableValues<T extends Readable<any>[]> = {
11
+ [K in keyof T]: T[K] extends Readable<infer U> ? U : never;
12
+ };
13
+ export type Unwrapped<T> = T extends Readable<infer U> ? U : T;
14
+ export interface Observable<T> {
15
+ /**
16
+ * Receives the latest value with `callback` whenever the value changes.
17
+ * The `previousValue` is always undefined the first time the callback is called, then the same value as the last time it was called going forward.
18
+ */
19
+ [OBSERVE]: ObserveMethod<T>;
20
+ }
21
+ export interface Readable<T> extends Observable<T> {
22
+ /**
23
+ * Returns the current value.
24
+ */
25
+ get(): T;
26
+ }
27
+ export interface Writable<T> extends Readable<T> {
28
+ /**
29
+ * Sets a new value.
30
+ */
31
+ set(value: T): void;
32
+ /**
33
+ * Passes the current value to `callback` and takes `callback`'s return value as the new value.
34
+ */
35
+ update(callback: (currentValue: T) => T): void;
36
+ }
37
+ export declare function isObservable<T>(value: any): value is Observable<T>;
38
+ export declare function isReadable<T>(value: any): value is Readable<T>;
39
+ export declare function isWritable<T>(value: any): value is Writable<T>;
40
+ export declare function readable<T>(value: Writable<T>): Readable<Unwrapped<T>>;
41
+ export declare function readable<T>(value: Readable<T>): Readable<Unwrapped<T>>;
42
+ export declare function readable<T>(value: undefined): Readable<T | undefined>;
43
+ export declare function readable<T>(): Readable<T | undefined>;
44
+ export declare function readable<T>(value: T): Readable<Unwrapped<T>>;
45
+ export declare function writable<T>(value: Writable<T>): Writable<Unwrapped<T>>;
46
+ export declare function writable<T>(value: Readable<T>): never;
47
+ export declare function writable<T>(value: undefined): Writable<T | undefined>;
48
+ export declare function writable<T>(): Writable<T | undefined>;
49
+ export declare function writable<T>(value: T): Writable<Unwrapped<T>>;
50
+ /**
51
+ * Observes a readable value. Calls `callback` each time the value changes.
52
+ * Returns a function to stop observing changes. This MUST be called when you are done
53
+ * with this observer to prevent memory leaks.
54
+ */
55
+ export declare function observe<T>(readable: Readable<T>, callback: (currentValue: T, previousValue: T) => void): StopFunction;
56
+ /**
57
+ * Observes a set of readable values.
58
+ * Calls `callback` with each value in the same order as `readables` each time any of their values change.
59
+ * Returns a function to stop observing changes. This MUST be called when you are done
60
+ * with this observer to prevent memory leaks.
61
+ */
62
+ export declare function observe<T extends Readable<any>[]>(readables: [...T], callback: (currentValues: ReadableValues<T>, previousValues: ReadableValues<T>) => void): StopFunction;
63
+ export declare function computed<I, O>(readable: Readable<I>, compute: (currentValue: I, previousValue?: I) => O): Readable<O>;
64
+ export declare function computed<I extends Readable<any>[], O>(readables: [...I], compute: (currentValues: ReadableValues<I>, previousValues?: ReadableValues<I>) => O): Readable<O>;
65
+ interface ProxyConfig<Source, Value> {
66
+ get(source: Source): Value;
67
+ set(source: Source, value: Value): void;
68
+ }
69
+ /**
70
+ * Creates a proxy `Writable` around an existing `Writable`.
71
+ * The config object takes custom `get` and `set` methods.
72
+ * All reads of this proxy goes through the `get` method
73
+ * and all writes go through `set`.
74
+ */
75
+ export declare function proxy<Source extends Writable<any>, Value>(source: Source, config: ProxyConfig<Source, Value>): Writable<Value>;
76
+ /**
77
+ * Creates a proxy `Writable` around an existing `Readable`.
78
+ * The config object takes custom `get` and `set` methods.
79
+ * All reads of this proxy goes through the `get` method
80
+ * and all writes go through `set`.
81
+ */
82
+ export declare function proxy<Source extends Readable<any>, Value>(source: Source, config: ProxyConfig<Source, Value>): Writable<Value>;
83
+ export declare function unwrap<T>(value: Readable<T> | T): T;
84
+ export {};
package/lib/store.d.ts ADDED
@@ -0,0 +1,67 @@
1
+ import { type AppContext, type ElementContext } from "./app.js";
2
+ import { type DebugChannel } from "./classes/DebugHub.js";
3
+ import { Readable, type ReadableValues } from "./state.js";
4
+ import type { BuiltInStores } from "./types.js";
5
+ export type Store<O, E> = (context: StoreContext<O>) => E | Promise<E>;
6
+ export interface StoreContext<Options = any> extends DebugChannel {
7
+ /**
8
+ * Returns the shared instance of `store`.
9
+ */
10
+ getStore<T extends Store<any, any>>(store: T): ReturnType<T>;
11
+ /**
12
+ * Returns the shared instance of a built-in store.
13
+ */
14
+ getStore<N extends keyof BuiltInStores>(name: N): BuiltInStores[N];
15
+ /**
16
+ * Runs `callback` after this store is connected.
17
+ */
18
+ onConnected(callback: () => any): void;
19
+ /**
20
+ * Runs `callback` after this store is disconnected.
21
+ */
22
+ onDisconnected(callback: () => any): void;
23
+ /**
24
+ * The name of this store for logging and debugging purposes.
25
+ */
26
+ name: string;
27
+ /**
28
+ * Takes an Error object, unmounts the app and displays its crash page.
29
+ */
30
+ crash(error: Error): void;
31
+ /**
32
+ * Observes a readable value while this store is connected. Calls `callback` each time the value changes.
33
+ */
34
+ observe<T>(readable: Readable<T>, callback: (currentValue: T, previousValue: T) => void): void;
35
+ /**
36
+ * Observes a set of readable values while this store is connected.
37
+ * Calls `callback` with each value in the same order as `readables` each time any of their values change.
38
+ */
39
+ observe<T extends Readable<any>[], V>(readables: [...T], callback: (currentValues: ReadableValues<T>, previousValues: ReadableValues<T>) => void): void;
40
+ /**
41
+ * Options this store was initialized with.
42
+ */
43
+ options: Options;
44
+ }
45
+ export interface StoreContextSecrets {
46
+ appContext: AppContext;
47
+ elementContext: ElementContext;
48
+ }
49
+ export declare function getStoreSecrets(c: StoreContext): StoreContextSecrets;
50
+ export declare function store<O>(callback: Store<any, O>): Store<any, O>;
51
+ /**
52
+ * Parameters passed to the makeStore function.
53
+ */
54
+ interface StoreConfig<O> {
55
+ store: Store<O, any>;
56
+ appContext: AppContext;
57
+ elementContext: ElementContext;
58
+ options: O;
59
+ }
60
+ export declare function initStore<O>(config: StoreConfig<O>): {
61
+ readonly name: string;
62
+ readonly exports: any;
63
+ setup(): void;
64
+ connect(): void;
65
+ disconnect(): void;
66
+ };
67
+ export {};
@@ -0,0 +1,30 @@
1
+ import { type DOMHandle } from "../markup.js";
2
+ import { type Writable } from "../state.js";
3
+ import { type StoreContext } from "../store.js";
4
+ import { type View } from "../view.js";
5
+ export interface DialogProps {
6
+ /**
7
+ * Whether the dialog is currently open.
8
+ */
9
+ $$open: Writable<boolean>;
10
+ /**
11
+ * Calls `callback` immediately after dialog has been connected.
12
+ */
13
+ transitionIn: (callback: () => Promise<void>) => void;
14
+ /**
15
+ * Calls `callback` and awaits its Promise before disconnecting the dialog.
16
+ */
17
+ transitionOut: (callback: () => Promise<void>) => void;
18
+ }
19
+ export interface OpenDialog {
20
+ instance: DOMHandle;
21
+ transitionInCallback?: () => Promise<void>;
22
+ transitionOutCallback?: () => Promise<void>;
23
+ }
24
+ /**
25
+ * Manages dialogs. Also known as modals.
26
+ * TODO: Describe this better.
27
+ */
28
+ export declare function DialogStore(ctx: StoreContext): {
29
+ open: <P extends DialogProps>(view: View<P>, props?: Omit<P, keyof DialogProps> | undefined) => () => void;
30
+ };
@@ -0,0 +1,10 @@
1
+ import { type StoreContext } from "../store.js";
2
+ type ScreenOrientation = "landscape" | "portrait";
3
+ type ColorScheme = "light" | "dark";
4
+ export declare function DocumentStore(ctx: StoreContext): {
5
+ $$title: import("../state.js").Writable<string>;
6
+ $visibility: import("../state.js").Readable<DocumentVisibilityState>;
7
+ $orientation: import("../state.js").Readable<ScreenOrientation>;
8
+ $colorScheme: import("../state.js").Readable<ColorScheme>;
9
+ };
10
+ export {};
@@ -0,0 +1,60 @@
1
+ import { type StoreContext } from "../store.js";
2
+ interface HTTPStoreOptions {
3
+ /**
4
+ * The fetch function to use for requests. Pass this to mock for testing.
5
+ */
6
+ fetch?: typeof window.fetch;
7
+ }
8
+ /**
9
+ * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,
10
+ * so it's the perfect way to handle things like auth headers and permission checks for API calls.
11
+ */
12
+ export declare function HTTPStore(ctx: StoreContext<HTTPStoreOptions>): {
13
+ /**
14
+ * Adds a new middleware that will apply to subsequent requests.
15
+ * Returns a function to remove this middleware.
16
+ *
17
+ * @param middleware - A middleware function that will intercept requests.
18
+ */
19
+ middleware(fn: HTTPMiddleware): () => void;
20
+ get<ResBody = unknown>(uri: string, options?: RequestOptions<never>): Promise<HTTPResponse<ResBody>>;
21
+ put<ResBody_1 = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody> | undefined): Promise<HTTPResponse<ResBody_1>>;
22
+ patch<ResBody_2 = unknown, ReqBody_1 = unknown>(uri: string, options?: RequestOptions<ReqBody_1> | undefined): Promise<HTTPResponse<ResBody_2>>;
23
+ post<ResBody_3 = unknown, ReqBody_2 = unknown>(uri: string, options?: RequestOptions<ReqBody_2> | undefined): Promise<HTTPResponse<ResBody_3>>;
24
+ delete<ResBody_4 = unknown>(uri: string, options?: RequestOptions<never>): Promise<HTTPResponse<ResBody_4>>;
25
+ head<ResBody_5 = unknown, ReqBody_3 = unknown>(uri: string, options?: RequestOptions<ReqBody_3> | undefined): Promise<HTTPResponse<ResBody_5>>;
26
+ options<ResBody_6 = unknown, ReqBody_4 = unknown>(uri: string, options?: RequestOptions<ReqBody_4> | undefined): Promise<HTTPResponse<ResBody_6>>;
27
+ trace<ResBody_7 = unknown, ReqBody_5 = unknown>(uri: string, options?: RequestOptions<ReqBody_5> | undefined): Promise<HTTPResponse<ResBody_7>>;
28
+ };
29
+ export type HTTPMiddleware = (request: HTTPRequest<unknown>, next: () => Promise<HTTPResponse<unknown>>) => void | Promise<void>;
30
+ interface RequestOptions<ReqBody> {
31
+ /**
32
+ * Body to send with the request.
33
+ */
34
+ body?: ReqBody;
35
+ /**
36
+ * Headers to send with the request.
37
+ */
38
+ headers?: Record<string, string | number | boolean> | Headers;
39
+ /**
40
+ * Query params to interpolate into the URL.
41
+ */
42
+ query?: Record<string, string | number | boolean> | URLSearchParams;
43
+ }
44
+ interface HTTPRequest<Body> {
45
+ method: string;
46
+ uri: string;
47
+ readonly sameOrigin: boolean;
48
+ headers: Headers;
49
+ query: URLSearchParams;
50
+ body: Body;
51
+ }
52
+ interface HTTPResponse<Body> {
53
+ method: string;
54
+ uri: string;
55
+ status: number;
56
+ statusText: string;
57
+ headers: Record<string, string>;
58
+ body: Body;
59
+ }
60
+ export {};