@danypops/pi-papyrus 0.45.4 → 0.45.6

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.
@@ -1,5 +1,6 @@
1
1
  import type { Theme } from "@earendil-works/pi-coding-agent";
2
- import { type Component, truncateToWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
2
+ import { type Component, truncateToWidth } from "@earendil-works/pi-tui";
3
+ import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
3
4
  import type { ArtifactToolDetails } from "./render-model.ts";
4
5
 
5
6
  const KIND_GLYPHS: Readonly<Record<string, string>> = {
@@ -92,33 +93,55 @@ export class ArtifactCard implements Component {
92
93
  this.invalidate();
93
94
  }
94
95
 
96
+ /** Every field as a labeled `Label: value` line (buildDetailLines), matching the same
97
+ * convention pi-tickets' issue-detail-view.ts already uses -- not bare stacked values. */
98
+ private fields(): DetailField[] {
99
+ const artifact = this.details.artifact;
100
+ const status = this.theme.fg(statusColor(artifact.status), `${statusGlyph(artifact.status)} ${artifact.status}`);
101
+ return [
102
+ { label: "Title", value: artifact.title },
103
+ { label: "Kind", value: `${kindGlyph(artifact.kind)} ${artifact.kind}` },
104
+ { label: "Status", value: status },
105
+ ...(this.expanded ? [{ label: "ID", value: artifact.id }] : []),
106
+ ...(this.expanded && artifact.subtype ? [{ label: "Subtype", value: artifact.subtype }] : []),
107
+ ...(this.expanded && artifact.labels.length > 0 ? [{ label: "Labels", value: artifact.labels.join(", ") }] : []),
108
+ ];
109
+ }
110
+
111
+ private sections(): DetailSection[] {
112
+ if (!this.expanded) return [];
113
+ const sections: DetailSection[] = [];
114
+ const artifact = this.details.artifact;
115
+ if (artifact.body) sections.push({ heading: "Body:", body: artifact.body });
116
+ if (this.details.completeness.truncated) {
117
+ sections.push({ lines: [`[truncated ${this.details.completeness.omitted} characters]`] });
118
+ }
119
+ return sections;
120
+ }
121
+
95
122
  render(width: number): string[] {
96
123
  const safeWidth = Math.max(1, width);
97
124
  if (this.cachedLines && this.cachedWidth === safeWidth) return this.cachedLines;
98
125
 
99
- const artifact = this.details.artifact;
100
- const status = `${statusGlyph(artifact.status)} ${artifact.status}`;
101
- const header = [
102
- this.theme.fg("toolTitle", this.theme.bold(`${kindGlyph(artifact.kind)} ${artifact.kind.toUpperCase()}`)),
103
- ...(this.expanded ? [this.theme.fg("accent", artifact.id)] : []),
104
- this.theme.fg(statusColor(artifact.status), status),
105
- ].join(" ");
106
- const lines = [truncateToWidth(header, safeWidth)];
107
- lines.push(truncateToWidth(this.theme.fg("text", artifact.title), safeWidth));
126
+ const theme = this.theme;
127
+ const lines = buildDetailLines(safeWidth, {
128
+ fields: this.fields(),
129
+ sections: this.sections(),
130
+ alignFields: true,
131
+ theme: {
132
+ field: (s) => theme.fg("text", s),
133
+ heading: (s) => theme.fg("toolTitle", theme.bold(s)),
134
+ byline: (s) => theme.fg("muted", s),
135
+ body: (s) => theme.fg("text", s),
136
+ line: (s) => theme.fg("warning", s),
137
+ },
138
+ });
108
139
 
109
140
  if (this.details.focus) {
110
- lines.push(truncateToWidth(focusLine(this.details.focus, this.theme), safeWidth));
141
+ lines.push(truncateToWidth(focusLine(this.details.focus, theme), safeWidth));
111
142
  }
112
-
113
- if (this.expanded) {
114
- const metadata = [artifact.subtype, ...artifact.labels].filter(Boolean).join(" · ");
115
- if (metadata) lines.push(truncateToWidth(this.theme.fg("muted", metadata), safeWidth));
116
- if (artifact.body) lines.push(...wrapTextWithAnsi(artifact.body, safeWidth));
117
- if (this.details.completeness.truncated) {
118
- lines.push(truncateToWidth(this.theme.fg("warning", `[truncated ${this.details.completeness.omitted} characters]`), safeWidth));
119
- }
120
- } else if (artifact.body || artifact.labels.length > 0) {
121
- lines.push(truncateToWidth(this.theme.fg("dim", expandHint()), safeWidth));
143
+ if (!this.expanded && (this.details.artifact.body || this.details.artifact.labels.length > 0)) {
144
+ lines.push(truncateToWidth(theme.fg("dim", expandHint()), safeWidth));
122
145
  }
123
146
 
124
147
  this.cachedWidth = safeWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-papyrus",
3
- "version": "0.45.4",
3
+ "version": "0.45.6",
4
4
  "description": "Pi host extension for Papyrus: native tools, TUI panels, and context injection over the daemon-backed graph store",
5
5
  "type": "module",
6
6
  "keywords": ["pi-package"],
@@ -20,11 +20,11 @@
20
20
  "@danypops/jittor": "^0.14.0",
21
21
  "@danypops/papyrus": "^0.44.0",
22
22
  "@danypops/vehicle-client": "^0.5.0",
23
- "@danypops/vehicle-client-pi": "^0.16.7",
23
+ "@danypops/vehicle-client-pi": "^0.16.8",
24
24
  "@danypops/vehicle-core": "^0.10.0",
25
25
  "@danypops/vehicle-server": "^0.13.0",
26
26
  "beautiful-mermaid": "1.1.3",
27
- "malevich-tui-components": "^0.20.3"
27
+ "malevich-tui-components": "^0.21.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@danypops/pi-tui-harness": "^0.0.2",