@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.
Files changed (241) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/anim.d.ts +4 -0
  4. package/dist/anim.d.ts.map +1 -0
  5. package/dist/anim.js +5 -0
  6. package/dist/anim.js.map +1 -0
  7. package/dist/ansi.d.ts +69 -0
  8. package/dist/ansi.d.ts.map +1 -0
  9. package/dist/ansi.js +72 -0
  10. package/dist/ansi.js.map +1 -0
  11. package/dist/index.d.ts +16 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +16 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/keys.d.ts +18 -0
  16. package/dist/keys.d.ts.map +1 -0
  17. package/dist/keys.js +247 -0
  18. package/dist/keys.js.map +1 -0
  19. package/dist/layout/linearStack.d.ts +17 -0
  20. package/dist/layout/linearStack.d.ts.map +1 -0
  21. package/dist/layout/linearStack.js +86 -0
  22. package/dist/layout/linearStack.js.map +1 -0
  23. package/dist/motion-value.d.ts +58 -0
  24. package/dist/motion-value.d.ts.map +1 -0
  25. package/dist/motion-value.js +250 -0
  26. package/dist/motion-value.js.map +1 -0
  27. package/dist/present/display.d.ts +58 -0
  28. package/dist/present/display.d.ts.map +1 -0
  29. package/dist/present/display.js +168 -0
  30. package/dist/present/display.js.map +1 -0
  31. package/dist/present/writers/fullscreen.d.ts +19 -0
  32. package/dist/present/writers/fullscreen.d.ts.map +1 -0
  33. package/dist/present/writers/fullscreen.js +55 -0
  34. package/dist/present/writers/fullscreen.js.map +1 -0
  35. package/dist/present/writers/inline.d.ts +20 -0
  36. package/dist/present/writers/inline.d.ts.map +1 -0
  37. package/dist/present/writers/inline.js +92 -0
  38. package/dist/present/writers/inline.js.map +1 -0
  39. package/dist/render/buffer.d.ts +31 -0
  40. package/dist/render/buffer.d.ts.map +1 -0
  41. package/dist/render/buffer.js +183 -0
  42. package/dist/render/buffer.js.map +1 -0
  43. package/dist/render/color-utils.d.ts +18 -0
  44. package/dist/render/color-utils.d.ts.map +1 -0
  45. package/dist/render/color-utils.js +58 -0
  46. package/dist/render/color-utils.js.map +1 -0
  47. package/dist/render/diff.d.ts +30 -0
  48. package/dist/render/diff.d.ts.map +1 -0
  49. package/dist/render/diff.js +83 -0
  50. package/dist/render/diff.js.map +1 -0
  51. package/dist/render/measure.d.ts +15 -0
  52. package/dist/render/measure.d.ts.map +1 -0
  53. package/dist/render/measure.js +65 -0
  54. package/dist/render/measure.js.map +1 -0
  55. package/dist/render/palette.d.ts +46 -0
  56. package/dist/render/palette.d.ts.map +1 -0
  57. package/dist/render/palette.js +108 -0
  58. package/dist/render/palette.js.map +1 -0
  59. package/dist/render/surface.d.ts +77 -0
  60. package/dist/render/surface.d.ts.map +1 -0
  61. package/dist/render/surface.js +198 -0
  62. package/dist/render/surface.js.map +1 -0
  63. package/dist/runtime/backend_node.d.ts +36 -0
  64. package/dist/runtime/backend_node.d.ts.map +1 -0
  65. package/dist/runtime/backend_node.js +66 -0
  66. package/dist/runtime/backend_node.js.map +1 -0
  67. package/dist/spring-physics.d.ts +36 -0
  68. package/dist/spring-physics.d.ts.map +1 -0
  69. package/dist/spring-physics.js +113 -0
  70. package/dist/spring-physics.js.map +1 -0
  71. package/dist/spring.d.ts +73 -0
  72. package/dist/spring.d.ts.map +1 -0
  73. package/dist/spring.js +136 -0
  74. package/dist/spring.js.map +1 -0
  75. package/dist/ui/containers/canvas.d.ts +13 -0
  76. package/dist/ui/containers/canvas.d.ts.map +1 -0
  77. package/dist/ui/containers/canvas.js +16 -0
  78. package/dist/ui/containers/canvas.js.map +1 -0
  79. package/dist/ui/containers/geometry-reader.d.ts +17 -0
  80. package/dist/ui/containers/geometry-reader.d.ts.map +1 -0
  81. package/dist/ui/containers/geometry-reader.js +24 -0
  82. package/dist/ui/containers/geometry-reader.js.map +1 -0
  83. package/dist/ui/containers/hstack.d.ts +12 -0
  84. package/dist/ui/containers/hstack.d.ts.map +1 -0
  85. package/dist/ui/containers/hstack.js +28 -0
  86. package/dist/ui/containers/hstack.js.map +1 -0
  87. package/dist/ui/containers/scroll.d.ts +28 -0
  88. package/dist/ui/containers/scroll.d.ts.map +1 -0
  89. package/dist/ui/containers/scroll.js +97 -0
  90. package/dist/ui/containers/scroll.js.map +1 -0
  91. package/dist/ui/containers/shared.d.ts +12 -0
  92. package/dist/ui/containers/shared.d.ts.map +1 -0
  93. package/dist/ui/containers/shared.js +19 -0
  94. package/dist/ui/containers/shared.js.map +1 -0
  95. package/dist/ui/containers/vstack.d.ts +12 -0
  96. package/dist/ui/containers/vstack.d.ts.map +1 -0
  97. package/dist/ui/containers/vstack.js +28 -0
  98. package/dist/ui/containers/vstack.js.map +1 -0
  99. package/dist/ui/containers/zstack.d.ts +14 -0
  100. package/dist/ui/containers/zstack.d.ts.map +1 -0
  101. package/dist/ui/containers/zstack.js +36 -0
  102. package/dist/ui/containers/zstack.js.map +1 -0
  103. package/dist/ui/core/geometry-store.d.ts +22 -0
  104. package/dist/ui/core/geometry-store.d.ts.map +1 -0
  105. package/dist/ui/core/geometry-store.js +29 -0
  106. package/dist/ui/core/geometry-store.js.map +1 -0
  107. package/dist/ui/core/geometry.d.ts +34 -0
  108. package/dist/ui/core/geometry.d.ts.map +1 -0
  109. package/dist/ui/core/geometry.js +14 -0
  110. package/dist/ui/core/geometry.js.map +1 -0
  111. package/dist/ui/core/view.d.ts +25 -0
  112. package/dist/ui/core/view.d.ts.map +1 -0
  113. package/dist/ui/core/view.js +34 -0
  114. package/dist/ui/core/view.js.map +1 -0
  115. package/dist/ui/index.d.ts +44 -0
  116. package/dist/ui/index.d.ts.map +1 -0
  117. package/dist/ui/index.js +39 -0
  118. package/dist/ui/index.js.map +1 -0
  119. package/dist/ui/inlinetext.d.ts +24 -0
  120. package/dist/ui/inlinetext.d.ts.map +1 -0
  121. package/dist/ui/inlinetext.js +131 -0
  122. package/dist/ui/inlinetext.js.map +1 -0
  123. package/dist/ui/install.d.ts +22 -0
  124. package/dist/ui/install.d.ts.map +1 -0
  125. package/dist/ui/install.js +66 -0
  126. package/dist/ui/install.js.map +1 -0
  127. package/dist/ui/markdown.d.ts +40 -0
  128. package/dist/ui/markdown.d.ts.map +1 -0
  129. package/dist/ui/markdown.js +351 -0
  130. package/dist/ui/markdown.js.map +1 -0
  131. package/dist/ui/modifiers/border.d.ts +33 -0
  132. package/dist/ui/modifiers/border.d.ts.map +1 -0
  133. package/dist/ui/modifiers/border.js +82 -0
  134. package/dist/ui/modifiers/border.js.map +1 -0
  135. package/dist/ui/modifiers/fill.d.ts +14 -0
  136. package/dist/ui/modifiers/fill.d.ts.map +1 -0
  137. package/dist/ui/modifiers/fill.js +25 -0
  138. package/dist/ui/modifiers/fill.js.map +1 -0
  139. package/dist/ui/modifiers/frame.d.ts +23 -0
  140. package/dist/ui/modifiers/frame.d.ts.map +1 -0
  141. package/dist/ui/modifiers/frame.js +54 -0
  142. package/dist/ui/modifiers/frame.js.map +1 -0
  143. package/dist/ui/modifiers/offset.d.ts +15 -0
  144. package/dist/ui/modifiers/offset.d.ts.map +1 -0
  145. package/dist/ui/modifiers/offset.js +21 -0
  146. package/dist/ui/modifiers/offset.js.map +1 -0
  147. package/dist/ui/modifiers/opacity.d.ts +15 -0
  148. package/dist/ui/modifiers/opacity.d.ts.map +1 -0
  149. package/dist/ui/modifiers/opacity.js +95 -0
  150. package/dist/ui/modifiers/opacity.js.map +1 -0
  151. package/dist/ui/modifiers/padding.d.ts +20 -0
  152. package/dist/ui/modifiers/padding.d.ts.map +1 -0
  153. package/dist/ui/modifiers/padding.js +36 -0
  154. package/dist/ui/modifiers/padding.js.map +1 -0
  155. package/dist/ui/modifiers/styled.d.ts +14 -0
  156. package/dist/ui/modifiers/styled.d.ts.map +1 -0
  157. package/dist/ui/modifiers/styled.js +26 -0
  158. package/dist/ui/modifiers/styled.js.map +1 -0
  159. package/dist/ui/primitives/rectangle.d.ts +15 -0
  160. package/dist/ui/primitives/rectangle.d.ts.map +1 -0
  161. package/dist/ui/primitives/rectangle.js +23 -0
  162. package/dist/ui/primitives/rectangle.js.map +1 -0
  163. package/dist/ui/primitives/spacer.d.ts +13 -0
  164. package/dist/ui/primitives/spacer.d.ts.map +1 -0
  165. package/dist/ui/primitives/spacer.js +16 -0
  166. package/dist/ui/primitives/spacer.js.map +1 -0
  167. package/dist/ui/primitives/text.d.ts +15 -0
  168. package/dist/ui/primitives/text.d.ts.map +1 -0
  169. package/dist/ui/primitives/text.js +79 -0
  170. package/dist/ui/primitives/text.js.map +1 -0
  171. package/dist/ui/primitives/wrapped-text.d.ts +30 -0
  172. package/dist/ui/primitives/wrapped-text.d.ts.map +1 -0
  173. package/dist/ui/primitives/wrapped-text.js +117 -0
  174. package/dist/ui/primitives/wrapped-text.js.map +1 -0
  175. package/dist/ui/shinytext.d.ts +66 -0
  176. package/dist/ui/shinytext.d.ts.map +1 -0
  177. package/dist/ui/shinytext.js +99 -0
  178. package/dist/ui/shinytext.js.map +1 -0
  179. package/dist/ui/text/layout.d.ts +35 -0
  180. package/dist/ui/text/layout.d.ts.map +1 -0
  181. package/dist/ui/text/layout.js +102 -0
  182. package/dist/ui/text/layout.js.map +1 -0
  183. package/dist/ui/textinput.d.ts +140 -0
  184. package/dist/ui/textinput.d.ts.map +1 -0
  185. package/dist/ui/textinput.js +402 -0
  186. package/dist/ui/textinput.js.map +1 -0
  187. package/dist/ui/view-constructors.d.ts +72 -0
  188. package/dist/ui/view-constructors.d.ts.map +1 -0
  189. package/dist/ui/view-constructors.js +74 -0
  190. package/dist/ui/view-constructors.js.map +1 -0
  191. package/package.json +57 -0
  192. package/src/anim.ts +5 -0
  193. package/src/ansi.ts +83 -0
  194. package/src/index.ts +21 -0
  195. package/src/keys.ts +302 -0
  196. package/src/layout/linearStack.ts +115 -0
  197. package/src/motion-value.ts +335 -0
  198. package/src/present/display.ts +206 -0
  199. package/src/present/writers/fullscreen.ts +58 -0
  200. package/src/present/writers/inline.ts +101 -0
  201. package/src/render/buffer.ts +200 -0
  202. package/src/render/color-utils.ts +60 -0
  203. package/src/render/diff.ts +95 -0
  204. package/src/render/measure.ts +74 -0
  205. package/src/render/palette.ts +113 -0
  206. package/src/render/surface.ts +238 -0
  207. package/src/runtime/backend_node.ts +80 -0
  208. package/src/spring-physics.ts +151 -0
  209. package/src/spring.ts +234 -0
  210. package/src/ui/__snapshots__/wrappedtext.test.ts.snap +57 -0
  211. package/src/ui/containers/canvas.ts +18 -0
  212. package/src/ui/containers/geometry-reader.ts +32 -0
  213. package/src/ui/containers/hstack.ts +33 -0
  214. package/src/ui/containers/scroll.ts +106 -0
  215. package/src/ui/containers/shared.ts +27 -0
  216. package/src/ui/containers/vstack.ts +34 -0
  217. package/src/ui/containers/zstack.ts +37 -0
  218. package/src/ui/core/geometry-store.ts +42 -0
  219. package/src/ui/core/geometry.ts +30 -0
  220. package/src/ui/core/view.ts +49 -0
  221. package/src/ui/index.ts +84 -0
  222. package/src/ui/inlinetext.ts +135 -0
  223. package/src/ui/install.ts +110 -0
  224. package/src/ui/markdown.test.ts +74 -0
  225. package/src/ui/markdown.ts +388 -0
  226. package/src/ui/modifiers/border.ts +100 -0
  227. package/src/ui/modifiers/fill.ts +28 -0
  228. package/src/ui/modifiers/frame.ts +74 -0
  229. package/src/ui/modifiers/offset.ts +23 -0
  230. package/src/ui/modifiers/opacity.ts +93 -0
  231. package/src/ui/modifiers/padding.ts +53 -0
  232. package/src/ui/modifiers/styled.ts +31 -0
  233. package/src/ui/primitives/rectangle.ts +25 -0
  234. package/src/ui/primitives/spacer.ts +18 -0
  235. package/src/ui/primitives/text.ts +85 -0
  236. package/src/ui/primitives/wrapped-text.ts +131 -0
  237. package/src/ui/shinytext.ts +159 -0
  238. package/src/ui/text/layout.ts +119 -0
  239. package/src/ui/textinput.ts +496 -0
  240. package/src/ui/view-constructors.ts +96 -0
  241. 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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"}
@@ -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":"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"}
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