@tangle-network/ui 11.16.4 → 11.16.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.16.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 74fbea5: A closed terminal command is a quiet bordered row on the surface it sits on, and turns into the dark terminal only when opened, so a list of commands no longer reads as a stack of black bars. Red is kept for evidence the command failed: a nonzero exit, a timeout or a signal. A tool that reported an error with nothing recorded about the command shows a neutral "tool error" badge. A command wraps between its tokens, so `--short` is no longer split at its hyphen; a token wider than the line still breaks, and the copied text is unchanged. The status pill marks a failed state with a cross instead of a slashed disc, which read as "disabled".
8
+
9
+ ## 11.16.5
10
+
11
+ ### Patch Changes
12
+
13
+ - 44ce397: Let model tool-schema converters accept the OpenUI node schema: container `children` no longer declares a nonempty minimum, which formed a required recursive loop that opencode rejected for `render_ui`. The persistence gate still rejects an empty stack, grid, or card children list.
14
+
3
15
  ## 11.16.4
4
16
 
5
17
  ### Patch Changes
@@ -1592,7 +1592,6 @@ const schema33 = {
1592
1592
  "wrap": { "type": "boolean" },
1593
1593
  "children": {
1594
1594
  "type": "array",
1595
- "minItems": 1,
1596
1595
  "items": { "$ref": "#/$defs/node" }
1597
1596
  }
1598
1597
  },
@@ -1807,7 +1806,6 @@ const schema46 = {
1807
1806
  ] },
1808
1807
  "children": {
1809
1808
  "type": "array",
1810
- "minItems": 1,
1811
1809
  "items": { "$ref": "#/$defs/node" }
1812
1810
  }
1813
1811
  },
@@ -1909,30 +1907,19 @@ function validate27(data, { instancePath = "", parentData, parentDataProperty, r
1909
1907
  const _errs7 = errors;
1910
1908
  if (errors === _errs7) {
1911
1909
  if (Array.isArray(data4)) {
1912
- if (data4.length < 1) {
1913
- validate27.errors = [{
1914
- instancePath: instancePath + "/children",
1915
- schemaPath: "#/properties/children/minItems",
1916
- keyword: "minItems",
1917
- params: { limit: 1 },
1918
- message: "must NOT have fewer than 1 items"
1919
- }];
1920
- return false;
1921
- } else {
1922
- const len0 = data4.length;
1923
- for (let i0 = 0; i0 < len0; i0++) {
1924
- const _errs9 = errors;
1925
- if (!wrapper1.validate(data4[i0], {
1926
- instancePath: instancePath + "/children/" + i0,
1927
- parentData: data4,
1928
- parentDataProperty: i0,
1929
- rootData
1930
- })) {
1931
- vErrors = vErrors === null ? wrapper1.validate.errors : vErrors.concat(wrapper1.validate.errors);
1932
- errors = vErrors.length;
1933
- }
1934
- if (!(_errs9 === errors)) break;
1910
+ const len0 = data4.length;
1911
+ for (let i0 = 0; i0 < len0; i0++) {
1912
+ const _errs9 = errors;
1913
+ if (!wrapper1.validate(data4[i0], {
1914
+ instancePath: instancePath + "/children/" + i0,
1915
+ parentData: data4,
1916
+ parentDataProperty: i0,
1917
+ rootData
1918
+ })) {
1919
+ vErrors = vErrors === null ? wrapper1.validate.errors : vErrors.concat(wrapper1.validate.errors);
1920
+ errors = vErrors.length;
1935
1921
  }
1922
+ if (!(_errs9 === errors)) break;
1936
1923
  }
1937
1924
  } else {
1938
1925
  validate27.errors = [{
@@ -2319,30 +2306,19 @@ function validate29(data, { instancePath = "", parentData, parentDataProperty, r
2319
2306
  const _errs34 = errors;
2320
2307
  if (errors === _errs34) {
2321
2308
  if (Array.isArray(data16)) {
2322
- if (data16.length < 1) {
2323
- validate29.errors = [{
2324
- instancePath: instancePath + "/children",
2325
- schemaPath: "#/properties/children/minItems",
2326
- keyword: "minItems",
2327
- params: { limit: 1 },
2328
- message: "must NOT have fewer than 1 items"
2329
- }];
2330
- return false;
2331
- } else {
2332
- const len1 = data16.length;
2333
- for (let i1 = 0; i1 < len1; i1++) {
2334
- const _errs36 = errors;
2335
- if (!wrapper1.validate(data16[i1], {
2336
- instancePath: instancePath + "/children/" + i1,
2337
- parentData: data16,
2338
- parentDataProperty: i1,
2339
- rootData
2340
- })) {
2341
- vErrors = vErrors === null ? wrapper1.validate.errors : vErrors.concat(wrapper1.validate.errors);
2342
- errors = vErrors.length;
2343
- }
2344
- if (!(_errs36 === errors)) break;
2309
+ const len1 = data16.length;
2310
+ for (let i1 = 0; i1 < len1; i1++) {
2311
+ const _errs36 = errors;
2312
+ if (!wrapper1.validate(data16[i1], {
2313
+ instancePath: instancePath + "/children/" + i1,
2314
+ parentData: data16,
2315
+ parentDataProperty: i1,
2316
+ rootData
2317
+ })) {
2318
+ vErrors = vErrors === null ? wrapper1.validate.errors : vErrors.concat(wrapper1.validate.errors);
2319
+ errors = vErrors.length;
2345
2320
  }
2321
+ if (!(_errs36 === errors)) break;
2346
2322
  }
2347
2323
  } else {
2348
2324
  validate29.errors = [{
@@ -4139,30 +4115,19 @@ function validate23(data, { instancePath = "", parentData, parentDataProperty, r
4139
4115
  const _errs10 = errors;
4140
4116
  if (errors === _errs10) {
4141
4117
  if (Array.isArray(data6)) {
4142
- if (data6.length < 1) {
4143
- validate23.errors = [{
4144
- instancePath: instancePath + "/children",
4145
- schemaPath: "#/properties/children/minItems",
4146
- keyword: "minItems",
4147
- params: { limit: 1 },
4148
- message: "must NOT have fewer than 1 items"
4149
- }];
4150
- return false;
4151
- } else {
4152
- const len0 = data6.length;
4153
- for (let i0 = 0; i0 < len0; i0++) {
4154
- const _errs12 = errors;
4155
- if (!validate24(data6[i0], {
4156
- instancePath: instancePath + "/children/" + i0,
4157
- parentData: data6,
4158
- parentDataProperty: i0,
4159
- rootData
4160
- })) {
4161
- vErrors = vErrors === null ? validate24.errors : vErrors.concat(validate24.errors);
4162
- errors = vErrors.length;
4163
- }
4164
- if (!(_errs12 === errors)) break;
4118
+ const len0 = data6.length;
4119
+ for (let i0 = 0; i0 < len0; i0++) {
4120
+ const _errs12 = errors;
4121
+ if (!validate24(data6[i0], {
4122
+ instancePath: instancePath + "/children/" + i0,
4123
+ parentData: data6,
4124
+ parentDataProperty: i0,
4125
+ rootData
4126
+ })) {
4127
+ vErrors = vErrors === null ? validate24.errors : vErrors.concat(validate24.errors);
4128
+ errors = vErrors.length;
4165
4129
  }
4130
+ if (!(_errs12 === errors)) break;
4166
4131
  }
4167
4132
  } else {
4168
4133
  validate23.errors = [{
@@ -4532,30 +4497,19 @@ function validate38(data, { instancePath = "", parentData, parentDataProperty, r
4532
4497
  const _errs10 = errors;
4533
4498
  if (errors === _errs10) {
4534
4499
  if (Array.isArray(data6)) {
4535
- if (data6.length < 1) {
4536
- validate38.errors = [{
4537
- instancePath: instancePath + "/children",
4538
- schemaPath: "#/properties/children/minItems",
4539
- keyword: "minItems",
4540
- params: { limit: 1 },
4541
- message: "must NOT have fewer than 1 items"
4542
- }];
4543
- return false;
4544
- } else {
4545
- const len0 = data6.length;
4546
- for (let i0 = 0; i0 < len0; i0++) {
4547
- const _errs12 = errors;
4548
- if (!wrapper3.validate(data6[i0], {
4549
- instancePath: instancePath + "/children/" + i0,
4550
- parentData: data6,
4551
- parentDataProperty: i0,
4552
- rootData
4553
- })) {
4554
- vErrors = vErrors === null ? wrapper3.validate.errors : vErrors.concat(wrapper3.validate.errors);
4555
- errors = vErrors.length;
4556
- }
4557
- if (!(_errs12 === errors)) break;
4500
+ const len0 = data6.length;
4501
+ for (let i0 = 0; i0 < len0; i0++) {
4502
+ const _errs12 = errors;
4503
+ if (!wrapper3.validate(data6[i0], {
4504
+ instancePath: instancePath + "/children/" + i0,
4505
+ parentData: data6,
4506
+ parentDataProperty: i0,
4507
+ rootData
4508
+ })) {
4509
+ vErrors = vErrors === null ? wrapper3.validate.errors : vErrors.concat(wrapper3.validate.errors);
4510
+ errors = vErrors.length;
4558
4511
  }
4512
+ if (!(_errs12 === errors)) break;
4559
4513
  }
4560
4514
  } else {
4561
4515
  validate38.errors = [{
@@ -4944,30 +4898,19 @@ function validate40(data, { instancePath = "", parentData, parentDataProperty, r
4944
4898
  const _errs34 = errors;
4945
4899
  if (errors === _errs34) {
4946
4900
  if (Array.isArray(data16)) {
4947
- if (data16.length < 1) {
4948
- validate40.errors = [{
4949
- instancePath: instancePath + "/children",
4950
- schemaPath: "#/properties/children/minItems",
4951
- keyword: "minItems",
4952
- params: { limit: 1 },
4953
- message: "must NOT have fewer than 1 items"
4954
- }];
4955
- return false;
4956
- } else {
4957
- const len1 = data16.length;
4958
- for (let i1 = 0; i1 < len1; i1++) {
4959
- const _errs36 = errors;
4960
- if (!wrapper3.validate(data16[i1], {
4961
- instancePath: instancePath + "/children/" + i1,
4962
- parentData: data16,
4963
- parentDataProperty: i1,
4964
- rootData
4965
- })) {
4966
- vErrors = vErrors === null ? wrapper3.validate.errors : vErrors.concat(wrapper3.validate.errors);
4967
- errors = vErrors.length;
4968
- }
4969
- if (!(_errs36 === errors)) break;
4901
+ const len1 = data16.length;
4902
+ for (let i1 = 0; i1 < len1; i1++) {
4903
+ const _errs36 = errors;
4904
+ if (!wrapper3.validate(data16[i1], {
4905
+ instancePath: instancePath + "/children/" + i1,
4906
+ parentData: data16,
4907
+ parentDataProperty: i1,
4908
+ rootData
4909
+ })) {
4910
+ vErrors = vErrors === null ? wrapper3.validate.errors : vErrors.concat(wrapper3.validate.errors);
4911
+ errors = vErrors.length;
4970
4912
  }
4913
+ if (!(_errs36 === errors)) break;
4971
4914
  }
4972
4915
  } else {
4973
4916
  validate40.errors = [{
@@ -6733,30 +6676,19 @@ function validate34(data, { instancePath = "", parentData, parentDataProperty, r
6733
6676
  const _errs7 = errors;
6734
6677
  if (errors === _errs7) {
6735
6678
  if (Array.isArray(data4)) {
6736
- if (data4.length < 1) {
6737
- validate34.errors = [{
6738
- instancePath: instancePath + "/children",
6739
- schemaPath: "#/properties/children/minItems",
6740
- keyword: "minItems",
6741
- params: { limit: 1 },
6742
- message: "must NOT have fewer than 1 items"
6743
- }];
6744
- return false;
6745
- } else {
6746
- const len0 = data4.length;
6747
- for (let i0 = 0; i0 < len0; i0++) {
6748
- const _errs9 = errors;
6749
- if (!validate35(data4[i0], {
6750
- instancePath: instancePath + "/children/" + i0,
6751
- parentData: data4,
6752
- parentDataProperty: i0,
6753
- rootData
6754
- })) {
6755
- vErrors = vErrors === null ? validate35.errors : vErrors.concat(validate35.errors);
6756
- errors = vErrors.length;
6757
- }
6758
- if (!(_errs9 === errors)) break;
6679
+ const len0 = data4.length;
6680
+ for (let i0 = 0; i0 < len0; i0++) {
6681
+ const _errs9 = errors;
6682
+ if (!validate35(data4[i0], {
6683
+ instancePath: instancePath + "/children/" + i0,
6684
+ parentData: data4,
6685
+ parentDataProperty: i0,
6686
+ rootData
6687
+ })) {
6688
+ vErrors = vErrors === null ? validate35.errors : vErrors.concat(validate35.errors);
6689
+ errors = vErrors.length;
6759
6690
  }
6691
+ if (!(_errs9 === errors)) break;
6760
6692
  }
6761
6693
  } else {
6762
6694
  validate34.errors = [{
@@ -7124,30 +7056,19 @@ function validate49(data, { instancePath = "", parentData, parentDataProperty, r
7124
7056
  const _errs10 = errors;
7125
7057
  if (errors === _errs10) {
7126
7058
  if (Array.isArray(data6)) {
7127
- if (data6.length < 1) {
7128
- validate49.errors = [{
7129
- instancePath: instancePath + "/children",
7130
- schemaPath: "#/properties/children/minItems",
7131
- keyword: "minItems",
7132
- params: { limit: 1 },
7133
- message: "must NOT have fewer than 1 items"
7134
- }];
7135
- return false;
7136
- } else {
7137
- const len0 = data6.length;
7138
- for (let i0 = 0; i0 < len0; i0++) {
7139
- const _errs12 = errors;
7140
- if (!wrapper6.validate(data6[i0], {
7141
- instancePath: instancePath + "/children/" + i0,
7142
- parentData: data6,
7143
- parentDataProperty: i0,
7144
- rootData
7145
- })) {
7146
- vErrors = vErrors === null ? wrapper6.validate.errors : vErrors.concat(wrapper6.validate.errors);
7147
- errors = vErrors.length;
7148
- }
7149
- if (!(_errs12 === errors)) break;
7059
+ const len0 = data6.length;
7060
+ for (let i0 = 0; i0 < len0; i0++) {
7061
+ const _errs12 = errors;
7062
+ if (!wrapper6.validate(data6[i0], {
7063
+ instancePath: instancePath + "/children/" + i0,
7064
+ parentData: data6,
7065
+ parentDataProperty: i0,
7066
+ rootData
7067
+ })) {
7068
+ vErrors = vErrors === null ? wrapper6.validate.errors : vErrors.concat(wrapper6.validate.errors);
7069
+ errors = vErrors.length;
7150
7070
  }
7071
+ if (!(_errs12 === errors)) break;
7151
7072
  }
7152
7073
  } else {
7153
7074
  validate49.errors = [{
@@ -7279,30 +7200,19 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
7279
7200
  const _errs7 = errors;
7280
7201
  if (errors === _errs7) {
7281
7202
  if (Array.isArray(data4)) {
7282
- if (data4.length < 1) {
7283
- validate51.errors = [{
7284
- instancePath: instancePath + "/children",
7285
- schemaPath: "#/properties/children/minItems",
7286
- keyword: "minItems",
7287
- params: { limit: 1 },
7288
- message: "must NOT have fewer than 1 items"
7289
- }];
7290
- return false;
7291
- } else {
7292
- const len0 = data4.length;
7293
- for (let i0 = 0; i0 < len0; i0++) {
7294
- const _errs9 = errors;
7295
- if (!wrapper6.validate(data4[i0], {
7296
- instancePath: instancePath + "/children/" + i0,
7297
- parentData: data4,
7298
- parentDataProperty: i0,
7299
- rootData
7300
- })) {
7301
- vErrors = vErrors === null ? wrapper6.validate.errors : vErrors.concat(wrapper6.validate.errors);
7302
- errors = vErrors.length;
7303
- }
7304
- if (!(_errs9 === errors)) break;
7203
+ const len0 = data4.length;
7204
+ for (let i0 = 0; i0 < len0; i0++) {
7205
+ const _errs9 = errors;
7206
+ if (!wrapper6.validate(data4[i0], {
7207
+ instancePath: instancePath + "/children/" + i0,
7208
+ parentData: data4,
7209
+ parentDataProperty: i0,
7210
+ rootData
7211
+ })) {
7212
+ vErrors = vErrors === null ? wrapper6.validate.errors : vErrors.concat(wrapper6.validate.errors);
7213
+ errors = vErrors.length;
7305
7214
  }
7215
+ if (!(_errs9 === errors)) break;
7306
7216
  }
7307
7217
  } else {
7308
7218
  validate51.errors = [{
@@ -9322,30 +9232,19 @@ function validate45(data, { instancePath = "", parentData, parentDataProperty, r
9322
9232
  const _errs34 = errors;
9323
9233
  if (errors === _errs34) {
9324
9234
  if (Array.isArray(data16)) {
9325
- if (data16.length < 1) {
9326
- validate45.errors = [{
9327
- instancePath: instancePath + "/children",
9328
- schemaPath: "#/properties/children/minItems",
9329
- keyword: "minItems",
9330
- params: { limit: 1 },
9331
- message: "must NOT have fewer than 1 items"
9332
- }];
9333
- return false;
9334
- } else {
9335
- const len1 = data16.length;
9336
- for (let i1 = 0; i1 < len1; i1++) {
9337
- const _errs36 = errors;
9338
- if (!validate46(data16[i1], {
9339
- instancePath: instancePath + "/children/" + i1,
9340
- parentData: data16,
9341
- parentDataProperty: i1,
9342
- rootData
9343
- })) {
9344
- vErrors = vErrors === null ? validate46.errors : vErrors.concat(validate46.errors);
9345
- errors = vErrors.length;
9346
- }
9347
- if (!(_errs36 === errors)) break;
9235
+ const len1 = data16.length;
9236
+ for (let i1 = 0; i1 < len1; i1++) {
9237
+ const _errs36 = errors;
9238
+ if (!validate46(data16[i1], {
9239
+ instancePath: instancePath + "/children/" + i1,
9240
+ parentData: data16,
9241
+ parentDataProperty: i1,
9242
+ rootData
9243
+ })) {
9244
+ vErrors = vErrors === null ? validate46.errors : vErrors.concat(validate46.errors);
9245
+ errors = vErrors.length;
9348
9246
  }
9247
+ if (!(_errs36 === errors)) break;
9349
9248
  }
9350
9249
  } else {
9351
9250
  validate45.errors = [{
@@ -29,7 +29,6 @@ const primitive = { type: [
29
29
  ] };
30
30
  const children = {
31
31
  type: "array",
32
- minItems: 1,
33
32
  items: { $ref: "#/$defs/node" }
34
33
  };
35
34
  const actions = {
@@ -26,6 +26,10 @@ function findUnsupportedOpenUINode(value) {
26
26
  message: `Unsupported OpenUI node type: ${String(record.type)}.`
27
27
  };
28
28
  if (record.type === "stack" || record.type === "grid" || record.type === "card") {
29
+ if (Array.isArray(record.children) && record.children.length === 0) return {
30
+ path: `${path}.children`,
31
+ message: "OpenUI containers need at least one child."
32
+ };
29
33
  if (Array.isArray(record.children)) for (const [index, child] of record.children.entries()) {
30
34
  const issue = visit(child, `${path}.children[${index}]`, depth + 1);
31
35
  if (issue) return issue;
@@ -10,8 +10,8 @@ import * as React from "react";
10
10
  * the tone's COLOUR, and the state's own LABEL as text.
11
11
  *
12
12
  * The glyphs are chosen to survive at 8px and to differ in outline rather than
13
- * in fill: a ring reads as "still open", a solid disc as "settled", a slashed
14
- * disc as "stopped". Two states never share one silhouette.
13
+ * in fill: a ring reads as "still open", a solid disc as "settled", a cross as
14
+ * "failed". Two states never share one silhouette.
15
15
  *
16
16
  * Each tone draws its fill, border and text from ONE matched token triple.
17
17
  * That pairing is the whole point: a status colour is solved against its own
@@ -45,22 +45,16 @@ function ToneGlyph({ tone }) {
45
45
  r: "3.25"
46
46
  })
47
47
  });
48
- case "danger": return /* @__PURE__ */ jsxs("svg", {
48
+ case "danger": return /* @__PURE__ */ jsx("svg", {
49
49
  ...common,
50
50
  "aria-hidden": "true",
51
51
  fill: "none",
52
52
  stroke: "currentColor",
53
- strokeWidth: "1.5",
54
- children: [/* @__PURE__ */ jsx("circle", {
55
- cx: "4",
56
- cy: "4",
57
- r: "3.1",
58
- fill: "currentColor",
59
- opacity: "0.35"
60
- }), /* @__PURE__ */ jsx("path", {
61
- d: "M1.9 6.1 6.1 1.9",
53
+ strokeWidth: "1.75",
54
+ children: /* @__PURE__ */ jsx("path", {
55
+ d: "M1.5 1.5 6.5 6.5M6.5 1.5 1.5 6.5",
62
56
  strokeLinecap: "round"
63
- })]
57
+ })
64
58
  });
65
59
  case "warning": return /* @__PURE__ */ jsx("svg", {
66
60
  ...common,
@@ -14,7 +14,9 @@ export interface CommandPreviewProps {
14
14
  * One shell command as a terminal block: a `$ command` prompt line with its
15
15
  * exit status, and stdout and stderr in separate regions below it.
16
16
  *
17
- * The block is always dark. It scopes the dark token set onto itself with
17
+ * Closed, a command is a quiet row on the surface it sits on: a list of
18
+ * commands should read as a list, not a stack of black bars. Opened, it is a
19
+ * dark terminal. It scopes the dark token set onto itself with
18
20
  * `data-theme="dark"`, so stderr, the badges and the muted prompt keep the
19
21
  * contrast they were designed with on a dark ground, in a light console too.
20
22
  */
@@ -61,10 +61,14 @@ function extractCommandOutput(output) {
61
61
  }
62
62
  function fromObject(obj) {
63
63
  const text = (value) => value === void 0 || value === null ? "" : String(value);
64
+ const timedOut = obj.timedOut ?? obj.timed_out;
65
+ const signal = obj.signal;
64
66
  return {
65
67
  stdout: text(obj.stdout ?? obj.output),
66
68
  stderr: text(obj.stderr),
67
- exitCode: finiteNumber(obj.exitCode ?? obj.exit_code ?? obj.code)
69
+ exitCode: finiteNumber(obj.exitCode ?? obj.exit_code ?? obj.code),
70
+ ...timedOut === true ? { timedOut: true } : {},
71
+ ...typeof signal === "string" && signal.length > 0 ? { signal } : {}
68
72
  };
69
73
  }
70
74
  /** The keys a serialized command result carries, and nothing else. */
@@ -96,9 +100,12 @@ function parseStructured(text) {
96
100
  return;
97
101
  }
98
102
  }
99
- /** Exit status as a badge: the code when one is known, else the tool's status.
100
- * Red only for a nonzero exit or an error; a clean run stays quiet green. */
101
- function ExitBadge({ exitCode, status }) {
103
+ /** Exit status as a badge. Red only where the command itself is known to have
104
+ * failed: a nonzero exit, a timeout, or a signal. A tool that reported an
105
+ * error with nothing recorded about the command (no exit code, or exit 0
106
+ * from a runner that failed afterwards) gets a neutral badge; its error text
107
+ * prints below. A clean run stays quiet green. */
108
+ function ExitBadge({ output, status }) {
102
109
  if (status === "running" || status === "pending") return /* @__PURE__ */ jsxs("span", {
103
110
  className: "inline-flex shrink-0 items-center gap-1 text-[11px] text-muted-foreground",
104
111
  children: [/* @__PURE__ */ jsx(Loader2, {
@@ -106,19 +113,53 @@ function ExitBadge({ exitCode, status }) {
106
113
  "aria-hidden": "true"
107
114
  }), "running"]
108
115
  });
109
- const failed = status === "error" || exitCode !== void 0 && exitCode !== 0;
110
- const label = exitCode !== void 0 ? `exit ${exitCode}` : failed ? "error" : null;
116
+ const { exitCode, timedOut, signal } = output;
117
+ let label;
118
+ let tone;
119
+ if (timedOut) {
120
+ label = "timed out";
121
+ tone = "danger";
122
+ } else if (signal) {
123
+ label = signal;
124
+ tone = "danger";
125
+ } else if (exitCode !== void 0 && exitCode !== 0) {
126
+ label = `exit ${exitCode}`;
127
+ tone = "danger";
128
+ } else if (status === "error") {
129
+ label = exitCode === 0 ? "exit 0 · tool error" : "tool error";
130
+ tone = "neutral";
131
+ } else {
132
+ label = exitCode === 0 ? "exit 0" : null;
133
+ tone = "success";
134
+ }
111
135
  if (label === null) return null;
112
136
  return /* @__PURE__ */ jsx("span", {
113
- className: cn("inline-flex shrink-0 items-center rounded-full px-1.5 py-px text-[11px] font-medium tabular-nums", failed ? "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]" : "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]"),
137
+ className: cn("inline-flex shrink-0 items-center rounded-full border px-1.5 py-px text-[11px] font-medium tabular-nums", tone === "danger" && "border-transparent bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]", tone === "success" && "border-transparent bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]", tone === "neutral" && "border-[var(--surface-neutral-border)] bg-[var(--surface-neutral-bg)] text-[var(--surface-neutral-text)]"),
114
138
  children: label
115
139
  });
116
140
  }
117
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 }) {
149
+ 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", {
152
+ className: "inline-block max-w-full [overflow-wrap:anywhere]",
153
+ children: token
154
+ }, i) : token), limit < tokens.length ? tokens.slice(limit).join("") : null] });
155
+ }
156
+ /**
118
157
  * One shell command as a terminal block: a `$ command` prompt line with its
119
158
  * exit status, and stdout and stderr in separate regions below it.
120
159
  *
121
- * The block is always dark. It scopes the dark token set onto itself with
160
+ * Closed, a command is a quiet row on the surface it sits on: a list of
161
+ * commands should read as a list, not a stack of black bars. Opened, it is a
162
+ * dark terminal. It scopes the dark token set onto itself with
122
163
  * `data-theme="dark"`, so stderr, the badges and the muted prompt keep the
123
164
  * contrast they were designed with on a dark ground, in a light console too.
124
165
  */
@@ -139,23 +180,27 @@ const CommandPreview = memo(({ part, defaultExpanded = false, className }) => {
139
180
  }),
140
181
  /* @__PURE__ */ jsx("code", {
141
182
  className: cn("min-w-0 flex-1 whitespace-pre-wrap [overflow-wrap:anywhere]", expanded ? "" : "line-clamp-2"),
142
- children: command
183
+ children: /* @__PURE__ */ jsx(CommandText, {
184
+ command,
185
+ all: expanded
186
+ })
143
187
  }),
144
188
  /* @__PURE__ */ jsx(ExitBadge, {
145
- exitCode: output.exitCode,
189
+ output,
146
190
  status
147
191
  })
148
192
  ] });
149
193
  return /* @__PURE__ */ jsxs("div", {
150
- "data-theme": "dark",
194
+ "data-theme": expanded ? "dark" : void 0,
151
195
  "data-testid": "command-preview",
152
- className: cn("overflow-hidden rounded-[var(--radius-md)] bg-[var(--md3-surface-container-lowest)] font-mono text-xs text-foreground", className),
196
+ "data-expanded": expanded,
197
+ className: cn("overflow-hidden rounded-[var(--radius-md)] border font-mono text-xs text-foreground", expanded ? "border-[var(--md3-surface-container-lowest)] bg-[var(--md3-surface-container-lowest)]" : "border-border bg-transparent", className),
153
198
  children: [hasBody ? /* @__PURE__ */ jsxs("button", {
154
199
  type: "button",
155
200
  onClick: () => setExpanded((value) => !value),
156
201
  "aria-expanded": expanded,
157
202
  "aria-controls": bodyId,
158
- className: cn("flex w-full items-start gap-2 px-3 py-2 text-left transition-colors hover:bg-white/5", focusRing),
203
+ className: cn("flex w-full items-start gap-2 px-3 py-2 text-left transition-colors", expanded ? "hover:bg-white/5" : "hover:bg-muted", focusRing),
159
204
  children: [promptLine, expanded ? /* @__PURE__ */ jsx(ChevronDown, {
160
205
  className: "mt-px h-3.5 w-3.5 shrink-0 text-muted-foreground",
161
206
  "aria-hidden": "true"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.16.4",
3
+ "version": "11.16.6",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -142,7 +142,7 @@
142
142
  "peerDependencies": {
143
143
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
144
144
  "@nanostores/react": ">=0.8.4 <3.0.0",
145
- "@tangle-network/brand": "^1.10.1",
145
+ "@tangle-network/brand": "^1.10.2",
146
146
  "@tiptap/core": ">=3.20.4 <4.0.0",
147
147
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
148
148
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",