@flemo/core 2.0.0 → 2.1.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.
@@ -46,6 +46,20 @@ interface MorphFlight {
46
46
  * stage a flight the runtime does not clock.
47
47
  */
48
48
  export declare const stageHeldFlights: (store: NavigateStoreApi, status: NavigateStatus) => MorphFlight[];
49
+ /**
50
+ * Forget any delivery the navigation never came to collect. A NEW gesture
51
+ * supersedes the last one; only the gesture's own entry point may do this,
52
+ * because the navigation reaches the scope through `stageHeldFlights` too and
53
+ * clearing there would erase the mark a moment before reading it.
54
+ */
55
+ /**
56
+ * Record that a gesture's release has DELIVERED whatever it is carrying — it
57
+ * plays those flights out to the arrival itself, so the navigation it commits
58
+ * must not stage them again. Whatever is in the air at the release is exactly
59
+ * what the gesture delivers. See `MorphScope.delivered`.
60
+ */
61
+ export declare const clearGestureDeliveries: (store: NavigateStoreApi) => void;
62
+ export declare const markGestureDelivered: (store: NavigateStoreApi) => void;
49
63
  /** The flights a scope currently holds — the nested ones included. */
50
64
  export declare const heldFlights: (store: NavigateStoreApi) => MorphFlight[];
51
65
  export type { MorphFlight };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export default function publishRideBox(element: HTMLElement): () => void;
@@ -1,5 +1,6 @@
1
1
  declare module '../typing' {
2
2
  interface RegisterTransition {
3
+ "custom-snap-percent": "custom-snap-percent";
3
4
  "custom-fade-blur": "custom-fade-blur";
4
5
  "custom-slide-fade": "custom-slide-fade";
5
6
  "custom-rich-css": "custom-rich-css";
@@ -13,6 +14,7 @@ declare module '../decorator/typing' {
13
14
  interface RegisterDecorator {
14
15
  "rich-deco": "rich-deco";
15
16
  "held-deco": "held-deco";
17
+ "moving-deco": "moving-deco";
16
18
  "authored-deco": "authored-deco";
17
19
  }
18
20
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -7,9 +7,10 @@ export type CssDecl = {
7
7
  value: string;
8
8
  };
9
9
  export declare const collectAnimatedProperties: (transition: Pick<Transition, "initial" | "variants">) => string[];
10
- export declare const targetToDecls: (target: TransitionVariantValue["value"] | InitialTarget) => CssDecl[];
10
+ export declare const targetToDecls: (target: TransitionVariantValue["value"] | InitialTarget, ride?: boolean) => CssDecl[];
11
11
  export declare const easingToCss: (ease: AnimationOptions["ease"] | undefined) => string;
12
12
  export declare const animationName: (scope: "screen" | "decorator" | "part", name: string, variant: TransitionVariant) => string;
13
+ export declare const decoratorAnimationName: (transitionName: string, decoratorName: string, variant: TransitionVariant) => string;
13
14
  export declare const HEAD_ANIMATION_SUFFIXES: readonly ["-gov", "-deskhead", "-govcreep"];
14
15
  export declare const matchesFlightAnimationName: (eventName: string, expectedName: string) => boolean;
15
16
  export declare const compileTransitionStyles: (transitions: Iterable<Transition>, decorators: Iterable<Decorator>, partTransitions?: Iterable<PartTransition>) => string;
@@ -0,0 +1,14 @@
1
+ declare module '../../typing' {
2
+ interface RegisterTransition {
3
+ "clock-long": "clock-long";
4
+ "clock-short": "clock-short";
5
+ "clock-directional": "clock-directional";
6
+ }
7
+ }
8
+ declare module '../typing' {
9
+ interface RegisterDecorator {
10
+ "clock-dim": "clock-dim";
11
+ "clock-fixed": "clock-fixed";
12
+ }
13
+ }
14
+ export {};
@@ -1,12 +1,11 @@
1
1
  import { InitialTarget } from '../cssTypes';
2
- import { TransitionVariantValue } from '../typing';
3
- import { DecoratorName, Decorator, DecoratorOptions } from './typing';
2
+ import { DecoratorName, Decorator, DecoratorOptions, DecoratorVariantValue } from './typing';
4
3
  interface CreateDecoratorProps {
5
4
  name: DecoratorName;
6
5
  initial: InitialTarget;
7
- idle: TransitionVariantValue;
8
- enter: TransitionVariantValue;
9
- exit: TransitionVariantValue;
6
+ idle: DecoratorVariantValue;
7
+ enter: DecoratorVariantValue;
8
+ exit: DecoratorVariantValue;
10
9
  options?: DecoratorOptions;
11
10
  }
12
11
  export default function createDecorator({ name, initial, idle, enter, exit, options }: CreateDecoratorProps): Decorator;
@@ -1,18 +1,17 @@
1
1
  import { InitialTarget } from '../cssTypes';
2
- import { TransitionVariantValue } from '../typing';
3
- import { DecoratorName, Decorator, DecoratorOptions } from './typing';
2
+ import { DecoratorName, Decorator, DecoratorOptions, DecoratorVariantValue } from './typing';
4
3
  interface CreateRawDecoratorProps {
5
4
  name: DecoratorName;
6
5
  initial: InitialTarget;
7
- idle: TransitionVariantValue;
8
- pushOnEnter: TransitionVariantValue;
9
- pushOnExit: TransitionVariantValue;
10
- replaceOnEnter: TransitionVariantValue;
11
- replaceOnExit: TransitionVariantValue;
12
- popOnEnter: TransitionVariantValue;
13
- popOnExit: TransitionVariantValue;
14
- completedOnEnter: TransitionVariantValue;
15
- completedOnExit: TransitionVariantValue;
6
+ idle: DecoratorVariantValue;
7
+ pushOnEnter: DecoratorVariantValue;
8
+ pushOnExit: DecoratorVariantValue;
9
+ replaceOnEnter: DecoratorVariantValue;
10
+ replaceOnExit: DecoratorVariantValue;
11
+ popOnEnter: DecoratorVariantValue;
12
+ popOnExit: DecoratorVariantValue;
13
+ completedOnEnter: DecoratorVariantValue;
14
+ completedOnExit: DecoratorVariantValue;
16
15
  options?: DecoratorOptions;
17
16
  }
18
17
  export default function createRawDecorator({ name, initial, idle, pushOnEnter, pushOnExit, replaceOnEnter, replaceOnExit, popOnEnter, popOnExit, completedOnEnter, completedOnExit, options }: CreateRawDecoratorProps): Decorator;
@@ -0,0 +1,36 @@
1
+ import { BaseTransition, Transition } from '../typing';
2
+ import { Decorator } from './typing';
3
+ /**
4
+ * A decorator's variant table with its clock filled in from the screen
5
+ * transition that names it.
6
+ *
7
+ * A decorator is only ever reached through `transition.decoratorName`, so the
8
+ * flight it dresses already decides how long it has. Authoring the length a
9
+ * second time is how the two drift apart, and this repository worked around
10
+ * that three times before removing the duplication:
11
+ *
12
+ * - `overlay` and `cupertino` each restated 0.7s, with a comment on the
13
+ * decorator saying the number came from the transition.
14
+ * - the playground's `drift` and `recess` share a constants file for no
15
+ * other reason than to keep two hand-written clocks equal.
16
+ * - `layout` dropped its dim ALTOGETHER rather than inherit `overlay`'s
17
+ * 0.7s over a 0.4s flight: measured on a pop, the dismissing screen was
18
+ * fully gone at 335ms while the screen underneath still carried a 10%
19
+ * black wash, which reads as a grey cast appearing from nowhere and then
20
+ * lifting for no reason.
21
+ *
22
+ * The rule is the SAME VARIANT KEY, which is exactly the mapping those
23
+ * workarounds were doing by hand: a decorator's `enter` sits at PUSHING-false
24
+ * with the screen's `exit`, its `exit` at POPPING-false with the screen's
25
+ * `exitBack`. It therefore also carries direction for free — a preset whose
26
+ * push and pop differ (material runs 0.35s and 0.25s) gives its dim the same
27
+ * asymmetry without the author restating it.
28
+ *
29
+ * Resolution is COMPILE TIME and produces a literal. It must never become a
30
+ * `var()` in `animation-duration`: timing that depended on custom properties
31
+ * lost WebKit's accelerated playback and collapsed to a 2-frame snap under
32
+ * main-thread starvation (device-bisected 2026-08-13, see
33
+ * compileTransitionStyles.ts).
34
+ */
35
+ export declare const resolveDecoratorClock: (transition: Pick<Transition, "variants">, decorator: Pick<Decorator, "initial" | "variants">) => Pick<BaseTransition, "initial" | "variants">;
36
+ export default resolveDecoratorClock;
@@ -1,4 +1,5 @@
1
- import { BaseTransition, SwipeAnimate } from '../typing';
1
+ import { AnimationOptions, TransitionTarget } from '../cssTypes';
2
+ import { BaseTransition, SwipeAnimate, TransitionVariant } from '../typing';
2
3
  export interface RegisterDecorator {
3
4
  }
4
5
  export type DecoratorName = RegisterDecorator[keyof RegisterDecorator] | "overlay";
@@ -19,6 +20,11 @@ export type DecoratorOptions = {
19
20
  prevDecorator: HTMLDivElement;
20
21
  }) => void;
21
22
  };
22
- export interface Decorator extends Omit<BaseTransition, "name">, DecoratorOptions {
23
+ export type DecoratorVariantValue = {
24
+ value: TransitionTarget;
25
+ options?: AnimationOptions;
26
+ };
27
+ export interface Decorator extends Omit<BaseTransition, "name" | "variants">, DecoratorOptions {
23
28
  name: DecoratorName;
29
+ variants: Record<TransitionVariant, DecoratorVariantValue>;
24
30
  }
@@ -0,0 +1,5 @@
1
+ import { TransitionTarget } from './cssTypes';
2
+ export declare const RIDE_HEIGHT_VAR = "--flemo-ride-y";
3
+ export declare const percentRatio: (value: unknown) => number | null;
4
+ export declare const rideLength: (ratio: number) => string;
5
+ export declare const resolveRideTarget: <T extends TransitionTarget>(target: T, screenHeight: number) => T;
@@ -29,8 +29,12 @@ export interface SwipeSettleInput {
29
29
  * time that curve itself spends on the stretch that is left; without them it
30
30
  * falls back to reading the motion as linear, which is what this used to do
31
31
  * for every transition.
32
+ *
33
+ * `null` is accepted as well as omission, because the callers that build
34
+ * this read their curve from `easeControlPoints`, which reports "no curve"
35
+ * as null. Converting at every call site bought nothing but a branch.
32
36
  */
33
- authoredEase?: readonly [number, number, number, number];
37
+ authoredEase?: readonly [number, number, number, number] | null;
34
38
  minSeconds?: number;
35
39
  }
36
40
  /**
@@ -42,7 +42,18 @@ export type TransitionOptions = {
42
42
  animate: SwipeAnimate;
43
43
  currentScreen: HTMLDivElement;
44
44
  prevScreen: HTMLDivElement;
45
- onProgress?: (triggered: boolean, progress: number) => void;
45
+ /**
46
+ * Report the gesture's VERDICT so the decorator and the parts can
47
+ * follow it. The controller supplies their progress itself, against
48
+ * the box the screen is actually dragged over, so a second argument
49
+ * is accepted for source compatibility and is not read.
50
+ *
51
+ * It used to be. A transition's own progress is in the transition's
52
+ * own unit — material's is a pull in pixels, layout's is a constant
53
+ * — so what reached a decorator depended on which preset it was
54
+ * paired with, and could not honour the 0-100 those hooks document.
55
+ */
56
+ onProgress?: (triggered: boolean, progress?: number) => void;
46
57
  }) => number;
47
58
  onSwipeEnd: (event: PointerEvent, info: SwipeInfo, options: {
48
59
  animate: SwipeAnimate;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flemo/core",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Framework-agnostic primitives for flemo: history, navigation, transitions, task manager.",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.mjs",