@flyingrobots/bijou 2.1.0 → 3.1.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 (157) hide show
  1. package/README.md +28 -20
  2. package/dist/adapters/test/clock.d.ts +36 -0
  3. package/dist/adapters/test/clock.d.ts.map +1 -0
  4. package/dist/adapters/test/clock.js +132 -0
  5. package/dist/adapters/test/clock.js.map +1 -0
  6. package/dist/adapters/test/index.d.ts +8 -1
  7. package/dist/adapters/test/index.d.ts.map +1 -1
  8. package/dist/adapters/test/index.js +24 -2
  9. package/dist/adapters/test/index.js.map +1 -1
  10. package/dist/adapters/test/io.d.ts +3 -0
  11. package/dist/adapters/test/io.d.ts.map +1 -1
  12. package/dist/adapters/test/io.js +5 -4
  13. package/dist/adapters/test/io.js.map +1 -1
  14. package/dist/adapters/test/runtime.d.ts +2 -0
  15. package/dist/adapters/test/runtime.d.ts.map +1 -1
  16. package/dist/adapters/test/runtime.js +1 -0
  17. package/dist/adapters/test/runtime.js.map +1 -1
  18. package/dist/core/ansi.d.ts +2 -0
  19. package/dist/core/ansi.d.ts.map +1 -1
  20. package/dist/core/ansi.js +2 -0
  21. package/dist/core/ansi.js.map +1 -1
  22. package/dist/core/clock.d.ts +12 -0
  23. package/dist/core/clock.d.ts.map +1 -0
  24. package/dist/core/clock.js +59 -0
  25. package/dist/core/clock.js.map +1 -0
  26. package/dist/core/components/alert-v3.d.ts +7 -0
  27. package/dist/core/components/alert-v3.d.ts.map +1 -0
  28. package/dist/core/components/alert-v3.js +37 -0
  29. package/dist/core/components/alert-v3.js.map +1 -0
  30. package/dist/core/components/alert.d.ts +4 -4
  31. package/dist/core/components/alert.d.ts.map +1 -1
  32. package/dist/core/components/alert.js +1 -1
  33. package/dist/core/components/alert.js.map +1 -1
  34. package/dist/core/components/badge.d.ts +6 -12
  35. package/dist/core/components/badge.d.ts.map +1 -1
  36. package/dist/core/components/badge.js +39 -24
  37. package/dist/core/components/badge.js.map +1 -1
  38. package/dist/core/components/bcss-style.d.ts +6 -0
  39. package/dist/core/components/bcss-style.d.ts.map +1 -0
  40. package/dist/core/components/bcss-style.js +44 -0
  41. package/dist/core/components/bcss-style.js.map +1 -0
  42. package/dist/core/components/box-v3.d.ts +17 -0
  43. package/dist/core/components/box-v3.d.ts.map +1 -0
  44. package/dist/core/components/box-v3.js +149 -0
  45. package/dist/core/components/box-v3.js.map +1 -0
  46. package/dist/core/components/box.d.ts +11 -4
  47. package/dist/core/components/box.d.ts.map +1 -1
  48. package/dist/core/components/box.js +37 -9
  49. package/dist/core/components/box.js.map +1 -1
  50. package/dist/core/components/index.d.ts +6 -0
  51. package/dist/core/components/index.d.ts.map +1 -1
  52. package/dist/core/components/index.js +4 -0
  53. package/dist/core/components/index.js.map +1 -1
  54. package/dist/core/components/log.d.ts.map +1 -1
  55. package/dist/core/components/log.js +6 -4
  56. package/dist/core/components/log.js.map +1 -1
  57. package/dist/core/components/overflow.d.ts +3 -0
  58. package/dist/core/components/overflow.d.ts.map +1 -0
  59. package/dist/core/components/overflow.js +33 -0
  60. package/dist/core/components/overflow.js.map +1 -0
  61. package/dist/core/components/progress.d.ts.map +1 -1
  62. package/dist/core/components/progress.js +3 -1
  63. package/dist/core/components/progress.js.map +1 -1
  64. package/dist/core/components/separator-v3.d.ts +7 -0
  65. package/dist/core/components/separator-v3.d.ts.map +1 -0
  66. package/dist/core/components/separator-v3.js +46 -0
  67. package/dist/core/components/separator-v3.js.map +1 -0
  68. package/dist/core/components/separator.d.ts +2 -4
  69. package/dist/core/components/separator.d.ts.map +1 -1
  70. package/dist/core/components/separator.js.map +1 -1
  71. package/dist/core/components/spinner.d.ts.map +1 -1
  72. package/dist/core/components/spinner.js +3 -1
  73. package/dist/core/components/spinner.js.map +1 -1
  74. package/dist/core/components/surface-text.d.ts +14 -0
  75. package/dist/core/components/surface-text.d.ts.map +1 -0
  76. package/dist/core/components/surface-text.js +95 -0
  77. package/dist/core/components/surface-text.js.map +1 -0
  78. package/dist/core/components/table-v3.d.ts +11 -0
  79. package/dist/core/components/table-v3.d.ts.map +1 -0
  80. package/dist/core/components/table-v3.js +148 -0
  81. package/dist/core/components/table-v3.js.map +1 -0
  82. package/dist/core/components/table.d.ts +2 -1
  83. package/dist/core/components/table.d.ts.map +1 -1
  84. package/dist/core/components/table.js +40 -11
  85. package/dist/core/components/table.js.map +1 -1
  86. package/dist/core/components/timer.d.ts.map +1 -1
  87. package/dist/core/components/timer.js +11 -9
  88. package/dist/core/components/timer.js.map +1 -1
  89. package/dist/core/components/types.d.ts +19 -0
  90. package/dist/core/components/types.d.ts.map +1 -0
  91. package/dist/core/components/types.js +2 -0
  92. package/dist/core/components/types.js.map +1 -0
  93. package/dist/core/layout/flex.d.ts +28 -0
  94. package/dist/core/layout/flex.d.ts.map +1 -0
  95. package/dist/core/layout/flex.js +126 -0
  96. package/dist/core/layout/flex.js.map +1 -0
  97. package/dist/core/render/differ.d.ts +49 -0
  98. package/dist/core/render/differ.d.ts.map +1 -0
  99. package/dist/core/render/differ.js +271 -0
  100. package/dist/core/render/differ.js.map +1 -0
  101. package/dist/core/runtime-viewport.d.ts +34 -0
  102. package/dist/core/runtime-viewport.d.ts.map +1 -0
  103. package/dist/core/runtime-viewport.js +74 -0
  104. package/dist/core/runtime-viewport.js.map +1 -0
  105. package/dist/core/text/index.d.ts +1 -0
  106. package/dist/core/text/index.d.ts.map +1 -1
  107. package/dist/core/text/index.js +1 -0
  108. package/dist/core/text/index.js.map +1 -1
  109. package/dist/core/text/wrap.d.ts +11 -0
  110. package/dist/core/text/wrap.d.ts.map +1 -0
  111. package/dist/core/text/wrap.js +90 -0
  112. package/dist/core/text/wrap.js.map +1 -0
  113. package/dist/core/theme/accessors.d.ts.map +1 -1
  114. package/dist/core/theme/accessors.js +21 -5
  115. package/dist/core/theme/accessors.js.map +1 -1
  116. package/dist/core/theme/graph-types.d.ts +58 -0
  117. package/dist/core/theme/graph-types.d.ts.map +1 -0
  118. package/dist/core/theme/graph-types.js +2 -0
  119. package/dist/core/theme/graph-types.js.map +1 -0
  120. package/dist/core/theme/graph.d.ts +27 -0
  121. package/dist/core/theme/graph.d.ts.map +1 -0
  122. package/dist/core/theme/graph.js +155 -0
  123. package/dist/core/theme/graph.js.map +1 -0
  124. package/dist/core/theme/index.d.ts +3 -0
  125. package/dist/core/theme/index.d.ts.map +1 -1
  126. package/dist/core/theme/index.js +2 -0
  127. package/dist/core/theme/index.js.map +1 -1
  128. package/dist/core/theme/resolve.d.ts +3 -0
  129. package/dist/core/theme/resolve.d.ts.map +1 -1
  130. package/dist/core/theme/resolve.js +3 -0
  131. package/dist/core/theme/resolve.js.map +1 -1
  132. package/dist/factory.d.ts +3 -0
  133. package/dist/factory.d.ts.map +1 -1
  134. package/dist/factory.js +8 -0
  135. package/dist/factory.js.map +1 -1
  136. package/dist/index.d.ts +10 -4
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +11 -3
  139. package/dist/index.js.map +1 -1
  140. package/dist/ports/clock.d.ts +29 -0
  141. package/dist/ports/clock.d.ts.map +1 -0
  142. package/dist/ports/clock.js +2 -0
  143. package/dist/ports/clock.js.map +1 -0
  144. package/dist/ports/context.d.ts +12 -0
  145. package/dist/ports/context.d.ts.map +1 -1
  146. package/dist/ports/index.d.ts +1 -0
  147. package/dist/ports/index.d.ts.map +1 -1
  148. package/dist/ports/index.js.map +1 -1
  149. package/dist/ports/io.d.ts +6 -0
  150. package/dist/ports/io.d.ts.map +1 -1
  151. package/dist/ports/runtime.d.ts +5 -0
  152. package/dist/ports/runtime.d.ts.map +1 -1
  153. package/dist/ports/surface.d.ts +152 -0
  154. package/dist/ports/surface.d.ts.map +1 -0
  155. package/dist/ports/surface.js +199 -0
  156. package/dist/ports/surface.js.map +1 -0
  157. package/package.json +2 -2
@@ -0,0 +1,37 @@
1
+ import { createSurface } from '../../ports/surface.js';
2
+ import { resolveSafeCtx as resolveCtx } from '../resolve-ctx.js';
3
+ import { boxSurface } from './box-v3.js';
4
+ import { createTextSurface, tokenToCellStyle } from './surface-text.js';
5
+ const ICONS = {
6
+ success: '\u2713',
7
+ error: '\u2717',
8
+ warning: '\u26A0',
9
+ info: '\u2139',
10
+ };
11
+ const BORDER_TOKENS = {
12
+ success: 'success',
13
+ error: 'error',
14
+ warning: 'warning',
15
+ info: 'primary',
16
+ };
17
+ /**
18
+ * Render an alert box as a Surface for V3-native composition.
19
+ */
20
+ export function alertSurface(message, options = {}) {
21
+ const ctx = resolveCtx(options.ctx);
22
+ const variant = options.variant ?? 'info';
23
+ const iconSurface = createTextSurface(ICONS[variant], tokenToCellStyle(ctx?.semantic(variant)));
24
+ const messageSurface = typeof message === 'string' ? createTextSurface(message) : message;
25
+ const width = iconSurface.width + 1 + messageSurface.width;
26
+ const height = Math.max(iconSurface.height, messageSurface.height, 1);
27
+ const content = createSurface(width, height, { char: ' ', empty: false });
28
+ content.blit(iconSurface, 0, 0);
29
+ content.set(iconSurface.width, 0, { char: ' ', empty: false });
30
+ content.blit(messageSurface, iconSurface.width + 1, 0);
31
+ return boxSurface(content, {
32
+ ...options,
33
+ borderToken: options.borderToken ?? ctx?.border(BORDER_TOKENS[variant]),
34
+ bgToken: options.bgToken ?? ctx?.surface('elevated'),
35
+ });
36
+ }
37
+ //# sourceMappingURL=alert-v3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-v3.js","sourceRoot":"","sources":["../../../src/core/components/alert-v3.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExE,MAAM,KAAK,GAAiC;IAC1C,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,MAAM,aAAa,GAAsE;IACvF,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAyB,EAAE,UAAwB,EAAE;IAChF,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAC1C,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,cAAc,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1F,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAE1E,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvD,OAAO,UAAU,CAAC,OAAO,EAAE;QACzB,GAAG,OAAO;QACV,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,EAAE,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACvE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC;KACrD,CAAC,CAAC;AACL,CAAC"}
@@ -1,15 +1,15 @@
1
- import type { BijouContext } from '../../ports/context.js';
2
1
  import type { TokenValue } from '../theme/tokens.js';
2
+ import type { BijouNodeOptions } from './types.js';
3
3
  /** Alert severity level. */
4
4
  export type AlertVariant = 'success' | 'error' | 'warning' | 'info';
5
5
  /** Configuration for rendering an alert box. */
6
- export interface AlertOptions {
6
+ export interface AlertOptions extends BijouNodeOptions {
7
7
  /** Severity variant (defaults to `'info'`). */
8
8
  variant?: AlertVariant;
9
+ /** Theme token applied to alert borders. Defaults to a variant-specific border token. */
10
+ borderToken?: TokenValue;
9
11
  /** Background fill token for the alert box interior. Defaults to `surface.elevated`. */
10
12
  bgToken?: TokenValue;
11
- /** Bijou context for I/O, styling, and mode detection. */
12
- ctx?: BijouContext;
13
13
  }
14
14
  /**
15
15
  * Render an alert box with an icon and message.
@@ -1 +1 @@
1
- {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/core/components/alert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAS,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAK5D,4BAA4B;AAC5B,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpE,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,wFAAwF;IACxF,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAkCD;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAsBzE"}
1
+ {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/core/components/alert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAI5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,4BAA4B;AAC5B,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpE,gDAAgD;AAChD,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD,+CAA+C;IAC/C,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,yFAAyF;IACzF,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,wFAAwF;IACxF,OAAO,CAAC,EAAE,UAAU,CAAC;CACtB;AAkCD;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAsBzE"}
@@ -51,7 +51,7 @@ export function alert(message, options = {}) {
51
51
  interactive: () => {
52
52
  const icon = ICONS[variant];
53
53
  const semanticToken = ctx.semantic(variant);
54
- const borderToken = ctx.border(BORDER_TOKENS[variant]);
54
+ const borderToken = options.borderToken ?? ctx.border(BORDER_TOKENS[variant]);
55
55
  const coloredIcon = ctx.style.styled(semanticToken, icon);
56
56
  return box(coloredIcon + ' ' + safeMessage, {
57
57
  borderToken,
@@ -1 +1 @@
1
- {"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../src/core/components/alert.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAejD,sDAAsD;AACtD,MAAM,KAAK,GAAiC;IAC1C,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,iDAAiD;AACjD,MAAM,WAAW,GAAiC;IAChD,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,yDAAyD;AACzD,MAAM,iBAAiB,GAAiC;IACtD,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,8EAA8E;AAC9E,MAAM,aAAa,GAAgD;IACjE,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,UAAwB,EAAE;IAC/D,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,IAAI,EAAE,CAAC;IAElC,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE;QAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,WAAW,EAAE;QACtD,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,KAAK,WAAW,EAAE;QACjE,WAAW,EAAE,GAAG,EAAE;YAChB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YAE1D,OAAO,GAAG,CAAC,WAAW,GAAG,GAAG,GAAG,WAAW,EAAE;gBAC1C,WAAW;gBACX,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;gBACnD,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;gBAC9B,GAAG;aACJ,CAAC,CAAC;QACL,CAAC;KACF,EAAE,OAAO,CAAC,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../src/core/components/alert.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgBjD,sDAAsD;AACtD,MAAM,KAAK,GAAiC;IAC1C,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,iDAAiD;AACjD,MAAM,WAAW,GAAiC;IAChD,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,yDAAyD;AACzD,MAAM,iBAAiB,GAAiC;IACtD,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,8EAA8E;AAC9E,MAAM,aAAa,GAAgD;IACjE,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;CAChB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,UAAwB,EAAE;IAC/D,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,IAAI,EAAE,CAAC;IAElC,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE;QAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,KAAK,WAAW,EAAE;QACtD,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG,iBAAiB,CAAC,OAAO,CAAC,KAAK,WAAW,EAAE;QACjE,WAAW,EAAE,GAAG,EAAE;YAChB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9E,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YAE1D,OAAO,GAAG,CAAC,WAAW,GAAG,GAAG,GAAG,WAAW,EAAE;gBAC1C,WAAW;gBACX,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;gBACnD,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;gBAC9B,GAAG;aACJ,CAAC,CAAC;QACL,CAAC;KACF,EAAE,OAAO,CAAC,CAAC;AACd,CAAC"}
@@ -1,27 +1,21 @@
1
- import type { BijouContext } from '../../ports/context.js';
1
+ import { type Surface } from '../../ports/surface.js';
2
2
  import type { BaseStatusKey } from '../theme/tokens.js';
3
+ import type { BijouNodeOptions } from './types.js';
3
4
  /** Badge color variant — any status key, plus `'accent'` and `'primary'`. */
4
5
  export type BadgeVariant = BaseStatusKey | 'accent' | 'primary';
5
6
  /** Configuration for rendering a badge. */
6
- export interface BadgeOptions {
7
+ export interface BadgeOptions extends BijouNodeOptions {
7
8
  /** Color variant (defaults to `'info'`). */
8
9
  variant?: BadgeVariant;
9
- /** Bijou context for I/O, styling, and mode detection. */
10
- ctx?: BijouContext;
11
10
  }
12
11
  /**
13
12
  * Render an inline badge (pill-shaped label) for the given text.
14
13
  *
15
- * Output adapts to the current output mode:
16
- * - `interactive` / `static` — inverse-colored pill using the variant token.
17
- * - `pipe` — bracketed text like `[OK]`.
18
- * - `accessible` — plain text.
19
- *
20
- * Falls back to a plain space-padded string when no context or theme is available.
14
+ * Returns a Surface containing the styled badge.
21
15
  *
22
16
  * @param text - Label to display inside the badge.
23
17
  * @param options - Badge configuration.
24
- * @returns The rendered badge string.
18
+ * @returns The rendered badge Surface.
25
19
  */
26
- export declare function badge(text: string, options?: BadgeOptions): string;
20
+ export declare function badge(text: string, options?: BadgeOptions): Surface;
27
21
  //# sourceMappingURL=badge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/core/components/badge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIpE,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhE,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAsBtE"}
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/core/components/badge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAa,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhE,2CAA2C;AAC3C,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD,4CAA4C;IAC5C,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CA2CvE"}
@@ -1,37 +1,52 @@
1
+ import { createSurface } from '../../ports/surface.js';
1
2
  import { resolveSafeCtx as resolveCtx } from '../resolve-ctx.js';
2
- import { renderByMode } from '../mode-render.js';
3
+ import { segmentGraphemes } from '../text/grapheme.js';
4
+ import { applyBCSSCellTextStyles } from './bcss-style.js';
3
5
  /**
4
6
  * Render an inline badge (pill-shaped label) for the given text.
5
7
  *
6
- * Output adapts to the current output mode:
7
- * - `interactive` / `static` — inverse-colored pill using the variant token.
8
- * - `pipe` — bracketed text like `[OK]`.
9
- * - `accessible` — plain text.
10
- *
11
- * Falls back to a plain space-padded string when no context or theme is available.
8
+ * Returns a Surface containing the styled badge.
12
9
  *
13
10
  * @param text - Label to display inside the badge.
14
11
  * @param options - Badge configuration.
15
- * @returns The rendered badge string.
12
+ * @returns The rendered badge Surface.
16
13
  */
17
14
  export function badge(text, options = {}) {
18
15
  const ctx = resolveCtx(options.ctx);
19
- if (!ctx)
20
- return ` ${text} `;
21
16
  const variant = options.variant ?? 'info';
22
- return renderByMode(ctx.mode, {
23
- pipe: () => `[${text}]`,
24
- accessible: () => text,
25
- interactive: () => {
26
- const baseToken = (variant === 'accent' || variant === 'primary')
27
- ? ctx.semantic(variant)
28
- : ctx.status(variant);
29
- const inverseToken = {
30
- hex: baseToken.hex,
31
- modifiers: [...(baseToken.modifiers ?? []), 'inverse'],
32
- };
33
- return ctx.style.styled(inverseToken, ` ${text} `);
34
- },
35
- }, options);
17
+ const paddedText = ` ${text} `;
18
+ const graphemes = segmentGraphemes(paddedText);
19
+ const width = graphemes.length;
20
+ const surface = createSurface(width, 1);
21
+ if (!ctx || ctx.mode === 'pipe' || ctx.mode === 'accessible') {
22
+ // Basic text output for non-rich modes
23
+ const char = ctx?.mode === 'pipe' ? `[${text}]` : paddedText;
24
+ return stringToSurface(char, char.length, 1);
25
+ }
26
+ // Resolve global CSS styles
27
+ const bcss = ctx.resolveBCSS({ type: 'Badge', id: options.id, classes: options.class?.split(' ') });
28
+ const baseToken = (variant === 'accent' || variant === 'primary')
29
+ ? ctx.semantic(variant)
30
+ : ctx.status(variant);
31
+ const cell = {
32
+ char: ' ',
33
+ ...applyBCSSCellTextStyles({
34
+ fg: baseToken.hex,
35
+ bg: undefined,
36
+ modifiers: [...(baseToken.modifiers ?? []), 'inverse'],
37
+ }, bcss),
38
+ empty: false
39
+ };
40
+ // If CSS background is set, we might want to disable 'inverse' modifier
41
+ // since the user is being explicit about the BG color.
42
+ if (bcss['background']) {
43
+ cell.modifiers = cell.modifiers?.filter(m => m !== 'inverse');
44
+ }
45
+ for (let i = 0; i < width; i++) {
46
+ surface.set(i, 0, { ...cell, char: graphemes[i] });
47
+ }
48
+ return surface;
36
49
  }
50
+ // Helper needed for the fallback
51
+ import { stringToSurface } from '../render/differ.js';
37
52
  //# sourceMappingURL=badge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../src/core/components/badge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAajD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,UAAwB,EAAE;IAC5D,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,IAAI,GAAG,CAAC;IAE7B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAE1C,OAAO,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE;QAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,GAAG;QACvB,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI;QACtB,WAAW,EAAE,GAAG,EAAE;YAChB,MAAM,SAAS,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC;gBAC/D,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACvB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAExB,MAAM,YAAY,GAAe;gBAC/B,GAAG,EAAE,SAAS,CAAC,GAAG;gBAClB,SAAS,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC;aACvD,CAAC;YAEF,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QACrD,CAAC;KACF,EAAE,OAAO,CAAC,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../src/core/components/badge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA2B,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EAAE,cAAc,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAW1D;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,UAAwB,EAAE;IAC5D,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAI,IAAI,GAAG,CAAC;IAC/B,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC;IAC/B,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAExC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7D,uCAAuC;QACvC,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;QAC7D,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,4BAA4B;IAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEpG,MAAM,SAAS,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC;QAC/D,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;QACvB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAExB,MAAM,IAAI,GAAS;QACjB,IAAI,EAAE,GAAG;QACT,GAAG,uBAAuB,CAAC;YACzB,EAAE,EAAE,SAAS,CAAC,GAAG;YACjB,EAAE,EAAE,SAAS;YACb,SAAS,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC;SACvD,EAAE,IAAI,CAAC;QACR,KAAK,EAAE,KAAK;KACb,CAAC;IAEF,yEAAyE;IACzE,uDAAuD;IACvD,IAAI,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iCAAiC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Cell } from '../../ports/surface.js';
2
+ type BCSSStyles = Record<string, string>;
3
+ export declare function mergeBCSSModifiers(base: readonly string[] | undefined, styles: BCSSStyles): string[] | undefined;
4
+ export declare function applyBCSSCellTextStyles(base: Pick<Cell, 'fg' | 'bg' | 'modifiers'>, styles: BCSSStyles): Pick<Cell, 'fg' | 'bg' | 'modifiers'>;
5
+ export {};
6
+ //# sourceMappingURL=bcss-style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bcss-style.d.ts","sourceRoot":"","sources":["../../../src/core/components/bcss-style.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAEnD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACnC,MAAM,EAAE,UAAU,GACjB,MAAM,EAAE,GAAG,SAAS,CAoCtB;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,EAC3C,MAAM,EAAE,UAAU,GACjB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,CAMvC"}
@@ -0,0 +1,44 @@
1
+ export function mergeBCSSModifiers(base, styles) {
2
+ const modifiers = new Set(base ?? []);
3
+ const fontWeight = styles['font-weight']?.trim().toLowerCase();
4
+ if (fontWeight === 'bold' || fontWeight === '700' || fontWeight === '800' || fontWeight === '900') {
5
+ modifiers.add('bold');
6
+ }
7
+ else if (fontWeight === 'normal' || fontWeight === '400') {
8
+ modifiers.delete('bold');
9
+ }
10
+ const fontStyle = styles['font-style']?.trim().toLowerCase();
11
+ if (fontStyle === 'italic') {
12
+ modifiers.add('italic');
13
+ }
14
+ else if (fontStyle === 'normal') {
15
+ modifiers.delete('italic');
16
+ }
17
+ const decoration = styles['text-decoration']?.trim().toLowerCase();
18
+ if (decoration === 'none') {
19
+ modifiers.delete('underline');
20
+ modifiers.delete('curly-underline');
21
+ modifiers.delete('dotted-underline');
22
+ modifiers.delete('dashed-underline');
23
+ modifiers.delete('strikethrough');
24
+ modifiers.delete('strike');
25
+ }
26
+ else if (decoration) {
27
+ if (decoration.includes('underline')) {
28
+ modifiers.add('underline');
29
+ }
30
+ if (decoration.includes('line-through')) {
31
+ modifiers.add('strikethrough');
32
+ modifiers.delete('strike');
33
+ }
34
+ }
35
+ return modifiers.size > 0 ? Array.from(modifiers) : undefined;
36
+ }
37
+ export function applyBCSSCellTextStyles(base, styles) {
38
+ return {
39
+ fg: styles['color'] ?? base.fg,
40
+ bg: styles['background'] ?? base.bg,
41
+ modifiers: mergeBCSSModifiers(base.modifiers, styles),
42
+ };
43
+ }
44
+ //# sourceMappingURL=bcss-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bcss-style.js","sourceRoot":"","sources":["../../../src/core/components/bcss-style.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,kBAAkB,CAChC,IAAmC,EACnC,MAAkB;IAElB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAEtC,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QAClG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;SAAM,IAAI,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QAC3D,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7D,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnE,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC9B,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACpC,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACrC,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACrC,SAAS,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAClC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,UAAU,EAAE,CAAC;QACtB,IAAI,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACrC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACxC,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YAC/B,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,IAA2C,EAC3C,MAAkB;IAElB,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE;QAC9B,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,EAAE;QACnC,SAAS,EAAE,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC;KACtD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Surface } from '../../ports/surface.js';
2
+ import { type BoxOptions, type HeaderBoxOptions } from './box.js';
3
+ /**
4
+ * Render a bordered box around a Surface.
5
+ *
6
+ * Returns a new Surface containing the box and the nested content.
7
+ */
8
+ export declare function boxSurface(content: Surface | string, options?: BoxOptions): Surface;
9
+ export declare const boxV3: typeof boxSurface;
10
+ /**
11
+ * Render a header box as a Surface for V3-native composition.
12
+ *
13
+ * Unlike {@link headerBox}, this always returns a Surface and is intended
14
+ * for use inside framed apps or other surface-first render paths.
15
+ */
16
+ export declare function headerBoxSurface(label: string, options?: HeaderBoxOptions): Surface;
17
+ //# sourceMappingURL=box-v3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box-v3.d.ts","sourceRoot":"","sources":["../../../src/core/components/box-v3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAa,MAAM,wBAAwB,CAAC;AAIhF,OAAO,EAAmB,KAAK,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AA4BnF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAwGvF;AAED,eAAO,MAAM,KAAK,mBAAa,CAAC;AAEhC;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAmBvF"}
@@ -0,0 +1,149 @@
1
+ import { createSurface } from '../../ports/surface.js';
2
+ import { resolveSafeCtx as resolveCtx } from '../resolve-ctx.js';
3
+ import { clipToWidth } from '../text/clip.js';
4
+ import { wrapToWidth } from '../text/wrap.js';
5
+ import { resolveFillChar } from './box.js';
6
+ import { applyBCSSCellTextStyles } from './bcss-style.js';
7
+ import { createSegmentSurface, createTextSurface, segmentSurfaceText, tokenToCellStyle, wrapSurfaceToWidth } from './surface-text.js';
8
+ import { resolveOverflowBehavior } from './overflow.js';
9
+ const BORDER = { tl: '┌', tr: '┐', bl: '└', br: '┘', h: '─', v: '│' };
10
+ function normalizeFixedWidth(width) {
11
+ if (width == null)
12
+ return undefined;
13
+ if (!Number.isFinite(width))
14
+ return undefined;
15
+ return Math.max(2, Math.floor(width));
16
+ }
17
+ function withInheritedBackground(surface, background) {
18
+ if (background == null)
19
+ return surface;
20
+ const next = surface.clone();
21
+ for (let y = 0; y < next.height; y++) {
22
+ for (let x = 0; x < next.width; x++) {
23
+ const cell = next.get(x, y);
24
+ if (cell.empty || cell.bg != null)
25
+ continue;
26
+ next.set(x, y, { ...cell, bg: background });
27
+ }
28
+ }
29
+ return next;
30
+ }
31
+ /**
32
+ * Render a bordered box around a Surface.
33
+ *
34
+ * Returns a new Surface containing the box and the nested content.
35
+ */
36
+ export function boxSurface(content, options = {}) {
37
+ const ctx = resolveCtx(options.ctx);
38
+ const { title, width: fixedWidth, padding = {} } = options;
39
+ const bcss = ctx?.resolveBCSS({ type: 'Box', id: options.id, classes: options.class?.split(' ') }) ?? {};
40
+ const overflow = resolveOverflowBehavior(options.overflow, bcss);
41
+ const normalizedFixedWidth = normalizeFixedWidth(fixedWidth);
42
+ const pt = padding.top ?? 0;
43
+ const pb = padding.bottom ?? 0;
44
+ const pl = padding.left ?? 0;
45
+ const pr = padding.right ?? 0;
46
+ let contentSurf;
47
+ if (typeof content === 'string') {
48
+ const wrapped = normalizedFixedWidth !== undefined && overflow === 'wrap'
49
+ ? wrapToWidth(content, Math.max(0, normalizedFixedWidth - 2 - pl - pr)).join('\n')
50
+ : content;
51
+ contentSurf = createTextSurface(wrapped);
52
+ }
53
+ else {
54
+ contentSurf = normalizedFixedWidth !== undefined && overflow === 'wrap'
55
+ ? wrapSurfaceToWidth(content, Math.max(0, normalizedFixedWidth - 2 - pl - pr))
56
+ : content;
57
+ }
58
+ const autoTitleWidth = normalizedFixedWidth === undefined && title
59
+ ? segmentSurfaceText(` ${title} `, 'boxSurface title').length
60
+ : 0;
61
+ const innerW = normalizedFixedWidth === undefined
62
+ ? Math.max(contentSurf.width + pl + pr, autoTitleWidth)
63
+ : contentSurf.width + pl + pr;
64
+ const innerH = contentSurf.height + pt + pb;
65
+ const outerW = normalizedFixedWidth ?? (innerW + 2);
66
+ const outerH = innerH + 2;
67
+ const boundedInnerW = Math.max(0, outerW - 2);
68
+ const effectiveLeft = normalizedFixedWidth !== undefined ? Math.min(pl, boundedInnerW) : pl;
69
+ const effectiveRight = normalizedFixedWidth !== undefined ? Math.min(pr, Math.max(0, boundedInnerW - effectiveLeft)) : pr;
70
+ const contentBoxWidth = Math.max(0, boundedInnerW - effectiveLeft - effectiveRight);
71
+ const surface = createSurface(outerW, outerH);
72
+ const resolvedFillChar = resolveFillChar(options.fillChar);
73
+ const fillStyle = applyBCSSCellTextStyles({
74
+ fg: undefined,
75
+ bg: options.bgToken?.bg,
76
+ modifiers: undefined,
77
+ }, bcss);
78
+ surface.fill({
79
+ char: resolvedFillChar,
80
+ bg: fillStyle.bg,
81
+ fg: fillStyle.fg,
82
+ modifiers: fillStyle.modifiers,
83
+ empty: false,
84
+ });
85
+ const borderToken = options.borderToken || ctx?.border('primary');
86
+ const borderStyle = applyBCSSCellTextStyles({
87
+ fg: borderToken?.hex ?? '#ffffff',
88
+ bg: borderToken?.bg,
89
+ modifiers: borderToken?.modifiers,
90
+ }, bcss);
91
+ const borderCell = {
92
+ char: ' ',
93
+ fg: borderStyle.fg,
94
+ bg: borderStyle.bg,
95
+ modifiers: borderStyle.modifiers,
96
+ };
97
+ // Draw borders
98
+ for (let x = 0; x < outerW; x++) {
99
+ surface.set(x, 0, { ...borderCell, char: BORDER.h });
100
+ surface.set(x, outerH - 1, { ...borderCell, char: BORDER.h });
101
+ }
102
+ for (let y = 0; y < outerH; y++) {
103
+ surface.set(0, y, { ...borderCell, char: BORDER.v });
104
+ surface.set(outerW - 1, y, { ...borderCell, char: BORDER.v });
105
+ }
106
+ surface.set(0, 0, { ...borderCell, char: BORDER.tl });
107
+ surface.set(outerW - 1, 0, { ...borderCell, char: BORDER.tr });
108
+ surface.set(0, outerH - 1, { ...borderCell, char: BORDER.bl });
109
+ surface.set(outerW - 1, outerH - 1, { ...borderCell, char: BORDER.br });
110
+ // Draw title
111
+ if (title && outerW >= 4) {
112
+ const available = Math.max(0, outerW - 4);
113
+ const titleText = clipToWidth(` ${title} `, available);
114
+ const titleGs = segmentSurfaceText(titleText, 'boxSurface title');
115
+ const titleLen = Math.min(titleGs.length, available);
116
+ for (let i = 0; i < titleLen; i++) {
117
+ surface.set(i + 2, 0, { ...borderCell, char: titleGs[i] });
118
+ }
119
+ }
120
+ // Blit content
121
+ surface.blit(withInheritedBackground(contentSurf, fillStyle.bg), effectiveLeft + 1, pt + 1, 0, 0, contentBoxWidth, contentSurf.height);
122
+ return surface;
123
+ }
124
+ export const boxV3 = boxSurface;
125
+ /**
126
+ * Render a header box as a Surface for V3-native composition.
127
+ *
128
+ * Unlike {@link headerBox}, this always returns a Surface and is intended
129
+ * for use inside framed apps or other surface-first render paths.
130
+ */
131
+ export function headerBoxSurface(label, options = {}) {
132
+ const ctx = resolveCtx(options.ctx);
133
+ const safeLabel = label ?? '';
134
+ const detail = options.detail ?? '';
135
+ const labelToken = options.labelToken ?? ctx?.semantic('primary');
136
+ const mutedToken = ctx?.semantic('muted');
137
+ const segments = [];
138
+ if (safeLabel.length > 0) {
139
+ segments.push({ text: safeLabel, style: tokenToCellStyle(labelToken) });
140
+ }
141
+ if (detail.length > 0) {
142
+ segments.push({
143
+ text: safeLabel.length > 0 ? ` ${detail}` : detail,
144
+ style: tokenToCellStyle(mutedToken),
145
+ });
146
+ }
147
+ return boxSurface(createSegmentSurface(segments), options);
148
+ }
149
+ //# sourceMappingURL=box-v3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box-v3.js","sourceRoot":"","sources":["../../../src/core/components/box-v3.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
- import type { BijouContext } from '../../ports/context.js';
2
1
  import type { TokenValue } from '../theme/tokens.js';
2
+ import type { BijouNodeOptions } from './types.js';
3
3
  /** Configuration for rendering a bordered box. */
4
- export interface BoxOptions {
4
+ export interface BoxOptions extends BijouNodeOptions {
5
+ /** Optional title displayed in the top border. */
6
+ title?: string;
5
7
  /** Theme token applied to border characters. */
6
8
  borderToken?: TokenValue;
7
9
  /** Background fill token. Interior spaces are styled with this token's bg color. */
@@ -21,8 +23,6 @@ export interface BoxOptions {
21
23
  * are rejected and fall back to space.
22
24
  */
23
25
  fillChar?: string;
24
- /** Bijou context for I/O, styling, and mode detection. */
25
- ctx?: BijouContext;
26
26
  }
27
27
  /**
28
28
  * Render content inside a bordered box.
@@ -55,4 +55,11 @@ export interface HeaderBoxOptions extends BoxOptions {
55
55
  * @returns The rendered header box string.
56
56
  */
57
57
  export declare function headerBox(label: string, options?: HeaderBoxOptions): string;
58
+ /**
59
+ * Validate and resolve a fill character option.
60
+ *
61
+ * Returns the character if it is a single-width grapheme cluster,
62
+ * otherwise falls back to a space.
63
+ */
64
+ export declare function resolveFillChar(fillChar: string | undefined): string;
58
65
  //# sourceMappingURL=box.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../../src/core/components/box.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,oFAAoF;IACpF,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,0EAA0E;IAC1E,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AA4ED;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAuBrE;AAED,4FAA4F;AAC5F,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAqB/E"}
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../../src/core/components/box.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,kDAAkD;AAClD,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IAClD,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,oFAAoF;IACpF,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,0EAA0E;IAC1E,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAwGD;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CA2BrE;AAED,4FAA4F;AAC5F,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAqB/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIpE"}
@@ -2,15 +2,17 @@ import { resolveCtx } from '../resolve-ctx.js';
2
2
  import { makeBgFill } from '../bg-fill.js';
3
3
  import { graphemeWidth } from '../text/grapheme.js';
4
4
  import { clipToWidth } from '../text/clip.js';
5
+ import { wrapToWidth } from '../text/wrap.js';
5
6
  import { renderByMode } from '../mode-render.js';
7
+ import { resolveOverflowBehavior } from './overflow.js';
6
8
  /** Unicode box-drawing characters for single-line borders. */
7
9
  const BORDER = { tl: '\u250c', tr: '\u2510', bl: '\u2514', br: '\u2518', h: '\u2500', v: '\u2502' };
8
10
  /**
9
11
  * Draw a unicode box around the given content string.
10
12
  *
11
13
  * Supports both auto-width (measured from content) and fixed-width modes.
12
- * Content lines wider than the available space are hard-truncated via
13
- * `clipToWidth` (no ellipsis is appended).
14
+ * Content lines wider than the available space wrap by default. Set
15
+ * `overflow: 'truncate'` to preserve the previous hard-clipping behavior.
14
16
  *
15
17
  * @param content - Multiline string to place inside the box.
16
18
  * @param borderColor - Function that wraps border characters with color styling.
@@ -18,10 +20,11 @@ const BORDER = { tl: '\u250c', tr: '\u2510', bl: '\u2514', br: '\u2518', h: '\u2
18
20
  * @param fixedWidth - If provided, lock the outer width and clip/pad content to fit.
19
21
  * @param bgFill - Optional function to wrap interior content with background color styling.
20
22
  * @param fillChar - Single-width character for padding areas (defaults to space).
23
+ * @param title - Optional title displayed in the top border.
21
24
  * @returns The rendered box as a multiline string.
22
25
  */
23
- function drawBox(content, borderColor, padding, fixedWidth, bgFill, fillChar = ' ') {
24
- const contentLines = content.split('\n');
26
+ function drawBox(content, borderColor, padding, fixedWidth, bgFill, fillChar = ' ', title, overflow = 'wrap') {
27
+ const rawContentLines = content.split('\n');
25
28
  let innerWidth;
26
29
  let contentWidth;
27
30
  if (fixedWidth !== undefined) {
@@ -31,13 +34,17 @@ function drawBox(content, borderColor, padding, fixedWidth, bgFill, fillChar = '
31
34
  }
32
35
  else {
33
36
  // Auto width: measure content
34
- const maxWidth = contentLines.reduce((max, line) => Math.max(max, graphemeWidth(line)), 0);
37
+ const titleWidth = title ? graphemeWidth(title) + 2 : 0;
38
+ const maxWidth = rawContentLines.reduce((max, line) => Math.max(max, graphemeWidth(line)), 0);
35
39
  contentWidth = maxWidth;
36
- innerWidth = maxWidth + padding.left + padding.right;
40
+ innerWidth = Math.max(titleWidth, maxWidth + padding.left + padding.right);
37
41
  }
38
42
  // When fixed width, padding may exceed innerWidth — clamp to fit
39
43
  const effectiveLeft = fixedWidth !== undefined ? Math.min(padding.left, innerWidth) : padding.left;
40
44
  const effectiveRight = fixedWidth !== undefined ? Math.min(padding.right, Math.max(0, innerWidth - effectiveLeft)) : padding.right;
45
+ const contentLines = fixedWidth !== undefined && overflow === 'wrap'
46
+ ? rawContentLines.flatMap((line) => wrapToWidth(line, contentWidth))
47
+ : rawContentLines;
41
48
  const pad = (line) => {
42
49
  const visible = graphemeWidth(line);
43
50
  let processed = line;
@@ -50,7 +57,27 @@ function drawBox(content, borderColor, padding, fixedWidth, bgFill, fillChar = '
50
57
  return leftPad + processed + rightPad;
51
58
  };
52
59
  const fill = bgFill ?? ((s) => s);
53
- const top = borderColor(BORDER.tl + BORDER.h.repeat(innerWidth) + BORDER.tr);
60
+ // Render top border with optional title
61
+ let topBorder = BORDER.h.repeat(innerWidth);
62
+ if (title && innerWidth >= 4) {
63
+ const label = ` ${title} `;
64
+ const labelWidth = graphemeWidth(label);
65
+ if (labelWidth <= innerWidth - 2) {
66
+ const start = 1;
67
+ const before = BORDER.h.repeat(start);
68
+ const after = BORDER.h.repeat(innerWidth - start - labelWidth);
69
+ topBorder = before + label + after;
70
+ }
71
+ else {
72
+ // Title too long, clip it
73
+ const clippedLabel = clipToWidth(label, innerWidth - 2);
74
+ const start = 1;
75
+ const before = BORDER.h.repeat(start);
76
+ const after = BORDER.h.repeat(innerWidth - start - graphemeWidth(clippedLabel));
77
+ topBorder = before + clippedLabel + after;
78
+ }
79
+ }
80
+ const top = borderColor(BORDER.tl + topBorder + BORDER.tr);
54
81
  const bottom = borderColor(BORDER.bl + BORDER.h.repeat(innerWidth) + BORDER.br);
55
82
  const emptyLine = borderColor(BORDER.v) + fill(fillChar.repeat(innerWidth)) + borderColor(BORDER.v);
56
83
  const lines = [top];
@@ -92,7 +119,8 @@ export function box(content, options = {}) {
92
119
  const colorize = (s) => ctx.style.styled(borderToken, s);
93
120
  const bgFill = makeBgFill(options.bgToken, ctx);
94
121
  const resolvedFill = resolveFillChar(options.fillChar);
95
- return drawBox(safeContent, colorize, padding, options.width, bgFill, resolvedFill);
122
+ const overflow = resolveOverflowBehavior(options.overflow, ctx.resolveBCSS({ type: 'Box', id: options.id, classes: options.class?.split(' ') }));
123
+ return drawBox(safeContent, colorize, padding, options.width, bgFill, resolvedFill, options.title, overflow);
96
124
  },
97
125
  }, options);
98
126
  }
@@ -133,7 +161,7 @@ export function headerBox(label, options = {}) {
133
161
  * Returns the character if it is a single-width grapheme cluster,
134
162
  * otherwise falls back to a space.
135
163
  */
136
- function resolveFillChar(fillChar) {
164
+ export function resolveFillChar(fillChar) {
137
165
  if (fillChar == null || fillChar.length === 0)
138
166
  return ' ';
139
167
  if (graphemeWidth(fillChar) !== 1)