foldkit-primitives 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -11
- package/dist/device/index.d.mts +9 -9
- package/dist/net/index.d.mts +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `foldkit-primitives`
|
|
2
2
|
|
|
3
|
-
Ready-made [`foldkit-bundle`](
|
|
3
|
+
Ready-made [`foldkit-bundle`](../bundle) primitives: media queries, breakpoints,
|
|
4
4
|
presence, timers, intervals, debounce, tweens, springs, pagination, history,
|
|
5
5
|
locales, selections, ranges, geolocation, cameras, permissions, sockets,
|
|
6
6
|
broadcasts, observers, and clipboard. Most are ordinary bundles — Model,
|
|
@@ -33,6 +33,15 @@ package depends on `foldkit-bundle` and nothing else (besides peers).
|
|
|
33
33
|
| One-shot actions | Command, not a bundle | clipboard copy, share, script load |
|
|
34
34
|
| Derived data | pure function, not a bundle | range, relative time, platform |
|
|
35
35
|
|
|
36
|
+
Choose by what you need to own. State that outlives the moment — a match,
|
|
37
|
+
a count, a page, a position — wants a bundle: the Model keeps it, replay
|
|
38
|
+
sees it. A stream you only react to wants an entry: map it into the
|
|
39
|
+
parent's Message and keep nothing. Work bound to one element wants a
|
|
40
|
+
Mount. Work that runs once and reports back wants a Command. A value
|
|
41
|
+
computed from data you already have wants a pure function. When in doubt,
|
|
42
|
+
start with the lighter form; promote to a bundle the day the state needs
|
|
43
|
+
a name in the Model.
|
|
44
|
+
|
|
36
45
|
A bundle holds no state and performs no I/O by itself. The parent Model owns
|
|
37
46
|
the placed slice; the browser (or server, or clock) only reports facts as
|
|
38
47
|
Messages. The same rule as everywhere else: observation is not ownership.
|
|
@@ -69,6 +78,20 @@ pnpm add foldkit-primitives foldkit-bundle effect foldkit
|
|
|
69
78
|
`foldkit-primitives/events`, `foldkit-primitives/observers`, `foldkit-primitives/dom` —
|
|
70
79
|
so bundlers drop the primitives you never import.
|
|
71
80
|
|
|
81
|
+
## Map of the package
|
|
82
|
+
|
|
83
|
+
Each subpath is one concern, one import:
|
|
84
|
+
|
|
85
|
+
- `media` — environment facts: MediaQuery (+presets), Breakpoints, platform
|
|
86
|
+
- `net` — remote facts: Online, WebSocket, SSE, BroadcastChannel
|
|
87
|
+
- `time` — clock facts: Timer, Interval, Debounce, Throttle, relative time
|
|
88
|
+
- `state` — owned UI state: Pagination, History, Locale, SelectionSet, Virtual, range
|
|
89
|
+
- `motion` — animation state: Tween, Spring, Presence
|
|
90
|
+
- `device` — hardware: Geolocation, MediaDevices, MediaStream, Permissions, Fullscreen
|
|
91
|
+
- `events` — raw browser events: Visibility, WindowSize, Idle, keyboard, pointer, scroll, focus
|
|
92
|
+
- `observers` — element Mounts: Resize, Intersection, Mutation, Bounds
|
|
93
|
+
- `dom` — element Mounts and one-shot Commands: Autofocus, InputMask, clipboard, share, script loading
|
|
94
|
+
|
|
72
95
|
## Sixty seconds: follow the color scheme
|
|
73
96
|
|
|
74
97
|
**Declare where it lives.** A declaration names the Model field and the
|
|
@@ -105,13 +128,29 @@ const config = placements.complete({
|
|
|
105
128
|
|
|
106
129
|
`update` routes `GotDarkMessage` to the bundle; `subscriptions` runs the
|
|
107
130
|
`matchMedia` stream; `initial` starts `matches` at `false` and the stream
|
|
108
|
-
corrects it on subscribe.
|
|
131
|
+
corrects it on subscribe. None of the placement calls perform I/O:
|
|
132
|
+
`declare` names a slot, `at` binds config to it, `assemble` derives the
|
|
133
|
+
folding and the streams — the browser is touched only when the runtime
|
|
134
|
+
subscribes. The Solid equivalent this replaces:
|
|
109
135
|
|
|
110
136
|
```ts
|
|
111
137
|
// solid-primitives: const dark = createMediaQuery('(prefers-color-scheme: dark)')
|
|
112
138
|
// Here the fact lives in the Model: replay, DevTools, and time travel see it.
|
|
113
139
|
```
|
|
114
140
|
|
|
141
|
+
## Composing placements
|
|
142
|
+
|
|
143
|
+
One assembly holds every placement: spread its update, init,
|
|
144
|
+
subscriptions, and resources once per application, as above. Two
|
|
145
|
+
placements of one bundle observe twice — share the field instead, so one
|
|
146
|
+
stream feeds every reader. One assembly holds one socket, stream, or
|
|
147
|
+
watch: resource tags are per module, and `assemble` refuses the second.
|
|
148
|
+
Bundles whose settled value is the whole point (`Debounce`, `Throttle`)
|
|
149
|
+
surface it as an OutMessage the placement handles with `onOut`, so the
|
|
150
|
+
signal can never be dropped by omission. Entries lift with
|
|
151
|
+
`Subscription.persistent`, mapping into the parent's Message; Mounts
|
|
152
|
+
attach in views with `h.OnMount`.
|
|
153
|
+
|
|
115
154
|
## Media: `foldkit-primitives/media`
|
|
116
155
|
|
|
117
156
|
> Reference: [`./media/README.md`](./media/README.md)
|
|
@@ -403,15 +442,6 @@ browser), restored through a `MirrorRestored` Message the application
|
|
|
403
442
|
reduces. Nothing here duplicates it — reach for the mirror when a slice
|
|
404
443
|
should survive reload, and keep this package's bundles for live facts.
|
|
405
444
|
|
|
406
|
-
## With Surface and Mirror
|
|
407
|
-
|
|
408
|
-
Placed state is ordinary Model, so the surrounding tools apply unchanged —
|
|
409
|
-
no bundle-specific Surface or Mirror API exists, by design. Declare a Surface
|
|
410
|
-
over the placed fields to render them or expose them to an agent; point
|
|
411
|
-
`Mirror.url` at them to link them; spread the bundle's cases into the same
|
|
412
|
-
unions. The field refs and wrapper Messages are the same ones the rest of the
|
|
413
|
-
application uses.
|
|
414
|
-
|
|
415
445
|
## Motion: `foldkit-primitives/motion`
|
|
416
446
|
|
|
417
447
|
> Reference: [`./motion/README.md`](./motion/README.md)
|
|
@@ -455,6 +485,15 @@ forking before the first `TestClock.adjust`, or dispatched events hit
|
|
|
455
485
|
unregistered listeners. Each ingredient is demonstrated in this package's
|
|
456
486
|
`test/` directory, named after its primitive.
|
|
457
487
|
|
|
488
|
+
## With Surface and Mirror
|
|
489
|
+
|
|
490
|
+
Placed state is ordinary Model, so the surrounding tools apply unchanged —
|
|
491
|
+
no bundle-specific Surface or Mirror API exists, by design. Declare a Surface
|
|
492
|
+
over the placed fields to render them or expose them to an agent; point
|
|
493
|
+
`Mirror.url` at them to link them; spread the bundle's cases into the same
|
|
494
|
+
unions. The field refs and wrapper Messages are the same ones the rest of the
|
|
495
|
+
application uses.
|
|
496
|
+
|
|
458
497
|
## Failure and recovery
|
|
459
498
|
|
|
460
499
|
| Failure | Behaviour |
|
package/dist/device/index.d.mts
CHANGED
|
@@ -59,7 +59,7 @@ export declare const GeolocationMessage: import("foldkit/message").MessageUnion<
|
|
|
59
59
|
}>;
|
|
60
60
|
export type GeolocationMessage = typeof GeolocationMessage.Type;
|
|
61
61
|
export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
|
|
62
|
-
readonly status: "unknown" | "
|
|
62
|
+
readonly status: "unknown" | "ready" | "denied";
|
|
63
63
|
readonly coords: {
|
|
64
64
|
readonly latitude: number;
|
|
65
65
|
readonly longitude: number;
|
|
@@ -67,6 +67,8 @@ export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
|
|
|
67
67
|
} | null;
|
|
68
68
|
readonly lastError: string | null;
|
|
69
69
|
}, {
|
|
70
|
+
readonly _tag: "Denied";
|
|
71
|
+
} | {
|
|
70
72
|
readonly _tag: "Failed";
|
|
71
73
|
readonly message: string;
|
|
72
74
|
} | {
|
|
@@ -74,8 +76,6 @@ export declare const Geolocation: Bundle.Bundle<"Geolocation", void, {
|
|
|
74
76
|
readonly latitude: number;
|
|
75
77
|
readonly longitude: number;
|
|
76
78
|
readonly accuracy: number;
|
|
77
|
-
} | {
|
|
78
|
-
readonly _tag: "Denied";
|
|
79
79
|
}, never, never, never, void, {}, {}>;
|
|
80
80
|
//#endregion
|
|
81
81
|
//#region src/device/media-devices.d.ts
|
|
@@ -130,7 +130,7 @@ export declare const mediaDevices: <const Name extends string>(config: {
|
|
|
130
130
|
/** Read lazily so tests can substitute a double, like the SSE bundle. */
|
|
131
131
|
readonly create?: ((navigator: Navigator) => MediaDevicesHandle | null) | undefined;
|
|
132
132
|
}) => Bundle.Bundle<Name, void, {
|
|
133
|
-
readonly status: "unknown" | "
|
|
133
|
+
readonly status: "unknown" | "ready" | "denied";
|
|
134
134
|
readonly devices: readonly {
|
|
135
135
|
readonly deviceId: string;
|
|
136
136
|
readonly groupId: string;
|
|
@@ -139,8 +139,6 @@ export declare const mediaDevices: <const Name extends string>(config: {
|
|
|
139
139
|
}[];
|
|
140
140
|
readonly lastError: string | null;
|
|
141
141
|
}, {
|
|
142
|
-
readonly _tag: "Denied";
|
|
143
|
-
} | {
|
|
144
142
|
readonly _tag: "Failed";
|
|
145
143
|
readonly message: string;
|
|
146
144
|
} | {
|
|
@@ -155,6 +153,8 @@ export declare const mediaDevices: <const Name extends string>(config: {
|
|
|
155
153
|
readonly kind: "audioinput" | "audiooutput" | "videoinput";
|
|
156
154
|
readonly label: string;
|
|
157
155
|
}[];
|
|
156
|
+
} | {
|
|
157
|
+
readonly _tag: "Denied";
|
|
158
158
|
}, never, never, never, void, {}, {}>;
|
|
159
159
|
//#endregion
|
|
160
160
|
//#region src/device/media-stream.d.ts
|
|
@@ -288,20 +288,20 @@ export declare const permissions: <const Name extends string>(config: {
|
|
|
288
288
|
readonly names: ReadonlyArray<string>;
|
|
289
289
|
}, {
|
|
290
290
|
readonly states: {
|
|
291
|
-
readonly [x: string]: "
|
|
291
|
+
readonly [x: string]: "denied" | "granted" | "prompt";
|
|
292
292
|
};
|
|
293
293
|
readonly lastError: string | null;
|
|
294
294
|
}, {
|
|
295
295
|
readonly _tag: "Changed";
|
|
296
296
|
readonly name: string;
|
|
297
|
-
readonly state: "
|
|
297
|
+
readonly state: "denied" | "granted" | "prompt";
|
|
298
298
|
} | {
|
|
299
299
|
readonly _tag: "Failed";
|
|
300
300
|
readonly message: string;
|
|
301
301
|
} | {
|
|
302
302
|
readonly _tag: "Snapshot";
|
|
303
303
|
readonly states: {
|
|
304
|
-
readonly [x: string]: "
|
|
304
|
+
readonly [x: string]: "denied" | "granted" | "prompt";
|
|
305
305
|
};
|
|
306
306
|
} | {
|
|
307
307
|
readonly _tag: "Cleared";
|
package/dist/net/index.d.mts
CHANGED
|
@@ -106,14 +106,14 @@ export declare const sse: <const Name extends string>(config: {
|
|
|
106
106
|
readonly status: "closed" | "connecting" | "open";
|
|
107
107
|
readonly lastError: string | null;
|
|
108
108
|
}, {
|
|
109
|
-
readonly _tag: "Received";
|
|
110
|
-
readonly data: string;
|
|
111
|
-
} | {
|
|
112
109
|
readonly _tag: "Connecting";
|
|
113
110
|
} | {
|
|
114
111
|
readonly _tag: "Opened";
|
|
115
112
|
} | {
|
|
116
113
|
readonly _tag: "Closed";
|
|
114
|
+
} | {
|
|
115
|
+
readonly _tag: "Received";
|
|
116
|
+
readonly data: string;
|
|
117
117
|
} | {
|
|
118
118
|
readonly _tag: "Failed";
|
|
119
119
|
readonly message: string;
|
|
@@ -179,11 +179,11 @@ export declare const websocket: <const Name extends string>(config: {
|
|
|
179
179
|
readonly _tag: "Connecting";
|
|
180
180
|
} | {
|
|
181
181
|
readonly _tag: "Opened";
|
|
182
|
-
} | {
|
|
183
|
-
readonly _tag: "Closed";
|
|
184
182
|
} | {
|
|
185
183
|
readonly _tag: "Received";
|
|
186
184
|
readonly data: string;
|
|
185
|
+
} | {
|
|
186
|
+
readonly _tag: "Closed";
|
|
187
187
|
} | {
|
|
188
188
|
readonly _tag: "Failed";
|
|
189
189
|
readonly message: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foldkit-primitives",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Ready-made primitives for the Elm architecture, packaged with foldkit-bundle: media queries, presence, timers, pagination, history, sockets, observers, and clipboard.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"foldkit",
|