@zakmandhro/bunti 0.1.5 → 0.2.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.
Files changed (192) hide show
  1. package/AGENTS.md +65 -0
  2. package/README.md +81 -11
  3. package/dist/cli.d.ts +44 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +147 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/colors.d.ts +77 -7
  8. package/dist/colors.d.ts.map +1 -1
  9. package/dist/colors.js +238 -39
  10. package/dist/colors.js.map +1 -1
  11. package/dist/components/Box.d.ts +6 -0
  12. package/dist/components/Box.d.ts.map +1 -1
  13. package/dist/components/Box.js +5 -0
  14. package/dist/components/Box.js.map +1 -1
  15. package/dist/components/Button.d.ts +12 -2
  16. package/dist/components/Button.d.ts.map +1 -1
  17. package/dist/components/Button.js +35 -24
  18. package/dist/components/Button.js.map +1 -1
  19. package/dist/components/Card.d.ts +24 -2
  20. package/dist/components/Card.d.ts.map +1 -1
  21. package/dist/components/Card.js +56 -14
  22. package/dist/components/Card.js.map +1 -1
  23. package/dist/components/Header.d.ts +11 -1
  24. package/dist/components/Header.d.ts.map +1 -1
  25. package/dist/components/Header.js +12 -8
  26. package/dist/components/Header.js.map +1 -1
  27. package/dist/components/Input.d.ts +10 -1
  28. package/dist/components/Input.d.ts.map +1 -1
  29. package/dist/components/Input.js +172 -41
  30. package/dist/components/Input.js.map +1 -1
  31. package/dist/components/Link.d.ts +21 -0
  32. package/dist/components/Link.d.ts.map +1 -0
  33. package/dist/components/Link.js +29 -0
  34. package/dist/components/Link.js.map +1 -0
  35. package/dist/components/Modal.d.ts +25 -0
  36. package/dist/components/Modal.d.ts.map +1 -1
  37. package/dist/components/Modal.js +83 -24
  38. package/dist/components/Modal.js.map +1 -1
  39. package/dist/components/Progress.d.ts +27 -0
  40. package/dist/components/Progress.d.ts.map +1 -0
  41. package/dist/components/Progress.js +39 -0
  42. package/dist/components/Progress.js.map +1 -0
  43. package/dist/components/Spinner.d.ts +19 -0
  44. package/dist/components/Spinner.d.ts.map +1 -0
  45. package/dist/components/Spinner.js +27 -0
  46. package/dist/components/Spinner.js.map +1 -0
  47. package/dist/components/index.d.ts +3 -0
  48. package/dist/components/index.d.ts.map +1 -1
  49. package/dist/components/index.js +3 -0
  50. package/dist/components/index.js.map +1 -1
  51. package/dist/data/nf-glyphs.d.ts +11 -0
  52. package/dist/data/nf-glyphs.d.ts.map +1 -0
  53. package/dist/data/nf-glyphs.js +535 -0
  54. package/dist/data/nf-glyphs.js.map +1 -0
  55. package/dist/data/nf-names.d.ts +8 -0
  56. package/dist/data/nf-names.d.ts.map +1 -0
  57. package/dist/data/nf-names.js +2 -0
  58. package/dist/data/nf-names.js.map +1 -0
  59. package/dist/demo-registry.d.ts +27 -0
  60. package/dist/demo-registry.d.ts.map +1 -0
  61. package/dist/demo-registry.js +57 -0
  62. package/dist/demo-registry.js.map +1 -0
  63. package/dist/demos/2048.ts +743 -0
  64. package/dist/demos/animation.ts +246 -0
  65. package/dist/demos/demo-layout.ts +124 -0
  66. package/dist/demos/engine.ts +374 -0
  67. package/dist/demos/interaction.ts +91 -0
  68. package/dist/demos/login.ts +203 -0
  69. package/dist/demos/mission-control.ts +558 -0
  70. package/dist/demos/showcase.ts +224 -0
  71. package/dist/detect.d.ts +92 -3
  72. package/dist/detect.d.ts.map +1 -1
  73. package/dist/detect.js +218 -40
  74. package/dist/detect.js.map +1 -1
  75. package/dist/diagnostics.d.ts +73 -0
  76. package/dist/diagnostics.d.ts.map +1 -0
  77. package/dist/diagnostics.js +225 -0
  78. package/dist/diagnostics.js.map +1 -0
  79. package/dist/dsl/context.d.ts +11 -0
  80. package/dist/dsl/context.d.ts.map +1 -0
  81. package/dist/dsl/context.js +563 -0
  82. package/dist/dsl/context.js.map +1 -0
  83. package/dist/dsl/hooks.d.ts +12 -0
  84. package/dist/dsl/hooks.d.ts.map +1 -0
  85. package/dist/dsl/hooks.js +148 -0
  86. package/dist/dsl/hooks.js.map +1 -0
  87. package/dist/dsl/interaction.d.ts +16 -0
  88. package/dist/dsl/interaction.d.ts.map +1 -0
  89. package/dist/dsl/interaction.js +101 -0
  90. package/dist/dsl/interaction.js.map +1 -0
  91. package/dist/dsl/layers.d.ts +14 -0
  92. package/dist/dsl/layers.d.ts.map +1 -0
  93. package/dist/dsl/layers.js +87 -0
  94. package/dist/dsl/layers.js.map +1 -0
  95. package/dist/dsl/motion.d.ts +10 -0
  96. package/dist/dsl/motion.d.ts.map +1 -0
  97. package/dist/dsl/motion.js +150 -0
  98. package/dist/dsl/motion.js.map +1 -0
  99. package/dist/dsl/render.d.ts +22 -0
  100. package/dist/dsl/render.d.ts.map +1 -0
  101. package/dist/dsl/render.js +69 -0
  102. package/dist/dsl/render.js.map +1 -0
  103. package/dist/dsl/types.d.ts +510 -0
  104. package/dist/dsl/types.d.ts.map +1 -0
  105. package/dist/dsl/types.js +33 -0
  106. package/dist/dsl/types.js.map +1 -0
  107. package/dist/dsl.d.ts +13 -154
  108. package/dist/dsl.d.ts.map +1 -1
  109. package/dist/dsl.js +12 -658
  110. package/dist/dsl.js.map +1 -1
  111. package/dist/easing.d.ts +41 -1
  112. package/dist/easing.d.ts.map +1 -1
  113. package/dist/easing.js +105 -2
  114. package/dist/easing.js.map +1 -1
  115. package/dist/geometry.d.ts +39 -0
  116. package/dist/geometry.d.ts.map +1 -1
  117. package/dist/geometry.js +20 -0
  118. package/dist/geometry.js.map +1 -1
  119. package/dist/icons-full.d.ts +5 -0
  120. package/dist/icons-full.d.ts.map +1 -0
  121. package/dist/icons-full.js +31 -0
  122. package/dist/icons-full.js.map +1 -0
  123. package/dist/icons.d.ts +426 -5
  124. package/dist/icons.d.ts.map +1 -1
  125. package/dist/icons.js +144 -15
  126. package/dist/icons.js.map +1 -1
  127. package/dist/index.d.ts +93 -22
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +17 -7
  130. package/dist/index.js.map +1 -1
  131. package/dist/input.d.ts +177 -0
  132. package/dist/input.d.ts.map +1 -0
  133. package/dist/input.js +533 -0
  134. package/dist/input.js.map +1 -0
  135. package/dist/layout.d.ts +111 -6
  136. package/dist/layout.d.ts.map +1 -1
  137. package/dist/layout.js +163 -23
  138. package/dist/layout.js.map +1 -1
  139. package/dist/render.d.ts +33 -1
  140. package/dist/render.d.ts.map +1 -1
  141. package/dist/render.js +431 -116
  142. package/dist/render.js.map +1 -1
  143. package/dist/state.d.ts +137 -3
  144. package/dist/state.d.ts.map +1 -1
  145. package/dist/state.js +25 -0
  146. package/dist/state.js.map +1 -1
  147. package/dist/theme.d.ts +129 -0
  148. package/dist/theme.d.ts.map +1 -0
  149. package/dist/theme.js +167 -0
  150. package/dist/theme.js.map +1 -0
  151. package/dist/themes/catppuccin-mocha.d.ts +19 -0
  152. package/dist/themes/catppuccin-mocha.d.ts.map +1 -0
  153. package/dist/themes/catppuccin-mocha.js +36 -0
  154. package/dist/themes/catppuccin-mocha.js.map +1 -0
  155. package/dist/themes/dracula.d.ts +21 -0
  156. package/dist/themes/dracula.d.ts.map +1 -0
  157. package/dist/themes/dracula.js +37 -0
  158. package/dist/themes/dracula.js.map +1 -0
  159. package/dist/themes/github-light.d.ts +21 -0
  160. package/dist/themes/github-light.d.ts.map +1 -0
  161. package/dist/themes/github-light.js +36 -0
  162. package/dist/themes/github-light.js.map +1 -0
  163. package/dist/themes/index.d.ts +19 -0
  164. package/dist/themes/index.d.ts.map +1 -0
  165. package/dist/themes/index.js +17 -0
  166. package/dist/themes/index.js.map +1 -0
  167. package/dist/themes/nord.d.ts +23 -0
  168. package/dist/themes/nord.d.ts.map +1 -0
  169. package/dist/themes/nord.js +38 -0
  170. package/dist/themes/nord.js.map +1 -0
  171. package/dist/themes/one-dark-pro.d.ts +21 -0
  172. package/dist/themes/one-dark-pro.d.ts.map +1 -0
  173. package/dist/themes/one-dark-pro.js +36 -0
  174. package/dist/themes/one-dark-pro.js.map +1 -0
  175. package/dist/themes/tokyo-night.d.ts +20 -0
  176. package/dist/themes/tokyo-night.d.ts.map +1 -0
  177. package/dist/themes/tokyo-night.js +37 -0
  178. package/dist/themes/tokyo-night.js.map +1 -0
  179. package/dist/utils.d.ts +1 -0
  180. package/dist/utils.d.ts.map +1 -1
  181. package/dist/utils.js +1 -0
  182. package/dist/utils.js.map +1 -1
  183. package/dist/vendor/colors.d.ts +45 -0
  184. package/dist/vendor/colors.d.ts.map +1 -0
  185. package/dist/vendor/colors.js +72 -0
  186. package/dist/vendor/colors.js.map +1 -0
  187. package/llms.txt +79 -0
  188. package/package.json +23 -7
  189. package/dist/data/glyphs.d.ts +0 -5
  190. package/dist/data/glyphs.d.ts.map +0 -1
  191. package/dist/data/glyphs.js +0 -29
  192. package/dist/data/glyphs.js.map +0 -1
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Bunti DSL state hooks: useState, useAsync, usePersistentState.
3
+ *
4
+ * Implementations close over the ScreenState only, so they are shared
5
+ * unchanged by every context created for that screen.
6
+ */
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { recordKeylessHook } from '../diagnostics';
10
+ export function createHooks(state) {
11
+ const hooks = {
12
+ useAsync(keyOrFetcher, fetcherOrOptions, maybeOptions) {
13
+ let key;
14
+ let fetcher;
15
+ let options;
16
+ if (typeof keyOrFetcher === 'string') {
17
+ key = keyOrFetcher;
18
+ fetcher = fetcherOrOptions;
19
+ options = maybeOptions;
20
+ }
21
+ else {
22
+ if (state.hookCounter === undefined) {
23
+ state.hookCounter = 0;
24
+ }
25
+ const index = state.hookCounter++;
26
+ recordKeylessHook(state, index, 'useAsync');
27
+ key = `_async_hook_${index}`;
28
+ fetcher = keyOrFetcher;
29
+ options = fetcherOrOptions;
30
+ }
31
+ const interval = options?.interval ?? 0;
32
+ const dataKey = `${key}_data`;
33
+ const loadingKey = `${key}_loading`;
34
+ const errorKey = `${key}_error`;
35
+ const lastFetchKey = `${key}_lastFetch`;
36
+ const fetchingKey = `${key}_fetching`;
37
+ if (!state.componentState.has(loadingKey)) {
38
+ state.componentState.set(loadingKey, true);
39
+ }
40
+ const lastFetch = state.componentState.get(lastFetchKey);
41
+ const isFetching = state.componentState.get(fetchingKey);
42
+ const now = Date.now();
43
+ const shouldFetch = !isFetching &&
44
+ (lastFetch === undefined ||
45
+ (interval > 0 && now - lastFetch >= interval));
46
+ if (shouldFetch) {
47
+ state.componentState.set(fetchingKey, true);
48
+ state.componentState.set(lastFetchKey, now);
49
+ fetcher()
50
+ .then((result) => {
51
+ state.componentState.set(dataKey, result);
52
+ state.componentState.set(loadingKey, false);
53
+ state.componentState.set(errorKey, undefined);
54
+ state.requestTick?.();
55
+ })
56
+ .catch((err) => {
57
+ state.componentState.set(errorKey, err);
58
+ state.componentState.set(loadingKey, false);
59
+ state.requestTick?.();
60
+ })
61
+ .finally(() => {
62
+ state.componentState.set(fetchingKey, false);
63
+ });
64
+ }
65
+ return {
66
+ data: state.componentState.get(dataKey),
67
+ loading: state.componentState.get(loadingKey),
68
+ error: state.componentState.get(errorKey),
69
+ };
70
+ },
71
+ useState(keyOrInitial, maybeInitial) {
72
+ let key;
73
+ let initial;
74
+ if (maybeInitial === undefined) {
75
+ if (state.hookCounter === undefined) {
76
+ state.hookCounter = 0;
77
+ }
78
+ const index = state.hookCounter++;
79
+ recordKeylessHook(state, index, 'useState');
80
+ key = `_state_hook_${index}`;
81
+ initial = keyOrInitial;
82
+ }
83
+ else {
84
+ key = keyOrInitial;
85
+ initial = maybeInitial;
86
+ }
87
+ if (!state.componentState.has(key)) {
88
+ state.componentState.set(key, initial);
89
+ }
90
+ return [
91
+ state.componentState.get(key),
92
+ (val) => {
93
+ state.componentState.set(key, val);
94
+ state.requestTick?.();
95
+ },
96
+ ];
97
+ },
98
+ usePersistentState(key, initial) {
99
+ if (!state.componentState.has(key)) {
100
+ const storeDir = join(process.cwd(), '.tmp');
101
+ const storeFile = join(storeDir, 'bunti_store.json');
102
+ let fileVal;
103
+ try {
104
+ if (existsSync(storeFile)) {
105
+ const data = readFileSync(storeFile, 'utf-8');
106
+ const parsed = JSON.parse(data);
107
+ fileVal = parsed[key];
108
+ }
109
+ }
110
+ catch {
111
+ // Ignore
112
+ }
113
+ const finalVal = fileVal !== undefined ? fileVal : initial;
114
+ state.componentState.set(key, finalVal);
115
+ }
116
+ return [
117
+ state.componentState.get(key),
118
+ (val) => {
119
+ state.componentState.set(key, val);
120
+ const storeDir = join(process.cwd(), '.tmp');
121
+ const storeFile = join(storeDir, 'bunti_store.json');
122
+ try {
123
+ if (!existsSync(storeDir)) {
124
+ mkdirSync(storeDir, { recursive: true });
125
+ }
126
+ let currentStore = {};
127
+ if (existsSync(storeFile)) {
128
+ try {
129
+ currentStore = JSON.parse(readFileSync(storeFile, 'utf-8'));
130
+ }
131
+ catch {
132
+ currentStore = {};
133
+ }
134
+ }
135
+ currentStore[key] = val;
136
+ writeFileSync(storeFile, JSON.stringify(currentStore, null, 2), 'utf-8');
137
+ }
138
+ catch {
139
+ // Ignore
140
+ }
141
+ state.requestTick?.();
142
+ },
143
+ ];
144
+ },
145
+ };
146
+ return hooks;
147
+ }
148
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/dsl/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Bunti DSL interaction: hitboxes, hover/press/click queries, and focus
3
+ * management.
4
+ *
5
+ * Click semantics: a 'click' KeyEvent is emitted once, on SGR mouse RELEASE,
6
+ * carrying the press-origin coordinates (state.clickX/clickY). isClicked is
7
+ * therefore true exactly one frame per click — components fire actions once
8
+ * per click instead of every frame the button is held.
9
+ */
10
+ import type { Rect, RectInput } from '../geometry';
11
+ import type { ScreenState } from '../state';
12
+ import type { BuntiContext } from './types';
13
+ type Interaction = Pick<BuntiContext, 'focusable' | 'isFocused' | 'focus' | 'focusNext' | 'hitbox' | 'isHovered' | 'isPressed' | 'isClicked' | 'isHoverEnter' | 'isHoverLeave'>;
14
+ export declare function createInteraction(state: ScreenState, resolveRect: (bounds: RectInput) => Rect): Interaction;
15
+ export {};
16
+ //# sourceMappingURL=interaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../../src/dsl/interaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAU,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,KAAK,WAAW,GAAG,IAAI,CACrB,YAAY,EACV,WAAW,GACX,WAAW,GACX,OAAO,GACP,WAAW,GACX,QAAQ,GACR,WAAW,GACX,WAAW,GACX,WAAW,GACX,cAAc,GACd,cAAc,CACjB,CAAC;AA6BF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,WAAW,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GACvC,WAAW,CAkFb"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Bunti DSL interaction: hitboxes, hover/press/click queries, and focus
3
+ * management.
4
+ *
5
+ * Click semantics: a 'click' KeyEvent is emitted once, on SGR mouse RELEASE,
6
+ * carrying the press-origin coordinates (state.clickX/clickY). isClicked is
7
+ * therefore true exactly one frame per click — components fire actions once
8
+ * per click instead of every frame the button is held.
9
+ */
10
+ function contains(box, x, y) {
11
+ return (x >= box.x && x < box.x + box.width && y >= box.y && y < box.y + box.height);
12
+ }
13
+ /**
14
+ * True when this frame carries a click. `state.keys` covers events drained
15
+ * by the render loop; the `state.lastKey === 'click'` check keeps manually
16
+ * driven states (tests, custom loops) working.
17
+ */
18
+ function frameHasClick(state) {
19
+ if (state.lastKey === 'click')
20
+ return true;
21
+ return (state.keys?.some((e) => e.key === 'click' && e.kind !== 'release') ?? false);
22
+ }
23
+ /** Click test point: press-origin when available, mouse position otherwise. */
24
+ function clickX(state) {
25
+ return state.clickX ?? state.mouseX;
26
+ }
27
+ function clickY(state) {
28
+ return state.clickY ?? state.mouseY;
29
+ }
30
+ export function createInteraction(state, resolveRect) {
31
+ const interaction = {
32
+ focusable(id) {
33
+ if (!state.focusableIds.includes(id)) {
34
+ state.focusableIds.push(id);
35
+ }
36
+ if (!state.focusedId)
37
+ state.focusedId = id;
38
+ return state.focusedId === id;
39
+ },
40
+ isFocused(id) {
41
+ return state.focusedId === id;
42
+ },
43
+ focus(id) {
44
+ state.focusedId = id;
45
+ },
46
+ focusNext() {
47
+ if (state.focusableIds.length === 0)
48
+ return;
49
+ const idx = state.focusableIds.indexOf(state.focusedId || '');
50
+ const nextIdx = (idx + 1) % state.focusableIds.length;
51
+ state.focusedId = state.focusableIds[nextIdx];
52
+ },
53
+ hitbox(id, bounds) {
54
+ const rect = resolveRect(bounds);
55
+ const box = { id, ...rect };
56
+ state.hitboxes.set(id, box);
57
+ const hovered = contains(box, state.mouseX, state.mouseY);
58
+ // Hover-change tracking against the last evaluation of this id.
59
+ const prevHovered = state.hoverStates.get(id) ?? false;
60
+ if (hovered !== prevHovered) {
61
+ if (hovered) {
62
+ state.hoverEntered.add(id);
63
+ state.hoverLeft.delete(id);
64
+ }
65
+ else {
66
+ state.hoverLeft.add(id);
67
+ state.hoverEntered.delete(id);
68
+ }
69
+ state.hoverStates.set(id, hovered);
70
+ }
71
+ const pressed = hovered && state.isMouseDown && state.mouseButton === 0;
72
+ const clicked = frameHasClick(state) && contains(box, clickX(state), clickY(state));
73
+ return { box, hovered, pressed, clicked };
74
+ },
75
+ isHovered(id) {
76
+ const box = state.hitboxes.get(id);
77
+ if (!box)
78
+ return false;
79
+ return contains(box, state.mouseX, state.mouseY);
80
+ },
81
+ isPressed(id) {
82
+ return (interaction.isHovered(id) &&
83
+ state.isMouseDown &&
84
+ state.mouseButton === 0);
85
+ },
86
+ isClicked(id) {
87
+ const box = state.hitboxes.get(id);
88
+ if (!box)
89
+ return false;
90
+ return (frameHasClick(state) && contains(box, clickX(state), clickY(state)));
91
+ },
92
+ isHoverEnter(id) {
93
+ return state.hoverEntered.has(id);
94
+ },
95
+ isHoverLeave(id) {
96
+ return state.hoverLeft.has(id);
97
+ },
98
+ };
99
+ return interaction;
100
+ }
101
+ //# sourceMappingURL=interaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction.js","sourceRoot":"","sources":["../../src/dsl/interaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Bunti DSL layer machinery: transparent buffers, layer screen states,
3
+ * painted-bounds tracking, and back-buffer compositing.
4
+ */
5
+ import type { Rect } from '../geometry';
6
+ import type { Cell, ScreenState } from '../state';
7
+ export declare function createLayerScreenState(state: ScreenState): ScreenState;
8
+ /**
9
+ * Tight min/max bounds of a layer buffer's painted cells, or null when the
10
+ * layer painted nothing. Used at composite time to place drop shadows.
11
+ */
12
+ export declare function layerContentBounds(buffer: Cell[], width: number): Rect | null;
13
+ export declare function compositeLayer(state: ScreenState, buffer: Cell[]): void;
14
+ //# sourceMappingURL=layers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/dsl/layers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAkBlD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAOtE;AAWD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAoB7E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAqBhE"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Bunti DSL layer machinery: transparent buffers, layer screen states,
3
+ * painted-bounds tracking, and back-buffer compositing.
4
+ */
5
+ function createTransparentBuffer(size) {
6
+ return Array.from({ length: size }, () => ({
7
+ char: ' ',
8
+ fg: undefined,
9
+ bg: undefined,
10
+ fgCode: undefined,
11
+ bgCode: undefined,
12
+ bold: false,
13
+ italic: false,
14
+ underline: false,
15
+ dim: false,
16
+ strike: false,
17
+ skip: true,
18
+ }));
19
+ }
20
+ export function createLayerScreenState(state) {
21
+ const size = state.width * state.height;
22
+ return {
23
+ ...state,
24
+ frontBuffer: createTransparentBuffer(size),
25
+ backBuffer: createTransparentBuffer(size),
26
+ };
27
+ }
28
+ /**
29
+ * Whether a layer-buffer cell holds painted content. Transparent cells are
30
+ * skip cells with the pristine ' ' char; painted wide-glyph tails are skip
31
+ * cells too but carry the '' char, so they count as content.
32
+ */
33
+ function isPainted(cell) {
34
+ return !cell.skip || cell.char === '';
35
+ }
36
+ /**
37
+ * Tight min/max bounds of a layer buffer's painted cells, or null when the
38
+ * layer painted nothing. Used at composite time to place drop shadows.
39
+ */
40
+ export function layerContentBounds(buffer, width) {
41
+ let minX = Infinity;
42
+ let minY = Infinity;
43
+ let maxX = -1;
44
+ let maxY = -1;
45
+ const height = Math.floor(buffer.length / width);
46
+ for (let y = 0; y < height; y++) {
47
+ const rowOffset = y * width;
48
+ for (let x = 0; x < width; x++) {
49
+ if (!isPainted(buffer[rowOffset + x]))
50
+ continue;
51
+ if (x < minX)
52
+ minX = x;
53
+ if (x > maxX)
54
+ maxX = x;
55
+ if (y < minY)
56
+ minY = y;
57
+ if (y > maxY)
58
+ maxY = y;
59
+ }
60
+ }
61
+ if (maxX < 0)
62
+ return null;
63
+ return { x: minX, y: minY, width: maxX - minX + 1, height: maxY - minY + 1 };
64
+ }
65
+ export function compositeLayer(state, buffer) {
66
+ for (let i = 0; i < buffer.length; i++) {
67
+ const source = buffer[i];
68
+ // Transparent cells never composite; painted wide-glyph tails
69
+ // (skip + '' char) must, or stale chars peek through under the glyph.
70
+ if (!isPainted(source))
71
+ continue;
72
+ const target = state.backBuffer[i];
73
+ target.char = source.char;
74
+ target.fg = source.fg;
75
+ target.bg = source.bg;
76
+ target.bold = source.bold;
77
+ target.italic = source.italic;
78
+ target.underline = source.underline;
79
+ target.dim = source.dim;
80
+ target.strike = source.strike;
81
+ target.fgCode = source.fgCode;
82
+ target.bgCode = source.bgCode;
83
+ target.skip = source.skip;
84
+ target.raw = source.raw;
85
+ }
86
+ }
87
+ //# sourceMappingURL=layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.js","sourceRoot":"","sources":["../../src/dsl/layers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Bunti DSL motion helpers: animate, fade, typewriter, flicker, transition,
3
+ * stagger, restartAnimation, and per-frame timing (dt / frame).
4
+ */
5
+ import type { ScreenState } from '../state';
6
+ import type { BuntiContext } from './types';
7
+ type Motion = Pick<BuntiContext, 'animate' | 'fade' | 'typewriter' | 'flicker' | 'transition' | 'stagger' | 'restartAnimation' | 'dt' | 'frame'>;
8
+ export declare function createMotion(state: ScreenState, useState: BuntiContext['useState']): Motion;
9
+ export {};
10
+ //# sourceMappingURL=motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/dsl/motion.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,SAAS,CAAC;AA2B/D,KAAK,MAAM,GAAG,IAAI,CAChB,YAAY,EACV,SAAS,GACT,MAAM,GACN,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,SAAS,GACT,kBAAkB,GAClB,IAAI,GACJ,OAAO,CACV,CAAC;AAEF,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,GACjC,MAAM,CAoKR"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Bunti DSL motion helpers: animate, fade, typewriter, flicker, transition,
3
+ * stagger, restartAnimation, and per-frame timing (dt / frame).
4
+ */
5
+ import { fade } from '../colors';
6
+ import { clamp01 } from '../easing';
7
+ function graphemes(text) {
8
+ const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
9
+ return Array.from(segmenter.segment(text), ({ segment }) => segment);
10
+ }
11
+ /** Deterministic 0-1 hash (FNV-1a) for time-bucketed flicker. */
12
+ function hash01(seed) {
13
+ let h = 2166136261;
14
+ for (let i = 0; i < seed.length; i++) {
15
+ h ^= seed.charCodeAt(i);
16
+ h = Math.imul(h, 16777619);
17
+ }
18
+ return ((h >>> 0) % 100000) / 100000;
19
+ }
20
+ const identity = (t) => t;
21
+ /** Namespaced componentState key for transition edge tracking. */
22
+ const transitionKey = (id) => `_motion:transition:${id}`;
23
+ export function createMotion(state, useState) {
24
+ return {
25
+ // loop() owns timing: it stamps state.dt / state.frameCount each tick.
26
+ // Outside a loop (tests, one-shot renders) both default to 0.
27
+ dt: state.dt ?? 0,
28
+ frame: state.frameCount ?? 0,
29
+ animate(duration, options = {}) {
30
+ const now = Date.now();
31
+ const start = options.id
32
+ ? useState(`${options.id}_start`, now)[0]
33
+ : state.startTime;
34
+ const elapsed = now - start - (options.delay || 0);
35
+ const ease = options.easing ?? identity;
36
+ if (elapsed < 0 || duration <= 0)
37
+ return ease(0);
38
+ if (options.loop === 'yoyo') {
39
+ // 0 -> 1 -> 0 over two durations; easing applies to each leg.
40
+ const phase = (elapsed % (duration * 2)) / duration;
41
+ return ease(phase <= 1 ? phase : 2 - phase);
42
+ }
43
+ if (options.loop)
44
+ return ease((elapsed % duration) / duration);
45
+ return ease(Math.min(1, elapsed / duration));
46
+ },
47
+ fade,
48
+ /**
49
+ * Visibility-driven enter/exit progress for immediate-mode UIs.
50
+ * Tracks visible-flag edges in componentState; `mounted` stays true
51
+ * through the exit animation so callers keep rendering while a panel
52
+ * animates out. Mid-animation flips retarget from the current progress
53
+ * (no jumps).
54
+ */
55
+ transition(id, visible, options = {}) {
56
+ const now = Date.now();
57
+ const duration = Math.max(0, options.duration ?? 300);
58
+ const exitDuration = Math.max(0, options.exitDuration ?? duration);
59
+ const ease = options.easing ?? identity;
60
+ const key = transitionKey(id);
61
+ let rec = state.componentState.get(key);
62
+ if (rec === undefined) {
63
+ // First sight: visible components animate in from 0; hidden ones
64
+ // start fully exited (mounted false immediately).
65
+ rec = { visible, flippedAt: visible ? now : now - exitDuration - 1 };
66
+ state.componentState.set(key, rec);
67
+ }
68
+ const rawAt = (r) => {
69
+ if (r.visible) {
70
+ return duration <= 0 ? 1 : clamp01((now - r.flippedAt) / duration);
71
+ }
72
+ return exitDuration <= 0
73
+ ? 0
74
+ : 1 - clamp01((now - r.flippedAt) / exitDuration);
75
+ };
76
+ if (rec.visible !== visible) {
77
+ // Retarget from the current raw progress so mid-animation flips
78
+ // continue smoothly instead of restarting the full leg.
79
+ const current = rawAt(rec);
80
+ rec.visible = visible;
81
+ rec.flippedAt = visible
82
+ ? now - current * duration
83
+ : now - (1 - current) * exitDuration;
84
+ }
85
+ const raw = rawAt(rec);
86
+ return {
87
+ progress: ease(raw),
88
+ mounted: visible || raw > 0,
89
+ };
90
+ },
91
+ /**
92
+ * Cascading entrance progress: item `index` starts `index * delay` ms
93
+ * into the timeline and runs for `duration` ms. The timeline is the
94
+ * screen's elapsed time, or an animate()-style `id` clock when given
95
+ * (restartAnimation(id) then replays the cascade).
96
+ */
97
+ stagger(index, options) {
98
+ const now = Date.now();
99
+ const start = options.id
100
+ ? useState(`${options.id}_start`, now)[0]
101
+ : state.startTime;
102
+ const elapsed = now - start - index * options.delay;
103
+ const ease = options.easing ?? identity;
104
+ if (options.duration <= 0)
105
+ return ease(elapsed >= 0 ? 1 : 0);
106
+ return ease(clamp01(elapsed / options.duration));
107
+ },
108
+ /** Resets an animate()/typewriter()/stagger() id clock to "now". */
109
+ restartAnimation(id) {
110
+ state.componentState.set(`${id}_start`, Date.now());
111
+ state.requestTick?.();
112
+ },
113
+ typewriter(text, options = {}) {
114
+ const now = Date.now();
115
+ const start = options.id
116
+ ? useState(`${options.id}_start`, now)[0]
117
+ : state.startTime;
118
+ const delay = options.delay ?? 0;
119
+ const elapsed = Math.max(0, now - start - delay);
120
+ const cps = options.cps ?? 24;
121
+ const chars = graphemes(text);
122
+ const rawIndex = Math.floor((elapsed / 1000) * cps);
123
+ const index = options.loop && chars.length > 0
124
+ ? rawIndex % (chars.length + 1)
125
+ : Math.min(chars.length, rawIndex);
126
+ const blinkRate = options.blinkRate ?? 450;
127
+ const showCursor = options.blink === false ||
128
+ Math.floor(elapsed / blinkRate) % 2 === 0 ||
129
+ index < chars.length;
130
+ return {
131
+ text: chars.slice(0, index).join(''),
132
+ cursor: showCursor ? (options.cursor ?? '█') : ' ',
133
+ done: index >= chars.length,
134
+ index,
135
+ progress: chars.length === 0 ? 1 : index / chars.length,
136
+ };
137
+ },
138
+ /**
139
+ * Time-based flicker: deterministic per interval bucket (hash of the
140
+ * bucket + id), so the flicker rate is fps-independent while keeping
141
+ * the same visual character as the old per-frame Math.random.
142
+ */
143
+ flicker(intensity = 0.5, options = {}) {
144
+ const interval = Math.max(1, options.interval ?? 50);
145
+ const bucket = Math.floor((Date.now() - state.startTime) / interval);
146
+ return hash01(`${options.id ?? ''}:${bucket}`) > 1 - intensity;
147
+ },
148
+ };
149
+ }
150
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/dsl/motion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Bunti DSL primary entry point: render.
3
+ */
4
+ import { type ScreenOptions } from '../state';
5
+ import type { BuntiContext } from './types';
6
+ /**
7
+ * Starts a Bunti app: runs `callback` every frame (immediate mode —
8
+ * redraw the whole screen from state each call) and flushes only the
9
+ * changed cells to the terminal. The returned promise resolves when the
10
+ * loop stops (ctx.requestStop() or Ctrl+C). Pass `once: true` to render
11
+ * a single frame and return. Keyboard input needs a real TTY on stdin:
12
+ * piped input is ignored.
13
+ * @example
14
+ * await render((ctx) => {
15
+ * ctx.box({ width: 30, border: 'rounded' }, (s) => s.text('hi'));
16
+ * if (ctx.lastKey === 'q') ctx.requestStop();
17
+ * }, { keyboard: true, mouse: true, alternateBuffer: true, hideCursor: true });
18
+ */
19
+ export declare function render(callback: ((b: BuntiContext) => void) | string, options?: ScreenOptions & {
20
+ once?: boolean;
21
+ }): Promise<void>;
22
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/dsl/render.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,wBAAsB,MAAM,CAC1B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,MAAM,EAC9C,OAAO,GAAE,aAAa,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,iBAkDjD"}