foldkit-primitives 0.8.0 → 0.10.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 (59) hide show
  1. package/README.md +32 -2
  2. package/dist/device/index.d.mts +66 -33
  3. package/dist/device/index.d.mts.map +1 -1
  4. package/dist/device/index.mjs +34 -34
  5. package/dist/device/index.mjs.map +1 -1
  6. package/dist/dom/index.d.mts +78 -18
  7. package/dist/dom/index.d.mts.map +1 -1
  8. package/dist/dom/index.mjs +56 -22
  9. package/dist/dom/index.mjs.map +1 -1
  10. package/dist/{editable-text-BbsPOATY.d.mts → editable-text-Dvm-Fuqs.d.mts} +65 -3
  11. package/dist/editable-text-Dvm-Fuqs.d.mts.map +1 -0
  12. package/dist/events/index.d.mts +52 -31
  13. package/dist/events/index.d.mts.map +1 -1
  14. package/dist/events/index.mjs +40 -28
  15. package/dist/events/index.mjs.map +1 -1
  16. package/dist/{follow-tab-stop-BDxyoUPQ.mjs → follow-tab-stop-Ci1tqAIW.mjs} +63 -61
  17. package/dist/follow-tab-stop-Ci1tqAIW.mjs.map +1 -0
  18. package/dist/{index-Cppf-lBx.d.mts → index-BC8kcar9.d.mts} +35 -16
  19. package/dist/index-BC8kcar9.d.mts.map +1 -0
  20. package/dist/index.d.mts +5 -5
  21. package/dist/index.mjs +5 -5
  22. package/dist/{input-modality-m6v7__Xs.mjs → input-modality-BXD383jg.mjs} +9 -9
  23. package/dist/input-modality-BXD383jg.mjs.map +1 -0
  24. package/dist/{input-modality-DGOhAknO.d.mts → input-modality-BY-bSrEc.d.mts} +9 -2
  25. package/dist/input-modality-BY-bSrEc.d.mts.map +1 -0
  26. package/dist/interaction/index.d.mts +118 -118
  27. package/dist/interaction/index.d.mts.map +1 -1
  28. package/dist/interaction/index.mjs +3 -3
  29. package/dist/interaction/index.mjs.map +1 -1
  30. package/dist/media/index.d.mts +24 -3
  31. package/dist/media/index.d.mts.map +1 -1
  32. package/dist/media/index.mjs +23 -13
  33. package/dist/media/index.mjs.map +1 -1
  34. package/dist/motion/index.d.mts +1 -1
  35. package/dist/motion/index.mjs +1 -2
  36. package/dist/{motion-DGGBZ0wt.mjs → motion-DmFDppRn.mjs} +20 -20
  37. package/dist/{motion-DGGBZ0wt.mjs.map → motion-DmFDppRn.mjs.map} +1 -1
  38. package/dist/net/index.d.mts +57 -19
  39. package/dist/net/index.d.mts.map +1 -1
  40. package/dist/net/index.mjs +31 -31
  41. package/dist/net/index.mjs.map +1 -1
  42. package/dist/observers/index.d.mts +25 -0
  43. package/dist/observers/index.d.mts.map +1 -1
  44. package/dist/observers/index.mjs +22 -22
  45. package/dist/observers/index.mjs.map +1 -1
  46. package/dist/state/index.d.mts +98 -44
  47. package/dist/state/index.d.mts.map +1 -1
  48. package/dist/state/index.mjs +39 -39
  49. package/dist/state/index.mjs.map +1 -1
  50. package/dist/time/index.d.mts +35 -5
  51. package/dist/time/index.d.mts.map +1 -1
  52. package/dist/time/index.mjs +20 -20
  53. package/dist/time/index.mjs.map +1 -1
  54. package/package.json +14 -14
  55. package/dist/editable-text-BbsPOATY.d.mts.map +0 -1
  56. package/dist/follow-tab-stop-BDxyoUPQ.mjs.map +0 -1
  57. package/dist/index-Cppf-lBx.d.mts.map +0 -1
  58. package/dist/input-modality-DGOhAknO.d.mts.map +0 -1
  59. package/dist/input-modality-m6v7__Xs.mjs.map +0 -1
package/README.md CHANGED
@@ -106,7 +106,7 @@ import * as Subscription from 'foldkit/subscription'
106
106
  import { keyboardEvents } from 'foldkit-primitives/events'
107
107
 
108
108
  const subscriptions = Subscription.make<GameModel, GameMessage>()(() => ({
109
- keys: Subscription.persistent(
109
+ keys: Subscription.persistentEntry(
110
110
  keyboardEvents({ preventDefault: press => press.key.startsWith('Arrow') }).pipe(
111
111
  Stream.filter(event => event._tag === 'Pressed'),
112
112
  Stream.map(({ key }) => GameMessage.PressedKey({ key })),
@@ -138,6 +138,36 @@ const copy = (model: NoteModel): Update.Return<NoteModel, NoteMessage> => ({
138
138
  })
139
139
  ```
140
140
 
141
+ ## Find one by the job
142
+
143
+ | You want to | Reach for | In |
144
+ | --- | --- | --- |
145
+ | Follow the color scheme, reduced motion or any media query | `MediaQuery`, `PrefersDark`, `PrefersReducedMotion` | [media](./media/README.md) |
146
+ | Change the layout at named widths | `Breakpoints` | [media](./media/README.md) |
147
+ | Know whether the tab is visible, the window's size, or the user idle | `Visibility`, `WindowSize`, `Idle` | [events](./events/README.md) |
148
+ | Answer keyboard shortcuts | `keyboardEvents` with `matchHotkey` | [events](./events/README.md) |
149
+ | Count ticks, or run something on an interval | `Timer`, `Interval`, `ticks` | [time](./time/README.md) |
150
+ | Wait until typing stops, or limit how often something runs | `debounce`, `Throttle` | [time](./time/README.md) |
151
+ | Say "3 minutes ago" | `formatRelativeTime` | [time](./time/README.md) |
152
+ | Page through a list | `Pagination`, `range` | [state](./state/README.md) |
153
+ | Undo and redo | `history` | [state](./state/README.md) |
154
+ | Draw only the visible rows of a long list | `Virtual` | [state](./state/README.md) |
155
+ | Animate a value, or let an element leave before it is removed | `Tween`, `Spring`, `Presence` | [motion](./motion/README.md) |
156
+ | Move with arrow keys through a toolbar, list, grid or tree | `RovingTabindex`, `ListNavigation`, `GridNavigation`, `TreeNavigation` | [interaction](./interaction/README.md) |
157
+ | Close a popup on Escape or an outside press | `DismissLayer`, `Overlay` | [interaction](./interaction/README.md) |
158
+ | Press, long-press or drag | `Press`, `LongPress`, `Move`, `PointerDrag` | [interaction](./interaction/README.md) |
159
+ | Edit text in place | `EditableText` | [interaction](./interaction/README.md) |
160
+ | Tell a screen reader what changed | `LiveAnnounce` | [interaction](./interaction/README.md) |
161
+ | Know whether the browser is online, or talk over a socket | `Online`, `websocket`, `sse` | [net](./net/README.md) |
162
+ | Talk between tabs | `broadcastMessages`, `SharedHost` | [net](./net/README.md) |
163
+ | Use the camera, the location or a permission | `mediaStream`, `Geolocation`, `permissions` | [device](./device/README.md) |
164
+ | Track one element's size or visibility | `Resize`, `Intersection`, `Bounds` | [observers](./observers/README.md) |
165
+ | Focus, mask or keep an element in view | `Autofocus`, `InputMask`, `KeepInView` | [dom](./dom/README.md) |
166
+ | Copy, share, load a script or restore scroll | `copyText`, `share`, `loadScript`, `keepScroll` | [dom](./dom/README.md) |
167
+
168
+ Working widgets built from the interaction primitives are listed under
169
+ [In the examples](./interaction/README.md#in-the-examples).
170
+
141
171
  ## The map
142
172
 
143
173
  Each subpath is one concern and one import. Its README has the full
@@ -154,7 +184,7 @@ reference: every Model shape, Message, argument, and failure rule.
154
184
  | [`device`](./device/README.md) | hardware | `Geolocation`, `mediaDevices`, `mediaStream`, `permissions`, fullscreen |
155
185
  | [`events`](./events/README.md) | raw window events | `Visibility`, `WindowSize`, `Idle`, `InputModality`, `keyboardEvents`, `pointerEvents`, `scrollEvents`, `activeElementEvents`, `matchHotkey` |
156
186
  | [`observers`](./observers/README.md) | element observers | `Resize`, `Intersection`, `Mutation`, `Bounds` |
157
- | [`dom`](./dom/README.md) | element Mounts and one-shot Commands | `Autofocus`, `InputMask`, `KeepInView`, `Measure`, `FocusScope`, `FollowTabStop`, `ScrollLock`, `HideOutside`, `copyText`, `readText`, `share`, `loadScript`, `keepScroll` |
187
+ | [`dom`](./dom/README.md) | element Mounts and one-shot Commands | `Autofocus`, `InputMask`, `KeepInView`, `Measure`, `FocusScope`, `FollowTabStop`, `ScrollLock`, `HideOutside`, `copyText`, `readText`, `share`, `loadScript`, `keepScroll`, `pointedLinks` |
158
188
 
159
189
  ## Rules every primitive keeps
160
190
 
@@ -5,12 +5,12 @@ import { Command } from "foldkit/command";
5
5
  //#region src/device/fullscreen.d.ts
6
6
  export declare const FullscreenMessage: import("foldkit/message").MessageUnion<{
7
7
  readonly Changed: {
8
- readonly active: Schema.Boolean;
8
+ active: Schema.Boolean;
9
9
  };
10
10
  readonly Entered: {};
11
11
  readonly Exited: {};
12
12
  readonly Failed: {
13
- readonly message: Schema.String;
13
+ message: Schema.String;
14
14
  };
15
15
  }>;
16
16
  export type FullscreenMessage = typeof FullscreenMessage.Type;
@@ -48,18 +48,24 @@ export declare const GeolocationModel: Schema.Struct<{
48
48
  export type GeolocationModel = typeof GeolocationModel.Type;
49
49
  export declare const GeolocationMessage: import("foldkit/message").MessageUnion<{
50
50
  readonly Located: {
51
- readonly latitude: Schema.Number;
52
- readonly longitude: Schema.Number;
53
- readonly accuracy: Schema.Number;
51
+ latitude: Schema.Number;
52
+ longitude: Schema.Number;
53
+ accuracy: Schema.Number;
54
54
  };
55
55
  readonly Denied: {};
56
56
  readonly Failed: {
57
- readonly message: Schema.String;
57
+ message: Schema.String;
58
58
  };
59
59
  }>;
60
60
  export type GeolocationMessage = typeof GeolocationMessage.Type;
61
+ /**
62
+ * Geolocation as a bundle: the device position in the Model, watched while
63
+ * placed. Permission denial is its own status (actionable UI); transient
64
+ * failures keep the last fix and note the error. No geolocation API yields
65
+ * an empty stream instead of throwing.
66
+ */
61
67
  export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
62
- readonly status: "unknown" | "denied" | "ready";
68
+ readonly status: "denied" | "ready" | "unknown";
63
69
  readonly coords: {
64
70
  readonly latitude: number;
65
71
  readonly longitude: number;
@@ -67,6 +73,8 @@ export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
67
73
  } | null;
68
74
  readonly lastError: string | null;
69
75
  }, {
76
+ readonly _tag: "Denied";
77
+ } | {
70
78
  readonly _tag: "Failed";
71
79
  readonly message: string;
72
80
  } | {
@@ -74,8 +82,6 @@ export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
74
82
  readonly latitude: number;
75
83
  readonly longitude: number;
76
84
  readonly accuracy: number;
77
- } | {
78
- readonly _tag: "Denied";
79
85
  }, never, never, never, void, {}, {}>;
80
86
  //#endregion
81
87
  //#region src/device/media-devices.d.ts
@@ -101,7 +107,7 @@ export declare const MediaDevicesMessage: import("foldkit/message").MessageUnion
101
107
  readonly Scan: {};
102
108
  readonly DevicesChanged: {};
103
109
  readonly Refreshed: {
104
- readonly devices: Schema.$Array<Schema.Struct<{
110
+ devices: Schema.$Array<Schema.Struct<{
105
111
  readonly deviceId: Schema.String;
106
112
  readonly groupId: Schema.String;
107
113
  readonly kind: Schema.Literals<readonly ["audioinput", "audiooutput", "videoinput"]>;
@@ -110,7 +116,7 @@ export declare const MediaDevicesMessage: import("foldkit/message").MessageUnion
110
116
  };
111
117
  readonly Denied: {};
112
118
  readonly Failed: {
113
- readonly message: Schema.String;
119
+ message: Schema.String;
114
120
  };
115
121
  }>;
116
122
  export type MediaDevicesMessage = typeof MediaDevicesMessage.Type;
@@ -125,12 +131,20 @@ export interface MediaDevicesHandle {
125
131
  addEventListener(type: string, listener: () => void): void;
126
132
  removeEventListener(type: string, listener: () => void): void;
127
133
  }
134
+ /**
135
+ * Media devices as a bundle factory: the enumerated device list in the
136
+ * Model, scanned on placement and re-scanned on every `devicechange`.
137
+ * Denial lands as `denied` while keeping the last list (actionable UI over
138
+ * stale data, like Geolocation's last fix); any other failure keeps the
139
+ * list and notes the error. No media-devices API yields an empty stream
140
+ * and a `Failed` scan instead of throwing.
141
+ */
128
142
  export declare const mediaDevices: <const Name extends string>(config: {
129
143
  readonly name: Name;
130
144
  /** Read lazily so tests can substitute a double, like the SSE bundle. */
131
145
  readonly create?: ((navigator: Navigator) => MediaDevicesHandle | null) | undefined;
132
146
  }) => Bundle.Bundle<Name, void, {
133
- readonly status: "unknown" | "denied" | "ready";
147
+ readonly status: "denied" | "ready" | "unknown";
134
148
  readonly devices: readonly {
135
149
  readonly deviceId: string;
136
150
  readonly groupId: string;
@@ -140,13 +154,11 @@ export declare const mediaDevices: <const Name extends string>(config: {
140
154
  readonly lastError: string | null;
141
155
  }, {
142
156
  readonly _tag: "Denied";
157
+ } | {
158
+ readonly _tag: "DevicesChanged";
143
159
  } | {
144
160
  readonly _tag: "Failed";
145
161
  readonly message: string;
146
- } | {
147
- readonly _tag: "Scan";
148
- } | {
149
- readonly _tag: "DevicesChanged";
150
162
  } | {
151
163
  readonly _tag: "Refreshed";
152
164
  readonly devices: readonly {
@@ -155,6 +167,8 @@ export declare const mediaDevices: <const Name extends string>(config: {
155
167
  readonly kind: "audioinput" | "audiooutput" | "videoinput";
156
168
  readonly label: string;
157
169
  }[];
170
+ } | {
171
+ readonly _tag: "Scan";
158
172
  }, never, never, never, void, {}, {}>;
159
173
  //#endregion
160
174
  //#region src/device/media-stream.d.ts
@@ -170,7 +184,7 @@ export declare const MediaStreamMessage: import("foldkit/message").MessageUnion<
170
184
  readonly Ended: {};
171
185
  readonly Denied: {};
172
186
  readonly Failed: {
173
- readonly message: Schema.String;
187
+ message: Schema.String;
174
188
  };
175
189
  }>;
176
190
  export type MediaStreamMessage = typeof MediaStreamMessage.Type;
@@ -182,6 +196,7 @@ export interface MediaTrackHandle {
182
196
  export interface MediaStreamHandle {
183
197
  getTracks(): ReadonlyArray<MediaTrackHandle>;
184
198
  }
199
+ /** Which tracks `mediaStream` asks `getUserMedia` for. */
185
200
  export interface MediaStreamConstraints {
186
201
  readonly audio: boolean;
187
202
  readonly video: boolean;
@@ -190,6 +205,15 @@ export interface MediaStreamConstraints {
190
205
  export declare const LiveStream: ManagedResource.ManagedResource<MediaStreamHandle, ManagedResource.ManagedResourceService<"media-stream">>;
191
206
  /** The stream service a placed camera requires. */
192
207
  export type LiveStreamService = ManagedResource.ServiceOf<typeof LiveStream>;
208
+ /**
209
+ * A camera/mic stream as a bundle factory: one live MediaStream held in a
210
+ * Managed Resource while the Model asks for it. `Started` requests,
211
+ * `Stopped` releases; denial parks at `denied` (actionable UI), any other
212
+ * acquire failure parks at `idle` with the error noted — both clear
213
+ * requirements, so a failing device never spins an acquire loop. Release
214
+ * stops every track. No media-devices API fails the acquire instead of
215
+ * throwing.
216
+ */
193
217
  export declare const mediaStream: <const Name extends string>(config: {
194
218
  readonly name: Name;
195
219
  /** Read lazily so tests can substitute a double, like the SSE bundle. */
@@ -198,7 +222,7 @@ export declare const mediaStream: <const Name extends string>(config: {
198
222
  readonly audio: boolean;
199
223
  readonly video: boolean;
200
224
  }, {
201
- readonly status: "denied" | "idle" | "requesting" | "live";
225
+ readonly status: "denied" | "idle" | "live" | "requesting";
202
226
  readonly lastError: string | null;
203
227
  }, {
204
228
  readonly _tag: "Started";
@@ -207,15 +231,15 @@ export declare const mediaStream: <const Name extends string>(config: {
207
231
  } | {
208
232
  readonly _tag: "Denied";
209
233
  } | {
210
- readonly _tag: "Live";
234
+ readonly _tag: "Ended";
211
235
  } | {
212
236
  readonly _tag: "Failed";
213
237
  readonly message: string;
214
238
  } | {
215
- readonly _tag: "Ended";
239
+ readonly _tag: "Live";
216
240
  }, never, never, never, void, {
217
241
  stream: ManagedResource.Entry<{
218
- readonly status: "denied" | "idle" | "requesting" | "live";
242
+ readonly status: "denied" | "idle" | "live" | "requesting";
219
243
  readonly lastError: string | null;
220
244
  }, {
221
245
  readonly _tag: "Started";
@@ -224,12 +248,12 @@ export declare const mediaStream: <const Name extends string>(config: {
224
248
  } | {
225
249
  readonly _tag: "Denied";
226
250
  } | {
227
- readonly _tag: "Live";
251
+ readonly _tag: "Ended";
228
252
  } | {
229
253
  readonly _tag: "Failed";
230
254
  readonly message: string;
231
255
  } | {
232
- readonly _tag: "Ended";
256
+ readonly _tag: "Live";
233
257
  }, Option.Option<{
234
258
  readonly audio: boolean;
235
259
  readonly video: boolean;
@@ -248,15 +272,15 @@ export declare const PermissionsModel: Schema.Struct<{
248
272
  export type PermissionsModel = typeof PermissionsModel.Type;
249
273
  export declare const PermissionsMessage: import("foldkit/message").MessageUnion<{
250
274
  readonly Snapshot: {
251
- readonly states: Schema.$Record<Schema.String, Schema.Literals<readonly ["granted", "denied", "prompt"]>>;
275
+ states: Schema.$Record<Schema.String, Schema.Literals<readonly ["granted", "denied", "prompt"]>>;
252
276
  };
253
277
  readonly Changed: {
254
- readonly name: Schema.String;
255
- readonly state: Schema.Literals<readonly ["granted", "denied", "prompt"]>;
278
+ name: Schema.String;
279
+ state: Schema.Literals<readonly ["granted", "denied", "prompt"]>;
256
280
  };
257
281
  readonly Cleared: {};
258
282
  readonly Failed: {
259
- readonly message: Schema.String;
283
+ message: Schema.String;
260
284
  };
261
285
  }>;
262
286
  export type PermissionsMessage = typeof PermissionsMessage.Type;
@@ -280,6 +304,14 @@ interface Acquired {
280
304
  export declare const Watch: ManagedResource.ManagedResource<Acquired, ManagedResource.ManagedResourceService<"permissions">>;
281
305
  /** The watch service a placed Permissions bundle requires. */
282
306
  export type WatchService = ManagedResource.ServiceOf<typeof Watch>;
307
+ /**
308
+ * Permission states as a bundle factory: queried on placement, kept current
309
+ * by each status object's `onchange`. A resource holds the status objects
310
+ * (they cannot live in the Model); its queue feeds the subscription, and
311
+ * release detaches every handler. An unknown permission name fails the
312
+ * acquire; an unknown state string fails it too — both become `Failed`,
313
+ * never Model facts.
314
+ */
283
315
  export declare const permissions: <const Name extends string>(config: {
284
316
  readonly name: Name;
285
317
  /** Read lazily so tests can substitute a double, like the SSE bundle. */
@@ -288,7 +320,7 @@ export declare const permissions: <const Name extends string>(config: {
288
320
  readonly names: ReadonlyArray<string>;
289
321
  }, {
290
322
  readonly states: {
291
- readonly [x: string]: "granted" | "denied" | "prompt";
323
+ readonly [x: string]: "denied" | "granted" | "prompt";
292
324
  };
293
325
  readonly lastError: string | null;
294
326
  }, {
@@ -296,17 +328,18 @@ export declare const permissions: <const Name extends string>(config: {
296
328
  } | {
297
329
  readonly _tag: "Changed";
298
330
  readonly name: string;
299
- readonly state: "granted" | "denied" | "prompt";
331
+ readonly state: "denied" | "granted" | "prompt";
332
+ } | {
333
+ readonly _tag: "Failed";
334
+ readonly message: string;
300
335
  } | {
301
336
  readonly _tag: "Snapshot";
302
337
  readonly states: {
303
- readonly [x: string]: "granted" | "denied" | "prompt";
338
+ readonly [x: string]: "denied" | "granted" | "prompt";
304
339
  };
305
- } | {
306
- readonly _tag: "Failed";
307
- readonly message: string;
308
340
  }, never, never, ManagedResource.ManagedResourceService<"permissions">, void, Readonly<{
309
341
  watch: ManagedResource.Entry<PermissionsModel, PermissionsMessage, Option.Option<ReadonlyArray<string>>, Acquired, WatchService, (acquired: Acquired) => PermissionsMessage>;
310
342
  }>, {}>;
311
343
  //#endregion
344
+ export {};
312
345
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/device/fullscreen.ts","../../src/device/geolocation.ts","../../src/device/media-devices.ts","../../src/device/media-stream.ts","../../src/device/permissions.ts"],"mappings":";;;;;qBAWa,6CAAiB;;;;;;;;;;YAMlB,2BAA2B,kBAAkB;;;;;;;qBAW5C,kBAAmB,SAAS,YAAU,QAAQ;;qBA0B9C,sBAAqB,QAAQ;;;;;qBAgC7B,yBAAwB,OAAO,OAAO;;;qBCzEtC,aAAW,OAAA;;;;;YAKZ,qBAAqB,YAAY;qBAEhC,kBAAgB,OAAA;;;;;;;;;YAKjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;;;;;;;;;;YASnB,4BAA4B,mBAAmB;qBAmD9C,aAAW,OAAA;;;;;;;;;;;;;;;;;;;;;qBCxEX,aAAW,OAAA;;;;;;YAMZ,qBAAqB,YAAY;qBAEhC,mBAAiB,OAAA;;;;;;;;;;YAKlB,2BAA2B,kBAAkB;qBAE5C,+CAAmB;;;;;;;;;;;;;;;;YAOpB,6BAA6B,oBAAoB;;iBAa5C;EACf,oBAAoB,QAClB;aACW;aACA;aACA;aACA;;EAGb,iBAAiB,cAAc;EAC/B,oBAAoB,cAAc;;qBAUvB,qBAAsB,qBAAqB;WAC7C,MAAM;;WAEN,WAAW,WAAW,cAAc;MAC9C,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBC1DY,kBAAgB,OAAA;;;;YAIjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;;;;;;sBAAlB,OAAA;;;YAQD,4BAA4B,mBAAmB;;iBAG1C;EACf;;;iBAIe;EACf,aAAa,cAAc;;iBAGZ;WACN;WACA;;;qBAIE,YAAU,gBAAA,gBAAA,mBAAA,gBAAA;;YAGX,oBAAoB,gBAAgB,iBAAiB;qBAoBpD,oBAAqB,qBAAqB;WAC5C,MAAM;;WAEN,YACL,aAAa,2BAA2B,QAAQ;MACrD,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBC5DY,iBAAe,OAAA;YAChB,yBAAyB,gBAAgB;qBAExC,kBAAgB,OAAA;;;;YAIjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;;;;;;;;;;;;YAMnB,4BAA4B,mBAAmB;;iBAG1C;WACN;EACT;;;iBAIe;EACf,MAAM;aAAuB;MAAiB,QAAQ;;UAG9C;WACC,UAAU,oBAAoB;WAC9B,UAAU,SAAS,eAAe;WAClC,QAAQ,MAAM,MAAM;;;qBAIlB,OAAK,gBAAA,gBAAA,UAAA,gBAAA;;YAGN,eAAe,gBAAgB,iBAAiB;qBAuB/C,oBAAqB,qBAAqB;WAC5C,MAAM;;WAEN,WAAW,WAAW,cAAc;MAC9C,OAAA,OAAA;WAYqB,OAAA;;;;;;;;;;;;;;;;;;;;;EApCb,OAAA,gBAAgB,MACrB,kBACA,oBACA,OAAO,OAAO,wBACd,UACA,eACC,UAAU,aAAa"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/device/fullscreen.ts","../../src/device/geolocation.ts","../../src/device/media-devices.ts","../../src/device/media-stream.ts","../../src/device/permissions.ts"],"mappings":";;;;;qBAWa,6CAAiB;;IACjB,QAAM,OAAA;;;;;IAGP,SAAO,OAAA;;;YAEP,2BAA2B,kBAAkB;;;;;;;qBAW5C,kBAAe,SAAa,YAAU,QAAQ;;qBA0B9C,sBAAqB,QAAQ;;;;;qBAgC7B,yBAAwB,OAAO,OAAO;;;qBC/EtC,aAAW,OAAA;;;;;YAKZ,qBAAqB,YAAY;qBAEhC,kBAAgB,OAAA;;;;;;;;;YAKjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;IAE3B,UAAQ,OAAA;IACR,WAAS,OAAA;IACT,UAAQ,OAAA;;;;IAGA,SAAO,OAAA;;;YAEP,4BAA4B,mBAAmB;;;;;;;qBAyD9C,aAAW,OAAA;;;;;;;;;;;;;;;;;;;;;qBChFX,aAAW,OAAA;;;;;;YAMZ,qBAAqB,YAAY;qBAEhC,mBAAiB,OAAA;;;;;;;;;;YAKlB,2BAA2B,kBAAkB;qBAE5C,+CAAmB;;;;IAGjB,SAAO,OAAA,OAAA,OAAA;;;;;;;;;IAEV,SAAO,OAAA;;;YAEP,6BAA6B,oBAAoB;;iBAa5C;EACf,oBAAoB,QAClB;aACW;aACA;aACA;aACA;;EAGb,iBAAiB,cAAc;EAC/B,oBAAoB,cAAc;;;;;;;;;;qBAkBvB,qBAAsB,qBAAmB;WAC3C,MAAM;;WAEN,WAAW,WAAW,cAAc;MAC9C,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCnEY,kBAAgB,OAAA;;;;YAIjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;;;;;;IAMnB,SAAO,OAAA;;;YAEP,4BAA4B,mBAAmB;;iBAG1C;EACf;;;iBAIe;EACf,aAAa,cAAc;;;iBAIZ;WACN;WACA;;;qBAIE,YAAU,gBAAA,gBAAA,mBAAA,gBAAA;;YAGX,oBAAoB,gBAAgB,iBAAiB;;;;;;;;;;qBA6BpD,oBAAqB,qBAAmB;WAC1C,MAAM;;WAEN,YACL,aAAa,2BAA2B,QAAQ;MACrD,OAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCrEY,iBAAe,OAAA;YAChB,yBAAyB,gBAAgB;qBAExC,kBAAgB,OAAA;;;;YAIjB,0BAA0B,iBAAiB;qBAE1C,8CAAkB;;IACjB,QAAM,OAAA,QAAA,OAAA,QAAA,OAAA;;;IACP,MAAI,OAAA;IAAiB,OAAK,OAAA;;;;IAE3B,SAAO,OAAA;;;YAEP,4BAA4B,mBAAmB;;iBAG1C;WACN;EACT;;;iBAIe;EACf,MAAM;aAAuB;MAAiB,QAAQ;;UAG9C;WACC,UAAU,oBAAoB;WAC9B,UAAU,SAAS,eAAe;WAClC,QAAQ,MAAM,MAAM;;;qBAIlB,OAAK,gBAAA,gBAAA,UAAA,gBAAA;;YAGN,eAAe,gBAAgB,iBAAiB;;;;;;;;;qBA+B/C,oBAAqB,qBAAmB;WAC1C,MAAM;;WAEN,WAAW,WAAW,cAAc;MAC9C,OAAA,OAAA;WAYqB,OAAA;;;;;;;;;;;;;;;;;;;;;EA5Cb,OAAA,gBAAgB,MACrB,kBACA,oBACA,OAAO,OAAO,wBACd,UACA,eACC,UAAU,aAAa"}
@@ -70,12 +70,6 @@ const fullscreenChanges = () => {
70
70
  };
71
71
  //#endregion
72
72
  //#region src/device/geolocation.ts
73
- /**
74
- * Geolocation as a bundle: the device position in the Model, watched while
75
- * placed. Permission denial is its own status (actionable UI); transient
76
- * failures keep the last fix and note the error. No geolocation API yields
77
- * an empty stream instead of throwing.
78
- */
79
73
  const Coordinates = Schema.Struct({
80
74
  latitude: Schema.Number,
81
75
  longitude: Schema.Number,
@@ -119,6 +113,12 @@ const watchStream = () => {
119
113
  return Stream.fromQueue(queue);
120
114
  }));
121
115
  };
116
+ /**
117
+ * Geolocation as a bundle: the device position in the Model, watched while
118
+ * placed. Permission denial is its own status (actionable UI); transient
119
+ * failures keep the last fix and note the error. No geolocation API yields
120
+ * an empty stream instead of throwing.
121
+ */
122
122
  const Geolocation = Bundle.make("Geolocation", {
123
123
  Model: GeolocationModel,
124
124
  Message: GeolocationMessage,
@@ -146,18 +146,10 @@ const Geolocation = Bundle.make("Geolocation", {
146
146
  lastError: message
147
147
  }) })
148
148
  }),
149
- subscriptions: () => Subscription.make()(() => ({ watch: Subscription.persistent(watchStream()) }))
149
+ subscriptions: () => Subscription.make()(() => ({ watch: Subscription.persistentEntry(watchStream()) }))
150
150
  });
151
151
  //#endregion
152
152
  //#region src/device/media-devices.ts
153
- /**
154
- * Media devices as a bundle factory: the enumerated device list in the
155
- * Model, scanned on placement and re-scanned on every `devicechange`.
156
- * Denial lands as `denied` while keeping the last list (actionable UI over
157
- * stale data, like Geolocation's last fix); any other failure keeps the
158
- * list and notes the error. No media-devices API yields an empty stream
159
- * and a `Failed` scan instead of throwing.
160
- */
161
153
  const MediaDevice = Schema.Struct({
162
154
  deviceId: Schema.String,
163
155
  groupId: Schema.String,
@@ -187,6 +179,14 @@ const MediaDevicesMessage = defineMessageUnion({
187
179
  const sameDevices = (a, b) => a.length === b.length && a.every((device, index) => device.deviceId === b[index].deviceId && device.groupId === b[index].groupId && device.kind === b[index].kind && device.label === b[index].label);
188
180
  const failMessage$2 = (error) => error instanceof Error ? error.message : String(error);
189
181
  const isDenied$1 = (error) => typeof error?.name === "string" && ["NotAllowedError", "SecurityError"].includes(error.name);
182
+ /**
183
+ * Media devices as a bundle factory: the enumerated device list in the
184
+ * Model, scanned on placement and re-scanned on every `devicechange`.
185
+ * Denial lands as `denied` while keeping the last list (actionable UI over
186
+ * stale data, like Geolocation's last fix); any other failure keeps the
187
+ * list and notes the error. No media-devices API yields an empty stream
188
+ * and a `Failed` scan instead of throwing.
189
+ */
190
190
  const mediaDevices = (config) => {
191
191
  const handle = () => {
192
192
  if (typeof navigator === "undefined") return null;
@@ -255,20 +255,11 @@ const mediaDevices = (config) => {
255
255
  lastError: message
256
256
  }) })
257
257
  }),
258
- subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistent(changedStream()) }))
258
+ subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistentEntry(changedStream()) }))
259
259
  });
260
260
  };
261
261
  //#endregion
262
262
  //#region src/device/media-stream.ts
263
- /**
264
- * A camera/mic stream as a bundle factory: one live MediaStream held in a
265
- * Managed Resource while the Model asks for it. `Started` requests,
266
- * `Stopped` releases; denial parks at `denied` (actionable UI), any other
267
- * acquire failure parks at `idle` with the error noted — both clear
268
- * requirements, so a failing device never spins an acquire loop. Release
269
- * stops every track. No media-devices API fails the acquire instead of
270
- * throwing.
271
- */
272
263
  const MediaStreamModel = Schema.Struct({
273
264
  status: Schema.Literals([
274
265
  "idle",
@@ -290,6 +281,15 @@ const MediaStreamMessage = defineMessageUnion({
290
281
  const LiveStream = ManagedResource.tag()("media-stream");
291
282
  const failMessage$1 = (error) => error instanceof Error ? error.message : String(error);
292
283
  const isDenied = (error) => typeof error?.name === "string" && ["NotAllowedError", "SecurityError"].includes(error.name);
284
+ /**
285
+ * A camera/mic stream as a bundle factory: one live MediaStream held in a
286
+ * Managed Resource while the Model asks for it. `Started` requests,
287
+ * `Stopped` releases; denial parks at `denied` (actionable UI), any other
288
+ * acquire failure parks at `idle` with the error noted — both clear
289
+ * requirements, so a failing device never spins an acquire loop. Release
290
+ * stops every track. No media-devices API fails the acquire instead of
291
+ * throwing.
292
+ */
293
293
  const mediaStream = (config) => {
294
294
  const request = (constraints) => {
295
295
  if (config.request !== void 0) return config.request(constraints);
@@ -359,14 +359,6 @@ const mediaStream = (config) => {
359
359
  };
360
360
  //#endregion
361
361
  //#region src/device/permissions.ts
362
- /**
363
- * Permission states as a bundle factory: queried on placement, kept current
364
- * by each status object's `onchange`. A resource holds the status objects
365
- * (they cannot live in the Model); its queue feeds the subscription, and
366
- * release detaches every handler. An unknown permission name fails the
367
- * acquire; an unknown state string fails it too — both become `Failed`,
368
- * never Model facts.
369
- */
370
362
  const PermissionState = Schema.Literals([
371
363
  "granted",
372
364
  "denied",
@@ -392,6 +384,14 @@ const readState = (state, name) => {
392
384
  if (state !== "granted" && state !== "denied" && state !== "prompt") throw new Error(`unknown permission state for ${name}: ${state}`);
393
385
  return state;
394
386
  };
387
+ /**
388
+ * Permission states as a bundle factory: queried on placement, kept current
389
+ * by each status object's `onchange`. A resource holds the status objects
390
+ * (they cannot live in the Model); its queue feeds the subscription, and
391
+ * release detaches every handler. An unknown permission name fails the
392
+ * acquire; an unknown state string fails it too — both become `Failed`,
393
+ * never Model facts.
394
+ */
395
395
  const permissions = (config) => {
396
396
  const handle = () => {
397
397
  if (typeof navigator === "undefined") return null;
@@ -486,7 +486,7 @@ const permissions = (config) => {
486
486
  }), Queue.shutdown(events)))
487
487
  }) }));
488
488
  },
489
- subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistent(Stream.unwrap(Effect.matchEffect(Watch.get, {
489
+ subscriptions: () => Subscription.make()(() => ({ changes: Subscription.persistentEntry(Stream.unwrap(Effect.matchEffect(Watch.get, {
490
490
  onFailure: () => Effect.succeed(Stream.empty),
491
491
  onSuccess: ({ events }) => Effect.succeed(Stream.fromQueue(events))
492
492
  }))) }))