foldkit 0.162.0 → 0.163.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 (72) hide show
  1. package/README.md +4 -4
  2. package/dist/asyncData/asyncData.d.ts +1 -1
  3. package/dist/asyncData/asyncData.js +1 -1
  4. package/dist/devTools/store.d.ts.map +1 -1
  5. package/dist/devTools/store.js +16 -16
  6. package/dist/experimental/machine/machine.d.ts +4 -4
  7. package/dist/experimental/machine/machine.js +3 -3
  8. package/dist/experimental/server/server.d.ts +9 -6
  9. package/dist/experimental/server/server.d.ts.map +1 -1
  10. package/dist/experimental/server/server.js +3 -28
  11. package/dist/html/index.d.ts +31 -20
  12. package/dist/html/index.d.ts.map +1 -1
  13. package/dist/html/index.js +1 -1
  14. package/dist/runtime/deepFreeze.d.ts +1 -1
  15. package/dist/runtime/deepFreeze.js +1 -1
  16. package/dist/runtime/documentMetadata.d.ts.map +1 -1
  17. package/dist/runtime/documentMetadata.js +69 -47
  18. package/dist/runtime/managedResourceFibers.d.ts +1 -1
  19. package/dist/runtime/managedResourceFibers.d.ts.map +1 -1
  20. package/dist/runtime/managedResourceFibers.js +3 -2
  21. package/dist/runtime/subscriptionFibers.d.ts +1 -1
  22. package/dist/runtime/subscriptionFibers.d.ts.map +1 -1
  23. package/dist/runtime/subscriptionFibers.js +3 -2
  24. package/dist/struct/index.d.ts +4 -4
  25. package/dist/struct/index.d.ts.map +1 -1
  26. package/dist/struct/index.js +4 -4
  27. package/dist/struct/public.d.ts +1 -1
  28. package/dist/struct/public.d.ts.map +1 -1
  29. package/dist/struct/public.js +1 -1
  30. package/dist/submodel/submodel.d.ts +3 -3
  31. package/dist/subscription/fromEvent.d.ts +47 -33
  32. package/dist/subscription/fromEvent.d.ts.map +1 -1
  33. package/dist/subscription/fromEvent.js +30 -25
  34. package/dist/subscription/keyBindings.d.ts +13 -11
  35. package/dist/subscription/keyBindings.d.ts.map +1 -1
  36. package/dist/subscription/keyBindings.js +9 -7
  37. package/dist/subscription/public.d.ts +1 -1
  38. package/dist/subscription/public.d.ts.map +1 -1
  39. package/dist/test/apps/bubbling.js +5 -5
  40. package/dist/test/apps/colorPicker.js +2 -2
  41. package/dist/test/apps/contentEditableEditor.js +3 -3
  42. package/dist/test/apps/contextMenu.js +2 -2
  43. package/dist/test/apps/counter.d.ts.map +1 -1
  44. package/dist/test/apps/counter.js +8 -5
  45. package/dist/test/apps/crashOnRender.js +3 -3
  46. package/dist/test/apps/drafts.js +3 -3
  47. package/dist/test/apps/feedSocket.js +5 -5
  48. package/dist/test/apps/fileUpload.js +2 -2
  49. package/dist/test/apps/focusBoundary.js +3 -3
  50. package/dist/test/apps/formChild.js +4 -4
  51. package/dist/test/apps/interactions.js +7 -7
  52. package/dist/test/apps/keypress.js +3 -3
  53. package/dist/test/apps/keypressSelf.js +2 -2
  54. package/dist/test/apps/login.js +7 -7
  55. package/dist/test/apps/mountPanel.js +4 -4
  56. package/dist/test/apps/multiRole.js +2 -2
  57. package/dist/test/apps/pointer.d.ts +5 -1
  58. package/dist/test/apps/pointer.d.ts.map +1 -1
  59. package/dist/test/apps/pointer.js +16 -7
  60. package/dist/test/apps/resumeUpload.js +5 -5
  61. package/dist/test/apps/scorePanel.js +2 -2
  62. package/dist/test/apps/selectiveKeys.d.ts.map +1 -1
  63. package/dist/test/apps/selectiveKeys.js +5 -3
  64. package/dist/test/apps/uploads.d.ts.map +1 -1
  65. package/dist/test/apps/uploads.js +13 -7
  66. package/dist/test/query.js +5 -5
  67. package/dist/test/scene.d.ts +6 -2
  68. package/dist/test/scene.d.ts.map +1 -1
  69. package/dist/test/scene.js +27 -3
  70. package/dist/update/update.d.ts +4 -4
  71. package/dist/update/update.js +3 -3
  72. package/package.json +6 -6
@@ -1,4 +1,4 @@
1
- import { Effect, Option, Record, Ref, Schema, Stream, pipe, } from 'effect';
1
+ import { Effect, Option, PubSub, Record, Ref, Schema, Scope, Stream, pipe, } from 'effect';
2
2
  import { measureSlowPhase, reportSlowPhase, } from './slowPhase.js';
3
3
  /**
4
4
  * Forks one fiber per Subscription into the runtime scope. Each fiber
@@ -18,7 +18,8 @@ export const forkSubscriptionFibers = ({ subscriptions, initModel, modelPubSub,
18
18
  thresholdMs,
19
19
  }));
20
20
  const latestDependenciesRef = yield* Ref.make(initDependencies);
21
- const modelChangesStream = Stream.fromPubSub(modelPubSub).pipe(
21
+ const modelSubscription = yield* PubSub.subscribe(modelPubSub).pipe(Effect.provideService(Scope.Scope, runtimeScope));
22
+ const modelChangesStream = Stream.fromSubscription(modelSubscription).pipe(
22
23
  // NOTE: Ref.set runs upstream of Stream.changesWith on
23
24
  // every model change, so readDependencies() returns
24
25
  // current values even when the equivalence filter
@@ -7,12 +7,12 @@ type StrictKeys<O, T> = T extends Record<string, any> ? Exclude<keyof T, keyof O
7
7
  type Evolved<O, T> = {
8
8
  [K in keyof O]: K extends keyof T ? T[K] extends (a: any) => infer R ? R : O[K] : O[K];
9
9
  };
10
- /** Immutably updates fields of a struct by applying transform functions. Wraps Effect's `Struct.evolve` with stricter key checking. */
11
- export declare const evo: {
10
+ /** Immutably modifies fields of a struct by applying transform functions. Each transformer must return its field's existing type. Wraps Effect's `Struct.evolve` with stricter key checking. */
11
+ export declare const modifyFields: {
12
12
  <O, const T extends EvolveTransform<O>>(t: StrictKeys<O, T>): (obj: O) => Evolved<O, T>;
13
13
  <O, const T extends EvolveTransform<O>>(obj: O, t: StrictKeys<O, T>): Evolved<O, T>;
14
14
  };
15
- /** Creates a variant of `evo` whose transforms are checked against a supertype. Useful in generic contexts where `evo`'s `StrictKeys` can't resolve `keyof` on an open type parameter. The returned function evolves a subtype model, preserving all fields not in the transform, and returns the subtype. */
16
- export declare const makeConstrainedEvo: <Constraint extends Record<string, unknown>>() => <Model extends Constraint>(model: Model, transforms: EvolveTransform<Constraint>) => Model;
15
+ /** Creates a field modifier for a base shape. Use in generic helpers whose Model extends that shape. Transformers are checked against the base shape, and the returned function preserves the Model's subtype and all fields not in the transform. */
16
+ export declare const makeModifyFieldsFor: <Base extends Record<string, unknown>>() => <Model extends Base>(model: Model, transforms: EvolveTransform<Base>) => Model;
17
17
  export {};
18
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/struct/index.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,CAAC,CAAC,IAAI,OAAO,CAAC;KAC/B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CAClC,CAAC,CAAA;AAEF,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAClB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,SAAS,KAAK,GACrC,CAAC,GACD,CAAC,GAAG;KACD,CAAC,IAAI,gBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK;CACnE,GACH,KAAK,CAAA;AAEX,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI;KAClB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAC7B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,KAAK,MAAM,CAAC,GAC9B,CAAC,GACD,CAAC,CAAC,CAAC,CAAC,GACN,CAAC,CAAC,CAAC,CAAC;CACT,CAAA;AAED,uIAAuI;AACvI,eAAO,MAAM,GAAG,EAAE;IAChB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,EACpC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAClB,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5B,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,EACpC,GAAG,EAAE,CAAC,EACN,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CACD,CAAA;AAEjB,8SAA8S;AAC9S,eAAO,MAAM,kBAAkB,GAC5B,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAC1C,KAAK,SAAS,UAAU,SAChB,KAAK,cACA,eAAe,CAAC,UAAU,CAAC,KACtC,KAE+C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/struct/index.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,CAAC,CAAC,IAAI,OAAO,CAAC;KAC/B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CAClC,CAAC,CAAA;AAEF,KAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAClB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,SAAS,KAAK,GACrC,CAAC,GACD,CAAC,GAAG;KACD,CAAC,IAAI,gBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,KAAK;CACnE,GACH,KAAK,CAAA;AAEX,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI;KAClB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,GAC7B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,KAAK,MAAM,CAAC,GAC9B,CAAC,GACD,CAAC,CAAC,CAAC,CAAC,GACN,CAAC,CAAC,CAAC,CAAC;CACT,CAAA;AAED,gMAAgM;AAChM,eAAO,MAAM,YAAY,EAAE;IACzB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,EACpC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAClB,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5B,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,EACpC,GAAG,EAAE,CAAC,EACN,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CACD,CAAA;AAEjB,sPAAsP;AACtP,eAAO,MAAM,mBAAmB,GAC7B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QACpC,KAAK,SAAS,IAAI,SACV,KAAK,cACA,eAAe,CAAC,IAAI,CAAC,KAChC,KAE+C,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { Struct } from 'effect';
2
- /** Immutably updates fields of a struct by applying transform functions. Wraps Effect's `Struct.evolve` with stricter key checking. */
3
- export const evo = Struct.evolve;
4
- /** Creates a variant of `evo` whose transforms are checked against a supertype. Useful in generic contexts where `evo`'s `StrictKeys` can't resolve `keyof` on an open type parameter. The returned function evolves a subtype model, preserving all fields not in the transform, and returns the subtype. */
5
- export const makeConstrainedEvo = () => (model, transforms) =>
2
+ /** Immutably modifies fields of a struct by applying transform functions. Each transformer must return its field's existing type. Wraps Effect's `Struct.evolve` with stricter key checking. */
3
+ export const modifyFields = Struct.evolve;
4
+ /** Creates a field modifier for a base shape. Use in generic helpers whose Model extends that shape. Transformers are checked against the base shape, and the returned function preserves the Model's subtype and all fields not in the transform. */
5
+ export const makeModifyFieldsFor = () => (model, transforms) =>
6
6
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
7
7
  Struct.evolve(model, transforms);
@@ -1,2 +1,2 @@
1
- export { evo, makeConstrainedEvo } from './index.js';
1
+ export { modifyFields, makeModifyFieldsFor } from './index.js';
2
2
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/struct/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/struct/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { evo, makeConstrainedEvo } from './index.js';
1
+ export { modifyFields, makeModifyFieldsFor } from './index.js';
@@ -9,13 +9,13 @@
9
9
  *
10
10
  * Being dual, it reads two ways. Data-first sets the field and returns the
11
11
  * model; data-last returns `(model) => model`, which slots point-free into
12
- * an `evo` callback:
12
+ * a `modifyFields` callback:
13
13
  *
14
14
  * ```ts
15
15
  * // data-first
16
16
  * const next = Slider.reflectRange(model.priceSlider, rangeFromUrl)
17
- * // data-last, point-free in evo
18
- * evo(model, { priceSlider: Slider.reflectRange(rangeFromUrl) })
17
+ * // data-last, point-free in modifyFields
18
+ * modifyFields(model, { priceSlider: Slider.reflectRange(rangeFromUrl) })
19
19
  * ```
20
20
  */
21
21
  export type Reflect<Model, Value> = {
@@ -51,10 +51,10 @@ type PreventDefaultEventListenerOptions = Omit<AddEventListenerOptions, 'passive
51
51
  * `document`.
52
52
  *
53
53
  * `type` is constrained to the event names the target declares, and
54
- * `toMessage`'s parameter is the event those two resolve to. Annotating that
54
+ * `mapEvent`'s parameter is the event those two resolve to. Annotating that
55
55
  * parameter is checked against the resolved event rather than replacing it.
56
56
  *
57
- * `toMessage(event)` transforms each dispatched event into a Message. The
57
+ * `mapEvent(event)` transforms each dispatched event into a Stream value. The
58
58
  * mapper runs synchronously in the same call stack as the browser's event
59
59
  * dispatch, so calling `event.preventDefault()` inside it takes effect,
60
60
  * unless the listener is passive. Some browsers default wheel and touch
@@ -62,11 +62,14 @@ type PreventDefaultEventListenerOptions = Omit<AddEventListenerOptions, 'passive
62
62
  * ignored. Pass `options: { passive: false }` explicitly when cancelling
63
63
  * those events, or reach for `fromEventFilterMapPreventDefault`, which does
64
64
  * so for you.
65
+ *
66
+ * The output type is inferred from the mapper; `Subscription.make` checks
67
+ * that the final Stream emits the application's Message type.
65
68
  */
66
- export type FromEventConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Message> = Readonly<{
69
+ export type FromEventConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Output> = Readonly<{
67
70
  target: Target | (() => Target);
68
71
  type: Type;
69
- toMessage: (event: EventOf<Target, Type>) => Message;
72
+ mapEvent: (event: EventOf<Target, Type>) => Output;
70
73
  options?: AddEventListenerOptions;
71
74
  }>;
72
75
  /**
@@ -79,10 +82,10 @@ export type FromEventConfig<Target extends EventTarget, Type extends EventTypeOf
79
82
  * `document`.
80
83
  *
81
84
  * `type` is constrained to the event names the target declares, and
82
- * `toMessage`'s parameter is the event those two resolve to. Annotating that
85
+ * `filterMapEvent`'s parameter is the event those two resolve to. Annotating that
83
86
  * parameter is checked against the resolved event rather than replacing it.
84
87
  *
85
- * `toMessage(event)` returns `Option.some(message)` to emit a Message for the
88
+ * `filterMapEvent(event)` returns `Option.some(value)` to emit a value for the
86
89
  * event, or `Option.none()` to ignore it. The mapper runs synchronously in the
87
90
  * same call stack as the browser's event dispatch, so calling
88
91
  * `event.preventDefault()` inside it takes effect, unless the listener is
@@ -90,11 +93,14 @@ export type FromEventConfig<Target extends EventTarget, Type extends EventTypeOf
90
93
  * to passive, where `preventDefault()` is ignored. Pass
91
94
  * `options: { passive: false }` explicitly when cancelling those events, or
92
95
  * reach for `fromEventFilterMapPreventDefault`, which does so for you.
96
+ *
97
+ * The output type is inferred from the mapper; `Subscription.make` checks
98
+ * that the final Stream emits the application's Message type.
93
99
  */
94
- export type FromEventFilterMapConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Message> = Readonly<{
100
+ export type FromEventFilterMapConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Output> = Readonly<{
95
101
  target: Target | (() => Target);
96
102
  type: Type;
97
- toMessage: (event: EventOf<Target, Type>) => Option.Option<Message>;
103
+ filterMapEvent: (event: EventOf<Target, Type>) => Option.Option<Output>;
98
104
  options?: AddEventListenerOptions;
99
105
  }>;
100
106
  /**
@@ -107,36 +113,38 @@ export type FromEventFilterMapConfig<Target extends EventTarget, Type extends Ev
107
113
  * `document`.
108
114
  *
109
115
  * `type` is constrained to the event names the target declares, and
110
- * `toMessage`'s parameter is the event those two resolve to. Annotating that
116
+ * `filterMapEvent`'s parameter is the event those two resolve to. Annotating that
111
117
  * parameter is checked against the resolved event rather than replacing it.
112
118
  *
113
- * `toMessage(event)` returns `Option.some(message)` to mark the dispatch
119
+ * `filterMapEvent(event)` returns `Option.some(value)` to mark the dispatch
114
120
  * handled, or `Option.none()` to leave the default behavior intact. For a
115
121
  * handled dispatch the helper calls `event.preventDefault()` and queues the
116
- * Message before the listener returns; the mapper itself never calls
122
+ * value before the listener returns; the mapper itself never calls
117
123
  * `preventDefault()`.
118
124
  *
119
125
  * `options.passive` defaults to `false` so `preventDefault()` keeps working
120
126
  * for the events browsers would otherwise register as passive. The config
121
127
  * rejects `passive: true`; the runtime guard also throws for unchecked
122
128
  * JavaScript inputs.
129
+ *
130
+ * The output type is inferred from the mapper; `Subscription.make` checks
131
+ * that the final Stream emits the application's Message type.
123
132
  */
124
- export type FromEventFilterMapPreventDefaultConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Message> = Readonly<{
133
+ export type FromEventFilterMapPreventDefaultConfig<Target extends EventTarget, Type extends EventTypeOf<Target>, Output> = Readonly<{
125
134
  target: Target | (() => Target);
126
135
  type: Type;
127
- toMessage: (event: EventOf<Target, Type>) => Option.Option<Message>;
136
+ filterMapEvent: (event: EventOf<Target, Type>) => Option.Option<Output>;
128
137
  options?: PreventDefaultEventListenerOptions;
129
138
  }>;
130
139
  /**
131
- * Build a Stream that emits a Message for the dispatches of a DOM event the
140
+ * Build a Stream that emits a value for the dispatches of a DOM event the
132
141
  * mapper chooses to keep, registering the listener when the Stream's scope
133
142
  * opens and removing it when the scope closes.
134
143
  *
135
- * This is the filtered variant of `fromEvent`. Its `toMessage` returns
136
- * `Option.some(message)` to emit and `Option.none()` to ignore the event, so a
144
+ * This is the filtered variant of `fromEvent`. Its `filterMapEvent` returns
145
+ * `Option.some(value)` to emit and `Option.none()` to ignore the event, so a
137
146
  * single listener can react to some dispatches while passing on the rest. A
138
- * mapper that never emits produces a `Stream<never>`, which composes wherever
139
- * a Message-producing Stream is expected.
147
+ * mapper that never emits produces a `Stream<never>`.
140
148
  *
141
149
  * Reach for this over a downstream `Stream.filterMap` whenever the decision to
142
150
  * keep an event is paired with `event.preventDefault()`. The mapper runs
@@ -164,7 +172,9 @@ export type FromEventFilterMapPreventDefaultConfig<Target extends EventTarget, T
164
172
  * `Subscription.persistent` for a listener whose lifetime spans the whole
165
173
  * Subscriptions record, or plug it into a `Subscription.make` entry's
166
174
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
167
- * Model condition.
175
+ * Model condition. The mapper's output type is inferred (even a raw Event is
176
+ * accepted here); `Subscription.make` checks the final Stream against the
177
+ * application's Message type.
168
178
  *
169
179
  * @example
170
180
  * ```typescript
@@ -178,7 +188,7 @@ export type FromEventFilterMapPreventDefaultConfig<Target extends EventTarget, T
178
188
  * Subscription.fromEventFilterMap({
179
189
  * target: window,
180
190
  * type: 'keydown',
181
- * toMessage: event =>
191
+ * filterMapEvent: event =>
182
192
  * event.key === 'Escape'
183
193
  * ? Option.some(Message.PressedEscape())
184
194
  * : Option.none(),
@@ -190,9 +200,9 @@ export type FromEventFilterMapPreventDefaultConfig<Target extends EventTarget, T
190
200
  * }))
191
201
  * ```
192
202
  */
193
- export declare const fromEventFilterMap: <Target extends EventTarget, Type extends EventTypeOf<Target>, Message>(config: FromEventFilterMapConfig<Target, Type, Message>) => Stream.Stream<Message>;
203
+ export declare const fromEventFilterMap: <Target extends EventTarget, Type extends EventTypeOf<Target>, Output>(config: FromEventFilterMapConfig<Target, Type, Output>) => Stream.Stream<Output>;
194
204
  /**
195
- * Build a Stream that emits a Message for every dispatch of a DOM event,
205
+ * Build a Stream that emits a value for every dispatch of a DOM event,
196
206
  * registering the listener when the Stream's scope opens and removing it when
197
207
  * the scope closes.
198
208
  *
@@ -212,10 +222,12 @@ export declare const fromEventFilterMap: <Target extends EventTarget, Type exten
212
222
  * `Subscription.persistent` for a listener whose lifetime spans the whole
213
223
  * Subscriptions record, or plug it into a `Subscription.make` entry's
214
224
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
215
- * Model condition.
225
+ * Model condition. The mapper's output type is inferred (even a raw Event is
226
+ * accepted here); `Subscription.make` checks the final Stream against the
227
+ * application's Message type.
216
228
  *
217
229
  * For a listener that reacts to only some events, reach for
218
- * `fromEventFilterMap`, whose mapper returns `Option<Message>`. For a
230
+ * `fromEventFilterMap`, whose mapper returns `Option<Output>`. For a
219
231
  * listener that also cancels the default action of the events it handles,
220
232
  * reach for `fromEventFilterMapPreventDefault`.
221
233
  *
@@ -231,7 +243,7 @@ export declare const fromEventFilterMap: <Target extends EventTarget, Type exten
231
243
  * Subscription.fromEvent({
232
244
  * target: window,
233
245
  * type: 'keydown',
234
- * toMessage: event => Message.PressedKey({ key: event.key }),
246
+ * mapEvent: event => Message.PressedKey({ key: event.key }),
235
247
  * }),
236
248
  * Effect.sync(() => isListening),
237
249
  * ),
@@ -240,17 +252,17 @@ export declare const fromEventFilterMap: <Target extends EventTarget, Type exten
240
252
  * }))
241
253
  * ```
242
254
  */
243
- export declare const fromEvent: <Target extends EventTarget, Type extends EventTypeOf<Target>, Message>(config: FromEventConfig<Target, Type, Message>) => Stream.Stream<Message>;
255
+ export declare const fromEvent: <Target extends EventTarget, Type extends EventTypeOf<Target>, Output>(config: FromEventConfig<Target, Type, Output>) => Stream.Stream<Output>;
244
256
  /**
245
- * Build a Stream that emits a Message for the dispatches of a DOM event the
257
+ * Build a Stream that emits a value for the dispatches of a DOM event the
246
258
  * mapper marks handled, calling `event.preventDefault()` on each of them,
247
259
  * registering the listener when the Stream's scope opens and removing it when
248
260
  * the scope closes.
249
261
  *
250
262
  * This is the cancelling variant of `fromEventFilterMap`, mirroring
251
- * `h.OnKeyDownPreventDefault` from `foldkit/html`. Its `toMessage` returns
252
- * `Option.some(message)` to mark a dispatch handled. The helper evaluates the
253
- * mapper, calls `event.preventDefault()`, and queues the Message before the
263
+ * `h.OnKeyDownPreventDefault` from `foldkit/html`. Its `filterMapEvent` returns
264
+ * `Option.some(value)` to mark a dispatch handled. The helper evaluates the
265
+ * mapper, calls `event.preventDefault()`, and queues the value before the
254
266
  * native listener returns. `Option.none()` leaves the default behavior intact.
255
267
  * The mapper never calls `preventDefault()` itself.
256
268
  *
@@ -275,7 +287,9 @@ export declare const fromEvent: <Target extends EventTarget, Type extends EventT
275
287
  * `Subscription.persistent` for a listener whose lifetime spans the whole
276
288
  * Subscriptions record, or plug it into a `Subscription.make` entry's
277
289
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
278
- * Model condition.
290
+ * Model condition. The mapper's output type is inferred (even a raw Event is
291
+ * accepted here); `Subscription.make` checks the final Stream against the
292
+ * application's Message type.
279
293
  *
280
294
  * @example
281
295
  * ```typescript
@@ -289,7 +303,7 @@ export declare const fromEvent: <Target extends EventTarget, Type extends EventT
289
303
  * Subscription.fromEventFilterMapPreventDefault({
290
304
  * target: window,
291
305
  * type: 'wheel',
292
- * toMessage: () => Option.some(Message.SuppressedWheelScroll()),
306
+ * filterMapEvent: () => Option.some(Message.SuppressedWheelScroll()),
293
307
  * }),
294
308
  * Effect.sync(() => isModalOpen),
295
309
  * ),
@@ -298,6 +312,6 @@ export declare const fromEvent: <Target extends EventTarget, Type extends EventT
298
312
  * }))
299
313
  * ```
300
314
  */
301
- export declare const fromEventFilterMapPreventDefault: <Target extends EventTarget, Type extends EventTypeOf<Target>, Message>(config: FromEventFilterMapPreventDefaultConfig<Target, Type, Message>) => Stream.Stream<Message>;
315
+ export declare const fromEventFilterMapPreventDefault: <Target extends EventTarget, Type extends EventTypeOf<Target>, Output>(config: FromEventFilterMapPreventDefaultConfig<Target, Type, Output>) => Stream.Stream<Output>;
302
316
  export {};
303
317
  //# sourceMappingURL=fromEvent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fromEvent.d.ts","sourceRoot":"","sources":["../../src/subscription/fromEvent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fromEvent.d.ts","sourceRoot":"","sources":["../../src/subscription/fromEvent.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,9 @@ const listen = (config) => Stream.callback(queue => Effect.acquireRelease(Effect
4
4
  const target = resolveTarget(config.target);
5
5
  const handleEvent = (event) => {
6
6
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
7
- const maybeMessage = config.toMessage(event);
8
- if (Option.isSome(maybeMessage)) {
9
- Queue.offerUnsafe(queue, maybeMessage.value);
7
+ const maybeOutput = config.filterMapEvent(event);
8
+ if (Option.isSome(maybeOutput)) {
9
+ Queue.offerUnsafe(queue, maybeOutput.value);
10
10
  }
11
11
  };
12
12
  target.addEventListener(config.type, handleEvent, config.options);
@@ -15,15 +15,14 @@ const listen = (config) => Stream.callback(queue => Effect.acquireRelease(Effect
15
15
  target.removeEventListener(config.type, handleEvent, config.options);
16
16
  })).pipe(Effect.flatMap(() => Effect.never)));
17
17
  /**
18
- * Build a Stream that emits a Message for the dispatches of a DOM event the
18
+ * Build a Stream that emits a value for the dispatches of a DOM event the
19
19
  * mapper chooses to keep, registering the listener when the Stream's scope
20
20
  * opens and removing it when the scope closes.
21
21
  *
22
- * This is the filtered variant of `fromEvent`. Its `toMessage` returns
23
- * `Option.some(message)` to emit and `Option.none()` to ignore the event, so a
22
+ * This is the filtered variant of `fromEvent`. Its `filterMapEvent` returns
23
+ * `Option.some(value)` to emit and `Option.none()` to ignore the event, so a
24
24
  * single listener can react to some dispatches while passing on the rest. A
25
- * mapper that never emits produces a `Stream<never>`, which composes wherever
26
- * a Message-producing Stream is expected.
25
+ * mapper that never emits produces a `Stream<never>`.
27
26
  *
28
27
  * Reach for this over a downstream `Stream.filterMap` whenever the decision to
29
28
  * keep an event is paired with `event.preventDefault()`. The mapper runs
@@ -51,7 +50,9 @@ const listen = (config) => Stream.callback(queue => Effect.acquireRelease(Effect
51
50
  * `Subscription.persistent` for a listener whose lifetime spans the whole
52
51
  * Subscriptions record, or plug it into a `Subscription.make` entry's
53
52
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
54
- * Model condition.
53
+ * Model condition. The mapper's output type is inferred (even a raw Event is
54
+ * accepted here); `Subscription.make` checks the final Stream against the
55
+ * application's Message type.
55
56
  *
56
57
  * @example
57
58
  * ```typescript
@@ -65,7 +66,7 @@ const listen = (config) => Stream.callback(queue => Effect.acquireRelease(Effect
65
66
  * Subscription.fromEventFilterMap({
66
67
  * target: window,
67
68
  * type: 'keydown',
68
- * toMessage: event =>
69
+ * filterMapEvent: event =>
69
70
  * event.key === 'Escape'
70
71
  * ? Option.some(Message.PressedEscape())
71
72
  * : Option.none(),
@@ -79,7 +80,7 @@ const listen = (config) => Stream.callback(queue => Effect.acquireRelease(Effect
79
80
  */
80
81
  export const fromEventFilterMap = (config) => listen(config);
81
82
  /**
82
- * Build a Stream that emits a Message for every dispatch of a DOM event,
83
+ * Build a Stream that emits a value for every dispatch of a DOM event,
83
84
  * registering the listener when the Stream's scope opens and removing it when
84
85
  * the scope closes.
85
86
  *
@@ -99,10 +100,12 @@ export const fromEventFilterMap = (config) => listen(config);
99
100
  * `Subscription.persistent` for a listener whose lifetime spans the whole
100
101
  * Subscriptions record, or plug it into a `Subscription.make` entry's
101
102
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
102
- * Model condition.
103
+ * Model condition. The mapper's output type is inferred (even a raw Event is
104
+ * accepted here); `Subscription.make` checks the final Stream against the
105
+ * application's Message type.
103
106
  *
104
107
  * For a listener that reacts to only some events, reach for
105
- * `fromEventFilterMap`, whose mapper returns `Option<Message>`. For a
108
+ * `fromEventFilterMap`, whose mapper returns `Option<Output>`. For a
106
109
  * listener that also cancels the default action of the events it handles,
107
110
  * reach for `fromEventFilterMapPreventDefault`.
108
111
  *
@@ -118,7 +121,7 @@ export const fromEventFilterMap = (config) => listen(config);
118
121
  * Subscription.fromEvent({
119
122
  * target: window,
120
123
  * type: 'keydown',
121
- * toMessage: event => Message.PressedKey({ key: event.key }),
124
+ * mapEvent: event => Message.PressedKey({ key: event.key }),
122
125
  * }),
123
126
  * Effect.sync(() => isListening),
124
127
  * ),
@@ -129,18 +132,18 @@ export const fromEventFilterMap = (config) => listen(config);
129
132
  */
130
133
  export const fromEvent = (config) => listen({
131
134
  ...config,
132
- toMessage: event => Option.some(config.toMessage(event)),
135
+ filterMapEvent: event => Option.some(config.mapEvent(event)),
133
136
  });
134
137
  /**
135
- * Build a Stream that emits a Message for the dispatches of a DOM event the
138
+ * Build a Stream that emits a value for the dispatches of a DOM event the
136
139
  * mapper marks handled, calling `event.preventDefault()` on each of them,
137
140
  * registering the listener when the Stream's scope opens and removing it when
138
141
  * the scope closes.
139
142
  *
140
143
  * This is the cancelling variant of `fromEventFilterMap`, mirroring
141
- * `h.OnKeyDownPreventDefault` from `foldkit/html`. Its `toMessage` returns
142
- * `Option.some(message)` to mark a dispatch handled. The helper evaluates the
143
- * mapper, calls `event.preventDefault()`, and queues the Message before the
144
+ * `h.OnKeyDownPreventDefault` from `foldkit/html`. Its `filterMapEvent` returns
145
+ * `Option.some(value)` to mark a dispatch handled. The helper evaluates the
146
+ * mapper, calls `event.preventDefault()`, and queues the value before the
144
147
  * native listener returns. `Option.none()` leaves the default behavior intact.
145
148
  * The mapper never calls `preventDefault()` itself.
146
149
  *
@@ -165,7 +168,9 @@ export const fromEvent = (config) => listen({
165
168
  * `Subscription.persistent` for a listener whose lifetime spans the whole
166
169
  * Subscriptions record, or plug it into a `Subscription.make` entry's
167
170
  * `dependenciesToStream` (typically behind `Stream.when`) to gate it on a
168
- * Model condition.
171
+ * Model condition. The mapper's output type is inferred (even a raw Event is
172
+ * accepted here); `Subscription.make` checks the final Stream against the
173
+ * application's Message type.
169
174
  *
170
175
  * @example
171
176
  * ```typescript
@@ -179,7 +184,7 @@ export const fromEvent = (config) => listen({
179
184
  * Subscription.fromEventFilterMapPreventDefault({
180
185
  * target: window,
181
186
  * type: 'wheel',
182
- * toMessage: () => Option.some(Message.SuppressedWheelScroll()),
187
+ * filterMapEvent: () => Option.some(Message.SuppressedWheelScroll()),
183
188
  * }),
184
189
  * Effect.sync(() => isModalOpen),
185
190
  * ),
@@ -204,12 +209,12 @@ export const fromEventFilterMapPreventDefault = (config) => {
204
209
  return fromEventFilterMap({
205
210
  ...config,
206
211
  options: { ...options, passive: false },
207
- toMessage: event => {
208
- const maybeMessage = config.toMessage(event);
209
- if (Option.isSome(maybeMessage)) {
212
+ filterMapEvent: event => {
213
+ const maybeOutput = config.filterMapEvent(event);
214
+ if (Option.isSome(maybeOutput)) {
210
215
  event.preventDefault();
211
216
  }
212
- return maybeMessage;
217
+ return maybeOutput;
213
218
  },
214
219
  });
215
220
  };
@@ -3,9 +3,9 @@ import { Duration, Stream } from 'effect';
3
3
  export type WhileTyping = 'Suppress' | 'Allow';
4
4
  /** A single key press or a sequence of two or more key presses. */
5
5
  export type KeySequence = string | Readonly<[string, string, ...Array<string>]>;
6
- type BindingBase<Message> = Readonly<{
6
+ type BindingBase<Output> = Readonly<{
7
7
  keys: KeySequence;
8
- toMessage: (event: KeyboardEvent) => Message;
8
+ mapEvent: (event: KeyboardEvent) => Output;
9
9
  isEnabled?: boolean;
10
10
  whileTyping?: WhileTyping;
11
11
  preventDefault?: boolean;
@@ -17,7 +17,7 @@ type BindingBase<Message> = Readonly<{
17
17
  * An array describes a sequence of at least two presses, such as
18
18
  * `['G', 'H']` or `['G', 'Shift+G']`.
19
19
  */
20
- export type KeyBinding<Message> = BindingBase<Message> & (Readonly<{
20
+ export type KeyBinding<Output> = BindingBase<Output> & (Readonly<{
21
21
  keys: string;
22
22
  whenRepeated?: 'Ignore' | 'Allow';
23
23
  }> | Readonly<{
@@ -26,14 +26,16 @@ export type KeyBinding<Message> = BindingBase<Message> & (Readonly<{
26
26
  }>);
27
27
  type ModKey = 'Control' | 'Meta';
28
28
  /** Configuration for the {@link keyBindings} Stream helper. */
29
- export type KeyBindingsConfig<Message> = Readonly<{
30
- bindings: ReadonlyArray<KeyBinding<Message>>;
29
+ export type KeyBindingsConfig<Output> = Readonly<{
30
+ bindings: ReadonlyArray<KeyBinding<Output>>;
31
31
  target?: EventTarget | (() => EventTarget);
32
32
  modKey?: ModKey;
33
33
  sequenceTimeout?: Duration.Input;
34
34
  }>;
35
35
  /**
36
- * Build a Stream that turns declarative key bindings into Messages.
36
+ * Build a Stream that maps declarative key bindings to values. The output is
37
+ * inferred from each binding's `mapEvent` callback; `Subscription.make`
38
+ * checks that the final Stream emits the application's Message type.
37
39
  *
38
40
  * A string describes one key press. Modifiers are joined with `+`:
39
41
  * `'Mod+K'`, `'Control+Shift+P'`, or `'Alt+ArrowDown'`. The supported modifiers
@@ -69,7 +71,7 @@ export type KeyBindingsConfig<Message> = Readonly<{
69
71
  * or put bindings with different parent-owned lifetimes in separate child
70
72
  * entries so `Subscription.lift` can gate them individually. If the meaning
71
73
  * of a key depends on the Model, dispatch a factual key Message and decide
72
- * what it means in update instead of reading the Model from `toMessage`.
74
+ * what it means in update instead of reading the Model from `mapEvent`.
73
75
  *
74
76
  * @example
75
77
  * ```typescript
@@ -87,16 +89,16 @@ export type KeyBindingsConfig<Message> = Readonly<{
87
89
  * keys: 'Escape',
88
90
  * isEnabled: isPaletteOpen,
89
91
  * whileTyping: 'Allow',
90
- * toMessage: () => Message.PressedEscape(),
92
+ * mapEvent: () => Message.PressedEscape(),
91
93
  * },
92
94
  * {
93
95
  * keys: 'Mod+K',
94
96
  * whileTyping: 'Allow',
95
- * toMessage: () => Message.PressedSearchShortcut(),
97
+ * mapEvent: () => Message.PressedSearchShortcut(),
96
98
  * },
97
99
  * {
98
100
  * keys: ['G', 'L'],
99
- * toMessage: () => Message.PressedListShortcut(),
101
+ * mapEvent: () => Message.PressedListShortcut(),
100
102
  * },
101
103
  * ],
102
104
  * }),
@@ -105,6 +107,6 @@ export type KeyBindingsConfig<Message> = Readonly<{
105
107
  * }))
106
108
  * ```
107
109
  */
108
- export declare const keyBindings: <Message>(config: KeyBindingsConfig<Message>) => Stream.Stream<Message>;
110
+ export declare const keyBindings: <Output>(config: KeyBindingsConfig<Output>) => Stream.Stream<Output>;
109
111
  export {};
110
112
  //# sourceMappingURL=keyBindings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyBindings.d.ts","sourceRoot":"","sources":["../../src/subscription/keyBindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAOR,MAAM,EAGP,MAAM,QAAQ,CAAA;AAEf,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAA;AAE9C,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AAE/E,KAAK,WAAW,CAAC,OAAO,IAAI,QAAQ,CAAC;IACnC,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAA;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,GACpD,CACI,QAAQ,CAAC;IACP,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAClC,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAClD,YAAY,CAAC,EAAE,KAAK,CAAA;CACrB,CAAC,CACL,CAAA;AAEH,KAAK,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AAEhC,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI,QAAQ,CAAC;IAChD,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;IAC5C,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAA;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;CACjC,CAAC,CAAA;AA2sBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,UACzB,iBAAiB,CAAC,OAAO,CAAC,KACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAuD,CAAA"}
1
+ {"version":3,"file":"keyBindings.d.ts","sourceRoot":"","sources":["../../src/subscription/keyBindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAOR,MAAM,EAGP,MAAM,QAAQ,CAAA;AAEf,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAA;AAE9C,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AAE/E,KAAK,WAAW,CAAC,MAAM,IAAI,QAAQ,CAAC;IAClC,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAA;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,CAAC,GAClD,CACI,QAAQ,CAAC;IACP,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAClC,CAAC,GACF,QAAQ,CAAC;IACP,IAAI,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAClD,YAAY,CAAC,EAAE,KAAK,CAAA;CACrB,CAAC,CACL,CAAA;AAEH,KAAK,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AAEhC,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,CAAC,MAAM,IAAI,QAAQ,CAAC;IAC/C,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3C,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAA;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAA;CACjC,CAAC,CAAA;AA2sBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,UACxB,iBAAiB,CAAC,MAAM,CAAC,KAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAuD,CAAA"}
@@ -109,7 +109,7 @@ const compileBinding = (binding) => {
109
109
  : Array.map(binding.keys, parsePress);
110
110
  return {
111
111
  presses,
112
- toMessage: binding.toMessage,
112
+ mapEvent: binding.mapEvent,
113
113
  whileTyping: binding.whileTyping ?? 'Suppress',
114
114
  preventDefault: binding.preventDefault ?? true,
115
115
  whenRepeated: binding.whenRepeated ?? 'Ignore',
@@ -237,7 +237,7 @@ const emitBindingMessage = (context, binding, event) => {
237
237
  if (binding.preventDefault) {
238
238
  event.preventDefault();
239
239
  }
240
- context.emitMessage(binding.toMessage(event));
240
+ context.emitMessage(binding.mapEvent(event));
241
241
  };
242
242
  const isMatchingOnePressBinding = (event, modKey, isEditable) => (binding) => !isSequence(binding) &&
243
243
  isAllowedWhileTyping(binding, isEditable) &&
@@ -368,7 +368,9 @@ const keyBindingStream = (config) => Stream.callback(queue => {
368
368
  return Effect.acquireRelease(Effect.sync(() => acquireKeyBindingListener(config, emitMessage)), listener => Effect.sync(() => releaseKeyBindingListener(listener)));
369
369
  });
370
370
  /**
371
- * Build a Stream that turns declarative key bindings into Messages.
371
+ * Build a Stream that maps declarative key bindings to values. The output is
372
+ * inferred from each binding's `mapEvent` callback; `Subscription.make`
373
+ * checks that the final Stream emits the application's Message type.
372
374
  *
373
375
  * A string describes one key press. Modifiers are joined with `+`:
374
376
  * `'Mod+K'`, `'Control+Shift+P'`, or `'Alt+ArrowDown'`. The supported modifiers
@@ -404,7 +406,7 @@ const keyBindingStream = (config) => Stream.callback(queue => {
404
406
  * or put bindings with different parent-owned lifetimes in separate child
405
407
  * entries so `Subscription.lift` can gate them individually. If the meaning
406
408
  * of a key depends on the Model, dispatch a factual key Message and decide
407
- * what it means in update instead of reading the Model from `toMessage`.
409
+ * what it means in update instead of reading the Model from `mapEvent`.
408
410
  *
409
411
  * @example
410
412
  * ```typescript
@@ -422,16 +424,16 @@ const keyBindingStream = (config) => Stream.callback(queue => {
422
424
  * keys: 'Escape',
423
425
  * isEnabled: isPaletteOpen,
424
426
  * whileTyping: 'Allow',
425
- * toMessage: () => Message.PressedEscape(),
427
+ * mapEvent: () => Message.PressedEscape(),
426
428
  * },
427
429
  * {
428
430
  * keys: 'Mod+K',
429
431
  * whileTyping: 'Allow',
430
- * toMessage: () => Message.PressedSearchShortcut(),
432
+ * mapEvent: () => Message.PressedSearchShortcut(),
431
433
  * },
432
434
  * {
433
435
  * keys: ['G', 'L'],
434
- * toMessage: () => Message.PressedListShortcut(),
436
+ * mapEvent: () => Message.PressedListShortcut(),
435
437
  * },
436
438
  * ],
437
439
  * }),
@@ -1,5 +1,5 @@
1
1
  export { aggregate, lift, make, persistent } from './subscription.js';
2
- export type { EntryWithoutKeepAlive, GatedDependencies, Subscription, Subscriptions, } from './subscription.js';
2
+ export type { EntryGates, EntryWithoutKeepAlive, GatedDependencies, Subscription, Subscriptions, } from './subscription.js';
3
3
  export { animationFrame } from './animationFrame.js';
4
4
  export type { AnimationFrameConfig } from './animationFrame.js';
5
5
  export { fromEvent, fromEventFilterMap, fromEventFilterMapPreventDefault, } from './fromEvent.js';