@manyducks.co/dolla 2.0.0-alpha.44 → 2.0.0-alpha.45

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
@@ -13,7 +13,7 @@ Dolla is a batteries-included JavaScript frontend framework covering the needs o
13
13
  - 🔀 Client side [routing](./docs/router.md) with nested routes and middleware support (check login status, preload data, etc).
14
14
  - 🐕 Built-in [HTTP](./docs/http.md) client with middleware support (set auth headers, etc).
15
15
  - 📍 Lightweight [localization](./docs/i18n.md) system (store translated strings in JSON files and call the `t` function to get them).
16
- - 🍳 Build system optional. [Write views in JSX](./docs/setup.md) or use `html` tagged template literals.
16
+ - 🍳 Build system optional. [Write views in JSX](./docs/setup.md) or bring in [HTM](https://github.com/developit/htm) and use tagged template literals directly in the browser.
17
17
 
18
18
  Dolla's goals include:
19
19
 
@@ -35,12 +35,12 @@ 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
  ```jsx
38
- import Dolla, { atom, html } from "@manyducks.co/dolla";
38
+ import Dolla, { atom } from "@manyducks.co/dolla";
39
39
 
40
- function Counter() {
40
+ function Counter(props, ctx) {
41
41
  const count = atom(0);
42
42
 
43
- this.effect(() => {
43
+ ctx.effect(() => {
44
44
  console.log(`Count is: ${count.get()}`);
45
45
  });
46
46
 
@@ -49,19 +49,19 @@ function Counter() {
49
49
  }
50
50
 
51
51
  function decrement() {
52
- // alternative to `set(get() - 1)`
53
52
  count.update((value) => value - 1);
53
+ // alternative to `set(get() - 1)`
54
54
  }
55
55
 
56
- return html`
56
+ return (
57
57
  <div>
58
- <p>Counter: ${count}</p>
58
+ <p>Counter: {counter}</p>
59
59
  <div>
60
- <button onclick=${increment}>+1</button>
61
- <button onclick=${decrement}>-1</button>
60
+ <button on:click={increment}>+1</button>
61
+ <button on:click={decrement}>-1</button>
62
62
  </div>
63
63
  </div>
64
- `;
64
+ );
65
65
  }
66
66
 
67
67
  Dolla.mount(document.body, Counter);
@@ -70,19 +70,19 @@ Dolla.mount(document.body, Counter);
70
70
  > TODO: Show small examples for routing and stores.
71
71
 
72
72
  ```js
73
- function MessageStore() {
74
- const message = atom("message", "Hello world!");
73
+ function MessageStore(options, ctx) {
74
+ const message = atom("Hello world!");
75
75
 
76
- this.effect(() => {
77
- this.log(`Message is now: ${get(message)}`);
76
+ ctx.effect(() => {
77
+ ctx.log(`Message is now: ${get(message)}`);
78
78
  // Calling `get()` inside an effect (or compose) function will track that reactive value as a dependency.
79
79
  // Effects will re-run when a dependency updates.
80
80
  });
81
- // `this` refers to the context object; StoreContext in a store and ViewContext in a view.
81
+ // `ctx` refers to the context object; StoreContext in a store and ViewContext in a view.
82
82
  // Context objects contain methods for controlling the component, logging and attaching lifecycle hooks.
83
83
 
84
84
  return {
85
- message: compose("message:readonly", () => get(message)),
85
+ message: compose(() => message.get()),
86
86
  // Creates a read-only reactive of the message value.
87
87
  // Composed values update when their dependencies update.
88
88
 
@@ -91,33 +91,33 @@ function MessageStore() {
91
91
  };
92
92
  }
93
93
 
94
- function App() {
95
- const { message, setMessage } = this.provide(MessageStore);
94
+ function App(props, ctx) {
95
+ const { message, setMessage } = ctx.provide(MessageStore);
96
96
  // Provides a MessageStore on this context and any child contexts.
97
97
  // When a store is provided its value is returned right away.
98
98
 
99
- return html`
99
+ return (
100
100
  <div>
101
- <${MessageView} />
102
- <${MessageView} />
103
- <${MessageView} />
101
+ <MessageView />
102
+ <MessageView />
103
+ <MessageView />
104
104
 
105
105
  <input
106
106
  type="text"
107
- value=${message}
108
- oninput=${(e) => {
107
+ value={message}
108
+ on:input={(e) => {
109
109
  setMessage(e.currentTarget.value);
110
110
  }}
111
111
  />
112
112
  </div>
113
- `;
113
+ );
114
114
  }
115
115
 
116
- function MessageView() {
117
- const { message } = this.get(MessageStore);
116
+ function MessageView(props, ctx) {
117
+ const { message } = ctx.get(MessageStore);
118
118
  // Gets the nearest instance of MessageStore. In this case the one provided at the parent.
119
119
 
120
- return html`<span>${message}</span>`;
120
+ return <span>{message}</span>;
121
121
  }
122
122
  ```
123
123
 
@@ -1,4 +1,6 @@
1
1
  import type { Dolla } from "./dolla";
2
+ import type { View } from "./nodes/view";
3
+ import type { Atom } from "./signals";
2
4
  import type { Store, StoreFunction } from "./store";
3
5
  export interface ElementContext {
4
6
  /**
@@ -21,6 +23,10 @@ export interface ElementContext {
21
23
  * The name of the nearest parent view.
22
24
  */
23
25
  viewName?: string;
26
+ /**
27
+ * Current route layer of the nearest view.
28
+ */
29
+ route?: Atom<View<{}> | undefined>;
24
30
  }
25
31
  export interface ComponentContext {
26
32
  /**
@@ -1,6 +1,6 @@
1
1
  import type { Renderable } from "../types.js";
2
2
  import type { ElementContext } from "./context.js";
3
- import { type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
3
+ import { View, type ViewContext, type ViewFunction, type ViewResult } from "./nodes/view.js";
4
4
  import { MaybeReactive, type Reactive } from "./signals.js";
5
5
  /**
6
6
  * Markup is a set of element metadata that hasn't been constructed into a MarkupElement yet.
@@ -18,7 +18,7 @@ export interface Markup {
18
18
  /**
19
19
  *
20
20
  */
21
- children?: Markup[];
21
+ children?: any[];
22
22
  }
23
23
  /**
24
24
  * A DOM node that has been constructed from a Markup object.
@@ -49,6 +49,9 @@ export interface MarkupAttributes {
49
49
  source: Reactive<Renderable>;
50
50
  };
51
51
  $outlet: {
52
+ view: Reactive<View<{}> | undefined>;
53
+ };
54
+ $fragment: {
52
55
  children: MaybeReactive<MarkupElement[]>;
53
56
  };
54
57
  $node: {
@@ -60,12 +63,11 @@ export interface MarkupAttributes {
60
63
  };
61
64
  [tag: string]: Record<string, any>;
62
65
  }
63
- export declare function createMarkup<T extends keyof MarkupAttributes>(type: T, attributes: MarkupAttributes[T], ...children: Renderable[]): Markup;
64
- export declare function createMarkup<I>(type: ViewFunction<I>, attributes?: I, ...children: Renderable[]): Markup;
66
+ export declare function markup<T extends keyof MarkupAttributes>(type: T, attributes: MarkupAttributes[T], ...children: Renderable[]): Markup;
67
+ export declare function markup<I>(type: ViewFunction<I>, attributes?: I, ...children: any[]): Markup;
65
68
  /**
66
69
  * Generate markup with HTML in a tagged template literal.
67
70
  */
68
- export declare const html: (strings: TemplateStringsArray, ...values: any[]) => Markup | Markup[];
69
71
  /**
70
72
  * Displays content conditionally. When `condition` holds a truthy value, `thenContent` is displayed; when `condition` holds a falsy value, `elseContent` is displayed.
71
73
  */
@@ -10,6 +10,8 @@ interface DynamicOptions {
10
10
  /**
11
11
  * Displays dynamic children without a parent element.
12
12
  * Renders a Reactive value via a render function.
13
+ *
14
+ * This is probably the most used element type aside from HTML.
13
15
  */
14
16
  export declare class Dynamic implements MarkupElement {
15
17
  [IS_MARKUP_ELEMENT]: boolean;
@@ -0,0 +1,19 @@
1
+ import { type MarkupElement } from "../markup.js";
2
+ import { type MaybeReactive } from "../signals.js";
3
+ import { IS_MARKUP_ELEMENT } from "../symbols.js";
4
+ /**
5
+ * Manages several MarkupElements as one.
6
+ */
7
+ export declare class Fragment implements MarkupElement {
8
+ [IS_MARKUP_ELEMENT]: boolean;
9
+ domNode: Text;
10
+ isMounted: boolean;
11
+ private source;
12
+ private elements;
13
+ private unsubscribe?;
14
+ constructor(source: MaybeReactive<MarkupElement[]>);
15
+ mount(parent: Node, after?: Node | undefined): void;
16
+ unmount(parentIsUnmounting?: boolean): void;
17
+ private cleanup;
18
+ private update;
19
+ }
@@ -1,11 +1,11 @@
1
1
  import { type ElementContext } from "../context.js";
2
- import { type Markup, type MarkupElement } from "../markup.js";
2
+ import { type MarkupElement } from "../markup.js";
3
3
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
4
4
  type HTMLOptions = {
5
5
  elementContext: ElementContext;
6
6
  tag: string;
7
7
  props: Record<string, any>;
8
- children?: Markup[];
8
+ children?: any[];
9
9
  };
10
10
  export declare class HTML implements MarkupElement {
11
11
  [IS_MARKUP_ELEMENT]: boolean;
@@ -1,17 +1,18 @@
1
1
  import { type MarkupElement } from "../markup.js";
2
- import { type MaybeReactive } from "../signals.js";
2
+ import { Reactive } from "../signals.js";
3
3
  import { IS_MARKUP_ELEMENT } from "../symbols.js";
4
+ import { View } from "./view.js";
4
5
  /**
5
- * Manages several MarkupElements as one.
6
+ * Renders the subroute of the nearest view.
6
7
  */
7
8
  export declare class Outlet implements MarkupElement {
8
9
  [IS_MARKUP_ELEMENT]: boolean;
9
10
  domNode: Text;
10
11
  isMounted: boolean;
11
- private source;
12
- private elements;
12
+ private view;
13
+ private mountedView?;
13
14
  private unsubscribe?;
14
- constructor(source: MaybeReactive<MarkupElement[]>);
15
+ constructor(view: Reactive<View<{}> | undefined>);
15
16
  mount(parent: Node, after?: Node | undefined): void;
16
17
  unmount(parentIsUnmounting?: boolean): void;
17
18
  private cleanup;
@@ -15,7 +15,7 @@ export interface ViewElement extends MarkupElement {
15
15
  /**
16
16
  * Take a ViewFunction and render it as a child of this view.
17
17
  */
18
- setChildView(view: ViewFunction<{}>): ViewElement;
18
+ setRouteView(view: ViewFunction<{}>): ViewElement;
19
19
  }
20
20
  export interface ViewContext extends Omit<Logger, "setName">, ComponentContext, StoreProviderContext, StoreConsumerContext {
21
21
  /**
@@ -48,7 +48,7 @@ export interface ViewContext extends Omit<Logger, "setName">, ComponentContext,
48
48
  */
49
49
  effect(callback: EffectCallback): UnsubscribeFunction;
50
50
  /**
51
- * Returns a Markup element that displays this view's children.
51
+ * Displays this view's subroutes if mounted as a router view.
52
52
  */
53
53
  outlet(): Markup;
54
54
  }
@@ -57,11 +57,11 @@ export declare class View<P> implements ViewElement {
57
57
  uniqueId: string;
58
58
  elementContext: ElementContext;
59
59
  logger: Logger;
60
- props: P;
60
+ props: P & {
61
+ children: Markup[] | undefined;
62
+ };
61
63
  fn: ViewFunction<P>;
62
64
  element?: MarkupElement;
63
- childMarkup: Markup[];
64
- children: import("../signals.js").Atom<MarkupElement[]>;
65
65
  lifecycleListeners: {
66
66
  beforeMount: (() => any)[];
67
67
  mount: (() => any)[];
@@ -73,6 +73,6 @@ export declare class View<P> implements ViewElement {
73
73
  isMounted: boolean;
74
74
  mount(parent: Node, after?: Node): void;
75
75
  unmount(parentIsUnmounting?: boolean): void;
76
- setChildView(fn: ViewFunction<{}>): View<{}>;
76
+ setRouteView(fn: ViewFunction<{}>): View<{}>;
77
77
  private _initialize;
78
78
  }
@@ -15,4 +15,4 @@ export type CrashViewProps = {
15
15
  */
16
16
  uid?: string;
17
17
  };
18
- export declare function DefaultCrashView(props: CrashViewProps): import("../markup.js").Markup | import("../markup.js").Markup[];
18
+ export declare function DefaultCrashView(props: CrashViewProps): import("../markup.js").Markup;
@@ -0,0 +1,9 @@
1
+ import { ViewContext, ViewResult } from "../nodes/view";
2
+ import { MaybeReactive, Reactive } from "../signals";
3
+ interface ForProps<T> {
4
+ each: MaybeReactive<Iterable<T>>;
5
+ key: (item: T, index: number) => any;
6
+ children: (item: Reactive<T>, index: Reactive<number>, ctx: ViewContext) => ViewResult;
7
+ }
8
+ export declare function For<T = any>({ each, key, children }: ForProps<T>): import("../markup").Markup;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { Renderable } from "../../types.js";
2
+ import { type ViewContext } from "../nodes/view.js";
3
+ /**
4
+ * A utility view that displays its children.
5
+ */
6
+ export declare function Fragment(props: {
7
+ children?: Renderable;
8
+ }, ctx: ViewContext): import("../markup.js").Markup;
@@ -1,5 +1,5 @@
1
1
  import { type ViewContext } from "../nodes/view.js";
2
2
  /**
3
- * A utility view that simply displays its children.
3
+ * A utility view that simply displays a route.
4
4
  */
5
5
  export declare function Passthrough(_: {}, ctx: ViewContext): import("../markup.js").Markup;
@@ -0,0 +1,8 @@
1
+ import { m, d as o } from "./markup-DZcvFR50.js";
2
+ function e(r, a) {
3
+ return m("$dynamic", { source: o(() => r.children) });
4
+ }
5
+ export {
6
+ e as F
7
+ };
8
+ //# sourceMappingURL=fragment-HanpB-Z6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fragment-HanpB-Z6.js","sources":["../src/core/views/fragment.ts"],"sourcesContent":["import type { Renderable } from \"../../types.js\";\nimport { markup } from \"../markup.js\";\nimport { type ViewContext } from \"../nodes/view.js\";\nimport { compose } from \"../signals.js\";\n\n/**\n * A utility view that displays its children.\n */\nexport function Fragment(props: { children?: Renderable }, ctx: ViewContext) {\n return markup(\"$dynamic\", { source: compose(() => props.children) });\n}\n"],"names":["Fragment","props","ctx","markup","compose"],"mappings":";AAQgB,SAAAA,EAASC,GAAkCC,GAAkB;AACpE,SAAAC,EAAO,YAAY,EAAE,QAAQC,EAAQ,MAAMH,EAAM,QAAQ,GAAG;AACrE;"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { atom, compose, effect, get, set, peek, untrack, getTracked } from "./core/signals.js";
2
- export type { Reactive, MaybeReactive, Atom } from "./core/signals.js";
1
+ export { atom, compose, effect, get, getTracked, peek, set, untrack } from "./core/signals.js";
2
+ export type { Atom, MaybeReactive, Reactive } from "./core/signals.js";
3
3
  export { deepEqual, shallowEqual, strictEqual } from "./utils.js";
4
4
  export { ref, type Ref } from "./core/ref.js";
5
- export { type StoreFunction, type StoreContext } from "./core/store.js";
5
+ export { type StoreContext, type StoreFunction } from "./core/store.js";
6
6
  export { createRouter, type Router, type RouterOptions } from "./router/index.js";
7
- export { cond, createMarkup, html, portal, list } from "./core/markup.js";
7
+ export { cond, list, markup, portal } from "./core/markup.js";
8
8
  export type { Markup, MarkupElement } from "./core/markup.js";
9
9
  import { Dolla } from "./core/dolla.js";
10
10
  declare const dolla: Dolla;
@@ -14,8 +14,8 @@ export declare const http: import("./http/index.js").HTTP;
14
14
  export declare const createLogger: (name: string, options?: import("./core/dolla.js").LoggerOptions) => import("./core/dolla.js").Logger;
15
15
  export type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from "./core/dolla.js";
16
16
  export type { ViewContext, ViewElement, ViewFunction } from "./core/nodes/view.js";
17
- export type { InputType, Renderable } from "./types.js";
18
17
  export type { CrashViewProps } from "./core/views/default-crash-view.js";
18
+ export type { InputType, Renderable } from "./types.js";
19
19
  import type { IntrinsicElements as Elements } from "./types";
20
20
  declare global {
21
21
  namespace JSX {