@vitest-agent/ui 2.5.2 → 3.0.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.
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { classifyOutcome, classifyRunShape } from "./dispatcher/classify.js";
2
2
  import { buildFooter, dominantClassification } from "./dispatcher/footer.js";
3
+ import { VitestAgentStatus, VitestAgentTokens, inkStyle, statusGlyph, statusInkStyle } from "./theme.js";
3
4
  import { formatDisplayDuration } from "./format-duration.js";
4
5
  import { dispatch, dispatchInk, dispatcherTable } from "./dispatcher/dispatch.js";
5
6
  import { RunEventChannel, RunEventChannelLive } from "./pubsub/Channel.js";
@@ -16,7 +17,7 @@ import { StatusIcon } from "./render-ink/StatusIcon.js";
16
17
  import { ModuleHeader } from "./render-ink/ModuleHeader.js";
17
18
  import { TagColumns, tagUnion } from "./render-ink/TagColumns.js";
18
19
  import { ProjectRow } from "./render-ink/ProjectRow.js";
19
- import { SPINNER_FRAMES, SPINNER_FRAME_MS, spinnerFrame, spinnerFrameForTime } from "./render-ink/spinner.js";
20
+ import { SPINNER_FRAMES, SPINNER_FRAME_MS, spinnerFrame } from "./render-ink/spinner.js";
20
21
  import { TestRow } from "./render-ink/TestRow.js";
21
22
  import { TrendLine } from "./render-ink/TrendLine.js";
22
23
  import { StreamApp } from "./render-ink/StreamApp.js";
@@ -33,7 +34,7 @@ import { ActionSeverity, CoverageFile, CoverageGap, CoverageMetric, CoverageRend
33
34
  *
34
35
  * @public
35
36
  */
36
- const CURRENT_UI_VERSION = "2.5.2";
37
+ const CURRENT_UI_VERSION = "3.0.0";
37
38
 
38
39
  //#endregion
39
- export { ActionSeverity, CURRENT_UI_VERSION, CountColumns, CoverageBlock, CoverageFile, CoverageGap, CoverageMetric, CoverageRenderState, DURATION_CELL_WIDTH, FailureRecord, FailureSection, FailuresSection, ModuleHeader, ModuleRecord, ProjectRow, RenderState, RenderTotals, RunEvent, RunEventChannel, RunEventChannelLive, SPINNER_FRAMES, SPINNER_FRAME_MS, SUITE_LOAD_FAILURE_LABEL, StatusIcon, StreamApp, SuggestedActionRecord, SuggestedActions, TagColumns, TestRecord, TestRow, TrendLine, accumulateUntilFinished, buildFooter, classifyOutcome, classifyRunShape, dispatch, dispatchInk, dispatcherTable, dominantClassification, forEachRenderState, formatDisplayDuration, initialRenderState, publish, publishAll, reduceRenderState, reduceRenderStateAll, renderAgent, renderStateStream, spinnerFrame, spinnerFrameForTime, subscribeRaw, synthesizeFromAgentReport, synthesizeRunEvents, tagUnion };
40
+ export { ActionSeverity, CURRENT_UI_VERSION, CountColumns, CoverageBlock, CoverageFile, CoverageGap, CoverageMetric, CoverageRenderState, DURATION_CELL_WIDTH, FailureRecord, FailureSection, FailuresSection, ModuleHeader, ModuleRecord, ProjectRow, RenderState, RenderTotals, RunEvent, RunEventChannel, RunEventChannelLive, SPINNER_FRAMES, SPINNER_FRAME_MS, SUITE_LOAD_FAILURE_LABEL, StatusIcon, StreamApp, SuggestedActionRecord, SuggestedActions, TagColumns, TestRecord, TestRow, TrendLine, VitestAgentStatus, VitestAgentTokens, accumulateUntilFinished, buildFooter, classifyOutcome, classifyRunShape, dispatch, dispatchInk, dispatcherTable, dominantClassification, forEachRenderState, formatDisplayDuration, initialRenderState, inkStyle, publish, publishAll, reduceRenderState, reduceRenderStateAll, renderAgent, renderStateStream, spinnerFrame, statusGlyph, statusInkStyle, subscribeRaw, synthesizeFromAgentReport, synthesizeRunEvents, tagUnion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/ui",
3
- "version": "2.5.2",
3
+ "version": "3.0.0",
4
4
  "private": false,
5
5
  "description": "Shared event-sourced renderer for vitest-agent. React Ink view for humans, plain-string view for agents, both fed by the same reducer over a RunEvent stream.",
6
6
  "keywords": [
@@ -39,10 +39,14 @@
39
39
  "./package.json": "./package.json"
40
40
  },
41
41
  "dependencies": {
42
- "@vitest-agent/sdk": "5.1.2",
43
- "effect": "4.0.0-rc.117"
42
+ "@vitest-agent/sdk": "5.2.0",
43
+ "effect": "^4.0.0"
44
44
  },
45
45
  "peerDependencies": {
46
+ "@effected/cli": "^0.11.0",
47
+ "@effected/env": "^0.1.0",
48
+ "@effected/glob": "^0.10.0",
49
+ "@effected/walker": "^0.15.0",
46
50
  "ink": "^7.1.0",
47
51
  "react": "^19.3.0"
48
52
  },
package/render-agent.js CHANGED
@@ -1,6 +1,17 @@
1
- import { formatDisplayDuration } from "./format-duration.js";
1
+ import { formatTotalsLine } from "./counts.js";
2
+ import { Fmt } from "@effected/cli";
2
3
 
3
4
  //#region src/render-agent.ts
5
+ /**
6
+ * Agent-mode renderer: produces a token-efficient final-frame string
7
+ * from a fully-reduced `RenderState`.
8
+ *
9
+ * Output is intentionally separate from the Ink renderer — agents
10
+ * benefit from a different layout than humans (no ANSI, no live
11
+ * progress, no decoration overhead). The output is stable for stable
12
+ * inputs: no timestamps, no derived "time ago" phrasing, no randomized
13
+ * ordering.
14
+ */
4
15
  const DEFAULT_WIDTH = 80;
5
16
  const DEFAULT_MAX_GAPS = 3;
6
17
  const severityLabel = {
@@ -8,18 +19,11 @@ const severityLabel = {
8
19
  warn: "warn",
9
20
  blocker: "blocker"
10
21
  };
11
- const formatHeader = (state) => {
12
- const { passCount, failCount, skipCount, timeoutCount, durationMs } = state.totals;
13
- const parts = [`${passCount}/${passCount + failCount + skipCount + timeoutCount} passed`];
14
- if (failCount > 0) parts.push(`${failCount} failed`);
15
- if (timeoutCount > 0) parts.push(`${timeoutCount} timed out`);
16
- if (skipCount > 0) parts.push(`${skipCount} skipped`);
17
- if (state.unhandledErrors.length > 0) {
18
- const noun = state.unhandledErrors.length === 1 ? "unhandled error" : "unhandled errors";
19
- parts.push(`${state.unhandledErrors.length} ${noun}`);
20
- }
21
- return `Tests: ${parts.join(", ")} (${formatDisplayDuration(durationMs)})`;
22
- };
22
+ const formatHeader = (state) => formatTotalsLine({
23
+ label: "Tests",
24
+ ...state.totals,
25
+ unhandledErrors: state.unhandledErrors.length
26
+ });
23
27
  const formatModulesSection = (state) => {
24
28
  const modules = state.moduleOrder.map((path) => state.modules[path]).filter((m) => m !== void 0);
25
29
  const { passCount, failCount, skipCount, timeoutCount } = state.totals;
@@ -27,9 +31,9 @@ const formatModulesSection = (state) => {
27
31
  const collected = state.collectedModules ?? modules.length;
28
32
  if (modules.length === 0) {
29
33
  if (collected === 0) return null;
30
- return `${collected} ${collected === 1 ? "module" : "modules"} all-passed.`;
34
+ return `${Fmt.plural(collected, "module")} all-passed.`;
31
35
  }
32
- if (modules.filter((m) => m.failCount > 0 || m.skipCount > 0).length === 0) return `${collected} ${collected === 1 ? "module" : "modules"} all-passed.`;
36
+ if (modules.filter((m) => m.failCount > 0 || m.skipCount > 0).length === 0) return `${Fmt.plural(collected, "module")} all-passed.`;
33
37
  const lines = ["Modules:"];
34
38
  for (const m of modules) {
35
39
  const parts = [];
@@ -41,12 +45,7 @@ const formatModulesSection = (state) => {
41
45
  }
42
46
  return lines.join("\n");
43
47
  };
44
- const truncate = (line, max) => {
45
- if (line.length <= max) return line;
46
- const slice = max - 1;
47
- if (slice <= 0) return "…";
48
- return `${line.slice(0, slice)}…`;
49
- };
48
+ const truncate = (line, max) => Fmt.truncate(line, max);
50
49
  const formatFailure = (f, width, includeStack) => {
51
50
  const suite = f.suitePath.length > 0 ? `${f.suitePath.join(" > ")} > ` : "";
52
51
  const classification = f.classification !== null ? ` [${f.classification}]` : "";
@@ -77,10 +76,8 @@ const formatUnhandledErrorsSection = (state, width, includeStack) => {
77
76
  for (const err of state.unhandledErrors) lines.push(formatUnhandledError(err, width, includeStack));
78
77
  return lines.join("\n");
79
78
  };
80
- const formatPercent = (n) => {
81
- const rounded = Math.round(n * 10) / 10;
82
- return Number.isInteger(rounded) ? `${rounded}%` : `${rounded}%`;
83
- };
79
+ /** Coverage metrics arrive on istanbul's 0–100 scale. */
80
+ const formatPercent = (n) => Fmt.percent(n, { scale: 100 });
84
81
  const formatCoverageSection = (state, maxGaps) => {
85
82
  const cov = state.coverage;
86
83
  if (cov === null) return null;
@@ -108,10 +105,7 @@ const formatCoverageSection = (state, maxGaps) => {
108
105
  lines.push(`- ${g.file}${detail}`);
109
106
  }
110
107
  const omitted = cov.gaps.length - topN.length;
111
- if (omitted > 0) {
112
- const noun = omitted === 1 ? "gap" : "gaps";
113
- lines.push(`- (+${omitted} more ${noun})`);
114
- }
108
+ if (omitted > 0) lines.push(`- (+${Fmt.plural(omitted, "more gap", "more gaps")})`);
115
109
  }
116
110
  return lines.join("\n");
117
111
  };
@@ -1,41 +1,42 @@
1
+ import { VitestAgentTokens, inkStyle, statusGlyph, statusInkStyle } from "../theme.js";
1
2
  import { Text } from "ink";
3
+ import { useGlyphs } from "@effected/cli/ui";
2
4
  import { jsxs } from "react/jsx-runtime";
3
5
 
4
6
  //#region src/render-ink/CountColumns.tsx
5
7
  /**
6
- * The four-outcome count columns for an aggregate row (a project or a
7
- * module): pass, fail, skip, timeout. All four always render — a zero
8
- * is dimmed, never omitted — so the columns line up across rows.
9
- */
10
- /**
11
8
  * Fixed width of the duration cell that follows the count columns on an
12
9
  * aggregate row — sized for the formatter's widest common output
13
- * (`999.9ms`). Longer values overflow their row rather than truncate.
10
+ * (`59m 59s`). Longer values overflow their row rather than truncate.
14
11
  *
15
12
  * @public
16
13
  */
17
14
  const DURATION_CELL_WIDTH = 7;
18
- const cell = (count, glyph, color) => /* @__PURE__ */ jsxs(Text, {
19
- color: count > 0 ? color : "gray",
20
- children: [String(count).padStart(4), glyph]
15
+ const cell = (count, status, glyphs) => /* @__PURE__ */ jsxs(Text, {
16
+ ...count > 0 ? statusInkStyle(status) : inkStyle(VitestAgentTokens.zero),
17
+ children: [String(count).padStart(4), statusGlyph(status, glyphs)]
21
18
  });
22
19
  /**
23
20
  * Renders four colored count columns (pass ✓, fail ✗, skip ↷, timeout ⧖)
24
21
  * for an aggregate row. Counts render right-aligned in fixed 4-digit cells so
25
22
  * columns align across rows; counts of 10,000+ overflow their row without
26
- * truncation. Zeros are dimmed; all four columns always appear.
23
+ * truncation. Zeros are greyed; all four columns always appear. Glyphs and
24
+ * colours come from `VitestAgentStatus` (skip is `muted`).
27
25
  *
28
26
  * @public
29
27
  */
30
- const CountColumns = ({ passCount, failCount, skipCount, timeoutCount }) => /* @__PURE__ */ jsxs(Text, { children: [
31
- cell(passCount, "✓", "green"),
32
- " ",
33
- cell(failCount, "✗", "red"),
34
- " ",
35
- cell(skipCount, "↷", "yellow"),
36
- " ",
37
- cell(timeoutCount, "⧖", "#e09a4e")
38
- ] });
28
+ const CountColumns = ({ passCount, failCount, skipCount, timeoutCount }) => {
29
+ const glyphs = useGlyphs();
30
+ return /* @__PURE__ */ jsxs(Text, { children: [
31
+ cell(passCount, "success", glyphs),
32
+ " ",
33
+ cell(failCount, "failure", glyphs),
34
+ " ",
35
+ cell(skipCount, "skip", glyphs),
36
+ " ",
37
+ cell(timeoutCount, "timeout", glyphs)
38
+ ] });
39
+ };
39
40
 
40
41
  //#endregion
41
42
  export { CountColumns, DURATION_CELL_WIDTH };
@@ -1,16 +1,22 @@
1
+ import { inkStyle } from "../theme.js";
1
2
  import { Box, Text } from "ink";
3
+ import { Fmt } from "@effected/cli";
2
4
  import { jsx, jsxs } from "react/jsx-runtime";
3
5
 
4
6
  //#region src/render-ink/CoverageBlock.tsx
7
+ /**
8
+ * Coverage section: per-metric percentage, threshold violations, top-N gaps.
9
+ */
5
10
  const METRIC_ORDER = [
6
11
  "lines",
7
12
  "branches",
8
13
  "functions",
9
14
  "statements"
10
15
  ];
11
- const formatPercent = (n) => {
12
- return `${Math.round(n * 10) / 10}%`;
13
- };
16
+ /** Coverage metrics arrive on istanbul's 0–100 scale. */
17
+ const formatPercent = (n) => Fmt.percent(n, { scale: 100 });
18
+ /** A metric below its threshold is a coverage threshold failure: the kit's `failure` token. */
19
+ const FAILURE = inkStyle("failure");
14
20
  /**
15
21
  * Renders the coverage section: per-metric percentages, threshold
16
22
  * violations, and top-N gap entries sorted by missing line count.
@@ -35,7 +41,7 @@ const CoverageBlock = ({ coverage, maxGaps = 3 }) => {
35
41
  return /* @__PURE__ */ jsxs(Box, { children: [
36
42
  /* @__PURE__ */ jsx(Text, { children: ` ${metric}: ` }),
37
43
  failing ? /* @__PURE__ */ jsx(Text, {
38
- color: "red",
44
+ ...FAILURE,
39
45
  children: formatPercent(actual)
40
46
  }) : /* @__PURE__ */ jsx(Text, { children: formatPercent(actual) }),
41
47
  threshold !== void 0 ? /* @__PURE__ */ jsxs(Text, {
@@ -51,10 +57,10 @@ const CoverageBlock = ({ coverage, maxGaps = 3 }) => {
51
57
  coverage.violations.length > 0 ? /* @__PURE__ */ jsxs(Box, {
52
58
  flexDirection: "column",
53
59
  children: [/* @__PURE__ */ jsx(Text, {
54
- color: "red",
60
+ ...FAILURE,
55
61
  children: "Violations"
56
62
  }), coverage.violations.map((v) => /* @__PURE__ */ jsx(Text, {
57
- color: "red",
63
+ ...FAILURE,
58
64
  children: ` ${v.metric}: ${formatPercent(v.actual)} < ${formatPercent(v.expected)}`
59
65
  }, v.metric))]
60
66
  }) : null,
@@ -68,7 +74,7 @@ const CoverageBlock = ({ coverage, maxGaps = 3 }) => {
68
74
  topGaps.map((g) => /* @__PURE__ */ jsxs(Text, { children: [` ${g.file}`, g.uncoveredLines !== void 0 ? `: ${g.uncoveredLines}` : ""] }, g.file)),
69
75
  elidedGaps > 0 ? /* @__PURE__ */ jsx(Text, {
70
76
  dimColor: true,
71
- children: ` (+${elidedGaps} more ${elidedGaps === 1 ? "gap" : "gaps"})`
77
+ children: ` (+${Fmt.plural(elidedGaps, "more gap", "more gaps")})`
72
78
  }) : null
73
79
  ]
74
80
  }) : null
@@ -1,17 +1,24 @@
1
+ import { inkStyle, statusGlyph, statusInkStyle } from "../theme.js";
1
2
  import { Box, Text } from "ink";
3
+ import { useGlyphs } from "@effected/cli/ui";
2
4
  import { jsx, jsxs } from "react/jsx-runtime";
3
5
 
4
6
  //#region src/render-ink/FailureSection.tsx
7
+ /**
8
+ * Failure list: one block per failed test with classification, message,
9
+ * diff, and optionally stack trace.
10
+ */
5
11
  const FailureRow = ({ failure, includeStack }) => {
6
12
  const suite = failure.suitePath.length > 0 ? `${failure.suitePath.join(" > ")} > ` : "";
7
13
  const classification = failure.classification !== null ? ` [${failure.classification}]` : "";
14
+ const glyphs = useGlyphs();
8
15
  return /* @__PURE__ */ jsxs(Box, {
9
16
  flexDirection: "column",
10
17
  children: [
11
18
  /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
12
19
  /* @__PURE__ */ jsx(Text, {
13
- color: "red",
14
- children: "✗"
20
+ ...statusInkStyle("failure"),
21
+ children: statusGlyph("failure", glyphs)
15
22
  }),
16
23
  ` ${failure.modulePath} > ${suite}${failure.testName}`,
17
24
  failure.classification !== null ? /* @__PURE__ */ jsx(Text, {
@@ -20,17 +27,17 @@ const FailureRow = ({ failure, includeStack }) => {
20
27
  }) : null
21
28
  ] }) }),
22
29
  failure.error?.message !== void 0 ? /* @__PURE__ */ jsx(Text, {
23
- color: "red",
30
+ ...inkStyle("failure"),
24
31
  children: ` ${failure.error.message.split("\n", 1)[0] ?? ""}`
25
32
  }) : null,
26
33
  failure.error?.diff !== void 0 ? failure.error.diff.split("\n").map((line, idx) => {
27
34
  const key = `diff-${idx}`;
28
35
  if (line.startsWith("-")) return /* @__PURE__ */ jsx(Text, {
29
- color: "red",
36
+ ...inkStyle("failure"),
30
37
  children: ` ${line}`
31
38
  }, key);
32
39
  if (line.startsWith("+")) return /* @__PURE__ */ jsx(Text, {
33
- color: "green",
40
+ ...inkStyle("success"),
34
41
  children: ` ${line}`
35
42
  }, key);
36
43
  return /* @__PURE__ */ jsx(Text, { children: ` ${line}` }, key);
@@ -1,7 +1,18 @@
1
+ import { VitestAgentTokens, inkStyle, statusGlyph, statusInkStyle } from "../theme.js";
1
2
  import { Box, Text } from "ink";
3
+ import { useGlyphs } from "@effected/cli/ui";
2
4
  import { jsx, jsxs } from "react/jsx-runtime";
3
5
 
4
6
  //#region src/render-ink/FailuresSection.tsx
7
+ /**
8
+ * The capped failures block for aggregate-row shapes (workspace,
9
+ * single-project) — the rows there are projects or modules and cannot
10
+ * expand a per-test error inline, so the failures collect here.
11
+ *
12
+ * Each entry: a glyph (⧖ for a timed-out failure, ✗ otherwise), the
13
+ * `module › suite › test` path, the classification tag when known, and
14
+ * one indented line — the first line of the error message.
15
+ */
5
16
  const pathOf = (f) => {
6
17
  return [
7
18
  f.modulePath,
@@ -9,6 +20,7 @@ const pathOf = (f) => {
9
20
  f.testName
10
21
  ].join(" › ");
11
22
  };
23
+ const failureStatus = (f) => f.timedOut === true ? "timeout" : "failure";
12
24
  const firstLine = (message) => message.split("\n", 1)[0] ?? "";
13
25
  const FAILURE_VALUE_LIMIT = 200;
14
26
  /**
@@ -20,6 +32,7 @@ const FAILURE_VALUE_LIMIT = 200;
20
32
  const FailuresSection = ({ failures, limit }) => {
21
33
  const shown = failures.slice(0, limit);
22
34
  const overflow = failures.length - shown.length;
35
+ const glyphs = useGlyphs();
23
36
  return /* @__PURE__ */ jsxs(Box, {
24
37
  flexDirection: "column",
25
38
  children: [
@@ -37,13 +50,13 @@ const FailuresSection = ({ failures, limit }) => {
37
50
  /* @__PURE__ */ jsxs(Text, { children: [
38
51
  " ",
39
52
  /* @__PURE__ */ jsx(Text, {
40
- color: f.timedOut === true ? "#e09a4e" : "red",
41
- children: f.timedOut === true ? "⧖" : "✗"
53
+ ...statusInkStyle(failureStatus(f)),
54
+ children: statusGlyph(failureStatus(f), glyphs)
42
55
  }),
43
56
  " ",
44
57
  pathOf(f),
45
58
  f.classification !== null ? /* @__PURE__ */ jsxs(Text, {
46
- color: "#c98ae0",
59
+ ...inkStyle(VitestAgentTokens.classification),
47
60
  children: [
48
61
  " [",
49
62
  f.classification,
@@ -1,3 +1,4 @@
1
+ import { statusInkStyle } from "../theme.js";
1
2
  import { formatDisplayDuration } from "../format-duration.js";
2
3
  import { CountColumns, DURATION_CELL_WIDTH } from "./CountColumns.js";
3
4
  import { StatusIcon } from "./StatusIcon.js";
@@ -13,7 +14,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
14
  */
14
15
  const projectGlyph = (counts, running, timedOut, frame) => {
15
16
  if (running && !timedOut) return /* @__PURE__ */ jsx(Text, {
16
- color: "yellow",
17
+ ...statusInkStyle("running"),
17
18
  children: frame
18
19
  });
19
20
  if (counts.failCount > 0) return /* @__PURE__ */ jsx(StatusIcon, { status: "failed" });
@@ -1,4 +1,6 @@
1
+ import { statusGlyph, statusInkStyle } from "../theme.js";
1
2
  import { Text } from "ink";
3
+ import { useGlyphs } from "@effected/cli/ui";
2
4
  import { jsx } from "react/jsx-runtime";
3
5
 
4
6
  //#region src/render-ink/StatusIcon.tsx
@@ -8,37 +10,34 @@ import { jsx } from "react/jsx-runtime";
8
10
  * Ink-only primitive — no DOM-isms. Renders one colored character so
9
11
  * the surrounding row can keep its width budget predictable.
10
12
  */
11
- const GLYPH = {
12
- passed: "✓",
13
- failed: "✗",
14
- skipped: "↷",
15
- pending: "◯",
16
- running: "…",
17
- queued: "·",
18
- finished: "✓",
19
- threshold: "⚠",
20
- "timed-out": "⧖"
21
- };
22
- const COLOR = {
23
- passed: "green",
24
- failed: "red",
25
- skipped: "gray",
26
- pending: "cyan",
27
- running: "yellow",
28
- queued: "gray",
29
- finished: "green",
30
- threshold: "yellow",
31
- "timed-out": "#e09a4e"
13
+ /**
14
+ * Each icon kind's status in the shared vocabulary. `finished` is a pass;
15
+ * `threshold` is a coverage threshold failure, which the kit ranks as a
16
+ * `failure`, not a warning.
17
+ */
18
+ const STATUS = {
19
+ passed: "success",
20
+ failed: "failure",
21
+ skipped: "skip",
22
+ pending: "pending",
23
+ running: "running",
24
+ queued: "queued",
25
+ finished: "success",
26
+ threshold: "failure",
27
+ "timed-out": "timeout"
32
28
  };
33
29
  /**
34
30
  * Renders a single colored status glyph for a test, module, or run.
35
31
  *
36
32
  * @public
37
33
  */
38
- const StatusIcon = ({ status }) => /* @__PURE__ */ jsx(Text, {
39
- color: COLOR[status],
40
- children: GLYPH[status]
41
- });
34
+ const StatusIcon = ({ status }) => {
35
+ const glyphs = useGlyphs();
36
+ return /* @__PURE__ */ jsx(Text, {
37
+ ...statusInkStyle(STATUS[status]),
38
+ children: statusGlyph(STATUS[status], glyphs)
39
+ });
40
+ };
42
41
 
43
42
  //#endregion
44
43
  export { StatusIcon };