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

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
@@ -35,44 +35,38 @@ 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 { $, when, mount } from "@manyducks.co/dolla";
38
+ import { $, effect, when, mount } from "@manyducks.co/dolla";
39
39
 
40
40
  function Counter(props, ctx) {
41
41
  const $count = $(0);
42
42
 
43
- // An effect will re-run whenever any signal value accessed inside it changes.
44
- ctx.effect(() => {
45
- console.log(`Count is: ${$count()}`);
43
+ effect(() => {
44
+ console.log("Count is: " + $count());
45
+ // An effect will re-run whenever any signal accessed inside it receives a new value.
46
46
  });
47
47
 
48
- function increment() {
49
- // Pass a function that takes the current value and returns a new one.
50
- $count((x) => x + 1);
48
+ function reset() {
49
+ $count.set(0);
51
50
  }
52
51
 
53
- function decrement() {
54
- $count((x) => x - 1);
52
+ function increment() {
53
+ $count.set((current) => current + 1);
55
54
  }
56
55
 
57
- function reset() {
58
- // Set state directly by passing a (non-function) value.
59
- $count(0);
56
+ function decrement() {
57
+ $count.set((current) => current - 1);
60
58
  }
61
59
 
62
60
  return (
63
61
  <div>
64
- {/* Signals can be slotted into the DOM to render them */}
65
62
  <p>Counter: {$count}</p>
63
+ {/* Signals can be slotted into the DOM to render them */}
64
+
66
65
  <div>
67
- <button on:click={increment}>+1</button>
68
- <button on:click={decrement}>-1</button>
66
+ <button onClick={increment}>+1</button>
67
+ <button onClick={decrement}>-1</button>
68
+ <button onClick={reset}>Reset</button>
69
69
  </div>
70
-
71
- {/* We can derive a new signal on the fly and conditionally render something based on that condition */}
72
- {when(
73
- $(() => $count() > 10),
74
- <span>That's a lot of clicks!</span>,
75
- )}
76
70
  </div>
77
71
  );
78
72
  }
@@ -95,8 +89,8 @@ function MessageStore(options, ctx) {
95
89
  // Context objects contain methods for controlling the component, logging and attaching lifecycle hooks.
96
90
 
97
91
  return {
98
- message: $(() => message()),
99
- setMessage: (value: string) => message(value),
92
+ $message: $(() => message()),
93
+ setMessage: (value: string) => message.set(value.toUpperCase()),
100
94
  };
101
95
  }
102
96
 
@@ -104,7 +98,7 @@ function App(props, ctx) {
104
98
  // Provide a store for this and all child views.
105
99
  ctx.addStore(MessageStore);
106
100
 
107
- const { message, setMessage } = ctx.getStore(MessageStore);
101
+ const { $message, setMessage } = ctx.getStore(MessageStore);
108
102
  // Provides a MessageStore on this context and any child contexts.
109
103
  // When a store is provided its value is returned right away.
110
104
 
@@ -116,8 +110,8 @@ function App(props, ctx) {
116
110
 
117
111
  <input
118
112
  type="text"
119
- value={message}
120
- on:input={(e) => {
113
+ value={$message}
114
+ onInput={(e) => {
121
115
  setMessage(e.currentTarget.value);
122
116
  }}
123
117
  />
@@ -1,8 +1,8 @@
1
- export { $, batch, effect, get, untracked } from "./signals.js";
2
- export type { MaybeSignal, Signal, Source } from "./signals.js";
1
+ export { $, batch, effect, get, memo, writable, untracked } from "./signals.js";
2
+ export type { MaybeSignal, Writable, Signal } from "./signals.js";
3
3
  export { createContext } from "./context.js";
4
4
  export type { Context } from "./context.js";
5
- export { m, MarkupNode, portal, render, repeat, unless, when } from "./markup.js";
5
+ export { m, Markup, MarkupNode, portal, render, repeat, unless, when } from "./markup.js";
6
6
  export { ref, type Ref } from "./ref.js";
7
7
  export { For, type ForProps } from "./views/for.js";
8
8
  export { Show, type ShowProps } from "./views/show.js";
@@ -2,23 +2,24 @@ import type { IntrinsicElements, Renderable, View } from "../types.js";
2
2
  import { Context } from "./context.js";
3
3
  import { MarkupNode } from "./nodes/_markup.js";
4
4
  import { KeyFn, RenderFn } from "./nodes/repeat.js";
5
- import { type MaybeSignal, type Signal } from "./signals.js";
5
+ import { type Signal, type MaybeSignal } from "./signals.js";
6
6
  export { MarkupNode };
7
+ type PropsOf<V extends string | View<any>> = V extends View<infer U> ? U : any;
7
8
  /**
8
9
  * `Markup` is a set of metadata that will be constructed into a `MarkupNode`.
9
10
  */
10
- export declare class Markup<P = any> {
11
+ export declare class Markup<Type extends string | View<any> = string | View<any>> {
11
12
  /**
12
13
  * In the case of a view, type will be the View function itself. It can also hold an identifier for special nodes like "$cond", "$repeat", etc.
13
14
  * DOM nodes can be created by name, such as HTML elements like "div", "ul" or "span", SVG elements like ""
14
15
  */
15
- type: string | View<P>;
16
+ type: Type;
16
17
  /**
17
18
  * Data that will be passed to a new MarkupNode instance when it is constructed.
18
19
  * Includes a `children` prop if children were passed.
19
20
  */
20
- props: P | undefined;
21
- constructor(type: string | View<P>, props?: P);
21
+ props: PropsOf<Type>;
22
+ constructor(type: Type, props: PropsOf<Type>);
22
23
  }
23
24
  export declare enum MarkupType {
24
25
  DOM = "$dom",
@@ -1,5 +1,5 @@
1
1
  import type { Context } from "../context.js";
2
- import { type Signal } from "../signals.js";
2
+ import { Signal } from "../signals.js";
3
3
  import { MarkupNode } from "./_markup.js";
4
4
  /**
5
5
  * Renders any kind of content; markup, signals, DOM nodes, etc.
@@ -9,9 +9,9 @@ export declare class DynamicNode extends MarkupNode {
9
9
  private root;
10
10
  private children;
11
11
  private context;
12
- private $slot;
12
+ private slot;
13
13
  private unsubscribe?;
14
- constructor(context: Context, $slot: Signal<any>);
14
+ constructor(context: Context, slot: Signal<any>);
15
15
  getRoot(): Text;
16
16
  isMounted(): boolean;
17
17
  mount(parent: Node, after?: Node): void;
@@ -5,6 +5,7 @@ import { MarkupNode } from "./_markup.js";
5
5
  */
6
6
  export declare class ElementNode extends MarkupNode {
7
7
  private root;
8
+ private id;
8
9
  readonly tag: string;
9
10
  readonly props: Record<string, any>;
10
11
  private context;
@@ -19,6 +20,7 @@ export declare class ElementNode extends MarkupNode {
19
20
  unmount(skipDOM?: boolean): void;
20
21
  move(parent: Element, after?: Node): void;
21
22
  private attachProp;
23
+ private getKey;
22
24
  private applyProps;
23
25
  private applyStyles;
24
26
  private applyClasses;
@@ -6,10 +6,10 @@ export declare const VIEW: unique symbol;
6
6
  * Renders a View.
7
7
  */
8
8
  export declare class ViewNode<P> extends MarkupNode {
9
- uniqueId: string;
10
- context: Context;
11
- props: P;
12
- view: View<P>;
9
+ readonly id: string;
10
+ readonly props: P;
11
+ readonly context: Context;
12
+ readonly view: View<P>;
13
13
  node?: MarkupNode;
14
14
  /**
15
15
  * @param context - Parent contenxt to link to.
@@ -0,0 +1,17 @@
1
+ export type Callback = () => void;
2
+ /**
3
+ * Centralized scheduling for DOM updates.
4
+ */
5
+ declare class Scheduler {
6
+ #private;
7
+ /**
8
+ * Schedules an update on the next tick. If `key` is supplied, this update will replace any scheduled update with the same key.
9
+ */
10
+ scheduleUpdate(update: Callback, key?: string): void;
11
+ /**
12
+ * Registers a callback to run after all processing has finished in the next tick.
13
+ */
14
+ nextTick(callback: Callback): void;
15
+ }
16
+ declare const _default: Scheduler;
17
+ export default _default;
@@ -1,23 +1,30 @@
1
1
  import { Context } from "./context";
2
- interface ComputedGetterState<T> {
3
- value?: T;
4
- }
5
2
  export declare function getCurrentContext(): Context | undefined;
6
3
  export declare function setCurrentContext(context: Context | undefined): Context | undefined;
7
4
  /**
8
- * A getter that returns the current value held within the signal.
9
- * If called inside a trackable scope this signal will be tracked as a dependency.
5
+ * A function that returns the current value of a signal.
6
+ * Automatically tracked as a dependency when called within a tracking scope (such as `memo` or `effect` functions).
10
7
  */
11
8
  export interface Signal<T> {
12
9
  (): T;
13
10
  }
14
11
  /**
15
- * Extends Signal with the ability to pass a value or an updater function to change the Signal's value.
12
+ * A function that sets the value of the signal.
16
13
  */
17
- export interface Source<T> extends Signal<T> {
14
+ export interface Setter<T> {
18
15
  (value: T): void;
19
- (updater: (value: T) => T): void;
16
+ (update: (current: T) => T): void;
17
+ }
18
+ /**
19
+ * A getter and setter in a single object. Callable like a getter, but includes a `set` method for updating the signal's value.
20
+ */
21
+ export interface Writable<T> extends Signal<T> {
22
+ set: Setter<T>;
20
23
  }
24
+ /**
25
+ * Utility type for a value that may be a getter or a plain value.
26
+ * This value can be unwrapped to a plain value with `get` or `untracked` (depending on whether you're in a tracking context and need to track it).
27
+ */
21
28
  export type MaybeSignal<T> = Signal<T> | T;
22
29
  export type EqualityFn<T> = (current: T, next: T) => boolean;
23
30
  export interface SignalOptions<T> {
@@ -26,6 +33,26 @@ export interface SignalOptions<T> {
26
33
  */
27
34
  equals?: EqualityFn<T>;
28
35
  }
36
+ export declare function $<T>(compute: (previousValue?: T) => MaybeSignal<T>, options?: MemoOptions<T>): Signal<T>;
37
+ export declare function $<T>(): Writable<T | undefined>;
38
+ export declare function $<T>(value: undefined, options: SignalOptions<T | undefined>): Writable<T | undefined>;
39
+ export declare function $<T>(value: T, options?: SignalOptions<T>): Writable<T>;
40
+ export declare function writable<T>(): Writable<T | undefined>;
41
+ export declare function writable<T>(value: undefined, options: SignalOptions<T | undefined>): Writable<T | undefined>;
42
+ export declare function writable<T>(value: T, options?: SignalOptions<T>): Writable<T>;
43
+ export interface MemoOptions<T> extends SignalOptions<T> {
44
+ /**
45
+ * An array of signals this `memo` depends on. If this is passed, calls to signals within `fn` will NOT be tracked.
46
+ * Instead the `deps` array will be tracked and `fn` will re-run when any value in `deps` changes.
47
+ */
48
+ deps?: Signal<any>[];
49
+ }
50
+ /**
51
+ * Creates a derived Signal that recomputes its value only when its dependencies change.
52
+ * Dependencies are tracked when called inside `fn` by default,
53
+ * but can be overridden by passing a `deps` array in the options object.
54
+ */
55
+ export declare function memo<T>(fn: (previousValue?: T) => MaybeSignal<T>, options?: MemoOptions<T>): Signal<T>;
29
56
  /**
30
57
  * Suspends effects during `fn`. Effects for all updated Signal values are called at the end of the batch.
31
58
  */
@@ -43,6 +70,18 @@ export declare function get<T>(value: MaybeSignal<T>): T;
43
70
  */
44
71
  export type EffectFn = () => void | (() => void);
45
72
  export type UnsubscribeFn = () => void;
73
+ export declare const INTERNAL_EFFECT: unique symbol;
74
+ export interface EffectOptions {
75
+ /**
76
+ * An array of signals this effect depends on. If this is passed, calls to signals within `fn` will NOT be tracked.
77
+ * Instead the `deps` array will be tracked and `fn` will re-run when any value in `deps` changes.
78
+ */
79
+ deps?: Signal<any>[];
80
+ /**
81
+ * For internal use.
82
+ */
83
+ _type?: symbol;
84
+ }
46
85
  /**
47
86
  * Creates a tracked scope that re-runs whenever the values of any tracked reactives changes.
48
87
  * Reactives are tracked by accessing their `value` within the body of the function.
@@ -50,9 +89,4 @@ export type UnsubscribeFn = () => void;
50
89
  * NOTE: You must call the unsubscribe function to stop watching for changes.
51
90
  * If you are using an effect inside a View or Store, use `ctx.effect` instead, which cleans up automatically when the component unmounts.
52
91
  */
53
- export declare function effect(fn: EffectFn): UnsubscribeFn;
54
- export declare function $<T>(compute: (this: ComputedGetterState<T>) => MaybeSignal<T>, options?: SignalOptions<T>): Signal<T>;
55
- export declare function $<T>(value: T, options?: SignalOptions<T>): Source<T>;
56
- export declare function $<T>(value: undefined, options?: SignalOptions<T>): Source<T | undefined>;
57
- export declare function $<T>(): Source<T | undefined>;
58
- export {};
92
+ export declare function effect(fn: EffectFn, options?: EffectOptions): UnsubscribeFn;
@@ -22,4 +22,4 @@ export interface CrashViewProps {
22
22
  /**
23
23
  * The crash view displayed unless you specify your own.
24
24
  */
25
- export declare function DefaultCrashView(props: CrashViewProps): import("../markup.js").Markup<any>;
25
+ export declare function DefaultCrashView(props: CrashViewProps): import("../markup.js").Markup<string | import("../index.js").View<any>>;
@@ -15,7 +15,7 @@ export interface ForProps<T> {
15
15
  /**
16
16
  * A render function. Takes the item and its index in signal form and returns something to display for each item.
17
17
  */
18
- children: ($item: Signal<T>, $index: Signal<number>, ctx: Context) => Renderable;
18
+ children: (item: Signal<T>, index: Signal<number>, ctx: Context) => Renderable;
19
19
  }
20
20
  /**
21
21
  *
@@ -1,5 +1,5 @@
1
1
  import { Context, Logger, type Ref, type Store } from "../core";
2
- import { type EffectFn, MaybeSignal, type Signal } from "../core/signals";
2
+ import { type EffectFn, Signal, MaybeSignal, Setter, SignalOptions } from "../core/signals";
3
3
  /**
4
4
  * Returns the Context object of the View, Store or Mixin this hook is called in.
5
5
  */
@@ -10,21 +10,18 @@ export declare function useContext(): Context;
10
10
  */
11
11
  export declare function useLogger(name?: MaybeSignal<string>): Logger;
12
12
  /**
13
- * Sets the value of the Signal it is bound to.
13
+ * Creates a new read-only Getter and a bound Setter function.
14
14
  */
15
- export interface Setter<T> {
16
- (value: T): void;
17
- (fn: (current: T) => T): void;
18
- }
15
+ export declare function useState<T>(value: T, options?: SignalOptions<T>): [Signal<T>, Setter<T>];
19
16
  /**
20
17
  * Creates a new read-only Signal and a bound Setter function.
21
18
  */
22
- export declare function useState<T>(value: T): [Signal<T>, Setter<T>];
19
+ export declare function useState<T>(value: undefined, options: SignalOptions<T>): [Signal<T | undefined>, Setter<T | undefined>];
23
20
  /**
24
21
  * Creates a new read-only Signal and a bound Setter function.
25
22
  */
26
23
  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>;
24
+ export declare function useMemo<T>(compute: (current?: T) => MaybeSignal<T>, deps?: Signal<any>[], options?: SignalOptions<T>): Signal<T>;
28
25
  export declare function useEffect(fn: EffectFn, deps?: Signal<any>[]): void;
29
26
  /**
30
27
  * Takes the current state and a dispatched action. Returns a new state based on the action.
package/dist/hooks.js CHANGED
@@ -1,69 +1,64 @@
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";
1
+ import { w as s, m as f, g as i, u as a, h as x } from "./signals-DbDmN2gr.js";
2
+ import { r as m } from "./ref-BD79iqlg.js";
3
3
  function o() {
4
- const t = a();
4
+ const t = x();
5
5
  if (!t)
6
6
  throw new Error("No context found; hooks can only be called in the body of a View, Store or Mixin.");
7
7
  return t;
8
8
  }
9
- function m(t) {
9
+ function p(t) {
10
10
  const e = o();
11
11
  return t && e.setName(t), e;
12
12
  }
13
- function l(t) {
13
+ function d(t, e) {
14
14
  o();
15
- const e = u(t);
16
- return [() => e(), e];
15
+ const n = s(t, e);
16
+ return [() => n(), n.set];
17
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
- });
18
+ function w(t, e, n) {
19
+ return o(), f(t, { ...n, deps: e });
25
20
  }
26
21
  function S(t, e) {
27
22
  const n = o();
28
23
  e ? n.effect(() => {
29
- for (const r of e) c(r);
30
- s(t);
24
+ for (const c of e) i(c);
25
+ a(t);
31
26
  }) : n.effect(t);
32
27
  }
33
- function v(t, e) {
34
- const [n, r] = l(e);
35
- return [n, (f) => {
36
- r((i) => t(i, f));
28
+ function b(t, e) {
29
+ const [n, c] = d(e);
30
+ return [n, (r) => {
31
+ c((u) => t(u, r));
37
32
  }];
38
33
  }
39
34
  function M(t) {
40
35
  return o().getStore(t);
41
36
  }
42
- function b(...t) {
37
+ function y(...t) {
43
38
  o();
44
- const e = x(...t);
39
+ const e = m(...t);
45
40
  return Object.defineProperty(e, "current", { get: e, set: e }), e;
46
41
  }
47
- function w(t) {
42
+ function C(t) {
48
43
  const e = o();
49
44
  e.onMount(() => {
50
45
  const n = t();
51
46
  n && e.onUnmount(n);
52
47
  });
53
48
  }
54
- function y(t) {
49
+ function R(t) {
55
50
  o().onUnmount(t);
56
51
  }
57
52
  export {
58
53
  o as useContext,
59
54
  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,
55
+ p as useLogger,
56
+ w as useMemo,
57
+ C as useMount,
58
+ b as useReducer,
59
+ y as useRef,
60
+ d as useState,
66
61
  M as useStore,
67
- y as useUnmount
62
+ R as useUnmount
68
63
  };
69
64
  //# sourceMappingURL=hooks.js.map
package/dist/hooks.js.map CHANGED
@@ -1 +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;"}
1
+ {"version":3,"file":"hooks.js","sources":["../src/hooks/index.ts"],"sourcesContent":["import { Context, Logger, ref, type Ref, type Store } from \"../core\";\nimport {\n type EffectFn,\n get,\n getCurrentContext,\n Signal,\n MaybeSignal,\n memo,\n Setter,\n writable,\n SignalOptions,\n untracked,\n} 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 * Creates a new read-only Getter and a bound Setter function.\n */\nexport function useState<T>(value: T, options?: SignalOptions<T>): [Signal<T>, Setter<T>];\n\n/**\n * Creates a new read-only Signal and a bound Setter function.\n */\nexport function useState<T>(\n value: undefined,\n options: SignalOptions<T>,\n): [Signal<T | undefined>, Setter<T | undefined>];\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, options?: SignalOptions<T>): [Signal<T>, Setter<T>] {\n useContext(); // assert that we're in a valid context\n const state = writable(value as T, options);\n return [() => state(), state.set];\n}\n\nexport function useMemo<T>(\n compute: (current?: T) => MaybeSignal<T>,\n deps?: Signal<any>[],\n options?: SignalOptions<T>,\n): Signal<T> {\n useContext(); // assert that we're in a valid context\n return memo(compute, { ...options, deps });\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/**\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","options","state","writable","useMemo","compute","deps","memo","useEffect","fn","dep","get","untracked","useReducer","reducer","initialState","setState","action","current","useStore","store","useRef","valueRef","ref","useMount","callback","result","useUnmount"],"mappings":";;AAiBO,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;AAoBgB,SAAAI,EAAYC,GAAWC,GAAoD;AAC9E,EAAAP,EAAA;AACL,QAAAQ,IAAQC,EAASH,GAAYC,CAAO;AAC1C,SAAO,CAAC,MAAMC,KAASA,EAAM,GAAG;AAClC;AAEgB,SAAAE,EACdC,GACAC,GACAL,GACW;AACA,SAAAP,EAAA,GACJa,EAAKF,GAAS,EAAE,GAAGJ,GAAS,MAAAK,GAAM;AAC3C;AAEgB,SAAAE,EAAUC,GAAcH,GAA4B;AAClE,QAAMX,IAAUD,EAAW;AAC3B,EAAIY,IACFX,EAAQ,OAAO,MAAM;AAER,eAAAe,KAAOJ,EAAM,CAAAK,EAAID,CAAG;AAC/B,IAAAE,EAAUH,CAAE;AAAA,EAAA,CACb,IAEDd,EAAQ,OAAOc,CAAE;AAErB;AAgBgB,SAAAI,EACdC,GACAC,GACqC;AACrC,QAAM,CAACb,GAAOc,CAAQ,IAAIjB,EAASgB,CAAY;AAIxC,SAAA,CAACb,GAHS,CAACe,MAAmB;AACnC,IAAAD,EAAS,CAACE,MAAYJ,EAAQI,GAASD,CAAM,CAAC;AAAA,EAChD,CACuB;AACzB;AAKO,SAASE,EAAYC,GAAyB;AAE5C,SADS1B,EAAW,EACZ,SAAS0B,CAAK;AAC/B;AAeO,SAASC,KAAarB,GAA0B;AAC1C,EAAAN,EAAA;AACL,QAAA4B,IAAWC,EAAI,GAAGvB,CAAK;AACtB,gBAAA,eAAesB,GAAU,WAAW,EAAE,KAAKA,GAAU,KAAKA,GAAU,GACpEA;AACT;AAKO,SAASE,EAASC,GAA2C;AAClE,QAAM9B,IAAUD,EAAW;AAC3B,EAAAC,EAAQ,QAAQ,MAAM;AACpB,UAAM+B,IAASD,EAAS;AACpB,IAAAC,KAAgB/B,EAAA,UAAU+B,CAAM;AAAA,EAAA,CACrC;AACH;AAKO,SAASC,EAAWF,GAA4B;AAErD,EADgB/B,EAAW,EACnB,UAAU+B,CAAQ;AAC5B;"}
package/dist/i18n.js CHANGED
@@ -5,11 +5,11 @@ var D = (o) => {
5
5
  var J = (o, t, e) => t in o ? B(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
6
6
  var O = (o, t, e) => J(o, typeof t != "symbol" ? t + "" : t, e), _ = (o, t, e) => t.has(o) || D("Cannot " + e);
7
7
  var r = (o, t, e) => (_(o, t, "read from private field"), e ? e.call(o) : t.get(o)), m = (o, t, e) => t.has(o) ? D("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(o) : t.set(o, e), N = (o, t, e, n) => (_(o, t, "write to private field"), n ? n.call(o, e) : t.set(o, e), e), g = (o, t, e) => (_(o, t, "access private method"), e);
8
- import { c as K } from "./logger-Bl496yfY.js";
9
- import { $, d as Q, g as x } from "./signals-gCwiIe5X.js";
10
- import { b as C, i as j, c as U, t as P } from "./typeChecking-CbltMOUt.js";
8
+ import { c as K } from "./logger-B7RBYtzP.js";
9
+ import { w as Q, m as k, d as U, g as x } from "./signals-DbDmN2gr.js";
10
+ import { b as C, i as j, c as W, t as P } from "./typeChecking-CbltMOUt.js";
11
11
  var I, F, p, S, G;
12
- class W {
12
+ class X {
13
13
  constructor(t) {
14
14
  m(this, p);
15
15
  O(this, "config");
@@ -22,7 +22,7 @@ class W {
22
22
  if (!r(this, I)) {
23
23
  if (j(this.config.strings))
24
24
  t = this.config.strings;
25
- else if (U(this.config.fetch)) {
25
+ else if (W(this.config.fetch)) {
26
26
  if (t = await this.config.fetch(), !j(t))
27
27
  throw new Error(`Fetch function did not return an object of language strings: ${t}`);
28
28
  } else if (C(this.config.path)) {
@@ -80,7 +80,7 @@ I = new WeakMap(), F = new WeakMap(), p = new WeakSet(), S = function(t, e = [])
80
80
  segments: []
81
81
  };
82
82
  let a = "", s = 0, i = 0, c, w, l;
83
- const k = () => {
83
+ const $ = () => {
84
84
  c = {
85
85
  type: 1,
86
86
  name: "",
@@ -99,7 +99,7 @@ I = new WeakMap(), F = new WeakMap(), p = new WeakSet(), S = function(t, e = [])
99
99
  }
100
100
  switch (i) {
101
101
  case 0:
102
- t[s] === "{" && t[s + 1] === "{" ? (i = 1, s += 2, a.length > 0 && (n.segments.push({ type: 0, text: a }), a = ""), k()) : (a += t[s], s++);
102
+ t[s] === "{" && t[s + 1] === "{" ? (i = 1, s += 2, a.length > 0 && (n.segments.push({ type: 0, text: a }), a = ""), $()) : (a += t[s], s++);
103
103
  break;
104
104
  case 1:
105
105
  t[s] === "|" ? (i = 2, s += 1, c.name = a, a = "", y()) : t[s] === "}" && t[s + 1] === "}" ? (i = 0, s += 2, c.name = a, a = "", n.segments.push(c)) : (a += t[s], s++);
@@ -121,7 +121,7 @@ I = new WeakMap(), F = new WeakMap(), p = new WeakSet(), S = function(t, e = [])
121
121
  return i === 0 && a.length > 0 && n.segments.push({ type: 0, text: a }), n;
122
122
  };
123
123
  var b, h, E, T, v, d, u, H, L, V, M, A;
124
- class X {
124
+ class Y {
125
125
  constructor() {
126
126
  m(this, u);
127
127
  m(this, b);
@@ -129,8 +129,8 @@ class X {
129
129
  m(this, E, []);
130
130
  m(this, T, /* @__PURE__ */ new Map());
131
131
  m(this, v, "auto");
132
- m(this, d, $("en"));
133
- O(this, "$locale", $(r(this, d)));
132
+ m(this, d, Q("en"));
133
+ O(this, "$locale", k(r(this, d)));
134
134
  N(this, b, K("dolla.i18n")), this.addFormat("number", (t, e, n) => g(this, u, L).call(this, Number(e), n)), this.addFormat("datetime", (t, e, n) => g(this, u, V).call(this, e, n)), this.addFormat("list", (t, e, n) => g(this, u, M).call(this, e, n));
135
135
  }
136
136
  get locales() {
@@ -138,7 +138,7 @@ class X {
138
138
  }
139
139
  async setup(t) {
140
140
  if (t.translations.forEach((e) => {
141
- r(this, h).set(e.locale, new W(e));
141
+ r(this, h).set(e.locale, new X(e));
142
142
  }), t.locale && t.locale !== "auto") {
143
143
  if (!t.translations.some((n) => n.locale === t.locale))
144
144
  throw new Error(`Initial locale '${t.locale}' is not registered in the locales array.`);
@@ -169,7 +169,7 @@ class X {
169
169
  throw new Error(`Locale '${t}' has no translation.`);
170
170
  const n = r(this, h).get(e);
171
171
  try {
172
- await n.load(), N(this, E, []), r(this, d).call(this, e), r(this, b).info("set language to " + e);
172
+ await n.load(), N(this, E, []), r(this, d).set(e), r(this, b).info("set language to " + e);
173
173
  } catch (s) {
174
174
  s instanceof Error && r(this, b).crash(s);
175
175
  }
@@ -188,7 +188,7 @@ class X {
188
188
  throw new Error(
189
189
  `The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from "@manyducks.co/dolla"'`
190
190
  );
191
- return $(() => {
191
+ return k(() => {
192
192
  const n = {};
193
193
  for (const a in e)
194
194
  n[a] = x(e[a]);
@@ -227,7 +227,7 @@ class X {
227
227
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
228
228
  */
229
229
  number(t, e) {
230
- return $(() => g(this, u, L).call(this, x(t), e));
230
+ return k(() => g(this, u, L).call(this, x(t), e));
231
231
  }
232
232
  /**
233
233
  * Formats a date for the current locale. Uses `Intl.DateTimeFormat` under the hood.
@@ -239,7 +239,7 @@ class X {
239
239
  * const $formatted = Dolla.i18n.dateTime(date, { dateFormat: "short" });
240
240
  */
241
241
  dateTime(t, e) {
242
- return $(() => g(this, u, V).call(this, x(t), e));
242
+ return k(() => g(this, u, V).call(this, x(t), e));
243
243
  }
244
244
  /**
245
245
  * Formats a list for the current locale. Uses `Intl.ListFormat` under the hood.
@@ -251,7 +251,7 @@ class X {
251
251
  * const $formatted = Dolla.i18n.list(list, { });
252
252
  */
253
253
  list(t, e) {
254
- return $(() => g(this, u, M).call(this, x(t), e));
254
+ return k(() => g(this, u, M).call(this, x(t), e));
255
255
  }
256
256
  }
257
257
  b = new WeakMap(), h = new WeakMap(), E = new WeakMap(), T = new WeakMap(), v = new WeakMap(), d = new WeakMap(), u = new WeakSet(), H = function(t, e, n) {
@@ -273,7 +273,7 @@ b = new WeakMap(), h = new WeakMap(), E = new WeakMap(), T = new WeakMap(), v =
273
273
  if (l.type === 0)
274
274
  c += l.text;
275
275
  else if (l.type === 1) {
276
- let k = Y(n, l.name);
276
+ let $ = Z(n, l.name);
277
277
  const y = ((w = n.formatOverrides) == null ? void 0 : w[l.name]) ?? [...l.formats];
278
278
  l.name === "count" && y.length === 0 && y.push({ name: "number", options: {} });
279
279
  for (const f of y) {
@@ -284,9 +284,9 @@ b = new WeakMap(), h = new WeakMap(), E = new WeakMap(), T = new WeakMap(), v =
284
284
  );
285
285
  throw r(this, b).crash(z), z;
286
286
  }
287
- k = R(t, k, f.options);
287
+ $ = R(t, $, f.options);
288
288
  }
289
- c += k;
289
+ c += $;
290
290
  }
291
291
  return c;
292
292
  }, L = function(t, e) {
@@ -298,10 +298,10 @@ b = new WeakMap(), h = new WeakMap(), E = new WeakMap(), T = new WeakMap(), v =
298
298
  }, // relativeTime(date?: MaybeSignal<string | number | Date | undefined>): Signal<string> {}
299
299
  A = function(t, e) {
300
300
  for (const n of r(this, E))
301
- if (n[0] === t && Q(n[1], e))
301
+ if (n[0] === t && U(n[1], e))
302
302
  return n[2];
303
303
  };
304
- function Y(o, t) {
304
+ function Z(o, t) {
305
305
  const e = String(t).split(/[\.\[\]]/).filter((a) => a.trim() !== "");
306
306
  let n = o;
307
307
  for (; e.length > 0; ) {
@@ -310,9 +310,9 @@ function Y(o, t) {
310
310
  }
311
311
  return n;
312
312
  }
313
- const q = new X(), nt = q.t.bind(q);
313
+ const q = new Y(), at = q.t.bind(q);
314
314
  export {
315
315
  q as i18n,
316
- nt as t
316
+ at as t
317
317
  };
318
318
  //# sourceMappingURL=i18n.js.map