opencode-visual-cache 1.7.0-beta.2 → 1.7.0-beta.4
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/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/balance-providers.js +27 -1
- package/dist/index.js +4 -1
- package/dist/server.d.ts +1 -4
- package/dist/server.js +0 -4
- package/dist/tui.js +31 -2
- package/dist/v2/index.d.ts +3 -1
- package/dist/v2/index.js +3 -0
- package/dist/v2.js +27 -3
- package/package.json +3 -2
- package/src/_version.ts +1 -1
- package/src/balance-providers.ts +25 -1
- package/src/core/color.ts +108 -108
- package/src/core/currency.ts +46 -46
- package/src/core/estimate.ts +36 -36
- package/src/core/format.ts +81 -81
- package/src/core/index.ts +5 -5
- package/src/core/types.ts +17 -17
- package/src/index.tsx +3 -0
- package/src/panel/panel-api.ts +104 -104
- package/src/server.ts +1 -5
- package/src/v2/data.ts +112 -112
- package/src/v2/index.tsx +187 -184
- package/src/v2/sidebar.tsx +69 -69
- package/src/v2/status.tsx +96 -96
- package/src/v2/theme.ts +19 -19
- package/src/v2/types.ts +159 -159
- package/src/v2/v2-panel-api.ts +177 -177
- package/tui/index.js +12 -0
package/src/v2/sidebar.tsx
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
/** @jsxImportSource @opentui/solid */
|
|
2
|
-
|
|
3
|
-
import { createMemo, For, Show } from "solid-js"
|
|
4
|
-
import type { Context } from "./types"
|
|
5
|
-
import { collectSessionStats, hitRate } from "./data"
|
|
6
|
-
import { fmt, fmtCost, progressBar, visualPadEnd } from "../core"
|
|
7
|
-
|
|
8
|
-
const LABEL_GAP = 1
|
|
9
|
-
const BAR_BRACKETS = 2
|
|
10
|
-
const BAR_GAP = 1
|
|
11
|
-
const PCT_FIXED_WIDTH = 5
|
|
12
|
-
const MIN_PANEL_WIDTH = 20
|
|
13
|
-
const DEFAULT_PANEL_WIDTH = 26
|
|
14
|
-
|
|
15
|
-
export function SidebarView(props: { context: Context; sessionID: string }) {
|
|
16
|
-
const stats = createMemo(() => collectSessionStats(props.context, props.sessionID))
|
|
17
|
-
const rate = createMemo(() => hitRate(stats()))
|
|
18
|
-
const theme = props.context.theme
|
|
19
|
-
|
|
20
|
-
const rateColor = () => {
|
|
21
|
-
const r = rate()
|
|
22
|
-
if (r >= 85) return theme.text.feedback.success.default
|
|
23
|
-
if (r >= 70) return theme.text.feedback.warning.default
|
|
24
|
-
return theme.text.feedback.error.default
|
|
25
|
-
}
|
|
26
|
-
const barWidth = () =>
|
|
27
|
-
Math.max(MIN_PANEL_WIDTH, Math.min(DEFAULT_PANEL_WIDTH, props.context.app.version ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_WIDTH)) -
|
|
28
|
-
LABEL_GAP - BAR_BRACKETS - BAR_GAP - PCT_FIXED_WIDTH - 1
|
|
29
|
-
|
|
30
|
-
const rows = () => {
|
|
31
|
-
const s = stats()
|
|
32
|
-
return [
|
|
33
|
-
{ label: "Hit", value: fmt(s.cacheRead) + " tok", color: rateColor() },
|
|
34
|
-
{ label: "Miss", value: fmt(s.input + s.cacheWrite) + " tok", color: theme.text.default },
|
|
35
|
-
{ label: "Write", value: fmt(s.cacheWrite) + " tok", color: theme.text.subdued },
|
|
36
|
-
{ label: "Out", value: fmt(s.output) + " tok", color: theme.text.subdued },
|
|
37
|
-
]
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Show when={stats().hasData}>
|
|
42
|
-
<box>
|
|
43
|
-
<box flexDirection="row" gap={LABEL_GAP}>
|
|
44
|
-
<text fg={theme.text.default}>Cache</text>
|
|
45
|
-
<text fg={rateColor()}>
|
|
46
|
-
{"["}
|
|
47
|
-
{progressBar(rate(), barWidth())}
|
|
48
|
-
{"]"}
|
|
49
|
-
</text>
|
|
50
|
-
<text fg={rateColor()}>{rate().toFixed(1) + "%"}</text>
|
|
51
|
-
</box>
|
|
52
|
-
<For each={rows()}>
|
|
53
|
-
{(row) => (
|
|
54
|
-
<box flexDirection="row" gap={LABEL_GAP}>
|
|
55
|
-
<text fg={theme.text.default}>{visualPadEnd(row.label, 5)}</text>
|
|
56
|
-
<text fg={row.color}>{row.value}</text>
|
|
57
|
-
</box>
|
|
58
|
-
)}
|
|
59
|
-
</For>
|
|
60
|
-
<Show when={stats().cost > 0}>
|
|
61
|
-
<box flexDirection="row" gap={LABEL_GAP}>
|
|
62
|
-
<text fg={theme.text.default}>{"Cost"}</text>
|
|
63
|
-
<text fg={theme.text.default}>{fmtCost(stats().cost)}</text>
|
|
64
|
-
</box>
|
|
65
|
-
</Show>
|
|
66
|
-
</box>
|
|
67
|
-
</Show>
|
|
68
|
-
)
|
|
69
|
-
}
|
|
1
|
+
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
|
|
3
|
+
import { createMemo, For, Show } from "solid-js"
|
|
4
|
+
import type { Context } from "./types"
|
|
5
|
+
import { collectSessionStats, hitRate } from "./data"
|
|
6
|
+
import { fmt, fmtCost, progressBar, visualPadEnd } from "../core"
|
|
7
|
+
|
|
8
|
+
const LABEL_GAP = 1
|
|
9
|
+
const BAR_BRACKETS = 2
|
|
10
|
+
const BAR_GAP = 1
|
|
11
|
+
const PCT_FIXED_WIDTH = 5
|
|
12
|
+
const MIN_PANEL_WIDTH = 20
|
|
13
|
+
const DEFAULT_PANEL_WIDTH = 26
|
|
14
|
+
|
|
15
|
+
export function SidebarView(props: { context: Context; sessionID: string }) {
|
|
16
|
+
const stats = createMemo(() => collectSessionStats(props.context, props.sessionID))
|
|
17
|
+
const rate = createMemo(() => hitRate(stats()))
|
|
18
|
+
const theme = props.context.theme
|
|
19
|
+
|
|
20
|
+
const rateColor = () => {
|
|
21
|
+
const r = rate()
|
|
22
|
+
if (r >= 85) return theme.text.feedback.success.default
|
|
23
|
+
if (r >= 70) return theme.text.feedback.warning.default
|
|
24
|
+
return theme.text.feedback.error.default
|
|
25
|
+
}
|
|
26
|
+
const barWidth = () =>
|
|
27
|
+
Math.max(MIN_PANEL_WIDTH, Math.min(DEFAULT_PANEL_WIDTH, props.context.app.version ? DEFAULT_PANEL_WIDTH : DEFAULT_PANEL_WIDTH)) -
|
|
28
|
+
LABEL_GAP - BAR_BRACKETS - BAR_GAP - PCT_FIXED_WIDTH - 1
|
|
29
|
+
|
|
30
|
+
const rows = () => {
|
|
31
|
+
const s = stats()
|
|
32
|
+
return [
|
|
33
|
+
{ label: "Hit", value: fmt(s.cacheRead) + " tok", color: rateColor() },
|
|
34
|
+
{ label: "Miss", value: fmt(s.input + s.cacheWrite) + " tok", color: theme.text.default },
|
|
35
|
+
{ label: "Write", value: fmt(s.cacheWrite) + " tok", color: theme.text.subdued },
|
|
36
|
+
{ label: "Out", value: fmt(s.output) + " tok", color: theme.text.subdued },
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Show when={stats().hasData}>
|
|
42
|
+
<box>
|
|
43
|
+
<box flexDirection="row" gap={LABEL_GAP}>
|
|
44
|
+
<text fg={theme.text.default}>Cache</text>
|
|
45
|
+
<text fg={rateColor()}>
|
|
46
|
+
{"["}
|
|
47
|
+
{progressBar(rate(), barWidth())}
|
|
48
|
+
{"]"}
|
|
49
|
+
</text>
|
|
50
|
+
<text fg={rateColor()}>{rate().toFixed(1) + "%"}</text>
|
|
51
|
+
</box>
|
|
52
|
+
<For each={rows()}>
|
|
53
|
+
{(row) => (
|
|
54
|
+
<box flexDirection="row" gap={LABEL_GAP}>
|
|
55
|
+
<text fg={theme.text.default}>{visualPadEnd(row.label, 5)}</text>
|
|
56
|
+
<text fg={row.color}>{row.value}</text>
|
|
57
|
+
</box>
|
|
58
|
+
)}
|
|
59
|
+
</For>
|
|
60
|
+
<Show when={stats().cost > 0}>
|
|
61
|
+
<box flexDirection="row" gap={LABEL_GAP}>
|
|
62
|
+
<text fg={theme.text.default}>{"Cost"}</text>
|
|
63
|
+
<text fg={theme.text.default}>{fmtCost(stats().cost)}</text>
|
|
64
|
+
</box>
|
|
65
|
+
</Show>
|
|
66
|
+
</box>
|
|
67
|
+
</Show>
|
|
68
|
+
)
|
|
69
|
+
}
|
package/src/v2/status.tsx
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
/** @jsxImportSource @opentui/solid */
|
|
2
|
-
|
|
3
|
-
import { createMemo, For, Show } from "solid-js"
|
|
4
|
-
import type { Context } from "./types"
|
|
5
|
-
import type { PanelSignals } from "../panel/panel-api"
|
|
6
|
-
import { collectLastHitRate } from "./data"
|
|
7
|
-
import { desaturateTo, fmtCompact, formatBalanceText, MAX_SAT, FALLBACK, visualWidth } from "../core"
|
|
8
|
-
import { createT } from "../i18n"
|
|
9
|
-
import { mapTheme } from "./theme"
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 底部状态栏(prompt.footer.status)——对齐 V1 BottomStatusBar 统计段口径:
|
|
13
|
-
* 单条命中率(最后一条有 token 的 assistant 消息)+ 趋势 + Tokens 总量 + 余额。
|
|
14
|
-
* 余额读共享 signals.balanceState(PluginRoot 驱动轮询);provider 不支持余额时隐藏余额段(对齐 V1)。
|
|
15
|
-
* 颜色经 mapTheme(V1 形状)——与侧边栏命中率颜色同源,保证两处一致。
|
|
16
|
-
*/
|
|
17
|
-
export function StatusView(props: {
|
|
18
|
-
context: Context
|
|
19
|
-
signals: PanelSignals
|
|
20
|
-
sessionID: string
|
|
21
|
-
}) {
|
|
22
|
-
const t = createT(() => props.signals.langCode())
|
|
23
|
-
|
|
24
|
-
// 与侧边栏 TokenCachePanel 同一颜色来源(mapTheme → desaturateTo)
|
|
25
|
-
const pal = createMemo(() => {
|
|
26
|
-
const th = mapTheme(props.context.theme) as unknown as Record<string, string>
|
|
27
|
-
const sat = (k: string, fb: string) => desaturateTo(th[k], MAX_SAT, fb)
|
|
28
|
-
return {
|
|
29
|
-
text: sat("text", FALLBACK.text),
|
|
30
|
-
muted: sat("textMuted", FALLBACK.muted),
|
|
31
|
-
success: sat("success", FALLBACK.success),
|
|
32
|
-
warning: sat("warning", FALLBACK.warning),
|
|
33
|
-
error: sat("error", FALLBACK.error),
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const stats = createMemo(() => collectLastHitRate(props.context, props.sessionID))
|
|
38
|
-
|
|
39
|
-
const hitColor = createMemo(() => {
|
|
40
|
-
const r = stats().hitRate
|
|
41
|
-
if (r >= 85) return pal().success
|
|
42
|
-
if (r >= 70) return pal().warning
|
|
43
|
-
return pal().error
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// 命中率趋势:最后一条与上一条的差值;|Δ| < 0.05 视为无变化(null = 不显示)
|
|
47
|
-
const trend = createMemo(() => {
|
|
48
|
-
const s = stats()
|
|
49
|
-
if (s.prevHitRate < 0 || s.hitRate < 0) return null
|
|
50
|
-
const d = s.hitRate - s.prevHitRate
|
|
51
|
-
return Math.abs(d) < 0.05 ? null : d
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// 余额文本(对齐 V1):ok → 数值;loading → …;error → ⚠;idle → -
|
|
55
|
-
const balanceText = createMemo(() => {
|
|
56
|
-
const s = props.signals.balanceState()
|
|
57
|
-
if (s.status === "ok" && s.data) return formatBalanceText(s.data, props.signals.balanceCurrency(), props.signals.exchangeRate())
|
|
58
|
-
if (s.status === "loading") return "\u2026"
|
|
59
|
-
if (s.status === "error") return "\u26a0"
|
|
60
|
-
return "-"
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const segs = createMemo<{ text: string; color: string | undefined }[]>(() => {
|
|
64
|
-
const s = stats()
|
|
65
|
-
const hr = s.hitRate >= 0 ? (Math.floor(s.hitRate * 10) / 10).toFixed(1) + "%" : "--"
|
|
66
|
-
const out: { text: string; color: string | undefined }[] = [
|
|
67
|
-
{ text: t("barHit") + " ", color: pal().muted },
|
|
68
|
-
{ text: hr, color: hitColor() },
|
|
69
|
-
]
|
|
70
|
-
const tr = trend()
|
|
71
|
-
if (tr !== null) {
|
|
72
|
-
out.push({ text: " " + (tr > 0 ? "\u2191" : "\u2193") + Math.abs(tr).toFixed(1) + "%", color: tr > 0 ? pal().success : pal().error })
|
|
73
|
-
}
|
|
74
|
-
out.push({ text: " \u00b7 " + t("barTok") + " ", color: pal().muted })
|
|
75
|
-
out.push({ text: s ? fmtCompact(s.input + s.read + s.write) : "--", color: pal().text })
|
|
76
|
-
if (!props.signals.balanceUnsupported()) {
|
|
77
|
-
out.push({ text: " \u00b7 " + t("barBal") + " ", color: pal().muted })
|
|
78
|
-
out.push({ text: balanceText(), color: pal().text })
|
|
79
|
-
}
|
|
80
|
-
out.push({ text: " \u00b7 ", color: pal().muted })
|
|
81
|
-
return out
|
|
82
|
-
})
|
|
83
|
-
const segsW = createMemo(() => {
|
|
84
|
-
let w = 0
|
|
85
|
-
for (const sg of segs()) w += visualWidth(sg.text)
|
|
86
|
-
return w
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<Show when={segsW() > 0}>
|
|
91
|
-
<text>
|
|
92
|
-
<For each={segs()}>{(sg) => <span style={{ fg: sg.color }}>{sg.text}</span>}</For>
|
|
93
|
-
</text>
|
|
94
|
-
</Show>
|
|
95
|
-
)
|
|
96
|
-
}
|
|
1
|
+
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
|
|
3
|
+
import { createMemo, For, Show } from "solid-js"
|
|
4
|
+
import type { Context } from "./types"
|
|
5
|
+
import type { PanelSignals } from "../panel/panel-api"
|
|
6
|
+
import { collectLastHitRate } from "./data"
|
|
7
|
+
import { desaturateTo, fmtCompact, formatBalanceText, MAX_SAT, FALLBACK, visualWidth } from "../core"
|
|
8
|
+
import { createT } from "../i18n"
|
|
9
|
+
import { mapTheme } from "./theme"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 底部状态栏(prompt.footer.status)——对齐 V1 BottomStatusBar 统计段口径:
|
|
13
|
+
* 单条命中率(最后一条有 token 的 assistant 消息)+ 趋势 + Tokens 总量 + 余额。
|
|
14
|
+
* 余额读共享 signals.balanceState(PluginRoot 驱动轮询);provider 不支持余额时隐藏余额段(对齐 V1)。
|
|
15
|
+
* 颜色经 mapTheme(V1 形状)——与侧边栏命中率颜色同源,保证两处一致。
|
|
16
|
+
*/
|
|
17
|
+
export function StatusView(props: {
|
|
18
|
+
context: Context
|
|
19
|
+
signals: PanelSignals
|
|
20
|
+
sessionID: string
|
|
21
|
+
}) {
|
|
22
|
+
const t = createT(() => props.signals.langCode())
|
|
23
|
+
|
|
24
|
+
// 与侧边栏 TokenCachePanel 同一颜色来源(mapTheme → desaturateTo)
|
|
25
|
+
const pal = createMemo(() => {
|
|
26
|
+
const th = mapTheme(props.context.theme) as unknown as Record<string, string>
|
|
27
|
+
const sat = (k: string, fb: string) => desaturateTo(th[k], MAX_SAT, fb)
|
|
28
|
+
return {
|
|
29
|
+
text: sat("text", FALLBACK.text),
|
|
30
|
+
muted: sat("textMuted", FALLBACK.muted),
|
|
31
|
+
success: sat("success", FALLBACK.success),
|
|
32
|
+
warning: sat("warning", FALLBACK.warning),
|
|
33
|
+
error: sat("error", FALLBACK.error),
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const stats = createMemo(() => collectLastHitRate(props.context, props.sessionID))
|
|
38
|
+
|
|
39
|
+
const hitColor = createMemo(() => {
|
|
40
|
+
const r = stats().hitRate
|
|
41
|
+
if (r >= 85) return pal().success
|
|
42
|
+
if (r >= 70) return pal().warning
|
|
43
|
+
return pal().error
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// 命中率趋势:最后一条与上一条的差值;|Δ| < 0.05 视为无变化(null = 不显示)
|
|
47
|
+
const trend = createMemo(() => {
|
|
48
|
+
const s = stats()
|
|
49
|
+
if (s.prevHitRate < 0 || s.hitRate < 0) return null
|
|
50
|
+
const d = s.hitRate - s.prevHitRate
|
|
51
|
+
return Math.abs(d) < 0.05 ? null : d
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// 余额文本(对齐 V1):ok → 数值;loading → …;error → ⚠;idle → -
|
|
55
|
+
const balanceText = createMemo(() => {
|
|
56
|
+
const s = props.signals.balanceState()
|
|
57
|
+
if (s.status === "ok" && s.data) return formatBalanceText(s.data, props.signals.balanceCurrency(), props.signals.exchangeRate())
|
|
58
|
+
if (s.status === "loading") return "\u2026"
|
|
59
|
+
if (s.status === "error") return "\u26a0"
|
|
60
|
+
return "-"
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const segs = createMemo<{ text: string; color: string | undefined }[]>(() => {
|
|
64
|
+
const s = stats()
|
|
65
|
+
const hr = s.hitRate >= 0 ? (Math.floor(s.hitRate * 10) / 10).toFixed(1) + "%" : "--"
|
|
66
|
+
const out: { text: string; color: string | undefined }[] = [
|
|
67
|
+
{ text: t("barHit") + " ", color: pal().muted },
|
|
68
|
+
{ text: hr, color: hitColor() },
|
|
69
|
+
]
|
|
70
|
+
const tr = trend()
|
|
71
|
+
if (tr !== null) {
|
|
72
|
+
out.push({ text: " " + (tr > 0 ? "\u2191" : "\u2193") + Math.abs(tr).toFixed(1) + "%", color: tr > 0 ? pal().success : pal().error })
|
|
73
|
+
}
|
|
74
|
+
out.push({ text: " \u00b7 " + t("barTok") + " ", color: pal().muted })
|
|
75
|
+
out.push({ text: s ? fmtCompact(s.input + s.read + s.write) : "--", color: pal().text })
|
|
76
|
+
if (!props.signals.balanceUnsupported()) {
|
|
77
|
+
out.push({ text: " \u00b7 " + t("barBal") + " ", color: pal().muted })
|
|
78
|
+
out.push({ text: balanceText(), color: pal().text })
|
|
79
|
+
}
|
|
80
|
+
out.push({ text: " \u00b7 ", color: pal().muted })
|
|
81
|
+
return out
|
|
82
|
+
})
|
|
83
|
+
const segsW = createMemo(() => {
|
|
84
|
+
let w = 0
|
|
85
|
+
for (const sg of segs()) w += visualWidth(sg.text)
|
|
86
|
+
return w
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Show when={segsW() > 0}>
|
|
91
|
+
<text>
|
|
92
|
+
<For each={segs()}>{(sg) => <span style={{ fg: sg.color }}>{sg.text}</span>}</For>
|
|
93
|
+
</text>
|
|
94
|
+
</Show>
|
|
95
|
+
)
|
|
96
|
+
}
|
package/src/v2/theme.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui"
|
|
2
|
-
import type { Context } from "./types"
|
|
3
|
-
|
|
4
|
-
/** V2 theme → V1 形状映射(组件按 primary/text/textMuted/… 字段消费)。
|
|
5
|
-
* 侧边栏与底部栏共用——保证命中率颜色等两处一致。
|
|
6
|
-
* - V1 primary → V2 interactive(v1-migrate.ts 官方映射:interactive = hues.byToken.primary)
|
|
7
|
-
* - step 取 300:更亮(对齐 V2 暗色强调惯例的亮端),500/400 在暗背景下偏深
|
|
8
|
-
*/
|
|
9
|
-
export function mapTheme(theme: Context["theme"]): TuiThemeCurrent {
|
|
10
|
-
return {
|
|
11
|
-
primary: theme.hue.interactive[300],
|
|
12
|
-
text: theme.text.default,
|
|
13
|
-
textMuted: theme.text.subdued,
|
|
14
|
-
success: theme.text.feedback.success.default,
|
|
15
|
-
warning: theme.text.feedback.warning.default,
|
|
16
|
-
error: theme.text.feedback.error.default,
|
|
17
|
-
border: theme.text.subdued,
|
|
18
|
-
} as unknown as TuiThemeCurrent
|
|
19
|
-
}
|
|
1
|
+
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui"
|
|
2
|
+
import type { Context } from "./types"
|
|
3
|
+
|
|
4
|
+
/** V2 theme → V1 形状映射(组件按 primary/text/textMuted/… 字段消费)。
|
|
5
|
+
* 侧边栏与底部栏共用——保证命中率颜色等两处一致。
|
|
6
|
+
* - V1 primary → V2 interactive(v1-migrate.ts 官方映射:interactive = hues.byToken.primary)
|
|
7
|
+
* - step 取 300:更亮(对齐 V2 暗色强调惯例的亮端),500/400 在暗背景下偏深
|
|
8
|
+
*/
|
|
9
|
+
export function mapTheme(theme: Context["theme"]): TuiThemeCurrent {
|
|
10
|
+
return {
|
|
11
|
+
primary: theme.hue.interactive[300],
|
|
12
|
+
text: theme.text.default,
|
|
13
|
+
textMuted: theme.text.subdued,
|
|
14
|
+
success: theme.text.feedback.success.default,
|
|
15
|
+
warning: theme.text.feedback.warning.default,
|
|
16
|
+
error: theme.text.feedback.error.default,
|
|
17
|
+
border: theme.text.subdued,
|
|
18
|
+
} as unknown as TuiThemeCurrent
|
|
19
|
+
}
|