@czap/core 0.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.
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/addressed-digest.d.ts +15 -0
- package/dist/addressed-digest.d.ts.map +1 -0
- package/dist/addressed-digest.js +35 -0
- package/dist/addressed-digest.js.map +1 -0
- package/dist/animation.d.ts +46 -0
- package/dist/animation.d.ts.map +1 -0
- package/dist/animation.js +70 -0
- package/dist/animation.js.map +1 -0
- package/dist/assembly.d.ts +25 -0
- package/dist/assembly.d.ts.map +1 -0
- package/dist/assembly.js +58 -0
- package/dist/assembly.js.map +1 -0
- package/dist/av-bridge.d.ts +74 -0
- package/dist/av-bridge.d.ts.map +1 -0
- package/dist/av-bridge.js +107 -0
- package/dist/av-bridge.js.map +1 -0
- package/dist/av-renderer.d.ts +56 -0
- package/dist/av-renderer.d.ts.map +1 -0
- package/dist/av-renderer.js +65 -0
- package/dist/av-renderer.js.map +1 -0
- package/dist/blend.d.ts +61 -0
- package/dist/blend.d.ts.map +1 -0
- package/dist/blend.js +100 -0
- package/dist/blend.js.map +1 -0
- package/dist/boundary.d.ts +154 -0
- package/dist/boundary.d.ts.map +1 -0
- package/dist/boundary.js +269 -0
- package/dist/boundary.js.map +1 -0
- package/dist/brands.d.ts +63 -0
- package/dist/brands.d.ts.map +1 -0
- package/dist/brands.js +31 -0
- package/dist/brands.js.map +1 -0
- package/dist/caps.d.ts +49 -0
- package/dist/caps.d.ts.map +1 -0
- package/dist/caps.js +73 -0
- package/dist/caps.js.map +1 -0
- package/dist/capsule.d.ts +77 -0
- package/dist/capsule.d.ts.map +1 -0
- package/dist/capsule.js +18 -0
- package/dist/capsule.js.map +1 -0
- package/dist/capsules/boundary-evaluate.d.ts +28 -0
- package/dist/capsules/boundary-evaluate.d.ts.map +1 -0
- package/dist/capsules/boundary-evaluate.js +117 -0
- package/dist/capsules/boundary-evaluate.js.map +1 -0
- package/dist/capsules/canonical-cbor.d.ts +13 -0
- package/dist/capsules/canonical-cbor.d.ts.map +1 -0
- package/dist/capsules/canonical-cbor.js +60 -0
- package/dist/capsules/canonical-cbor.js.map +1 -0
- package/dist/capsules/token-buffer.d.ts +24 -0
- package/dist/capsules/token-buffer.d.ts.map +1 -0
- package/dist/capsules/token-buffer.js +53 -0
- package/dist/capsules/token-buffer.js.map +1 -0
- package/dist/capture.d.ts +40 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +10 -0
- package/dist/capture.js.map +1 -0
- package/dist/cbor.d.ts +33 -0
- package/dist/cbor.d.ts.map +1 -0
- package/dist/cbor.js +179 -0
- package/dist/cbor.js.map +1 -0
- package/dist/cell.d.ts +53 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +83 -0
- package/dist/cell.js.map +1 -0
- package/dist/codec.d.ts +30 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +25 -0
- package/dist/codec.js.map +1 -0
- package/dist/component.d.ts +52 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/component.js +44 -0
- package/dist/component.js.map +1 -0
- package/dist/composable.d.ts +76 -0
- package/dist/composable.d.ts.map +1 -0
- package/dist/composable.js +221 -0
- package/dist/composable.js.map +1 -0
- package/dist/compositor-pool.d.ts +74 -0
- package/dist/compositor-pool.d.ts.map +1 -0
- package/dist/compositor-pool.js +119 -0
- package/dist/compositor-pool.js.map +1 -0
- package/dist/compositor.d.ts +90 -0
- package/dist/compositor.d.ts.map +1 -0
- package/dist/compositor.js +278 -0
- package/dist/compositor.js.map +1 -0
- package/dist/config.d.ts +72 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/dag.d.ts +251 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/dag.js +450 -0
- package/dist/dag.js.map +1 -0
- package/dist/defaults.d.ts +45 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +45 -0
- package/dist/defaults.js.map +1 -0
- package/dist/derived.d.ts +34 -0
- package/dist/derived.d.ts.map +1 -0
- package/dist/derived.js +101 -0
- package/dist/derived.js.map +1 -0
- package/dist/diagnostics.d.ts +77 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +122 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/dirty.d.ts +55 -0
- package/dist/dirty.d.ts.map +1 -0
- package/dist/dirty.js +80 -0
- package/dist/dirty.js.map +1 -0
- package/dist/easing.d.ts +55 -0
- package/dist/easing.d.ts.map +1 -0
- package/dist/easing.js +291 -0
- package/dist/easing.js.map +1 -0
- package/dist/ecs.d.ts +105 -0
- package/dist/ecs.d.ts.map +1 -0
- package/dist/ecs.js +245 -0
- package/dist/ecs.js.map +1 -0
- package/dist/fnv.d.ts +14 -0
- package/dist/fnv.d.ts.map +1 -0
- package/dist/fnv.js +28 -0
- package/dist/fnv.js.map +1 -0
- package/dist/frame-budget.d.ts +73 -0
- package/dist/frame-budget.d.ts.map +1 -0
- package/dist/frame-budget.js +114 -0
- package/dist/frame-budget.js.map +1 -0
- package/dist/gen-frame.d.ts +102 -0
- package/dist/gen-frame.d.ts.map +1 -0
- package/dist/gen-frame.js +121 -0
- package/dist/gen-frame.js.map +1 -0
- package/dist/harness/arbitrary-from-schema.d.ts +28 -0
- package/dist/harness/arbitrary-from-schema.d.ts.map +1 -0
- package/dist/harness/arbitrary-from-schema.js +262 -0
- package/dist/harness/arbitrary-from-schema.js.map +1 -0
- package/dist/harness/cached-projection.d.ts +19 -0
- package/dist/harness/cached-projection.d.ts.map +1 -0
- package/dist/harness/cached-projection.js +39 -0
- package/dist/harness/cached-projection.js.map +1 -0
- package/dist/harness/index.d.ts +16 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +15 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/policy-gate.d.ts +18 -0
- package/dist/harness/policy-gate.d.ts.map +1 -0
- package/dist/harness/policy-gate.js +46 -0
- package/dist/harness/policy-gate.js.map +1 -0
- package/dist/harness/pure-transform.d.ts +42 -0
- package/dist/harness/pure-transform.d.ts.map +1 -0
- package/dist/harness/pure-transform.js +76 -0
- package/dist/harness/pure-transform.js.map +1 -0
- package/dist/harness/receipted-mutation.d.ts +23 -0
- package/dist/harness/receipted-mutation.d.ts.map +1 -0
- package/dist/harness/receipted-mutation.js +52 -0
- package/dist/harness/receipted-mutation.js.map +1 -0
- package/dist/harness/scene-composition.d.ts +19 -0
- package/dist/harness/scene-composition.d.ts.map +1 -0
- package/dist/harness/scene-composition.js +47 -0
- package/dist/harness/scene-composition.js.map +1 -0
- package/dist/harness/site-adapter.d.ts +18 -0
- package/dist/harness/site-adapter.d.ts.map +1 -0
- package/dist/harness/site-adapter.js +38 -0
- package/dist/harness/site-adapter.js.map +1 -0
- package/dist/harness/state-machine.d.ts +19 -0
- package/dist/harness/state-machine.d.ts.map +1 -0
- package/dist/harness/state-machine.js +44 -0
- package/dist/harness/state-machine.js.map +1 -0
- package/dist/hlc.d.ts +99 -0
- package/dist/hlc.d.ts.map +1 -0
- package/dist/hlc.js +219 -0
- package/dist/hlc.js.map +1 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +14 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +31 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/live-cell.d.ts +46 -0
- package/dist/live-cell.d.ts.map +1 -0
- package/dist/live-cell.js +154 -0
- package/dist/live-cell.js.map +1 -0
- package/dist/op.d.ts +58 -0
- package/dist/op.d.ts.map +1 -0
- package/dist/op.js +171 -0
- package/dist/op.js.map +1 -0
- package/dist/plan.d.ts +195 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +211 -0
- package/dist/plan.js.map +1 -0
- package/dist/protocol.d.ts +33 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +10 -0
- package/dist/protocol.js.map +1 -0
- package/dist/quantizer-types.d.ts +28 -0
- package/dist/quantizer-types.d.ts.map +1 -0
- package/dist/quantizer-types.js +9 -0
- package/dist/quantizer-types.js.map +1 -0
- package/dist/receipt.d.ts +294 -0
- package/dist/receipt.d.ts.map +1 -0
- package/dist/receipt.js +352 -0
- package/dist/receipt.js.map +1 -0
- package/dist/runtime-coordinator.d.ts +75 -0
- package/dist/runtime-coordinator.d.ts.map +1 -0
- package/dist/runtime-coordinator.js +149 -0
- package/dist/runtime-coordinator.js.map +1 -0
- package/dist/scheduler.d.ts +58 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +109 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/ship-capsule.d.ts +54 -0
- package/dist/ship-capsule.d.ts.map +1 -0
- package/dist/ship-capsule.js +142 -0
- package/dist/ship-capsule.js.map +1 -0
- package/dist/ship-manifest.d.ts +45 -0
- package/dist/ship-manifest.d.ts.map +1 -0
- package/dist/ship-manifest.js +175 -0
- package/dist/ship-manifest.js.map +1 -0
- package/dist/signal.d.ts +149 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +277 -0
- package/dist/signal.js.map +1 -0
- package/dist/speculative.d.ts +67 -0
- package/dist/speculative.d.ts.map +1 -0
- package/dist/speculative.js +139 -0
- package/dist/speculative.js.map +1 -0
- package/dist/store.d.ts +39 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +42 -0
- package/dist/store.js.map +1 -0
- package/dist/style.d.ts +119 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +168 -0
- package/dist/style.js.map +1 -0
- package/dist/testing.d.ts +14 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +14 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme.d.ts +78 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +109 -0
- package/dist/theme.js.map +1 -0
- package/dist/timeline.d.ts +45 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +101 -0
- package/dist/timeline.js.map +1 -0
- package/dist/token-buffer.d.ts +43 -0
- package/dist/token-buffer.d.ts.map +1 -0
- package/dist/token-buffer.js +112 -0
- package/dist/token-buffer.js.map +1 -0
- package/dist/token.d.ts +107 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +143 -0
- package/dist/token.js.map +1 -0
- package/dist/tuple.d.ts +16 -0
- package/dist/tuple.d.ts.map +1 -0
- package/dist/tuple.js +16 -0
- package/dist/tuple.js.map +1 -0
- package/dist/type-utils.d.ts +41 -0
- package/dist/type-utils.d.ts.map +1 -0
- package/dist/type-utils.js +10 -0
- package/dist/type-utils.js.map +1 -0
- package/dist/typed-ref.d.ts +50 -0
- package/dist/typed-ref.d.ts.map +1 -0
- package/dist/typed-ref.js +59 -0
- package/dist/typed-ref.js.map +1 -0
- package/dist/ui-quality.d.ts +50 -0
- package/dist/ui-quality.d.ts.map +1 -0
- package/dist/ui-quality.js +64 -0
- package/dist/ui-quality.js.map +1 -0
- package/dist/validation-error.d.ts +25 -0
- package/dist/validation-error.d.ts.map +1 -0
- package/dist/validation-error.js +32 -0
- package/dist/validation-error.js.map +1 -0
- package/dist/vector-clock.d.ts +46 -0
- package/dist/vector-clock.d.ts.map +1 -0
- package/dist/vector-clock.js +91 -0
- package/dist/vector-clock.js.map +1 -0
- package/dist/video.d.ts +62 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +59 -0
- package/dist/video.js.map +1 -0
- package/dist/wasm-dispatch.d.ts +52 -0
- package/dist/wasm-dispatch.d.ts.map +1 -0
- package/dist/wasm-dispatch.js +204 -0
- package/dist/wasm-dispatch.js.map +1 -0
- package/dist/wasm-fallback.d.ts +19 -0
- package/dist/wasm-fallback.d.ts.map +1 -0
- package/dist/wasm-fallback.js +93 -0
- package/dist/wasm-fallback.js.map +1 -0
- package/dist/wire.d.ts +49 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +201 -0
- package/dist/wire.js.map +1 -0
- package/dist/zap.d.ts +42 -0
- package/dist/zap.d.ts.map +1 -0
- package/dist/zap.js +172 -0
- package/dist/zap.js.map +1 -0
- package/package.json +71 -0
- package/src/addressed-digest.ts +48 -0
- package/src/animation.ts +103 -0
- package/src/assembly.ts +76 -0
- package/src/av-bridge.ts +161 -0
- package/src/av-renderer.ts +118 -0
- package/src/blend.ts +135 -0
- package/src/boundary.ts +363 -0
- package/src/brands.ts +86 -0
- package/src/caps.ts +100 -0
- package/src/capsule.ts +95 -0
- package/src/capsules/boundary-evaluate.ts +128 -0
- package/src/capsules/canonical-cbor.ts +60 -0
- package/src/capsules/token-buffer.ts +57 -0
- package/src/capture.ts +48 -0
- package/src/cbor.ts +199 -0
- package/src/cell.ts +130 -0
- package/src/codec.ts +39 -0
- package/src/component.ts +102 -0
- package/src/composable.ts +328 -0
- package/src/compositor-pool.ts +162 -0
- package/src/compositor.ts +387 -0
- package/src/config.ts +157 -0
- package/src/dag.ts +527 -0
- package/src/defaults.ts +60 -0
- package/src/derived.ts +164 -0
- package/src/diagnostics.ts +186 -0
- package/src/dirty.ts +101 -0
- package/src/easing.ts +334 -0
- package/src/ecs.ts +382 -0
- package/src/fnv.ts +31 -0
- package/src/frame-budget.ts +149 -0
- package/src/gen-frame.ts +229 -0
- package/src/harness/arbitrary-from-schema.ts +270 -0
- package/src/harness/cached-projection.ts +46 -0
- package/src/harness/index.ts +16 -0
- package/src/harness/policy-gate.ts +51 -0
- package/src/harness/pure-transform.ts +121 -0
- package/src/harness/receipted-mutation.ts +59 -0
- package/src/harness/scene-composition.ts +54 -0
- package/src/harness/site-adapter.ts +43 -0
- package/src/harness/state-machine.ts +49 -0
- package/src/hlc.ts +238 -0
- package/src/index.ts +274 -0
- package/src/interpolate.ts +37 -0
- package/src/live-cell.ts +199 -0
- package/src/op.ts +233 -0
- package/src/plan.ts +317 -0
- package/src/protocol.ts +49 -0
- package/src/quantizer-types.ts +29 -0
- package/src/receipt.ts +444 -0
- package/src/runtime-coordinator.ts +230 -0
- package/src/scheduler.ts +161 -0
- package/src/ship-capsule.ts +191 -0
- package/src/signal.ts +345 -0
- package/src/speculative.ts +186 -0
- package/src/store.ts +77 -0
- package/src/style.ts +249 -0
- package/src/testing.ts +14 -0
- package/src/theme.ts +153 -0
- package/src/timeline.ts +146 -0
- package/src/token-buffer.ts +151 -0
- package/src/token.ts +197 -0
- package/src/tuple.ts +19 -0
- package/src/type-utils.ts +48 -0
- package/src/typed-ref.ts +79 -0
- package/src/ui-quality.ts +105 -0
- package/src/validation-error.ts +34 -0
- package/src/vector-clock.ts +111 -0
- package/src/video.ts +106 -0
- package/src/wasm-dispatch.ts +300 -0
- package/src/wasm-fallback.ts +102 -0
- package/src/wire.ts +274 -0
- package/src/zap.ts +241 -0
package/dist/blend.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlendTree -- weighted multi-state blending.
|
|
3
|
+
*
|
|
4
|
+
* A blend tree holds named numeric-record values with weights.
|
|
5
|
+
* `compute()` returns the weighted average of all values.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { Scope } from 'effect';
|
|
10
|
+
import { Effect, Stream } from 'effect';
|
|
11
|
+
interface BlendNodeShape<T> {
|
|
12
|
+
readonly value: T;
|
|
13
|
+
readonly weight: number;
|
|
14
|
+
}
|
|
15
|
+
interface BlendTreeShape<T extends Record<string, number>> {
|
|
16
|
+
add(name: string, value: T, weight: number): void;
|
|
17
|
+
remove(name: string): void;
|
|
18
|
+
setWeight(name: string, weight: number): void;
|
|
19
|
+
compute(): T;
|
|
20
|
+
readonly changes: Stream.Stream<T>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new BlendTree for weighted multi-state blending of numeric records.
|
|
24
|
+
* Requires a Scope for lifecycle management of the change stream.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
29
|
+
* const tree = yield* BlendTree.make<{ x: number; y: number }>();
|
|
30
|
+
* tree.add('idle', { x: 0, y: 0 }, 0.3);
|
|
31
|
+
* tree.add('active', { x: 100, y: 50 }, 0.7);
|
|
32
|
+
* const blended = tree.compute(); // { x: 70, y: 35 }
|
|
33
|
+
* }));
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare function _make<T extends Record<string, number>>(): Effect.Effect<BlendTreeShape<T>, never, Scope.Scope>;
|
|
37
|
+
/**
|
|
38
|
+
* BlendTree -- weighted multi-state blending for numeric records.
|
|
39
|
+
* Add named nodes with values and weights, then compute the weighted average.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
44
|
+
* const tree = yield* BlendTree.make<{ opacity: number }>();
|
|
45
|
+
* tree.add('fadeIn', { opacity: 1 }, 0.8);
|
|
46
|
+
* tree.add('fadeOut', { opacity: 0 }, 0.2);
|
|
47
|
+
* const result = tree.compute(); // { opacity: 0.8 }
|
|
48
|
+
* }));
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const BlendTree: {
|
|
52
|
+
make: typeof _make;
|
|
53
|
+
};
|
|
54
|
+
export declare namespace BlendTree {
|
|
55
|
+
/** Structural shape of a blend-tree instance: `sample(weights)` over a `Record<string, number>` space. */
|
|
56
|
+
type Shape<T extends Record<string, number>> = BlendTreeShape<T>;
|
|
57
|
+
/** Individual leaf/intermediate node in a blend tree. */
|
|
58
|
+
type Node<T> = BlendNodeShape<T>;
|
|
59
|
+
}
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=blend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blend.d.ts","sourceRoot":"","sources":["../src/blend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAEhD,UAAU,cAAc,CAAC,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IACvD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,IAAI,CAAC,CAAC;IACb,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;GAaG;AACH,iBAAS,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAwEvG;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,SAAS;;CAAkB,CAAC;AAEzC,MAAM,CAAC,OAAO,WAAW,SAAS,CAAC;IACjC,0GAA0G;IAC1G,KAAY,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IACxE,yDAAyD;IACzD,KAAY,IAAI,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;CACzC"}
|
package/dist/blend.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BlendTree -- weighted multi-state blending.
|
|
3
|
+
*
|
|
4
|
+
* A blend tree holds named numeric-record values with weights.
|
|
5
|
+
* `compute()` returns the weighted average of all values.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, Stream, PubSub } from 'effect';
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new BlendTree for weighted multi-state blending of numeric records.
|
|
12
|
+
* Requires a Scope for lifecycle management of the change stream.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
17
|
+
* const tree = yield* BlendTree.make<{ x: number; y: number }>();
|
|
18
|
+
* tree.add('idle', { x: 0, y: 0 }, 0.3);
|
|
19
|
+
* tree.add('active', { x: 100, y: 50 }, 0.7);
|
|
20
|
+
* const blended = tree.compute(); // { x: 70, y: 35 }
|
|
21
|
+
* }));
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function _make() {
|
|
25
|
+
return Effect.gen(function* () {
|
|
26
|
+
const nodes = new Map();
|
|
27
|
+
const pubsub = yield* PubSub.unbounded();
|
|
28
|
+
// The computed result is a Record<string, number> whose keys match T's keys by
|
|
29
|
+
// construction (we only write keys copied from node.value, which is T). TS can't
|
|
30
|
+
// track that structural promise, so we contain one cast in a named helper.
|
|
31
|
+
const finalizeBlend = (record) => record;
|
|
32
|
+
function computeBlend() {
|
|
33
|
+
const result = {};
|
|
34
|
+
let totalWeight = 0;
|
|
35
|
+
for (const node of nodes.values()) {
|
|
36
|
+
if (node.weight > 0)
|
|
37
|
+
totalWeight += node.weight;
|
|
38
|
+
}
|
|
39
|
+
if (totalWeight === 0 || nodes.size === 0) {
|
|
40
|
+
return finalizeBlend(result);
|
|
41
|
+
}
|
|
42
|
+
let initialized = false;
|
|
43
|
+
for (const node of nodes.values()) {
|
|
44
|
+
const w = node.weight > 0 ? node.weight / totalWeight : 0;
|
|
45
|
+
for (const key in node.value) {
|
|
46
|
+
if (Object.prototype.hasOwnProperty.call(node.value, key)) {
|
|
47
|
+
if (!initialized || !(key in result)) {
|
|
48
|
+
result[key] = 0;
|
|
49
|
+
}
|
|
50
|
+
result[key] += node.value[key] * w;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
initialized = true;
|
|
54
|
+
}
|
|
55
|
+
return finalizeBlend(result);
|
|
56
|
+
}
|
|
57
|
+
function notifyChange() {
|
|
58
|
+
const blended = computeBlend();
|
|
59
|
+
Effect.runSync(PubSub.publish(pubsub, blended));
|
|
60
|
+
}
|
|
61
|
+
const tree = {
|
|
62
|
+
add(name, value, weight) {
|
|
63
|
+
nodes.set(name, { value, weight });
|
|
64
|
+
notifyChange();
|
|
65
|
+
},
|
|
66
|
+
remove(name) {
|
|
67
|
+
nodes.delete(name);
|
|
68
|
+
notifyChange();
|
|
69
|
+
},
|
|
70
|
+
setWeight(name, weight) {
|
|
71
|
+
const node = nodes.get(name);
|
|
72
|
+
if (node) {
|
|
73
|
+
nodes.set(name, { ...node, weight });
|
|
74
|
+
notifyChange();
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
compute() {
|
|
78
|
+
return computeBlend();
|
|
79
|
+
},
|
|
80
|
+
changes: Stream.fromPubSub(pubsub),
|
|
81
|
+
};
|
|
82
|
+
return tree;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* BlendTree -- weighted multi-state blending for numeric records.
|
|
87
|
+
* Add named nodes with values and weights, then compute the weighted average.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const program = Effect.scoped(Effect.gen(function* () {
|
|
92
|
+
* const tree = yield* BlendTree.make<{ opacity: number }>();
|
|
93
|
+
* tree.add('fadeIn', { opacity: 1 }, 0.8);
|
|
94
|
+
* tree.add('fadeOut', { opacity: 0 }, 0.2);
|
|
95
|
+
* const result = tree.compute(); // { opacity: 0.8 }
|
|
96
|
+
* }));
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export const BlendTree = { make: _make };
|
|
100
|
+
//# sourceMappingURL=blend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blend.js","sourceRoot":"","sources":["../src/blend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoundaryDef -- the core primitive of constraint-based adaptive rendering.
|
|
3
|
+
*
|
|
4
|
+
* A boundary defines quantization: how a continuous signal value maps
|
|
5
|
+
* to a discrete set of named states. Content-addressed via FNV-1a.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { SignalInput, ThresholdValue, ContentAddress } from './brands.js';
|
|
10
|
+
/** The core primitive. Source of truth for quantization boundaries. */
|
|
11
|
+
interface BoundaryDef<I extends string = string, S extends readonly [string, ...string[]] = readonly [string, ...string[]]> {
|
|
12
|
+
readonly _tag: 'BoundaryDef';
|
|
13
|
+
readonly _version: 1;
|
|
14
|
+
readonly id: ContentAddress;
|
|
15
|
+
readonly input: SignalInput<I>;
|
|
16
|
+
readonly thresholds: readonly ThresholdValue[];
|
|
17
|
+
readonly states: S;
|
|
18
|
+
readonly hysteresis?: number;
|
|
19
|
+
readonly spec?: BoundarySpec;
|
|
20
|
+
}
|
|
21
|
+
interface BoundaryFactory {
|
|
22
|
+
make<I extends string, const S extends readonly [string, ...string[]]>(config: {
|
|
23
|
+
readonly input: I;
|
|
24
|
+
readonly at: {
|
|
25
|
+
readonly [K in keyof S]: readonly [number, S[K]];
|
|
26
|
+
};
|
|
27
|
+
readonly hysteresis?: number;
|
|
28
|
+
readonly spec?: BoundarySpec;
|
|
29
|
+
}): BoundaryDef<I, S>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Evaluate which state a value falls into given a boundary (binary search).
|
|
33
|
+
*
|
|
34
|
+
* Uses binary search to find the rightmost threshold `<= value`, returning
|
|
35
|
+
* the corresponding state name.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const bp = Boundary.make({ input: 'viewport.width', at: [[0, 'sm'], [768, 'md'], [1024, 'lg']] });
|
|
40
|
+
* const state = Boundary.evaluate(bp, 800);
|
|
41
|
+
* // state === 'md'
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
declare function _evaluate<B extends BoundaryDef>(boundary: B, value: number): B['states'][number];
|
|
45
|
+
/**
|
|
46
|
+
* Evaluate with hysteresis (requires previous state). Half-width dead zone algorithm.
|
|
47
|
+
*
|
|
48
|
+
* Prevents flickering at boundary edges by requiring the value to cross
|
|
49
|
+
* beyond a dead zone (half the hysteresis width) before transitioning states.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const bp = Boundary.make({ input: 'viewport.width', at: [[0, 'sm'], [768, 'md']], hysteresis: 20 });
|
|
54
|
+
* const state1 = Boundary.evaluateWithHysteresis(bp, 770, 'sm');
|
|
55
|
+
* // state1 === 'sm' (within dead zone, stays at previous)
|
|
56
|
+
* const state2 = Boundary.evaluateWithHysteresis(bp, 780, 'sm');
|
|
57
|
+
* // state2 === 'md' (past dead zone, transitions)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function _evaluateWithHysteresis<B extends BoundaryDef>(boundary: B, value: number, previousState: B['states'][number]): B['states'][number];
|
|
61
|
+
/**
|
|
62
|
+
* Boundary namespace -- the core primitive of constraint-based adaptive rendering.
|
|
63
|
+
*
|
|
64
|
+
* Create boundaries that quantize continuous signal values into discrete named
|
|
65
|
+
* states. Supports hysteresis for flicker-free transitions at threshold edges.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { Boundary } from '@czap/core';
|
|
70
|
+
*
|
|
71
|
+
* const bp = Boundary.make({
|
|
72
|
+
* input: 'viewport.width',
|
|
73
|
+
* at: [[0, 'mobile'], [768, 'tablet'], [1024, 'desktop']],
|
|
74
|
+
* hysteresis: 20,
|
|
75
|
+
* });
|
|
76
|
+
* const state = Boundary.evaluate(bp, 900);
|
|
77
|
+
* // state === 'tablet'
|
|
78
|
+
* const stableState = Boundary.evaluateWithHysteresis(bp, 770, 'mobile');
|
|
79
|
+
* // stableState === 'mobile' (within dead zone)
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* Check whether a boundary is active given its optional spec and current context.
|
|
84
|
+
* Returns true if the boundary has no spec or the spec allows evaluation.
|
|
85
|
+
*/
|
|
86
|
+
declare function _isActive<B extends BoundaryDef>(boundary: B, context?: {
|
|
87
|
+
capabilities?: Record<string, unknown>;
|
|
88
|
+
nowMs?: number;
|
|
89
|
+
activeExperiments?: ReadonlyArray<string>;
|
|
90
|
+
}): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Boundary — core primitive of constraint-based adaptive rendering.
|
|
93
|
+
*
|
|
94
|
+
* A boundary quantizes a continuous signal (viewport, scroll, audio, …) into
|
|
95
|
+
* a discrete set of named states. Every boundary is content-addressed via
|
|
96
|
+
* FNV-1a, supports optional hysteresis to prevent flicker at thresholds, and
|
|
97
|
+
* can be gated by a {@link BoundarySpec} for A/B or device-conditional activation.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* import { Boundary } from '@czap/core';
|
|
102
|
+
*
|
|
103
|
+
* const viewport = Boundary.make({
|
|
104
|
+
* input: 'viewport.width',
|
|
105
|
+
* at: [[0, 'mobile'], [640, 'tablet'], [1024, 'desktop']] as const,
|
|
106
|
+
* hysteresis: 16,
|
|
107
|
+
* });
|
|
108
|
+
* Boundary.evaluate(viewport, 800); // 'tablet'
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare const Boundary: BoundaryFactory & {
|
|
112
|
+
evaluate: typeof _evaluate;
|
|
113
|
+
evaluateWithHysteresis: typeof _evaluateWithHysteresis;
|
|
114
|
+
isActive: typeof _isActive;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* BoundarySpec: optional filter that gates whether a boundary is active.
|
|
118
|
+
* Enables A/B testing, time-bounded experiments, and device targeting
|
|
119
|
+
* without external wrapping logic.
|
|
120
|
+
*
|
|
121
|
+
* **Phase 2**: Spec evaluation is implemented and tested but not yet wired
|
|
122
|
+
* into the Compositor evaluation loop. Call `BoundarySpec.isActive()` or
|
|
123
|
+
* `Boundary.isActive()` manually to check activation in the interim.
|
|
124
|
+
*/
|
|
125
|
+
export interface BoundarySpec {
|
|
126
|
+
/** Only evaluate this boundary when the device filter returns true. */
|
|
127
|
+
readonly deviceFilter?: (capabilities: Record<string, unknown>) => boolean;
|
|
128
|
+
/** Only evaluate this boundary within this time range (epoch ms). */
|
|
129
|
+
readonly timeRange?: {
|
|
130
|
+
readonly from?: number;
|
|
131
|
+
readonly until?: number;
|
|
132
|
+
};
|
|
133
|
+
/** Only evaluate this boundary for participants in this experiment. */
|
|
134
|
+
readonly experimentId?: string;
|
|
135
|
+
}
|
|
136
|
+
/** Check if a BoundarySpec allows evaluation given current context. */
|
|
137
|
+
declare function _isSpecActive(spec: BoundarySpec | undefined, context?: {
|
|
138
|
+
capabilities?: Record<string, unknown>;
|
|
139
|
+
nowMs?: number;
|
|
140
|
+
activeExperiments?: ReadonlyArray<string>;
|
|
141
|
+
}): boolean;
|
|
142
|
+
/** BoundarySpec namespace — helpers for working with the optional activation filter on a boundary. */
|
|
143
|
+
export declare const BoundarySpec: {
|
|
144
|
+
/** Check whether a {@link BoundarySpec} allows evaluation in the given context. */
|
|
145
|
+
isActive: typeof _isSpecActive;
|
|
146
|
+
};
|
|
147
|
+
export declare namespace Boundary {
|
|
148
|
+
/** Structural shape of a boundary definition parameterized by input name `I` and state tuple `S`. */
|
|
149
|
+
type Shape<I extends string = string, S extends readonly [string, ...string[]] = readonly [string, ...string[]]> = BoundaryDef<I, S>;
|
|
150
|
+
/** Alias for {@link BoundarySpec}. */
|
|
151
|
+
type Spec = BoundarySpec;
|
|
152
|
+
}
|
|
153
|
+
export {};
|
|
154
|
+
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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"}
|
package/dist/boundary.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoundaryDef -- the core primitive of constraint-based adaptive rendering.
|
|
3
|
+
*
|
|
4
|
+
* A boundary defines quantization: how a continuous signal value maps
|
|
5
|
+
* to a discrete set of named states. Content-addressed via FNV-1a.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { SignalInput as mkSignalInput, ThresholdValue as mkThresholdValue } from './brands.js';
|
|
10
|
+
import { CanonicalCbor } from './cbor.js';
|
|
11
|
+
import { fnv1aBytes } from './fnv.js';
|
|
12
|
+
import { CzapValidationError } from './validation-error.js';
|
|
13
|
+
/**
|
|
14
|
+
* Compute the content address for a boundary synchronously.
|
|
15
|
+
* FNV-1a hash of the RFC 8949 §4.2.1 canonical CBOR encoding (ADR-0003).
|
|
16
|
+
* Cross-machine stable: identical definitions produce byte-identical IDs.
|
|
17
|
+
*/
|
|
18
|
+
function deterministicId(input, thresholds, states, hysteresis, spec) {
|
|
19
|
+
return fnv1aBytes(CanonicalCbor.encode({
|
|
20
|
+
_tag: 'BoundaryDef',
|
|
21
|
+
_version: 1,
|
|
22
|
+
input,
|
|
23
|
+
thresholds,
|
|
24
|
+
states,
|
|
25
|
+
hysteresis: hysteresis ?? null,
|
|
26
|
+
spec: spec ?? null,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Evaluate which state a value falls into given a boundary (binary search).
|
|
31
|
+
*
|
|
32
|
+
* Uses binary search to find the rightmost threshold `<= value`, returning
|
|
33
|
+
* the corresponding state name.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const bp = Boundary.make({ input: 'viewport.width', at: [[0, 'sm'], [768, 'md'], [1024, 'lg']] });
|
|
38
|
+
* const state = Boundary.evaluate(bp, 800);
|
|
39
|
+
* // state === 'md'
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
function _evaluate(boundary, value) {
|
|
43
|
+
const { thresholds, states } = boundary;
|
|
44
|
+
const len = thresholds.length;
|
|
45
|
+
// Fast path: unrolled if-chain for small threshold arrays (≤4).
|
|
46
|
+
// Avoids loop overhead and branch prediction misses of binary search.
|
|
47
|
+
// Check from highest threshold downward; first match wins.
|
|
48
|
+
if (len <= 4) {
|
|
49
|
+
if (len === 1) {
|
|
50
|
+
return states[0];
|
|
51
|
+
}
|
|
52
|
+
if (len === 2) {
|
|
53
|
+
if (value >= thresholds[1])
|
|
54
|
+
return states[1];
|
|
55
|
+
return states[0];
|
|
56
|
+
}
|
|
57
|
+
if (len === 3) {
|
|
58
|
+
if (value >= thresholds[2])
|
|
59
|
+
return states[2];
|
|
60
|
+
if (value >= thresholds[1])
|
|
61
|
+
return states[1];
|
|
62
|
+
return states[0];
|
|
63
|
+
}
|
|
64
|
+
// len === 4
|
|
65
|
+
if (value >= thresholds[3])
|
|
66
|
+
return states[3];
|
|
67
|
+
if (value >= thresholds[2])
|
|
68
|
+
return states[2];
|
|
69
|
+
if (value >= thresholds[1])
|
|
70
|
+
return states[1];
|
|
71
|
+
return states[0];
|
|
72
|
+
}
|
|
73
|
+
// Binary search: find the rightmost threshold <= value
|
|
74
|
+
let lo = 0;
|
|
75
|
+
let hi = len;
|
|
76
|
+
while (lo < hi) {
|
|
77
|
+
const mid = (lo + hi) >>> 1;
|
|
78
|
+
if (thresholds[mid] <= value) {
|
|
79
|
+
lo = mid + 1;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
hi = mid;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// lo is the first threshold > value, so lo-1 is the match (or 0 if none)
|
|
86
|
+
return states[lo > 0 ? lo - 1 : 0];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Evaluate with hysteresis (requires previous state). Half-width dead zone algorithm.
|
|
90
|
+
*
|
|
91
|
+
* Prevents flickering at boundary edges by requiring the value to cross
|
|
92
|
+
* beyond a dead zone (half the hysteresis width) before transitioning states.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* const bp = Boundary.make({ input: 'viewport.width', at: [[0, 'sm'], [768, 'md']], hysteresis: 20 });
|
|
97
|
+
* const state1 = Boundary.evaluateWithHysteresis(bp, 770, 'sm');
|
|
98
|
+
* // state1 === 'sm' (within dead zone, stays at previous)
|
|
99
|
+
* const state2 = Boundary.evaluateWithHysteresis(bp, 780, 'sm');
|
|
100
|
+
* // state2 === 'md' (past dead zone, transitions)
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
function _evaluateWithHysteresis(boundary, value, previousState) {
|
|
104
|
+
if (!boundary.hysteresis || boundary.hysteresis <= 0)
|
|
105
|
+
return _evaluate(boundary, value);
|
|
106
|
+
const half = boundary.hysteresis / 2;
|
|
107
|
+
const { thresholds, states } = boundary;
|
|
108
|
+
const prevIdx = states.indexOf(previousState);
|
|
109
|
+
// Unknown previous state -- fall back to raw evaluation
|
|
110
|
+
if (prevIdx === -1)
|
|
111
|
+
return _evaluate(boundary, value);
|
|
112
|
+
// Find raw state via linear scan (matching evaluate semantics)
|
|
113
|
+
let rawIdx = 0;
|
|
114
|
+
for (let i = thresholds.length - 1; i >= 0; i--) {
|
|
115
|
+
if (value >= thresholds[i]) {
|
|
116
|
+
rawIdx = i;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// No crossing needed
|
|
121
|
+
if (rawIdx === prevIdx)
|
|
122
|
+
return states[rawIdx];
|
|
123
|
+
// Dead-zone suppression: when crossing a threshold, require the value to exceed the
|
|
124
|
+
// threshold by half the hysteresis width before committing. Prevents jitter when a
|
|
125
|
+
// signal oscillates near a boundary.
|
|
126
|
+
if (rawIdx > prevIdx) {
|
|
127
|
+
for (let i = prevIdx + 1; i <= rawIdx; i++) {
|
|
128
|
+
if (value < thresholds[i] + half) {
|
|
129
|
+
return states[i - 1];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
for (let i = prevIdx; i > rawIdx; i--) {
|
|
135
|
+
if (value > thresholds[i] - half) {
|
|
136
|
+
return states[i];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return states[rawIdx];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Boundary namespace -- the core primitive of constraint-based adaptive rendering.
|
|
144
|
+
*
|
|
145
|
+
* Create boundaries that quantize continuous signal values into discrete named
|
|
146
|
+
* states. Supports hysteresis for flicker-free transitions at threshold edges.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { Boundary } from '@czap/core';
|
|
151
|
+
*
|
|
152
|
+
* const bp = Boundary.make({
|
|
153
|
+
* input: 'viewport.width',
|
|
154
|
+
* at: [[0, 'mobile'], [768, 'tablet'], [1024, 'desktop']],
|
|
155
|
+
* hysteresis: 20,
|
|
156
|
+
* });
|
|
157
|
+
* const state = Boundary.evaluate(bp, 900);
|
|
158
|
+
* // state === 'tablet'
|
|
159
|
+
* const stableState = Boundary.evaluateWithHysteresis(bp, 770, 'mobile');
|
|
160
|
+
* // stableState === 'mobile' (within dead zone)
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
/**
|
|
164
|
+
* Check whether a boundary is active given its optional spec and current context.
|
|
165
|
+
* Returns true if the boundary has no spec or the spec allows evaluation.
|
|
166
|
+
*/
|
|
167
|
+
function _isActive(boundary, context) {
|
|
168
|
+
return _isSpecActive(boundary.spec, context);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Boundary — core primitive of constraint-based adaptive rendering.
|
|
172
|
+
*
|
|
173
|
+
* A boundary quantizes a continuous signal (viewport, scroll, audio, …) into
|
|
174
|
+
* a discrete set of named states. Every boundary is content-addressed via
|
|
175
|
+
* FNV-1a, supports optional hysteresis to prevent flicker at thresholds, and
|
|
176
|
+
* can be gated by a {@link BoundarySpec} for A/B or device-conditional activation.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* import { Boundary } from '@czap/core';
|
|
181
|
+
*
|
|
182
|
+
* const viewport = Boundary.make({
|
|
183
|
+
* input: 'viewport.width',
|
|
184
|
+
* at: [[0, 'mobile'], [640, 'tablet'], [1024, 'desktop']] as const,
|
|
185
|
+
* hysteresis: 16,
|
|
186
|
+
* });
|
|
187
|
+
* Boundary.evaluate(viewport, 800); // 'tablet'
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export const Boundary = {
|
|
191
|
+
/**
|
|
192
|
+
* Create a new `BoundaryDef` from a configuration object.
|
|
193
|
+
*
|
|
194
|
+
* Thresholds must be strictly ascending. The boundary is content-addressed
|
|
195
|
+
* via FNV-1a hash of its definition.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* const bp = Boundary.make({
|
|
200
|
+
* input: 'viewport.width',
|
|
201
|
+
* at: [[0, 'sm'], [768, 'md'], [1024, 'lg']],
|
|
202
|
+
* hysteresis: 10,
|
|
203
|
+
* });
|
|
204
|
+
* // bp._tag === 'BoundaryDef'
|
|
205
|
+
* // bp.id === 'fnv1a:...' (content address)
|
|
206
|
+
* // bp.states === ['sm', 'md', 'lg']
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
make(config) {
|
|
210
|
+
const pairs = config.at;
|
|
211
|
+
for (let i = 1; i < pairs.length; i++) {
|
|
212
|
+
if (pairs[i][0] <= pairs[i - 1][0]) {
|
|
213
|
+
throw new CzapValidationError('Boundary.make', `thresholds must be strictly ascending. Got ${pairs[i - 1][0]} before ${pairs[i][0]} at index ${i}.`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const stateNames = pairs.map(([, s]) => s);
|
|
217
|
+
const seen = new Set();
|
|
218
|
+
for (const name of stateNames) {
|
|
219
|
+
if (seen.has(name)) {
|
|
220
|
+
throw new CzapValidationError('Boundary.make', `duplicate state name "${name}". Each state must have a unique name.`);
|
|
221
|
+
}
|
|
222
|
+
seen.add(name);
|
|
223
|
+
}
|
|
224
|
+
const thresholds = pairs.map(([t]) => mkThresholdValue(t));
|
|
225
|
+
// tupleMap preserves arity but fn returns `string`, not per-element S[K]; one narrow cast is unavoidable.
|
|
226
|
+
const states = pairs.map(([, s]) => s);
|
|
227
|
+
const id = deterministicId(config.input, thresholds, states, config.hysteresis, config.spec);
|
|
228
|
+
return {
|
|
229
|
+
_tag: 'BoundaryDef',
|
|
230
|
+
_version: 1,
|
|
231
|
+
id,
|
|
232
|
+
input: mkSignalInput(config.input),
|
|
233
|
+
thresholds,
|
|
234
|
+
states,
|
|
235
|
+
...(config.hysteresis !== undefined ? { hysteresis: config.hysteresis } : {}),
|
|
236
|
+
...(config.spec !== undefined ? { spec: config.spec } : {}),
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
evaluate: _evaluate,
|
|
240
|
+
evaluateWithHysteresis: _evaluateWithHysteresis,
|
|
241
|
+
isActive: _isActive,
|
|
242
|
+
};
|
|
243
|
+
/** Check if a BoundarySpec allows evaluation given current context. */
|
|
244
|
+
function _isSpecActive(spec, context) {
|
|
245
|
+
if (!spec)
|
|
246
|
+
return true;
|
|
247
|
+
if (spec.deviceFilter && context?.capabilities) {
|
|
248
|
+
if (!spec.deviceFilter(context.capabilities))
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (spec.timeRange) {
|
|
252
|
+
const now = context?.nowMs ?? Date.now();
|
|
253
|
+
if (spec.timeRange.from !== undefined && now < spec.timeRange.from)
|
|
254
|
+
return false;
|
|
255
|
+
if (spec.timeRange.until !== undefined && now > spec.timeRange.until)
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
if (spec.experimentId && context?.activeExperiments) {
|
|
259
|
+
if (!context.activeExperiments.includes(spec.experimentId))
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
/** BoundarySpec namespace — helpers for working with the optional activation filter on a boundary. */
|
|
265
|
+
export const BoundarySpec = {
|
|
266
|
+
/** Check whether a {@link BoundarySpec} allows evaluation in the given context. */
|
|
267
|
+
isActive: _isSpecActive,
|
|
268
|
+
};
|
|
269
|
+
//# sourceMappingURL=boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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"}
|