@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
@@ -1,28 +1,87 @@
1
+ import { fade, isThemeColor } from '../colors';
2
+ import { clamp01, easeOutCubic } from '../easing';
3
+ /** Entrance animation length. */
4
+ const ENTRANCE_MS = 150;
5
+ /** A modal unseen for this long counts as closed; reopening replays the entrance. */
6
+ const REOPEN_MS = 250;
7
+ /** Colors the entrance can interpolate (not gradients/styler functions). */
8
+ function fadeable(color) {
9
+ if (isThemeColor(color))
10
+ return true;
11
+ if (typeof color === 'string' || typeof color === 'number')
12
+ return true;
13
+ return typeof color === 'object' && color !== null && 'r' in color;
14
+ }
15
+ /**
16
+ * Modal dialog: renders on its own layer with a dimmed backdrop and drop
17
+ * shadow, centered, with a 150ms fade/slide-in entrance. Surface and border
18
+ * derive from ctx.theme tokens; every visual default can be overridden or
19
+ * disabled via props.
20
+ */
1
21
  export function Modal(ctx, props, callback) {
2
- const parentW = ctx.width;
3
- const parentH = ctx.height;
4
- const modalW = props.width;
5
- const modalH = props.height;
6
- const localX = Math.max(0, Math.floor((parentW - modalW) / 2));
7
- const localY = Math.max(0, Math.floor((parentH - modalH) / 2));
8
- const x = ctx.offsetX + localX;
9
- const y = ctx.offsetY + localY;
10
- // 1. Draw solid background rect for the modal
11
- ctx.rect(x, y, modalW, modalH, {
12
- char: ' ',
13
- bg: props.bgColor || { r: 0, g: 0, b: 0 },
22
+ const theme = ctx.theme;
23
+ const backdrop = props.backdrop === false ? 0 : (props.backdrop ?? 0.55);
24
+ const shadow = props.shadow ?? true;
25
+ // Entrance progress, keyed per modal id in componentState. `lastSeen`
26
+ // tracks presence so a reopened modal (absent > REOPEN_MS) replays the
27
+ // entrance instead of reusing its stale open timestamp.
28
+ let progress = 1;
29
+ if (props.entrance !== false) {
30
+ const key = `__modal_entrance:${props.id ?? 'modal'}`;
31
+ const now = Date.now();
32
+ const record = ctx.state.componentState.get(key);
33
+ if (!record || now - record.lastSeen > REOPEN_MS) {
34
+ ctx.state.componentState.set(key, { openedAt: now, lastSeen: now });
35
+ progress = 0;
36
+ }
37
+ else {
38
+ record.lastSeen = now;
39
+ progress = clamp01((now - record.openedAt) / ENTRANCE_MS);
40
+ }
41
+ }
42
+ const eased = easeOutCubic(progress);
43
+ let rendered = '';
44
+ ctx.layer({
45
+ zIndex: props.zIndex ?? 100,
46
+ backdrop: backdrop > 0 ? backdrop : undefined,
47
+ shadow,
48
+ }, (overlay) => {
49
+ const modalW = props.width;
50
+ const modalH = props.height;
51
+ // Slide: enter from 1 row above the resting position.
52
+ const slide = Math.round(1 - eased);
53
+ const localX = Math.max(0, Math.floor((overlay.width - modalW) / 2));
54
+ const localY = Math.max(0, Math.floor((overlay.height - modalH) / 2) - slide);
55
+ const x = overlay.offsetX + localX;
56
+ const y = overlay.offsetY + localY;
57
+ // Fade: surface bg and border sweep from the screen background color
58
+ // to their final colors over the entrance.
59
+ const targetBg = props.bgColor ?? theme.surfaceRaised;
60
+ const surfaceBg = eased < 1 && fadeable(targetBg)
61
+ ? fade(theme.background.rgb, targetBg, eased)
62
+ : targetBg;
63
+ const targetBorder = props.borderColor ?? theme.border;
64
+ const borderColor = eased < 1 && fadeable(targetBorder)
65
+ ? fade(theme.background.rgb, targetBorder, eased)
66
+ : targetBorder;
67
+ // 1. Solid background rect: the raised-surface plate the dialog
68
+ // floats on (guarantees full coverage under sparse content).
69
+ overlay.rect(x, y, modalW, modalH, { char: ' ', bg: surfaceBg });
70
+ // 2. The box enclosing the modal content.
71
+ rendered = overlay.box({
72
+ x: localX,
73
+ y: localY,
74
+ width: modalW,
75
+ height: modalH,
76
+ border: props.border ?? 'double',
77
+ borderColor,
78
+ // Content fallback fg: explicit ANSI styling in content still wins.
79
+ color: theme.foreground,
80
+ align: props.align ?? 'center',
81
+ valign: props.valign,
82
+ padding: props.padding,
83
+ }, callback);
14
84
  });
15
- // 2. Draw the Box enclosing the modal content
16
- return ctx.box({
17
- x: localX,
18
- y: localY,
19
- width: modalW,
20
- height: modalH,
21
- border: props.border ?? 'double',
22
- borderColor: props.borderColor,
23
- align: props.align ?? 'center',
24
- valign: props.valign,
25
- padding: props.padding,
26
- }, callback);
85
+ return rendered;
27
86
  }
28
87
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../src/components/Modal.ts"],"names":[],"mappings":"AAsBA,MAAM,UAAU,KAAK,CACnB,GAAiB,EACjB,KAAiB,EACjB,QAAqC;IAErC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC;IAC1B,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAE5B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC;IAE/B,8CAA8C;IAC9C,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;QAC7B,IAAI,EAAE,GAAG;QACT,EAAE,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;KAC1C,CAAC,CAAC;IAEH,8CAA8C;IAC9C,OAAO,GAAG,CAAC,GAAG,CACZ;QACE,CAAC,EAAE,MAAM;QACT,CAAC,EAAE,MAAM;QACT,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,QAAQ;QAChC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,EACD,QAAQ,CACT,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../src/components/Modal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type ColorValue } from '../colors';
2
+ import type { BuntiContext } from '../dsl';
3
+ export interface ProgressProps {
4
+ /** Fill fraction 0..1 (clamped). */
5
+ value: number;
6
+ /** Bar width in cells (default 20). */
7
+ width?: number;
8
+ /** Multi-stop gradient fill: per-cell colors across the full bar. */
9
+ gradient?: ColorValue[];
10
+ /** Solid fill color (default theme.primary; ignored with gradient). */
11
+ fillColor?: ColorValue;
12
+ /** Track (unfilled) color (default theme.border). */
13
+ trackColor?: ColorValue;
14
+ /** Fill glyph (default '█'). */
15
+ filledChar?: string;
16
+ /** Track glyph (default '░'). */
17
+ trackChar?: string;
18
+ /** Appends a percent readout after the bar. */
19
+ showPercent?: boolean;
20
+ }
21
+ /**
22
+ * Themed progress bar: theme.primary fill over a theme.border track, with
23
+ * optional per-cell gradient fill. Appends to the current flow and returns
24
+ * the styled string.
25
+ */
26
+ export declare function Progress(ctx: BuntiContext, props: ProgressProps): string;
27
+ //# sourceMappingURL=Progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Progress.d.ts","sourceRoot":"","sources":["../../src/components/Progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkB,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAG3C,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,uEAAuE;IACvE,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,qDAAqD;IACrD,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAwCxE"}
@@ -0,0 +1,39 @@
1
+ import { createGradient } from '../colors';
2
+ import { clamp01 } from '../easing';
3
+ /**
4
+ * Themed progress bar: theme.primary fill over a theme.border track, with
5
+ * optional per-cell gradient fill. Appends to the current flow and returns
6
+ * the styled string.
7
+ */
8
+ export function Progress(ctx, props) {
9
+ const theme = ctx.theme;
10
+ const width = Math.max(1, Math.floor(props.width ?? 20));
11
+ const value = clamp01(props.value);
12
+ const filled = Math.round(width * value);
13
+ const filledChar = props.filledChar ?? '█';
14
+ const trackChar = props.trackChar ?? '░';
15
+ let bar = '';
16
+ if (filled > 0) {
17
+ if (props.gradient && props.gradient.length > 0) {
18
+ // Gradient spans the FULL bar so the fill's leading edge shows the
19
+ // stop for its position, not a compressed whole gradient.
20
+ const stops = createGradient(props.gradient, width);
21
+ for (let i = 0; i < filled; i++) {
22
+ bar += ctx.color.fg(stops[i], filledChar);
23
+ }
24
+ }
25
+ else {
26
+ bar = ctx.color.fg(props.fillColor ?? theme.primary, filledChar.repeat(filled));
27
+ }
28
+ }
29
+ const track = width - filled > 0
30
+ ? ctx.color.fg(props.trackColor ?? theme.border, trackChar.repeat(width - filled))
31
+ : '';
32
+ const percent = props.showPercent
33
+ ? ` ${String(Math.round(value * 100)).padStart(3)}%`
34
+ : '';
35
+ const out = bar + track + percent;
36
+ ctx.text(out);
37
+ return out;
38
+ }
39
+ //# sourceMappingURL=Progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Progress.js","sourceRoot":"","sources":["../../src/components/Progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAiB,EAAE,KAAoB;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC;IAEzC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,mEAAmE;YACnE,0DAA0D;YAC1D,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,UAAU,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAChB,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,EAChC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GACT,KAAK,GAAG,MAAM,GAAG,CAAC;QAChB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CACV,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,EAChC,SAAS,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,CACjC;QACH,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW;QAC/B,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG;QACpD,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO,CAAC;IAClC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { BuntiContext } from '../dsl';
3
+ /** Braille spinner animation frames, in playback order. */
4
+ export declare const SPINNER_FRAMES: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
5
+ export interface SpinnerProps {
6
+ /** Text rendered after the spinner glyph. */
7
+ label?: string;
8
+ /** Glyph color (default theme.accent). */
9
+ color?: ColorValue;
10
+ /** Milliseconds per animation frame (default 80). */
11
+ intervalMs?: number;
12
+ }
13
+ /**
14
+ * Animated braille spinner driven by ctx.elapsedTime — stateless, so it
15
+ * animates for free on any render loop. Appends to the current flow and
16
+ * returns the styled string.
17
+ */
18
+ export declare function Spinner(ctx: BuntiContext, props?: SpinnerProps): string;
19
+ //# sourceMappingURL=Spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../src/components/Spinner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,2DAA2D;AAC3D,eAAO,MAAM,cAAc,6DAWjB,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,GAAE,YAAiB,GAAG,MAAM,CAU3E"}
@@ -0,0 +1,27 @@
1
+ /** Braille spinner animation frames, in playback order. */
2
+ export const SPINNER_FRAMES = [
3
+ '⠋',
4
+ '⠙',
5
+ '⠹',
6
+ '⠸',
7
+ '⠼',
8
+ '⠴',
9
+ '⠦',
10
+ '⠧',
11
+ '⠇',
12
+ '⠏',
13
+ ];
14
+ /**
15
+ * Animated braille spinner driven by ctx.elapsedTime — stateless, so it
16
+ * animates for free on any render loop. Appends to the current flow and
17
+ * returns the styled string.
18
+ */
19
+ export function Spinner(ctx, props = {}) {
20
+ const interval = Math.max(1, props.intervalMs ?? 80);
21
+ const frame = SPINNER_FRAMES[Math.floor(ctx.elapsedTime / interval) % SPINNER_FRAMES.length];
22
+ const glyph = ctx.color.fg(props.color ?? ctx.theme.accent, frame);
23
+ const out = props.label ? `${glyph} ${props.label}` : glyph;
24
+ ctx.text(out);
25
+ return out;
26
+ }
27
+ //# sourceMappingURL=Spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../src/components/Spinner.ts"],"names":[],"mappings":"AAGA,2DAA2D;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;IACH,GAAG;CACK,CAAC;AAWX;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,GAAiB,EAAE,QAAsB,EAAE;IACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,KAAK,GACT,cAAc,CACZ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAC,GAAG,cAAc,CAAC,MAAM,CAC9D,CAAC;IACL,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5D,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -3,5 +3,8 @@ export * from './Button';
3
3
  export * from './Card';
4
4
  export * from './Header';
5
5
  export * from './Input';
6
+ export * from './Link';
6
7
  export * from './Modal';
8
+ export * from './Progress';
9
+ export * from './Spinner';
7
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
@@ -3,5 +3,8 @@ export * from './Button';
3
3
  export * from './Card';
4
4
  export * from './Header';
5
5
  export * from './Input';
6
+ export * from './Link';
6
7
  export * from './Modal';
8
+ export * from './Progress';
9
+ export * from './Spinner';
7
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * GENERATED FILE - do not edit by hand.
3
+ * Full Nerd Fonts name -> glyph map. Loaded only via the icons-full subpath.
4
+ * Source: Nerd Fonts v3.4.0 glyphnames.json
5
+ * Regenerate: bun scripts/gen-icons.ts
6
+ */
7
+ import type { IconName } from './nf-names';
8
+ export type { IconName } from './nf-names';
9
+ export declare const NF_GLYPHS: Record<IconName, string>;
10
+ export declare const NF_VERSION = "v3.4.0";
11
+ //# sourceMappingURL=nf-glyphs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nf-glyphs.d.ts","sourceRoot":"","sources":["../../src/data/nf-glyphs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAohB9C,CAAC;AAEF,eAAO,MAAM,UAAU,WAAW,CAAC"}