@effect-tui/core 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/dist/anim.d.ts +4 -0
- package/dist/anim.d.ts.map +1 -0
- package/dist/anim.js +5 -0
- package/dist/anim.js.map +1 -0
- package/dist/ansi.d.ts +69 -0
- package/dist/ansi.d.ts.map +1 -0
- package/dist/ansi.js +72 -0
- package/dist/ansi.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +18 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +247 -0
- package/dist/keys.js.map +1 -0
- package/dist/layout/linearStack.d.ts +17 -0
- package/dist/layout/linearStack.d.ts.map +1 -0
- package/dist/layout/linearStack.js +86 -0
- package/dist/layout/linearStack.js.map +1 -0
- package/dist/motion-value.d.ts +58 -0
- package/dist/motion-value.d.ts.map +1 -0
- package/dist/motion-value.js +250 -0
- package/dist/motion-value.js.map +1 -0
- package/dist/present/display.d.ts +58 -0
- package/dist/present/display.d.ts.map +1 -0
- package/dist/present/display.js +168 -0
- package/dist/present/display.js.map +1 -0
- package/dist/present/writers/fullscreen.d.ts +19 -0
- package/dist/present/writers/fullscreen.d.ts.map +1 -0
- package/dist/present/writers/fullscreen.js +55 -0
- package/dist/present/writers/fullscreen.js.map +1 -0
- package/dist/present/writers/inline.d.ts +20 -0
- package/dist/present/writers/inline.d.ts.map +1 -0
- package/dist/present/writers/inline.js +92 -0
- package/dist/present/writers/inline.js.map +1 -0
- package/dist/render/buffer.d.ts +31 -0
- package/dist/render/buffer.d.ts.map +1 -0
- package/dist/render/buffer.js +183 -0
- package/dist/render/buffer.js.map +1 -0
- package/dist/render/color-utils.d.ts +18 -0
- package/dist/render/color-utils.d.ts.map +1 -0
- package/dist/render/color-utils.js +58 -0
- package/dist/render/color-utils.js.map +1 -0
- package/dist/render/diff.d.ts +30 -0
- package/dist/render/diff.d.ts.map +1 -0
- package/dist/render/diff.js +83 -0
- package/dist/render/diff.js.map +1 -0
- package/dist/render/measure.d.ts +15 -0
- package/dist/render/measure.d.ts.map +1 -0
- package/dist/render/measure.js +65 -0
- package/dist/render/measure.js.map +1 -0
- package/dist/render/palette.d.ts +46 -0
- package/dist/render/palette.d.ts.map +1 -0
- package/dist/render/palette.js +108 -0
- package/dist/render/palette.js.map +1 -0
- package/dist/render/surface.d.ts +77 -0
- package/dist/render/surface.d.ts.map +1 -0
- package/dist/render/surface.js +198 -0
- package/dist/render/surface.js.map +1 -0
- package/dist/runtime/backend_node.d.ts +36 -0
- package/dist/runtime/backend_node.d.ts.map +1 -0
- package/dist/runtime/backend_node.js +66 -0
- package/dist/runtime/backend_node.js.map +1 -0
- package/dist/spring-physics.d.ts +36 -0
- package/dist/spring-physics.d.ts.map +1 -0
- package/dist/spring-physics.js +113 -0
- package/dist/spring-physics.js.map +1 -0
- package/dist/spring.d.ts +73 -0
- package/dist/spring.d.ts.map +1 -0
- package/dist/spring.js +136 -0
- package/dist/spring.js.map +1 -0
- package/dist/ui/containers/canvas.d.ts +13 -0
- package/dist/ui/containers/canvas.d.ts.map +1 -0
- package/dist/ui/containers/canvas.js +16 -0
- package/dist/ui/containers/canvas.js.map +1 -0
- package/dist/ui/containers/geometry-reader.d.ts +17 -0
- package/dist/ui/containers/geometry-reader.d.ts.map +1 -0
- package/dist/ui/containers/geometry-reader.js +24 -0
- package/dist/ui/containers/geometry-reader.js.map +1 -0
- package/dist/ui/containers/hstack.d.ts +12 -0
- package/dist/ui/containers/hstack.d.ts.map +1 -0
- package/dist/ui/containers/hstack.js +28 -0
- package/dist/ui/containers/hstack.js.map +1 -0
- package/dist/ui/containers/scroll.d.ts +28 -0
- package/dist/ui/containers/scroll.d.ts.map +1 -0
- package/dist/ui/containers/scroll.js +97 -0
- package/dist/ui/containers/scroll.js.map +1 -0
- package/dist/ui/containers/shared.d.ts +12 -0
- package/dist/ui/containers/shared.d.ts.map +1 -0
- package/dist/ui/containers/shared.js +19 -0
- package/dist/ui/containers/shared.js.map +1 -0
- package/dist/ui/containers/vstack.d.ts +12 -0
- package/dist/ui/containers/vstack.d.ts.map +1 -0
- package/dist/ui/containers/vstack.js +28 -0
- package/dist/ui/containers/vstack.js.map +1 -0
- package/dist/ui/containers/zstack.d.ts +14 -0
- package/dist/ui/containers/zstack.d.ts.map +1 -0
- package/dist/ui/containers/zstack.js +36 -0
- package/dist/ui/containers/zstack.js.map +1 -0
- package/dist/ui/core/geometry-store.d.ts +22 -0
- package/dist/ui/core/geometry-store.d.ts.map +1 -0
- package/dist/ui/core/geometry-store.js +29 -0
- package/dist/ui/core/geometry-store.js.map +1 -0
- package/dist/ui/core/geometry.d.ts +34 -0
- package/dist/ui/core/geometry.d.ts.map +1 -0
- package/dist/ui/core/geometry.js +14 -0
- package/dist/ui/core/geometry.js.map +1 -0
- package/dist/ui/core/view.d.ts +25 -0
- package/dist/ui/core/view.d.ts.map +1 -0
- package/dist/ui/core/view.js +34 -0
- package/dist/ui/core/view.js.map +1 -0
- package/dist/ui/index.d.ts +44 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +39 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/inlinetext.d.ts +24 -0
- package/dist/ui/inlinetext.d.ts.map +1 -0
- package/dist/ui/inlinetext.js +131 -0
- package/dist/ui/inlinetext.js.map +1 -0
- package/dist/ui/install.d.ts +22 -0
- package/dist/ui/install.d.ts.map +1 -0
- package/dist/ui/install.js +66 -0
- package/dist/ui/install.js.map +1 -0
- package/dist/ui/markdown.d.ts +40 -0
- package/dist/ui/markdown.d.ts.map +1 -0
- package/dist/ui/markdown.js +351 -0
- package/dist/ui/markdown.js.map +1 -0
- package/dist/ui/modifiers/border.d.ts +33 -0
- package/dist/ui/modifiers/border.d.ts.map +1 -0
- package/dist/ui/modifiers/border.js +82 -0
- package/dist/ui/modifiers/border.js.map +1 -0
- package/dist/ui/modifiers/fill.d.ts +14 -0
- package/dist/ui/modifiers/fill.d.ts.map +1 -0
- package/dist/ui/modifiers/fill.js +25 -0
- package/dist/ui/modifiers/fill.js.map +1 -0
- package/dist/ui/modifiers/frame.d.ts +23 -0
- package/dist/ui/modifiers/frame.d.ts.map +1 -0
- package/dist/ui/modifiers/frame.js +54 -0
- package/dist/ui/modifiers/frame.js.map +1 -0
- package/dist/ui/modifiers/offset.d.ts +15 -0
- package/dist/ui/modifiers/offset.d.ts.map +1 -0
- package/dist/ui/modifiers/offset.js +21 -0
- package/dist/ui/modifiers/offset.js.map +1 -0
- package/dist/ui/modifiers/opacity.d.ts +15 -0
- package/dist/ui/modifiers/opacity.d.ts.map +1 -0
- package/dist/ui/modifiers/opacity.js +95 -0
- package/dist/ui/modifiers/opacity.js.map +1 -0
- package/dist/ui/modifiers/padding.d.ts +20 -0
- package/dist/ui/modifiers/padding.d.ts.map +1 -0
- package/dist/ui/modifiers/padding.js +36 -0
- package/dist/ui/modifiers/padding.js.map +1 -0
- package/dist/ui/modifiers/styled.d.ts +14 -0
- package/dist/ui/modifiers/styled.d.ts.map +1 -0
- package/dist/ui/modifiers/styled.js +26 -0
- package/dist/ui/modifiers/styled.js.map +1 -0
- package/dist/ui/primitives/rectangle.d.ts +15 -0
- package/dist/ui/primitives/rectangle.d.ts.map +1 -0
- package/dist/ui/primitives/rectangle.js +23 -0
- package/dist/ui/primitives/rectangle.js.map +1 -0
- package/dist/ui/primitives/spacer.d.ts +13 -0
- package/dist/ui/primitives/spacer.d.ts.map +1 -0
- package/dist/ui/primitives/spacer.js +16 -0
- package/dist/ui/primitives/spacer.js.map +1 -0
- package/dist/ui/primitives/text.d.ts +15 -0
- package/dist/ui/primitives/text.d.ts.map +1 -0
- package/dist/ui/primitives/text.js +79 -0
- package/dist/ui/primitives/text.js.map +1 -0
- package/dist/ui/primitives/wrapped-text.d.ts +30 -0
- package/dist/ui/primitives/wrapped-text.d.ts.map +1 -0
- package/dist/ui/primitives/wrapped-text.js +117 -0
- package/dist/ui/primitives/wrapped-text.js.map +1 -0
- package/dist/ui/shinytext.d.ts +66 -0
- package/dist/ui/shinytext.d.ts.map +1 -0
- package/dist/ui/shinytext.js +99 -0
- package/dist/ui/shinytext.js.map +1 -0
- package/dist/ui/text/layout.d.ts +35 -0
- package/dist/ui/text/layout.d.ts.map +1 -0
- package/dist/ui/text/layout.js +102 -0
- package/dist/ui/text/layout.js.map +1 -0
- package/dist/ui/textinput.d.ts +140 -0
- package/dist/ui/textinput.d.ts.map +1 -0
- package/dist/ui/textinput.js +402 -0
- package/dist/ui/textinput.js.map +1 -0
- package/dist/ui/view-constructors.d.ts +72 -0
- package/dist/ui/view-constructors.d.ts.map +1 -0
- package/dist/ui/view-constructors.js +74 -0
- package/dist/ui/view-constructors.js.map +1 -0
- package/package.json +57 -0
- package/src/anim.ts +5 -0
- package/src/ansi.ts +83 -0
- package/src/index.ts +21 -0
- package/src/keys.ts +302 -0
- package/src/layout/linearStack.ts +115 -0
- package/src/motion-value.ts +335 -0
- package/src/present/display.ts +206 -0
- package/src/present/writers/fullscreen.ts +58 -0
- package/src/present/writers/inline.ts +101 -0
- package/src/render/buffer.ts +200 -0
- package/src/render/color-utils.ts +60 -0
- package/src/render/diff.ts +95 -0
- package/src/render/measure.ts +74 -0
- package/src/render/palette.ts +113 -0
- package/src/render/surface.ts +238 -0
- package/src/runtime/backend_node.ts +80 -0
- package/src/spring-physics.ts +151 -0
- package/src/spring.ts +234 -0
- package/src/ui/__snapshots__/wrappedtext.test.ts.snap +57 -0
- package/src/ui/containers/canvas.ts +18 -0
- package/src/ui/containers/geometry-reader.ts +32 -0
- package/src/ui/containers/hstack.ts +33 -0
- package/src/ui/containers/scroll.ts +106 -0
- package/src/ui/containers/shared.ts +27 -0
- package/src/ui/containers/vstack.ts +34 -0
- package/src/ui/containers/zstack.ts +37 -0
- package/src/ui/core/geometry-store.ts +42 -0
- package/src/ui/core/geometry.ts +30 -0
- package/src/ui/core/view.ts +49 -0
- package/src/ui/index.ts +84 -0
- package/src/ui/inlinetext.ts +135 -0
- package/src/ui/install.ts +110 -0
- package/src/ui/markdown.test.ts +74 -0
- package/src/ui/markdown.ts +388 -0
- package/src/ui/modifiers/border.ts +100 -0
- package/src/ui/modifiers/fill.ts +28 -0
- package/src/ui/modifiers/frame.ts +74 -0
- package/src/ui/modifiers/offset.ts +23 -0
- package/src/ui/modifiers/opacity.ts +93 -0
- package/src/ui/modifiers/padding.ts +53 -0
- package/src/ui/modifiers/styled.ts +31 -0
- package/src/ui/primitives/rectangle.ts +25 -0
- package/src/ui/primitives/spacer.ts +18 -0
- package/src/ui/primitives/text.ts +85 -0
- package/src/ui/primitives/wrapped-text.ts +131 -0
- package/src/ui/shinytext.ts +159 -0
- package/src/ui/text/layout.ts +119 -0
- package/src/ui/textinput.ts +496 -0
- package/src/ui/view-constructors.ts +96 -0
- package/src/ui/wrappedtext.test.ts +138 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface TerminalBackend {
|
|
2
|
+
size(): {
|
|
3
|
+
cols: number;
|
|
4
|
+
rows: number;
|
|
5
|
+
};
|
|
6
|
+
write(s: string): void;
|
|
7
|
+
enterFullscreen(): void;
|
|
8
|
+
exitFullscreen(): void;
|
|
9
|
+
hideCursor(): void;
|
|
10
|
+
showCursor(): void;
|
|
11
|
+
enableMouse(): void;
|
|
12
|
+
disableMouse(): void;
|
|
13
|
+
/** Query terminal for current cursor position (1-based). */
|
|
14
|
+
getCursorPosition(): Promise<{
|
|
15
|
+
row: number;
|
|
16
|
+
col: number;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export declare class TerminalBackendLive implements TerminalBackend {
|
|
20
|
+
size(): {
|
|
21
|
+
cols: number;
|
|
22
|
+
rows: number;
|
|
23
|
+
};
|
|
24
|
+
write(s: string): void;
|
|
25
|
+
enterFullscreen(): void;
|
|
26
|
+
exitFullscreen(): void;
|
|
27
|
+
hideCursor(): void;
|
|
28
|
+
showCursor(): void;
|
|
29
|
+
enableMouse(): void;
|
|
30
|
+
disableMouse(): void;
|
|
31
|
+
getCursorPosition(): Promise<{
|
|
32
|
+
row: number;
|
|
33
|
+
col: number;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=backend_node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_node.d.ts","sourceRoot":"","sources":["../../src/runtime/backend_node.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,eAAe,IAAI,IAAI,CAAA;IACvB,cAAc,IAAI,IAAI,CAAA;IACtB,UAAU,IAAI,IAAI,CAAA;IAClB,UAAU,IAAI,IAAI,CAAA;IAClB,WAAW,IAAI,IAAI,CAAA;IACnB,YAAY,IAAI,IAAI,CAAA;IACpB,4DAA4D;IAC5D,iBAAiB,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED,qBAAa,mBAAoB,YAAW,eAAe;IACzD,IAAI;;;;IAGJ,KAAK,CAAC,CAAC,EAAE,MAAM;IASf,eAAe;IAKf,cAAc;IAKd,UAAU;IAGV,UAAU;IAGV,WAAW;IAGX,YAAY;IAIZ,iBAAiB,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CA4B3D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ANSI, Terminal } from "../ansi.js";
|
|
2
|
+
export class TerminalBackendLive {
|
|
3
|
+
size() {
|
|
4
|
+
return { cols: process.stdout.columns || 80, rows: process.stdout.rows || 24 };
|
|
5
|
+
}
|
|
6
|
+
write(s) {
|
|
7
|
+
try {
|
|
8
|
+
if (!process.stdout.write(s)) {
|
|
9
|
+
// queue a microtask to flush on 'drain' without blocking
|
|
10
|
+
const onDrain = () => process.stdout.off("drain", onDrain);
|
|
11
|
+
process.stdout.on("drain", onDrain);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
}
|
|
16
|
+
enterFullscreen() {
|
|
17
|
+
this.write(Terminal.enterFullscreen);
|
|
18
|
+
this.write(Terminal.bracketedPasteOn);
|
|
19
|
+
this.enableMouse();
|
|
20
|
+
}
|
|
21
|
+
exitFullscreen() {
|
|
22
|
+
this.disableMouse();
|
|
23
|
+
this.write(Terminal.bracketedPasteOff);
|
|
24
|
+
this.write(Terminal.exitFullscreen);
|
|
25
|
+
}
|
|
26
|
+
hideCursor() {
|
|
27
|
+
this.write(ANSI.cursor.hide);
|
|
28
|
+
}
|
|
29
|
+
showCursor() {
|
|
30
|
+
this.write(ANSI.cursor.show);
|
|
31
|
+
}
|
|
32
|
+
enableMouse() {
|
|
33
|
+
this.write(Terminal.mouseOn);
|
|
34
|
+
}
|
|
35
|
+
disableMouse() {
|
|
36
|
+
this.write(Terminal.mouseOff);
|
|
37
|
+
}
|
|
38
|
+
getCursorPosition() {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
const inp = process.stdin;
|
|
41
|
+
let buf = "";
|
|
42
|
+
const onData = (b) => {
|
|
43
|
+
buf += b.toString("utf8");
|
|
44
|
+
// Look for ESC [ row ; col R
|
|
45
|
+
const m = /\x1b\[(\d+);(\d+)R/.exec(buf);
|
|
46
|
+
if (m) {
|
|
47
|
+
cleanup();
|
|
48
|
+
resolve({ row: parseInt(m[1], 10) || 1, col: parseInt(m[2], 10) || 1 });
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const cleanup = () => {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
inp.off("data", onData);
|
|
54
|
+
};
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
cleanup();
|
|
57
|
+
// Fallback: best effort guess (bottom-left)
|
|
58
|
+
resolve({ row: process.stdout.rows || 24, col: 1 });
|
|
59
|
+
}, 120);
|
|
60
|
+
inp.on("data", onData);
|
|
61
|
+
// Device Status Report: “Report Cursor Position”
|
|
62
|
+
this.write(Terminal.reportCursorPosition);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=backend_node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_node.js","sourceRoot":"","sources":["../../src/runtime/backend_node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type SpringState = {
|
|
2
|
+
x: number;
|
|
3
|
+
v: number;
|
|
4
|
+
target: number;
|
|
5
|
+
};
|
|
6
|
+
export type SpringConfig = {
|
|
7
|
+
frequency?: number;
|
|
8
|
+
dampingRatio?: number;
|
|
9
|
+
epsilon?: number;
|
|
10
|
+
duration?: number;
|
|
11
|
+
bounce?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const DEFAULTS: Required<Omit<SpringConfig, "duration">> & {
|
|
14
|
+
duration?: number;
|
|
15
|
+
};
|
|
16
|
+
export declare function fromDurationBounce(durationSec: number, bounce?: number): {
|
|
17
|
+
frequency: number;
|
|
18
|
+
dampingRatio: number;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Advance a 1D damped spring towards its target using a semi-implicit Euler step.
|
|
22
|
+
* - Stable enough for small dt (<= ~1/30s) typical of frame ticks.
|
|
23
|
+
* - Uses frequency/dampingRatio to feel similar across frame rates.
|
|
24
|
+
*/
|
|
25
|
+
export declare function advanceSpring(state: SpringState, dtSeconds: number, config?: SpringConfig): SpringState & {
|
|
26
|
+
settled: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Internal exact spring step for 1D channel (frame-rate independent).
|
|
30
|
+
* Uses closed-form analytical solution for underdamped/critically-damped/overdamped cases.
|
|
31
|
+
*/
|
|
32
|
+
export declare function stepSpring1D(x: number, v: number, target: number, dt: number, freq: number, zeta: number): {
|
|
33
|
+
x: number;
|
|
34
|
+
v: number;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=spring-physics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring-physics.d.ts","sourceRoot":"","sources":["../src/spring-physics.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IAEzB,CAAC,EAAE,MAAM,CAAA;IAET,CAAC,EAAE,MAAM,CAAA;IAET,MAAM,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAE1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB,OAAO,CAAC,EAAE,MAAM,CAAA;IAGhB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,MAAM,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAMpF,CAAA;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAgB/G;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACnB,WAAW,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CA4CpC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACV;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAiC1B"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// spring-physics.ts - Core spring physics primitives
|
|
2
|
+
export const DEFAULTS = {
|
|
3
|
+
frequency: 3,
|
|
4
|
+
dampingRatio: 1,
|
|
5
|
+
epsilon: 0.0005,
|
|
6
|
+
duration: undefined,
|
|
7
|
+
bounce: 0,
|
|
8
|
+
};
|
|
9
|
+
export function fromDurationBounce(durationSec, bounce = 0) {
|
|
10
|
+
const d = Math.max(0.05, durationSec);
|
|
11
|
+
let zeta;
|
|
12
|
+
const b = Math.max(0, Math.min(0.999, bounce));
|
|
13
|
+
if (b <= 0) {
|
|
14
|
+
zeta = 1; // critically damped, no overshoot
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// Map overshoot ratio M_p=b to damping ratio via standard 2nd-order step response
|
|
18
|
+
const lnMp = Math.log(Math.max(1e-6, b));
|
|
19
|
+
zeta = Math.sqrt((lnMp * lnMp) / (Math.PI * Math.PI + lnMp * lnMp));
|
|
20
|
+
zeta = Math.max(0.02, Math.min(0.999, zeta));
|
|
21
|
+
}
|
|
22
|
+
// Use ~2% settling time approximation Ts ≈ 4/(ζ ω_n)
|
|
23
|
+
const omega = 4 / (Math.max(0.02, zeta) * d);
|
|
24
|
+
const freq = omega / (2 * Math.PI);
|
|
25
|
+
return { frequency: freq, dampingRatio: zeta };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Advance a 1D damped spring towards its target using a semi-implicit Euler step.
|
|
29
|
+
* - Stable enough for small dt (<= ~1/30s) typical of frame ticks.
|
|
30
|
+
* - Uses frequency/dampingRatio to feel similar across frame rates.
|
|
31
|
+
*/
|
|
32
|
+
export function advanceSpring(state, dtSeconds, config) {
|
|
33
|
+
let { frequency, dampingRatio, epsilon } = { ...DEFAULTS, ...(config ?? {}) };
|
|
34
|
+
const bounce = config?.bounce ?? DEFAULTS.bounce;
|
|
35
|
+
// If duration is provided, derive frequency/dampingRatio from it and bounce
|
|
36
|
+
if (config?.duration != null) {
|
|
37
|
+
const derived = fromDurationBounce(config.duration, config.bounce ?? DEFAULTS.bounce);
|
|
38
|
+
frequency = derived.frequency;
|
|
39
|
+
dampingRatio = derived.dampingRatio;
|
|
40
|
+
}
|
|
41
|
+
const omega = Math.PI * 2 * Math.max(0.001, frequency);
|
|
42
|
+
const k = omega * omega; // stiffness
|
|
43
|
+
const c = 2 * dampingRatio * omega; // damping
|
|
44
|
+
let { x, v, target } = state;
|
|
45
|
+
const prevX = x;
|
|
46
|
+
if (dtSeconds <= 0)
|
|
47
|
+
return {
|
|
48
|
+
x,
|
|
49
|
+
v,
|
|
50
|
+
target,
|
|
51
|
+
settled: Math.abs(x - target) < epsilon && Math.abs(v) < epsilon,
|
|
52
|
+
};
|
|
53
|
+
// semi-implicit Euler integration
|
|
54
|
+
const a = k * (target - x) - c * v;
|
|
55
|
+
v += a * dtSeconds;
|
|
56
|
+
x += v * dtSeconds;
|
|
57
|
+
// With bounce=0 users expect a monotonic approach; clamp if we cross the target.
|
|
58
|
+
if (bounce <= 0) {
|
|
59
|
+
const crossed = (prevX - target) * (x - target) <= 0;
|
|
60
|
+
if (crossed) {
|
|
61
|
+
x = target;
|
|
62
|
+
v = 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// snap to target when sufficiently close to avoid long tails
|
|
66
|
+
const settled = Math.abs(x - target) < epsilon && Math.abs(v) < epsilon;
|
|
67
|
+
if (settled) {
|
|
68
|
+
x = target;
|
|
69
|
+
v = 0;
|
|
70
|
+
}
|
|
71
|
+
return { x, v, target, settled };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Internal exact spring step for 1D channel (frame-rate independent).
|
|
75
|
+
* Uses closed-form analytical solution for underdamped/critically-damped/overdamped cases.
|
|
76
|
+
*/
|
|
77
|
+
export function stepSpring1D(x, v, target, dt, freq, zeta) {
|
|
78
|
+
const omega = Math.max(0.001, freq) * 2 * Math.PI;
|
|
79
|
+
const A0 = x - target;
|
|
80
|
+
const exp = Math.exp(-zeta * omega * dt);
|
|
81
|
+
if (zeta < 1) {
|
|
82
|
+
// Underdamped
|
|
83
|
+
const wd = omega * Math.sqrt(1 - zeta * zeta);
|
|
84
|
+
const cos = Math.cos(wd * dt);
|
|
85
|
+
const sin = Math.sin(wd * dt);
|
|
86
|
+
const B0 = v + zeta * omega * A0;
|
|
87
|
+
const A = exp * (A0 * cos + (B0 / wd) * sin);
|
|
88
|
+
const dA = exp * (-zeta * omega * (A0 * cos + (B0 / wd) * sin) + (-A0 * wd * sin + B0 * cos));
|
|
89
|
+
return { x: target + A, v: dA };
|
|
90
|
+
}
|
|
91
|
+
else if (zeta === 1) {
|
|
92
|
+
// Critically damped
|
|
93
|
+
const t = dt;
|
|
94
|
+
const C2 = v + omega * A0;
|
|
95
|
+
const A = exp * (A0 + C2 * t);
|
|
96
|
+
const dA = exp * (C2 - omega * (A0 + C2 * t));
|
|
97
|
+
return { x: target + A, v: dA };
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Overdamped
|
|
101
|
+
const s = Math.sqrt(zeta * zeta - 1);
|
|
102
|
+
const r1 = -omega * (zeta - s);
|
|
103
|
+
const r2 = -omega * (zeta + s);
|
|
104
|
+
const C1 = (v - r2 * A0) / (r1 - r2);
|
|
105
|
+
const C2 = A0 - C1;
|
|
106
|
+
const e1 = Math.exp(r1 * dt);
|
|
107
|
+
const e2 = Math.exp(r2 * dt);
|
|
108
|
+
const A = C1 * e1 + C2 * e2;
|
|
109
|
+
const dA = C1 * r1 * e1 + C2 * r2 * e2;
|
|
110
|
+
return { x: target + A, v: dA };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=spring-physics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring-physics.js","sourceRoot":"","sources":["../src/spring-physics.ts"],"names":[],"mappings":"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"}
|
package/dist/spring.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ColorLike, ColorValue } from "./render/surface.js";
|
|
2
|
+
import { type SpringConfig, type SpringState } from "./spring-physics.js";
|
|
3
|
+
export type SpringValue = SpringState & {
|
|
4
|
+
/** last timestamp in ms used for dt; hidden from callers */
|
|
5
|
+
_last?: number;
|
|
6
|
+
/** default config for ticks (optional) */
|
|
7
|
+
_config?: SpringConfig;
|
|
8
|
+
};
|
|
9
|
+
export type SpringColorValue = {
|
|
10
|
+
x: {
|
|
11
|
+
r: number;
|
|
12
|
+
g: number;
|
|
13
|
+
b: number;
|
|
14
|
+
};
|
|
15
|
+
v: {
|
|
16
|
+
r: number;
|
|
17
|
+
g: number;
|
|
18
|
+
b: number;
|
|
19
|
+
};
|
|
20
|
+
target: {
|
|
21
|
+
r: number;
|
|
22
|
+
g: number;
|
|
23
|
+
b: number;
|
|
24
|
+
};
|
|
25
|
+
_last?: number;
|
|
26
|
+
_config?: SpringConfig;
|
|
27
|
+
};
|
|
28
|
+
export type AnySpringValue = SpringValue | SpringColorValue;
|
|
29
|
+
export type SpringAutoOptions = SpringConfig & {
|
|
30
|
+
as?: "auto" | "number" | "color";
|
|
31
|
+
};
|
|
32
|
+
export declare function colorLikeToRGB(c: ColorLike): {
|
|
33
|
+
r: number;
|
|
34
|
+
g: number;
|
|
35
|
+
b: number;
|
|
36
|
+
};
|
|
37
|
+
export type SpringAPI = {
|
|
38
|
+
init(initial: number, cfg?: SpringConfig): SpringValue;
|
|
39
|
+
to(s: SpringValue, target: number): SpringValue;
|
|
40
|
+
tick(s: SpringValue, nowMs: number, cfg?: SpringConfig): SpringValue;
|
|
41
|
+
value(s: SpringValue): number;
|
|
42
|
+
settled(s: SpringValue, eps?: number): boolean;
|
|
43
|
+
color: {
|
|
44
|
+
init(initial: ColorLike, cfg?: SpringConfig): SpringColorValue;
|
|
45
|
+
to(s: SpringColorValue, target: ColorLike): SpringColorValue;
|
|
46
|
+
tick(s: SpringColorValue, nowMs: number, cfg?: SpringConfig): SpringColorValue;
|
|
47
|
+
value(s: SpringColorValue): ColorValue;
|
|
48
|
+
settled(s: SpringColorValue, eps?: number): boolean;
|
|
49
|
+
};
|
|
50
|
+
create(initial: number, cfg?: SpringAutoOptions): SpringValue;
|
|
51
|
+
create(initial: ColorLike, cfg?: SpringAutoOptions): SpringColorValue;
|
|
52
|
+
to(s: SpringColorValue, target: ColorLike): SpringColorValue;
|
|
53
|
+
tick(s: SpringColorValue, nowMs: number, cfg?: SpringConfig): SpringColorValue;
|
|
54
|
+
advance(s: SpringValue, nowMs: number, cfg?: SpringConfig): SpringValue;
|
|
55
|
+
advance(s: SpringColorValue, nowMs: number, cfg?: SpringConfig): SpringColorValue;
|
|
56
|
+
read(s: SpringValue): number;
|
|
57
|
+
read(s: SpringColorValue): ColorValue;
|
|
58
|
+
isSettled(s: SpringValue, eps?: number): boolean;
|
|
59
|
+
isSettled(s: SpringColorValue, eps?: number): boolean;
|
|
60
|
+
};
|
|
61
|
+
export declare const Spring: SpringAPI;
|
|
62
|
+
export type Stepper = {
|
|
63
|
+
index: number;
|
|
64
|
+
length: number;
|
|
65
|
+
intervalMs: number;
|
|
66
|
+
_accumMs: number;
|
|
67
|
+
_last?: number;
|
|
68
|
+
};
|
|
69
|
+
export declare const Step: {
|
|
70
|
+
init(length: number, intervalMs: number, startIndex?: number): Stepper;
|
|
71
|
+
tick(s: Stepper, nowMs: number): Stepper;
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=spring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring.d.ts","sourceRoot":"","sources":["../src/spring.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAGhE,OAAO,EAA2B,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAIlG,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IACvC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,OAAO,CAAC,EAAE,YAAY,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC9B,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,YAAY,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,gBAAgB,CAAA;AAE3D,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG;IAC9C,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;CAChC,CAAA;AAID,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAIhF;AAwHD,MAAM,MAAM,SAAS,GAAG;IAEvB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,WAAW,CAAA;IACtD,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAA;IAC/C,IAAI,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,WAAW,CAAA;IACpE,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IAC7B,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAG9C,KAAK,EAAE;QACN,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAAA;QAC9D,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAAA;QAC5D,IAAI,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAAA;QAC9E,KAAK,CAAC,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAAA;QACtC,OAAO,CAAC,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KACnD,CAAA;IAGD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAAA;IAC7D,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,iBAAiB,GAAG,gBAAgB,CAAA;IACrE,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,GAAG,gBAAgB,CAAA;IAC5D,IAAI,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAAA;IAC9E,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,WAAW,CAAA;IACvE,OAAO,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAAA;IACjF,IAAI,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;IAC5B,IAAI,CAAC,CAAC,EAAE,gBAAgB,GAAG,UAAU,CAAA;IACrC,SAAS,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAChD,SAAS,CAAC,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrD,CAAA;AAED,eAAO,MAAM,MAAM,EAAE,SAgBpB,CAAA;AAID,MAAM,MAAM,OAAO,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,IAAI;iBACH,MAAM,cAAc,MAAM,wBAAmB,OAAO;YAQzD,OAAO,SAAS,MAAM,GAAG,OAAO;CAUxC,CAAA"}
|
package/dist/spring.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// spring.ts - Higher-level spring API for number and color values
|
|
2
|
+
import { parseColor } from "./render/surface.js";
|
|
3
|
+
import { idxToRGB } from "./render/color-utils.js";
|
|
4
|
+
import { advanceSpring, DEFAULTS } from "./spring-physics.js";
|
|
5
|
+
// ---- Helpers ----
|
|
6
|
+
export function colorLikeToRGB(c) {
|
|
7
|
+
const v = parseColor(c);
|
|
8
|
+
if (typeof v === "number")
|
|
9
|
+
return idxToRGB(v);
|
|
10
|
+
return { r: v.r | 0, g: v.g | 0, b: v.b | 0 };
|
|
11
|
+
}
|
|
12
|
+
function isColorSpring(s) {
|
|
13
|
+
return typeof s.x === "object";
|
|
14
|
+
}
|
|
15
|
+
// ---- Number spring primitives ----
|
|
16
|
+
function initNumber(initial, cfg) {
|
|
17
|
+
return {
|
|
18
|
+
x: initial,
|
|
19
|
+
v: 0,
|
|
20
|
+
target: initial,
|
|
21
|
+
...(cfg && { _config: cfg }),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function tickNumber(s, nowMs, cfg) {
|
|
25
|
+
const last = s._last ?? nowMs;
|
|
26
|
+
const dt = Math.max(0, Math.min(0.1, (nowMs - last) / 1000));
|
|
27
|
+
const stepped = advanceSpring(s, dt, cfg ?? s._config);
|
|
28
|
+
return {
|
|
29
|
+
...s,
|
|
30
|
+
x: stepped.x,
|
|
31
|
+
v: stepped.v,
|
|
32
|
+
target: stepped.target,
|
|
33
|
+
_last: nowMs,
|
|
34
|
+
...(cfg || s._config ? { _config: cfg ?? s._config } : {}),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function toNumber(s, target) {
|
|
38
|
+
return { ...s, target };
|
|
39
|
+
}
|
|
40
|
+
function valueNumber(s) {
|
|
41
|
+
return s.x;
|
|
42
|
+
}
|
|
43
|
+
function settledNumber(s, eps = DEFAULTS.epsilon) {
|
|
44
|
+
return Math.abs(s.x - s.target) < eps && Math.abs(s.v) < eps;
|
|
45
|
+
}
|
|
46
|
+
// ---- Color spring primitives ----
|
|
47
|
+
const SpringColor = {
|
|
48
|
+
init(initial, cfg) {
|
|
49
|
+
const rgb = colorLikeToRGB(initial);
|
|
50
|
+
return {
|
|
51
|
+
x: { ...rgb },
|
|
52
|
+
v: { r: 0, g: 0, b: 0 },
|
|
53
|
+
target: { ...rgb },
|
|
54
|
+
...(cfg && { _config: cfg }),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
to(s, target) {
|
|
58
|
+
const rgb = colorLikeToRGB(target);
|
|
59
|
+
return { ...s, target: { ...rgb } };
|
|
60
|
+
},
|
|
61
|
+
tick(s, nowMs, cfg) {
|
|
62
|
+
const last = s._last ?? nowMs;
|
|
63
|
+
const dt = Math.max(0, Math.min(0.1, (nowMs - last) / 1000));
|
|
64
|
+
const rx = advanceSpring({ x: s.x.r, v: s.v.r, target: s.target.r }, dt, cfg ?? s._config);
|
|
65
|
+
const gx = advanceSpring({ x: s.x.g, v: s.v.g, target: s.target.g }, dt, cfg ?? s._config);
|
|
66
|
+
const bx = advanceSpring({ x: s.x.b, v: s.v.b, target: s.target.b }, dt, cfg ?? s._config);
|
|
67
|
+
return {
|
|
68
|
+
x: { r: rx.x, g: gx.x, b: bx.x },
|
|
69
|
+
v: { r: rx.v, g: gx.v, b: bx.v },
|
|
70
|
+
target: { r: s.target.r, g: s.target.g, b: s.target.b },
|
|
71
|
+
_last: nowMs,
|
|
72
|
+
...(cfg || s._config ? { _config: cfg ?? s._config } : {}),
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
value(s) {
|
|
76
|
+
const clamp = (n) => (n < 0 ? 0 : n > 255 ? 255 : n | 0);
|
|
77
|
+
return { r: clamp(s.x.r), g: clamp(s.x.g), b: clamp(s.x.b) };
|
|
78
|
+
},
|
|
79
|
+
settled(s, eps = DEFAULTS.epsilon) {
|
|
80
|
+
const dx = Math.abs(s.x.r - s.target.r) + Math.abs(s.x.g - s.target.g) + Math.abs(s.x.b - s.target.b);
|
|
81
|
+
const dv = Math.abs(s.v.r) + Math.abs(s.v.g) + Math.abs(s.v.b);
|
|
82
|
+
return dx < eps * 3 && dv < eps * 3;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
function create(initial, cfg) {
|
|
86
|
+
const as = cfg?.as ?? (typeof initial === "number" ? "number" : "color");
|
|
87
|
+
return as === "number" ? initNumber(initial, cfg) : SpringColor.init(initial, cfg);
|
|
88
|
+
}
|
|
89
|
+
function to(s, target) {
|
|
90
|
+
return isColorSpring(s) ? SpringColor.to(s, target) : toNumber(s, target);
|
|
91
|
+
}
|
|
92
|
+
function tick(s, nowMs, cfg) {
|
|
93
|
+
return isColorSpring(s) ? SpringColor.tick(s, nowMs, cfg) : tickNumber(s, nowMs, cfg);
|
|
94
|
+
}
|
|
95
|
+
function read(s) {
|
|
96
|
+
return isColorSpring(s) ? SpringColor.value(s) : valueNumber(s);
|
|
97
|
+
}
|
|
98
|
+
function isSettled(s, eps = DEFAULTS.epsilon) {
|
|
99
|
+
return isColorSpring(s) ? SpringColor.settled(s, eps) : settledNumber(s, eps);
|
|
100
|
+
}
|
|
101
|
+
export const Spring = {
|
|
102
|
+
// number
|
|
103
|
+
init: initNumber,
|
|
104
|
+
to,
|
|
105
|
+
tick,
|
|
106
|
+
value: valueNumber,
|
|
107
|
+
settled: settledNumber,
|
|
108
|
+
// color (explicit path)
|
|
109
|
+
color: SpringColor,
|
|
110
|
+
// unified ergonomic API
|
|
111
|
+
create,
|
|
112
|
+
advance: tick,
|
|
113
|
+
read,
|
|
114
|
+
isSettled,
|
|
115
|
+
};
|
|
116
|
+
export const Step = {
|
|
117
|
+
init(length, intervalMs, startIndex = 0) {
|
|
118
|
+
return {
|
|
119
|
+
index: ((startIndex % length) + length) % length,
|
|
120
|
+
length: Math.max(1, length | 0),
|
|
121
|
+
intervalMs: Math.max(1, intervalMs | 0),
|
|
122
|
+
_accumMs: 0,
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
tick(s, nowMs) {
|
|
126
|
+
const last = s._last ?? nowMs;
|
|
127
|
+
let accum = s._accumMs + Math.max(0, nowMs - last);
|
|
128
|
+
let idx = s.index;
|
|
129
|
+
while (accum >= s.intervalMs) {
|
|
130
|
+
accum -= s.intervalMs;
|
|
131
|
+
idx = (idx + 1) % s.length;
|
|
132
|
+
}
|
|
133
|
+
return { ...s, index: idx, _accumMs: accum, _last: nowMs };
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=spring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring.js","sourceRoot":"","sources":["../src/spring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Palette, Surface } from "../../render/surface.js";
|
|
2
|
+
import { View } from "../core/view.js";
|
|
3
|
+
import type { Rect } from "../core/geometry.js";
|
|
4
|
+
export declare class Canvas extends View {
|
|
5
|
+
readonly paint: (s: Surface, pal: Palette, rect: Rect) => void;
|
|
6
|
+
constructor(paint: (s: Surface, pal: Palette, rect: Rect) => void);
|
|
7
|
+
protected measureContent(maxW: number, maxH: number): {
|
|
8
|
+
w: number;
|
|
9
|
+
h: number;
|
|
10
|
+
};
|
|
11
|
+
protected renderContent(s: Surface, pal: Palette, rect: Rect): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=canvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/ui/containers/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAE/C,qBAAa,MAAO,SAAQ,IAAI;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI;gBAArD,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI;IAI1E,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;;IAKnD,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;CAG7D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { View } from "../core/view.js";
|
|
2
|
+
export class Canvas extends View {
|
|
3
|
+
paint;
|
|
4
|
+
constructor(paint) {
|
|
5
|
+
super();
|
|
6
|
+
this.paint = paint;
|
|
7
|
+
}
|
|
8
|
+
measureContent(maxW, maxH) {
|
|
9
|
+
// Greedy: occupy the full available area (caller can constrain via frame())
|
|
10
|
+
return { w: Math.max(0, maxW), h: Math.max(0, maxH) };
|
|
11
|
+
}
|
|
12
|
+
renderContent(s, pal, rect) {
|
|
13
|
+
this.paint(s, pal, rect);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=canvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../../src/ui/containers/canvas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAGtC,MAAM,OAAO,MAAO,SAAQ,IAAI;IACT;IAArB,YAAqB,KAAqD;QACxE,KAAK,EAAE,CAAA;QADY,UAAK,GAAL,KAAK,CAAgD;IAE1E,CAAC;IAES,cAAc,CAAC,IAAY,EAAE,IAAY;QACjD,4EAA4E;QAC5E,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAA;IACvD,CAAC;IAES,aAAa,CAAC,CAAU,EAAE,GAAY,EAAE,IAAU;QAC1D,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Palette, Surface } from "../../render/surface.js";
|
|
2
|
+
import { View } from "../core/view.js";
|
|
3
|
+
import type { Rect } from "../core/geometry.js";
|
|
4
|
+
export type GeometryProxy = {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
};
|
|
8
|
+
export declare class GeometryReader extends View {
|
|
9
|
+
readonly reader: (proxy: GeometryProxy) => View;
|
|
10
|
+
constructor(reader: (proxy: GeometryProxy) => View);
|
|
11
|
+
protected measureContent(maxW: number, maxH: number): {
|
|
12
|
+
w: number;
|
|
13
|
+
h: number;
|
|
14
|
+
};
|
|
15
|
+
protected renderContent(s: Surface, pal: Palette, rect: Rect): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=geometry-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry-reader.d.ts","sourceRoot":"","sources":["../../../src/ui/containers/geometry-reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAG/C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qBAAa,cAAe,SAAQ,IAAI;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;gBAAtC,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;IAI3D,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;;;IAKnD,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;CAW7D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { View } from "../core/view.js";
|
|
2
|
+
export class GeometryReader extends View {
|
|
3
|
+
reader;
|
|
4
|
+
constructor(reader) {
|
|
5
|
+
super();
|
|
6
|
+
this.reader = reader;
|
|
7
|
+
}
|
|
8
|
+
measureContent(maxW, maxH) {
|
|
9
|
+
// GeometryReader is greedy - takes all available space
|
|
10
|
+
return { w: maxW, h: maxH };
|
|
11
|
+
}
|
|
12
|
+
renderContent(s, pal, rect) {
|
|
13
|
+
// Create the child with the actual geometry
|
|
14
|
+
const proxy = {
|
|
15
|
+
width: rect.w,
|
|
16
|
+
height: rect.h,
|
|
17
|
+
};
|
|
18
|
+
const child = this.reader(proxy);
|
|
19
|
+
// Measure the child first, then render
|
|
20
|
+
child.measure(rect.w, rect.h);
|
|
21
|
+
child.render(s, pal, rect);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=geometry-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry-reader.js","sourceRoot":"","sources":["../../../src/ui/containers/geometry-reader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAStC,MAAM,OAAO,cAAe,SAAQ,IAAI;IACjB;IAArB,YAAqB,MAAsC;QACzD,KAAK,EAAE,CAAA;QADY,WAAM,GAAN,MAAM,CAAgC;IAE3D,CAAC;IAES,cAAc,CAAC,IAAY,EAAE,IAAY;QACjD,uDAAuD;QACvD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAA;IAC7B,CAAC;IAES,aAAa,CAAC,CAAU,EAAE,GAAY,EAAE,IAAU;QAC1D,4CAA4C;QAC5C,MAAM,KAAK,GAAkB;YAC3B,KAAK,EAAE,IAAI,CAAC,CAAC;YACb,MAAM,EAAE,IAAI,CAAC,CAAC;SACf,CAAA;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAChC,uCAAuC;QACvC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAC7B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Palette, Surface } from "../../render/surface.js";
|
|
2
|
+
import { View } from "../core/view.js";
|
|
3
|
+
import type { Rect, VAlign } from "../core/geometry.js";
|
|
4
|
+
export declare class HStack extends View {
|
|
5
|
+
readonly children: View[];
|
|
6
|
+
readonly spacing: number;
|
|
7
|
+
readonly align: VAlign;
|
|
8
|
+
constructor(children: View[], spacing?: number, align?: VAlign);
|
|
9
|
+
protected measureContent(maxW: number, maxH: number): import("../../layout/linearStack.js").Size;
|
|
10
|
+
protected renderContent(s: Surface, pal: Palette, rect: Rect): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=hstack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hstack.d.ts","sourceRoot":"","sources":["../../../src/ui/containers/hstack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAKvD,qBAAa,MAAO,SAAQ,IAAI;IAE5B,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE;IACzB,QAAQ,CAAC,OAAO;IAChB,QAAQ,CAAC,KAAK,EAAE,MAAM;gBAFb,QAAQ,EAAE,IAAI,EAAE,EAChB,OAAO,SAAI,EACX,KAAK,GAAE,MAAiB;IAKnC,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAQnD,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;CAQ7D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { View } from "../core/view.js";
|
|
2
|
+
import { measureLinear, layoutLinear } from "../../layout/linearStack.js";
|
|
3
|
+
import { Spacer } from "../primitives/spacer.js";
|
|
4
|
+
import { flexBaseForAxis } from "./shared.js";
|
|
5
|
+
export class HStack extends View {
|
|
6
|
+
children;
|
|
7
|
+
spacing;
|
|
8
|
+
align;
|
|
9
|
+
constructor(children, spacing = 1, align = "center") {
|
|
10
|
+
super();
|
|
11
|
+
this.children = children;
|
|
12
|
+
this.spacing = spacing;
|
|
13
|
+
this.align = align;
|
|
14
|
+
}
|
|
15
|
+
measureContent(maxW, maxH) {
|
|
16
|
+
const sizes = this.children.map((c) => c.measure(maxW, maxH));
|
|
17
|
+
const flexBase = this.children.map((c, i) => c instanceof Spacer ? c.minLength | 0 : flexBaseForAxis(c, "horizontal", sizes[i]));
|
|
18
|
+
return measureLinear("horizontal", maxW, maxH, this.spacing, sizes, flexBase);
|
|
19
|
+
}
|
|
20
|
+
renderContent(s, pal, rect) {
|
|
21
|
+
const sizes = this.children.map((c) => c.measure(rect.w, rect.h));
|
|
22
|
+
const flexBase = this.children.map((c, i) => c instanceof Spacer ? c.minLength | 0 : flexBaseForAxis(c, "horizontal", sizes[i]));
|
|
23
|
+
const rects = layoutLinear("horizontal", rect, this.spacing, this.align, sizes, flexBase);
|
|
24
|
+
for (let i = 0; i < this.children.length; i++)
|
|
25
|
+
this.children[i].render(s, pal, rects[i]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=hstack.js.map
|