march-hare 0.6.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 (38) hide show
  1. package/README.md +453 -0
  2. package/dist/march-hare.js +6 -0
  3. package/dist/march-hare.umd.cjs +1 -0
  4. package/dist/src/library/action/index.d.ts +66 -0
  5. package/dist/src/library/action/utils.d.ts +89 -0
  6. package/dist/src/library/annotate/index.d.ts +25 -0
  7. package/dist/src/library/boundary/components/broadcast/index.d.ts +12 -0
  8. package/dist/src/library/boundary/components/broadcast/types.d.ts +19 -0
  9. package/dist/src/library/boundary/components/broadcast/utils.d.ts +39 -0
  10. package/dist/src/library/boundary/components/consumer/components/partition/index.d.ts +27 -0
  11. package/dist/src/library/boundary/components/consumer/components/partition/types.d.ts +9 -0
  12. package/dist/src/library/boundary/components/consumer/index.d.ts +19 -0
  13. package/dist/src/library/boundary/components/consumer/types.d.ts +37 -0
  14. package/dist/src/library/boundary/components/consumer/utils.d.ts +13 -0
  15. package/dist/src/library/boundary/components/mode/index.d.ts +15 -0
  16. package/dist/src/library/boundary/components/mode/types.d.ts +7 -0
  17. package/dist/src/library/boundary/components/mode/utils.d.ts +55 -0
  18. package/dist/src/library/boundary/components/scope/index.d.ts +40 -0
  19. package/dist/src/library/boundary/components/scope/types.d.ts +20 -0
  20. package/dist/src/library/boundary/components/scope/utils.d.ts +19 -0
  21. package/dist/src/library/boundary/components/tasks/index.d.ts +14 -0
  22. package/dist/src/library/boundary/components/tasks/types.d.ts +43 -0
  23. package/dist/src/library/boundary/components/tasks/utils.d.ts +26 -0
  24. package/dist/src/library/boundary/index.d.ts +20 -0
  25. package/dist/src/library/boundary/types.d.ts +4 -0
  26. package/dist/src/library/error/index.d.ts +2 -0
  27. package/dist/src/library/error/types.d.ts +75 -0
  28. package/dist/src/library/error/utils.d.ts +15 -0
  29. package/dist/src/library/hooks/index.d.ts +43 -0
  30. package/dist/src/library/hooks/types.d.ts +72 -0
  31. package/dist/src/library/hooks/utils.d.ts +198 -0
  32. package/dist/src/library/index.d.ts +16 -0
  33. package/dist/src/library/resource/index.d.ts +99 -0
  34. package/dist/src/library/types/index.d.ts +718 -0
  35. package/dist/src/library/utils/index.d.ts +42 -0
  36. package/dist/src/library/utils/utils.d.ts +5 -0
  37. package/dist/src/library/utils.d.ts +37 -0
  38. package/package.json +104 -0
package/README.md ADDED
@@ -0,0 +1,453 @@
1
+ <div align="center">
2
+ <img src="/media/logo-v3.png" width="475" />
3
+
4
+ [![Checks](https://github.com/Wildhoney/march-hare/actions/workflows/checks.yml/badge.svg)](https://github.com/Wildhoney/march-hare/actions/workflows/checks.yml)
5
+
6
+ </div>
7
+
8
+ Strongly typed React framework using generators and efficiently updated views alongside the publish-subscribe pattern.
9
+
10
+ **[View Live Demo →](https://wildhoney.github.io/march-hare/)**
11
+
12
+ ## Contents
13
+
14
+ 1. [Benefits](#benefits)
15
+ 1. [Getting started](#getting-started)
16
+
17
+ For advanced topics, see the [recipes directory](./recipes/).
18
+
19
+ ## Benefits
20
+
21
+ - Event-driven architecture superset of [React](https://react.dev/).
22
+ - Views only re-render when the model changes.
23
+ - Built-in [optimistic updates](https://medium.com/@kyledeguzmanx/what-are-optimistic-updates-483662c3e171) via [Immertation](https://github.com/Wildhoney/Immertation).
24
+ - No stale closures &ndash; `context.data` stays current after `await`.
25
+ - No need to lift state &ndash; siblings communicate via events.
26
+ - Reduces context proliferation &ndash; events replace many contexts.
27
+ - No need to memoize callbacks &ndash; handlers are stable references with fresh closure access.
28
+ - Clear separation between business logic and markup.
29
+ - Complements [Feature Slice Design](https://feature-sliced.design/) architecture.
30
+ - Strongly typed dispatches, models, payloads, etc.
31
+ - Built-in request cancellation with `AbortController`.
32
+ - Granular async state tracking per model field.
33
+ - Declarative lifecycle hooks without `useEffect`.
34
+ - Centralised error handling via the global `Lifecycle.Fault` broadcast.
35
+ - React Native compatible &ndash; uses [eventemitter3](https://github.com/primus/eventemitter3) for cross-platform pub/sub.
36
+
37
+ ## Getting started
38
+
39
+ We dispatch the `Actions.Name` event upon clicking the "Sign in" button and within the component we subscribe to that same event via `useActions` so that when it's triggered it updates the model with the payload &ndash; in the React component we render `model.name`. The `With.Update` helper binds the action's payload directly to a model property.
40
+
41
+ ```tsx
42
+ import { useActions, Action, With } from "march-hare";
43
+
44
+ type Model = {
45
+ name: string | null;
46
+ };
47
+
48
+ const model: Model = {
49
+ name: null,
50
+ };
51
+
52
+ export class Actions {
53
+ static Name = Action<string>("Name");
54
+ }
55
+
56
+ export default function Profile(): React.ReactElement {
57
+ const [state, actions] = useActions<Model, typeof Actions>(model);
58
+
59
+ actions.useAction(Actions.Name, With.Update("name"));
60
+
61
+ return (
62
+ <>
63
+ <p>Hey {state.name}</p>
64
+
65
+ <button onClick={() => actions.dispatch(Actions.Name, randomName())}>
66
+ Sign in
67
+ </button>
68
+ </>
69
+ );
70
+ }
71
+ ```
72
+
73
+ When you need to do more than just assign the payload &ndash; such as making an API request &ndash; expand `useAction` to a full function. It can be synchronous, asynchronous, or even a generator:
74
+
75
+ ```tsx
76
+ actions.useAction(Actions.Name, async (context) => {
77
+ context.actions.produce(
78
+ (draft) =>
79
+ void (draft.model.name = context.actions.annotate(null, Op.Update)),
80
+ );
81
+
82
+ const name = await fetch(api.user());
83
+
84
+ context.actions.produce((draft) => void (draft.model.name = name));
85
+ });
86
+ ```
87
+
88
+ Notice we're using `annotate` which you can read more about in the [Immertation documentation](https://github.com/Wildhoney/Immertation). Nevertheless once the request is finished we update the model again with the `name` fetched from the response and update our React component again.
89
+
90
+ If you need to access external reactive values (like props or `useState` from parent components) that always reflect the latest value even after `await` operations, pass a data callback to `useActions`:
91
+
92
+ ```tsx
93
+ const actions = useActions<Model, typeof Actions, { query: string }>(
94
+ model,
95
+ () => ({ query: props.query }),
96
+ );
97
+
98
+ actions.useAction(Actions.Search, async (context) => {
99
+ await fetch("/search");
100
+ // context.data.query is always the latest value
101
+ console.log(context.data.query);
102
+ });
103
+ ```
104
+
105
+ For more details, see the [referential equality recipe](./recipes/referential-equality.md).
106
+
107
+ Both the model and actions type parameters default to `void`, so you can call `useActions()` with no generics at all when neither is needed:
108
+
109
+ ```tsx
110
+ import { useActions, Lifecycle } from "march-hare";
111
+
112
+ class Actions {
113
+ static Mount = Lifecycle.Mount();
114
+ }
115
+
116
+ const actions = useActions<void, typeof Actions>();
117
+
118
+ actions.useAction(Actions.Mount, () => {
119
+ console.log("Mounted!");
120
+ });
121
+ ```
122
+
123
+ If your component doesn't need local state but still needs to dispatch or listen to typed actions, pass `void` as the model type. No initial model is required:
124
+
125
+ ```tsx
126
+ import { useActions, Action, Lifecycle } from "march-hare";
127
+
128
+ export class Actions {
129
+ static Ping = Action("Ping");
130
+ }
131
+
132
+ export default function Pinger(): React.ReactElement {
133
+ const [, actions] = useActions<void, typeof Actions>();
134
+
135
+ actions.useAction(Actions.Ping, () => {
136
+ console.log("Pinged!");
137
+ });
138
+
139
+ return <button onClick={() => actions.dispatch(Actions.Ping)}>Ping</button>;
140
+ }
141
+ ```
142
+
143
+ This is useful for components that only coordinate via events &ndash; forwarding broadcasts, triggering side-effects, or bridging external systems. You can still use lifecycle hooks, `context.data`, and `dispatch` as normal. See the [void model recipe](./recipes/void-model.md) for more details.
144
+
145
+ Each action should be responsible for managing its own data &ndash; in this case our `Profile` action handles fetching the user but other components may want to consume it &ndash; for that we should use a broadcast action:
146
+
147
+ ```tsx
148
+ class BroadcastActions {
149
+ static Name = Action<string>("Name", Distribution.Broadcast);
150
+ }
151
+
152
+ class Actions {
153
+ static Broadcast = BroadcastActions;
154
+ static Profile = Action<string>("Profile");
155
+ }
156
+ ```
157
+
158
+ ```tsx
159
+ actions.useAction(Actions.Profile, async (context) => {
160
+ context.actions.produce(
161
+ (draft) =>
162
+ void (draft.model.name = context.actions.annotate(null, Op.Update)),
163
+ );
164
+
165
+ const name = await fetch(api.user());
166
+
167
+ context.actions.produce((draft) => void (draft.model.name = name));
168
+
169
+ context.actions.dispatch(Actions.Broadcast.Name, name);
170
+ });
171
+ ```
172
+
173
+ Once we have the broadcast action, if we want to listen for it and perform another operation in our local component we can do that via `useAction`:
174
+
175
+ ```tsx
176
+ actions.useAction(Actions.Broadcast.Name, async (context, name) => {
177
+ const friends = await fetch(api.friends(name));
178
+
179
+ context.actions.produce((draft) => void (draft.model.friends = friends));
180
+ });
181
+ ```
182
+
183
+ Both `read` and `peek` access the latest cached broadcast value without subscribing via `useAction`. The difference is that `read` waits for any pending annotations on the corresponding model field to settle before resolving, whereas `peek` returns the value immediately:
184
+
185
+ ```tsx
186
+ actions.useAction(Actions.FetchFriends, async (context) => {
187
+ const name = await context.actions.resolution(Actions.Broadcast.Name);
188
+ if (!name) return;
189
+ const friends = await fetch(api.friends(name));
190
+ context.actions.produce(({ model }) => void (model.friends = friends));
191
+ });
192
+ ```
193
+
194
+ `peek` is useful for guard checks or synchronous reads where you don't need to wait for settled state:
195
+
196
+ ```tsx
197
+ actions.useAction(Actions.Check, (context) => {
198
+ const name = context.actions.peek(Actions.Broadcast.Name);
199
+ if (!name) return;
200
+ console.log(name);
201
+ });
202
+ ```
203
+
204
+ Dispatch is awaitable &ndash; `context.actions.dispatch` returns a `Promise<void>` that resolves when all triggered handlers have completed. This prevents UI flashes where local state changes before upstream handlers finish:
205
+
206
+ ```tsx
207
+ actions.useAction(Actions.Mount, async (context) => {
208
+ // Wait for all PaymentSent handlers across the app to finish.
209
+ await context.actions.dispatch(Actions.Broadcast.PaymentSent);
210
+
211
+ // Safe to update local state now — upstream work is done.
212
+ context.actions.produce(({ model }) => void (model.loading = false));
213
+ });
214
+ ```
215
+
216
+ Generator handlers are excluded from the await &mdash; they run in the background and do not block the dispatch promise, since they are typically long-lived (polling, SSE streams, etc.).
217
+
218
+ You can also render broadcast values declaratively in JSX with `actions.stream`. The renderer callback receives `(value, inspect)` and returns React nodes:
219
+
220
+ ```tsx
221
+ function Dashboard() {
222
+ const [model, actions] = useActions<Model, typeof Actions>(initialModel);
223
+
224
+ return (
225
+ <div>
226
+ {actions.stream(Actions.Broadcast.User, (user, inspect) => (
227
+ <span>Welcome, {user.name}</span>
228
+ ))}
229
+ </div>
230
+ );
231
+ }
232
+ ```
233
+
234
+ Components that mount after a broadcast has already been dispatched automatically receive the cached value via their `useAction` handler. If you also fetch data in `Lifecycle.Mount()`, see the [mount deduplication recipe](./recipes/mount-broadcast-deduplication.md) to avoid duplicate requests.
235
+
236
+ For remote data, declare a `Resource` at module scope &ndash; same shape as `Action` &ndash; and consume it via `actions.useResource` inside a component. Convention is to keep all resources in `resources.ts` and import them as a namespace:
237
+
238
+ ```ts
239
+ // resources.ts
240
+ import { Resource } from "march-hare";
241
+
242
+ export const user = Resource("user", () => ky.get("/api/user").json<User>());
243
+ ```
244
+
245
+ ```tsx
246
+ // actions.ts
247
+ import * as marchHare from "march-hare";
248
+ import * as resource from "./resources";
249
+
250
+ export function useActions() {
251
+ const actions = marchHare.useActions<Model, typeof Actions>(initialModel);
252
+
253
+ const user = actions.useResource(resource.user);
254
+
255
+ actions.useAction(Actions.Mount, async (context) => {
256
+ const data = await user.run.if({ over: { minutes: 5 } });
257
+
258
+ context.actions.produce(({ model }) => void (model.user = data));
259
+ });
260
+
261
+ return actions;
262
+ }
263
+ ```
264
+
265
+ `actions.useResource(handle)` returns a frozen `{ run, data, at }` object. Every call to `run()` hits the network &ndash; concurrent calls share one in-flight request, but there is no memoised result. `data` and `at` are read-only snapshots of the most recent successful payload and a `Temporal.Instant` of when it resolved (both `null` until the first success). Coordination across components still happens at the broadcast layer; `data` is a diagnostic snapshot, not a reactive subscription. `Temporal` is read from the host runtime &ndash; bring a polyfill (e.g. [`@js-temporal/polyfill`](https://github.com/js-temporal/temporal-polyfill)) if your target environment does not yet expose it natively. `run.if({ over })` accepts a `Temporal.Duration`, a `DurationLike` object, or an ISO 8601 duration string.
266
+
267
+ `Resource` takes two arguments: a key and a fetcher. The fetcher receives the call-site `params` object as its only argument and returns a `Promise<T>`. There are no callbacks &ndash; no `onSuccess`, no `onError`, no injected `dispatch`. Side-effects after a run (broadcasting, analytics, model writes) live in the `useAction` handler that awaited `run()`, next to the rest of the flow:
268
+
269
+ ```ts
270
+ export const user = Resource("user", () => ky.get("/api/user").json<User>());
271
+
272
+ actions.useAction(Actions.Mount, async (context) => {
273
+ const data = await user.run();
274
+ await context.actions.dispatch(Actions.Broadcast.UserUpdated, data);
275
+ context.actions.produce(({ model }) => void (model.user = data));
276
+ });
277
+ ```
278
+
279
+ `params` is the second generic on `Resource` and defaults to `{}`. Declare it when the fetcher needs call-time inputs &ndash; cursors, ids, query strings. `params` is a single object (not positional args), which keeps call sites self-documenting and lets in-flight dedup key cleanly per param shape:
280
+
281
+ ```ts
282
+ type Params = { cursor: string | null };
283
+
284
+ export const feed = Resource<Page<Item>, Params>("feed", ({ cursor }) =>
285
+ http
286
+ .get("feed", { searchParams: { cursor: cursor ?? "" } })
287
+ .json<Page<Item>>(),
288
+ );
289
+
290
+ const feed = actions.useResource(resource.feed);
291
+ const page = await feed.run({ cursor: context.model.cursor });
292
+ ```
293
+
294
+ A complete IntersectionObserver-driven infinite-scroll demo lives at [`src/example/transactions/`](./src/example/transactions/) &ndash; mock paginated API, scroll-triggered `LoadMore`, `pending()` guard, broadcast on success.
295
+
296
+ For typed failure routing, wrap the call in `try/catch` and use `instanceof` &ndash; TypeScript cannot type promise rejections, so narrowing happens in the handler that catches them:
297
+
298
+ ```ts
299
+ actions.useAction(Actions.Mount, async (context) => {
300
+ try {
301
+ const data = await user.run();
302
+ context.actions.produce(({ model }) => void (model.user = data));
303
+ } catch (error) {
304
+ if (error instanceof RateLimitedError) {
305
+ await context.actions.dispatch(
306
+ Actions.Broadcast.RateLimited,
307
+ error.retryAfter,
308
+ );
309
+ }
310
+ throw error;
311
+ }
312
+ });
313
+ ```
314
+
315
+ See the [Resource recipe](./recipes/use-resource.md) for the three-tier error handling model, parameterised resources, and limitations.
316
+
317
+ For targeted event delivery, use channeled actions. Define a channel type as the second generic argument and call the action with a channel object &ndash; handlers fire when the dispatch channel matches:
318
+
319
+ ```tsx
320
+ class Actions {
321
+ // Second generic arg defines the channel type
322
+ static UserUpdated = Action<User, { UserId: number }>("UserUpdated");
323
+ }
324
+
325
+ // Subscribe to updates for a specific user
326
+ actions.useAction(
327
+ Actions.UserUpdated({ UserId: props.userId }),
328
+ (context, user) => {
329
+ // Only fires when dispatched with matching UserId
330
+ },
331
+ );
332
+
333
+ // Subscribe to all admin user updates
334
+ actions.useAction(
335
+ Actions.UserUpdated({ Role: Role.Admin }),
336
+ (context, user) => {
337
+ // Fires for {Role: Role.Admin}, {Role: Role.Admin, UserId: 5}, etc.
338
+ },
339
+ );
340
+
341
+ // Dispatch to specific user
342
+ actions.dispatch(Actions.UserUpdated({ UserId: user.id }), user);
343
+
344
+ // Dispatch to all admin handlers
345
+ actions.dispatch(Actions.UserUpdated({ Role: Role.Admin }), user);
346
+
347
+ // Dispatch to plain action - ALL handlers fire (plain + all channeled)
348
+ actions.dispatch(Actions.UserUpdated, user);
349
+ ```
350
+
351
+ Channel values support non-nullable primitives: `string`, `number`, `boolean`, or `symbol`. By convention, use uppercase keys like `{UserId: 4}` to distinguish channel keys from payload properties.
352
+
353
+ For scoped communication between component groups, use multicast actions with the `withScope` HOC. Each multicast action defines its own scope &ndash; pass the same action to `withScope` and to `dispatch`, no separate scope name required:
354
+
355
+ ```tsx
356
+ import { Action, Distribution, withScope } from "march-hare";
357
+
358
+ // Group multicast actions on a class named `Scope`.
359
+ class Scope {
360
+ static Update = Action<number>("Update", Distribution.Multicast);
361
+ }
362
+
363
+ class Actions {
364
+ static Increment = Action("Increment");
365
+ }
366
+
367
+ function ScoreArea() {
368
+ return (
369
+ <>
370
+ <ScoreBoard />
371
+ <PlayerList />
372
+ </>
373
+ );
374
+ }
375
+
376
+ // Wrap the subtree where the scope applies.
377
+ export default withScope(Scope.Update, ScoreArea);
378
+
379
+ // Dispatch to every component inside the scope.
380
+ actions.dispatch(Scope.Update, 42);
381
+ ```
382
+
383
+ Unlike broadcast which reaches all mounted components, multicast is confined to the wrapped subtree &ndash; perfect for isolated widget groups, form sections, or distinct UI regions. Like broadcast, multicast caches dispatched values per scope &ndash; components that mount later automatically receive the cached value. See the [mount deduplication recipe](./recipes/mount-broadcast-deduplication.md) if you also fetch data in `Lifecycle.Mount()`.
384
+
385
+ See the [multicast recipe](./recipes/multicast-actions.md) for more details.
386
+
387
+ For coordinating between async handlers without re-rendering the JSX tree, use the per-`<Boundary>` mode handle returned by `useMode()`. Thread it through the `useActions` data callback so it shows up as `context.data.mode` inside handlers, fully typed. Mode is **not** reactive &mdash; drive view state through the model, not mode.
388
+
389
+ ```ts
390
+ import * as marchHare from "march-hare";
391
+
392
+ enum Mode {
393
+ Idle,
394
+ SigningOut,
395
+ }
396
+
397
+ export function useActions() {
398
+ const mode = marchHare.useMode<Mode>();
399
+ // Spell the data shape as the third generic so `context.data.mode` keeps
400
+ // its concrete type inside handlers.
401
+ const actions = marchHare.useActions<
402
+ Model,
403
+ typeof Actions,
404
+ { mode: typeof mode }
405
+ >(model, () => ({ mode }));
406
+
407
+ actions.useAction(Actions.SignOut, async (context) => {
408
+ context.data.mode.update(Mode.SigningOut);
409
+ await api.signOut();
410
+ context.data.mode.update(Mode.Idle);
411
+ });
412
+
413
+ actions.useAction(Actions.Refresh, async (context) => {
414
+ if (context.data.mode.read() === Mode.SigningOut) return;
415
+ // ...
416
+ });
417
+
418
+ return actions;
419
+ }
420
+ ```
421
+
422
+ Toggling boolean UI state &ndash; modals, sidebars, drawers &ndash; is one of the most common patterns. Bind a unicast action to a boolean field on the model with `With.Invert`:
423
+
424
+ ```tsx
425
+ import { useActions, Action, With } from "march-hare";
426
+
427
+ type Model = {
428
+ paymentDialog: boolean;
429
+ sidebar: boolean;
430
+ };
431
+
432
+ export class Actions {
433
+ static TogglePaymentDialog = Action("TogglePaymentDialog");
434
+ static ToggleSidebar = Action("ToggleSidebar");
435
+ }
436
+
437
+ const [model, actions] = useActions<Model, typeof Actions>({
438
+ paymentDialog: false,
439
+ sidebar: false,
440
+ });
441
+
442
+ actions.useAction(Actions.TogglePaymentDialog, With.Invert("paymentDialog"));
443
+ actions.useAction(Actions.ToggleSidebar, With.Invert("sidebar"));
444
+
445
+ // Dispatch from anywhere with access to the actions object.
446
+ actions.dispatch(Actions.TogglePaymentDialog);
447
+
448
+ {
449
+ model.paymentDialog && <PaymentDialog />;
450
+ }
451
+ ```
452
+
453
+ `With.Invert` only compiles when the named property is a boolean on the model. `With.Update("name")` works the same way for arbitrary fields, and the payload type must match `model[name]`.
@@ -0,0 +1,6 @@
1
+ import{G as e,A as t}from"@mobily/ts-belt";import{immerable as n,enablePatches as r,Immer as o}from"immer";import{jsx as s}from"react/jsx-runtime";import*as c from"react";const i=(e="")=>`march-hare.action/${e}`,a=(e="")=>`march-hare.action/broadcast/${e}`,u=(e="")=>`march-hare.action/multicast/${e}`,l=(e="")=>`march-hare.action.lifecycle/${e}`;class f{static Payload=/* @__PURE__ */Symbol("march-hare.brand/Payload");static Broadcast=/* @__PURE__ */Symbol("march-hare.brand/Broadcast");static Multicast=/* @__PURE__ */Symbol("march-hare.brand/Multicast");static Action=/* @__PURE__ */Symbol("march-hare.brand/Action");static Channel=/* @__PURE__ */Symbol("march-hare.brand/Channel")}function d(e){const t=/* @__PURE__ */Symbol(`march-hare.action.lifecycle/${e}`),n=function(e){return{[f.Action]:t,[f.Payload]:void 0,[f.Channel]:e,channel:e}};return Object.defineProperty(n,f.Action,{value:t,enumerable:!1}),Object.defineProperty(n,f.Payload,{value:void 0,enumerable:!1}),n}const p=Symbol(a("Fault"));class h{static Mount(){return d("Mount")}static Unmount(){return d("Unmount")}static Error(){return d("Error")}static Update(){return d("Update")}static Fault=(()=>{const e={};return Object.defineProperty(e,f.Action,{value:p,enumerable:!1}),Object.defineProperty(e,f.Payload,{value:void 0,enumerable:!1}),Object.defineProperty(e,f.Broadcast,{value:!0,enumerable:!1}),e})()}var m=/* @__PURE__ */(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(m||{}),y=/* @__PURE__ */(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(y||{});const b=e=>"symbol"==typeof e;function v(t){return e.isString(t)||b(t)?t:(e.isObject(t)||e.isFunction(t))&&f.Action in t?t[f.Action]:t}function g(t){if(e.isString(t))return t.startsWith(a());if(b(t))return t.description?.startsWith(a())??!1;if(e.isObject(t)||e.isFunction(t)){if(f.Broadcast in t&&t[f.Broadcast])return!0;if(f.Action in t){const e=t[f.Action];return e.description?.startsWith(a())??!1}}return!1}function w(t){const n=v(t),r=e.isString(n)?n:n.description??"";return r.startsWith(i())&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function O(t){return e.isObject(t)&&f.Channel in t&&"channel"in t}function j(e){const t=v(e),n=b(t)?t.description??"":t;return n.startsWith(l())&&n.slice(l().length)||null}function S(t){if(e.isString(t))return t.startsWith(u());if(b(t))return t.description?.startsWith(u())??!1;if(e.isObject(t)||e.isFunction(t)){if(f.Multicast in t&&t[f.Multicast])return!0;if(f.Action in t){const e=t[f.Action];return e.description?.startsWith(u())??!1}}return!1}const E=(e,t=m.Unicast)=>{const n=t===m.Broadcast?Symbol(a(e)):t===m.Multicast?Symbol(u(e)):Symbol(i(e)),r=function(e){return{[f.Action]:n,[f.Payload]:void 0,[f.Channel]:e,channel:e}};return Object.defineProperty(r,f.Action,{value:n,enumerable:!1}),Object.defineProperty(r,f.Payload,{value:void 0,enumerable:!1}),t===m.Broadcast&&Object.defineProperty(r,f.Broadcast,{value:!0,enumerable:!1}),t===m.Multicast&&Object.defineProperty(r,f.Multicast,{value:!0,enumerable:!1}),r};var P=/* @__PURE__ */(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Errored=2]="Errored",e))(P||{});class M extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}class C extends Error{name="TimeoutError";constructor(e="Timeout"){super(e)}}let x=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var k=/* @__PURE__ */(e=>(e[e.Add=1]="Add",e[e.Remove=2]="Remove",e[e.Update=4]="Update",e[e.Move=8]="Move",e[e.Replace=16]="Replace",e[e.Sort=32]="Sort",e[e.Create=64]="Create",e[e.Fetch=128]="Fetch",e[e.Clone=256]="Clone",e[e.Archive=512]="Archive",e[e.Restore=1024]="Restore",e[e.Merge=2048]="Merge",e[e.Reorder=4096]="Reorder",e[e.Sync=8192]="Sync",e[e.Publish=16384]="Publish",e[e.Link=32768]="Link",e[e.Unlink=65536]="Unlink",e[e.Lock=131072]="Lock",e[e.Unlock=262144]="Unlock",e[e.Import=524288]="Import",e[e.Export=1048576]="Export",e[e.Transfer=2097152]="Transfer",e))(k||{}),A=/* @__PURE__ */(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(A||{}),_=/* @__PURE__ */(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(_||{});class R{[n]=!0;static keys=new Set(Object.values(_));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new R(this.value,this.operation);return n.property=e,n.process=t,n}}class N{static immer=(()=>{r();const e=new o;return e.setAutoFreeze(!1),e})();static tag="κ";static id=x}function U(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function L(t){if(e.isNullable(t)||F(t))return t;if(e.isArray(t))return t.map(e=>L(e));if(e.isObject(t)&&B(t)){const e=Object.entries(t).map(([e,t])=>[e,L(t)]);return{...Object.fromEntries(e),[N.tag]:t[N.tag]??N.id()}}return t}function T(e){if(Array.isArray(e))return e.filter(e=>N.tag in e).map(e=>e[N.tag]??"").join(",");const t=e[N.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function B(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function F(t){return e.isNullable(t)||e.isString(t)||e.isNumber(t)||e.isBoolean(t)||"symbol"==typeof t||"bigint"==typeof t}function W(t,n,r,o,s,c){return function i(a,u=n.path){if(a instanceof R){const n=U(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!R.keys.has(e)&&t instanceof R).forEach(([e,t])=>i(t,u.concat(e))),F(a.value)){if(t===A.Hydrate)return a.value;const i=u.slice(0,-1),l=i.length>0?U(r,i.join(".")):r;return e.isNullable(l)||$(l,a,u.at(-1),o,s,c),n??a.value}if(t===A.Hydrate){const e=L(i(a.value,u));return $(e,a,null,o,s,c),e}const l=n??L(a.value);return $(l,a,null,o,s,c),e.isNullable(n)?l:(i(a.value,u),n)}if(e.isArray(a))return a.map((e,t)=>i(e,u.concat(t)));if(e.isObject(a)&&!B(a))return a;if(e.isObject(a)){const e=Object.entries(a).map(([e,t])=>[e,i(t,u.concat(e))]),n=Object.fromEntries(e);if(t===A.Hydrate){const e=L(n);return Object.entries(a).forEach(([t,n])=>{n instanceof R&&F(n.value)&&$(e,n,t,o,s,c)}),e}return n}return a}(n.value)}function $(e,t,n,r,o,s){const c=s(e),i=o.get(c)??[];o.set(c,[t.assign(n,r),...i])}class z{#e={};#t;#n=/* @__PURE__ */new Map;#r=/* @__PURE__ */new Set;#o=!1;constructor(e=T){this.#t=e}static pk(){return x()}static"κ"=z.pk;annotate(e,t){return new R(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(n,r,o,s,c){function i(s){const c=s.at(-1),i=U(n(),s),a=s.slice(0,-1),u=t.isNotEmpty(a)?U(n(),a):n();return[...e.isObject(i)||e.isArray(i)?r.get(o(i))?.filter(t=>e.isNullable(t.property))??[]:[],...e.isObject(u)?r.get(o(u))?.filter(e=>e.property===c)??[]:[]]}return function e(r){return new Proxy(()=>{},{get:(o,a)=>"pending"===a?()=>!t.isEmpty(i(r)):"remaining"===a?()=>t.length(i(r)):"box"===a?()=>({value:U(n(),r),inspect:e(r)}):"is"===a?e=>i(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.head(i(r))?.value??U(n(),r):"settled"===a?()=>new Promise(e=>{if(t.isEmpty(i(r)))return e(U(n(),r));const o=()=>{t.isEmpty(i(r))&&(c(o),e(U(n(),r)))};s(o)}):e([...r,String(a)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#s(A.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#s(A.Produce,e)}#s(e,t){const n=/* @__PURE__ */Symbol("process"),[,r]=N.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>N.immer.applyPatches(t,[{...r,value:W(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=L(this.#e),this.#c(),n}prune(e){this.#n.forEach((n,r)=>{const o=n.filter(t=>t.process!==e);t.isEmpty(o)?this.#n.delete(r):this.#n.set(r,o)}),this.#c()}#c(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}const H=new z;function I(e,t=k.Update){return H.annotate(t,e)}function D(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var G,J={exports:{}};const V=/* @__PURE__ */D((G||(G=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function s(e,t,r,s,c){if("function"!=typeof r)throw new TypeError("The listener must be a function");var i=new o(r,s||e,c),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],i]:e._events[a].push(i):(e._events[a]=i,e._eventsCount++),e}function c(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function i(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=/* @__PURE__ */Object.create(null),(new r).__proto__||(n=!1)),i.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},i.prototype.listeners=function(e){var t=this._events[n?n+e:e];if(!t)return[];if(t.fn)return[t.fn];for(var r=0,o=t.length,s=new Array(o);r<o;r++)s[r]=t[r].fn;return s},i.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},i.prototype.emit=function(e,t,r,o,s,c){var i=n?n+e:e;if(!this._events[i])return!1;var a,u,l=this._events[i],f=arguments.length;if(l.fn){switch(l.once&&this.removeListener(e,l.fn,void 0,!0),f){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,t),!0;case 3:return l.fn.call(l.context,t,r),!0;case 4:return l.fn.call(l.context,t,r,o),!0;case 5:return l.fn.call(l.context,t,r,o,s),!0;case 6:return l.fn.call(l.context,t,r,o,s,c),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},i.prototype.on=function(e,t,n){return s(this,e,t,n,!1)},i.prototype.once=function(e,t,n){return s(this,e,t,n,!0)},i.prototype.removeListener=function(e,t,r,o){var s=n?n+e:e;if(!this._events[s])return this;if(!t)return c(this,s),this;var i=this._events[s];if(i.fn)i.fn!==t||o&&!i.once||r&&i.context!==r||c(this,s);else{for(var a=0,u=[],l=i.length;a<l;a++)(i[a].fn!==t||o&&!i[a].once||r&&i[a].context!==r)&&u.push(i[a]);u.length?this._events[s]=1===u.length?u[0]:u:c(this,s)}return this},i.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&c(this,t):(this._events=new r,this._eventsCount=0),this},i.prototype.off=i.prototype.removeListener,i.prototype.addListener=i.prototype.on,i.prefixed=n,i.EventEmitter=i,e.exports=i}(J)),J.exports));class q extends V{cache=/* @__PURE__ */new Map;emit(e,...t){return this.cache.set(e,t[0]),super.emit(e,...t)}setCache(e,t){this.cache.set(e,t)}getCached(e){return this.cache.get(e)}fire(e,...t){return super.emit(e,...t)}}const K=c.createContext(new q);function Q(){return c.useContext(K)}function X({children:e}){const t=c.useMemo(()=>new q,[]);/* @__PURE__ */
2
+ return s(K.Provider,{value:t,children:e})}const Y=c.createContext(/* @__PURE__ */new Set);function Z({children:e}){const t=c.useMemo(()=>/* @__PURE__ */new Set,[]);/* @__PURE__ */
3
+ return s(Y.Provider,{value:t,children:e})}const ee=c.createContext({current:null});function te(){const e=c.useContext(ee);return c.useMemo(()=>({read:()=>e.current,update(t){e.current=t}}),[e])}function ne({children:e}){const t=c.useRef(null);/* @__PURE__ */
4
+ return s(ee.Provider,{value:t,children:e})}function re({children:e}){/* @__PURE__ */
5
+ return s(X,{children:/* @__PURE__ */s(ne,{children:/* @__PURE__ */s(Z,{children:e})})})}const oe=c.createContext(null);function se(){return c.useContext(oe)}function ce(e,t){return e?.get(t)??null}function ie(e,t){const n=`Scoped${t.displayName||t.name||"Component"}`,r=v(e);return{[n](e){const n=se(),o=c.useMemo(()=>({action:r,emitter:new q}),[]),i=c.useMemo(()=>{const e=new Map(n??[]);return e.set(r,o),e},[n,o]);/* @__PURE__ */
6
+ return s(oe.Provider,{value:i,children:/* @__PURE__ */s(t,{...e})})}}[n]}const ae=Symbol(((e="")=>`march-hare/replay${e}`)());function ue(e,t,...n){e instanceof q&&e.setCache(t,n[0]);const r=e.listeners(t);return 0===r.length?Promise.resolve():Promise.all(r.map(e=>Promise.resolve(e(...n)))).then(()=>{})}const le={Update:e=>(t,n)=>{t.actions.produce(t=>{t.model[e]=n})},Invert:e=>t=>{t.actions.produce(t=>{t.model[e]=!t.model[e]})}};function fe(e,t){for(const n of e.keys())if(j(n)===t)return n;return null}function de(){const[,e]=c.useReducer(e=>e+1,0);return e}function pe(e){if(e instanceof Error){if("TimeoutError"===e.name)return P.Timedout;if("AbortError"===e.name)return P.Supplanted}return P.Errored}const he=c.createContext(/* @__PURE__ */new Map);function me({action:t,renderer:n}){const r=Q(),o=c.useContext(he),s=de(),i=c.useMemo(()=>{const e=o.get(t);if(e)return e;const n={state:new z,listeners:/* @__PURE__ */new Set};return o.set(t,n),n},[t,o]);c.useLayoutEffect(()=>{function e(e){i.state.hydrate({value:e}),i.listeners.forEach(e=>e())}return i.listeners.add(s),r.on(t,e),()=>{i.listeners.delete(s),r.off(t,e)}},[t,r,i]);const a=i.state.model?.value;return e.isNullable(a)?null:n(a,i.state.inspect.value)}function ye(...n){const r=e.isUndefined(n[0])||e.isFunction(n[0])?{}:n[0],o=e.isFunction(n[0])?n[0]:n[1]??(()=>({})),s=Q(),i=se(),a=c.useContext(Y),u=de(),l=c.useRef(!1),f=c.useRef(null),d=c.useRef(new z);l.current||(l.current=!0,f.current=d.current.hydrate(r));const[h,m]=c.useState(()=>d.current.model),b=function(e){const t=c.useRef(e);return c.useLayoutEffect(()=>{t.current=e},[e]),c.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(o()),j=c.useMemo(()=>new V,[]),E=c.useRef({handlers:/* @__PURE__ */new Map});E.current.handlers=/* @__PURE__ */new Map;const P=function(){const e=c.useRef(/* @__PURE__ */new Set),t=c.useRef(/* @__PURE__ */new Set);return c.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),M=c.useRef(y.Mounting),C=c.useRef(/* @__PURE__ */new Set),x=c.useRef(0),A=c.useCallback((e,t,n)=>{const r=new AbortController,o={controller:r,action:e,payload:t};return a.add(o),C.current.add(o),{model:d.current.model,get phase(){return M.current},task:o,data:b,tasks:a,actions:{produce(e){if(r.signal.aborted)return;const t=d.current.produce(t=>{e({model:t,inspect:d.current.inspect})});m(d.current.model),n.processes.add(t),f.current&&(n.processes.add(f.current),f.current=null)},dispatch(e,t){if(r.signal.aborted)return Promise.resolve();const n=v(e),o=O(e)?e.channel:void 0;if(S(e)){const e=ce(i,n);return e?ue(e.emitter,n,t,o):Promise.resolve()}return ue(g(e)?s:j,n,t,o)},annotate:(e,t=k.Update)=>d.current.annotate(t,e),async resolution(e){if(r.signal.aborted)return null;const t=v(e),n=S(e)?ce(i,t)?.emitter??null:s;if(!n)return null;if(void 0===n.getCached(t))return null;const o=w(e),c="unknown"!==o?o[0].toLowerCase()+o.slice(1):null;if(c){const e=d.current.inspect[c];e?.pending?.()&&await new Promise((t,n)=>{if(r.signal.aborted)return void n(r.signal.reason);const o=()=>n(r.signal.reason);r.signal.addEventListener("abort",o,{once:!0}),e.settled().then(()=>{r.signal.removeEventListener("abort",o),t()})})}return n.getCached(t)??null},peek(e){if(r.signal.aborted)return null;const t=v(e),n=S(e)?ce(i,t)?.emitter??null:s;return n?n.getCached(t)??null:null}}}},[h]);c.useLayoutEffect(()=>{function t(t,n,r){return function(o,c){const i=r();if(c===ae&&e.isNotNullable(i))return;if(e.isNotNullable(c)&&c!==ae&&e.isNotNullable(i)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(c,i))return;const l={processes:/* @__PURE__ */new Set},f=Promise.withResolvers(),h=A(t,o,l);function m(e){const n=fe(E.current.handlers,"Error"),r=null!==n,o={reason:pe(e),error:(c=e,c instanceof Error?c:new Error(String(c))),action:w(t),handled:r,tasks:a};var c;s.fire(p,o),r&&n&&j.emit(n,o)}function y(){for(const e of a)if(e===h.task){a.delete(e),C.current.delete(e);break}l.processes.forEach(e=>d.current.prune(e)),l.processes.size>0&&u(),f.resolve()}let b;try{b=n(h,o)}catch(v){return m(v),void y()}if(!function(e){if(!e||"object"!=typeof e)return!1;const t=Object.prototype.toString.call(e);return"[object Generator]"===t||"[object AsyncGenerator]"===t}(b))return Promise.resolve(b).catch(m).finally(y),f.promise;(async()=>{for await(const e of b);})().catch(m).finally(y)}}x.current++;const n=/* @__PURE__ */new Set;return E.current.handlers.forEach((e,r)=>{for(const{getChannel:o,handler:c}of e){const e=t(r,c,o);if(S(r)){if(i)for(const t of i.values()){const o=t.emitter;o.on(r,e),n.add(()=>o.off(r,e))}j.on(r,e),P.multicast.add(r),n.add(()=>j.off(r,e))}else g(r)?(s.on(r,e),j.on(r,e),P.broadcast.add(r),n.add(()=>{s.off(r,e),j.off(r,e)})):(j.on(r,e),n.add(()=>j.off(r,e)))}}),()=>{const e=++x.current,t=new Set(n);queueMicrotask(()=>{if(x.current!==e){for(const e of t)e();return}for(const e of C.current)e.controller.abort(),a.delete(e);C.current.clear(),M.current=y.Unmounting;const n=fe(E.current.handlers,"Unmount");n&&j.emit(n),M.current=y.Unmounted;for(const e of t)e()})}},[j]),function({unicast:n,broadcast:r,dispatchers:o,scope:s,phase:i,data:a,handlers:u}){const l=c.useRef(null);c.useLayoutEffect(()=>{if(i.current===y.Mounted)return;i.current=y.Mounting;const t=fe(u,"Mount");t&&n.emit(t),o.broadcast.forEach(t=>{const o=r.getCached(t);e.isNullable(o)||n.emit(t,o,ae)}),s&&o.multicast.forEach(t=>{for(const r of s.values()){const o=r.emitter.getCached(t);e.isNullable(o)||n.emit(t,o,ae)}}),i.current=y.Mounted},[]),c.useLayoutEffect(()=>{if(e.isNotNullable(l.current)){const e=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(l.current,a);if(t.isNotEmpty(Object.keys(e))){const t=fe(u,"Update");t&&n.emit(t,e)}}l.current=a},[a,n])}({unicast:j,broadcast:s,dispatchers:P,scope:i,phase:M,data:o(),handlers:E.current.handlers});const _=c.useMemo(()=>[h,{dispatch(e,t){const n=v(e),r=O(e)?e.channel:void 0;if(S(e)){const e=ce(i,n);return e?ue(e.emitter,n,t,r):Promise.resolve()}return ue(g(e)?s:j,n,t,r)},get inspect(){return d.current.inspect},stream:(e,t)=>c.createElement(me,{action:v(e),renderer:t})}],[h,j]);return _.useAction=(e,t)=>{!function(e,t,n){const r=c.useRef(n);c.useLayoutEffect(()=>{r.current=n});const o=c.useRef(t);c.useLayoutEffect(()=>{o.current=t});const s=c.useCallback((e,t)=>r.current(e,t),[]),i=c.useCallback(()=>O(o.current)?o.current.channel:void 0,[]),a=v(t),u=e.current.handlers.get(a)??/* @__PURE__ */new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:i,handler:s})}(E,e,t)},_.useResource=e=>{const t=c.useMemo(()=>{const t=t=>e.run(t??{});return Object.assign(t,{if:(n,r)=>{const{data:o,at:s}=e;if(null!==s&&null!==o){const e=Temporal.Now.instant().since(s),t=Temporal.Duration.from(n.over);if(Temporal.Duration.compare(e,t)<=0)return Promise.resolve(o)}return t(r)}})},[e]);return c.useMemo(()=>Object.freeze({run:t,get data(){return e.data},get at(){return e.at}}),[e,t])},_}function be(e,t){const n=/* @__PURE__ */new Map;let r=null,o=null;return Object.freeze({key:e,run:e=>{const s=JSON.stringify(e),c=n.get(s);if(c)return c;const i=t(e).then(e=>(n.get(s)===i&&n.delete(s),r=e,o=Temporal.Now.instant(),e),e=>{throw n.get(s)===i&&n.delete(s),e});return n.set(s,i),i},get data(){return r},get at(){return o}})}function ve(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new M);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new M)},{once:!0})})}async function ge(e,t,n){if(t?.aborted)throw new M;for(;;){if(await n())return;await ve(e,t)}}function we(e){return e?Boolean(e&&"symbol"!=typeof e):/* @__PURE__ */Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const Oe=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,pk:we,poll:ge,sleep:ve,"ζ":ve,"κ":we,"π":ge},Symbol.toStringTag,{value:"Module"}));export{M as AbortError,E as Action,re as Boundary,m as Distribution,h as Lifecycle,k as Op,k as Operation,P as Reason,be as Resource,z as State,C as TimeoutError,le as With,I as annotate,ye as useActions,te as useMode,Oe as utils,ie as withScope};
@@ -0,0 +1 @@
1
+ var global,factory;global=this,factory=function(e,t,n,r,o){"use strict";function s(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const c=s(o),i=(e="")=>`march-hare.action/${e}`,a=(e="")=>`march-hare.action/broadcast/${e}`,u=(e="")=>`march-hare.action/multicast/${e}`,l=(e="")=>`march-hare.action.lifecycle/${e}`;class f{static Payload=Symbol("march-hare.brand/Payload");static Broadcast=Symbol("march-hare.brand/Broadcast");static Multicast=Symbol("march-hare.brand/Multicast");static Action=Symbol("march-hare.brand/Action");static Channel=Symbol("march-hare.brand/Channel")}function d(e){const t=Symbol(`march-hare.action.lifecycle/${e}`),n=function(e){return{[f.Action]:t,[f.Payload]:void 0,[f.Channel]:e,channel:e}};return Object.defineProperty(n,f.Action,{value:t,enumerable:!1}),Object.defineProperty(n,f.Payload,{value:void 0,enumerable:!1}),n}const p=Symbol(a("Fault"));class h{static Mount(){return d("Mount")}static Unmount(){return d("Unmount")}static Error(){return d("Error")}static Update(){return d("Update")}static Fault=(()=>{const e={};return Object.defineProperty(e,f.Action,{value:p,enumerable:!1}),Object.defineProperty(e,f.Payload,{value:void 0,enumerable:!1}),Object.defineProperty(e,f.Broadcast,{value:!0,enumerable:!1}),e})()}var m=(e=>(e.Unicast="unicast",e.Broadcast="broadcast",e.Multicast="multicast",e))(m||{}),b=(e=>(e.Mounting="mounting",e.Mounted="mounted",e.Unmounting="unmounting",e.Unmounted="unmounted",e))(b||{});const y=e=>"symbol"==typeof e;function v(e){return t.G.isString(e)||y(e)?e:(t.G.isObject(e)||t.G.isFunction(e))&&f.Action in e?e[f.Action]:e}function g(e){if(t.G.isString(e))return e.startsWith(a());if(y(e))return e.description?.startsWith(a())??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(f.Broadcast in e&&e[f.Broadcast])return!0;if(f.Action in e){const t=e[f.Action];return t.description?.startsWith(a())??!1}}return!1}function w(e){const n=v(e),r=t.G.isString(n)?n:n.description??"";return r.startsWith(i())&&r.slice(r.lastIndexOf("/")+1)||"unknown"}function j(e){return t.G.isObject(e)&&f.Channel in e&&"channel"in e}function O(e){const t=v(e),n=y(t)?t.description??"":t;return n.startsWith(l())&&n.slice(l().length)||null}function S(e){if(t.G.isString(e))return e.startsWith(u());if(y(e))return e.description?.startsWith(u())??!1;if(t.G.isObject(e)||t.G.isFunction(e)){if(f.Multicast in e&&e[f.Multicast])return!0;if(f.Action in e){const t=e[f.Action];return t.description?.startsWith(u())??!1}}return!1}var P=(e=>(e[e.Timedout=0]="Timedout",e[e.Supplanted=1]="Supplanted",e[e.Errored=2]="Errored",e))(P||{});class x extends Error{name="AbortError";constructor(e="Aborted"){super(e)}}class E extends Error{name="TimeoutError";constructor(e="Timeout"){super(e)}}let M=(e=21)=>{let t="",n=crypto.getRandomValues(new Uint8Array(e|=0));for(;e--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[63&n[e]];return t};var A=(e=>(e[e.Add=1]="Add",e[e.Remove=2]="Remove",e[e.Update=4]="Update",e[e.Move=8]="Move",e[e.Replace=16]="Replace",e[e.Sort=32]="Sort",e[e.Create=64]="Create",e[e.Fetch=128]="Fetch",e[e.Clone=256]="Clone",e[e.Archive=512]="Archive",e[e.Restore=1024]="Restore",e[e.Merge=2048]="Merge",e[e.Reorder=4096]="Reorder",e[e.Sync=8192]="Sync",e[e.Publish=16384]="Publish",e[e.Link=32768]="Link",e[e.Unlink=65536]="Unlink",e[e.Lock=131072]="Lock",e[e.Unlock=262144]="Unlock",e[e.Import=524288]="Import",e[e.Export=1048576]="Export",e[e.Transfer=2097152]="Transfer",e))(A||{}),C=(e=>(e[e.Produce=0]="Produce",e[e.Hydrate=1]="Hydrate",e))(C||{}),G=(e=>(e.Property="property",e.Process="process",e.Value="value",e.Operation="operation",e))(G||{});class k{[n.immerable]=!0;static keys=new Set(Object.values(G));property=null;process=null;value;operation;constructor(e,t){this.value=e,this.operation=t}assign(e,t){const n=new k(this.value,this.operation);return n.property=e,n.process=t,n}}class _{static immer=(()=>{n.enablePatches();const e=new n.Immer;return e.setAutoFreeze(!1),e})();static tag="κ";static id=M}function R(e,t){const n="string"==typeof t?""===t?[]:t.split("."):t;let r=e;for(const o of n){if(null==r)return;r=r[o]}return r}function N(e){if(t.G.isNullable(e)||L(e))return e;if(t.G.isArray(e))return e.map(e=>N(e));if(t.G.isObject(e)&&T(e)){const t=Object.entries(e).map(([e,t])=>[e,N(t)]);return{...Object.fromEntries(t),[_.tag]:e[_.tag]??_.id()}}return e}function U(e){if(Array.isArray(e))return e.filter(e=>_.tag in e).map(e=>e[_.tag]??"").join(",");const t=e[_.tag];if(t)return t;try{return JSON.stringify(e)}catch{return`[unserializable:${typeof e}]`}}function T(e){const t=Object.getPrototypeOf(e);return t===Object.prototype||null===t}function L(e){return t.G.isNullable(e)||t.G.isString(e)||t.G.isNumber(e)||t.G.isBoolean(e)||"symbol"==typeof e||"bigint"==typeof e}function B(e,n,r,o,s,c){return function i(a,u=n.path){if(a instanceof k){const n=R(r,u.join("."));if(Object.entries(a).filter(([e,t])=>!k.keys.has(e)&&t instanceof k).forEach(([e,t])=>i(t,u.concat(e))),L(a.value)){if(e===C.Hydrate)return a.value;const i=u.slice(0,-1),l=i.length>0?R(r,i.join(".")):r;return t.G.isNullable(l)||F(l,a,u.at(-1),o,s,c),n??a.value}if(e===C.Hydrate){const e=N(i(a.value,u));return F(e,a,null,o,s,c),e}const l=n??N(a.value);return F(l,a,null,o,s,c),t.G.isNullable(n)?l:(i(a.value,u),n)}if(t.G.isArray(a))return a.map((e,t)=>i(e,u.concat(t)));if(t.G.isObject(a)&&!T(a))return a;if(t.G.isObject(a)){const t=Object.entries(a).map(([e,t])=>[e,i(t,u.concat(e))]),n=Object.fromEntries(t);if(e===C.Hydrate){const e=N(n);return Object.entries(a).forEach(([t,n])=>{n instanceof k&&L(n.value)&&F(e,n,t,o,s,c)}),e}return n}return a}(n.value)}function F(e,t,n,r,o,s){const c=s(e),i=o.get(c)??[];o.set(c,[t.assign(n,r),...i])}class W{#e={};#t;#n=new Map;#r=new Set;#o=!1;constructor(e=U){this.#t=e}static pk(){return M()}static"κ"=W.pk;annotate(e,t){return new k(t,e)}"δ"=this.annotate;get model(){return this.#e}get inspect(){return function(e,n,r,o,s){function c(o){const s=o.at(-1),c=R(e(),o),i=o.slice(0,-1),a=t.A.isNotEmpty(i)?R(e(),i):e();return[...t.G.isObject(c)||t.G.isArray(c)?n.get(r(c))?.filter(e=>t.G.isNullable(e.property))??[]:[],...t.G.isObject(a)?n.get(r(a))?.filter(e=>e.property===s)??[]:[]]}return function n(r){return new Proxy(()=>{},{get:(i,a)=>"pending"===a?()=>!t.A.isEmpty(c(r)):"remaining"===a?()=>t.A.length(c(r)):"box"===a?()=>({value:R(e(),r),inspect:n(r)}):"is"===a?e=>c(r).some(t=>0!==(t.operation&e)):"draft"===a?()=>t.A.head(c(r))?.value??R(e(),r):"settled"===a?()=>new Promise(n=>{if(t.A.isEmpty(c(r)))return n(R(e(),r));const i=()=>{t.A.isEmpty(c(r))&&(s(i),n(R(e(),r)))};o(i)}):n([...r,String(a)])})}([])}(()=>this.#e,this.#n,this.#t,e=>this.#r.add(e),e=>this.#r.delete(e))}hydrate(e){return this.#o=!0,this.#s(C.Hydrate,()=>e)}produce(e){if(!this.#o)throw new Error("State must be hydrated using hydrate() before calling produce()");return this.#s(C.Produce,e)}#s(e,t){const n=Symbol("process"),[,r]=_.immer.produceWithPatches(this.#e,t);return this.#e=r.reduce((t,r)=>_.immer.applyPatches(t,[{...r,value:B(e,r,t,n,this.#n,this.#t)}]),this.#e),this.#e=N(this.#e),this.#c(),n}prune(e){this.#n.forEach((n,r)=>{const o=n.filter(t=>t.process!==e);t.A.isEmpty(o)?this.#n.delete(r):this.#n.set(r,o)}),this.#c()}#c(){this.#r.forEach(e=>e())}observe(e){const t=()=>e(this.#e);return this.#r.add(t),()=>this.#r.delete(t)}}const $=new W;function z(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var H,I={exports:{}},D=(H||(H=1,function(e){var t=Object.prototype.hasOwnProperty,n="~";function r(){}function o(e,t,n){this.fn=e,this.context=t,this.once=n||!1}function s(e,t,r,s,c){if("function"!=typeof r)throw new TypeError("The listener must be a function");var i=new o(r,s||e,c),a=n?n+t:t;return e._events[a]?e._events[a].fn?e._events[a]=[e._events[a],i]:e._events[a].push(i):(e._events[a]=i,e._eventsCount++),e}function c(e,t){0===--e._eventsCount?e._events=new r:delete e._events[t]}function i(){this._events=new r,this._eventsCount=0}Object.create&&(r.prototype=Object.create(null),(new r).__proto__||(n=!1)),i.prototype.eventNames=function(){var e,r,o=[];if(0===this._eventsCount)return o;for(r in e=this._events)t.call(e,r)&&o.push(n?r.slice(1):r);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(e)):o},i.prototype.listeners=function(e){var t=this._events[n?n+e:e];if(!t)return[];if(t.fn)return[t.fn];for(var r=0,o=t.length,s=new Array(o);r<o;r++)s[r]=t[r].fn;return s},i.prototype.listenerCount=function(e){var t=this._events[n?n+e:e];return t?t.fn?1:t.length:0},i.prototype.emit=function(e,t,r,o,s,c){var i=n?n+e:e;if(!this._events[i])return!1;var a,u,l=this._events[i],f=arguments.length;if(l.fn){switch(l.once&&this.removeListener(e,l.fn,void 0,!0),f){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,t),!0;case 3:return l.fn.call(l.context,t,r),!0;case 4:return l.fn.call(l.context,t,r,o),!0;case 5:return l.fn.call(l.context,t,r,o,s),!0;case 6:return l.fn.call(l.context,t,r,o,s,c),!0}for(u=1,a=new Array(f-1);u<f;u++)a[u-1]=arguments[u];l.fn.apply(l.context,a)}else{var d,p=l.length;for(u=0;u<p;u++)switch(l[u].once&&this.removeListener(e,l[u].fn,void 0,!0),f){case 1:l[u].fn.call(l[u].context);break;case 2:l[u].fn.call(l[u].context,t);break;case 3:l[u].fn.call(l[u].context,t,r);break;case 4:l[u].fn.call(l[u].context,t,r,o);break;default:if(!a)for(d=1,a=new Array(f-1);d<f;d++)a[d-1]=arguments[d];l[u].fn.apply(l[u].context,a)}}return!0},i.prototype.on=function(e,t,n){return s(this,e,t,n,!1)},i.prototype.once=function(e,t,n){return s(this,e,t,n,!0)},i.prototype.removeListener=function(e,t,r,o){var s=n?n+e:e;if(!this._events[s])return this;if(!t)return c(this,s),this;var i=this._events[s];if(i.fn)i.fn!==t||o&&!i.once||r&&i.context!==r||c(this,s);else{for(var a=0,u=[],l=i.length;a<l;a++)(i[a].fn!==t||o&&!i[a].once||r&&i[a].context!==r)&&u.push(i[a]);u.length?this._events[s]=1===u.length?u[0]:u:c(this,s)}return this},i.prototype.removeAllListeners=function(e){var t;return e?this._events[t=n?n+e:e]&&c(this,t):(this._events=new r,this._eventsCount=0),this},i.prototype.off=i.prototype.removeListener,i.prototype.addListener=i.prototype.on,i.prefixed=n,i.EventEmitter=i,e.exports=i}(I)),I.exports);const q=z(D);class J extends q{cache=new Map;emit(e,...t){return this.cache.set(e,t[0]),super.emit(e,...t)}setCache(e,t){this.cache.set(e,t)}getCached(e){return this.cache.get(e)}fire(e,...t){return super.emit(e,...t)}}const V=c.createContext(new J);function K(){return c.useContext(V)}function Q({children:e}){const t=c.useMemo(()=>new J,[]);return r.jsx(V.Provider,{value:t,children:e})}const X=c.createContext(new Set);function Y({children:e}){const t=c.useMemo(()=>new Set,[]);return r.jsx(X.Provider,{value:t,children:e})}const Z=c.createContext({current:null});function ee({children:e}){const t=c.useRef(null);return r.jsx(Z.Provider,{value:t,children:e})}const te=c.createContext(null);function ne(){return c.useContext(te)}function re(e,t){return e?.get(t)??null}const oe=Symbol(((e="")=>`march-hare/replay${e}`)());function se(e,t,...n){e instanceof J&&e.setCache(t,n[0]);const r=e.listeners(t);return 0===r.length?Promise.resolve():Promise.all(r.map(e=>Promise.resolve(e(...n)))).then(()=>{})}function ce(e,t){for(const n of e.keys())if(O(n)===t)return n;return null}function ie(){const[,e]=c.useReducer(e=>e+1,0);return e}function ae(e){if(e instanceof Error){if("TimeoutError"===e.name)return P.Timedout;if("AbortError"===e.name)return P.Supplanted}return P.Errored}const ue=c.createContext(new Map);function le({action:e,renderer:n}){const r=K(),o=c.useContext(ue),s=ie(),i=c.useMemo(()=>{const t=o.get(e);if(t)return t;const n={state:new W,listeners:new Set};return o.set(e,n),n},[e,o]);c.useLayoutEffect(()=>{function t(e){i.state.hydrate({value:e}),i.listeners.forEach(e=>e())}return i.listeners.add(s),r.on(e,t),()=>{i.listeners.delete(s),r.off(e,t)}},[e,r,i]);const a=i.state.model?.value;return t.G.isNullable(a)?null:n(a,i.state.inspect.value)}function fe(e,t){return new Promise((n,r)=>{if(t?.aborted)return void r(new x);const o=setTimeout(n,e);t?.addEventListener("abort",()=>{clearTimeout(o),r(new x)},{once:!0})})}async function de(e,t,n){if(t?.aborted)throw new x;for(;;){if(await n())return;await fe(e,t)}}function pe(e){return e?Boolean(e&&"symbol"!=typeof e):Symbol(`pk.${Date.now()}.${crypto.randomUUID()}`)}const he=Object.freeze(Object.defineProperty({__proto__:null,pk:pe,poll:de,sleep:fe,"ζ":fe,"κ":pe,"π":de},Symbol.toStringTag,{value:"Module"}));e.AbortError=x,e.Action=(e,t=m.Unicast)=>{const n=t===m.Broadcast?Symbol(a(e)):t===m.Multicast?Symbol(u(e)):Symbol(i(e)),r=function(e){return{[f.Action]:n,[f.Payload]:void 0,[f.Channel]:e,channel:e}};return Object.defineProperty(r,f.Action,{value:n,enumerable:!1}),Object.defineProperty(r,f.Payload,{value:void 0,enumerable:!1}),t===m.Broadcast&&Object.defineProperty(r,f.Broadcast,{value:!0,enumerable:!1}),t===m.Multicast&&Object.defineProperty(r,f.Multicast,{value:!0,enumerable:!1}),r},e.Boundary=function({children:e}){return r.jsx(Q,{children:r.jsx(ee,{children:r.jsx(Y,{children:e})})})},e.Distribution=m,e.Lifecycle=h,e.Op=A,e.Operation=A,e.Reason=P,e.Resource=function(e,t){const n=new Map;let r=null,o=null;return Object.freeze({key:e,run:e=>{const s=JSON.stringify(e),c=n.get(s);if(c)return c;const i=t(e).then(e=>(n.get(s)===i&&n.delete(s),r=e,o=Temporal.Now.instant(),e),e=>{throw n.get(s)===i&&n.delete(s),e});return n.set(s,i),i},get data(){return r},get at(){return o}})},e.State=W,e.TimeoutError=E,e.With={Update:e=>(t,n)=>{t.actions.produce(t=>{t.model[e]=n})},Invert:e=>t=>{t.actions.produce(t=>{t.model[e]=!t.model[e]})}},e.annotate=function(e,t=A.Update){return $.annotate(t,e)},e.useActions=function(...e){const n=t.G.isUndefined(e[0])||t.G.isFunction(e[0])?{}:e[0],r=t.G.isFunction(e[0])?e[0]:e[1]??(()=>({})),o=K(),s=ne(),i=c.useContext(X),a=ie(),u=c.useRef(!1),l=c.useRef(null),f=c.useRef(new W);u.current||(u.current=!0,l.current=f.current.hydrate(n));const[d,h]=c.useState(()=>f.current.model),m=function(e){const t=c.useRef(e);return c.useLayoutEffect(()=>{t.current=e},[e]),c.useMemo(()=>{return n=t,Object.keys(e).reduce((e,t)=>(Object.defineProperty(e,t,{get:()=>n.current[t],enumerable:!0}),e),{});var n},[e])}(r()),y=c.useMemo(()=>new q,[]),O=c.useRef({handlers:new Map});O.current.handlers=new Map;const P=function(){const e=c.useRef(new Set),t=c.useRef(new Set);return c.useMemo(()=>({broadcast:e.current,multicast:t.current}),[])}(),x=c.useRef(b.Mounting),E=c.useRef(new Set),M=c.useRef(0),C=c.useCallback((e,t,n)=>{const r=new AbortController,c={controller:r,action:e,payload:t};return i.add(c),E.current.add(c),{model:f.current.model,get phase(){return x.current},task:c,data:m,tasks:i,actions:{produce(e){if(r.signal.aborted)return;const t=f.current.produce(t=>{e({model:t,inspect:f.current.inspect})});h(f.current.model),n.processes.add(t),l.current&&(n.processes.add(l.current),l.current=null)},dispatch(e,t){if(r.signal.aborted)return Promise.resolve();const n=v(e),c=j(e)?e.channel:void 0;if(S(e)){const e=re(s,n);return e?se(e.emitter,n,t,c):Promise.resolve()}return se(g(e)?o:y,n,t,c)},annotate:(e,t=A.Update)=>f.current.annotate(t,e),async resolution(e){if(r.signal.aborted)return null;const t=v(e),n=S(e)?re(s,t)?.emitter??null:o;if(!n)return null;if(void 0===n.getCached(t))return null;const c=w(e),i="unknown"!==c?c[0].toLowerCase()+c.slice(1):null;if(i){const e=f.current.inspect[i];e?.pending?.()&&await new Promise((t,n)=>{if(r.signal.aborted)return void n(r.signal.reason);const o=()=>n(r.signal.reason);r.signal.addEventListener("abort",o,{once:!0}),e.settled().then(()=>{r.signal.removeEventListener("abort",o),t()})})}return n.getCached(t)??null},peek(e){if(r.signal.aborted)return null;const t=v(e),n=S(e)?re(s,t)?.emitter??null:o;return n?n.getCached(t)??null:null}}}},[d]);c.useLayoutEffect(()=>{function e(e,n,r){return function(s,c){const u=r();if(c===oe&&t.G.isNotNullable(u))return;if(t.G.isNotNullable(c)&&c!==oe&&t.G.isNotNullable(u)&&!function(e,t){for(const n of Object.keys(e))if(t[n]!==e[n])return!1;return!0}(c,u))return;const l={processes:new Set},d=Promise.withResolvers(),h=C(e,s,l);function m(t){const n=ce(O.current.handlers,"Error"),r=null!==n,s={reason:ae(t),error:(c=t,c instanceof Error?c:new Error(String(c))),action:w(e),handled:r,tasks:i};var c;o.fire(p,s),r&&n&&y.emit(n,s)}function b(){for(const e of i)if(e===h.task){i.delete(e),E.current.delete(e);break}l.processes.forEach(e=>f.current.prune(e)),l.processes.size>0&&a(),d.resolve()}let v;try{v=n(h,s)}catch(g){return m(g),void b()}if(!function(e){if(!e||"object"!=typeof e)return!1;const t=Object.prototype.toString.call(e);return"[object Generator]"===t||"[object AsyncGenerator]"===t}(v))return Promise.resolve(v).catch(m).finally(b),d.promise;(async()=>{for await(const e of v);})().catch(m).finally(b)}}M.current++;const n=new Set;return O.current.handlers.forEach((t,r)=>{for(const{getChannel:c,handler:i}of t){const t=e(r,i,c);if(S(r)){if(s)for(const e of s.values()){const o=e.emitter;o.on(r,t),n.add(()=>o.off(r,t))}y.on(r,t),P.multicast.add(r),n.add(()=>y.off(r,t))}else g(r)?(o.on(r,t),y.on(r,t),P.broadcast.add(r),n.add(()=>{o.off(r,t),y.off(r,t)})):(y.on(r,t),n.add(()=>y.off(r,t)))}}),()=>{const e=++M.current,t=new Set(n);queueMicrotask(()=>{if(M.current!==e){for(const e of t)e();return}for(const e of E.current)e.controller.abort(),i.delete(e);E.current.clear(),x.current=b.Unmounting;const n=ce(O.current.handlers,"Unmount");n&&y.emit(n),x.current=b.Unmounted;for(const e of t)e()})}},[y]),function({unicast:e,broadcast:n,dispatchers:r,scope:o,phase:s,data:i,handlers:a}){const u=c.useRef(null);c.useLayoutEffect(()=>{if(s.current===b.Mounted)return;s.current=b.Mounting;const c=ce(a,"Mount");c&&e.emit(c),r.broadcast.forEach(r=>{const o=n.getCached(r);t.G.isNullable(o)||e.emit(r,o,oe)}),o&&r.multicast.forEach(n=>{for(const r of o.values()){const o=r.emitter.getCached(n);t.G.isNullable(o)||e.emit(n,o,oe)}}),s.current=b.Mounted},[]),c.useLayoutEffect(()=>{if(t.G.isNotNullable(u.current)){const n=function(e,t){return Object.keys(t).reduce((n,r)=>e[r]!==t[r]?{...n,[r]:t[r]}:n,{})}(u.current,i);if(t.A.isNotEmpty(Object.keys(n))){const t=ce(a,"Update");t&&e.emit(t,n)}}u.current=i},[i,e])}({unicast:y,broadcast:o,dispatchers:P,scope:s,phase:x,data:r(),handlers:O.current.handlers});const G=c.useMemo(()=>[d,{dispatch(e,t){const n=v(e),r=j(e)?e.channel:void 0;if(S(e)){const e=re(s,n);return e?se(e.emitter,n,t,r):Promise.resolve()}return se(g(e)?o:y,n,t,r)},get inspect(){return f.current.inspect},stream:(e,t)=>c.createElement(le,{action:v(e),renderer:t})}],[d,y]);return G.useAction=(e,t)=>{!function(e,t,n){const r=c.useRef(n);c.useLayoutEffect(()=>{r.current=n});const o=c.useRef(t);c.useLayoutEffect(()=>{o.current=t});const s=c.useCallback((e,t)=>r.current(e,t),[]),i=c.useCallback(()=>j(o.current)?o.current.channel:void 0,[]),a=v(t),u=e.current.handlers.get(a)??new Set;0===u.size&&e.current.handlers.set(a,u),u.add({getChannel:i,handler:s})}(O,e,t)},G.useResource=e=>{const t=c.useMemo(()=>{const t=t=>e.run(t??{});return Object.assign(t,{if:(n,r)=>{const{data:o,at:s}=e;if(null!==s&&null!==o){const e=Temporal.Now.instant().since(s),t=Temporal.Duration.from(n.over);if(Temporal.Duration.compare(e,t)<=0)return Promise.resolve(o)}return t(r)}})},[e]);return c.useMemo(()=>Object.freeze({run:t,get data(){return e.data},get at(){return e.at}}),[e,t])},G},e.useMode=function(){const e=c.useContext(Z);return c.useMemo(()=>({read:()=>e.current,update(t){e.current=t}}),[e])},e.utils=he,e.withScope=function(e,t){const n=`Scoped${t.displayName||t.name||"Component"}`,o=v(e);return{[n](e){const n=ne(),s=c.useMemo(()=>({action:o,emitter:new J}),[]),i=c.useMemo(()=>{const e=new Map(n??[]);return e.set(o,s),e},[n,s]);return r.jsx(te.Provider,{value:i,children:r.jsx(t,{...e})})}}[n]},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports,require("@mobily/ts-belt"),require("immer"),require("react/jsx-runtime"),require("react")):"function"==typeof define&&define.amd?define(["exports","@mobily/ts-belt","immer","react/jsx-runtime","react"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).MarchHare={},global.TsBelt,global.Immer,global.jsxRuntime,global.React);
@@ -0,0 +1,66 @@
1
+ import { HandlerPayload, BroadcastPayload, MulticastPayload, Distribution, Filter } from '../types/index.ts';
2
+ export { getActionSymbol, getLifecycleType, isBroadcastAction, isMulticastAction, getName, isChanneledAction, } from './utils.ts';
3
+ /**
4
+ * Interface for the Action factory function.
5
+ */
6
+ type ActionFactory = {
7
+ /**
8
+ * Creates a new unicast action with the given name.
9
+ * @template P The payload type for the action.
10
+ * @template C The channel type for channeled dispatches (defaults to never).
11
+ * @param name The action name, used for debugging purposes.
12
+ * @returns A typed action object.
13
+ */
14
+ <P = never, C extends Filter = never>(name: string): HandlerPayload<P, C>;
15
+ /**
16
+ * Creates a new action with the specified distribution mode.
17
+ * @template P The payload type for the action.
18
+ * @template C The channel type for channeled dispatches (defaults to never).
19
+ * @param name The action name, used for debugging purposes.
20
+ * @param distribution The distribution mode (Unicast, Broadcast, or Multicast).
21
+ * @returns A typed action object (BroadcastPayload if Broadcast, MulticastPayload if Multicast).
22
+ */
23
+ <P = never, C extends Filter = never>(name: string, distribution: Distribution.Broadcast): BroadcastPayload<P, C>;
24
+ <P = never, C extends Filter = never>(name: string, distribution: Distribution.Multicast): MulticastPayload<P, C>;
25
+ <P = never, C extends Filter = never>(name: string, distribution: Distribution.Unicast): HandlerPayload<P, C>;
26
+ <P = never, C extends Filter = never>(name: string, distribution: Distribution): HandlerPayload<P, C> | BroadcastPayload<P, C> | MulticastPayload<P, C>;
27
+ };
28
+ /**
29
+ * Creates a new action with a given payload type, optional channel type, and optional distribution mode.
30
+ *
31
+ * Actions are strongly typed identifiers used to dispatch and handle state changes.
32
+ * By default, actions use `Distribution.Unicast` (local to the defining component).
33
+ * Use `Distribution.Broadcast` for actions that need to be shared across components.
34
+ *
35
+ * When a channel type is specified, the action becomes callable to create channeled dispatches:
36
+ * - `Action({ UserId: 5 })` creates a channeled action targeting that specific channel
37
+ * - Plain `Action` (uncalled) broadcasts to all handlers
38
+ *
39
+ * @template P The type of the payload that the action will carry.
40
+ * @template C The type of the channel for channeled dispatches (defaults to never).
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * export class Actions {
45
+ * // Unicast action with no payload
46
+ * static Reset = Action("Reset");
47
+ *
48
+ * // Unicast action with typed payload
49
+ * static Increment = Action<number>("Increment");
50
+ *
51
+ * // Action with channel support for targeted dispatches
52
+ * static UserUpdated = Action<User, { UserId: number }>("UserUpdated");
53
+ *
54
+ * // Broadcast action - can be read across components
55
+ * static Counter = Action<number>("Counter", Distribution.Broadcast);
56
+ * }
57
+ *
58
+ * // Usage
59
+ * actions.dispatch(Actions.Reset);
60
+ * actions.dispatch(Actions.Increment, 5);
61
+ * actions.dispatch(Actions.UserUpdated, user); // broadcast to all
62
+ * actions.dispatch(Actions.UserUpdated({ UserId: 5 }), user); // channeled dispatch
63
+ * actions.stream(Actions.Counter, (box) => box.value);
64
+ * ```
65
+ */
66
+ export declare const Action: ActionFactory;