@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,22 +1,49 @@
1
+ import { adjustBrightness } from '../colors';
2
+ import { visibleWidth } from '../utils';
1
3
  import { Box } from './Box';
2
4
  /**
3
5
  * Tactical Card Component
4
- * A structural container with an integrated header.
6
+ * A structural container with an integrated header. Colors derive from
7
+ * ctx.theme tokens:
8
+ * - default: border `theme.border`, title `theme.muted`
9
+ * - accent: border `theme.border`, title `theme.accent`
10
+ * - danger: border `theme.danger`, title `theme.danger`
11
+ *
12
+ * With an `id`, hovering lifts the border to `theme.focus` and shifts the
13
+ * background one step. Hover styling reads the hitbox registered on the
14
+ * previous frame (immediate-mode: geometry is only exact after a render),
15
+ * which is invisible at interactive frame rates.
5
16
  */
6
17
  export function Card(ctx, props, callback) {
7
- const { color } = ctx;
8
- const neutralGray = { r: 217, g: 216, b: 213 };
9
- let borderColor = neutralGray;
10
- let titleColor = neutralGray;
11
- if (props.theme === 'accent') {
12
- titleColor = 'black';
13
- // Border remains neutral gray
18
+ const { color, theme } = ctx;
19
+ const variant = props.variant ?? props.theme ?? 'default';
20
+ let borderColor = theme.border;
21
+ let titleColor = theme.muted;
22
+ if (variant === 'accent') {
23
+ titleColor = theme.accent;
14
24
  }
15
- else if (props.theme === 'danger') {
16
- borderColor = 'error';
17
- titleColor = 'error';
25
+ else if (variant === 'danger') {
26
+ borderColor = theme.danger;
27
+ titleColor = theme.danger;
18
28
  }
19
- return Box(ctx, {
29
+ // Hover affordance (previous-frame hover state; see docblock).
30
+ const hoverable = props.id !== undefined;
31
+ const hovered = hoverable
32
+ ? (ctx.state.hoverStates.get(props.id) ?? false)
33
+ : false;
34
+ let bgColor = props.bgColor;
35
+ let finalBorder = props.borderColor || borderColor;
36
+ if (hovered) {
37
+ finalBorder = theme.focus;
38
+ const shift = theme.mode === 'dark' ? 12 : -12;
39
+ bgColor =
40
+ bgColor !== undefined &&
41
+ !(typeof bgColor === 'object' && 'colors' in bgColor)
42
+ ? adjustBrightness(bgColor, shift)
43
+ : (bgColor ?? theme.surface);
44
+ }
45
+ const startY = ctx.cursorY;
46
+ const rendered = Box(ctx, {
20
47
  x: props.x,
21
48
  y: props.y,
22
49
  anchor: props.anchor,
@@ -24,14 +51,29 @@ export function Card(ctx, props, callback) {
24
51
  height: props.height,
25
52
  minHeight: props.minHeight,
26
53
  border: props.border || 'frame',
27
- borderColor: props.borderColor || borderColor,
54
+ borderColor: finalBorder,
28
55
  padding: props.padding || [1, 2],
29
- bgColor: props.bgColor,
56
+ bgColor,
30
57
  }, (sub) => {
31
58
  if (props.title) {
32
59
  sub.text(color.fg(titleColor, color.bold(`${props.title.toUpperCase()}\n\n`)));
33
60
  }
34
61
  callback(sub);
35
62
  });
63
+ if (hoverable) {
64
+ const lines = rendered.split('\n');
65
+ const h = lines.length;
66
+ const w = Math.max(0, ...lines.map(visibleWidth));
67
+ // Mirror resolveBoxArea's placement defaults (centered when unplaced).
68
+ const area = ctx.resolveLocalRect({
69
+ x: props.x,
70
+ y: props.y ?? (startY || undefined),
71
+ width: w,
72
+ height: h,
73
+ anchor: props.anchor,
74
+ });
75
+ ctx.hitbox(props.id, area);
76
+ }
77
+ return rendered;
36
78
  }
37
79
  //# sourceMappingURL=Card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/components/Card.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAO5B;;;GAGG;AACH,MAAM,UAAU,IAAI,CAClB,GAAiB,EACjB,KAAgB,EAChB,QAAqC;IAErC,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAEtB,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;IAC/C,IAAI,WAAW,GAAQ,WAAW,CAAC;IACnC,IAAI,UAAU,GAAQ,WAAW,CAAC;IAElC,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC7B,UAAU,GAAG,OAAO,CAAC;QACrB,8BAA8B;IAChC,CAAC;SAAM,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACpC,WAAW,GAAG,OAAO,CAAC;QACtB,UAAU,GAAG,OAAO,CAAC;IACvB,CAAC;IAED,OAAO,GAAG,CACR,GAAG,EACH;QACE,CAAC,EAAE,KAAK,CAAC,CAAC;QACV,CAAC,EAAE,KAAK,CAAC,CAAC;QACV,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,MAAM;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,OAAO;QAC/B,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,WAAW;QAC7C,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAChC,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,EACD,CAAC,GAAG,EAAE,EAAE;QACN,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,GAAG,CAAC,IAAI,CACN,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CACrE,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/components/Card.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,23 @@
1
1
  import type { BuntiContext } from '../dsl';
2
+ /** Props for Header. */
2
3
  export interface HeaderProps {
4
+ /** Centered bar title. */
3
5
  title: string;
6
+ /** Brand glyph on the left edge (use ctx.icon(name)). */
4
7
  leftIcon?: string;
8
+ /** Muted telemetry/exit label on the right edge. */
5
9
  rightLabel?: string;
10
+ /**
11
+ * @deprecated Colors now derive from `ctx.theme` tokens; wrap the Header
12
+ * in `ctx.themed(...)` to restyle it. This prop is ignored.
13
+ */
6
14
  theme?: 'light' | 'dark';
7
15
  }
8
16
  /**
9
17
  * Enterprise Tactical Header
10
- * A full-width, high-signal branding bar.
18
+ * A full-width, high-signal branding bar. Colors derive from ctx.theme:
19
+ * bar `theme.surfaceRaised`, title `theme.foreground`, brand icon
20
+ * `theme.accent`, right label `theme.muted`.
11
21
  */
12
22
  export declare function Header(ctx: BuntiContext, props: HeaderProps): void;
13
23
  //# sourceMappingURL=Header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/components/Header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAI3C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,QAwD3D"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/components/Header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAI3C,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,QA0D3D"}
@@ -2,14 +2,14 @@ import { box as engineBox } from '../layout';
2
2
  import { Box } from './Box';
3
3
  /**
4
4
  * Enterprise Tactical Header
5
- * A full-width, high-signal branding bar.
5
+ * A full-width, high-signal branding bar. Colors derive from ctx.theme:
6
+ * bar `theme.surfaceRaised`, title `theme.foreground`, brand icon
7
+ * `theme.accent`, right label `theme.muted`.
6
8
  */
7
9
  export function Header(ctx, props) {
8
- const { color, joinHorizontal } = ctx;
9
- // Resolve Theme Colors
10
- const isLight = props.theme !== 'dark';
11
- const bg = isLight ? 'white' : 'midnight';
12
- const fg = isLight ? 236 : 'silver';
10
+ const { color, joinHorizontal, theme } = ctx;
11
+ const bg = theme.surfaceRaised;
12
+ const fg = theme.foreground;
13
13
  // Master Background Box
14
14
  Box(ctx, {
15
15
  anchor: 'top',
@@ -24,7 +24,9 @@ export function Header(ctx, props) {
24
24
  constraints: [12, '1fr', 12],
25
25
  });
26
26
  // 1. Left: Branding
27
- const leftStr = props.leftIcon ? color.fg('plasma', props.leftIcon) : '';
27
+ const leftStr = props.leftIcon
28
+ ? color.fg(theme.accent, props.leftIcon)
29
+ : '';
28
30
  const leftNode = engineBox(leftStr, {
29
31
  width: leftArea?.width ?? 0,
30
32
  align: 'left',
@@ -40,7 +42,9 @@ export function Header(ctx, props) {
40
42
  padding: [0, 0],
41
43
  });
42
44
  // 3. Right: Telemetry / Exit
43
- const rightStr = props.rightLabel ? color.dim(props.rightLabel) : '';
45
+ const rightStr = props.rightLabel
46
+ ? color.fg(theme.muted, props.rightLabel)
47
+ : '';
44
48
  const rightNode = engineBox(rightStr, {
45
49
  width: rightArea?.width ?? 0,
46
50
  align: 'right',
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/components/Header.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAS5B;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,GAAiB,EAAE,KAAkB;IAC1D,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC;IAEtC,uBAAuB;IACvB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC;IACvC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC1C,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEpC,wBAAwB;IACxB,GAAG,CACD,GAAG,EACH;QACE,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;KAChB,EACD,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;YAC3C,SAAS,EAAE,YAAY;YACvB,WAAW,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;SAC7B,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE;YAClC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;YAC3B,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,mBAAmB;QACnB,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE;YAChC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;YAC1B,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,EAAE;YACpC,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;YAC5B,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,mCAAmC;QACnC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/components/Header.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAiB5B;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,GAAiB,EAAE,KAAkB;IAC1D,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAE7C,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC;IAC/B,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC;IAE5B,wBAAwB;IACxB,GAAG,CACD,GAAG,EACH;QACE,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;KAChB,EACD,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC;YAC3C,SAAS,EAAE,YAAY;YACvB,WAAW,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;SAC7B,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ;YAC5B,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE;YAClC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;YAC3B,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,mBAAmB;QACnB,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,EAAE;YAChC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;YAC1B,KAAK,EAAE,QAAQ;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU;YAC/B,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC;YACzC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,EAAE;YACpC,KAAK,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;YAC5B,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAChB,CAAC,CAAC;QAEH,mCAAmC;QACnC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,16 +1,25 @@
1
1
  import type { BuntiContext } from '../dsl';
2
2
  import type { StyleOptions } from '../layout';
3
+ /** Props for Input. */
3
4
  export interface InputProps extends StyleOptions {
5
+ /** Stable id: keys the value state, focus slot, and hitbox. */
4
6
  id: string;
7
+ /** Label rendered above the field. */
5
8
  label?: string;
9
+ /** Ghost text shown while the field is empty. */
6
10
  placeholder?: string;
11
+ /** Initial value (state lives in useState(id) afterwards). */
7
12
  value?: string;
13
+ /** 'password' masks every glyph as '*'. */
8
14
  type?: 'text' | 'password';
15
+ /** Fires with the new value after every edit. */
9
16
  onChange?: (value: string) => void;
10
17
  }
11
18
  /**
12
19
  * Tactical Input Component
13
- * Managed state HOC with cursor simulation, keyboard interception, and mouse focus.
20
+ * Managed state HOC with a grapheme-aware editing cursor (insert/delete at
21
+ * cursor, arrows/home/end, ctrl+a/ctrl+e), an inverse-video cursor cell, and
22
+ * a width-aware horizontal scroll window.
14
23
  */
15
24
  export declare function Input(ctx: BuntiContext, props: InputProps): string;
16
25
  //# sourceMappingURL=Input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,MAAM,WAAW,UAAW,SAAQ,YAAY;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC3B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,UA2GzD"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/components/Input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,uBAAuB;AACvB,MAAM,WAAW,UAAW,SAAQ,YAAY;IAC9C,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAyJD;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,UAyHzD"}
@@ -1,7 +1,128 @@
1
- import { indentBlock } from '../utils';
1
+ import { charWidth, indentBlock } from '../utils';
2
+ /** Key names that must never insert as text. */
3
+ const NON_TEXT_KEYS = new Set([
4
+ 'up',
5
+ 'down',
6
+ 'left',
7
+ 'right',
8
+ 'enter',
9
+ 'escape',
10
+ 'tab',
11
+ 'backspace',
12
+ 'home',
13
+ 'end',
14
+ 'delete',
15
+ 'pageup',
16
+ 'pagedown',
17
+ 'insert',
18
+ 'click',
19
+ 'wheel_up',
20
+ 'wheel_down',
21
+ ]);
22
+ const FN_KEY_RE = /^f\d{1,2}$/;
23
+ function graphemes(text) {
24
+ if (text.length === 0)
25
+ return [];
26
+ const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
27
+ return Array.from(segmenter.segment(text), ({ segment }) => segment);
28
+ }
29
+ function isTextKey(key) {
30
+ return key.length > 0 && !NON_TEXT_KEYS.has(key) && !FN_KEY_RE.test(key);
31
+ }
32
+ /**
33
+ * Applies one frame of KeyEvents to the (value, cursor) pair. Grapheme-aware:
34
+ * cursor is a grapheme index, insert/delete operate on whole graphemes.
35
+ * Ctrl/alt combos never insert; ctrl+a/ctrl+e map to home/end (readline).
36
+ */
37
+ function applyKeys(keys, value, cursor) {
38
+ let glyphs = graphemes(value);
39
+ let pos = Math.max(0, Math.min(cursor, glyphs.length));
40
+ let changed = false;
41
+ for (const event of keys) {
42
+ if (event.kind === 'release')
43
+ continue;
44
+ if (event.ctrl || event.alt) {
45
+ // Readline muscle memory; every other modified combo is ignored so
46
+ // control bytes can never leak into the value.
47
+ if (event.ctrl && !event.alt && event.key === 'a')
48
+ pos = 0;
49
+ if (event.ctrl && !event.alt && event.key === 'e')
50
+ pos = glyphs.length;
51
+ continue;
52
+ }
53
+ switch (event.key) {
54
+ case 'left':
55
+ pos = Math.max(0, pos - 1);
56
+ break;
57
+ case 'right':
58
+ pos = Math.min(glyphs.length, pos + 1);
59
+ break;
60
+ case 'home':
61
+ pos = 0;
62
+ break;
63
+ case 'end':
64
+ pos = glyphs.length;
65
+ break;
66
+ case 'backspace':
67
+ if (pos > 0) {
68
+ glyphs = [...glyphs.slice(0, pos - 1), ...glyphs.slice(pos)];
69
+ pos--;
70
+ changed = true;
71
+ }
72
+ break;
73
+ case 'delete':
74
+ if (pos < glyphs.length) {
75
+ glyphs = [...glyphs.slice(0, pos), ...glyphs.slice(pos + 1)];
76
+ changed = true;
77
+ }
78
+ break;
79
+ default:
80
+ if (isTextKey(event.key)) {
81
+ glyphs = [...glyphs.slice(0, pos), event.key, ...glyphs.slice(pos)];
82
+ pos++;
83
+ changed = true;
84
+ }
85
+ }
86
+ }
87
+ return { value: glyphs.join(''), cursor: pos, changed };
88
+ }
89
+ /**
90
+ * Computes the horizontal scroll window that keeps the cursor visible in
91
+ * `innerW` columns. Width-aware: wide graphemes (emoji) count their real
92
+ * column width, so the window never overflows the field.
93
+ */
94
+ function cursorWindow(glyphs, cursor, scrollX, innerW) {
95
+ const widths = glyphs.map((g) => charWidth(g));
96
+ const cursorGlyph = cursor < glyphs.length ? glyphs[cursor] : ' ';
97
+ const cursorW = cursor < glyphs.length ? widths[cursor] : 1;
98
+ let scroll = Math.max(0, Math.min(scrollX, glyphs.length));
99
+ if (cursor < scroll)
100
+ scroll = cursor;
101
+ const spanWidth = (from) => {
102
+ let w = 0;
103
+ for (let i = from; i < cursor; i++)
104
+ w += widths[i];
105
+ return w + cursorW;
106
+ };
107
+ // Scroll right until the cursor cell fits (tail view when cursor at end).
108
+ while (scroll < cursor && spanWidth(scroll) > innerW)
109
+ scroll++;
110
+ const before = glyphs.slice(scroll, cursor).join('');
111
+ let used = spanWidth(scroll);
112
+ let after = '';
113
+ for (let i = cursor + 1; i < glyphs.length; i++) {
114
+ if (used + widths[i] > innerW)
115
+ break;
116
+ after += glyphs[i];
117
+ used += widths[i];
118
+ }
119
+ return { scroll, before, cursorGlyph, after };
120
+ }
2
121
  /**
3
122
  * Tactical Input Component
4
- * Managed state HOC with cursor simulation, keyboard interception, and mouse focus.
123
+ * Managed state HOC with a grapheme-aware editing cursor (insert/delete at
124
+ * cursor, arrows/home/end, ctrl+a/ctrl+e), an inverse-video cursor cell, and
125
+ * a width-aware horizontal scroll window.
5
126
  */
6
127
  export function Input(ctx, props) {
7
128
  const { box, color, focusable, state, useState, hitbox, resolveLocalRect } = ctx;
@@ -29,52 +150,61 @@ export function Input(ctx, props) {
29
150
  }
30
151
  // 2. Register in the global focus loop
31
152
  const isSelected = focusable(props.id);
32
- // 3. Manage internal state
153
+ // 3. Manage internal state: value + grapheme cursor + scroll window
33
154
  const [value, setValue] = useState(props.id, props.value || '');
34
- // 4. Handle Keyboard Interaction (only when focused)
35
- if (isSelected && state.lastKey) {
36
- const key = state.lastKey;
37
- if (key === 'backspace') {
38
- if (value.length > 0) {
39
- const newValue = value.slice(0, -1);
40
- setValue(newValue);
41
- if (props.onChange)
42
- props.onChange(newValue);
43
- }
44
- }
45
- else if (key === 'enter' ||
46
- key === 'tab' ||
47
- key === 'escape' ||
48
- key === 'up' ||
49
- key === 'down' ||
50
- key === 'left' ||
51
- key === 'right') {
52
- // System keys: ignore
53
- }
54
- else if (key.length === 1) {
55
- // Standard character input
56
- const newValue = value + key;
57
- setValue(newValue);
155
+ const [storedCursor, setCursor] = useState(`${props.id}_cursor`, graphemes(value).length);
156
+ const [scrollX, setScrollX] = useState(`${props.id}_scroll`, 0);
157
+ // The value can change externally (props/onChange round-trips): re-clamp.
158
+ let glyphs = graphemes(value);
159
+ let cursor = Math.max(0, Math.min(storedCursor, glyphs.length));
160
+ // 4. Keyboard interaction via the KeyEvent frame queue (only when focused)
161
+ if (isSelected && ctx.keys.length > 0) {
162
+ const edit = applyKeys(ctx.keys, value, cursor);
163
+ if (edit.changed) {
164
+ setValue(edit.value);
58
165
  if (props.onChange)
59
- props.onChange(newValue);
166
+ props.onChange(edit.value);
167
+ glyphs = graphemes(edit.value);
60
168
  }
169
+ if (edit.cursor !== storedCursor)
170
+ setCursor(edit.cursor);
171
+ cursor = edit.cursor;
61
172
  }
62
- // 5. Resolve Theme
63
- const neutralGray = { r: 217, g: 216, b: 213 };
64
- const borderCol = isSelected ? 'bunti-blue' : isHovered ? 'ash' : neutralGray;
65
- const labelColor = 'silver';
66
- const placeholderColor = 'ash';
67
- const textColor = 'white';
173
+ // 5. Resolve Theme — all colors come from ctx.theme tokens so the field
174
+ // restyles on live theme swaps.
175
+ const theme = ctx.theme;
176
+ const borderCol = isSelected
177
+ ? theme.focus
178
+ : isHovered
179
+ ? theme.muted
180
+ : theme.border;
181
+ const labelColor = theme.foreground;
182
+ const placeholderColor = theme.muted;
183
+ const textColor = theme.foreground;
184
+ // Inverse-video cursor cell: swap the field's fg/bg at the cursor.
185
+ const inverse = (s) => color.bg(theme.foreground, color.fg(theme.surface, s));
186
+ const displayGlyphs = props.type === 'password' ? glyphs.map(() => '*') : glyphs;
187
+ // Inner columns between the borders and [0,1] padding.
188
+ const innerW = Math.max(1, area.width - 4);
68
189
  let fieldValue = '';
69
- if (value.length === 0 && props.placeholder) {
70
- fieldValue = color.fg(placeholderColor, props.placeholder);
190
+ if (glyphs.length === 0) {
191
+ const placeholder = props.placeholder
192
+ ? color.fg(placeholderColor, props.placeholder)
193
+ : '';
194
+ // Focused empty field: inverse-space cursor, ghost placeholder after it.
195
+ fieldValue = isSelected ? inverse(' ') + placeholder : placeholder;
71
196
  }
72
- else {
73
- const displayValue = props.type === 'password' ? '*'.repeat(value.length) : value;
74
- fieldValue = color.fg(textColor, displayValue);
197
+ else if (isSelected) {
198
+ const win = cursorWindow(displayGlyphs, cursor, scrollX, innerW);
199
+ if (win.scroll !== scrollX)
200
+ setScrollX(win.scroll);
201
+ fieldValue =
202
+ color.fg(textColor, win.before) +
203
+ inverse(win.cursorGlyph) +
204
+ color.fg(textColor, win.after);
75
205
  }
76
- if (isSelected) {
77
- fieldValue += color.fg('silver', '█');
206
+ else {
207
+ fieldValue = color.fg(textColor, displayGlyphs.join(''));
78
208
  }
79
209
  const field = box({
80
210
  x: area.x,
@@ -83,6 +213,7 @@ export function Input(ctx, props) {
83
213
  height: area.height,
84
214
  border: 'rounded',
85
215
  borderColor: borderCol,
216
+ bgColor: theme.surface,
86
217
  padding: [0, 1],
87
218
  align: 'left',
88
219
  valign: 'middle',
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/components/Input.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/components/Input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type ColorValue } from '../colors';
2
+ import type { BuntiContext } from '../dsl';
3
+ export interface LinkProps {
4
+ id: string;
5
+ label: string;
6
+ /** Base color (default theme.accent); brightens on hover (mode-aware). */
7
+ color?: ColorValue;
8
+ onClick?: () => void;
9
+ /** Explicit column (default: current flow cursor). */
10
+ x?: number;
11
+ /** Explicit row (default: current flow cursor). */
12
+ y?: number;
13
+ }
14
+ /**
15
+ * Inline hyperlink: underlined themed text with a pointer-friendly hitbox.
16
+ * Hover brightens the color one step (mode-aware); clicks fire once per
17
+ * mouse release via the hitbox harness. Appends to the current flow and
18
+ * returns the styled string.
19
+ */
20
+ export declare function Link(ctx: BuntiContext, props: LinkProps): string;
21
+ //# sourceMappingURL=Link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../src/components/Link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,UAAU,EAAM,MAAM,WAAW,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAG3C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,sDAAsD;IACtD,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAuBhE"}
@@ -0,0 +1,29 @@
1
+ import { adjustBrightness, fg } from '../colors';
2
+ import { visibleWidth } from '../utils';
3
+ /**
4
+ * Inline hyperlink: underlined themed text with a pointer-friendly hitbox.
5
+ * Hover brightens the color one step (mode-aware); clicks fire once per
6
+ * mouse release via the hitbox harness. Appends to the current flow and
7
+ * returns the styled string.
8
+ */
9
+ export function Link(ctx, props) {
10
+ const width = visibleWidth(props.label);
11
+ const x = props.x ?? ctx.cursorX;
12
+ const y = props.y ?? ctx.cursorY;
13
+ const interaction = ctx.hitbox(props.id, { x, y, width, height: 1 });
14
+ if (interaction.clicked)
15
+ props.onClick?.();
16
+ const theme = ctx.theme;
17
+ const base = props.color ?? theme.accent;
18
+ const shift = theme.mode === 'dark' ? 25 : -25;
19
+ const colorNow = interaction.hovered ? adjustBrightness(base, shift) : base;
20
+ // Raw SGR 4/24 (not ctx.color.underline) so underline survives regardless
21
+ // of the vendor formatter's TTY color gate.
22
+ const styled = `\x1b[4m${fg(colorNow, props.label)}\x1b[24m`;
23
+ // When explicitly placed right of the cursor, pad the gap so the flow
24
+ // lands the label on its hitbox.
25
+ const pad = props.x !== undefined ? ' '.repeat(Math.max(0, props.x - ctx.cursorX)) : '';
26
+ ctx.text(pad + styled);
27
+ return styled;
28
+ }
29
+ //# sourceMappingURL=Link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../src/components/Link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAmB,EAAE,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAcxC;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,GAAiB,EAAE,KAAgB;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC;IACjC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC;IAEjC,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACrE,IAAI,WAAW,CAAC,OAAO;QAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5E,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;IAE7D,sEAAsE;IACtE,iCAAiC;IACjC,MAAM,GAAG,GACP,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,13 +1,38 @@
1
1
  import type { BuntiContext } from '../dsl';
2
+ /** Props for Modal. */
2
3
  export interface ModalProps {
4
+ /** Dialog width in cells. */
3
5
  width: number;
6
+ /** Dialog height in rows. */
4
7
  height: number;
8
+ /** Border glyph set (default 'double'). */
5
9
  border?: 'default' | 'rounded' | 'double' | 'dashed' | 'dotted' | 'frame' | 'thick-frame' | 'classic' | 'none';
10
+ /** Border color (default theme.border). */
6
11
  borderColor?: any;
12
+ /** Surface color (default theme.surfaceRaised). */
7
13
  bgColor?: any;
14
+ /** Horizontal content alignment (default 'center'). */
8
15
  align?: 'left' | 'center' | 'right';
16
+ /** Vertical content alignment. */
9
17
  valign?: 'top' | 'middle' | 'bottom';
18
+ /** [vertical, horizontal] padding inside the border, in cells. */
10
19
  padding?: [number, number];
20
+ /** Keys the entrance animation when multiple modals coexist. */
21
+ id?: string;
22
+ /** Layer z-index the modal composites at (default 100). */
23
+ zIndex?: number;
24
+ /** Backdrop dim 0..1 under the modal; `false` or 0 disables (default 0.55). */
25
+ backdrop?: number | false;
26
+ /** Drop shadow under the modal surface (default true). */
27
+ shadow?: boolean;
28
+ /** 150ms fade + slide-in entrance (default true). */
29
+ entrance?: boolean;
11
30
  }
31
+ /**
32
+ * Modal dialog: renders on its own layer with a dimmed backdrop and drop
33
+ * shadow, centered, with a 150ms fade/slide-in entrance. Surface and border
34
+ * derive from ctx.theme tokens; every visual default can be overridden or
35
+ * disabled via props.
36
+ */
12
37
  export declare function Modal(ctx: BuntiContext, props: ModalProps, callback: (sub: BuntiContext) => void): string;
13
38
  //# sourceMappingURL=Modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EACH,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,aAAa,GACb,SAAS,GACT,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,wBAAgB,KAAK,CACnB,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,UAiCtC"}
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAI3C,uBAAuB;AACvB,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,MAAM,CAAC,EACH,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,aAAa,GACb,SAAS,GACT,MAAM,CAAC;IACX,2CAA2C;IAC3C,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,mDAAmD;IACnD,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,kCAAkC;IAClC,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAcD;;;;;GAKG;AACH,wBAAgB,KAAK,CACnB,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,GACpC,MAAM,CAmFR"}