foldkit-primitives 0.13.0 → 0.15.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.
package/README.md CHANGED
@@ -185,7 +185,7 @@ reference: every Model shape, Message, argument, and failure rule.
185
185
  | [`device`](./device/README.md) | hardware | `Geolocation`, `mediaDevices`, `mediaStream`, `permissions`, fullscreen |
186
186
  | [`events`](./events/README.md) | raw window events | `Visibility`, `WindowSize`, `Idle`, `InputModality`, `keyboardEvents`, `pointerEvents`, `scrollEvents`, `activeElementEvents`, `matchHotkey` |
187
187
  | [`observers`](./observers/README.md) | element observers | `Resize`, `Intersection`, `Mutation`, `Bounds` |
188
- | [`dom`](./dom/README.md) | element Mounts and one-shot Commands | `Autofocus`, `InputMask`, `KeepInView`, `Measure`, `FluidHover`, `ScrollBars`, `PointerPosition`, `FocusScope`, `FollowTabStop`, `ScrollLock`, `HideOutside`, `copyText`, `readText`, `share`, `loadScript`, `keepScroll`, `pointedLinks` |
188
+ | [`dom`](./dom/README.md) | element Mounts and one-shot Commands | `Autofocus`, `InputMask`, `KeepInView`, `Measure`, `FluidHover`, `ScrollBars`, `PointerPosition`, `FocusScope`, `FollowTabStop`, `ScrollLock`, `HideOutside`, `copyText`, `readText`, `share`, `loadScript`, `decodeImage`, `keepScroll`, `pointedLinks` |
189
189
 
190
190
  ## Rules every primitive keeps
191
191
 
@@ -404,6 +404,11 @@ export type SwipeEnded = typeof SwipeEnded.Type;
404
404
  export type SwipeFact = SwipeStarted | Swiped | SwipeEnded;
405
405
  /** How far back, in milliseconds, the release velocity looks. */
406
406
  export declare const SWIPE_WINDOW = 100;
407
+ /**
408
+ * What a swipe never starts on when its element `scrolls`: a field whose own
409
+ * drag selects text or moves a thumb, and anything marked `data-no-swipe`.
410
+ */
411
+ export declare const NO_SWIPE = "input, textarea, select, [contenteditable=\"\"], [contenteditable=\"true\"], [data-no-swipe]";
407
412
  interface Sample {
408
413
  readonly at: number;
409
414
  readonly x: number;
@@ -418,6 +423,12 @@ export declare const velocityOf: (samples: ReadonlyArray<Sample>) => {
418
423
  x: number;
419
424
  y: number;
420
425
  };
426
+ /**
427
+ * Whether anything from `target` up to `root` can still scroll along `axis`
428
+ * the way a finger moving `along` (positive is down or right) pulls it: a
429
+ * finger going down scrolls content toward its start.
430
+ */
431
+ export declare const canScroll: (target: Element, root: Element, axis: 'x' | 'y', along: number) => boolean;
421
432
  /**
422
433
  * `Move` with the speed of its release, for a gesture that a flick ends
423
434
  * (a sheet dragged to dismiss, a card swiped away): a primary-button pointer
@@ -428,6 +439,15 @@ export declare const velocityOf: (samples: ReadonlyArray<Sample>) => {
428
439
  * The start reports the size of what is moved, so a distance can be read as
429
440
  * a share of it. What a delta or a speed means is the parent's `update`.
430
441
  * Capture is released with the Mount.
442
+ *
443
+ * Given `scrolls`, the element holds content that scrolls (a sheet's panel),
444
+ * and a touch is followed by touch events, whose move can still refuse the
445
+ * browser's scroll once the touch is under way, where a pointer's cannot:
446
+ * past the slop, a touch that runs along the axis and finds nothing under it
447
+ * that can scroll further its way swipes, and the browser scrolls any other.
448
+ * A touch inside an element with a Swipe of its own (a handle in the panel)
449
+ * is that one's, and none starts on a field or on `data-no-swipe`
450
+ * (`NO_SWIPE`).
431
451
  */
432
452
  export declare const Swipe: Mount.MountDefinitionWithArgs<"Swipe", {
433
453
  /**
@@ -440,9 +460,14 @@ export declare const Swipe: Mount.MountDefinitionWithArgs<"Swipe", {
440
460
  * How far, in pixels, a press must move before it is a swipe. Until
441
461
  * then nothing is captured or reported, so a press that stays put is
442
462
  * still a click on whatever is under it (a tab inside a drag grip).
443
- * Default 0: the press itself starts the swipe.
463
+ * Default 0: the press itself starts the swipe; with `scrolls`, the
464
+ * first move decides.
444
465
  */
445
466
  slop: Schema.optional<Schema.Number>;
467
+ /** The axis the element's content scrolls along, which a touch yields to; see above. */
468
+ scrolls: Schema.optional<Schema.Literals<readonly ["x", "y"]>>;
469
+ /** Follows touches alone: a mouse or a pen is left to the page (and to a handle's own Swipe). */
470
+ touchOnly: Schema.optional<Schema.Boolean>;
446
471
  }, {
447
472
  readonly _tag: "SwipeStarted";
448
473
  readonly pointerId: number;
@@ -687,5 +712,31 @@ export declare const TrackBox: Mount.MountDefinitionWithArgs<"TrackBox", {
687
712
  readonly found: boolean;
688
713
  }>;
689
714
  //#endregion
715
+ //#region src/dom/image-decode.d.ts
716
+ export declare const ImageDecodeMessage: import("foldkit/message").MessageUnion<{
717
+ readonly Decoded: {
718
+ src: Schema.String;
719
+ };
720
+ readonly DecodeFailed: {
721
+ src: Schema.String;
722
+ message: Schema.String;
723
+ };
724
+ }>;
725
+ export type ImageDecodeMessage = typeof ImageDecodeMessage.Type;
726
+ /** What to decode: a URL, or an `img`'s candidates, so the browser decodes the one it would draw. */
727
+ export interface ImageSource {
728
+ readonly src: string;
729
+ readonly srcset?: string | undefined;
730
+ readonly sizes?: string | undefined;
731
+ }
732
+ /**
733
+ * Fetches and decodes `source` (`img.decode()`), yielding `Decoded` once it
734
+ * can be painted at once, or `DecodeFailed` when it cannot be fetched or read,
735
+ * or there is no document (a server render). Given `srcset` and `sizes`, as
736
+ * `foldkit-media`'s `Picture.Img` has them, the browser picks the candidate
737
+ * it would draw, so the decoded file is the one shown.
738
+ */
739
+ export declare const decodeImage: (source: ImageSource) => Command<ImageDecodeMessage, never, never>;
740
+ //#endregion
690
741
  export { DRAG_THRESHOLD, DragCancelled, DragDropped, DragFact, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, Fact, FocusScope, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, Move, MoveEnded, MoveStarted, Moved, PointerDrag, ScrollLock, TargetFact, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, TextFact, boxOf, tabbableWithin, targetOf, textOf, zoneOf };
691
742
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/dom/autofocus.ts","../../src/dom/clipboard.ts","../../src/dom/input-mask.ts","../../src/dom/keep-in-view.ts","../../src/dom/script-loader.ts","../../src/dom/share.ts","../../src/dom/measure.ts","../../src/dom/follow-tab-stop.ts","../../src/dom/scroll.ts","../../src/dom/pointed-links.ts","../../src/dom/fluid-hover.ts","../../src/dom/keyboard-inset.ts","../../src/dom/scroll-bars.ts","../../src/dom/swipe.ts","../../src/dom/scroll-settle.ts","../../src/dom/pointer-position.ts","../../src/dom/track-box.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/dom/autofocus.ts","../../src/dom/clipboard.ts","../../src/dom/input-mask.ts","../../src/dom/keep-in-view.ts","../../src/dom/script-loader.ts","../../src/dom/share.ts","../../src/dom/measure.ts","../../src/dom/follow-tab-stop.ts","../../src/dom/scroll.ts","../../src/dom/pointed-links.ts","../../src/dom/fluid-hover.ts","../../src/dom/keyboard-inset.ts","../../src/dom/scroll-bars.ts","../../src/dom/swipe.ts","../../src/dom/scroll-settle.ts","../../src/dom/pointer-position.ts","../../src/dom/track-box.ts","../../src/dom/image-decode.ts"],"mappings":";;;;;;qBAGa,SAAO,OAAA;YACR,iBAAiB,QAAQ;;;;;;;;qBASxB,WAAS,MAAA;;;;;qBCJT,4CAAgB;;;IAEb,SAAO,OAAA;;;YAEX,0BAA0B,iBAAiB;qBAE1C,gDAAoB;;IACvB,MAAI,OAAA;;;IACE,SAAO,OAAA;;;YAEX,8BAA8B,qBAAqB;;;;;;qBAUlD,WAAQ,iBAAmB,QAAQ;;;;;qBAsBnC,gBAAe,QAAQ;;;;qBC/CvB,OAAK,OAAA;;;;YAIN,eAAe,MAAM;;;;;;;qBAiCpB,YAAS,eACP;WAED;WAAyB;;;;;;;;;;;qBA6C1B,WAAS,MAAA;WAAT,OAAA;;;;;;;;;;;;;;;;;qBC7EA,YAAU,MAAA;;YAAV,OAAA;;;;qBCDA,yCAAa;;;IAEV,SAAO,OAAA;;;YAEX,uBAAuB,cAAc;;qBASpC,aAAU,gBAAkB,QAAQ;;;qBCbpC,WAAS,OAAA;;;;;YAKV,mBAAmB,UAAU;qBAE5B,wCAAY;;;;IAGR,SAAO,OAAA;;;YAEZ,sBAAsB,aAAa;;qBAUlC,QAAK,MAAU,cAAY,QAAQ;;;;qBC7BnC,WAAQ;WAEjB;WACA;WACA;WACA;WACA;;;;;;;WAOA;;;;;;;;;;;;;;;;;;;;;;qBAuBS,SAAO,MAAA;;;;;;;;;;;;;;qBC7BP,eAAa,MAAA;;;;iBCuBT;;WAEN;;WAEA;;;;;WAKA;;;;;;;;qBAuHE,aAAU,UAAa,sBAAyB,OAAO;;;;;;;;;;qBCvJvD,oBAAmB,OAAO,OAAO;;;;qBCPjC,eAAY;WAErB;WACA;WACA;WACA;;WAEA;;;;;;WAMA;;;;;;;qBAQS;;qBAGA;;qBAGA;cAEP,MAAI,OAAA;YACE,mBAAmB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAyDvB,YAAU,MAAA;;;;;;;;;;;;;;;;;;;;;;;qBCnFV;;;;;qBAMA,gBAAa;WACf;WACA;aAA2B;aAAyB;;;;;;;;;;;;qBAkBlD,eAAa,MAAA;;;;;;;qBC3Bb;;;;;;qBAOA;;;;;;qBAOA;WACX;WACA;;;;;;;;;;;;;;;;;;;;;qBA6BW,YAAU,MAAA;;;;;;;;;;;;qBCjDV,cAAY,OAAA;;;;;;;YAOb,sBAAsB,aAAa;qBAElC,QAAM,OAAA;;;;;;YAMP,gBAAgB,OAAO;qBAEtB,YAAU,OAAA;;;;;;;;;;;;;;YAcX,oBAAoB,WAAW;YAE/B,YAAY,eAAe,SAAS;;qBAGnC;;;;;qBAMA;UAgBH;WACC;WACA;WACA;;;;;;;qBAmBE,aAAU,SAAa,cAAc;EAAY;EAAW;;;;;;;qBAe5D,YAAS,QACZ,SAAO,MACT,SAAO,iBACE;;;;;;;;;;;;;;;;;;;;;qBAoCJ,OAAK,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCtIL,eAAa,OAAA;;kBAAb,OAAA;;YAID,uBAAuB,cAAc;;qBAGpC;;;;;;;;;;;;;qBAcA,cAAY,MAAA;;;;;;;;;;;;;;;;;;;qBCfZ,cAAY,OAAA;;;;;YAKb,sBAAsB,aAAa;qBAKlC,gBAAc,OAAA;;;;;;;;;;;YAMf,wBAAwB,eAAe;qBAEtC,cAAY,OAAA;;;;;;;;;;;;;;;;;;;;YAWb,sBAAsB,aAAa;qBAElC,iBAAe,OAAA;;sBAAf,OAAA;;YAID,yBAAyB,gBAAgB;YAEzC,cAAc,iBAAiB,eAAe;UAEhD;WACC;WACA;WACA;WACA;;iBAGM;WACN;WACA;WACA;WACA;;;;;;;;qBASE,eAAY;WAAuB,MAAM;WAAe,QAAQ;MAAU;;;;;;;;qBAwB1E,oBAAiB,SAAa,YAAU;;;;;;;;;;;;;;;qBA0BxC,iBAAe,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBClHf;;qBAGA,aAAU;WAEnB;WACA;WACA;WACA;WACA;;;qBAIS,eAAa,OAAA;;;;YAId,uBAAuB,cAAc;;;;;;;qBAQpC,eAAY,eAAiB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;qBAiC5C,UAAQ,MAAA;;;;;;;;;;;;qBCnDR,8CAAkB;;IAClB,KAAG,OAAA;;;IACE,KAAG,OAAA;IAAiB,SAAO,OAAA;;;YAEjC,4BAA4B,mBAAmB;;iBAG1C;WACN;WACA;WACA;;;;;;;;;qBAUE,cAAW,QAAY,gBAAc,QAAQ"}
@@ -1139,6 +1139,13 @@ const SwipeEnded = Schema.TaggedStruct("SwipeEnded", {
1139
1139
  /** How far back, in milliseconds, the release velocity looks. */
1140
1140
  const SWIPE_WINDOW = 100;
1141
1141
  /**
1142
+ * What a swipe never starts on when its element `scrolls`: a field whose own
1143
+ * drag selects text or moves a thumb, and anything marked `data-no-swipe`.
1144
+ */
1145
+ const NO_SWIPE = "input, textarea, select, [contenteditable=\"\"], [contenteditable=\"true\"], [data-no-swipe]";
1146
+ /** Every element a Swipe is mounted on: a touch inside one is that one's, not an outer one's. */
1147
+ const owners = /* @__PURE__ */ new WeakSet();
1148
+ /**
1142
1149
  * The velocity of the samples within `SWIPE_WINDOW` of the last: the way
1143
1150
  * from the oldest of them to the last over the time between. A pointer that
1144
1151
  * came to rest before the last sample has no recent way to measure, so 0.
@@ -1160,6 +1167,23 @@ const velocityOf = (samples) => {
1160
1167
  };
1161
1168
  };
1162
1169
  /**
1170
+ * Whether anything from `target` up to `root` can still scroll along `axis`
1171
+ * the way a finger moving `along` (positive is down or right) pulls it: a
1172
+ * finger going down scrolls content toward its start.
1173
+ */
1174
+ const canScroll = (target, root, axis, along) => {
1175
+ for (let at = target; at !== null; at = at.parentElement) {
1176
+ const overflow = getComputedStyle(at)[axis === "y" ? "overflowY" : "overflowX"];
1177
+ if (overflow === "auto" || overflow === "scroll") {
1178
+ const position = Math.abs(axis === "y" ? at.scrollTop : at.scrollLeft);
1179
+ const room = axis === "y" ? at.scrollHeight - at.clientHeight : at.scrollWidth - at.clientWidth;
1180
+ if (room > 1 && (along > 0 ? position > .5 : position < room - .5)) return true;
1181
+ }
1182
+ if (at === root) return false;
1183
+ }
1184
+ return false;
1185
+ };
1186
+ /**
1163
1187
  * `Move` with the speed of its release, for a gesture that a flick ends
1164
1188
  * (a sheet dragged to dismiss, a card swiped away): a primary-button pointer
1165
1189
  * down (or, given a `slop`, its first move past it) captures the pointer,
@@ -1169,6 +1193,15 @@ const velocityOf = (samples) => {
1169
1193
  * The start reports the size of what is moved, so a distance can be read as
1170
1194
  * a share of it. What a delta or a speed means is the parent's `update`.
1171
1195
  * Capture is released with the Mount.
1196
+ *
1197
+ * Given `scrolls`, the element holds content that scrolls (a sheet's panel),
1198
+ * and a touch is followed by touch events, whose move can still refuse the
1199
+ * browser's scroll once the touch is under way, where a pointer's cannot:
1200
+ * past the slop, a touch that runs along the axis and finds nothing under it
1201
+ * that can scroll further its way swipes, and the browser scrolls any other.
1202
+ * A touch inside an element with a Swipe of its own (a handle in the panel)
1203
+ * is that one's, and none starts on a field or on `data-no-swipe`
1204
+ * (`NO_SWIPE`).
1172
1205
  */
1173
1206
  const Swipe = Mount.defineStream("Swipe", {
1174
1207
  messages: [
@@ -1187,47 +1220,51 @@ const Swipe = Mount.defineStream("Swipe", {
1187
1220
  * How far, in pixels, a press must move before it is a swipe. Until
1188
1221
  * then nothing is captured or reported, so a press that stays put is
1189
1222
  * still a click on whatever is under it (a tab inside a drag grip).
1190
- * Default 0: the press itself starts the swipe.
1223
+ * Default 0: the press itself starts the swipe; with `scrolls`, the
1224
+ * first move decides.
1191
1225
  */
1192
- slop: Schema.optional(Schema.Number)
1226
+ slop: Schema.optional(Schema.Number),
1227
+ /** The axis the element's content scrolls along, which a touch yields to; see above. */
1228
+ scrolls: Schema.optional(Schema.Literals(["x", "y"])),
1229
+ /** Follows touches alone: a mouse or a pen is left to the page (and to a handle's own Swipe). */
1230
+ touchOnly: Schema.optional(Schema.Boolean)
1193
1231
  },
1194
- execute: ({ element, measure, slop = 0 }) => Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
1232
+ execute: ({ element, measure, slop = 0, scrolls, touchOnly = false }) => Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
1195
1233
  const target = element;
1196
1234
  let active = null;
1197
1235
  const offer = (fact) => Queue.offerUnsafe(queue, fact);
1198
- const sampleOf = (event) => ({
1199
- at: event.timeStamp,
1200
- x: event.clientX ?? 0,
1201
- y: event.clientY ?? 0
1236
+ const sampleOf = (at, x = 0, y = 0) => ({
1237
+ at,
1238
+ x,
1239
+ y
1202
1240
  });
1203
- const end = (event, completed) => {
1204
- const pointerId = event.pointerId ?? 0;
1241
+ const end = (pointerId, last, completed, captured) => {
1205
1242
  if (active === null || active.pointerId !== pointerId) return;
1206
1243
  const { samples, started } = active;
1207
1244
  active = null;
1208
1245
  if (!started) return;
1209
- try {
1246
+ if (captured) try {
1210
1247
  target.releasePointerCapture?.(pointerId);
1211
1248
  } catch {}
1212
- const last = completed ? sampleOf(event) : samples.at(-1) ?? sampleOf(event);
1213
- const all = completed ? [...samples, last] : samples;
1214
- const start = all[0] ?? last;
1249
+ const final = completed ? last : samples.at(-1) ?? last;
1250
+ const all = completed ? [...samples, final] : samples;
1251
+ const start = all[0] ?? final;
1215
1252
  const velocity = completed ? velocityOf(all) : {
1216
1253
  x: 0,
1217
1254
  y: 0
1218
1255
  };
1219
1256
  offer(SwipeEnded.make({
1220
1257
  pointerId,
1221
- deltaX: last.x - start.x,
1222
- deltaY: last.y - start.y,
1258
+ deltaX: final.x - start.x,
1259
+ deltaY: final.y - start.y,
1223
1260
  velocityX: velocity.x,
1224
1261
  velocityY: velocity.y,
1225
1262
  completed
1226
1263
  }));
1227
1264
  };
1228
- const begin = (pointer) => {
1265
+ const begin = (pointer, capture) => {
1229
1266
  pointer.started = true;
1230
- try {
1267
+ if (capture) try {
1231
1268
  target.setPointerCapture?.(pointer.pointerId);
1232
1269
  } catch {}
1233
1270
  const box = (measure === void 0 ? element : element.closest(measure) ?? element).getBoundingClientRect();
@@ -1238,52 +1275,121 @@ const Swipe = Mount.defineStream("Swipe", {
1238
1275
  height: box.height
1239
1276
  }));
1240
1277
  };
1241
- const listeners = [
1278
+ const moved = (pointer, sample) => {
1279
+ const start = pointer.samples[0] ?? sample;
1280
+ pointer.samples = [
1281
+ start,
1282
+ ...pointer.samples.slice(1).filter((each) => sample.at - each.at <= 100),
1283
+ sample
1284
+ ];
1285
+ offer(Swiped.make({
1286
+ pointerId: pointer.pointerId,
1287
+ deltaX: sample.x - start.x,
1288
+ deltaY: sample.y - start.y
1289
+ }));
1290
+ };
1291
+ const ownTouch = (from) => {
1292
+ if (!(from instanceof Element)) return false;
1293
+ const field = from.closest(NO_SWIPE);
1294
+ if (field !== null && element.contains(field)) return false;
1295
+ for (let at = from; at !== null && at !== element; at = at.parentElement) if (owners.has(at)) return false;
1296
+ return true;
1297
+ };
1298
+ const touchOf = (event, id) => Array.from(event.changedTouches).find((touch) => touch.identifier === id);
1299
+ let touched = null;
1300
+ const pointerListeners = [
1242
1301
  ["pointerdown", (event) => {
1243
1302
  const pointer = event;
1303
+ const type = pointer.pointerType ?? "mouse";
1304
+ if (scrolls !== void 0 && type === "touch") return;
1305
+ if (touchOnly && type !== "touch") return;
1244
1306
  if ((pointer.button ?? 0) !== 0 || active !== null) return;
1245
1307
  active = {
1246
1308
  pointerId: pointer.pointerId ?? 0,
1247
- pointerType: pointer.pointerType ?? "mouse",
1248
- samples: [sampleOf(pointer)],
1309
+ pointerType: type,
1310
+ samples: [sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY)],
1249
1311
  started: false
1250
1312
  };
1251
- if (slop <= 0) begin(active);
1313
+ if (slop <= 0) begin(active, true);
1252
1314
  }],
1253
1315
  ["pointermove", (event) => {
1254
1316
  const pointer = event;
1255
- const pointerId = pointer.pointerId ?? 0;
1256
- if (active === null || active.pointerId !== pointerId) return;
1257
- const sample = sampleOf(pointer);
1258
- const start = active.samples[0] ?? sample;
1317
+ if (active === null || active.pointerId !== (pointer.pointerId ?? 0)) return;
1318
+ const sample = sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY);
1259
1319
  if (!active.started) {
1320
+ const start = active.samples[0] ?? sample;
1260
1321
  if (Math.hypot(sample.x - start.x, sample.y - start.y) < slop) return;
1261
- begin(active);
1322
+ begin(active, true);
1323
+ }
1324
+ moved(active, sample);
1325
+ }],
1326
+ ...[
1327
+ "pointerup",
1328
+ "pointercancel",
1329
+ "lostpointercapture"
1330
+ ].map((type) => [type, (event) => {
1331
+ const pointer = event;
1332
+ if (active?.pointerType === "touch" && scrolls !== void 0) return;
1333
+ end(pointer.pointerId ?? 0, sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY), type === "pointerup", true);
1334
+ }])
1335
+ ];
1336
+ const touchListeners = scrolls === void 0 ? [] : [
1337
+ ["touchstart", (event) => {
1338
+ const touches = event;
1339
+ const touch = touches.changedTouches[0];
1340
+ if (active !== null || touches.touches.length !== 1 || touch === void 0) return;
1341
+ if (!ownTouch(touches.target)) return;
1342
+ touched = touches.target;
1343
+ active = {
1344
+ pointerId: touch.identifier,
1345
+ pointerType: "touch",
1346
+ samples: [sampleOf(touches.timeStamp, touch.clientX, touch.clientY)],
1347
+ started: false
1348
+ };
1349
+ }],
1350
+ ["touchmove", (event) => {
1351
+ const touches = event;
1352
+ if (active === null) return;
1353
+ const touch = touchOf(touches, active.pointerId);
1354
+ if (touch === void 0) return;
1355
+ const sample = sampleOf(touches.timeStamp, touch.clientX, touch.clientY);
1356
+ if (!active.started) {
1357
+ const start = active.samples[0] ?? sample;
1358
+ const dx = sample.x - start.x;
1359
+ const dy = sample.y - start.y;
1360
+ if (Math.hypot(dx, dy) < Math.max(slop, 1)) return;
1361
+ const along = scrolls === "y" ? dy : dx;
1362
+ if (Math.abs(scrolls === "y" ? dx : dy) > Math.abs(along) || canScroll(touched ?? element, element, scrolls, along) || !touches.cancelable) {
1363
+ active = null;
1364
+ return;
1365
+ }
1366
+ begin(active, false);
1262
1367
  }
1263
- active.samples = [
1264
- start,
1265
- ...active.samples.slice(1).filter((each) => sample.at - each.at <= 100),
1266
- sample
1267
- ];
1268
- offer(Swiped.make({
1269
- pointerId,
1270
- deltaX: sample.x - start.x,
1271
- deltaY: sample.y - start.y
1272
- }));
1368
+ touches.preventDefault();
1369
+ moved(active, sample);
1273
1370
  }],
1274
- ["pointerup", (event) => end(event, true)],
1275
- ["pointercancel", (event) => end(event, false)],
1276
- ["lostpointercapture", (event) => end(event, false)]
1371
+ ...["touchend", "touchcancel"].map((type) => [type, (event) => {
1372
+ const touches = event;
1373
+ if (active === null) return;
1374
+ const touch = touchOf(touches, active.pointerId);
1375
+ if (touch === void 0) return;
1376
+ end(active.pointerId, sampleOf(touches.timeStamp, touch.clientX, touch.clientY), type === "touchend", false);
1377
+ }])
1277
1378
  ];
1278
- for (const [type, listener] of listeners) element.addEventListener(type, listener);
1379
+ owners.add(element);
1380
+ for (const [type, listener] of pointerListeners) element.addEventListener(type, listener);
1381
+ for (const [type, listener] of touchListeners) element.addEventListener(type, listener, { passive: false });
1279
1382
  return {
1280
- listeners,
1383
+ pointerListeners,
1384
+ touchListeners,
1281
1385
  current: () => active
1282
1386
  };
1283
- }), ({ listeners, current }) => Effect.sync(() => {
1284
- for (const [type, listener] of listeners) element.removeEventListener(type, listener);
1387
+ }), ({ pointerListeners, touchListeners, current }) => Effect.sync(() => {
1388
+ owners.delete(element);
1389
+ for (const [type, listener] of pointerListeners) element.removeEventListener(type, listener);
1390
+ for (const [type, listener] of touchListeners) element.removeEventListener(type, listener);
1285
1391
  const pointer = current();
1286
- if (pointer !== null) try {
1392
+ if (pointer !== null && !(pointer.pointerType === "touch" && scrolls !== void 0)) try {
1287
1393
  element.releasePointerCapture?.(pointer.pointerId);
1288
1394
  } catch {}
1289
1395
  })))
@@ -1665,6 +1771,52 @@ const TrackBox = Mount.defineStream("TrackBox", {
1665
1771
  }), (stop) => Effect.sync(stop)))
1666
1772
  });
1667
1773
  //#endregion
1668
- export { Autofocus, ClipboardMessage, ClipboardReadMessage, DRAG_THRESHOLD, DragCancelled, DragDropped, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, FocusScope, Focused, FollowTabStop, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, Input, InputMask, KEYBOARD_INSET, KeepInView, KeyboardInset, Measure, Move, MoveEnded, MoveStarted, Moved, PointerDrag, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, TrackBox, TrackedTarget, applyMask, boxOf, copyText, cornerRadius, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, tabbableWithin, targetOf, textOf, trackedBox, velocityOf, zoneOf };
1774
+ //#region src/dom/image-decode.ts
1775
+ /**
1776
+ * An image fetched and decoded before it is shown, as a Command: a lightbox
1777
+ * or a carousel asks for the next picture, and shows it on `Decoded`, so the
1778
+ * switch never passes through a blank frame. A Command, not a Mount: the
1779
+ * Model decides to show the image, so the Message that leads there carries
1780
+ * the news that it is ready.
1781
+ */
1782
+ const ImageDecodeMessage = defineMessageUnion({
1783
+ Decoded: { src: Schema.String },
1784
+ DecodeFailed: {
1785
+ src: Schema.String,
1786
+ message: Schema.String
1787
+ }
1788
+ });
1789
+ /**
1790
+ * Fetches and decodes `source` (`img.decode()`), yielding `Decoded` once it
1791
+ * can be painted at once, or `DecodeFailed` when it cannot be fetched or read,
1792
+ * or there is no document (a server render). Given `srcset` and `sizes`, as
1793
+ * `foldkit-media`'s `Picture.Img` has them, the browser picks the candidate
1794
+ * it would draw, so the decoded file is the one shown.
1795
+ */
1796
+ const decodeImage = (source) => ({
1797
+ name: "Image.decode",
1798
+ args: { src: source.src },
1799
+ effect: typeof document === "undefined" ? Effect.succeed(ImageDecodeMessage.DecodeFailed({
1800
+ src: source.src,
1801
+ message: "there is no document"
1802
+ })) : Effect.matchEffect(Effect.tryPromise({
1803
+ try: () => {
1804
+ const image = new Image();
1805
+ if (source.sizes !== void 0) image.sizes = source.sizes;
1806
+ if (source.srcset !== void 0) image.srcset = source.srcset;
1807
+ image.src = source.src;
1808
+ return image.decode();
1809
+ },
1810
+ catch: (error) => error instanceof Error ? error.message : String(error)
1811
+ }), {
1812
+ onFailure: (message) => Effect.succeed(ImageDecodeMessage.DecodeFailed({
1813
+ src: source.src,
1814
+ message
1815
+ })),
1816
+ onSuccess: () => Effect.succeed(ImageDecodeMessage.Decoded({ src: source.src }))
1817
+ })
1818
+ });
1819
+ //#endregion
1820
+ export { Autofocus, ClipboardMessage, ClipboardReadMessage, DRAG_THRESHOLD, DragCancelled, DragDropped, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, FocusScope, Focused, FollowTabStop, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, ImageDecodeMessage, Input, InputMask, KEYBOARD_INSET, KeepInView, KeyboardInset, Measure, Move, MoveEnded, MoveStarted, Moved, NO_SWIPE, PointerDrag, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, TrackBox, TrackedTarget, applyMask, boxOf, canScroll, copyText, cornerRadius, decodeImage, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, tabbableWithin, targetOf, textOf, trackedBox, velocityOf, zoneOf };
1669
1821
 
1670
1822
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["failMessage","failMessage","urlToString"],"sources":["../../src/dom/autofocus.ts","../../src/dom/clipboard.ts","../../src/dom/input-mask.ts","../../src/dom/keep-in-view.ts","../../src/dom/script-loader.ts","../../src/dom/share.ts","../../src/dom/measure.ts","../../src/dom/scroll.ts","../../src/dom/pointed-links.ts","../../src/dom/fluid-hover.ts","../../src/dom/keyboard-inset.ts","../../src/dom/scroll-bars.ts","../../src/dom/swipe.ts","../../src/dom/scroll-settle.ts","../../src/dom/pointer-position.ts","../../src/dom/track-box.ts"],"sourcesContent":["import { Effect, Schema } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const Focused = Schema.TaggedStruct('Focused', {})\nexport type Focused = typeof Focused.Type\n\n/**\n * Autofocus as a Mount: focuses the element on insert, then emits `Focused`.\n * The message means focus was requested — a non-focusable element or a\n * hidden tab may decline, and the browser does not report that. Plain\n * `focus()`, no scroll options: scroll behavior stays the application's\n * choice.\n */\nexport const Autofocus = Mount.define('Autofocus', {\n messages: [Focused],\n execute: ({ element }) =>\n Effect.sync(() => {\n const focusable = element as unknown as { readonly focus?: unknown }\n if (typeof focusable.focus === 'function') {\n ;(focusable.focus as () => void).call(element)\n }\n return Focused.make({})\n }),\n})\n","/**\n * The clipboard as Commands: run in `update` beside any bundle. A copy yields\n * `Copied` or `CopyFailed`, a read `Read` or `ReadFailed`. No Model involved:\n * the clipboard is not application state.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ClipboardMessage = defineMessageUnion({\n Copied: {},\n CopyFailed: { message: Schema.String },\n})\nexport type ClipboardMessage = typeof ClipboardMessage.Type\n\nexport const ClipboardReadMessage = defineMessageUnion({\n Read: { text: Schema.String },\n ReadFailed: { message: Schema.String },\n})\nexport type ClipboardReadMessage = typeof ClipboardReadMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\n/**\n * Copies text to the clipboard. Without a clipboard API (SSR, insecure\n * context, denied permission) the command yields `CopyFailed` instead of\n * throwing, so `update` handles both outcomes as Messages.\n */\nexport const copyText = (text: string): Command<ClipboardMessage, never, never> => ({\n name: 'Clipboard.copy',\n args: { text },\n effect:\n typeof navigator !== 'undefined' && typeof navigator.clipboard?.writeText === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({\n try: () => navigator.clipboard.writeText(text),\n catch: failMessage,\n }),\n {\n onFailure: message => Effect.succeed(ClipboardMessage.CopyFailed({ message })),\n onSuccess: () => Effect.succeed(ClipboardMessage.Copied()),\n },\n )\n : Effect.succeed(ClipboardMessage.CopyFailed({ message: 'clipboard is unavailable' })),\n})\n\n/**\n * Reads the clipboard's text. The browser may ask the user first; a refusal,\n * an insecure context or no clipboard API yields `ReadFailed`.\n */\nexport const readText = (): Command<ClipboardReadMessage, never, never> => ({\n name: 'Clipboard.read',\n effect:\n typeof navigator !== 'undefined' && typeof navigator.clipboard?.readText === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({ try: () => navigator.clipboard.readText(), catch: failMessage }),\n {\n onFailure: message => Effect.succeed(ClipboardReadMessage.ReadFailed({ message })),\n onSuccess: text => Effect.succeed(ClipboardReadMessage.Read({ text })),\n },\n )\n : Effect.succeed(ClipboardReadMessage.ReadFailed({ message: 'clipboard is unavailable' })),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** What `InputMask` reports after each edit: the masked text shown, and the characters typed. */\nexport const Input = Schema.TaggedStruct('Input', {\n value: Schema.String,\n raw: Schema.String,\n})\nexport type Input = typeof Input.Type\n\nconst isDigit = (char: string): boolean => char >= '0' && char <= '9'\nconst isLetter = (char: string): boolean =>\n (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z')\n\nconst matches = (placeholder: string, char: string): boolean =>\n placeholder === '#'\n ? isDigit(char)\n : placeholder === 'A'\n ? isLetter(char)\n : isDigit(char) || isLetter(char)\n\nconst isPlaceholder = (char: string): boolean => char === '#' || char === 'A' || char === '*'\n\n/** Whether any placeholder at or after `from` consumes any input at or after `at`. */\nconst fillable = (pattern: string, from: number, value: string, at: number): boolean => {\n for (let i = from; i < pattern.length; i++) {\n const placeholder = pattern[i]!\n if (!isPlaceholder(placeholder)) continue\n for (let j = at; j < value.length; j++) {\n if (matches(placeholder, value[j]!)) return true\n }\n }\n return false\n}\n\n/**\n * The mask as a pure function: `#` takes a digit, `A` a letter, `*` either, and\n * any other character of the pattern is written in once input reaches past it.\n * Input that fits no placeholder is skipped. `masked` is what the field shows;\n * `raw` is only the characters typed.\n */\nexport const applyMask = (\n value: string,\n pattern: string,\n): { readonly masked: string; readonly raw: string } => {\n let masked = ''\n let raw = ''\n let at = 0\n for (let i = 0; i < pattern.length; i++) {\n const slot = pattern[i]!\n if (isPlaceholder(slot)) {\n while (at < value.length && !matches(slot, value[at]!)) at++\n if (at >= value.length) break\n masked += value[at]!\n raw += value[at]!\n at++\n } else if (fillable(pattern, i + 1, value, at)) {\n masked += slot\n } else {\n break\n }\n }\n return { masked, raw }\n}\n\ninterface MaskableField {\n value: string\n selectionStart: number | null\n addEventListener(type: string, listener: () => void): void\n removeEventListener(type: string, listener: () => void): void\n setSelectionRange?(start: number, end: number): void\n}\n\nconst asField = (element: Element): MaskableField | null => {\n const field = element as unknown as Partial<MaskableField>\n return typeof field.value === 'string' && typeof field.addEventListener === 'function'\n ? (field as MaskableField)\n : null\n}\n\n/**\n * An input mask as a Mount plus a pure mask function. The pattern language\n * is three placeholders — `#` digit, `A` letter, `*` either, all ASCII —\n * with every other character literal. Literals appear only once a later placeholder\n * consumes input, so partial values never dangle a separator. The Mount\n * rewrites the field, restores the caret approximately, and emits `Input`\n * with both the masked and raw values; the parent owns the state, like any\n * controlled input.\n */\nexport const InputMask = Mount.defineStream('InputMask', {\n messages: [Input],\n args: { pattern: Schema.String },\n execute: ({ element, pattern }) =>\n Stream.callback<typeof Input.Type>(queue =>\n Effect.gen(function* () {\n const field = asField(element)\n if (field === null) return\n const onInput = () => {\n const { masked, raw } = applyMask(field.value, pattern)\n if (masked !== field.value) {\n const caret = field.selectionStart ?? masked.length\n field.value = masked\n const at = Math.min(caret, masked.length)\n try {\n field.setSelectionRange?.(at, at)\n } catch {\n // Select-all style inputs reject ranges; the value still stands.\n }\n }\n Queue.offerUnsafe(queue, Input.make({ value: masked, raw }))\n }\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n field.addEventListener('input', onInput)\n return field\n }),\n current => Effect.sync(() => current.removeEventListener('input', onInput)),\n )\n }),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * Keeps what is marked in view as a Mount: whenever an element in the mounted\n * one's subtree newly matches `selector`, such as the row just selected in a\n * list, it is scrolled into view the least amount that shows it (`nearest`).\n * The element keeps its identity and its focus: nothing is redrawn to move it.\n *\n * It watches with a `MutationObserver` for as long as it is mounted, which is as\n * long as the list or canvas that can change what is marked.\n */\nexport const KeepInView = Mount.defineStream('KeepInView', {\n messages: [Schema.Never],\n args: {\n /** What is marked, as a selector within the element: `[aria-selected=\"true\"]`. */\n selector: Schema.String,\n },\n execute: ({ element, selector }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n let marked = element.querySelector(selector)\n const observer = new MutationObserver(() => {\n const now = element.querySelector(selector)\n // Only a change of what is marked scrolls: the author's own scrolling stays.\n // A DOM with no layout (jsdom, in a test) has no scrollIntoView and nothing to scroll.\n if (now !== null && now !== marked && typeof now.scrollIntoView === 'function')\n now.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n marked = now\n })\n observer.observe(element, { subtree: true, childList: true, attributes: true })\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n ),\n ),\n})\n","/**\n * Script loading as a Command: appends a `src` script to the head unless one\n * is already there. Idempotent by URL — concurrent placements collapse onto\n * the first tag instead of fetching twice. Yields `Loaded` on success and\n * `LoadFailed` otherwise (network error, no document), so `update` handles\n * both outcomes as Messages.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ScriptMessage = defineMessageUnion({\n Loaded: {},\n LoadFailed: { message: Schema.String },\n})\nexport type ScriptMessage = typeof ScriptMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\n// Tags still fetching, by URL: concurrent loads share one tag and its fate.\nconst inflight = new Map<string, Promise<void>>()\n\n/** Loads a script by URL, once per URL. */\nexport const loadScript = (src: string): Command<ScriptMessage, never, never> => ({\n name: 'Script.load',\n args: { src },\n effect: Effect.matchEffect(\n Effect.tryPromise({\n try: () => {\n if (typeof document === 'undefined') {\n return Promise.reject(new Error('script loading is unavailable'))\n }\n // Concurrent loads share one tag and its fate, instead of racing\n // past the presence check and fetching twice: the in-flight entry\n // is checked before presence, in the same synchronous block that\n // appends, so a second load cannot slip between them.\n const running = inflight.get(src)\n if (running !== undefined) return running\n // getAttribute, not .src: the property resolves to an absolute URL\n // and would never equal the given string.\n const present = Array.from(document.getElementsByTagName('script')).some(\n element => element.getAttribute('src') === src,\n )\n if (present) return Promise.resolve()\n const completion = new Promise<void>((resolve, reject) => {\n const element = document.createElement('script')\n element.src = src\n element.async = true\n element.onload = () => resolve()\n element.onerror = () => {\n // A dead tag must not satisfy later presence checks.\n element.remove()\n reject(new Error(`failed to load script: ${src}`))\n }\n document.head.appendChild(element)\n })\n const tracked = completion.then(\n () => {\n inflight.delete(src)\n },\n (error: unknown) => {\n inflight.delete(src)\n throw error\n },\n )\n inflight.set(src, tracked)\n return tracked\n },\n catch: (error: unknown) => error,\n }),\n {\n onFailure: error => Effect.succeed(ScriptMessage.LoadFailed({ message: failMessage(error) })),\n onSuccess: () => Effect.succeed(ScriptMessage.Loaded()),\n },\n ),\n})\n","/**\n * Web Share as a Command: runs in `update` beside any bundle, yields\n * `Shared` on success. Dismissal is its own outcome, not a failure — the\n * application tells a cancelled sheet apart from a broken one. Without a\n * share API (desktop, insecure context) it yields `ShareFailed` instead of\n * throwing, so `update` handles every outcome as a Message.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ShareData = Schema.Struct({\n title: Schema.optional(Schema.String),\n text: Schema.optional(Schema.String),\n url: Schema.optional(Schema.String),\n})\nexport type ShareData = typeof ShareData.Type\n\nexport const ShareMessage = defineMessageUnion({\n Shared: {},\n Dismissed: {},\n ShareFailed: { message: Schema.String },\n})\nexport type ShareMessage = typeof ShareMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\nconst isDismissal = (error: unknown): boolean =>\n typeof (error as { readonly name?: unknown } | null)?.name === 'string' &&\n (error as { readonly name: string }).name === 'AbortError'\n\n/** Shares data through the platform sheet. */\nexport const share = (data: ShareData): Command<ShareMessage, never, never> => ({\n name: 'Share.share',\n args: { data },\n effect:\n typeof navigator !== 'undefined' && typeof navigator.share === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({\n // Omit absent fields: the platform type rejects explicit\n // undefined under exactOptionalPropertyTypes.\n try: () =>\n navigator.share({\n ...(data.title !== undefined ? { title: data.title } : {}),\n ...(data.text !== undefined ? { text: data.text } : {}),\n ...(data.url !== undefined ? { url: data.url } : {}),\n }),\n catch: (error: unknown) => error,\n }),\n {\n onFailure: error =>\n Effect.succeed(\n isDismissal(error)\n ? ShareMessage.Dismissed()\n : ShareMessage.ShareFailed({ message: failMessage(error) }),\n ),\n onSuccess: () => Effect.succeed(ShareMessage.Shared()),\n },\n )\n : Effect.succeed(ShareMessage.ShareFailed({ message: 'share is unavailable' })),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The custom properties `Measure` writes for a target named `name`. */\nexport const measured = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n display: `--fk-${name}-display`,\n /**\n * `1` for the measure that finds the mark on another element than the\n * last, `0` for any other (the layout moved or resized the same one, or\n * it is the first found): an overlay that glides to a new mark scales its\n * duration by it, so it keeps to its element as the layout settles.\n */\n moving: `--fk-${name}-moving`,\n }) as const\n\n/**\n * Measures marked elements as a Mount, for a view to draw something over them,\n * such as an editor's selection outline, with no Message and no Model: where\n * an element is, is presentation, known to the DOM and to no transition.\n *\n * For each named target, the first element in the mounted one's subtree that\n * matches its selector is measured relative to the mounted element's scroll\n * box, which is what an absolutely placed child of it is laid out in. The\n * mounted element gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, and\n * `--fk-<name>-display`: `block` while a target is found, `none` while none is,\n * and `--fk-<name>-moving` (see `measured`).\n *\n * It measures again when the subtree changes (a selection moves) or the\n * mounted element or a measured one changes size, in the frame the change is\n * drawn in; and, at most once a frame, when the mounted element scrolls, the\n * window resizes, an image or a font inside loads, and on every frame of a\n * transition or an animation inside. What moves a target by any other way,\n * such as a stylesheet added that shifts it without resizing it, is seen at\n * the next of these.\n */\nexport const Measure = Mount.defineStream('Measure', {\n messages: [Schema.Never],\n args: {\n /** Each target by name, as a selector within the element: `{ selected: '[aria-selected=\"true\"]' }`. */\n targets: Schema.Record(Schema.String, Schema.String),\n },\n execute: ({ element, targets }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const container = element as HTMLElement\n const names = Object.keys(targets)\n let watched: ReadonlyArray<Element> = []\n // The element each target was last measured on, to tell a new mark from a moved layout.\n const last = new Map<string, Element>()\n let frame: number | undefined\n // Whether a transition or an animation may be moving something, until one frame finds none.\n let animating = false\n\n const measure = () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n frame = undefined\n const box = container.getBoundingClientRect()\n const found: Array<Element> = []\n for (const name of names) {\n const property = measured(name)\n const target = container.querySelector(targets[name]!)\n if (target === null) {\n container.style.setProperty(property.display, 'none')\n continue\n }\n found.push(target)\n const previous = last.get(name)\n last.set(name, target)\n const rect = target.getBoundingClientRect()\n // Relative to the scroll box: where the content is, not where the viewport shows it.\n const x = rect.left - box.left - container.clientLeft + container.scrollLeft\n const y = rect.top - box.top - container.clientTop + container.scrollTop\n container.style.setProperty(property.x, `${x}px`)\n container.style.setProperty(property.y, `${y}px`)\n container.style.setProperty(property.w, `${rect.width}px`)\n container.style.setProperty(property.h, `${rect.height}px`)\n container.style.setProperty(property.display, 'block')\n container.style.setProperty(\n property.moving,\n previous === undefined || previous === target ? '0' : '1',\n )\n }\n // A measured element that changes size, as an image loading does, is measured again.\n if (found.length !== watched.length || found.some((each, at) => each !== watched[at])) {\n for (const each of watched) sizes.unobserve(each)\n for (const each of found) sizes.observe(each)\n watched = found\n }\n if (animating) {\n // Asked each frame rather than counted: an element removed mid-transition ends none.\n animating = container\n .getAnimations({ subtree: true })\n .some(animation => animation.playState === 'running')\n if (animating) soon()\n }\n }\n const soon = () => {\n if (frame === undefined) frame = requestAnimationFrame(measure)\n }\n const moving = () => {\n animating = true\n soon()\n }\n\n // A change is measured as its records arrive, before the frame it is drawn in is\n // painted, so a box never shows one frame on the element it has left.\n const changes = new MutationObserver(measure)\n // Made, and the fonts listened to, before anything observes: where one is\n // missing (jsdom has neither a ResizeObserver nor `document.fonts`), the Mount\n // fails with nothing attached to call `measure`. A size is measured as it is\n // observed, after layout and before paint: a frame later, a popup whose width\n // settled as it opened showed its marker at the old width, past its edge.\n const sizes = new ResizeObserver(measure)\n document.fonts.addEventListener('loadingdone', soon)\n // Its own properties change the container's style too, but writing the same\n // values again records nothing, so a measure that changed nothing rests.\n changes.observe(container, { subtree: true, childList: true, attributes: true })\n sizes.observe(container)\n container.addEventListener('scroll', soon, { passive: true })\n window.addEventListener('resize', soon)\n // `load` does not bubble, so it is caught on the way down.\n container.addEventListener('load', soon, { capture: true })\n container.addEventListener('transitionrun', moving)\n container.addEventListener('animationstart', moving)\n measure()\n return () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n changes.disconnect()\n sizes.disconnect()\n container.removeEventListener('scroll', soon)\n window.removeEventListener('resize', soon)\n container.removeEventListener('load', soon, { capture: true })\n document.fonts.removeEventListener('loadingdone', soon)\n container.removeEventListener('transitionrun', moving)\n container.removeEventListener('animationstart', moving)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","/**\n * Where the window is scrolled, across an application's own navigations, as\n * a stream. Left to itself, a browser keeps the scroll of the entry it\n * leaves when a link pushes a new one, and on Back restores the old offset\n * before the application has drawn the entry it returns to, so the offset is\n * clamped to a page still loading. Here a pushed entry starts at the top,\n * and Back, Forward or a reload return where that entry was, once the page\n * is tall enough to hold it.\n *\n * Three rules, each found the slow way:\n *\n * 1. The offset is taken when the reader acts. The next screen is drawn\n * before a Navigate Command pushes the address, so by the time the URL\n * changes the window is already clamped to the new, shorter page. The\n * scroll is recorded at the reader's click or key (capture phase), and at\n * the start of Back and Forward, which begin in the browser before\n * anything is drawn.\n * 2. A restore holds its place while the next screen settles. A restore made\n * when the entry changes is undone by the loading state drawn right after\n * it, so the target is held on each frame for a moment, until the reader\n * scrolls, touches or types, or another navigation starts.\n * 3. Entries are keyed by the Navigation API's entry key, which a reload and\n * a full navigation keep; offsets rest in `sessionStorage`, so Back into\n * another document restores too. Where the browser has no Navigation API\n * the stream attaches nothing and leaves the browser's own behaviour\n * alone.\n *\n * Lift with `Subscription.persistentEntry`; the stream sends no Messages. Only\n * the window scrolls: a nested container is the route graph's to know, when\n * `Site.transition` arrives.\n */\nimport { Effect, Option, Stream } from 'effect'\n\n/** How `keepScroll` remembers and restores each history entry's offset. */\nexport interface KeepScrollOptions {\n /** The `sessionStorage` key holding entry offsets. Default `'foldkit:scroll'`. */\n readonly storageKey?: string | undefined\n /** Entries remembered at most: the oldest are forgotten first. Default 50. */\n readonly kept?: number | undefined\n /**\n * How long a restore holds its place while the next screen settles, in\n * milliseconds. Default 2000.\n */\n readonly patience?: number | undefined\n}\n\nconst navigationTypeOf = (event: Event): Option.Option<unknown> =>\n 'navigationType' in event ? Option.some(event.navigationType) : Option.none()\n\nconst readSaved = (storageKey: string): Map<string, number> => {\n try {\n const stored: unknown = JSON.parse(sessionStorage.getItem(storageKey) ?? '[]')\n return new Map(\n Array.isArray(stored)\n ? stored.filter(\n (pair): pair is [string, number] =>\n Array.isArray(pair) && typeof pair[0] === 'string' && typeof pair[1] === 'number',\n )\n : [],\n )\n } catch {\n // Storage blocked, or something else wrote the key: nothing is remembered.\n return new Map()\n }\n}\n\n/** Starts keeping the scroll; the release undoes everything it installed. */\nconst attach = (storageKey: string, kept: number, patience: number): (() => void) => {\n // TypeScript's DOM library declares it on every window; a browser without\n // the Navigation API has none.\n const navigation: Navigation | undefined = window.navigation\n if (navigation === undefined) return () => {}\n const restoration = window.history.scrollRestoration\n window.history.scrollRestoration = 'manual'\n const saved = readSaved(storageKey)\n const detaches: Array<() => void> = []\n const on = (target: EventTarget, type: string, listener: EventListener, capture?: boolean) => {\n target.addEventListener(type, listener, capture)\n detaches.push(() => target.removeEventListener(type, listener, capture))\n }\n const keyOf = () =>\n Option.fromNullOr(navigation.currentEntry).pipe(Option.map(entry => entry.key))\n /** Where the current entry was left, if it has been. */\n const savedHere = () => Option.flatMap(keyOf(), key => Option.fromUndefinedOr(saved.get(key)))\n const remember = () => {\n const key = keyOf()\n if (Option.isNone(key)) return\n // Moved to the end, so it is the last to be forgotten.\n saved.delete(key.value)\n saved.set(key.value, window.scrollY)\n for (const old of saved.keys()) {\n if (saved.size <= kept) break\n saved.delete(old)\n }\n }\n\n let settling = new AbortController()\n /**\n * Holds the window at `top` while the next screen settles, whenever the page\n * can hold it, until the reader scrolls, touches or types, or another\n * navigation starts.\n */\n const settle = (top: number) => {\n settling.abort()\n settling = new AbortController()\n const { signal } = settling\n for (const input of ['wheel', 'touchstart', 'keydown', 'pointerdown'])\n window.addEventListener(input, () => settling.abort(), { passive: true, signal })\n const until = performance.now() + patience\n const step = () => {\n if (signal.aborted) return\n const room = document.documentElement.scrollHeight - window.innerHeight\n if (room >= top && Math.round(window.scrollY) !== top)\n window.scrollTo({ top, behavior: 'instant' })\n if (performance.now() < until) requestAnimationFrame(step)\n else settling.abort()\n }\n step()\n }\n\n // Remembered where the reader acts, before the application does: by the time\n // it pushes an address it has drawn the next screen, and the window is\n // already clamped to it. Back and Forward start in the browser, before\n // anything is drawn, so they are remembered as they begin.\n const acted = () => remember()\n for (const input of ['click', 'keydown']) on(window, input, acted, true)\n const traversing = (event: Event) => {\n if (Option.contains(navigationTypeOf(event), 'traverse')) remember()\n }\n on(navigation, 'navigate', traversing)\n const changed = (event: Event) => {\n const type = navigationTypeOf(event)\n if (Option.contains(type, 'push')) settle(0)\n else if (Option.contains(type, 'traverse')) settle(Option.getOrElse(savedHere(), () => 0))\n // A replace is the same entry, narrowed or selected in place: it stays where it is.\n }\n on(navigation, 'currententrychange', changed)\n const hidden = () => {\n remember()\n try {\n sessionStorage.setItem(storageKey, JSON.stringify([...saved]))\n } catch {\n // Storage blocked: the next document starts at the top.\n }\n }\n on(window, 'pagehide', hidden)\n // A reload, or Back into this document from another: where this entry was.\n const here = savedHere()\n if (Option.isSome(here)) settle(here.value)\n return () => {\n settling.abort()\n for (const detach of detaches) detach()\n window.history.scrollRestoration = restoration\n }\n}\n\n/**\n * Keeps the window's scroll across same-document navigations: a pushed entry\n * starts at the top, and Back, Forward or a reload return where that entry\n * was. Without a window the stream is empty instead of throwing. Lift with\n * `Subscription.persistentEntry`; the stream sends no Messages.\n */\nexport const keepScroll = (options: KeepScrollOptions = {}): Stream.Stream<never> => {\n if (typeof window === 'undefined') return Stream.empty\n const storageKey = options.storageKey ?? 'foldkit:scroll'\n const kept = options.kept ?? 50\n const patience = options.patience ?? 2000\n return Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => attach(storageKey, kept, patience)),\n detach => Effect.sync(detach),\n ),\n )\n}\n","import { Option, Stream } from 'effect'\nimport * as Dom from 'foldkit/dom'\nimport { fromString, toString as urlToString, type Url } from 'foldkit/url'\n\n/**\n * The address of the link a reader points at or tabs to, on the page's own\n * origin: where they may go next, for a `Data.preload` before they go. Each\n * link once while they stay on it, since crossing its text sends one event\n * per element inside it. Without a document the stream is empty. Lift with\n * `Subscription.persistentEntry`, mapping each address to a Message.\n */\nexport const pointedLinks = (): Stream.Stream<Url> => {\n if (typeof document === 'undefined') return Stream.empty\n const linkOf = (event: Event): Option.Option<Url> => {\n const link = event.target instanceof Element ? event.target.closest('a[href]') : null\n return link instanceof HTMLAnchorElement && link.origin === window.location.origin\n ? fromString(link.href)\n : Option.none()\n }\n return Stream.merge(\n Dom.streamFromEventFilterMap({\n target: document,\n type: 'pointerover',\n filterMapEvent: linkOf,\n }),\n Dom.streamFromEventFilterMap({ target: document, type: 'focusin', filterMapEvent: linkOf }),\n ).pipe(Stream.changesWith((a, b) => urlToString(a) === urlToString(b)))\n}\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The custom properties `FluidHover` writes on its container for a highlight named `name`. */\nexport const fluidHovered = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n /** `1` while an item is highlighted, `0` once the pointer and focus have left. */\n shown: `--fk-${name}-shown`,\n /**\n * `0` for the frame the highlight appears in, then `1`: a highlight's\n * movement scales its duration by it, so it appears on its item rather\n * than sliding in from where it last was.\n */\n moving: `--fk-${name}-moving`,\n }) as const\n\n/**\n * The attribute `FluidHover` sets on its container, to the highlight's name,\n * while it runs: a stylist draws the highlight, and drops each item's own\n * hover, only under it.\n */\nexport const FLUID_HOVER_ATTRIBUTE = 'data-fluid-hover'\n\n/** The attribute that names, inside an item, the control a press in a gap reaches. */\nexport const FLUID_PRESS_ATTRIBUTE = 'data-fluid-press'\n\n/** The attribute on the item the highlight is shown on, for what CSS draws beside it. */\nexport const FLUID_LIT_ATTRIBUTE = 'data-fluid-lit'\n\nconst Axis = Schema.Literals(['x', 'y', 'xy'])\nexport type FluidAxis = typeof Axis.Type\n\n/** How far a point is from a rectangle along each axis: zero inside it. */\nconst gap = (low: number, high: number, at: number) => Math.max(low - at, 0, at - high)\n\n// On one axis the other only breaks ties, so a list's highlight never leaves\n// the row level with the pointer for a nearer edge of the next column.\nconst away: Record<FluidAxis, (dx: number, dy: number) => number> = {\n x: (dx, dy) => dx * 1e6 + dy,\n y: (dx, dy) => dy * 1e6 + dx,\n xy: Math.hypot,\n}\n\nconst distance = (rect: DOMRect, x: number, y: number, axis: FluidAxis) =>\n away[axis](gap(rect.left, rect.right, x), gap(rect.top, rect.bottom, y))\n\nconst isDisabled = (item: Element) =>\n item.matches('[aria-disabled=\"true\"], [data-disabled]:not([data-disabled=\"false\"]), :disabled')\n\n/**\n * One highlight that follows the pointer across a container's items, as a\n * Mount, with no Message and no Model: which item the pointer is nearest is\n * presentation, known to the DOM and to no transition.\n *\n * The item nearest the pointer is the one highlighted, so the pointer in a gap\n * between two items still points at one, and the highlight moves from item to\n * item instead of blinking off between them. On the `y` axis nearness is read\n * vertically (a list), on `x` horizontally (a strip), on `xy` both (a grid). A\n * disabled item (`aria-disabled=\"true\"`, `data-disabled`, `:disabled`) is never\n * highlighted. An item reached by the keyboard (`:focus-visible`) is\n * highlighted too, and with `focused`, the item that selector finds from a\n * focused element that is no item (a tree's row, from its focused\n * `treeitem`, which also holds the rows beneath it); a touch highlights\n * nothing, since there is no pointer to\n * follow before the press.\n *\n * The container gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, relative\n * to its scroll box like `Measure`'s, and `-shown` and `-moving` (see\n * `fluidHovered`); a view draws the highlight as an absolutely placed child\n * that reads them. With `gapClick`, a click in a gap presses the highlighted\n * item: its descendant marked `data-fluid-press`, or the item itself; with\n * `gapReach` too, only a click within that many pixels of it, as a grid of\n * cards with wide gutters wants (Fluid Functionalism's uses 16). A popup\n * measured before it has a layout box keeps its last complete place, and\n * tries again for three frames, rather than drawing the highlight at zero.\n * The item the highlight is shown on carries `data-fluid-lit`, so a style\n * can change what sits beside it (a table hides the lines around the lit\n * row).\n *\n * `follows` names the item the highlight sits on while the pointer is not\n * moving it: a menu marks the row its keys reach (`[data-active]`), and the\n * highlight goes there whenever that mark moves, so the keys and the pointer\n * light the same one. `from` names the item a fresh highlight grows out of,\n * as a tab's hover leaves the chosen tab. A highlight always fades where it\n * is: once the pointer leaves, nothing should move. It stays only for an item\n * the keyboard reached (`:focus-visible`), not one a click focused.\n */\nexport const FluidHover = Mount.defineStream('FluidHover', {\n messages: [Schema.Never],\n args: {\n /** The highlight's name, which names the custom properties. */\n name: Schema.String,\n /** The selector of an item within the container. */\n item: Schema.String,\n axis: Axis,\n gapClick: Schema.Boolean,\n /** How far from the highlighted item, in pixels, a click in a gap still presses it. */\n gapReach: Schema.optional(Schema.Number),\n /** The selector of the item the highlight sits on while the pointer is not moving it. */\n follows: Schema.optional(Schema.String),\n /** The selector of the item a fresh highlight grows out of. */\n from: Schema.optional(Schema.String),\n /** The selector, run from a focused element outside any item, of the item it lights. */\n focused: Schema.optional(Schema.String),\n },\n execute: ({ element, name, item: selector, axis, gapClick, gapReach, follows, from, focused }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const container = element as HTMLElement\n const property = fluidHovered(name)\n let active: Element | null = null\n let followed: Element | null = null\n let pointer: { readonly x: number; readonly y: number } | null = null\n let frame: number | undefined\n\n const origin = () => (from === undefined ? null : container.querySelector(from))\n let retries = 0\n const place = (at: Element | null = active) => {\n if (at === null) return\n const box = container.getBoundingClientRect()\n const rect = at.getBoundingClientRect()\n // No layout box yet (a popup still opening): keep the last place and look again.\n if (rect.width === 0 && rect.height === 0) {\n if (retries < 3) {\n retries += 1\n requestAnimationFrame(() => place(at))\n }\n return\n }\n retries = 0\n const x = rect.left - box.left - container.clientLeft + container.scrollLeft\n const y = rect.top - box.top - container.clientTop + container.scrollTop\n container.style.setProperty(property.x, `${x}px`)\n container.style.setProperty(property.y, `${y}px`)\n container.style.setProperty(property.w, `${rect.width}px`)\n container.style.setProperty(property.h, `${rect.height}px`)\n }\n /** Marks `item` as the lit one, and nothing else. */\n const light = (item: Element | null) => {\n container\n .querySelectorAll(`[${FLUID_LIT_ATTRIBUTE}]`)\n .forEach(each => each !== item && each.removeAttribute(FLUID_LIT_ATTRIBUTE))\n item?.setAttribute(FLUID_LIT_ATTRIBUTE, '')\n }\n const show = (next: Element) => {\n const appearing = container.style.getPropertyValue(property.shown) !== '1'\n active = next\n light(next)\n const grows = appearing ? origin() : null\n if (appearing) container.style.setProperty(property.moving, '0')\n if (grows === null) {\n place()\n container.style.setProperty(property.shown, '1')\n } else {\n // Drawn first where it grows from, then moved: it travels out of that item.\n place(grows)\n requestAnimationFrame(() => {\n if (active !== next) return\n place()\n container.style.setProperty(property.shown, '1')\n })\n }\n if (appearing) {\n // The frame after: by then the jump to the item has been drawn without moving.\n requestAnimationFrame(() => container.style.setProperty(property.moving, '1'))\n }\n }\n const hide = () => {\n container.style.setProperty(property.shown, '0')\n light(null)\n }\n /** Whether the keyboard has an item focused, which the highlight then stays on. */\n const keyed = () => {\n const focused = document.activeElement\n return (\n focused !== null && container.contains(focused) && focused.matches(':focus-visible')\n )\n }\n const nearest = (x: number, y: number) => {\n let best: Element | null = null\n let bestDistance = Infinity\n for (const each of Array.from(container.querySelectorAll(selector))) {\n if (isDisabled(each)) continue\n const far = distance(each.getBoundingClientRect(), x, y, axis)\n if (far < bestDistance) {\n best = each\n bestDistance = far\n }\n }\n return best\n }\n const follow = () => {\n frame = undefined\n if (pointer === null) return\n const next = nearest(pointer.x, pointer.y)\n if (next === null) hide()\n else if (next !== active || container.style.getPropertyValue(property.shown) !== '1')\n show(next)\n }\n\n const move = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n pointer = { x: event.clientX, y: event.clientY }\n if (frame === undefined) frame = requestAnimationFrame(follow)\n }\n const leave = () => {\n pointer = null\n if (!keyed()) hide()\n }\n const focus = (event: FocusEvent) => {\n if (!(event.target instanceof Element) || !event.target.matches(':focus-visible')) {\n return\n }\n const owner =\n event.target.closest(selector) ??\n (focused === undefined ? null : event.target.querySelector(focused))\n if (owner !== null && container.contains(owner) && !isDisabled(owner)) show(owner)\n }\n const blur = (event: FocusEvent) => {\n const to = event.relatedTarget\n if (pointer === null && !(to instanceof Node && container.contains(to))) hide()\n }\n const click = (event: MouseEvent) => {\n if (!gapClick || active === null) return\n if (container.style.getPropertyValue(property.shown) !== '1') return\n const target = event.target\n if (!(target instanceof Element) || target.closest(selector) !== null) return\n const reach = distance(\n active.getBoundingClientRect(),\n event.clientX,\n event.clientY,\n 'xy',\n )\n if (gapReach !== undefined && reach > gapReach) return\n const press = active.querySelector(`[${FLUID_PRESS_ATTRIBUTE}]`) ?? active\n if (press instanceof HTMLElement) press.click()\n }\n const soon = () => {\n if (active !== null) requestAnimationFrame(() => place())\n }\n /** The marked item moved: the highlight goes with it, or fades if it is gone. */\n const marked = () => {\n if (follows === undefined) return\n const next = container.querySelector(follows)\n if (next === followed) return\n followed = next\n if (next !== null && !isDisabled(next)) show(next)\n else if (pointer === null && !keyed()) hide()\n }\n\n // Where there is no layout (jsdom has no ResizeObserver) nothing moves to\n // follow, and a view drawn there is no worse for the highlight's absence.\n const sizes = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(soon)\n const marks = follows === undefined ? undefined : new MutationObserver(marked)\n sizes?.observe(container)\n marks?.observe(container, { subtree: true, childList: true, attributes: true })\n container.addEventListener('pointermove', move, { passive: true })\n container.addEventListener('pointerleave', leave)\n container.addEventListener('focusin', focus)\n container.addEventListener('focusout', blur)\n container.addEventListener('click', click)\n container.addEventListener('scroll', soon, { passive: true })\n window.addEventListener('resize', soon)\n container.style.setProperty(property.shown, '0')\n container.setAttribute(FLUID_HOVER_ATTRIBUTE, name)\n marked()\n return () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n sizes?.disconnect()\n marks?.disconnect()\n container.removeAttribute(FLUID_HOVER_ATTRIBUTE)\n light(null)\n container.removeEventListener('pointermove', move)\n container.removeEventListener('pointerleave', leave)\n container.removeEventListener('focusin', focus)\n container.removeEventListener('focusout', blur)\n container.removeEventListener('click', click)\n container.removeEventListener('scroll', soon)\n window.removeEventListener('resize', soon)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * The custom property `KeyboardInset` writes on its element: how much of the layout\n * viewport's bottom the on-screen keyboard (or anything else the visual viewport leaves\n * out) covers, in pixels.\n */\nexport const KEYBOARD_INSET = '--fk-keyboard-inset'\n\n/**\n * The part of the layout viewport's height below the visual viewport: what the on-screen\n * keyboard covers. Rounded down, since a fraction of a pixel of zoom is no keyboard.\n */\nexport const keyboardInset = (view: {\n readonly innerHeight: number\n readonly visualViewport: { readonly height: number; readonly offsetTop: number } | null\n}): number =>\n view.visualViewport === null\n ? 0\n : Math.max(\n 0,\n Math.floor(view.innerHeight - view.visualViewport.height - view.visualViewport.offsetTop),\n )\n\n/**\n * The on-screen keyboard's height as a Mount, with no Message and no Model: where it is\n * is the browser's. iOS Safari, and Chrome on Android unless the page asks otherwise,\n * leave the layout viewport as it is when the keyboard opens, so a panel fixed to the\n * screen keeps its height and its bottom under the keys. This writes `KEYBOARD_INSET` on\n * the element, from the visual viewport's size and scroll, for a style to pad or shrink by\n * (`var(--fk-keyboard-inset, 0px)`), and removes it when the element goes. Where there is\n * no visual viewport it writes nothing.\n */\nexport const KeyboardInset = Mount.defineStream('KeyboardInset', {\n messages: [Schema.Never],\n args: {},\n execute: ({ element }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const view = element.ownerDocument.defaultView\n const viewport = view?.visualViewport\n if (\n !(element instanceof HTMLElement) ||\n view === null ||\n view === undefined ||\n viewport === null ||\n viewport === undefined\n ) {\n return () => {}\n }\n const target = element\n const measure = () => target.style.setProperty(KEYBOARD_INSET, `${keyboardInset(view)}px`)\n measure()\n viewport.addEventListener('resize', measure)\n viewport.addEventListener('scroll', measure)\n return () => {\n viewport.removeEventListener('resize', measure)\n viewport.removeEventListener('scroll', measure)\n target.style.removeProperty(KEYBOARD_INSET)\n }\n }),\n release => Effect.sync(release),\n ),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * The attribute that marks a bar beside a scroller `ScrollBars` runs on, set\n * to the axis it shows: `block` (the up-and-down bar) or `inline`.\n */\nexport const SCROLL_BAR_ATTRIBUTE = 'data-scroll-bar'\n\n/**\n * The attribute `ScrollBars` sets on its scroller while it draws the bars, so a\n * style hides the native bar only then: with no Mount running (a coarse\n * pointer, a page not yet hydrated) the browser's bar stays.\n */\nexport const SCROLL_OVERLAID_ATTRIBUTE = 'data-scroll-overlaid'\n\n/**\n * The custom properties `ScrollBars` writes on each bar, in pixels, for its\n * thumb to read: how far along the bar the thumb starts, and how long it is.\n * Physical: an inline bar's offset is from its left edge in either direction.\n */\nexport const scrollThumb = {\n offset: '--fk-scroll-thumb-offset',\n size: '--fk-scroll-thumb-size',\n} as const\n\n/** The shortest a thumb is drawn, however long the content, so it stays a target. */\nconst SHORTEST = 20\n\nconst FINE_POINTER = '(hover: hover) and (pointer: fine)'\n\ntype Axis = 'block' | 'inline'\n\n/**\n * An overlay scrollbar as a Mount, with no Message and no Model: where a\n * scroller is scrolled is the browser's, and the bar only shows it.\n *\n * It runs on the scroller (or on an element holding it, named by `scroller`,\n * when the scroller carries another Mount) and drives the bars drawn beside\n * it: the scroller's parent's children marked `data-scroll-bar` (`block` or\n * `inline`), which a style lays over the scroller's edge. Each bar gets `data-scrollable` while its axis has\n * more to scroll, `data-shown` while the scroller scrolls or the pointer moves\n * over it, until `idle` milliseconds pass with neither (or longer, while the\n * pointer rests on a bar), and `data-dragging` while its thumb is dragged; and\n * `--fk-scroll-thumb-offset` and `-size` (see `scrollThumb`). Pressing a bar\n * off its thumb moves the thumb there, then drags it.\n *\n * It does nothing where the primary pointer is coarse or cannot hover, decided\n * when it mounts: touch keeps the browser's bar and its physics. Otherwise the\n * scroller gets `data-scroll-overlaid`, for a style to hide the native bar.\n * How the bar looks, rests, widens and fades is the style's.\n */\nexport const ScrollBars = Mount.defineStream('ScrollBars', {\n messages: [Schema.Never],\n args: {\n /** How long, in milliseconds, the bars stay after the last scroll or move. Default 600. */\n idle: Schema.optional(Schema.Number),\n /**\n * The scroller, as a selector within the element, when it cannot hold this\n * Mount itself (another component's, with a Mount of its own); looked for\n * once, when it mounts. Default: the element is the scroller.\n */\n scroller: Schema.optional(Schema.String),\n },\n execute: ({ element, idle = 600, scroller: within }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n if (typeof matchMedia !== 'function' || !matchMedia(FINE_POINTER).matches) {\n return () => {}\n }\n const found = within === undefined ? element : element.querySelector(within)\n if (!(found instanceof HTMLElement)) return () => {}\n const scroller = found\n const area = scroller.parentElement\n if (area === null) return () => {}\n\n const isBar = (child: Element): child is HTMLElement =>\n child instanceof HTMLElement && child.hasAttribute(SCROLL_BAR_ATTRIBUTE)\n /** Looked for at each use, so a redraw that replaced a bar is followed. */\n const bars = () => Array.from(area.children).filter(isBar)\n const axisOf = (bar: HTMLElement): Axis =>\n bar.getAttribute(SCROLL_BAR_ATTRIBUTE) === 'inline' ? 'inline' : 'block'\n\n /** The scroller along one axis, with the start measured from the top or the left. */\n const extent = (axis: Axis) => {\n if (axis === 'block') {\n return {\n view: scroller.clientHeight,\n content: scroller.scrollHeight,\n start: scroller.scrollTop,\n }\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n // A right-to-left scroller counts from 0 at the right down to minus its room.\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n return {\n view: scroller.clientWidth,\n content: scroller.scrollWidth,\n start: rtl ? room + scroller.scrollLeft : scroller.scrollLeft,\n }\n }\n const scrollTo = (axis: Axis, start: number) => {\n if (axis === 'block') {\n scroller.scrollTop = start\n return\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n scroller.scrollLeft = rtl ? start - room : start\n }\n const trackOf = (bar: HTMLElement, axis: Axis) =>\n axis === 'block' ? bar.clientHeight : bar.clientWidth\n /** Where the thumb is along its bar, or nothing while the axis has nothing to scroll. */\n const thumbOf = (bar: HTMLElement, axis: Axis) => {\n const { view, content, start } = extent(axis)\n const track = trackOf(bar, axis)\n if (content - view < 1 || track <= 0) return null\n const size = Math.min(track, Math.max(SHORTEST, (track * view) / content))\n const offset = ((track - size) * start) / (content - view)\n return { track, size, offset, room: content - view }\n }\n const set = (bar: HTMLElement, name: string, value: string) => {\n if (bar.style.getPropertyValue(name) !== value) bar.style.setProperty(name, value)\n }\n const mark = (bar: HTMLElement, name: string, on: boolean) => {\n if (bar.hasAttribute(name) !== on) bar.toggleAttribute(name, on)\n }\n\n let frame: number | undefined\n const update = () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n frame = undefined\n for (const bar of bars()) {\n const axis = axisOf(bar)\n const { view, content } = extent(axis)\n // Marked first: a style draws no bar until it is, so it has no length before.\n mark(bar, 'data-scrollable', content - view >= 1)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) continue\n set(bar, scrollThumb.offset, `${thumb.offset}px`)\n set(bar, scrollThumb.size, `${thumb.size}px`)\n }\n }\n const soon = () => {\n if (frame === undefined) frame = requestAnimationFrame(update)\n }\n\n let hiding: ReturnType<typeof setTimeout> | undefined\n let resting: HTMLElement | null = null\n /** Ends the drag under way, if one is. */\n let dragging: (() => void) | null = null\n const hide = () => {\n hiding = undefined\n // A bar the pointer rests on, or one being dragged, stays until it is left.\n if (resting !== null || dragging !== null) return\n for (const bar of bars()) mark(bar, 'data-shown', false)\n }\n const show = () => {\n for (const bar of bars()) mark(bar, 'data-shown', true)\n if (hiding !== undefined) clearTimeout(hiding)\n hiding = setTimeout(hide, idle)\n }\n\n const scrolled = () => {\n update()\n show()\n }\n // Listened to only while the pointer is over the area.\n const moved = (event: PointerEvent) => {\n if (event.pointerType !== 'touch') show()\n }\n const entered = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n area.addEventListener('pointermove', moved, { passive: true })\n show()\n }\n const left = () => {\n area.removeEventListener('pointermove', moved)\n resting = null\n // A hide that came while the pointer rested on a bar waited for this.\n if (hiding === undefined) hiding = setTimeout(hide, idle)\n }\n const over = (event: PointerEvent) => {\n const target = event.target\n resting =\n target instanceof Element ? (bars().find(bar => bar.contains(target)) ?? null) : null\n }\n\n const pressed = (event: PointerEvent) => {\n if (event.button !== 0 || event.pointerType === 'touch' || dragging !== null) return\n const target = event.target\n if (!(target instanceof Element)) return\n const bar = bars().find(each => each.contains(target))\n if (bar === undefined) return\n const axis = axisOf(bar)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) return\n // The bar takes the press: no text selected, no focus moved off the scroller.\n event.preventDefault()\n const along = (at: PointerEvent) => {\n const box = bar.getBoundingClientRect()\n return axis === 'block'\n ? at.clientY - box.top - bar.clientTop\n : at.clientX - box.left - bar.clientLeft\n }\n const at = along(event)\n const onThumb = at >= thumb.offset && at <= thumb.offset + thumb.size\n // Held where it was taken, or by its middle when the press jumped it there.\n const grab = onThumb ? at - thumb.offset : thumb.size / 2\n const follow = (to: PointerEvent) => {\n const current = thumbOf(bar, axis)\n if (current === null) return\n const offset = Math.min(Math.max(along(to) - grab, 0), current.track - current.size)\n scrollTo(axis, (offset / (current.track - current.size)) * current.room)\n }\n const id = event.pointerId\n const move = (to: PointerEvent) => {\n if (to.pointerId === id) follow(to)\n }\n const end = (to: PointerEvent) => {\n if (to.pointerId === id) stop()\n }\n // On the document, for the drag alone: the pointer leaves the bar as it drags.\n const owner = bar.ownerDocument\n const stop = () => {\n owner.removeEventListener('pointermove', move)\n owner.removeEventListener('pointerup', end)\n owner.removeEventListener('pointercancel', end)\n mark(bar, 'data-dragging', false)\n dragging = null\n show()\n }\n owner.addEventListener('pointermove', move)\n owner.addEventListener('pointerup', end)\n owner.addEventListener('pointercancel', end)\n mark(bar, 'data-dragging', true)\n dragging = stop\n show()\n if (!onThumb) follow(event)\n }\n\n // Both made before anything observes: where one is missing, the Mount\n // fails with nothing attached.\n const sizes = new ResizeObserver(soon)\n // The content's size moves the thumb as much as the scroller's, so each\n // child of the scroller is watched, and each bar for its track. Only what\n // a change added or removed is watched or let go: a virtual list swaps\n // a row or two each frame it scrolls, out of many.\n const changes = new MutationObserver(records => {\n for (const record of records) {\n for (const node of Array.from(record.removedNodes)) {\n if (node instanceof Element) sizes.unobserve(node)\n }\n for (const node of Array.from(record.addedNodes)) {\n if (node instanceof Element && (record.target === scroller || isBar(node))) {\n sizes.observe(node)\n }\n }\n }\n soon()\n })\n sizes.observe(scroller)\n for (const child of Array.from(scroller.children)) sizes.observe(child)\n for (const bar of bars()) sizes.observe(bar)\n changes.observe(scroller, { childList: true })\n changes.observe(area, { childList: true })\n scroller.addEventListener('scroll', scrolled, { passive: true })\n area.addEventListener('pointerenter', entered)\n area.addEventListener('pointerleave', left)\n area.addEventListener('pointerover', over)\n area.addEventListener('pointerdown', pressed)\n scroller.setAttribute(SCROLL_OVERLAID_ATTRIBUTE, '')\n update()\n return () => {\n // Ended first: ending a drag shows the bars, which sets a hide to clear.\n dragging?.()\n if (frame !== undefined) cancelAnimationFrame(frame)\n if (hiding !== undefined) clearTimeout(hiding)\n sizes.disconnect()\n changes.disconnect()\n scroller.removeEventListener('scroll', scrolled)\n area.removeEventListener('pointerenter', entered)\n area.removeEventListener('pointerleave', left)\n area.removeEventListener('pointerover', over)\n area.removeEventListener('pointerdown', pressed)\n area.removeEventListener('pointermove', moved)\n scroller.removeAttribute(SCROLL_OVERLAID_ATTRIBUTE)\n for (const bar of bars()) {\n for (const name of ['data-scrollable', 'data-shown', 'data-dragging'])\n bar.removeAttribute(name)\n bar.style.removeProperty(scrollThumb.offset)\n bar.style.removeProperty(scrollThumb.size)\n }\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const SwipeStarted = Schema.TaggedStruct('SwipeStarted', {\n pointerId: Schema.Number,\n pointerType: Schema.String,\n /** The border box of what `measure` names (the element itself by default), as the swipe starts. */\n width: Schema.Number,\n height: Schema.Number,\n})\nexport type SwipeStarted = typeof SwipeStarted.Type\n\nexport const Swiped = Schema.TaggedStruct('Swiped', {\n pointerId: Schema.Number,\n /** From where the pointer went down, in CSS pixels. */\n deltaX: Schema.Number,\n deltaY: Schema.Number,\n})\nexport type Swiped = typeof Swiped.Type\n\nexport const SwipeEnded = Schema.TaggedStruct('SwipeEnded', {\n pointerId: Schema.Number,\n /** From where the pointer went down to where it came up, in CSS pixels. */\n deltaX: Schema.Number,\n deltaY: Schema.Number,\n /**\n * How fast the pointer was moving as it came up, in pixels a millisecond,\n * over the last `SWIPE_WINDOW` milliseconds: 0 when it rested there first.\n */\n velocityX: Schema.Number,\n velocityY: Schema.Number,\n /** `false` when the pointer was cancelled or capture was lost. */\n completed: Schema.Boolean,\n})\nexport type SwipeEnded = typeof SwipeEnded.Type\n\nexport type SwipeFact = SwipeStarted | Swiped | SwipeEnded\n\n/** How far back, in milliseconds, the release velocity looks. */\nexport const SWIPE_WINDOW = 100\n\ntype PointerLike = Event & {\n readonly pointerId?: number\n readonly button?: number\n readonly pointerType?: string\n readonly clientX?: number\n readonly clientY?: number\n}\n\ntype Capturing = Element & {\n setPointerCapture?: (pointerId: number) => void\n releasePointerCapture?: (pointerId: number) => void\n}\n\ninterface Sample {\n readonly at: number\n readonly x: number\n readonly y: number\n}\n\n/**\n * The velocity of the samples within `SWIPE_WINDOW` of the last: the way\n * from the oldest of them to the last over the time between. A pointer that\n * came to rest before the last sample has no recent way to measure, so 0.\n */\nexport const velocityOf = (samples: ReadonlyArray<Sample>): { x: number; y: number } => {\n const last = samples.at(-1)\n if (last === undefined) return { x: 0, y: 0 }\n const first = samples.find(sample => last.at - sample.at <= SWIPE_WINDOW) ?? last\n const elapsed = last.at - first.at\n return elapsed <= 0\n ? { x: 0, y: 0 }\n : { x: (last.x - first.x) / elapsed, y: (last.y - first.y) / elapsed }\n}\n\n/**\n * `Move` with the speed of its release, for a gesture that a flick ends\n * (a sheet dragged to dismiss, a card swiped away): a primary-button pointer\n * down (or, given a `slop`, its first move past it) captures the pointer,\n * each move reports the delta from where it was pressed, and up reports the\n * last delta with the velocity over the last `SWIPE_WINDOW` milliseconds, by\n * the events' own time stamps. Cancel or lost capture ends it incomplete.\n * The start reports the size of what is moved, so a distance can be read as\n * a share of it. What a delta or a speed means is the parent's `update`.\n * Capture is released with the Mount.\n */\nexport const Swipe = Mount.defineStream('Swipe', {\n messages: [SwipeStarted, Swiped, SwipeEnded],\n args: {\n /**\n * The nearest ancestor matching this selector is measured as the swipe\n * starts, for what the swipe moves (a sheet's panel, dragged by its\n * handle). Default: the element itself.\n */\n measure: Schema.optional(Schema.String),\n /**\n * How far, in pixels, a press must move before it is a swipe. Until\n * then nothing is captured or reported, so a press that stays put is\n * still a click on whatever is under it (a tab inside a drag grip).\n * Default 0: the press itself starts the swipe.\n */\n slop: Schema.optional(Schema.Number),\n },\n execute: ({ element, measure, slop = 0 }) =>\n Stream.callback<SwipeFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const target = element as Capturing\n let active: {\n readonly pointerId: number\n readonly pointerType: string\n samples: Array<Sample>\n started: boolean\n } | null = null\n const offer = (fact: SwipeFact) => Queue.offerUnsafe(queue, fact)\n const sampleOf = (event: PointerLike): Sample => ({\n at: event.timeStamp,\n x: event.clientX ?? 0,\n y: event.clientY ?? 0,\n })\n const end = (event: PointerLike, completed: boolean) => {\n const pointerId = event.pointerId ?? 0\n if (active === null || active.pointerId !== pointerId) return\n const { samples, started } = active\n active = null\n // A press that never moved past the slop was a click, not a swipe.\n if (!started) return\n try {\n target.releasePointerCapture?.(pointerId)\n } catch {\n // Capture may already be gone; the end is still reported.\n }\n // A lost capture or a cancel carries no place: the last move's stands.\n const last = completed ? sampleOf(event) : (samples.at(-1) ?? sampleOf(event))\n const all = completed ? [...samples, last] : samples\n const start = all[0] ?? last\n const velocity = completed ? velocityOf(all) : { x: 0, y: 0 }\n offer(\n SwipeEnded.make({\n pointerId,\n deltaX: last.x - start.x,\n deltaY: last.y - start.y,\n velocityX: velocity.x,\n velocityY: velocity.y,\n completed,\n }),\n )\n }\n // Capture, and report the size of what is moved.\n const begin = (pointer: NonNullable<typeof active>) => {\n pointer.started = true\n try {\n target.setPointerCapture?.(pointer.pointerId)\n } catch {\n // Without capture the move still reports while over the element.\n }\n const moved = measure === undefined ? element : (element.closest(measure) ?? element)\n const box = moved.getBoundingClientRect()\n offer(\n SwipeStarted.make({\n pointerId: pointer.pointerId,\n pointerType: pointer.pointerType,\n width: box.width,\n height: box.height,\n }),\n )\n }\n const listeners: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n [\n 'pointerdown',\n event => {\n const pointer = event as PointerLike\n if ((pointer.button ?? 0) !== 0 || active !== null) return\n active = {\n pointerId: pointer.pointerId ?? 0,\n pointerType: pointer.pointerType ?? 'mouse',\n samples: [sampleOf(pointer)],\n started: false,\n }\n if (slop <= 0) begin(active)\n },\n ],\n [\n 'pointermove',\n event => {\n const pointer = event as PointerLike\n const pointerId = pointer.pointerId ?? 0\n if (active === null || active.pointerId !== pointerId) return\n const sample = sampleOf(pointer)\n const start = active.samples[0] ?? sample\n if (!active.started) {\n if (Math.hypot(sample.x - start.x, sample.y - start.y) < slop) return\n begin(active)\n }\n // Only what the velocity can still read, and where it began.\n active.samples = [\n start,\n ...active.samples.slice(1).filter(each => sample.at - each.at <= SWIPE_WINDOW),\n sample,\n ]\n offer(\n Swiped.make({\n pointerId,\n deltaX: sample.x - start.x,\n deltaY: sample.y - start.y,\n }),\n )\n },\n ],\n ['pointerup', event => end(event as PointerLike, true)],\n ['pointercancel', event => end(event as PointerLike, false)],\n ['lostpointercapture', event => end(event as PointerLike, false)],\n ]\n for (const [type, listener] of listeners) element.addEventListener(type, listener)\n return { listeners, current: () => active }\n }),\n ({ listeners, current }) =>\n Effect.sync(() => {\n for (const [type, listener] of listeners) element.removeEventListener(type, listener)\n const pointer = current()\n if (pointer !== null) {\n try {\n ;(element as Capturing).releasePointerCapture?.(pointer.pointerId)\n } catch {\n // Already released.\n }\n }\n }),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const ScrollSettled = Schema.TaggedStruct('ScrollSettled', {\n /** The item whose start lies nearest the scroller's start, from 0. */\n index: Schema.Number,\n})\nexport type ScrollSettled = typeof ScrollSettled.Type\n\n/** How long a scroll must be still to count as settled, where `scrollend` is missing. */\nexport const SETTLE_QUIET = 120\n\n/**\n * Hears a scroller come to rest, as a Mount: after a swipe, a fling, a\n * trackpad or a scroll a Command made, it reports which of its items starts\n * nearest its own start (inside its `scroll-padding`), the start being the\n * right edge right to left. A snapping carousel reads it as the slide shown.\n *\n * At insert it first scrolls, at once, to item `start` (the Mount's args are\n * read only then, so this is where a redrawn or restored scroller begins),\n * and reports where it lies, since a scroller drawn already at rest sends no\n * `scrollend`. It listens for `scrollend` where the browser has it, and\n * otherwise for a scroll that is quiet for `SETTLE_QUIET` milliseconds.\n */\nexport const ScrollSettle = Mount.defineStream('ScrollSettle', {\n messages: [ScrollSettled],\n args: {\n /** Which children are the items; default every child. */\n item: Schema.optional(Schema.String),\n /** Default `inline`, the row a carousel scrolls along. */\n axis: Schema.optional(Schema.Literals(['inline', 'block'])),\n /** The item to scroll to at insert; default the first, which needs no scroll. */\n start: Schema.optional(Schema.Number),\n },\n execute: ({ element, item, axis = 'inline', start = 0 }) =>\n Stream.callback<ScrollSettled>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const items = () =>\n Array.from(\n item === undefined ? element.children : element.querySelectorAll(`:scope > ${item}`),\n )\n /** How far `child`'s start lies past the scroller's start, along the axis. */\n const offsetOf = (child: Element): number => {\n const style = getComputedStyle(element)\n const box = element.getBoundingClientRect()\n const own = child.getBoundingClientRect()\n if (axis === 'block') {\n return own.top - box.top - (parseFloat(style.scrollPaddingBlockStart) || 0)\n }\n const padding = parseFloat(style.scrollPaddingInlineStart) || 0\n return style.direction === 'rtl'\n ? box.right - padding - own.right\n : own.left - box.left - padding\n }\n const report = () => {\n let nearest = -1\n let distance = Infinity\n items().forEach((child, index) => {\n const away = Math.abs(offsetOf(child))\n if (away < distance) {\n nearest = index\n distance = away\n }\n })\n if (nearest >= 0) Queue.offerUnsafe(queue, ScrollSettled.make({ index: nearest }))\n }\n const first = items()[start]\n const before = element.scrollLeft + element.scrollTop\n if (start > 0 && first !== undefined) {\n const by = offsetOf(first)\n const rtl = axis === 'inline' && getComputedStyle(element).direction === 'rtl'\n // A larger `scrollLeft` moves the content toward the start either way, so right to\n // left the way to an item's start is the other sign. To a position, not by a\n // distance: a relative scroll stops at every `scroll-snap-stop: always` on the way.\n element.scrollTo(\n axis === 'block'\n ? { top: element.scrollTop + by, behavior: 'instant' }\n : { left: element.scrollLeft + (rtl ? -by : by), behavior: 'instant' },\n )\n }\n // A scroll just made reports itself when it ends; one that moved nothing never ends.\n if (element.scrollLeft + element.scrollTop === before) report()\n let quiet: ReturnType<typeof setTimeout> | undefined\n const hasEnd = 'onscrollend' in element\n const listener = hasEnd\n ? report\n : () => {\n clearTimeout(quiet)\n quiet = setTimeout(report, SETTLE_QUIET)\n }\n const type = hasEnd ? 'scrollend' : 'scroll'\n element.addEventListener(type, listener)\n return () => {\n clearTimeout(quiet)\n element.removeEventListener(type, listener)\n }\n }),\n detach => Effect.sync(detach),\n ),\n ),\n})\n","import { Effect, Option, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * A place in an element's padding box, in CSS pixels from its top left\n * corner, and the pointer's pressure there (0 to 1; a mouse reads 0.5 while\n * a button is down). A captured pointer can be outside the box, so `x` and\n * `y` can be negative or past its size.\n */\nexport const PointerPoint = Schema.Struct({\n x: Schema.Number,\n y: Schema.Number,\n pressure: Schema.Number,\n})\nexport type PointerPoint = typeof PointerPoint.Type\n\n/** The padding box's size at the event, in CSS pixels. */\nconst Size = { width: Schema.Number, height: Schema.Number }\n\nexport const PointerPressed = Schema.TaggedStruct('PointerPressed', {\n ...Size,\n point: PointerPoint,\n /** `mouse`, `pen` or `touch`, as the browser names it. */\n pointerType: Schema.String,\n})\nexport type PointerPressed = typeof PointerPressed.Type\n\nexport const PointerMoved = Schema.TaggedStruct('PointerMoved', {\n ...Size,\n /** Where the pointer is now. */\n point: PointerPoint,\n /**\n * Every place it passed since the last move, ending with `point`: the\n * browser's coalesced events, so a fast stroke keeps its curve. Just\n * `point` where the browser coalesces none.\n */\n points: Schema.Array(PointerPoint),\n})\nexport type PointerMoved = typeof PointerMoved.Type\n\nexport const PointerReleased = Schema.TaggedStruct('PointerReleased', {\n /** `false` when the pointer was cancelled, lost its capture, or pressed again unreleased. */\n completed: Schema.Boolean,\n})\nexport type PointerReleased = typeof PointerReleased.Type\n\nexport type PointerFact = PointerPressed | PointerMoved | PointerReleased\n\ninterface Sides {\n readonly top: number\n readonly right: number\n readonly bottom: number\n readonly left: number\n}\n\nexport interface Rect {\n readonly left: number\n readonly top: number\n readonly width: number\n readonly height: number\n}\n\n/**\n * The padding box of an element whose border box is `rect`: inside its\n * border, padding included. An absolutely positioned child (a thumb, a\n * stroke) is laid out against it, so a place read here is where that child\n * sits, whatever padding a stylist adds.\n */\nexport const paddingBoxOf = (layout: { readonly rect: Rect; readonly border: Sides }): Rect => {\n const { rect, border } = layout\n return {\n left: rect.left + border.left,\n top: rect.top + border.top,\n width: Math.max(0, rect.width - border.left - border.right),\n height: Math.max(0, rect.height - border.top - border.bottom),\n }\n}\n\nconst borderOf = (style: CSSStyleDeclaration): Sides => ({\n top: parseFloat(style.borderTopWidth),\n right: parseFloat(style.borderRightWidth),\n bottom: parseFloat(style.borderBottomWidth),\n left: parseFloat(style.borderLeftWidth),\n})\n\n/**\n * An element's padding box now, in the viewport, as `PointerPosition`\n * measures it: for a size kept beside its places, which a `ResizeObserver`'s\n * content box does not match once the element has padding. Read from the\n * bounding rectangle and the computed border, since `clientWidth` and\n * `clientLeft` round to whole pixels.\n */\nexport const measurePaddingBox = (element: Element): Rect =>\n paddingBoxOf({\n rect: element.getBoundingClientRect(),\n border: borderOf(getComputedStyle(element)),\n })\n\nconst pointIn = (box: Rect, event: PointerEvent): PointerPoint => ({\n x: event.clientX - box.left,\n y: event.clientY - box.top,\n pressure: event.pressure,\n})\n\n/**\n * Where one pointer is inside an element, as a Mount, for a surface the\n * pointer draws on or points into (a color area, a dial, a signature pad): a\n * primary press, each move until the release, and the release, each with\n * the place in the element's padding box and the box's size. The box is\n * measured at each event, so an element that moved or resized is followed.\n * Coordinates are raw, left to right and top down whatever the direction:\n * what a place means (a share, an angle, a reading direction) is the parent's.\n *\n * The pointer is captured from press to release, so a drag that leaves the\n * element is still heard, and the moves and the release are listened to only\n * meanwhile. A press keeps the browser's own focus and text selection away,\n * and a second pointer while one is down is ignored.\n */\nexport const PointerPosition = Mount.defineStream('PointerPosition', {\n messages: [PointerPressed, PointerMoved, PointerReleased],\n args: {\n /**\n * A descendant to focus on a press, found by this selector (a thumb), so\n * the keys go on from where the pointer left it.\n */\n focus: Schema.optionalKey(Schema.String),\n },\n execute: ({ element, focus }) =>\n Stream.callback<PointerFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const offer = (fact: PointerFact) => Queue.offerUnsafe(queue, fact)\n let held: Option.Option<number> = Option.none()\n const ours = (event: Event): event is PointerEvent =>\n event instanceof PointerEvent && Option.contains(held, event.pointerId)\n\n const release = () => {\n if (Option.isNone(held)) return\n const pointerId = held.value\n held = Option.none()\n for (const [type, listener] of during) element.removeEventListener(type, listener)\n try {\n element.releasePointerCapture(pointerId)\n } catch {\n // Capture may already be gone with the pointer.\n }\n }\n const end = (completed: boolean) => (event: Event) => {\n if (!ours(event)) return\n release()\n offer(PointerReleased.make({ completed }))\n }\n const move = (event: Event) => {\n if (!ours(event)) return\n const box = measurePaddingBox(element)\n const point = pointIn(box, event)\n // Safari coalesces none and has no method for it.\n const coalesced = event.getCoalescedEvents?.() ?? []\n offer(\n PointerMoved.make({\n width: box.width,\n height: box.height,\n point,\n points: coalesced.length > 0 ? coalesced.map(one => pointIn(box, one)) : [point],\n }),\n )\n }\n const during: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n ['pointermove', move],\n ['pointerup', end(true)],\n ['pointercancel', end(false)],\n ['lostpointercapture', end(false)],\n ]\n\n const down = (event: Event) => {\n if (!(event instanceof PointerEvent) || event.button !== 0) return\n if (Option.isSome(held)) {\n if (!ours(event)) return\n // The same pointer down again: its release went where nothing heard it.\n release()\n offer(PointerReleased.make({ completed: false }))\n }\n held = Option.some(event.pointerId)\n for (const [type, listener] of during) element.addEventListener(type, listener)\n try {\n element.setPointerCapture(event.pointerId)\n } catch {\n // A pointer the browser no longer tracks cannot be captured; its moves over the element still come.\n }\n // Kept from the browser's own focus and text selection, and from the mouse events a touch also sends.\n event.preventDefault()\n if (focus !== undefined) {\n const into = element.querySelector(focus)\n if (into instanceof HTMLElement) into.focus()\n }\n const box = measurePaddingBox(element)\n offer(\n PointerPressed.make({\n width: box.width,\n height: box.height,\n point: pointIn(box, event),\n pointerType: event.pointerType,\n }),\n )\n }\n element.addEventListener('pointerdown', down)\n return () => {\n element.removeEventListener('pointerdown', down)\n release()\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The attribute on the mounted element naming the element `TrackBox` follows, by id. */\nexport const TRACK_TARGET_ATTRIBUTE = 'data-target'\n\n/** The custom properties `TrackBox` writes for `name`, as `measured` names `Measure`'s. */\nexport const trackedBox = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n radius: `--fk-${name}-radius`,\n }) as const\n\n/** Sent as the followed element changes: its id, and whether it is on the page. */\nexport const TrackedTarget = Schema.TaggedStruct('TrackedTarget', {\n target: Schema.String,\n found: Schema.Boolean,\n})\nexport type TrackedTarget = typeof TrackedTarget.Type\n\n/**\n * The radius a box of `width` by `height` draws for a computed\n * `border-top-left-radius` of `value` (`8px`, `50%`, `8px 4px`): its\n * horizontal length in pixels, a share of the width for a percentage, and\n * never more than half the shorter side, where the browser stops it.\n */\nexport const cornerRadius = (value: string, width: number, height: number): number => {\n const first = value.trim().split(/\\s+/)[0] ?? ''\n const length = parseFloat(first)\n if (!Number.isFinite(length)) return 0\n const pixels = first.endsWith('%') ? (length * width) / 100 : length\n return Math.max(0, Math.min(pixels, width / 2, height / 2))\n}\n\n/**\n * Follows another element's box, as a Mount: the element whose id is the\n * mounted element's `data-target` (`TRACK_TARGET_ATTRIBUTE`). Its box in\n * viewport pixels is written on the mounted element as `--fk-<name>-x`,\n * `-y`, `-w` and `-h`, and with `radius`, its top left corner's radius as\n * `--fk-<name>-radius` (`cornerRadius`), so a fixed overlay drawn from them\n * (a tour's cutout, a coach mark's ring) sits over it. While nothing is\n * followed they are removed, so a stylist's fallbacks apply.\n *\n * The box is read again on a scroll anywhere (heard on the way down, since\n * `scroll` does not bubble), a window resize, the followed element's own\n * resize, and any change to the document's elements, which is also how a\n * target drawn anew under the same id is found. `data-target` is read again\n * whenever it changes, so one element can glide from target to target\n * without being drawn again, which a Mount's args, read once, could not do.\n * What moves the target by any other way (a stylesheet added) is seen at the\n * next of these.\n *\n * Whether a target is on the page is the parent's to act on (a tour shows\n * the step in the middle instead), so each change of the target or of\n * whether it is found sends `TrackedTarget`, starting with the first one.\n * Since it sends a Message, a component may draw it by default: a Scene test\n * resolves it with what the parent maps it to. An empty `data-target` follows\n * nothing and sends nothing.\n */\nexport const TrackBox = Mount.defineStream('TrackBox', {\n messages: [TrackedTarget],\n args: {\n /** The custom properties' prefix: `tour` writes `--fk-tour-x`. */\n name: Schema.String,\n /** Whether to write the target's corner radius too; it reads the target's computed style. */\n radius: Schema.optional(Schema.Boolean),\n },\n execute: ({ element, name, radius = false }) =>\n Stream.callback<TrackedTarget>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const document = element.ownerDocument\n const view = document.defaultView\n const properties = trackedBox(name)\n const style = element instanceof HTMLElement ? element.style : undefined\n let target: Element | null = null\n let told: TrackedTarget | undefined\n\n const place = () => {\n if (style === undefined) return\n if (target === null) {\n for (const property of Object.values(properties)) style.removeProperty(property)\n return\n }\n const box = target.getBoundingClientRect()\n style.setProperty(properties.x, `${box.left}px`)\n style.setProperty(properties.y, `${box.top}px`)\n style.setProperty(properties.w, `${box.width}px`)\n style.setProperty(properties.h, `${box.height}px`)\n if (radius) {\n const corner = getComputedStyle(target).borderTopLeftRadius\n style.setProperty(\n properties.radius,\n `${cornerRadius(corner, box.width, box.height)}px`,\n )\n }\n }\n // Looks the target up again, telling the parent when what it follows, or whether\n // that is found, changed.\n const follow = () => {\n const id = element.getAttribute(TRACK_TARGET_ATTRIBUTE) ?? ''\n const found = id === '' ? null : document.getElementById(id)\n if (found !== target) {\n if (target !== null) resized.unobserve(target)\n if (found !== null) resized.observe(found)\n target = found\n }\n place()\n if (id !== '' && (told?.target !== id || told.found !== (found !== null))) {\n told = TrackedTarget.make({ target: id, found: found !== null })\n Queue.offerUnsafe(queue, told)\n }\n }\n\n // Every observer is made before any observes, so one that throws (jsdom has no\n // ResizeObserver) leaves nothing attached.\n const resized = new ResizeObserver(place)\n const changed = new MutationObserver(follow)\n changed.observe(element, {\n attributes: true,\n attributeFilter: [TRACK_TARGET_ATTRIBUTE],\n })\n changed.observe(document, { childList: true, subtree: true })\n view?.addEventListener('scroll', place, { capture: true, passive: true })\n view?.addEventListener('resize', place)\n follow()\n return () => {\n changed.disconnect()\n resized.disconnect()\n view?.removeEventListener('scroll', place, { capture: true })\n view?.removeEventListener('resize', place)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["failMessage","failMessage","urlToString"],"sources":["../../src/dom/autofocus.ts","../../src/dom/clipboard.ts","../../src/dom/input-mask.ts","../../src/dom/keep-in-view.ts","../../src/dom/script-loader.ts","../../src/dom/share.ts","../../src/dom/measure.ts","../../src/dom/scroll.ts","../../src/dom/pointed-links.ts","../../src/dom/fluid-hover.ts","../../src/dom/keyboard-inset.ts","../../src/dom/scroll-bars.ts","../../src/dom/swipe.ts","../../src/dom/scroll-settle.ts","../../src/dom/pointer-position.ts","../../src/dom/track-box.ts","../../src/dom/image-decode.ts"],"sourcesContent":["import { Effect, Schema } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const Focused = Schema.TaggedStruct('Focused', {})\nexport type Focused = typeof Focused.Type\n\n/**\n * Autofocus as a Mount: focuses the element on insert, then emits `Focused`.\n * The message means focus was requested — a non-focusable element or a\n * hidden tab may decline, and the browser does not report that. Plain\n * `focus()`, no scroll options: scroll behavior stays the application's\n * choice.\n */\nexport const Autofocus = Mount.define('Autofocus', {\n messages: [Focused],\n execute: ({ element }) =>\n Effect.sync(() => {\n const focusable = element as unknown as { readonly focus?: unknown }\n if (typeof focusable.focus === 'function') {\n ;(focusable.focus as () => void).call(element)\n }\n return Focused.make({})\n }),\n})\n","/**\n * The clipboard as Commands: run in `update` beside any bundle. A copy yields\n * `Copied` or `CopyFailed`, a read `Read` or `ReadFailed`. No Model involved:\n * the clipboard is not application state.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ClipboardMessage = defineMessageUnion({\n Copied: {},\n CopyFailed: { message: Schema.String },\n})\nexport type ClipboardMessage = typeof ClipboardMessage.Type\n\nexport const ClipboardReadMessage = defineMessageUnion({\n Read: { text: Schema.String },\n ReadFailed: { message: Schema.String },\n})\nexport type ClipboardReadMessage = typeof ClipboardReadMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\n/**\n * Copies text to the clipboard. Without a clipboard API (SSR, insecure\n * context, denied permission) the command yields `CopyFailed` instead of\n * throwing, so `update` handles both outcomes as Messages.\n */\nexport const copyText = (text: string): Command<ClipboardMessage, never, never> => ({\n name: 'Clipboard.copy',\n args: { text },\n effect:\n typeof navigator !== 'undefined' && typeof navigator.clipboard?.writeText === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({\n try: () => navigator.clipboard.writeText(text),\n catch: failMessage,\n }),\n {\n onFailure: message => Effect.succeed(ClipboardMessage.CopyFailed({ message })),\n onSuccess: () => Effect.succeed(ClipboardMessage.Copied()),\n },\n )\n : Effect.succeed(ClipboardMessage.CopyFailed({ message: 'clipboard is unavailable' })),\n})\n\n/**\n * Reads the clipboard's text. The browser may ask the user first; a refusal,\n * an insecure context or no clipboard API yields `ReadFailed`.\n */\nexport const readText = (): Command<ClipboardReadMessage, never, never> => ({\n name: 'Clipboard.read',\n effect:\n typeof navigator !== 'undefined' && typeof navigator.clipboard?.readText === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({ try: () => navigator.clipboard.readText(), catch: failMessage }),\n {\n onFailure: message => Effect.succeed(ClipboardReadMessage.ReadFailed({ message })),\n onSuccess: text => Effect.succeed(ClipboardReadMessage.Read({ text })),\n },\n )\n : Effect.succeed(ClipboardReadMessage.ReadFailed({ message: 'clipboard is unavailable' })),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** What `InputMask` reports after each edit: the masked text shown, and the characters typed. */\nexport const Input = Schema.TaggedStruct('Input', {\n value: Schema.String,\n raw: Schema.String,\n})\nexport type Input = typeof Input.Type\n\nconst isDigit = (char: string): boolean => char >= '0' && char <= '9'\nconst isLetter = (char: string): boolean =>\n (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z')\n\nconst matches = (placeholder: string, char: string): boolean =>\n placeholder === '#'\n ? isDigit(char)\n : placeholder === 'A'\n ? isLetter(char)\n : isDigit(char) || isLetter(char)\n\nconst isPlaceholder = (char: string): boolean => char === '#' || char === 'A' || char === '*'\n\n/** Whether any placeholder at or after `from` consumes any input at or after `at`. */\nconst fillable = (pattern: string, from: number, value: string, at: number): boolean => {\n for (let i = from; i < pattern.length; i++) {\n const placeholder = pattern[i]!\n if (!isPlaceholder(placeholder)) continue\n for (let j = at; j < value.length; j++) {\n if (matches(placeholder, value[j]!)) return true\n }\n }\n return false\n}\n\n/**\n * The mask as a pure function: `#` takes a digit, `A` a letter, `*` either, and\n * any other character of the pattern is written in once input reaches past it.\n * Input that fits no placeholder is skipped. `masked` is what the field shows;\n * `raw` is only the characters typed.\n */\nexport const applyMask = (\n value: string,\n pattern: string,\n): { readonly masked: string; readonly raw: string } => {\n let masked = ''\n let raw = ''\n let at = 0\n for (let i = 0; i < pattern.length; i++) {\n const slot = pattern[i]!\n if (isPlaceholder(slot)) {\n while (at < value.length && !matches(slot, value[at]!)) at++\n if (at >= value.length) break\n masked += value[at]!\n raw += value[at]!\n at++\n } else if (fillable(pattern, i + 1, value, at)) {\n masked += slot\n } else {\n break\n }\n }\n return { masked, raw }\n}\n\ninterface MaskableField {\n value: string\n selectionStart: number | null\n addEventListener(type: string, listener: () => void): void\n removeEventListener(type: string, listener: () => void): void\n setSelectionRange?(start: number, end: number): void\n}\n\nconst asField = (element: Element): MaskableField | null => {\n const field = element as unknown as Partial<MaskableField>\n return typeof field.value === 'string' && typeof field.addEventListener === 'function'\n ? (field as MaskableField)\n : null\n}\n\n/**\n * An input mask as a Mount plus a pure mask function. The pattern language\n * is three placeholders — `#` digit, `A` letter, `*` either, all ASCII —\n * with every other character literal. Literals appear only once a later placeholder\n * consumes input, so partial values never dangle a separator. The Mount\n * rewrites the field, restores the caret approximately, and emits `Input`\n * with both the masked and raw values; the parent owns the state, like any\n * controlled input.\n */\nexport const InputMask = Mount.defineStream('InputMask', {\n messages: [Input],\n args: { pattern: Schema.String },\n execute: ({ element, pattern }) =>\n Stream.callback<typeof Input.Type>(queue =>\n Effect.gen(function* () {\n const field = asField(element)\n if (field === null) return\n const onInput = () => {\n const { masked, raw } = applyMask(field.value, pattern)\n if (masked !== field.value) {\n const caret = field.selectionStart ?? masked.length\n field.value = masked\n const at = Math.min(caret, masked.length)\n try {\n field.setSelectionRange?.(at, at)\n } catch {\n // Select-all style inputs reject ranges; the value still stands.\n }\n }\n Queue.offerUnsafe(queue, Input.make({ value: masked, raw }))\n }\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n field.addEventListener('input', onInput)\n return field\n }),\n current => Effect.sync(() => current.removeEventListener('input', onInput)),\n )\n }),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * Keeps what is marked in view as a Mount: whenever an element in the mounted\n * one's subtree newly matches `selector`, such as the row just selected in a\n * list, it is scrolled into view the least amount that shows it (`nearest`).\n * The element keeps its identity and its focus: nothing is redrawn to move it.\n *\n * It watches with a `MutationObserver` for as long as it is mounted, which is as\n * long as the list or canvas that can change what is marked.\n */\nexport const KeepInView = Mount.defineStream('KeepInView', {\n messages: [Schema.Never],\n args: {\n /** What is marked, as a selector within the element: `[aria-selected=\"true\"]`. */\n selector: Schema.String,\n },\n execute: ({ element, selector }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n let marked = element.querySelector(selector)\n const observer = new MutationObserver(() => {\n const now = element.querySelector(selector)\n // Only a change of what is marked scrolls: the author's own scrolling stays.\n // A DOM with no layout (jsdom, in a test) has no scrollIntoView and nothing to scroll.\n if (now !== null && now !== marked && typeof now.scrollIntoView === 'function')\n now.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n marked = now\n })\n observer.observe(element, { subtree: true, childList: true, attributes: true })\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n ),\n ),\n})\n","/**\n * Script loading as a Command: appends a `src` script to the head unless one\n * is already there. Idempotent by URL — concurrent placements collapse onto\n * the first tag instead of fetching twice. Yields `Loaded` on success and\n * `LoadFailed` otherwise (network error, no document), so `update` handles\n * both outcomes as Messages.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ScriptMessage = defineMessageUnion({\n Loaded: {},\n LoadFailed: { message: Schema.String },\n})\nexport type ScriptMessage = typeof ScriptMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\n// Tags still fetching, by URL: concurrent loads share one tag and its fate.\nconst inflight = new Map<string, Promise<void>>()\n\n/** Loads a script by URL, once per URL. */\nexport const loadScript = (src: string): Command<ScriptMessage, never, never> => ({\n name: 'Script.load',\n args: { src },\n effect: Effect.matchEffect(\n Effect.tryPromise({\n try: () => {\n if (typeof document === 'undefined') {\n return Promise.reject(new Error('script loading is unavailable'))\n }\n // Concurrent loads share one tag and its fate, instead of racing\n // past the presence check and fetching twice: the in-flight entry\n // is checked before presence, in the same synchronous block that\n // appends, so a second load cannot slip between them.\n const running = inflight.get(src)\n if (running !== undefined) return running\n // getAttribute, not .src: the property resolves to an absolute URL\n // and would never equal the given string.\n const present = Array.from(document.getElementsByTagName('script')).some(\n element => element.getAttribute('src') === src,\n )\n if (present) return Promise.resolve()\n const completion = new Promise<void>((resolve, reject) => {\n const element = document.createElement('script')\n element.src = src\n element.async = true\n element.onload = () => resolve()\n element.onerror = () => {\n // A dead tag must not satisfy later presence checks.\n element.remove()\n reject(new Error(`failed to load script: ${src}`))\n }\n document.head.appendChild(element)\n })\n const tracked = completion.then(\n () => {\n inflight.delete(src)\n },\n (error: unknown) => {\n inflight.delete(src)\n throw error\n },\n )\n inflight.set(src, tracked)\n return tracked\n },\n catch: (error: unknown) => error,\n }),\n {\n onFailure: error => Effect.succeed(ScriptMessage.LoadFailed({ message: failMessage(error) })),\n onSuccess: () => Effect.succeed(ScriptMessage.Loaded()),\n },\n ),\n})\n","/**\n * Web Share as a Command: runs in `update` beside any bundle, yields\n * `Shared` on success. Dismissal is its own outcome, not a failure — the\n * application tells a cancelled sheet apart from a broken one. Without a\n * share API (desktop, insecure context) it yields `ShareFailed` instead of\n * throwing, so `update` handles every outcome as a Message.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ShareData = Schema.Struct({\n title: Schema.optional(Schema.String),\n text: Schema.optional(Schema.String),\n url: Schema.optional(Schema.String),\n})\nexport type ShareData = typeof ShareData.Type\n\nexport const ShareMessage = defineMessageUnion({\n Shared: {},\n Dismissed: {},\n ShareFailed: { message: Schema.String },\n})\nexport type ShareMessage = typeof ShareMessage.Type\n\nconst failMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error)\n\nconst isDismissal = (error: unknown): boolean =>\n typeof (error as { readonly name?: unknown } | null)?.name === 'string' &&\n (error as { readonly name: string }).name === 'AbortError'\n\n/** Shares data through the platform sheet. */\nexport const share = (data: ShareData): Command<ShareMessage, never, never> => ({\n name: 'Share.share',\n args: { data },\n effect:\n typeof navigator !== 'undefined' && typeof navigator.share === 'function'\n ? Effect.matchEffect(\n Effect.tryPromise({\n // Omit absent fields: the platform type rejects explicit\n // undefined under exactOptionalPropertyTypes.\n try: () =>\n navigator.share({\n ...(data.title !== undefined ? { title: data.title } : {}),\n ...(data.text !== undefined ? { text: data.text } : {}),\n ...(data.url !== undefined ? { url: data.url } : {}),\n }),\n catch: (error: unknown) => error,\n }),\n {\n onFailure: error =>\n Effect.succeed(\n isDismissal(error)\n ? ShareMessage.Dismissed()\n : ShareMessage.ShareFailed({ message: failMessage(error) }),\n ),\n onSuccess: () => Effect.succeed(ShareMessage.Shared()),\n },\n )\n : Effect.succeed(ShareMessage.ShareFailed({ message: 'share is unavailable' })),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The custom properties `Measure` writes for a target named `name`. */\nexport const measured = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n display: `--fk-${name}-display`,\n /**\n * `1` for the measure that finds the mark on another element than the\n * last, `0` for any other (the layout moved or resized the same one, or\n * it is the first found): an overlay that glides to a new mark scales its\n * duration by it, so it keeps to its element as the layout settles.\n */\n moving: `--fk-${name}-moving`,\n }) as const\n\n/**\n * Measures marked elements as a Mount, for a view to draw something over them,\n * such as an editor's selection outline, with no Message and no Model: where\n * an element is, is presentation, known to the DOM and to no transition.\n *\n * For each named target, the first element in the mounted one's subtree that\n * matches its selector is measured relative to the mounted element's scroll\n * box, which is what an absolutely placed child of it is laid out in. The\n * mounted element gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, and\n * `--fk-<name>-display`: `block` while a target is found, `none` while none is,\n * and `--fk-<name>-moving` (see `measured`).\n *\n * It measures again when the subtree changes (a selection moves) or the\n * mounted element or a measured one changes size, in the frame the change is\n * drawn in; and, at most once a frame, when the mounted element scrolls, the\n * window resizes, an image or a font inside loads, and on every frame of a\n * transition or an animation inside. What moves a target by any other way,\n * such as a stylesheet added that shifts it without resizing it, is seen at\n * the next of these.\n */\nexport const Measure = Mount.defineStream('Measure', {\n messages: [Schema.Never],\n args: {\n /** Each target by name, as a selector within the element: `{ selected: '[aria-selected=\"true\"]' }`. */\n targets: Schema.Record(Schema.String, Schema.String),\n },\n execute: ({ element, targets }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const container = element as HTMLElement\n const names = Object.keys(targets)\n let watched: ReadonlyArray<Element> = []\n // The element each target was last measured on, to tell a new mark from a moved layout.\n const last = new Map<string, Element>()\n let frame: number | undefined\n // Whether a transition or an animation may be moving something, until one frame finds none.\n let animating = false\n\n const measure = () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n frame = undefined\n const box = container.getBoundingClientRect()\n const found: Array<Element> = []\n for (const name of names) {\n const property = measured(name)\n const target = container.querySelector(targets[name]!)\n if (target === null) {\n container.style.setProperty(property.display, 'none')\n continue\n }\n found.push(target)\n const previous = last.get(name)\n last.set(name, target)\n const rect = target.getBoundingClientRect()\n // Relative to the scroll box: where the content is, not where the viewport shows it.\n const x = rect.left - box.left - container.clientLeft + container.scrollLeft\n const y = rect.top - box.top - container.clientTop + container.scrollTop\n container.style.setProperty(property.x, `${x}px`)\n container.style.setProperty(property.y, `${y}px`)\n container.style.setProperty(property.w, `${rect.width}px`)\n container.style.setProperty(property.h, `${rect.height}px`)\n container.style.setProperty(property.display, 'block')\n container.style.setProperty(\n property.moving,\n previous === undefined || previous === target ? '0' : '1',\n )\n }\n // A measured element that changes size, as an image loading does, is measured again.\n if (found.length !== watched.length || found.some((each, at) => each !== watched[at])) {\n for (const each of watched) sizes.unobserve(each)\n for (const each of found) sizes.observe(each)\n watched = found\n }\n if (animating) {\n // Asked each frame rather than counted: an element removed mid-transition ends none.\n animating = container\n .getAnimations({ subtree: true })\n .some(animation => animation.playState === 'running')\n if (animating) soon()\n }\n }\n const soon = () => {\n if (frame === undefined) frame = requestAnimationFrame(measure)\n }\n const moving = () => {\n animating = true\n soon()\n }\n\n // A change is measured as its records arrive, before the frame it is drawn in is\n // painted, so a box never shows one frame on the element it has left.\n const changes = new MutationObserver(measure)\n // Made, and the fonts listened to, before anything observes: where one is\n // missing (jsdom has neither a ResizeObserver nor `document.fonts`), the Mount\n // fails with nothing attached to call `measure`. A size is measured as it is\n // observed, after layout and before paint: a frame later, a popup whose width\n // settled as it opened showed its marker at the old width, past its edge.\n const sizes = new ResizeObserver(measure)\n document.fonts.addEventListener('loadingdone', soon)\n // Its own properties change the container's style too, but writing the same\n // values again records nothing, so a measure that changed nothing rests.\n changes.observe(container, { subtree: true, childList: true, attributes: true })\n sizes.observe(container)\n container.addEventListener('scroll', soon, { passive: true })\n window.addEventListener('resize', soon)\n // `load` does not bubble, so it is caught on the way down.\n container.addEventListener('load', soon, { capture: true })\n container.addEventListener('transitionrun', moving)\n container.addEventListener('animationstart', moving)\n measure()\n return () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n changes.disconnect()\n sizes.disconnect()\n container.removeEventListener('scroll', soon)\n window.removeEventListener('resize', soon)\n container.removeEventListener('load', soon, { capture: true })\n document.fonts.removeEventListener('loadingdone', soon)\n container.removeEventListener('transitionrun', moving)\n container.removeEventListener('animationstart', moving)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","/**\n * Where the window is scrolled, across an application's own navigations, as\n * a stream. Left to itself, a browser keeps the scroll of the entry it\n * leaves when a link pushes a new one, and on Back restores the old offset\n * before the application has drawn the entry it returns to, so the offset is\n * clamped to a page still loading. Here a pushed entry starts at the top,\n * and Back, Forward or a reload return where that entry was, once the page\n * is tall enough to hold it.\n *\n * Three rules, each found the slow way:\n *\n * 1. The offset is taken when the reader acts. The next screen is drawn\n * before a Navigate Command pushes the address, so by the time the URL\n * changes the window is already clamped to the new, shorter page. The\n * scroll is recorded at the reader's click or key (capture phase), and at\n * the start of Back and Forward, which begin in the browser before\n * anything is drawn.\n * 2. A restore holds its place while the next screen settles. A restore made\n * when the entry changes is undone by the loading state drawn right after\n * it, so the target is held on each frame for a moment, until the reader\n * scrolls, touches or types, or another navigation starts.\n * 3. Entries are keyed by the Navigation API's entry key, which a reload and\n * a full navigation keep; offsets rest in `sessionStorage`, so Back into\n * another document restores too. Where the browser has no Navigation API\n * the stream attaches nothing and leaves the browser's own behaviour\n * alone.\n *\n * Lift with `Subscription.persistentEntry`; the stream sends no Messages. Only\n * the window scrolls: a nested container is the route graph's to know, when\n * `Site.transition` arrives.\n */\nimport { Effect, Option, Stream } from 'effect'\n\n/** How `keepScroll` remembers and restores each history entry's offset. */\nexport interface KeepScrollOptions {\n /** The `sessionStorage` key holding entry offsets. Default `'foldkit:scroll'`. */\n readonly storageKey?: string | undefined\n /** Entries remembered at most: the oldest are forgotten first. Default 50. */\n readonly kept?: number | undefined\n /**\n * How long a restore holds its place while the next screen settles, in\n * milliseconds. Default 2000.\n */\n readonly patience?: number | undefined\n}\n\nconst navigationTypeOf = (event: Event): Option.Option<unknown> =>\n 'navigationType' in event ? Option.some(event.navigationType) : Option.none()\n\nconst readSaved = (storageKey: string): Map<string, number> => {\n try {\n const stored: unknown = JSON.parse(sessionStorage.getItem(storageKey) ?? '[]')\n return new Map(\n Array.isArray(stored)\n ? stored.filter(\n (pair): pair is [string, number] =>\n Array.isArray(pair) && typeof pair[0] === 'string' && typeof pair[1] === 'number',\n )\n : [],\n )\n } catch {\n // Storage blocked, or something else wrote the key: nothing is remembered.\n return new Map()\n }\n}\n\n/** Starts keeping the scroll; the release undoes everything it installed. */\nconst attach = (storageKey: string, kept: number, patience: number): (() => void) => {\n // TypeScript's DOM library declares it on every window; a browser without\n // the Navigation API has none.\n const navigation: Navigation | undefined = window.navigation\n if (navigation === undefined) return () => {}\n const restoration = window.history.scrollRestoration\n window.history.scrollRestoration = 'manual'\n const saved = readSaved(storageKey)\n const detaches: Array<() => void> = []\n const on = (target: EventTarget, type: string, listener: EventListener, capture?: boolean) => {\n target.addEventListener(type, listener, capture)\n detaches.push(() => target.removeEventListener(type, listener, capture))\n }\n const keyOf = () =>\n Option.fromNullOr(navigation.currentEntry).pipe(Option.map(entry => entry.key))\n /** Where the current entry was left, if it has been. */\n const savedHere = () => Option.flatMap(keyOf(), key => Option.fromUndefinedOr(saved.get(key)))\n const remember = () => {\n const key = keyOf()\n if (Option.isNone(key)) return\n // Moved to the end, so it is the last to be forgotten.\n saved.delete(key.value)\n saved.set(key.value, window.scrollY)\n for (const old of saved.keys()) {\n if (saved.size <= kept) break\n saved.delete(old)\n }\n }\n\n let settling = new AbortController()\n /**\n * Holds the window at `top` while the next screen settles, whenever the page\n * can hold it, until the reader scrolls, touches or types, or another\n * navigation starts.\n */\n const settle = (top: number) => {\n settling.abort()\n settling = new AbortController()\n const { signal } = settling\n for (const input of ['wheel', 'touchstart', 'keydown', 'pointerdown'])\n window.addEventListener(input, () => settling.abort(), { passive: true, signal })\n const until = performance.now() + patience\n const step = () => {\n if (signal.aborted) return\n const room = document.documentElement.scrollHeight - window.innerHeight\n if (room >= top && Math.round(window.scrollY) !== top)\n window.scrollTo({ top, behavior: 'instant' })\n if (performance.now() < until) requestAnimationFrame(step)\n else settling.abort()\n }\n step()\n }\n\n // Remembered where the reader acts, before the application does: by the time\n // it pushes an address it has drawn the next screen, and the window is\n // already clamped to it. Back and Forward start in the browser, before\n // anything is drawn, so they are remembered as they begin.\n const acted = () => remember()\n for (const input of ['click', 'keydown']) on(window, input, acted, true)\n const traversing = (event: Event) => {\n if (Option.contains(navigationTypeOf(event), 'traverse')) remember()\n }\n on(navigation, 'navigate', traversing)\n const changed = (event: Event) => {\n const type = navigationTypeOf(event)\n if (Option.contains(type, 'push')) settle(0)\n else if (Option.contains(type, 'traverse')) settle(Option.getOrElse(savedHere(), () => 0))\n // A replace is the same entry, narrowed or selected in place: it stays where it is.\n }\n on(navigation, 'currententrychange', changed)\n const hidden = () => {\n remember()\n try {\n sessionStorage.setItem(storageKey, JSON.stringify([...saved]))\n } catch {\n // Storage blocked: the next document starts at the top.\n }\n }\n on(window, 'pagehide', hidden)\n // A reload, or Back into this document from another: where this entry was.\n const here = savedHere()\n if (Option.isSome(here)) settle(here.value)\n return () => {\n settling.abort()\n for (const detach of detaches) detach()\n window.history.scrollRestoration = restoration\n }\n}\n\n/**\n * Keeps the window's scroll across same-document navigations: a pushed entry\n * starts at the top, and Back, Forward or a reload return where that entry\n * was. Without a window the stream is empty instead of throwing. Lift with\n * `Subscription.persistentEntry`; the stream sends no Messages.\n */\nexport const keepScroll = (options: KeepScrollOptions = {}): Stream.Stream<never> => {\n if (typeof window === 'undefined') return Stream.empty\n const storageKey = options.storageKey ?? 'foldkit:scroll'\n const kept = options.kept ?? 50\n const patience = options.patience ?? 2000\n return Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => attach(storageKey, kept, patience)),\n detach => Effect.sync(detach),\n ),\n )\n}\n","import { Option, Stream } from 'effect'\nimport * as Dom from 'foldkit/dom'\nimport { fromString, toString as urlToString, type Url } from 'foldkit/url'\n\n/**\n * The address of the link a reader points at or tabs to, on the page's own\n * origin: where they may go next, for a `Data.preload` before they go. Each\n * link once while they stay on it, since crossing its text sends one event\n * per element inside it. Without a document the stream is empty. Lift with\n * `Subscription.persistentEntry`, mapping each address to a Message.\n */\nexport const pointedLinks = (): Stream.Stream<Url> => {\n if (typeof document === 'undefined') return Stream.empty\n const linkOf = (event: Event): Option.Option<Url> => {\n const link = event.target instanceof Element ? event.target.closest('a[href]') : null\n return link instanceof HTMLAnchorElement && link.origin === window.location.origin\n ? fromString(link.href)\n : Option.none()\n }\n return Stream.merge(\n Dom.streamFromEventFilterMap({\n target: document,\n type: 'pointerover',\n filterMapEvent: linkOf,\n }),\n Dom.streamFromEventFilterMap({ target: document, type: 'focusin', filterMapEvent: linkOf }),\n ).pipe(Stream.changesWith((a, b) => urlToString(a) === urlToString(b)))\n}\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The custom properties `FluidHover` writes on its container for a highlight named `name`. */\nexport const fluidHovered = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n /** `1` while an item is highlighted, `0` once the pointer and focus have left. */\n shown: `--fk-${name}-shown`,\n /**\n * `0` for the frame the highlight appears in, then `1`: a highlight's\n * movement scales its duration by it, so it appears on its item rather\n * than sliding in from where it last was.\n */\n moving: `--fk-${name}-moving`,\n }) as const\n\n/**\n * The attribute `FluidHover` sets on its container, to the highlight's name,\n * while it runs: a stylist draws the highlight, and drops each item's own\n * hover, only under it.\n */\nexport const FLUID_HOVER_ATTRIBUTE = 'data-fluid-hover'\n\n/** The attribute that names, inside an item, the control a press in a gap reaches. */\nexport const FLUID_PRESS_ATTRIBUTE = 'data-fluid-press'\n\n/** The attribute on the item the highlight is shown on, for what CSS draws beside it. */\nexport const FLUID_LIT_ATTRIBUTE = 'data-fluid-lit'\n\nconst Axis = Schema.Literals(['x', 'y', 'xy'])\nexport type FluidAxis = typeof Axis.Type\n\n/** How far a point is from a rectangle along each axis: zero inside it. */\nconst gap = (low: number, high: number, at: number) => Math.max(low - at, 0, at - high)\n\n// On one axis the other only breaks ties, so a list's highlight never leaves\n// the row level with the pointer for a nearer edge of the next column.\nconst away: Record<FluidAxis, (dx: number, dy: number) => number> = {\n x: (dx, dy) => dx * 1e6 + dy,\n y: (dx, dy) => dy * 1e6 + dx,\n xy: Math.hypot,\n}\n\nconst distance = (rect: DOMRect, x: number, y: number, axis: FluidAxis) =>\n away[axis](gap(rect.left, rect.right, x), gap(rect.top, rect.bottom, y))\n\nconst isDisabled = (item: Element) =>\n item.matches('[aria-disabled=\"true\"], [data-disabled]:not([data-disabled=\"false\"]), :disabled')\n\n/**\n * One highlight that follows the pointer across a container's items, as a\n * Mount, with no Message and no Model: which item the pointer is nearest is\n * presentation, known to the DOM and to no transition.\n *\n * The item nearest the pointer is the one highlighted, so the pointer in a gap\n * between two items still points at one, and the highlight moves from item to\n * item instead of blinking off between them. On the `y` axis nearness is read\n * vertically (a list), on `x` horizontally (a strip), on `xy` both (a grid). A\n * disabled item (`aria-disabled=\"true\"`, `data-disabled`, `:disabled`) is never\n * highlighted. An item reached by the keyboard (`:focus-visible`) is\n * highlighted too, and with `focused`, the item that selector finds from a\n * focused element that is no item (a tree's row, from its focused\n * `treeitem`, which also holds the rows beneath it); a touch highlights\n * nothing, since there is no pointer to\n * follow before the press.\n *\n * The container gets `--fk-<name>-x`, `-y`, `-w` and `-h` in pixels, relative\n * to its scroll box like `Measure`'s, and `-shown` and `-moving` (see\n * `fluidHovered`); a view draws the highlight as an absolutely placed child\n * that reads them. With `gapClick`, a click in a gap presses the highlighted\n * item: its descendant marked `data-fluid-press`, or the item itself; with\n * `gapReach` too, only a click within that many pixels of it, as a grid of\n * cards with wide gutters wants (Fluid Functionalism's uses 16). A popup\n * measured before it has a layout box keeps its last complete place, and\n * tries again for three frames, rather than drawing the highlight at zero.\n * The item the highlight is shown on carries `data-fluid-lit`, so a style\n * can change what sits beside it (a table hides the lines around the lit\n * row).\n *\n * `follows` names the item the highlight sits on while the pointer is not\n * moving it: a menu marks the row its keys reach (`[data-active]`), and the\n * highlight goes there whenever that mark moves, so the keys and the pointer\n * light the same one. `from` names the item a fresh highlight grows out of,\n * as a tab's hover leaves the chosen tab. A highlight always fades where it\n * is: once the pointer leaves, nothing should move. It stays only for an item\n * the keyboard reached (`:focus-visible`), not one a click focused.\n */\nexport const FluidHover = Mount.defineStream('FluidHover', {\n messages: [Schema.Never],\n args: {\n /** The highlight's name, which names the custom properties. */\n name: Schema.String,\n /** The selector of an item within the container. */\n item: Schema.String,\n axis: Axis,\n gapClick: Schema.Boolean,\n /** How far from the highlighted item, in pixels, a click in a gap still presses it. */\n gapReach: Schema.optional(Schema.Number),\n /** The selector of the item the highlight sits on while the pointer is not moving it. */\n follows: Schema.optional(Schema.String),\n /** The selector of the item a fresh highlight grows out of. */\n from: Schema.optional(Schema.String),\n /** The selector, run from a focused element outside any item, of the item it lights. */\n focused: Schema.optional(Schema.String),\n },\n execute: ({ element, name, item: selector, axis, gapClick, gapReach, follows, from, focused }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const container = element as HTMLElement\n const property = fluidHovered(name)\n let active: Element | null = null\n let followed: Element | null = null\n let pointer: { readonly x: number; readonly y: number } | null = null\n let frame: number | undefined\n\n const origin = () => (from === undefined ? null : container.querySelector(from))\n let retries = 0\n const place = (at: Element | null = active) => {\n if (at === null) return\n const box = container.getBoundingClientRect()\n const rect = at.getBoundingClientRect()\n // No layout box yet (a popup still opening): keep the last place and look again.\n if (rect.width === 0 && rect.height === 0) {\n if (retries < 3) {\n retries += 1\n requestAnimationFrame(() => place(at))\n }\n return\n }\n retries = 0\n const x = rect.left - box.left - container.clientLeft + container.scrollLeft\n const y = rect.top - box.top - container.clientTop + container.scrollTop\n container.style.setProperty(property.x, `${x}px`)\n container.style.setProperty(property.y, `${y}px`)\n container.style.setProperty(property.w, `${rect.width}px`)\n container.style.setProperty(property.h, `${rect.height}px`)\n }\n /** Marks `item` as the lit one, and nothing else. */\n const light = (item: Element | null) => {\n container\n .querySelectorAll(`[${FLUID_LIT_ATTRIBUTE}]`)\n .forEach(each => each !== item && each.removeAttribute(FLUID_LIT_ATTRIBUTE))\n item?.setAttribute(FLUID_LIT_ATTRIBUTE, '')\n }\n const show = (next: Element) => {\n const appearing = container.style.getPropertyValue(property.shown) !== '1'\n active = next\n light(next)\n const grows = appearing ? origin() : null\n if (appearing) container.style.setProperty(property.moving, '0')\n if (grows === null) {\n place()\n container.style.setProperty(property.shown, '1')\n } else {\n // Drawn first where it grows from, then moved: it travels out of that item.\n place(grows)\n requestAnimationFrame(() => {\n if (active !== next) return\n place()\n container.style.setProperty(property.shown, '1')\n })\n }\n if (appearing) {\n // The frame after: by then the jump to the item has been drawn without moving.\n requestAnimationFrame(() => container.style.setProperty(property.moving, '1'))\n }\n }\n const hide = () => {\n container.style.setProperty(property.shown, '0')\n light(null)\n }\n /** Whether the keyboard has an item focused, which the highlight then stays on. */\n const keyed = () => {\n const focused = document.activeElement\n return (\n focused !== null && container.contains(focused) && focused.matches(':focus-visible')\n )\n }\n const nearest = (x: number, y: number) => {\n let best: Element | null = null\n let bestDistance = Infinity\n for (const each of Array.from(container.querySelectorAll(selector))) {\n if (isDisabled(each)) continue\n const far = distance(each.getBoundingClientRect(), x, y, axis)\n if (far < bestDistance) {\n best = each\n bestDistance = far\n }\n }\n return best\n }\n const follow = () => {\n frame = undefined\n if (pointer === null) return\n const next = nearest(pointer.x, pointer.y)\n if (next === null) hide()\n else if (next !== active || container.style.getPropertyValue(property.shown) !== '1')\n show(next)\n }\n\n const move = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n pointer = { x: event.clientX, y: event.clientY }\n if (frame === undefined) frame = requestAnimationFrame(follow)\n }\n const leave = () => {\n pointer = null\n if (!keyed()) hide()\n }\n const focus = (event: FocusEvent) => {\n if (!(event.target instanceof Element) || !event.target.matches(':focus-visible')) {\n return\n }\n const owner =\n event.target.closest(selector) ??\n (focused === undefined ? null : event.target.querySelector(focused))\n if (owner !== null && container.contains(owner) && !isDisabled(owner)) show(owner)\n }\n const blur = (event: FocusEvent) => {\n const to = event.relatedTarget\n if (pointer === null && !(to instanceof Node && container.contains(to))) hide()\n }\n const click = (event: MouseEvent) => {\n if (!gapClick || active === null) return\n if (container.style.getPropertyValue(property.shown) !== '1') return\n const target = event.target\n if (!(target instanceof Element) || target.closest(selector) !== null) return\n const reach = distance(\n active.getBoundingClientRect(),\n event.clientX,\n event.clientY,\n 'xy',\n )\n if (gapReach !== undefined && reach > gapReach) return\n const press = active.querySelector(`[${FLUID_PRESS_ATTRIBUTE}]`) ?? active\n if (press instanceof HTMLElement) press.click()\n }\n const soon = () => {\n if (active !== null) requestAnimationFrame(() => place())\n }\n /** The marked item moved: the highlight goes with it, or fades if it is gone. */\n const marked = () => {\n if (follows === undefined) return\n const next = container.querySelector(follows)\n if (next === followed) return\n followed = next\n if (next !== null && !isDisabled(next)) show(next)\n else if (pointer === null && !keyed()) hide()\n }\n\n // Where there is no layout (jsdom has no ResizeObserver) nothing moves to\n // follow, and a view drawn there is no worse for the highlight's absence.\n const sizes = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(soon)\n const marks = follows === undefined ? undefined : new MutationObserver(marked)\n sizes?.observe(container)\n marks?.observe(container, { subtree: true, childList: true, attributes: true })\n container.addEventListener('pointermove', move, { passive: true })\n container.addEventListener('pointerleave', leave)\n container.addEventListener('focusin', focus)\n container.addEventListener('focusout', blur)\n container.addEventListener('click', click)\n container.addEventListener('scroll', soon, { passive: true })\n window.addEventListener('resize', soon)\n container.style.setProperty(property.shown, '0')\n container.setAttribute(FLUID_HOVER_ATTRIBUTE, name)\n marked()\n return () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n sizes?.disconnect()\n marks?.disconnect()\n container.removeAttribute(FLUID_HOVER_ATTRIBUTE)\n light(null)\n container.removeEventListener('pointermove', move)\n container.removeEventListener('pointerleave', leave)\n container.removeEventListener('focusin', focus)\n container.removeEventListener('focusout', blur)\n container.removeEventListener('click', click)\n container.removeEventListener('scroll', soon)\n window.removeEventListener('resize', soon)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * The custom property `KeyboardInset` writes on its element: how much of the layout\n * viewport's bottom the on-screen keyboard (or anything else the visual viewport leaves\n * out) covers, in pixels.\n */\nexport const KEYBOARD_INSET = '--fk-keyboard-inset'\n\n/**\n * The part of the layout viewport's height below the visual viewport: what the on-screen\n * keyboard covers. Rounded down, since a fraction of a pixel of zoom is no keyboard.\n */\nexport const keyboardInset = (view: {\n readonly innerHeight: number\n readonly visualViewport: { readonly height: number; readonly offsetTop: number } | null\n}): number =>\n view.visualViewport === null\n ? 0\n : Math.max(\n 0,\n Math.floor(view.innerHeight - view.visualViewport.height - view.visualViewport.offsetTop),\n )\n\n/**\n * The on-screen keyboard's height as a Mount, with no Message and no Model: where it is\n * is the browser's. iOS Safari, and Chrome on Android unless the page asks otherwise,\n * leave the layout viewport as it is when the keyboard opens, so a panel fixed to the\n * screen keeps its height and its bottom under the keys. This writes `KEYBOARD_INSET` on\n * the element, from the visual viewport's size and scroll, for a style to pad or shrink by\n * (`var(--fk-keyboard-inset, 0px)`), and removes it when the element goes. Where there is\n * no visual viewport it writes nothing.\n */\nexport const KeyboardInset = Mount.defineStream('KeyboardInset', {\n messages: [Schema.Never],\n args: {},\n execute: ({ element }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const view = element.ownerDocument.defaultView\n const viewport = view?.visualViewport\n if (\n !(element instanceof HTMLElement) ||\n view === null ||\n view === undefined ||\n viewport === null ||\n viewport === undefined\n ) {\n return () => {}\n }\n const target = element\n const measure = () => target.style.setProperty(KEYBOARD_INSET, `${keyboardInset(view)}px`)\n measure()\n viewport.addEventListener('resize', measure)\n viewport.addEventListener('scroll', measure)\n return () => {\n viewport.removeEventListener('resize', measure)\n viewport.removeEventListener('scroll', measure)\n target.style.removeProperty(KEYBOARD_INSET)\n }\n }),\n release => Effect.sync(release),\n ),\n ),\n})\n","import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * The attribute that marks a bar beside a scroller `ScrollBars` runs on, set\n * to the axis it shows: `block` (the up-and-down bar) or `inline`.\n */\nexport const SCROLL_BAR_ATTRIBUTE = 'data-scroll-bar'\n\n/**\n * The attribute `ScrollBars` sets on its scroller while it draws the bars, so a\n * style hides the native bar only then: with no Mount running (a coarse\n * pointer, a page not yet hydrated) the browser's bar stays.\n */\nexport const SCROLL_OVERLAID_ATTRIBUTE = 'data-scroll-overlaid'\n\n/**\n * The custom properties `ScrollBars` writes on each bar, in pixels, for its\n * thumb to read: how far along the bar the thumb starts, and how long it is.\n * Physical: an inline bar's offset is from its left edge in either direction.\n */\nexport const scrollThumb = {\n offset: '--fk-scroll-thumb-offset',\n size: '--fk-scroll-thumb-size',\n} as const\n\n/** The shortest a thumb is drawn, however long the content, so it stays a target. */\nconst SHORTEST = 20\n\nconst FINE_POINTER = '(hover: hover) and (pointer: fine)'\n\ntype Axis = 'block' | 'inline'\n\n/**\n * An overlay scrollbar as a Mount, with no Message and no Model: where a\n * scroller is scrolled is the browser's, and the bar only shows it.\n *\n * It runs on the scroller (or on an element holding it, named by `scroller`,\n * when the scroller carries another Mount) and drives the bars drawn beside\n * it: the scroller's parent's children marked `data-scroll-bar` (`block` or\n * `inline`), which a style lays over the scroller's edge. Each bar gets `data-scrollable` while its axis has\n * more to scroll, `data-shown` while the scroller scrolls or the pointer moves\n * over it, until `idle` milliseconds pass with neither (or longer, while the\n * pointer rests on a bar), and `data-dragging` while its thumb is dragged; and\n * `--fk-scroll-thumb-offset` and `-size` (see `scrollThumb`). Pressing a bar\n * off its thumb moves the thumb there, then drags it.\n *\n * It does nothing where the primary pointer is coarse or cannot hover, decided\n * when it mounts: touch keeps the browser's bar and its physics. Otherwise the\n * scroller gets `data-scroll-overlaid`, for a style to hide the native bar.\n * How the bar looks, rests, widens and fades is the style's.\n */\nexport const ScrollBars = Mount.defineStream('ScrollBars', {\n messages: [Schema.Never],\n args: {\n /** How long, in milliseconds, the bars stay after the last scroll or move. Default 600. */\n idle: Schema.optional(Schema.Number),\n /**\n * The scroller, as a selector within the element, when it cannot hold this\n * Mount itself (another component's, with a Mount of its own); looked for\n * once, when it mounts. Default: the element is the scroller.\n */\n scroller: Schema.optional(Schema.String),\n },\n execute: ({ element, idle = 600, scroller: within }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n if (typeof matchMedia !== 'function' || !matchMedia(FINE_POINTER).matches) {\n return () => {}\n }\n const found = within === undefined ? element : element.querySelector(within)\n if (!(found instanceof HTMLElement)) return () => {}\n const scroller = found\n const area = scroller.parentElement\n if (area === null) return () => {}\n\n const isBar = (child: Element): child is HTMLElement =>\n child instanceof HTMLElement && child.hasAttribute(SCROLL_BAR_ATTRIBUTE)\n /** Looked for at each use, so a redraw that replaced a bar is followed. */\n const bars = () => Array.from(area.children).filter(isBar)\n const axisOf = (bar: HTMLElement): Axis =>\n bar.getAttribute(SCROLL_BAR_ATTRIBUTE) === 'inline' ? 'inline' : 'block'\n\n /** The scroller along one axis, with the start measured from the top or the left. */\n const extent = (axis: Axis) => {\n if (axis === 'block') {\n return {\n view: scroller.clientHeight,\n content: scroller.scrollHeight,\n start: scroller.scrollTop,\n }\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n // A right-to-left scroller counts from 0 at the right down to minus its room.\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n return {\n view: scroller.clientWidth,\n content: scroller.scrollWidth,\n start: rtl ? room + scroller.scrollLeft : scroller.scrollLeft,\n }\n }\n const scrollTo = (axis: Axis, start: number) => {\n if (axis === 'block') {\n scroller.scrollTop = start\n return\n }\n const room = scroller.scrollWidth - scroller.clientWidth\n const rtl = getComputedStyle(scroller).direction === 'rtl'\n scroller.scrollLeft = rtl ? start - room : start\n }\n const trackOf = (bar: HTMLElement, axis: Axis) =>\n axis === 'block' ? bar.clientHeight : bar.clientWidth\n /** Where the thumb is along its bar, or nothing while the axis has nothing to scroll. */\n const thumbOf = (bar: HTMLElement, axis: Axis) => {\n const { view, content, start } = extent(axis)\n const track = trackOf(bar, axis)\n if (content - view < 1 || track <= 0) return null\n const size = Math.min(track, Math.max(SHORTEST, (track * view) / content))\n const offset = ((track - size) * start) / (content - view)\n return { track, size, offset, room: content - view }\n }\n const set = (bar: HTMLElement, name: string, value: string) => {\n if (bar.style.getPropertyValue(name) !== value) bar.style.setProperty(name, value)\n }\n const mark = (bar: HTMLElement, name: string, on: boolean) => {\n if (bar.hasAttribute(name) !== on) bar.toggleAttribute(name, on)\n }\n\n let frame: number | undefined\n const update = () => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n frame = undefined\n for (const bar of bars()) {\n const axis = axisOf(bar)\n const { view, content } = extent(axis)\n // Marked first: a style draws no bar until it is, so it has no length before.\n mark(bar, 'data-scrollable', content - view >= 1)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) continue\n set(bar, scrollThumb.offset, `${thumb.offset}px`)\n set(bar, scrollThumb.size, `${thumb.size}px`)\n }\n }\n const soon = () => {\n if (frame === undefined) frame = requestAnimationFrame(update)\n }\n\n let hiding: ReturnType<typeof setTimeout> | undefined\n let resting: HTMLElement | null = null\n /** Ends the drag under way, if one is. */\n let dragging: (() => void) | null = null\n const hide = () => {\n hiding = undefined\n // A bar the pointer rests on, or one being dragged, stays until it is left.\n if (resting !== null || dragging !== null) return\n for (const bar of bars()) mark(bar, 'data-shown', false)\n }\n const show = () => {\n for (const bar of bars()) mark(bar, 'data-shown', true)\n if (hiding !== undefined) clearTimeout(hiding)\n hiding = setTimeout(hide, idle)\n }\n\n const scrolled = () => {\n update()\n show()\n }\n // Listened to only while the pointer is over the area.\n const moved = (event: PointerEvent) => {\n if (event.pointerType !== 'touch') show()\n }\n const entered = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n area.addEventListener('pointermove', moved, { passive: true })\n show()\n }\n const left = () => {\n area.removeEventListener('pointermove', moved)\n resting = null\n // A hide that came while the pointer rested on a bar waited for this.\n if (hiding === undefined) hiding = setTimeout(hide, idle)\n }\n const over = (event: PointerEvent) => {\n const target = event.target\n resting =\n target instanceof Element ? (bars().find(bar => bar.contains(target)) ?? null) : null\n }\n\n const pressed = (event: PointerEvent) => {\n if (event.button !== 0 || event.pointerType === 'touch' || dragging !== null) return\n const target = event.target\n if (!(target instanceof Element)) return\n const bar = bars().find(each => each.contains(target))\n if (bar === undefined) return\n const axis = axisOf(bar)\n const thumb = thumbOf(bar, axis)\n if (thumb === null) return\n // The bar takes the press: no text selected, no focus moved off the scroller.\n event.preventDefault()\n const along = (at: PointerEvent) => {\n const box = bar.getBoundingClientRect()\n return axis === 'block'\n ? at.clientY - box.top - bar.clientTop\n : at.clientX - box.left - bar.clientLeft\n }\n const at = along(event)\n const onThumb = at >= thumb.offset && at <= thumb.offset + thumb.size\n // Held where it was taken, or by its middle when the press jumped it there.\n const grab = onThumb ? at - thumb.offset : thumb.size / 2\n const follow = (to: PointerEvent) => {\n const current = thumbOf(bar, axis)\n if (current === null) return\n const offset = Math.min(Math.max(along(to) - grab, 0), current.track - current.size)\n scrollTo(axis, (offset / (current.track - current.size)) * current.room)\n }\n const id = event.pointerId\n const move = (to: PointerEvent) => {\n if (to.pointerId === id) follow(to)\n }\n const end = (to: PointerEvent) => {\n if (to.pointerId === id) stop()\n }\n // On the document, for the drag alone: the pointer leaves the bar as it drags.\n const owner = bar.ownerDocument\n const stop = () => {\n owner.removeEventListener('pointermove', move)\n owner.removeEventListener('pointerup', end)\n owner.removeEventListener('pointercancel', end)\n mark(bar, 'data-dragging', false)\n dragging = null\n show()\n }\n owner.addEventListener('pointermove', move)\n owner.addEventListener('pointerup', end)\n owner.addEventListener('pointercancel', end)\n mark(bar, 'data-dragging', true)\n dragging = stop\n show()\n if (!onThumb) follow(event)\n }\n\n // Both made before anything observes: where one is missing, the Mount\n // fails with nothing attached.\n const sizes = new ResizeObserver(soon)\n // The content's size moves the thumb as much as the scroller's, so each\n // child of the scroller is watched, and each bar for its track. Only what\n // a change added or removed is watched or let go: a virtual list swaps\n // a row or two each frame it scrolls, out of many.\n const changes = new MutationObserver(records => {\n for (const record of records) {\n for (const node of Array.from(record.removedNodes)) {\n if (node instanceof Element) sizes.unobserve(node)\n }\n for (const node of Array.from(record.addedNodes)) {\n if (node instanceof Element && (record.target === scroller || isBar(node))) {\n sizes.observe(node)\n }\n }\n }\n soon()\n })\n sizes.observe(scroller)\n for (const child of Array.from(scroller.children)) sizes.observe(child)\n for (const bar of bars()) sizes.observe(bar)\n changes.observe(scroller, { childList: true })\n changes.observe(area, { childList: true })\n scroller.addEventListener('scroll', scrolled, { passive: true })\n area.addEventListener('pointerenter', entered)\n area.addEventListener('pointerleave', left)\n area.addEventListener('pointerover', over)\n area.addEventListener('pointerdown', pressed)\n scroller.setAttribute(SCROLL_OVERLAID_ATTRIBUTE, '')\n update()\n return () => {\n // Ended first: ending a drag shows the bars, which sets a hide to clear.\n dragging?.()\n if (frame !== undefined) cancelAnimationFrame(frame)\n if (hiding !== undefined) clearTimeout(hiding)\n sizes.disconnect()\n changes.disconnect()\n scroller.removeEventListener('scroll', scrolled)\n area.removeEventListener('pointerenter', entered)\n area.removeEventListener('pointerleave', left)\n area.removeEventListener('pointerover', over)\n area.removeEventListener('pointerdown', pressed)\n area.removeEventListener('pointermove', moved)\n scroller.removeAttribute(SCROLL_OVERLAID_ATTRIBUTE)\n for (const bar of bars()) {\n for (const name of ['data-scrollable', 'data-shown', 'data-dragging'])\n bar.removeAttribute(name)\n bar.style.removeProperty(scrollThumb.offset)\n bar.style.removeProperty(scrollThumb.size)\n }\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const SwipeStarted = Schema.TaggedStruct('SwipeStarted', {\n pointerId: Schema.Number,\n pointerType: Schema.String,\n /** The border box of what `measure` names (the element itself by default), as the swipe starts. */\n width: Schema.Number,\n height: Schema.Number,\n})\nexport type SwipeStarted = typeof SwipeStarted.Type\n\nexport const Swiped = Schema.TaggedStruct('Swiped', {\n pointerId: Schema.Number,\n /** From where the pointer went down, in CSS pixels. */\n deltaX: Schema.Number,\n deltaY: Schema.Number,\n})\nexport type Swiped = typeof Swiped.Type\n\nexport const SwipeEnded = Schema.TaggedStruct('SwipeEnded', {\n pointerId: Schema.Number,\n /** From where the pointer went down to where it came up, in CSS pixels. */\n deltaX: Schema.Number,\n deltaY: Schema.Number,\n /**\n * How fast the pointer was moving as it came up, in pixels a millisecond,\n * over the last `SWIPE_WINDOW` milliseconds: 0 when it rested there first.\n */\n velocityX: Schema.Number,\n velocityY: Schema.Number,\n /** `false` when the pointer was cancelled or capture was lost. */\n completed: Schema.Boolean,\n})\nexport type SwipeEnded = typeof SwipeEnded.Type\n\nexport type SwipeFact = SwipeStarted | Swiped | SwipeEnded\n\n/** How far back, in milliseconds, the release velocity looks. */\nexport const SWIPE_WINDOW = 100\n\n/**\n * What a swipe never starts on when its element `scrolls`: a field whose own\n * drag selects text or moves a thumb, and anything marked `data-no-swipe`.\n */\nexport const NO_SWIPE =\n 'input, textarea, select, [contenteditable=\"\"], [contenteditable=\"true\"], [data-no-swipe]'\n\ntype PointerLike = Event & {\n readonly pointerId?: number\n readonly button?: number\n readonly pointerType?: string\n readonly clientX?: number\n readonly clientY?: number\n}\n\ntype Capturing = Element & {\n setPointerCapture?: (pointerId: number) => void\n releasePointerCapture?: (pointerId: number) => void\n}\n\ninterface Sample {\n readonly at: number\n readonly x: number\n readonly y: number\n}\n\n/** A pointer or a touch being followed, from where it went down. */\ninterface Active {\n readonly pointerId: number\n readonly pointerType: string\n samples: Array<Sample>\n started: boolean\n}\n\n/** Every element a Swipe is mounted on: a touch inside one is that one's, not an outer one's. */\nconst owners = new WeakSet<Element>()\n\n/**\n * The velocity of the samples within `SWIPE_WINDOW` of the last: the way\n * from the oldest of them to the last over the time between. A pointer that\n * came to rest before the last sample has no recent way to measure, so 0.\n */\nexport const velocityOf = (samples: ReadonlyArray<Sample>): { x: number; y: number } => {\n const last = samples.at(-1)\n if (last === undefined) return { x: 0, y: 0 }\n const first = samples.find(sample => last.at - sample.at <= SWIPE_WINDOW) ?? last\n const elapsed = last.at - first.at\n return elapsed <= 0\n ? { x: 0, y: 0 }\n : { x: (last.x - first.x) / elapsed, y: (last.y - first.y) / elapsed }\n}\n\n/**\n * Whether anything from `target` up to `root` can still scroll along `axis`\n * the way a finger moving `along` (positive is down or right) pulls it: a\n * finger going down scrolls content toward its start.\n */\nexport const canScroll = (\n target: Element,\n root: Element,\n axis: 'x' | 'y',\n along: number,\n): boolean => {\n for (let at: Element | null = target; at !== null; at = at.parentElement) {\n const overflow = getComputedStyle(at)[axis === 'y' ? 'overflowY' : 'overflowX']\n if (overflow === 'auto' || overflow === 'scroll') {\n const position = Math.abs(axis === 'y' ? at.scrollTop : at.scrollLeft)\n const room =\n axis === 'y' ? at.scrollHeight - at.clientHeight : at.scrollWidth - at.clientWidth\n if (room > 1 && (along > 0 ? position > 0.5 : position < room - 0.5)) return true\n }\n if (at === root) return false\n }\n return false\n}\n\n/**\n * `Move` with the speed of its release, for a gesture that a flick ends\n * (a sheet dragged to dismiss, a card swiped away): a primary-button pointer\n * down (or, given a `slop`, its first move past it) captures the pointer,\n * each move reports the delta from where it was pressed, and up reports the\n * last delta with the velocity over the last `SWIPE_WINDOW` milliseconds, by\n * the events' own time stamps. Cancel or lost capture ends it incomplete.\n * The start reports the size of what is moved, so a distance can be read as\n * a share of it. What a delta or a speed means is the parent's `update`.\n * Capture is released with the Mount.\n *\n * Given `scrolls`, the element holds content that scrolls (a sheet's panel),\n * and a touch is followed by touch events, whose move can still refuse the\n * browser's scroll once the touch is under way, where a pointer's cannot:\n * past the slop, a touch that runs along the axis and finds nothing under it\n * that can scroll further its way swipes, and the browser scrolls any other.\n * A touch inside an element with a Swipe of its own (a handle in the panel)\n * is that one's, and none starts on a field or on `data-no-swipe`\n * (`NO_SWIPE`).\n */\nexport const Swipe = Mount.defineStream('Swipe', {\n messages: [SwipeStarted, Swiped, SwipeEnded],\n args: {\n /**\n * The nearest ancestor matching this selector is measured as the swipe\n * starts, for what the swipe moves (a sheet's panel, dragged by its\n * handle). Default: the element itself.\n */\n measure: Schema.optional(Schema.String),\n /**\n * How far, in pixels, a press must move before it is a swipe. Until\n * then nothing is captured or reported, so a press that stays put is\n * still a click on whatever is under it (a tab inside a drag grip).\n * Default 0: the press itself starts the swipe; with `scrolls`, the\n * first move decides.\n */\n slop: Schema.optional(Schema.Number),\n /** The axis the element's content scrolls along, which a touch yields to; see above. */\n scrolls: Schema.optional(Schema.Literals(['x', 'y'])),\n /** Follows touches alone: a mouse or a pen is left to the page (and to a handle's own Swipe). */\n touchOnly: Schema.optional(Schema.Boolean),\n },\n execute: ({ element, measure, slop = 0, scrolls, touchOnly = false }) =>\n Stream.callback<SwipeFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const target = element as Capturing\n let active: Active | null = null\n const offer = (fact: SwipeFact) => Queue.offerUnsafe(queue, fact)\n const sampleOf = (at: number, x = 0, y = 0): Sample => ({ at, x, y })\n const end = (pointerId: number, last: Sample, completed: boolean, captured: boolean) => {\n if (active === null || active.pointerId !== pointerId) return\n const { samples, started } = active\n active = null\n // A press that never moved past the slop was a click, not a swipe.\n if (!started) return\n if (captured) {\n try {\n target.releasePointerCapture?.(pointerId)\n } catch {\n // Capture may already be gone; the end is still reported.\n }\n }\n // A lost capture or a cancel carries no place: the last move's stands.\n const final = completed ? last : (samples.at(-1) ?? last)\n const all = completed ? [...samples, final] : samples\n const start = all[0] ?? final\n const velocity = completed ? velocityOf(all) : { x: 0, y: 0 }\n offer(\n SwipeEnded.make({\n pointerId,\n deltaX: final.x - start.x,\n deltaY: final.y - start.y,\n velocityX: velocity.x,\n velocityY: velocity.y,\n completed,\n }),\n )\n }\n // Report the size of what is moved; a pointer's swipe also captures it.\n const begin = (pointer: Active, capture: boolean) => {\n pointer.started = true\n if (capture) {\n try {\n target.setPointerCapture?.(pointer.pointerId)\n } catch {\n // Without capture the move still reports while over the element.\n }\n }\n const moved = measure === undefined ? element : (element.closest(measure) ?? element)\n const box = moved.getBoundingClientRect()\n offer(\n SwipeStarted.make({\n pointerId: pointer.pointerId,\n pointerType: pointer.pointerType,\n width: box.width,\n height: box.height,\n }),\n )\n }\n const moved = (pointer: Active, sample: Sample) => {\n const start = pointer.samples[0] ?? sample\n // Only what the velocity can still read, and where it began.\n pointer.samples = [\n start,\n ...pointer.samples.slice(1).filter(each => sample.at - each.at <= SWIPE_WINDOW),\n sample,\n ]\n offer(\n Swiped.make({\n pointerId: pointer.pointerId,\n deltaX: sample.x - start.x,\n deltaY: sample.y - start.y,\n }),\n )\n }\n // A touch this Swipe follows: started in it, on nothing of another Swipe's or NO_SWIPE.\n const ownTouch = (from: EventTarget | null): from is Element => {\n if (!(from instanceof Element)) return false\n const field = from.closest(NO_SWIPE)\n if (field !== null && element.contains(field)) return false\n for (\n let at: Element | null = from;\n at !== null && at !== element;\n at = at.parentElement\n )\n if (owners.has(at)) return false\n return true\n }\n const touchOf = (event: TouchEvent, id: number) =>\n Array.from(event.changedTouches).find(touch => touch.identifier === id)\n let touched: Element | null = null\n const pointerListeners: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n [\n 'pointerdown',\n event => {\n const pointer = event as PointerLike\n const type = pointer.pointerType ?? 'mouse'\n // Touch events follow a touch when the content scrolls.\n if (scrolls !== undefined && type === 'touch') return\n if (touchOnly && type !== 'touch') return\n if ((pointer.button ?? 0) !== 0 || active !== null) return\n active = {\n pointerId: pointer.pointerId ?? 0,\n pointerType: type,\n samples: [sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY)],\n started: false,\n }\n if (slop <= 0) begin(active, true)\n },\n ],\n [\n 'pointermove',\n event => {\n const pointer = event as PointerLike\n if (active === null || active.pointerId !== (pointer.pointerId ?? 0)) return\n const sample = sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY)\n if (!active.started) {\n const start = active.samples[0] ?? sample\n if (Math.hypot(sample.x - start.x, sample.y - start.y) < slop) return\n begin(active, true)\n }\n moved(active, sample)\n },\n ],\n ...(['pointerup', 'pointercancel', 'lostpointercapture'] as const).map(\n type =>\n [\n type,\n (event: Event) => {\n const pointer = event as PointerLike\n if (active?.pointerType === 'touch' && scrolls !== undefined) return\n end(\n pointer.pointerId ?? 0,\n sampleOf(pointer.timeStamp, pointer.clientX, pointer.clientY),\n type === 'pointerup',\n true,\n )\n },\n ] as const,\n ),\n ]\n const touchListeners: ReadonlyArray<readonly [string, (event: Event) => void]> =\n scrolls === undefined\n ? []\n : [\n [\n 'touchstart',\n event => {\n const touches = event as TouchEvent\n const touch = touches.changedTouches[0]\n if (active !== null || touches.touches.length !== 1 || touch === undefined)\n return\n if (!ownTouch(touches.target)) return\n touched = touches.target as Element\n active = {\n pointerId: touch.identifier,\n pointerType: 'touch',\n samples: [sampleOf(touches.timeStamp, touch.clientX, touch.clientY)],\n started: false,\n }\n },\n ],\n [\n 'touchmove',\n event => {\n const touches = event as TouchEvent\n if (active === null) return\n const touch = touchOf(touches, active.pointerId)\n if (touch === undefined) return\n const sample = sampleOf(touches.timeStamp, touch.clientX, touch.clientY)\n if (!active.started) {\n const start = active.samples[0] ?? sample\n const dx = sample.x - start.x\n const dy = sample.y - start.y\n if (Math.hypot(dx, dy) < Math.max(slop, 1)) return\n const along = scrolls === 'y' ? dy : dx\n const across = scrolls === 'y' ? dx : dy\n // Across the axis, into content that scrolls, or already\n // the browser's: the page's, and followed no further.\n if (\n Math.abs(across) > Math.abs(along) ||\n canScroll(touched ?? element, element, scrolls, along) ||\n !touches.cancelable\n ) {\n active = null\n return\n }\n begin(active, false)\n }\n touches.preventDefault()\n moved(active, sample)\n },\n ],\n ...(['touchend', 'touchcancel'] as const).map(\n type =>\n [\n type,\n (event: Event) => {\n const touches = event as TouchEvent\n if (active === null) return\n const touch = touchOf(touches, active.pointerId)\n if (touch === undefined) return\n end(\n active.pointerId,\n sampleOf(touches.timeStamp, touch.clientX, touch.clientY),\n type === 'touchend',\n false,\n )\n },\n ] as const,\n ),\n ]\n owners.add(element)\n for (const [type, listener] of pointerListeners) element.addEventListener(type, listener)\n // Not passive: a move that swipes refuses the browser's scroll.\n for (const [type, listener] of touchListeners)\n element.addEventListener(type, listener, { passive: false })\n return { pointerListeners, touchListeners, current: () => active }\n }),\n ({ pointerListeners, touchListeners, current }) =>\n Effect.sync(() => {\n owners.delete(element)\n for (const [type, listener] of pointerListeners)\n element.removeEventListener(type, listener)\n for (const [type, listener] of touchListeners)\n element.removeEventListener(type, listener)\n const pointer = current()\n if (pointer !== null && !(pointer.pointerType === 'touch' && scrolls !== undefined)) {\n try {\n ;(element as Capturing).releasePointerCapture?.(pointer.pointerId)\n } catch {\n // Already released.\n }\n }\n }),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const ScrollSettled = Schema.TaggedStruct('ScrollSettled', {\n /** The item whose start lies nearest the scroller's start, from 0. */\n index: Schema.Number,\n})\nexport type ScrollSettled = typeof ScrollSettled.Type\n\n/** How long a scroll must be still to count as settled, where `scrollend` is missing. */\nexport const SETTLE_QUIET = 120\n\n/**\n * Hears a scroller come to rest, as a Mount: after a swipe, a fling, a\n * trackpad or a scroll a Command made, it reports which of its items starts\n * nearest its own start (inside its `scroll-padding`), the start being the\n * right edge right to left. A snapping carousel reads it as the slide shown.\n *\n * At insert it first scrolls, at once, to item `start` (the Mount's args are\n * read only then, so this is where a redrawn or restored scroller begins),\n * and reports where it lies, since a scroller drawn already at rest sends no\n * `scrollend`. It listens for `scrollend` where the browser has it, and\n * otherwise for a scroll that is quiet for `SETTLE_QUIET` milliseconds.\n */\nexport const ScrollSettle = Mount.defineStream('ScrollSettle', {\n messages: [ScrollSettled],\n args: {\n /** Which children are the items; default every child. */\n item: Schema.optional(Schema.String),\n /** Default `inline`, the row a carousel scrolls along. */\n axis: Schema.optional(Schema.Literals(['inline', 'block'])),\n /** The item to scroll to at insert; default the first, which needs no scroll. */\n start: Schema.optional(Schema.Number),\n },\n execute: ({ element, item, axis = 'inline', start = 0 }) =>\n Stream.callback<ScrollSettled>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const items = () =>\n Array.from(\n item === undefined ? element.children : element.querySelectorAll(`:scope > ${item}`),\n )\n /** How far `child`'s start lies past the scroller's start, along the axis. */\n const offsetOf = (child: Element): number => {\n const style = getComputedStyle(element)\n const box = element.getBoundingClientRect()\n const own = child.getBoundingClientRect()\n if (axis === 'block') {\n return own.top - box.top - (parseFloat(style.scrollPaddingBlockStart) || 0)\n }\n const padding = parseFloat(style.scrollPaddingInlineStart) || 0\n return style.direction === 'rtl'\n ? box.right - padding - own.right\n : own.left - box.left - padding\n }\n const report = () => {\n let nearest = -1\n let distance = Infinity\n items().forEach((child, index) => {\n const away = Math.abs(offsetOf(child))\n if (away < distance) {\n nearest = index\n distance = away\n }\n })\n if (nearest >= 0) Queue.offerUnsafe(queue, ScrollSettled.make({ index: nearest }))\n }\n const first = items()[start]\n const before = element.scrollLeft + element.scrollTop\n if (start > 0 && first !== undefined) {\n const by = offsetOf(first)\n const rtl = axis === 'inline' && getComputedStyle(element).direction === 'rtl'\n // A larger `scrollLeft` moves the content toward the start either way, so right to\n // left the way to an item's start is the other sign. To a position, not by a\n // distance: a relative scroll stops at every `scroll-snap-stop: always` on the way.\n element.scrollTo(\n axis === 'block'\n ? { top: element.scrollTop + by, behavior: 'instant' }\n : { left: element.scrollLeft + (rtl ? -by : by), behavior: 'instant' },\n )\n }\n // A scroll just made reports itself when it ends; one that moved nothing never ends.\n if (element.scrollLeft + element.scrollTop === before) report()\n let quiet: ReturnType<typeof setTimeout> | undefined\n const hasEnd = 'onscrollend' in element\n const listener = hasEnd\n ? report\n : () => {\n clearTimeout(quiet)\n quiet = setTimeout(report, SETTLE_QUIET)\n }\n const type = hasEnd ? 'scrollend' : 'scroll'\n element.addEventListener(type, listener)\n return () => {\n clearTimeout(quiet)\n element.removeEventListener(type, listener)\n }\n }),\n detach => Effect.sync(detach),\n ),\n ),\n})\n","import { Effect, Option, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * A place in an element's padding box, in CSS pixels from its top left\n * corner, and the pointer's pressure there (0 to 1; a mouse reads 0.5 while\n * a button is down). A captured pointer can be outside the box, so `x` and\n * `y` can be negative or past its size.\n */\nexport const PointerPoint = Schema.Struct({\n x: Schema.Number,\n y: Schema.Number,\n pressure: Schema.Number,\n})\nexport type PointerPoint = typeof PointerPoint.Type\n\n/** The padding box's size at the event, in CSS pixels. */\nconst Size = { width: Schema.Number, height: Schema.Number }\n\nexport const PointerPressed = Schema.TaggedStruct('PointerPressed', {\n ...Size,\n point: PointerPoint,\n /** `mouse`, `pen` or `touch`, as the browser names it. */\n pointerType: Schema.String,\n})\nexport type PointerPressed = typeof PointerPressed.Type\n\nexport const PointerMoved = Schema.TaggedStruct('PointerMoved', {\n ...Size,\n /** Where the pointer is now. */\n point: PointerPoint,\n /**\n * Every place it passed since the last move, ending with `point`: the\n * browser's coalesced events, so a fast stroke keeps its curve. Just\n * `point` where the browser coalesces none.\n */\n points: Schema.Array(PointerPoint),\n})\nexport type PointerMoved = typeof PointerMoved.Type\n\nexport const PointerReleased = Schema.TaggedStruct('PointerReleased', {\n /** `false` when the pointer was cancelled, lost its capture, or pressed again unreleased. */\n completed: Schema.Boolean,\n})\nexport type PointerReleased = typeof PointerReleased.Type\n\nexport type PointerFact = PointerPressed | PointerMoved | PointerReleased\n\ninterface Sides {\n readonly top: number\n readonly right: number\n readonly bottom: number\n readonly left: number\n}\n\nexport interface Rect {\n readonly left: number\n readonly top: number\n readonly width: number\n readonly height: number\n}\n\n/**\n * The padding box of an element whose border box is `rect`: inside its\n * border, padding included. An absolutely positioned child (a thumb, a\n * stroke) is laid out against it, so a place read here is where that child\n * sits, whatever padding a stylist adds.\n */\nexport const paddingBoxOf = (layout: { readonly rect: Rect; readonly border: Sides }): Rect => {\n const { rect, border } = layout\n return {\n left: rect.left + border.left,\n top: rect.top + border.top,\n width: Math.max(0, rect.width - border.left - border.right),\n height: Math.max(0, rect.height - border.top - border.bottom),\n }\n}\n\nconst borderOf = (style: CSSStyleDeclaration): Sides => ({\n top: parseFloat(style.borderTopWidth),\n right: parseFloat(style.borderRightWidth),\n bottom: parseFloat(style.borderBottomWidth),\n left: parseFloat(style.borderLeftWidth),\n})\n\n/**\n * An element's padding box now, in the viewport, as `PointerPosition`\n * measures it: for a size kept beside its places, which a `ResizeObserver`'s\n * content box does not match once the element has padding. Read from the\n * bounding rectangle and the computed border, since `clientWidth` and\n * `clientLeft` round to whole pixels.\n */\nexport const measurePaddingBox = (element: Element): Rect =>\n paddingBoxOf({\n rect: element.getBoundingClientRect(),\n border: borderOf(getComputedStyle(element)),\n })\n\nconst pointIn = (box: Rect, event: PointerEvent): PointerPoint => ({\n x: event.clientX - box.left,\n y: event.clientY - box.top,\n pressure: event.pressure,\n})\n\n/**\n * Where one pointer is inside an element, as a Mount, for a surface the\n * pointer draws on or points into (a color area, a dial, a signature pad): a\n * primary press, each move until the release, and the release, each with\n * the place in the element's padding box and the box's size. The box is\n * measured at each event, so an element that moved or resized is followed.\n * Coordinates are raw, left to right and top down whatever the direction:\n * what a place means (a share, an angle, a reading direction) is the parent's.\n *\n * The pointer is captured from press to release, so a drag that leaves the\n * element is still heard, and the moves and the release are listened to only\n * meanwhile. A press keeps the browser's own focus and text selection away,\n * and a second pointer while one is down is ignored.\n */\nexport const PointerPosition = Mount.defineStream('PointerPosition', {\n messages: [PointerPressed, PointerMoved, PointerReleased],\n args: {\n /**\n * A descendant to focus on a press, found by this selector (a thumb), so\n * the keys go on from where the pointer left it.\n */\n focus: Schema.optionalKey(Schema.String),\n },\n execute: ({ element, focus }) =>\n Stream.callback<PointerFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const offer = (fact: PointerFact) => Queue.offerUnsafe(queue, fact)\n let held: Option.Option<number> = Option.none()\n const ours = (event: Event): event is PointerEvent =>\n event instanceof PointerEvent && Option.contains(held, event.pointerId)\n\n const release = () => {\n if (Option.isNone(held)) return\n const pointerId = held.value\n held = Option.none()\n for (const [type, listener] of during) element.removeEventListener(type, listener)\n try {\n element.releasePointerCapture(pointerId)\n } catch {\n // Capture may already be gone with the pointer.\n }\n }\n const end = (completed: boolean) => (event: Event) => {\n if (!ours(event)) return\n release()\n offer(PointerReleased.make({ completed }))\n }\n const move = (event: Event) => {\n if (!ours(event)) return\n const box = measurePaddingBox(element)\n const point = pointIn(box, event)\n // Safari coalesces none and has no method for it.\n const coalesced = event.getCoalescedEvents?.() ?? []\n offer(\n PointerMoved.make({\n width: box.width,\n height: box.height,\n point,\n points: coalesced.length > 0 ? coalesced.map(one => pointIn(box, one)) : [point],\n }),\n )\n }\n const during: ReadonlyArray<readonly [string, (event: Event) => void]> = [\n ['pointermove', move],\n ['pointerup', end(true)],\n ['pointercancel', end(false)],\n ['lostpointercapture', end(false)],\n ]\n\n const down = (event: Event) => {\n if (!(event instanceof PointerEvent) || event.button !== 0) return\n if (Option.isSome(held)) {\n if (!ours(event)) return\n // The same pointer down again: its release went where nothing heard it.\n release()\n offer(PointerReleased.make({ completed: false }))\n }\n held = Option.some(event.pointerId)\n for (const [type, listener] of during) element.addEventListener(type, listener)\n try {\n element.setPointerCapture(event.pointerId)\n } catch {\n // A pointer the browser no longer tracks cannot be captured; its moves over the element still come.\n }\n // Kept from the browser's own focus and text selection, and from the mouse events a touch also sends.\n event.preventDefault()\n if (focus !== undefined) {\n const into = element.querySelector(focus)\n if (into instanceof HTMLElement) into.focus()\n }\n const box = measurePaddingBox(element)\n offer(\n PointerPressed.make({\n width: box.width,\n height: box.height,\n point: pointIn(box, event),\n pointerType: event.pointerType,\n }),\n )\n }\n element.addEventListener('pointerdown', down)\n return () => {\n element.removeEventListener('pointerdown', down)\n release()\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/** The attribute on the mounted element naming the element `TrackBox` follows, by id. */\nexport const TRACK_TARGET_ATTRIBUTE = 'data-target'\n\n/** The custom properties `TrackBox` writes for `name`, as `measured` names `Measure`'s. */\nexport const trackedBox = (name: string) =>\n ({\n x: `--fk-${name}-x`,\n y: `--fk-${name}-y`,\n w: `--fk-${name}-w`,\n h: `--fk-${name}-h`,\n radius: `--fk-${name}-radius`,\n }) as const\n\n/** Sent as the followed element changes: its id, and whether it is on the page. */\nexport const TrackedTarget = Schema.TaggedStruct('TrackedTarget', {\n target: Schema.String,\n found: Schema.Boolean,\n})\nexport type TrackedTarget = typeof TrackedTarget.Type\n\n/**\n * The radius a box of `width` by `height` draws for a computed\n * `border-top-left-radius` of `value` (`8px`, `50%`, `8px 4px`): its\n * horizontal length in pixels, a share of the width for a percentage, and\n * never more than half the shorter side, where the browser stops it.\n */\nexport const cornerRadius = (value: string, width: number, height: number): number => {\n const first = value.trim().split(/\\s+/)[0] ?? ''\n const length = parseFloat(first)\n if (!Number.isFinite(length)) return 0\n const pixels = first.endsWith('%') ? (length * width) / 100 : length\n return Math.max(0, Math.min(pixels, width / 2, height / 2))\n}\n\n/**\n * Follows another element's box, as a Mount: the element whose id is the\n * mounted element's `data-target` (`TRACK_TARGET_ATTRIBUTE`). Its box in\n * viewport pixels is written on the mounted element as `--fk-<name>-x`,\n * `-y`, `-w` and `-h`, and with `radius`, its top left corner's radius as\n * `--fk-<name>-radius` (`cornerRadius`), so a fixed overlay drawn from them\n * (a tour's cutout, a coach mark's ring) sits over it. While nothing is\n * followed they are removed, so a stylist's fallbacks apply.\n *\n * The box is read again on a scroll anywhere (heard on the way down, since\n * `scroll` does not bubble), a window resize, the followed element's own\n * resize, and any change to the document's elements, which is also how a\n * target drawn anew under the same id is found. `data-target` is read again\n * whenever it changes, so one element can glide from target to target\n * without being drawn again, which a Mount's args, read once, could not do.\n * What moves the target by any other way (a stylesheet added) is seen at the\n * next of these.\n *\n * Whether a target is on the page is the parent's to act on (a tour shows\n * the step in the middle instead), so each change of the target or of\n * whether it is found sends `TrackedTarget`, starting with the first one.\n * Since it sends a Message, a component may draw it by default: a Scene test\n * resolves it with what the parent maps it to. An empty `data-target` follows\n * nothing and sends nothing.\n */\nexport const TrackBox = Mount.defineStream('TrackBox', {\n messages: [TrackedTarget],\n args: {\n /** The custom properties' prefix: `tour` writes `--fk-tour-x`. */\n name: Schema.String,\n /** Whether to write the target's corner radius too; it reads the target's computed style. */\n radius: Schema.optional(Schema.Boolean),\n },\n execute: ({ element, name, radius = false }) =>\n Stream.callback<TrackedTarget>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const document = element.ownerDocument\n const view = document.defaultView\n const properties = trackedBox(name)\n const style = element instanceof HTMLElement ? element.style : undefined\n let target: Element | null = null\n let told: TrackedTarget | undefined\n\n const place = () => {\n if (style === undefined) return\n if (target === null) {\n for (const property of Object.values(properties)) style.removeProperty(property)\n return\n }\n const box = target.getBoundingClientRect()\n style.setProperty(properties.x, `${box.left}px`)\n style.setProperty(properties.y, `${box.top}px`)\n style.setProperty(properties.w, `${box.width}px`)\n style.setProperty(properties.h, `${box.height}px`)\n if (radius) {\n const corner = getComputedStyle(target).borderTopLeftRadius\n style.setProperty(\n properties.radius,\n `${cornerRadius(corner, box.width, box.height)}px`,\n )\n }\n }\n // Looks the target up again, telling the parent when what it follows, or whether\n // that is found, changed.\n const follow = () => {\n const id = element.getAttribute(TRACK_TARGET_ATTRIBUTE) ?? ''\n const found = id === '' ? null : document.getElementById(id)\n if (found !== target) {\n if (target !== null) resized.unobserve(target)\n if (found !== null) resized.observe(found)\n target = found\n }\n place()\n if (id !== '' && (told?.target !== id || told.found !== (found !== null))) {\n told = TrackedTarget.make({ target: id, found: found !== null })\n Queue.offerUnsafe(queue, told)\n }\n }\n\n // Every observer is made before any observes, so one that throws (jsdom has no\n // ResizeObserver) leaves nothing attached.\n const resized = new ResizeObserver(place)\n const changed = new MutationObserver(follow)\n changed.observe(element, {\n attributes: true,\n attributeFilter: [TRACK_TARGET_ATTRIBUTE],\n })\n changed.observe(document, { childList: true, subtree: true })\n view?.addEventListener('scroll', place, { capture: true, passive: true })\n view?.addEventListener('resize', place)\n follow()\n return () => {\n changed.disconnect()\n resized.disconnect()\n view?.removeEventListener('scroll', place, { capture: true })\n view?.removeEventListener('resize', place)\n }\n }),\n stop => Effect.sync(stop),\n ),\n ),\n})\n","/**\n * An image fetched and decoded before it is shown, as a Command: a lightbox\n * or a carousel asks for the next picture, and shows it on `Decoded`, so the\n * switch never passes through a blank frame. A Command, not a Mount: the\n * Model decides to show the image, so the Message that leads there carries\n * the news that it is ready.\n */\nimport { Effect, Schema } from 'effect'\nimport type { Command } from 'foldkit/command'\nimport { defineMessageUnion } from 'foldkit/message'\n\nexport const ImageDecodeMessage = defineMessageUnion({\n Decoded: { src: Schema.String },\n DecodeFailed: { src: Schema.String, message: Schema.String },\n})\nexport type ImageDecodeMessage = typeof ImageDecodeMessage.Type\n\n/** What to decode: a URL, or an `img`'s candidates, so the browser decodes the one it would draw. */\nexport interface ImageSource {\n readonly src: string\n readonly srcset?: string | undefined\n readonly sizes?: string | undefined\n}\n\n/**\n * Fetches and decodes `source` (`img.decode()`), yielding `Decoded` once it\n * can be painted at once, or `DecodeFailed` when it cannot be fetched or read,\n * or there is no document (a server render). Given `srcset` and `sizes`, as\n * `foldkit-media`'s `Picture.Img` has them, the browser picks the candidate\n * it would draw, so the decoded file is the one shown.\n */\nexport const decodeImage = (source: ImageSource): Command<ImageDecodeMessage, never, never> => ({\n name: 'Image.decode',\n args: { src: source.src },\n effect:\n typeof document === 'undefined'\n ? Effect.succeed(\n ImageDecodeMessage.DecodeFailed({ src: source.src, message: 'there is no document' }),\n )\n : Effect.matchEffect(\n Effect.tryPromise({\n try: () => {\n const image = new Image()\n // Before `src`, so the browser chooses among the candidates, not the fallback.\n if (source.sizes !== undefined) image.sizes = source.sizes\n if (source.srcset !== undefined) image.srcset = source.srcset\n image.src = source.src\n return image.decode()\n },\n catch: error => (error instanceof Error ? error.message : String(error)),\n }),\n {\n onFailure: message =>\n Effect.succeed(ImageDecodeMessage.DecodeFailed({ src: source.src, message })),\n onSuccess: () => Effect.succeed(ImageDecodeMessage.Decoded({ src: source.src })),\n },\n ),\n})\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Coordinates, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, LiveStream, LiveStreamService, MediaDevice, MediaDevicesHandle, MediaDevicesMessage, MediaDevicesModel, MediaStreamConstraints, MediaStreamHandle, MediaStreamMessage, MediaStreamModel, MediaTrackHandle, PermissionState, PermissionStatusHandle, PermissionsHandle, PermissionsMessage, PermissionsModel, Watch, WatchService, enterFullscreen, exitFullscreen, fullscreenChanges, mediaDevices, mediaStream, permissions } from "./device/index.mjs";
2
2
  import { A as Moved, C as TargetPressed, D as Move, E as Fact, M as ScrollLock, N as FocusScope, O as MoveEnded, P as tabbableWithin, S as TargetHovered, T as targetOf, _ as HOLD_TO_DRAG_MS, a as TextEdited, b as zoneOf, c as DRAG_THRESHOLD, d as DragFact, f as DragPlace, g as HOLD_SLOP, h as DraggedOver, i as TextCommitted, j as HideOutside, k as MoveStarted, l as DragCancelled, m as DragZone, n as EditableText, o as TextFact, p as DragStarted, r as TextCancelled, s as textOf, t as EditAsked, u as DragDropped, v as PointerDrag, w as Targets, x as TargetFact, y as boxOf } from "./editable-text-1D31qthY.mjs";
3
- import { Autofocus, ClipboardMessage, ClipboardReadMessage, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidAxis, FluidHover, Focused, FollowTabStop, Input, InputMask, KEYBOARD_INSET, KeepInView, KeepScrollOptions, KeyboardInset, Measure, PointerFact, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, Rect, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeFact, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TrackBox, TrackedTarget, applyMask, copyText, cornerRadius, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, trackedBox, velocityOf } from "./dom/index.mjs";
3
+ import { Autofocus, ClipboardMessage, ClipboardReadMessage, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidAxis, FluidHover, Focused, FollowTabStop, ImageDecodeMessage, ImageSource, Input, InputMask, KEYBOARD_INSET, KeepInView, KeepScrollOptions, KeyboardInset, Measure, NO_SWIPE, PointerFact, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, Rect, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeFact, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TrackBox, TrackedTarget, applyMask, canScroll, copyText, cornerRadius, decodeImage, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, trackedBox, velocityOf } from "./dom/index.mjs";
4
4
  import { a as modalityOfKey, i as Modality, n as InputModalityMessage, r as InputModalityModel, t as InputModality } from "./input-modality-BY-bSrEc.mjs";
5
5
  import { ActiveElementMessage, Idle, IdleMessage, IdleModel, KeyPress, KeyboardMessage, PointerMessage, ScrollMessage, Visibility, VisibilityMessage, VisibilityModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, keyboardEvents, matchHotkey, pointerEvents, scrollEvents } from "./events/index.mjs";
6
6
  import { Breakpoints, BreakpointsMessage, BreakpointsModel, MediaQuery, MediaQueryMessage, MediaQueryModel, Platform, PlatformHints, PrefersDark, PrefersReducedMotion, breakpointFor, isBrowser, isServer, platformFromUA } from "./media/index.mjs";
@@ -9,4 +9,4 @@ import { Acquired, AcquiredSource, BroadcastChannelHandle, BroadcastMessage, Con
9
9
  import { Bounds, Intersection, IntersectionChanged, Measured, Mutated, Mutation, Resize, Resized } from "./observers/index.mjs";
10
10
  import { History, HistoryModel, Locale, LocaleMessage, LocaleModel, MasonryPlacement, MeasureRow, Pagination, PaginationMessage, PaginationModel, RowMeasured, SelectionSet, SelectionSetMessage, SelectionSetModel, Viewport, ViewportScrolled, Virtual, VirtualLayout, VirtualMessage, VirtualModel, VirtualWindow, canRedo, canUndo, distanceToEnd, history, isAtEnd, isSelected, masonry, offset, offsetFor, pageCount, range, stickyHeader, totalHeight, visibleRange, windowFor } from "./state/index.mjs";
11
11
  import { Interval, IntervalMessage, IntervalModel, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, debounce, formatRelativeTime, ticks } from "./time/index.mjs";
12
- export { Acquired, AcquiredSource, ActiveElementMessage, Autofocus, Bounds, Breakpoints, BreakpointsMessage, BreakpointsModel, BroadcastChannelHandle, BroadcastMessage, ClipboardMessage, ClipboardReadMessage, Conversation, ConversationHandler, Coordinates, DRAG_THRESHOLD, DragCancelled, DragDropped, DragFact, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, Fact, FluidAxis, FluidHover, FocusScope, Focused, FollowTabStop, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, History, HistoryModel, Idle, IdleMessage, IdleModel, Input, InputMask, InputModality, InputModalityMessage, InputModalityModel, Intersection, IntersectionChanged, Interval, IntervalMessage, IntervalModel, KEYBOARD_INSET, KeepInView, KeepScrollOptions, KeyPress, KeyboardInset, KeyboardMessage, LiveStream, LiveStreamService, Locale, LocaleMessage, LocaleModel, MasonryPlacement, Measure, MeasureRow, Measured, MediaDevice, MediaDevicesHandle, MediaDevicesMessage, MediaDevicesModel, MediaQuery, MediaQueryMessage, MediaQueryModel, MediaStreamConstraints, MediaStreamHandle, MediaStreamMessage, MediaStreamModel, MediaTrackHandle, Modality, motion_d_exports as Motion, Move, MoveEnded, MoveStarted, Moved, Mutated, Mutation, Online, OnlineMessage, OnlineModel, Pagination, PaginationMessage, PaginationModel, PermissionState, PermissionStatusHandle, PermissionsHandle, PermissionsMessage, PermissionsModel, Platform, PlatformHints, PointerDrag, PointerFact, PointerMessage, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, PrefersDark, PrefersReducedMotion, Presence, PresenceMessage, PresenceModel, Rect, Resize, Resized, RowMeasured, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollMessage, ScrollSettle, ScrollSettled, SelectionSet, SelectionSetMessage, SelectionSetModel, ShareData, ShareMessage, SharedHost, SharedHostConnection, SharedHostOptions, Socket, SocketHandle, SocketService, SocketView, Source, SourceHandle, SourceService, Spring, SpringMessage, SpringModel, SseMessage, SseModel, SseView, StartHost, Swipe, SwipeEnded, SwipeFact, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetFact, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, TextFact, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, TrackBox, TrackedTarget, Tween, TweenMessage, TweenModel, Viewport, ViewportScrolled, Virtual, VirtualLayout, VirtualMessage, VirtualModel, VirtualWindow, Visibility, VisibilityMessage, VisibilityModel, Watch, WatchService, WebSocketMessage, WebSocketModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, applyMask, boxOf, breakpointFor, broadcastMessages, canRedo, canUndo, copyText, cornerRadius, debounce, distanceToEnd, enterFullscreen, exitFullscreen, fluidHovered, formatRelativeTime, fullscreenChanges, history, isAtEnd, isBrowser, isLive, isOpen, isSelected, isServer, isVisible, keepScroll, keyboardEvents, keyboardInset, loadScript, masonry, matchHotkey, measurePaddingBox, measured, mediaDevices, mediaStream, modalityOfKey, offset, offsetFor, paddingBoxOf, pageCount, permissions, platformFromUA, pointedLinks, pointerEvents, postBroadcast, range, readText, scrollEvents, scrollThumb, share, sse, stickyHeader, tabbableWithin, targetOf, textOf, ticks, totalHeight, trackedBox, velocityOf, viewOf, viewOfSse, visibleRange, websocket, windowFor, zoneOf };
12
+ export { Acquired, AcquiredSource, ActiveElementMessage, Autofocus, Bounds, Breakpoints, BreakpointsMessage, BreakpointsModel, BroadcastChannelHandle, BroadcastMessage, ClipboardMessage, ClipboardReadMessage, Conversation, ConversationHandler, Coordinates, DRAG_THRESHOLD, DragCancelled, DragDropped, DragFact, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, Fact, FluidAxis, FluidHover, FocusScope, Focused, FollowTabStop, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, History, HistoryModel, Idle, IdleMessage, IdleModel, ImageDecodeMessage, ImageSource, Input, InputMask, InputModality, InputModalityMessage, InputModalityModel, Intersection, IntersectionChanged, Interval, IntervalMessage, IntervalModel, KEYBOARD_INSET, KeepInView, KeepScrollOptions, KeyPress, KeyboardInset, KeyboardMessage, LiveStream, LiveStreamService, Locale, LocaleMessage, LocaleModel, MasonryPlacement, Measure, MeasureRow, Measured, MediaDevice, MediaDevicesHandle, MediaDevicesMessage, MediaDevicesModel, MediaQuery, MediaQueryMessage, MediaQueryModel, MediaStreamConstraints, MediaStreamHandle, MediaStreamMessage, MediaStreamModel, MediaTrackHandle, Modality, motion_d_exports as Motion, Move, MoveEnded, MoveStarted, Moved, Mutated, Mutation, NO_SWIPE, Online, OnlineMessage, OnlineModel, Pagination, PaginationMessage, PaginationModel, PermissionState, PermissionStatusHandle, PermissionsHandle, PermissionsMessage, PermissionsModel, Platform, PlatformHints, PointerDrag, PointerFact, PointerMessage, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, PrefersDark, PrefersReducedMotion, Presence, PresenceMessage, PresenceModel, Rect, Resize, Resized, RowMeasured, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollMessage, ScrollSettle, ScrollSettled, SelectionSet, SelectionSetMessage, SelectionSetModel, ShareData, ShareMessage, SharedHost, SharedHostConnection, SharedHostOptions, Socket, SocketHandle, SocketService, SocketView, Source, SourceHandle, SourceService, Spring, SpringMessage, SpringModel, SseMessage, SseModel, SseView, StartHost, Swipe, SwipeEnded, SwipeFact, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetFact, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, TextFact, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, TrackBox, TrackedTarget, Tween, TweenMessage, TweenModel, Viewport, ViewportScrolled, Virtual, VirtualLayout, VirtualMessage, VirtualModel, VirtualWindow, Visibility, VisibilityMessage, VisibilityModel, Watch, WatchService, WebSocketMessage, WebSocketModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, applyMask, boxOf, breakpointFor, broadcastMessages, canRedo, canScroll, canUndo, copyText, cornerRadius, debounce, decodeImage, distanceToEnd, enterFullscreen, exitFullscreen, fluidHovered, formatRelativeTime, fullscreenChanges, history, isAtEnd, isBrowser, isLive, isOpen, isSelected, isServer, isVisible, keepScroll, keyboardEvents, keyboardInset, loadScript, masonry, matchHotkey, measurePaddingBox, measured, mediaDevices, mediaStream, modalityOfKey, offset, offsetFor, paddingBoxOf, pageCount, permissions, platformFromUA, pointedLinks, pointerEvents, postBroadcast, range, readText, scrollEvents, scrollThumb, share, sse, stickyHeader, tabbableWithin, targetOf, textOf, ticks, totalHeight, trackedBox, velocityOf, viewOf, viewOfSse, visibleRange, websocket, windowFor, zoneOf };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { A as FocusScope, C as targetOf, D as Moved, E as MoveStarted, O as HideOutside, S as Targets, T as MoveEnded, _ as PointerDrag, a as TextCommitted, b as TargetHovered, c as DRAG_THRESHOLD, d as DragPlace, f as DragStarted, g as HOLD_TO_DRAG_MS, h as HOLD_SLOP, i as TextCancelled, j as tabbableWithin, k as ScrollLock, l as DragCancelled, m as DraggedOver, n as EditAsked, o as TextEdited, p as DragZone, r as EditableText, s as textOf, t as FollowTabStop, u as DragDropped, v as boxOf, w as Move, x as TargetPressed, y as zoneOf } from "./follow-tab-stop-Caog2qg1.mjs";
2
- import { Autofocus, ClipboardMessage, ClipboardReadMessage, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, Focused, Input, InputMask, KEYBOARD_INSET, KeepInView, KeyboardInset, Measure, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TrackBox, TrackedTarget, applyMask, copyText, cornerRadius, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, trackedBox, velocityOf } from "./dom/index.mjs";
2
+ import { Autofocus, ClipboardMessage, ClipboardReadMessage, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, Focused, ImageDecodeMessage, Input, InputMask, KEYBOARD_INSET, KeepInView, KeyboardInset, Measure, NO_SWIPE, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollSettle, ScrollSettled, ShareData, ShareMessage, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TrackBox, TrackedTarget, applyMask, canScroll, copyText, cornerRadius, decodeImage, fluidHovered, keepScroll, keyboardInset, loadScript, measurePaddingBox, measured, paddingBoxOf, pointedLinks, readText, scrollThumb, share, trackedBox, velocityOf } from "./dom/index.mjs";
3
3
  import { Coordinates, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, LiveStream, MediaDevice, MediaDevicesMessage, MediaDevicesModel, MediaStreamMessage, MediaStreamModel, PermissionState, PermissionsMessage, PermissionsModel, Watch, enterFullscreen, exitFullscreen, fullscreenChanges, mediaDevices, mediaStream, permissions } from "./device/index.mjs";
4
4
  import { a as modalityOfKey, i as Modality, n as InputModalityMessage, r as InputModalityModel, t as InputModality } from "./input-modality-BXD383jg.mjs";
5
5
  import { ActiveElementMessage, Idle, IdleMessage, IdleModel, KeyboardMessage, PointerMessage, ScrollMessage, Visibility, VisibilityMessage, VisibilityModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, keyboardEvents, matchHotkey, pointerEvents, scrollEvents } from "./events/index.mjs";
@@ -9,4 +9,4 @@ import { BroadcastMessage, Online, OnlineMessage, OnlineModel, SharedHost, Socke
9
9
  import { Bounds, Intersection, IntersectionChanged, Measured, Mutated, Mutation, Resize, Resized } from "./observers/index.mjs";
10
10
  import { History, HistoryModel, Locale, LocaleMessage, LocaleModel, MeasureRow, Pagination, PaginationMessage, PaginationModel, RowMeasured, SelectionSet, SelectionSetMessage, SelectionSetModel, Viewport, ViewportScrolled, Virtual, VirtualMessage, VirtualModel, canRedo, canUndo, distanceToEnd, history, isAtEnd, isSelected, masonry, offset, offsetFor, pageCount, range, stickyHeader, totalHeight, visibleRange, windowFor } from "./state/index.mjs";
11
11
  import { Interval, IntervalMessage, IntervalModel, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, debounce, formatRelativeTime, ticks } from "./time/index.mjs";
12
- export { ActiveElementMessage, Autofocus, Bounds, Breakpoints, BreakpointsMessage, BreakpointsModel, BroadcastMessage, ClipboardMessage, ClipboardReadMessage, Coordinates, DRAG_THRESHOLD, DragCancelled, DragDropped, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, FocusScope, Focused, FollowTabStop, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, History, HistoryModel, Idle, IdleMessage, IdleModel, Input, InputMask, InputModality, InputModalityMessage, InputModalityModel, Intersection, IntersectionChanged, Interval, IntervalMessage, IntervalModel, KEYBOARD_INSET, KeepInView, KeyboardInset, KeyboardMessage, LiveStream, Locale, LocaleMessage, LocaleModel, Measure, MeasureRow, Measured, MediaDevice, MediaDevicesMessage, MediaDevicesModel, MediaQuery, MediaQueryMessage, MediaQueryModel, MediaStreamMessage, MediaStreamModel, Modality, motion_exports as Motion, Move, MoveEnded, MoveStarted, Moved, Mutated, Mutation, Online, OnlineMessage, OnlineModel, Pagination, PaginationMessage, PaginationModel, PermissionState, PermissionsMessage, PermissionsModel, Platform, PointerDrag, PointerMessage, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, PrefersDark, PrefersReducedMotion, Presence, PresenceMessage, PresenceModel, Resize, Resized, RowMeasured, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollMessage, ScrollSettle, ScrollSettled, SelectionSet, SelectionSetMessage, SelectionSetModel, ShareData, ShareMessage, SharedHost, Socket, SocketView, Source, Spring, SpringMessage, SpringModel, SseMessage, SseModel, SseView, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, TrackBox, TrackedTarget, Tween, TweenMessage, TweenModel, Viewport, ViewportScrolled, Virtual, VirtualMessage, VirtualModel, Visibility, VisibilityMessage, VisibilityModel, Watch, WebSocketMessage, WebSocketModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, applyMask, boxOf, breakpointFor, broadcastMessages, canRedo, canUndo, copyText, cornerRadius, debounce, distanceToEnd, enterFullscreen, exitFullscreen, fluidHovered, formatRelativeTime, fullscreenChanges, history, isAtEnd, isBrowser, isLive, isOpen, isSelected, isServer, isVisible, keepScroll, keyboardEvents, keyboardInset, loadScript, masonry, matchHotkey, measurePaddingBox, measured, mediaDevices, mediaStream, modalityOfKey, offset, offsetFor, paddingBoxOf, pageCount, permissions, platformFromUA, pointedLinks, pointerEvents, postBroadcast, range, readText, scrollEvents, scrollThumb, share, sse, stickyHeader, tabbableWithin, targetOf, textOf, ticks, totalHeight, trackedBox, velocityOf, viewOf, viewOfSse, visibleRange, websocket, windowFor, zoneOf };
12
+ export { ActiveElementMessage, Autofocus, Bounds, Breakpoints, BreakpointsMessage, BreakpointsModel, BroadcastMessage, ClipboardMessage, ClipboardReadMessage, Coordinates, DRAG_THRESHOLD, DragCancelled, DragDropped, DragPlace, DragStarted, DragZone, DraggedOver, EditAsked, EditableText, FLUID_HOVER_ATTRIBUTE, FLUID_LIT_ATTRIBUTE, FLUID_PRESS_ATTRIBUTE, FluidHover, FocusScope, Focused, FollowTabStop, FullscreenMessage, Geolocation, GeolocationMessage, GeolocationModel, HOLD_SLOP, HOLD_TO_DRAG_MS, HideOutside, History, HistoryModel, Idle, IdleMessage, IdleModel, ImageDecodeMessage, Input, InputMask, InputModality, InputModalityMessage, InputModalityModel, Intersection, IntersectionChanged, Interval, IntervalMessage, IntervalModel, KEYBOARD_INSET, KeepInView, KeyboardInset, KeyboardMessage, LiveStream, Locale, LocaleMessage, LocaleModel, Measure, MeasureRow, Measured, MediaDevice, MediaDevicesMessage, MediaDevicesModel, MediaQuery, MediaQueryMessage, MediaQueryModel, MediaStreamMessage, MediaStreamModel, Modality, motion_exports as Motion, Move, MoveEnded, MoveStarted, Moved, Mutated, Mutation, NO_SWIPE, Online, OnlineMessage, OnlineModel, Pagination, PaginationMessage, PaginationModel, PermissionState, PermissionsMessage, PermissionsModel, Platform, PointerDrag, PointerMessage, PointerMoved, PointerPoint, PointerPosition, PointerPressed, PointerReleased, PrefersDark, PrefersReducedMotion, Presence, PresenceMessage, PresenceModel, Resize, Resized, RowMeasured, SCROLL_BAR_ATTRIBUTE, SCROLL_OVERLAID_ATTRIBUTE, SETTLE_QUIET, SWIPE_WINDOW, ScriptMessage, ScrollBars, ScrollLock, ScrollMessage, ScrollSettle, ScrollSettled, SelectionSet, SelectionSetMessage, SelectionSetModel, ShareData, ShareMessage, SharedHost, Socket, SocketView, Source, Spring, SpringMessage, SpringModel, SseMessage, SseModel, SseView, Swipe, SwipeEnded, SwipeStarted, Swiped, TRACK_TARGET_ATTRIBUTE, TargetHovered, TargetPressed, Targets, TextCancelled, TextCommitted, TextEdited, Throttle, ThrottleMessage, ThrottleModel, Throttled, Timer, TimerMessage, TimerModel, TrackBox, TrackedTarget, Tween, TweenMessage, TweenModel, Viewport, ViewportScrolled, Virtual, VirtualMessage, VirtualModel, Visibility, VisibilityMessage, VisibilityModel, Watch, WebSocketMessage, WebSocketModel, WindowSize, WindowSizeMessage, WindowSizeModel, activeElementEvents, applyMask, boxOf, breakpointFor, broadcastMessages, canRedo, canScroll, canUndo, copyText, cornerRadius, debounce, decodeImage, distanceToEnd, enterFullscreen, exitFullscreen, fluidHovered, formatRelativeTime, fullscreenChanges, history, isAtEnd, isBrowser, isLive, isOpen, isSelected, isServer, isVisible, keepScroll, keyboardEvents, keyboardInset, loadScript, masonry, matchHotkey, measurePaddingBox, measured, mediaDevices, mediaStream, modalityOfKey, offset, offsetFor, paddingBoxOf, pageCount, permissions, platformFromUA, pointedLinks, pointerEvents, postBroadcast, range, readText, scrollEvents, scrollThumb, share, sse, stickyHeader, tabbableWithin, targetOf, textOf, ticks, totalHeight, trackedBox, velocityOf, viewOf, viewOfSse, visibleRange, websocket, windowFor, zoneOf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldkit-primitives",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "Ready-made primitives for the Elm architecture, packaged with foldkit-bundle: media queries, presence, timers, pagination, history, sockets, observers, clipboard, and interaction Bundles with their Behaviors.",
5
5
  "keywords": [
6
6
  "foldkit",
@@ -94,7 +94,7 @@
94
94
  "peerDependencies": {
95
95
  "effect": "^4.0.0",
96
96
  "foldkit": "^0.168.0",
97
- "foldkit-mixins": "^0.16.0"
97
+ "foldkit-mixins": "^0.17.0"
98
98
  },
99
99
  "devDependencies": {
100
100
  "@effect/platform-browser": "^4.0.4",
@@ -105,7 +105,7 @@
105
105
  "tsdown": "^0.23.1",
106
106
  "typescript": "7.0.2",
107
107
  "ws": "^8.22.0",
108
- "foldkit-mixins": "0.16.0"
108
+ "foldkit-mixins": "0.17.0"
109
109
  },
110
110
  "peerDependenciesMeta": {
111
111
  "foldkit-mixins": {