@tangle-network/ui 11.16.8 → 11.16.10

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.16.10
4
+
5
+ ### Patch Changes
6
+
7
+ - 06b665d: A closed terminal command is two lines of plain text that end in an ellipsis when cut, with the whole command in its title, so a reader can see that text is missing. Terminal output wraps on every width again: scrolling it sideways on a phone clipped columns with no sign that more was there.
8
+
9
+ ## 11.16.9
10
+
11
+ ### Patch Changes
12
+
13
+ - 272704e: On a phone, terminal output keeps its own lines and scrolls sideways inside the block, so listing columns stay aligned and hashes and URLs are not split mid-token. A closed command shows at most two lines at every width.
14
+
3
15
  ## 11.16.8
4
16
 
5
17
  ### Patch Changes
@@ -138,20 +138,12 @@ function ExitBadge({ output, status }) {
138
138
  children: label
139
139
  });
140
140
  }
141
- /**
142
- * A command split at its whitespace, each token in an inline box. Browsers
143
- * break after a hyphen, which split `--short` into `--` and `short` on a
144
- * phone. A box moves to the next line whole, and breaks inside only when it
145
- * is wider than the line (a full SHA). The text is unchanged, so a copy still
146
- * pastes the exact command.
147
- */
148
- function CommandText({ command, all }) {
141
+ function CommandText({ command }) {
149
142
  const tokens = command.split(/(\s+)/);
150
- const limit = all ? tokens.length : 128;
151
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [tokens.slice(0, limit).map((token, i) => token.length > 0 && !/\s/.test(token) ? /* @__PURE__ */ jsx("span", {
143
+ return /* @__PURE__ */ jsx(Fragment$1, { children: tokens.map((token, i) => token.length > 0 && !/\s/.test(token) ? /* @__PURE__ */ jsx("span", {
152
144
  className: "inline-block max-w-full [overflow-wrap:anywhere]",
153
145
  children: token
154
- }, i) : token), limit < tokens.length ? tokens.slice(limit).join("") : null] });
146
+ }, i) : token) });
155
147
  }
156
148
  /**
157
149
  * One shell command as a terminal block: a `$ command` prompt line with its
@@ -179,11 +171,9 @@ const CommandPreview = memo(({ part, defaultExpanded = false, className }) => {
179
171
  children: "$"
180
172
  }),
181
173
  /* @__PURE__ */ jsx("code", {
174
+ title: expanded ? void 0 : command,
182
175
  className: cn("min-w-0 flex-1 whitespace-pre-wrap [overflow-wrap:anywhere]", expanded ? "" : "line-clamp-2"),
183
- children: /* @__PURE__ */ jsx(CommandText, {
184
- command,
185
- all: expanded
186
- })
176
+ children: expanded ? /* @__PURE__ */ jsx(CommandText, { command }) : command
187
177
  }),
188
178
  /* @__PURE__ */ jsx("span", {
189
179
  className: "flex shrink-0 max-sm:order-last max-sm:basis-full max-sm:pl-4",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.16.8",
3
+ "version": "11.16.10",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,8 +30,9 @@ describe("CommandPreview", () => {
30
30
  expect(screen.getByText("exit 2").className).toContain("surface-danger");
31
31
  });
32
32
 
33
- it("boxes each token so a phone wraps between flags", () => {
33
+ it("boxes each token of an opened command so a phone wraps between flags", () => {
34
34
  render(<CommandPreview part={part({ output: "M a" })} />);
35
+ fireEvent.click(screen.getByRole("button"));
35
36
  const flag = screen.getByText("--short");
36
37
  expect(flag.tagName).toBe("SPAN");
37
38
  expect(flag.className).toContain("inline-block");
@@ -61,6 +62,14 @@ describe("CommandPreview", () => {
61
62
  expect(screen.getByText("exit 0 · tool reported error").className).toContain("surface-warning");
62
63
  });
63
64
 
65
+ it("shows a closed command as plain text that ends in an ellipsis, whole in its title", () => {
66
+ render(<CommandPreview part={part({ output: "M a" })} />);
67
+ const code = screen.getByTestId("command-preview").querySelector("code");
68
+ expect(code?.className).toContain("line-clamp-2");
69
+ expect(code).toHaveAttribute("title", "git status --short");
70
+ expect(code?.querySelector("span")).toBeNull();
71
+ });
72
+
64
73
  it("is a quiet row until opened, then a dark terminal", () => {
65
74
  render(<CommandPreview part={part({ output: "M a" })} />);
66
75
  const block = screen.getByTestId("command-preview");
@@ -187,23 +187,11 @@ function ExitBadge({
187
187
  );
188
188
  }
189
189
 
190
- /** A closed row shows two lines, so only its first tokens need their own
191
- * box; a long script renders the rest as plain text. */
192
- const BOXED_TOKENS = 64;
193
-
194
- /**
195
- * A command split at its whitespace, each token in an inline box. Browsers
196
- * break after a hyphen, which split `--short` into `--` and `short` on a
197
- * phone. A box moves to the next line whole, and breaks inside only when it
198
- * is wider than the line (a full SHA). The text is unchanged, so a copy still
199
- * pastes the exact command.
200
- */
201
- function CommandText({ command, all }: { command: string; all: boolean }) {
190
+ function CommandText({ command }: { command: string }) {
202
191
  const tokens = command.split(/(\s+)/);
203
- const limit = all ? tokens.length : BOXED_TOKENS * 2;
204
192
  return (
205
193
  <>
206
- {tokens.slice(0, limit).map((token, i) =>
194
+ {tokens.map((token, i) =>
207
195
  token.length > 0 && !/\s/.test(token) ? (
208
196
  // Tokens repeat (two spaces, two "&&"), so position is the key.
209
197
  <span key={i} className="inline-block max-w-full [overflow-wrap:anywhere]">
@@ -213,7 +201,6 @@ function CommandText({ command, all }: { command: string; all: boolean }) {
213
201
  token
214
202
  ),
215
203
  )}
216
- {limit < tokens.length ? tokens.slice(limit).join("") : null}
217
204
  </>
218
205
  );
219
206
  }
@@ -256,12 +243,16 @@ export const CommandPreview = memo(
256
243
  $
257
244
  </span>
258
245
  <code
246
+ title={expanded ? undefined : command}
259
247
  className={cn(
260
248
  "min-w-0 flex-1 whitespace-pre-wrap [overflow-wrap:anywhere]",
249
+ // Closed, two lines of plain text that end in an ellipsis when
250
+ // cut, with the whole command in the title. Opened, each token
251
+ // is a box that wraps whole (line-clamp does not count boxes).
261
252
  expanded ? "" : "line-clamp-2",
262
253
  )}
263
254
  >
264
- <CommandText command={command} all={expanded} />
255
+ {expanded ? <CommandText command={command} /> : command}
265
256
  </code>
266
257
  {/* On a phone the badge takes its own line under the command, so the
267
258
  command keeps the row's width. */}