@cleocode/animations 2026.5.105 → 2026.5.107

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.
@@ -19,6 +19,7 @@
19
19
  export { type AnimateContext, type AnimateContextInput, createAnimateContext, type FlagResolutionLike, SILENT_CONTEXT, } from './animate-context.js';
20
20
  export { type BrailleSpinnerName, CANON_TO_GENERIC, type CanonSpinnerName, canonSpinners, default, gridToBraille, makeGrid, resolveSpinner, type Spinner, spinners, } from './braille.js';
21
21
  export { type ProgressBarRenderer, type ProgressBarStyle, progressBars, renderProgressBar, } from './progress.js';
22
+ export { type LegendItem, type RenderBadgeOptions, type RenderLegendInput, type RenderSectionInput, type RenderSummaryInput, type RenderTableOptions, type RenderTreeViewOptions, renderBadge, renderLegend, renderSection, renderStatusBadge, renderSummary, renderTable, renderTree, type StatusBadgeName, type SummaryCount, } from './render/index.js';
22
23
  export { type Spark, type SparkName, sparkDurationMs, sparks } from './spark.js';
23
24
  export { createSpinnerHandle, type SpinnerHandle, type SpinnerHandleOptions, } from './spinner-handle.js';
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,aAAa,EACb,OAAO,EACP,aAAa,EACb,QAAQ,EACR,cAAc,EACd,KAAK,OAAO,EACZ,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,YAAY,EACZ,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGjF,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,kBAAkB,EACvB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,aAAa,EACb,OAAO,EACP,aAAa,EACb,QAAQ,EACR,cAAc,EACd,KAAK,OAAO,EACZ,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,YAAY,EACZ,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,WAAW,EACX,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC"}
package/dist/src/index.js CHANGED
@@ -22,6 +22,8 @@ export { createAnimateContext, SILENT_CONTEXT, } from './animate-context.js';
22
22
  export { CANON_TO_GENERIC, canonSpinners, default, gridToBraille, makeGrid, resolveSpinner, spinners, } from './braille.js';
23
23
  // === Progress bars ===
24
24
  export { progressBars, renderProgressBar, } from './progress.js';
25
+ // === Static UI primitives (T10128 — tree, table, section, badge, legend) ===
26
+ export { renderBadge, renderLegend, renderSection, renderStatusBadge, renderSummary, renderTable, renderTree, } from './render/index.js';
25
27
  // === Sparks (one-shot accents) ===
26
28
  export { sparkDurationMs, sparks } from './spark.js';
27
29
  // === Spinner handle (canonical owner of \r writes) ===
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,kDAAkD;AAClD,OAAO,EAGL,oBAAoB,EAEpB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,mBAAmB;AACnB,OAAO,EAEL,gBAAgB,EAEhB,aAAa,EACb,OAAO,EACP,aAAa,EACb,QAAQ,EACR,cAAc,EAEd,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,wBAAwB;AACxB,OAAO,EAGL,YAAY,EACZ,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,oCAAoC;AACpC,OAAO,EAA8B,eAAe,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEjF,wDAAwD;AACxD,OAAO,EACL,mBAAmB,GAGpB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,kDAAkD;AAClD,OAAO,EAGL,oBAAoB,EAEpB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,mBAAmB;AACnB,OAAO,EAEL,gBAAgB,EAEhB,aAAa,EACb,OAAO,EACP,aAAa,EACb,QAAQ,EACR,cAAc,EAEd,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,wBAAwB;AACxB,OAAO,EAGL,YAAY,EACZ,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,8EAA8E;AAC9E,OAAO,EAQL,WAAW,EACX,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,UAAU,GAGX,MAAM,mBAAmB,CAAC;AAC3B,oCAAoC;AACpC,OAAO,EAA8B,eAAe,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACjF,wDAAwD;AACxD,OAAO,EACL,mBAAmB,GAGpB,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Static badge rendering — single-icon glyphs with ASCII fallback.
3
+ *
4
+ * @remarks
5
+ * Part of the Human Render Contract (Epic T10114, ADR-077). Every CLI status,
6
+ * kind, badge, or relation glyph that surfaces in `--human` mode flows through
7
+ * one of these two helpers. The {@link AnimateContext} gate guarantees JSON /
8
+ * quiet / non-TTY / NO_COLOR outputs emit nothing, mirroring the silence
9
+ * contract enforced by {@link createSpinnerHandle}.
10
+ *
11
+ * @epic T10114
12
+ * @task T10128
13
+ * @subtask T10145
14
+ */
15
+ import { type BadgeIcon, type KindIcon, type RelationIcon, StatusIcon } from '@cleocode/contracts/render/icon.js';
16
+ import type { AnimateContext } from '../animate-context.js';
17
+ /**
18
+ * Common options for badge rendering.
19
+ *
20
+ * @remarks
21
+ * `ascii` is an explicit override. When omitted the helper falls back to
22
+ * `ctx.inputs.noColor` so callers can simply thread the context through.
23
+ */
24
+ export interface RenderBadgeOptions {
25
+ /** Render gate — primitive returns `''` when `enabled === false`. */
26
+ readonly ctx: AnimateContext;
27
+ /**
28
+ * When `true`, force the ASCII fallback regardless of the context's
29
+ * `noColor` signal. When `false`, force the emoji form. When omitted,
30
+ * defer to `ctx.inputs.noColor`.
31
+ */
32
+ readonly ascii?: boolean;
33
+ }
34
+ /** Lifecycle status names accepted by {@link renderStatusBadge}. */
35
+ export type StatusBadgeName = 'pending' | 'in_progress' | 'done' | 'blocked' | 'cancelled' | 'archived';
36
+ /**
37
+ * Render a single icon as its emoji form or ASCII fallback.
38
+ *
39
+ * @param icon - Any member of {@link StatusIcon}, {@link KindIcon},
40
+ * {@link BadgeIcon}, or {@link RelationIcon}.
41
+ * @param opts - Render gate + optional ASCII override.
42
+ * @returns The emoji or ASCII glyph. Empty string when `opts.ctx.enabled` is `false`.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * renderBadge(StatusIcon.DONE, { ctx: enabledCtx }); // '✅'
47
+ * renderBadge(StatusIcon.DONE, { ctx: enabledCtx, ascii: true }); // '[x]'
48
+ * renderBadge(StatusIcon.DONE, { ctx: disabledCtx }); // ''
49
+ * ```
50
+ */
51
+ export declare function renderBadge(icon: StatusIcon | KindIcon | BadgeIcon | RelationIcon, opts: RenderBadgeOptions): string;
52
+ /**
53
+ * Render a lifecycle status string as a badge glyph.
54
+ *
55
+ * @param status - Canonical task status name (`'pending'`, `'in_progress'`, …).
56
+ * @param opts - Render gate + optional ASCII override.
57
+ * @returns The emoji or ASCII glyph for the status. Empty string when
58
+ * `opts.ctx.enabled` is `false`.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * renderStatusBadge('done', { ctx }); // '✅'
63
+ * renderStatusBadge('pending', { ctx: ascii }); // '[ ]'
64
+ * ```
65
+ */
66
+ export declare function renderStatusBadge(status: StatusBadgeName, opts: RenderBadgeOptions): string;
67
+ //# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/render/badge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,UAAU,EACX,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oEAAoE;AACpE,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,aAAa,GACb,MAAM,GACN,SAAS,GACT,WAAW,GACX,UAAU,CAAC;AAEf;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,EACtD,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAIR;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAE3F"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Static badge rendering — single-icon glyphs with ASCII fallback.
3
+ *
4
+ * @remarks
5
+ * Part of the Human Render Contract (Epic T10114, ADR-077). Every CLI status,
6
+ * kind, badge, or relation glyph that surfaces in `--human` mode flows through
7
+ * one of these two helpers. The {@link AnimateContext} gate guarantees JSON /
8
+ * quiet / non-TTY / NO_COLOR outputs emit nothing, mirroring the silence
9
+ * contract enforced by {@link createSpinnerHandle}.
10
+ *
11
+ * @epic T10114
12
+ * @task T10128
13
+ * @subtask T10145
14
+ */
15
+ import { ascii, StatusIcon, } from '@cleocode/contracts/render/icon.js';
16
+ /**
17
+ * Render a single icon as its emoji form or ASCII fallback.
18
+ *
19
+ * @param icon - Any member of {@link StatusIcon}, {@link KindIcon},
20
+ * {@link BadgeIcon}, or {@link RelationIcon}.
21
+ * @param opts - Render gate + optional ASCII override.
22
+ * @returns The emoji or ASCII glyph. Empty string when `opts.ctx.enabled` is `false`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * renderBadge(StatusIcon.DONE, { ctx: enabledCtx }); // '✅'
27
+ * renderBadge(StatusIcon.DONE, { ctx: enabledCtx, ascii: true }); // '[x]'
28
+ * renderBadge(StatusIcon.DONE, { ctx: disabledCtx }); // ''
29
+ * ```
30
+ */
31
+ export function renderBadge(icon, opts) {
32
+ if (!opts.ctx.enabled)
33
+ return '';
34
+ const useAscii = opts.ascii ?? opts.ctx.inputs.noColor;
35
+ return useAscii ? ascii(icon) : icon;
36
+ }
37
+ /** Internal mapping — lifecycle status name → canonical {@link StatusIcon}. */
38
+ const STATUS_NAME_TO_ICON = {
39
+ pending: StatusIcon.PENDING,
40
+ in_progress: StatusIcon.ACTIVE,
41
+ done: StatusIcon.DONE,
42
+ blocked: StatusIcon.BLOCKED,
43
+ cancelled: StatusIcon.CANCELLED,
44
+ archived: StatusIcon.ARCHIVED,
45
+ };
46
+ /**
47
+ * Render a lifecycle status string as a badge glyph.
48
+ *
49
+ * @param status - Canonical task status name (`'pending'`, `'in_progress'`, …).
50
+ * @param opts - Render gate + optional ASCII override.
51
+ * @returns The emoji or ASCII glyph for the status. Empty string when
52
+ * `opts.ctx.enabled` is `false`.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * renderStatusBadge('done', { ctx }); // '✅'
57
+ * renderStatusBadge('pending', { ctx: ascii }); // '[ ]'
58
+ * ```
59
+ */
60
+ export function renderStatusBadge(status, opts) {
61
+ return renderBadge(STATUS_NAME_TO_ICON[status], opts);
62
+ }
63
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../src/render/badge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,EAIL,UAAU,GACX,MAAM,oCAAoC,CAAC;AA8B5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,WAAW,CACzB,IAAsD,EACtD,IAAwB;IAExB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;IACvD,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED,+EAA+E;AAC/E,MAAM,mBAAmB,GAAkD;IACzE,OAAO,EAAE,UAAU,CAAC,OAAO;IAC3B,WAAW,EAAE,UAAU,CAAC,MAAM;IAC9B,IAAI,EAAE,UAAU,CAAC,IAAI;IACrB,OAAO,EAAE,UAAU,CAAC,OAAO;IAC3B,SAAS,EAAE,UAAU,CAAC,SAAS;IAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ;CAC9B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAuB,EAAE,IAAwB;IACjF,OAAO,WAAW,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Static UI primitives — tree, table, section, badge, legend.
3
+ *
4
+ * @remarks
5
+ * Companion to the spinner / progress / spark animations in this package.
6
+ * Every primitive is a pure function that returns a string and respects the
7
+ * {@link AnimateContext} gate — emitting `''` when the context is silent
8
+ * (JSON, quiet, no-TTY, NO_COLOR).
9
+ *
10
+ * Consumes typed contracts from `@cleocode/contracts/render/*` (Epic T10114,
11
+ * ADR-077) and icon enums from `@cleocode/contracts/render/icon.js`.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @packageDocumentation
16
+ */
17
+ export { type RenderBadgeOptions, renderBadge, renderStatusBadge, type StatusBadgeName, } from './badge.js';
18
+ export { type LegendItem, type RenderLegendInput, type RenderSummaryInput, renderLegend, renderSummary, type SummaryCount, } from './legend.js';
19
+ export { type RenderSectionInput, renderSection, } from './section.js';
20
+ export { type RenderTableOptions, renderTable, } from './table.js';
21
+ export { type RenderTreeViewOptions, renderTree, } from './tree.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,KAAK,kBAAkB,EACvB,WAAW,EACX,iBAAiB,EACjB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,YAAY,EACZ,aAAa,EACb,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,kBAAkB,EACvB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,kBAAkB,EACvB,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,qBAAqB,EAC1B,UAAU,GACX,MAAM,WAAW,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Static UI primitives — tree, table, section, badge, legend.
3
+ *
4
+ * @remarks
5
+ * Companion to the spinner / progress / spark animations in this package.
6
+ * Every primitive is a pure function that returns a string and respects the
7
+ * {@link AnimateContext} gate — emitting `''` when the context is silent
8
+ * (JSON, quiet, no-TTY, NO_COLOR).
9
+ *
10
+ * Consumes typed contracts from `@cleocode/contracts/render/*` (Epic T10114,
11
+ * ADR-077) and icon enums from `@cleocode/contracts/render/icon.js`.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @packageDocumentation
16
+ */
17
+ export { renderBadge, renderStatusBadge, } from './badge.js';
18
+ export { renderLegend, renderSummary, } from './legend.js';
19
+ export { renderSection, } from './section.js';
20
+ export { renderTable, } from './table.js';
21
+ export { renderTree, } from './tree.js';
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAEL,WAAW,EACX,iBAAiB,GAElB,MAAM,YAAY,CAAC;AACpB,OAAO,EAIL,YAAY,EACZ,aAAa,GAEd,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,UAAU,GACX,MAAM,WAAW,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Legend and summary footer rendering.
3
+ *
4
+ * @remarks
5
+ * `renderLegend` produces a compact glossary mapping icons to labels — e.g.
6
+ * `✅ done 🚧 active ⏳ pending` — that complements a tree, table, or list.
7
+ * `renderSummary` produces a one-line aggregate footer such as
8
+ * `15 Sagas · 89 member Epics · 1 orphan`.
9
+ *
10
+ * Both helpers honor the {@link AnimateContext} gate and emit the empty string
11
+ * when rendering is disabled.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @subtask T10146
16
+ */
17
+ import type { AnimateContext } from '../animate-context.js';
18
+ /** One legend entry — icon glyph + plain-text label. */
19
+ export interface LegendItem {
20
+ /** Pre-resolved icon glyph (caller is responsible for ASCII selection). */
21
+ readonly icon: string;
22
+ /** Plain-text label rendered after the icon. */
23
+ readonly label: string;
24
+ }
25
+ /** Inputs to {@link renderLegend}. */
26
+ export interface RenderLegendInput {
27
+ /** Icon → label pairs rendered in order. */
28
+ readonly items: ReadonlyArray<LegendItem>;
29
+ /** Render gate — primitive returns `''` when `enabled === false`. */
30
+ readonly ctx: AnimateContext;
31
+ /**
32
+ * When the item count is `<=` this threshold the legend renders as a single
33
+ * line; above it the legend renders one item per line. Defaults to `8`.
34
+ */
35
+ readonly multiLineThreshold?: number;
36
+ }
37
+ /**
38
+ * Render an icon legend — one-line for small counts, multi-line otherwise.
39
+ *
40
+ * @param input - Legend items, render gate, and optional threshold.
41
+ * @returns The formatted legend string. Empty when `input.ctx.enabled` is `false`
42
+ * or `input.items` is empty.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * renderLegend({
47
+ * ctx,
48
+ * items: [
49
+ * { icon: '✅', label: 'done' },
50
+ * { icon: '🚧', label: 'active' },
51
+ * { icon: '⏳', label: 'pending' },
52
+ * ],
53
+ * });
54
+ * // → '✅ done 🚧 active ⏳ pending'
55
+ * ```
56
+ */
57
+ export declare function renderLegend(input: RenderLegendInput): string;
58
+ /** One aggregate count cell in {@link renderSummary}. */
59
+ export interface SummaryCount {
60
+ /** Human-readable label (e.g. `'Sagas'`, `'member Epics'`). */
61
+ readonly label: string;
62
+ /** Numeric count rendered before the label. */
63
+ readonly n: number;
64
+ }
65
+ /** Inputs to {@link renderSummary}. */
66
+ export interface RenderSummaryInput {
67
+ /** Counts rendered left-to-right, separated by middle dots. */
68
+ readonly counts: ReadonlyArray<SummaryCount>;
69
+ /** Render gate — primitive returns `''` when `enabled === false`. */
70
+ readonly ctx: AnimateContext;
71
+ }
72
+ /**
73
+ * Render a one-line aggregate summary footer.
74
+ *
75
+ * @param input - Counts to render and the gate context.
76
+ * @returns The formatted summary string. Empty when `input.ctx.enabled` is `false`
77
+ * or `input.counts` is empty.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * renderSummary({
82
+ * ctx,
83
+ * counts: [
84
+ * { label: 'Sagas', n: 15 },
85
+ * { label: 'member Epics', n: 89 },
86
+ * { label: 'orphan', n: 1 },
87
+ * ],
88
+ * });
89
+ * // → '15 Sagas · 89 member Epics · 1 orphan'
90
+ * ```
91
+ */
92
+ export declare function renderSummary(input: RenderSummaryInput): string;
93
+ //# sourceMappingURL=legend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legend.d.ts","sourceRoot":"","sources":["../../../src/render/legend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,wDAAwD;AACxD,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAW7D;AAED,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAC7C,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAM/D"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Legend and summary footer rendering.
3
+ *
4
+ * @remarks
5
+ * `renderLegend` produces a compact glossary mapping icons to labels — e.g.
6
+ * `✅ done 🚧 active ⏳ pending` — that complements a tree, table, or list.
7
+ * `renderSummary` produces a one-line aggregate footer such as
8
+ * `15 Sagas · 89 member Epics · 1 orphan`.
9
+ *
10
+ * Both helpers honor the {@link AnimateContext} gate and emit the empty string
11
+ * when rendering is disabled.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @subtask T10146
16
+ */
17
+ /** Default item count above which {@link renderLegend} emits multi-line output. */
18
+ const DEFAULT_MULTILINE_THRESHOLD = 8;
19
+ /** Middle-dot separator used in summaries (U+00B7). */
20
+ const SUMMARY_SEPARATOR = ' · ';
21
+ /** ASCII fallback separator used when the context is in `no-color` mode. */
22
+ const SUMMARY_SEPARATOR_ASCII = ' | ';
23
+ /**
24
+ * Render an icon legend — one-line for small counts, multi-line otherwise.
25
+ *
26
+ * @param input - Legend items, render gate, and optional threshold.
27
+ * @returns The formatted legend string. Empty when `input.ctx.enabled` is `false`
28
+ * or `input.items` is empty.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * renderLegend({
33
+ * ctx,
34
+ * items: [
35
+ * { icon: '✅', label: 'done' },
36
+ * { icon: '🚧', label: 'active' },
37
+ * { icon: '⏳', label: 'pending' },
38
+ * ],
39
+ * });
40
+ * // → '✅ done 🚧 active ⏳ pending'
41
+ * ```
42
+ */
43
+ export function renderLegend(input) {
44
+ if (!input.ctx.enabled)
45
+ return '';
46
+ if (input.items.length === 0)
47
+ return '';
48
+ const threshold = input.multiLineThreshold ?? DEFAULT_MULTILINE_THRESHOLD;
49
+ const formatted = input.items.map((item) => `${item.icon} ${item.label}`);
50
+ if (input.items.length <= threshold) {
51
+ return formatted.join(' ');
52
+ }
53
+ return formatted.join('\n');
54
+ }
55
+ /**
56
+ * Render a one-line aggregate summary footer.
57
+ *
58
+ * @param input - Counts to render and the gate context.
59
+ * @returns The formatted summary string. Empty when `input.ctx.enabled` is `false`
60
+ * or `input.counts` is empty.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * renderSummary({
65
+ * ctx,
66
+ * counts: [
67
+ * { label: 'Sagas', n: 15 },
68
+ * { label: 'member Epics', n: 89 },
69
+ * { label: 'orphan', n: 1 },
70
+ * ],
71
+ * });
72
+ * // → '15 Sagas · 89 member Epics · 1 orphan'
73
+ * ```
74
+ */
75
+ export function renderSummary(input) {
76
+ if (!input.ctx.enabled)
77
+ return '';
78
+ if (input.counts.length === 0)
79
+ return '';
80
+ const separator = input.ctx.inputs.noColor ? SUMMARY_SEPARATOR_ASCII : SUMMARY_SEPARATOR;
81
+ return input.counts.map((c) => `${c.n} ${c.label}`).join(separator);
82
+ }
83
+ //# sourceMappingURL=legend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legend.js","sourceRoot":"","sources":["../../../src/render/legend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,mFAAmF;AACnF,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAEtC,uDAAuD;AACvD,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC,4EAA4E;AAC5E,MAAM,uBAAuB,GAAG,KAAK,CAAC;AAuBtC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,MAAM,SAAS,GAAG,KAAK,CAAC,kBAAkB,IAAI,2BAA2B,CAAC;IAC1E,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAE1E,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAkBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACzF,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Static section rendering — header (optional icon + subtitle) over indented items.
3
+ *
4
+ * @remarks
5
+ * Part of the Human Render Contract (Epic T10114, ADR-077). Sections are the
6
+ * canonical "labelled block" presenter — used for `cleo saga show` deviation
7
+ * lists, doctor reports, and similar ad-hoc human output. Items are
8
+ * pre-formatted; this primitive only owns the header + indentation.
9
+ *
10
+ * Section bodies are indented by 2 spaces. An empty `items` array renders only
11
+ * the header line.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @subtask T10144
16
+ */
17
+ import type { AnimateContext } from '../animate-context.js';
18
+ /** Inputs to {@link renderSection}. */
19
+ export interface RenderSectionInput {
20
+ /**
21
+ * Optional leading glyph (emoji or ASCII). Caller picks the right form for
22
+ * the active terminal — this primitive renders it verbatim.
23
+ */
24
+ readonly icon?: string;
25
+ /** Section heading rendered on the first line. */
26
+ readonly header: string;
27
+ /** Optional subtitle appended after the header with an em-dash separator. */
28
+ readonly subtitle?: string;
29
+ /** Pre-formatted item strings rendered as an indented block. */
30
+ readonly items: ReadonlyArray<string>;
31
+ /** Render gate — primitive returns `''` when `enabled === false`. */
32
+ readonly ctx: AnimateContext;
33
+ }
34
+ /**
35
+ * Render a section block — header line plus indented items.
36
+ *
37
+ * @param input - Header text, optional icon/subtitle, items, and gate context.
38
+ * @returns A multi-line string. Empty when `input.ctx.enabled` is `false`.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * renderSection({
43
+ * ctx,
44
+ * icon: '✅',
45
+ * header: 'DONE',
46
+ * subtitle: '3 epics shipped',
47
+ * items: ['T9832 contracts foundation', 'T9836 test helpers', 'T9837 SSoT enforcement'],
48
+ * });
49
+ * // ✅ DONE — 3 epics shipped
50
+ * // T9832 contracts foundation
51
+ * // T9836 test helpers
52
+ * // T9837 SSoT enforcement
53
+ * ```
54
+ */
55
+ export declare function renderSection(input: RenderSectionInput): string;
56
+ //# sourceMappingURL=section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section.d.ts","sourceRoot":"","sources":["../../../src/render/section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B;AAQD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAgB/D"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Static section rendering — header (optional icon + subtitle) over indented items.
3
+ *
4
+ * @remarks
5
+ * Part of the Human Render Contract (Epic T10114, ADR-077). Sections are the
6
+ * canonical "labelled block" presenter — used for `cleo saga show` deviation
7
+ * lists, doctor reports, and similar ad-hoc human output. Items are
8
+ * pre-formatted; this primitive only owns the header + indentation.
9
+ *
10
+ * Section bodies are indented by 2 spaces. An empty `items` array renders only
11
+ * the header line.
12
+ *
13
+ * @epic T10114
14
+ * @task T10128
15
+ * @subtask T10144
16
+ */
17
+ /** Two-space indent applied to every item line. */
18
+ const ITEM_INDENT = ' ';
19
+ /** Em-dash separator between header and subtitle. */
20
+ const SUBTITLE_SEPARATOR = ' — ';
21
+ /**
22
+ * Render a section block — header line plus indented items.
23
+ *
24
+ * @param input - Header text, optional icon/subtitle, items, and gate context.
25
+ * @returns A multi-line string. Empty when `input.ctx.enabled` is `false`.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * renderSection({
30
+ * ctx,
31
+ * icon: '✅',
32
+ * header: 'DONE',
33
+ * subtitle: '3 epics shipped',
34
+ * items: ['T9832 contracts foundation', 'T9836 test helpers', 'T9837 SSoT enforcement'],
35
+ * });
36
+ * // ✅ DONE — 3 epics shipped
37
+ * // T9832 contracts foundation
38
+ * // T9836 test helpers
39
+ * // T9837 SSoT enforcement
40
+ * ```
41
+ */
42
+ export function renderSection(input) {
43
+ if (!input.ctx.enabled)
44
+ return '';
45
+ const iconPart = input.icon !== undefined && input.icon.length > 0 ? `${input.icon} ` : '';
46
+ const subtitlePart = input.subtitle !== undefined && input.subtitle.length > 0
47
+ ? `${SUBTITLE_SEPARATOR}${input.subtitle}`
48
+ : '';
49
+ const headerLine = `${iconPart}${input.header}${subtitlePart}`;
50
+ if (input.items.length === 0) {
51
+ return headerLine;
52
+ }
53
+ const itemLines = input.items.map((item) => `${ITEM_INDENT}${item}`);
54
+ return [headerLine, ...itemLines].join('\n');
55
+ }
56
+ //# sourceMappingURL=section.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section.js","sourceRoot":"","sources":["../../../src/render/section.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAqBH,mDAAmD;AACnD,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB,qDAAqD;AACrD,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,MAAM,YAAY,GAChB,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACvD,CAAC,CAAC,GAAG,kBAAkB,GAAG,KAAK,CAAC,QAAQ,EAAE;QAC1C,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,UAAU,GAAG,GAAG,QAAQ,GAAG,KAAK,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;IAE/D,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC,CAAC;IACrE,OAAO,CAAC,UAAU,EAAE,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Static table rendering — column-aligned rows with terminal-width awareness.
3
+ *
4
+ * @remarks
5
+ * Part of the Human Render Contract (Epic T10114, ADR-077). Consumes a typed
6
+ * {@link TableResponse} (schema + rows + total) and emits an aligned monospace
7
+ * table that fits within the active terminal width. Wide string columns shrink
8
+ * proportionally when the total width exceeds the budget; narrow numeric
9
+ * columns are preserved.
10
+ *
11
+ * @epic T10114
12
+ * @task T10128
13
+ * @subtask T10143
14
+ */
15
+ import type { TableResponse } from '@cleocode/contracts/render/table.js';
16
+ import type { AnimateContext } from '../animate-context.js';
17
+ /** Options to {@link renderTable}. */
18
+ export interface RenderTableOptions {
19
+ /** Render gate — primitive returns `''` when `enabled === false`. */
20
+ readonly ctx: AnimateContext;
21
+ /**
22
+ * Maximum line width. Defaults to `process.stdout.columns` and falls back to
23
+ * `80` when the column count is unavailable. The renderer never produces a
24
+ * row longer than this.
25
+ */
26
+ readonly maxWidth?: number;
27
+ /**
28
+ * When `true`, force ASCII separator characters. When `false`, force the
29
+ * Unicode form. When omitted, defer to `ctx.inputs.noColor`.
30
+ */
31
+ readonly asciiBoxDrawing?: boolean;
32
+ }
33
+ /**
34
+ * Render a {@link TableResponse} as an aligned columnar string.
35
+ *
36
+ * @param resp - Typed table response (schema + rows + total).
37
+ * @param opts - Render gate + width / ASCII overrides.
38
+ * @returns Multi-line aligned table. Empty when `opts.ctx.enabled` is `false`.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * renderTable(
43
+ * {
44
+ * rows: [{ id: 'T1', title: 'Implement', status: 'done' }],
45
+ * schema: {
46
+ * columns: [
47
+ * { key: 'id', header: 'ID' },
48
+ * { key: 'title', header: 'Title' },
49
+ * { key: 'status', header: 'Status' },
50
+ * ],
51
+ * },
52
+ * total: 1,
53
+ * },
54
+ * { ctx },
55
+ * );
56
+ * ```
57
+ */
58
+ export declare function renderTable<T>(resp: TableResponse<T>, opts: RenderTableOptions): string;
59
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/render/table.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAmDvF"}