dsh-coding-subscription-oauth 0.5.6 → 0.5.8
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 +21 -0
- package/CONTRIBUTING.md +12 -1
- package/INSTALL.md +4 -4
- package/README.de.md +4 -4
- package/README.es.md +4 -4
- package/README.fr.md +4 -4
- package/README.ja.md +4 -4
- package/README.ko.md +4 -4
- package/README.md +4 -4
- package/README.pt-BR.md +4 -4
- package/README.ru.md +4 -4
- package/README.zh-CN.md +4 -4
- package/docs/02-architecture.md +1 -1
- package/docs/02-architecture.zh-CN.md +1 -1
- package/lib/client.js +3 -3
- package/lib/client.js.map +3 -3
- package/package.json +1 -1
- package/scripts/release.mjs +4 -0
- package/src/client/components/AboutTab.tsx +12 -2
- package/src/client/components/GatewayTab.tsx +81 -36
- package/src/client/components/ProgressBar.tsx +3 -2
- package/src/client/components/ToggleSwitch.tsx +4 -2
- package/src/client/constants.ts +1 -1
- package/src/client/locales.ts +4 -0
- package/src/client/styles.ts +19 -18
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-coding-subscription-oauth",
|
|
3
3
|
"description": "DeepSeek Harness coding-subscription OAuth: SuperGrok/Grok Build, ChatGPT Plus Codex, Kimi Code, Claude Code. Fixes AUTH API key is invalid, INVALID_REPLAY_STATE, grok-4.6 xhigh, Kimi Bearer vs x-api-key.",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.8",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
package/scripts/release.mjs
CHANGED
|
@@ -73,6 +73,10 @@ if (releaseVersions[0] !== manifest.version) {
|
|
|
73
73
|
fail(`top CHANGELOG release (${releaseVersions[0] ?? "missing"}) does not match package version ${manifest.version}`);
|
|
74
74
|
}
|
|
75
75
|
if (!readme.includes(manifest.version)) fail(`README.md does not mention ${manifest.version}`);
|
|
76
|
+
const installDoc = await readFile(join(root, "INSTALL.md"), "utf8");
|
|
77
|
+
if (!installDoc.includes(manifest.version)) fail(`INSTALL.md does not mention ${manifest.version}`);
|
|
78
|
+
const readmeZh = await readFile(join(root, "README.zh-CN.md"), "utf8");
|
|
79
|
+
if (!readmeZh.includes(manifest.version)) fail(`README.zh-CN.md does not mention ${manifest.version}`);
|
|
76
80
|
|
|
77
81
|
if (mode === "pack") run("pnpm", ["run", "release:build"]);
|
|
78
82
|
else run("pnpm", ["run", "release:verify"]);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/** About tab: terms, remote help, and plugin version. */
|
|
2
2
|
|
|
3
3
|
import { PLUGIN_VERSION } from "../constants.ts";
|
|
4
|
-
import { bodyStyle, cardStyle, hintStyle, warningStyle } from "../styles.ts";
|
|
4
|
+
import { bodyStyle, cardStyle, hintStyle, linkStyle, titleStyle, warningStyle } from "../styles.ts";
|
|
5
5
|
import type { GrokBuildSettingsInjected } from "../types.ts";
|
|
6
6
|
|
|
7
|
+
const README_URL = "https://github.com/lninghaha/dsh-coding-subscription-oauth#readme";
|
|
8
|
+
|
|
7
9
|
export interface AboutTabProps {
|
|
8
10
|
t: GrokBuildSettingsInjected["t"];
|
|
9
11
|
}
|
|
@@ -11,10 +13,18 @@ export interface AboutTabProps {
|
|
|
11
13
|
export function AboutTab({ t }: AboutTabProps) {
|
|
12
14
|
return (
|
|
13
15
|
<section style={cardStyle} aria-labelledby="coding-oauth-about-title">
|
|
14
|
-
<
|
|
16
|
+
<h3 id="coding-oauth-about-title" style={{ ...titleStyle, fontSize: 16 }}>
|
|
17
|
+
{t("aboutTitle")}
|
|
18
|
+
</h3>
|
|
19
|
+
<p style={{ ...warningStyle, marginTop: 12 }}>{t("termsWarning")}</p>
|
|
15
20
|
<p style={{ ...bodyStyle, marginTop: 12 }}>{t("remoteLoginHelp")}</p>
|
|
16
21
|
<p style={{ ...hintStyle, marginTop: 12 }}>{t("pluginVersion", { version: PLUGIN_VERSION })}</p>
|
|
17
22
|
<p style={{ ...hintStyle, marginTop: 8 }}>{t("aboutDocsHint")}</p>
|
|
23
|
+
<p style={{ marginTop: 8 }}>
|
|
24
|
+
<a href={README_URL} target="_blank" rel="noreferrer" style={linkStyle}>
|
|
25
|
+
{t("aboutDocsLink")}
|
|
26
|
+
</a>
|
|
27
|
+
</p>
|
|
18
28
|
</section>
|
|
19
29
|
);
|
|
20
30
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Local API gateway settings tab. */
|
|
2
2
|
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
3
|
+
import { type KeyboardEvent, useMemo, useState } from "react";
|
|
4
4
|
import { GATEWAY_PORT_MAX, GATEWAY_PORT_MIN } from "../constants.ts";
|
|
5
5
|
import { buildGatewaySnippets, type GatewaySnippetId } from "../gatewaySnippets.ts";
|
|
6
6
|
import { formatGatewayBaseUrl, parseGatewayPort, randomGatewayPort } from "../parsers.ts";
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
bodyStyle,
|
|
9
9
|
buttonStyle,
|
|
10
10
|
cardStyle,
|
|
11
|
-
checkRowStyle,
|
|
12
11
|
copyRowStyle,
|
|
13
12
|
dotStyle,
|
|
14
13
|
errorStyle,
|
|
@@ -29,6 +28,7 @@ import {
|
|
|
29
28
|
import type { CopyField, GatewayView, GrokBuildSettingsInjected } from "../types.ts";
|
|
30
29
|
import { Badge } from "./Badge.tsx";
|
|
31
30
|
import { CopyButton } from "./CopyButton.tsx";
|
|
31
|
+
import { ToggleSwitch } from "./ToggleSwitch.tsx";
|
|
32
32
|
|
|
33
33
|
export interface GatewayTabProps {
|
|
34
34
|
t: GrokBuildSettingsInjected["t"];
|
|
@@ -79,7 +79,6 @@ export function GatewayTab({
|
|
|
79
79
|
onPortDraftChange,
|
|
80
80
|
onApplyPort,
|
|
81
81
|
onRandomPort,
|
|
82
|
-
onCopy,
|
|
83
82
|
onCopyKey,
|
|
84
83
|
onToggleKeyVisible,
|
|
85
84
|
onRotateConfirm,
|
|
@@ -111,6 +110,34 @@ export function GatewayTab({
|
|
|
111
110
|
return idle ?? t("copy");
|
|
112
111
|
};
|
|
113
112
|
|
|
113
|
+
const focusSnippetTab = (index: number): void => {
|
|
114
|
+
const tab = SNIPPET_TABS[index];
|
|
115
|
+
if (tab === undefined) return;
|
|
116
|
+
setActiveSnippet(tab.id);
|
|
117
|
+
document.getElementById(`coding-oauth-snippet-tab-${tab.id}`)?.focus();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const onSnippetKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
|
|
121
|
+
const current = SNIPPET_TABS.findIndex((tab) => tab.id === activeSnippet);
|
|
122
|
+
if (current < 0) return;
|
|
123
|
+
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
focusSnippetTab((current + 1) % SNIPPET_TABS.length);
|
|
126
|
+
} else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
focusSnippetTab((current - 1 + SNIPPET_TABS.length) % SNIPPET_TABS.length);
|
|
129
|
+
} else if (event.key === "Home") {
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
focusSnippetTab(0);
|
|
132
|
+
} else if (event.key === "End") {
|
|
133
|
+
event.preventDefault();
|
|
134
|
+
focusSnippetTab(SNIPPET_TABS.length - 1);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const openAiUrl = gateway === undefined ? "" : `${formatGatewayBaseUrl(gateway.bind, gateway.port)}/v1`;
|
|
139
|
+
const anthropicUrl = gateway === undefined ? "" : formatGatewayBaseUrl(gateway.bind, gateway.port);
|
|
140
|
+
|
|
114
141
|
return (
|
|
115
142
|
<section style={cardStyle} aria-labelledby="coding-oauth-gateway-title">
|
|
116
143
|
<div>
|
|
@@ -138,7 +165,11 @@ export function GatewayTab({
|
|
|
138
165
|
{t("gatewayLoading")}
|
|
139
166
|
</div>
|
|
140
167
|
</div>
|
|
141
|
-
) : gateway === undefined ?
|
|
168
|
+
) : gateway === undefined ? (
|
|
169
|
+
<p style={hintStyle} role="status">
|
|
170
|
+
{t("gatewayLoadFailed")}
|
|
171
|
+
</p>
|
|
172
|
+
) : (
|
|
142
173
|
<div style={nestedStyle}>
|
|
143
174
|
<Badge
|
|
144
175
|
label={gateway.running ? t("gatewayRunning") : t("gatewayStopped")}
|
|
@@ -172,13 +203,23 @@ export function GatewayTab({
|
|
|
172
203
|
</div>
|
|
173
204
|
</div>
|
|
174
205
|
) : (
|
|
175
|
-
<label
|
|
176
|
-
|
|
177
|
-
|
|
206
|
+
<label
|
|
207
|
+
htmlFor="coding-oauth-gateway-enabled"
|
|
208
|
+
style={{
|
|
209
|
+
display: "flex",
|
|
210
|
+
alignItems: "center",
|
|
211
|
+
justifyContent: "space-between",
|
|
212
|
+
gap: 12,
|
|
213
|
+
fontSize: 14,
|
|
214
|
+
color: "var(--dsw-alias-label-primary)",
|
|
215
|
+
}}
|
|
216
|
+
>
|
|
217
|
+
<span>{t("gatewayEnabled")}</span>
|
|
218
|
+
<ToggleSwitch
|
|
219
|
+
id="coding-oauth-gateway-enabled"
|
|
178
220
|
checked={gateway.enabled}
|
|
179
221
|
disabled={gatewayBusy}
|
|
180
|
-
onChange={(
|
|
181
|
-
const enabled = event.target.checked;
|
|
222
|
+
onChange={(enabled) => {
|
|
182
223
|
if (enabled) {
|
|
183
224
|
setEnableConfirm(true);
|
|
184
225
|
return;
|
|
@@ -186,7 +227,6 @@ export function GatewayTab({
|
|
|
186
227
|
onEnabledChange(false);
|
|
187
228
|
}}
|
|
188
229
|
/>
|
|
189
|
-
<span>{t("gatewayEnabled")}</span>
|
|
190
230
|
</label>
|
|
191
231
|
)}
|
|
192
232
|
<div>
|
|
@@ -261,34 +301,26 @@ export function GatewayTab({
|
|
|
261
301
|
<p style={copyRowStyle}>
|
|
262
302
|
<span style={hintStyle}>
|
|
263
303
|
{t("gatewayOpenAiUrl")}
|
|
264
|
-
<span style={{ display: "block", ...monoStyle }}>
|
|
265
|
-
{`${formatGatewayBaseUrl(gateway.bind, gateway.port)}/v1`}
|
|
266
|
-
</span>
|
|
304
|
+
<span style={{ display: "block", ...monoStyle }}>{openAiUrl}</span>
|
|
267
305
|
</span>
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
>
|
|
275
|
-
{copyLabel("openai")}
|
|
276
|
-
</button>
|
|
306
|
+
<CopyButton
|
|
307
|
+
text={openAiUrl}
|
|
308
|
+
idleLabel={t("copy")}
|
|
309
|
+
copiedLabel={t("copied")}
|
|
310
|
+
failedLabel={t("copyFailed")}
|
|
311
|
+
/>
|
|
277
312
|
</p>
|
|
278
313
|
<p style={copyRowStyle}>
|
|
279
314
|
<span style={hintStyle}>
|
|
280
315
|
{t("gatewayAnthropicUrl")}
|
|
281
|
-
<span style={{ display: "block", ...monoStyle }}>{
|
|
316
|
+
<span style={{ display: "block", ...monoStyle }}>{anthropicUrl}</span>
|
|
282
317
|
</span>
|
|
283
|
-
<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
>
|
|
290
|
-
{copyLabel("anthropic")}
|
|
291
|
-
</button>
|
|
318
|
+
<CopyButton
|
|
319
|
+
text={anthropicUrl}
|
|
320
|
+
idleLabel={t("copy")}
|
|
321
|
+
copiedLabel={t("copied")}
|
|
322
|
+
failedLabel={t("copyFailed")}
|
|
323
|
+
/>
|
|
292
324
|
</p>
|
|
293
325
|
<p style={copyRowStyle}>
|
|
294
326
|
<span style={hintStyle}>
|
|
@@ -310,15 +342,23 @@ export function GatewayTab({
|
|
|
310
342
|
{gateway.enabled && snippets !== undefined ? (
|
|
311
343
|
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
|
|
312
344
|
<h4 style={{ ...titleStyle, fontSize: 14 }}>{t("gatewaySnippetsTitle")}</h4>
|
|
313
|
-
<div
|
|
345
|
+
<div
|
|
346
|
+
role="tablist"
|
|
347
|
+
aria-label={t("gatewaySnippetsTitle")}
|
|
348
|
+
style={segmentedNavStyle}
|
|
349
|
+
onKeyDown={onSnippetKeyDown}
|
|
350
|
+
>
|
|
314
351
|
{SNIPPET_TABS.map((tab) => {
|
|
315
352
|
const selected = activeSnippet === tab.id;
|
|
316
353
|
return (
|
|
317
354
|
<button
|
|
318
355
|
key={tab.id}
|
|
356
|
+
id={`coding-oauth-snippet-tab-${tab.id}`}
|
|
319
357
|
type="button"
|
|
320
358
|
role="tab"
|
|
321
359
|
aria-selected={selected}
|
|
360
|
+
aria-controls="coding-oauth-snippet-panel"
|
|
361
|
+
tabIndex={selected ? 0 : -1}
|
|
322
362
|
style={selected ? segmentedTabActiveStyle : segmentedTabStyle}
|
|
323
363
|
onClick={() => {
|
|
324
364
|
setActiveSnippet(tab.id);
|
|
@@ -329,13 +369,18 @@ export function GatewayTab({
|
|
|
329
369
|
);
|
|
330
370
|
})}
|
|
331
371
|
</div>
|
|
332
|
-
<
|
|
372
|
+
<div
|
|
373
|
+
id="coding-oauth-snippet-panel"
|
|
374
|
+
role="tabpanel"
|
|
375
|
+
aria-labelledby={`coding-oauth-snippet-tab-${activeSnippet}`}
|
|
376
|
+
>
|
|
377
|
+
<code style={snippetStyle}>{snippets[activeSnippet]}</code>
|
|
378
|
+
</div>
|
|
333
379
|
<CopyButton
|
|
334
380
|
text={snippets[activeSnippet]}
|
|
335
381
|
idleLabel={t("copy")}
|
|
336
382
|
copiedLabel={t("copied")}
|
|
337
383
|
failedLabel={t("copyFailed")}
|
|
338
|
-
primary
|
|
339
384
|
/>
|
|
340
385
|
</div>
|
|
341
386
|
) : null}
|
|
@@ -344,7 +389,7 @@ export function GatewayTab({
|
|
|
344
389
|
<p style={bodyStyle}>{t("gatewayRotateConfirm")}</p>
|
|
345
390
|
<p style={hintStyle}>{t("gatewayRotateConfirmHint")}</p>
|
|
346
391
|
<div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
|
|
347
|
-
<button type="button" style={
|
|
392
|
+
<button type="button" style={primaryButtonStyle} disabled={gatewayBusy} onClick={onRotate}>
|
|
348
393
|
{t("gatewayRotateConfirmAction")}
|
|
349
394
|
</button>
|
|
350
395
|
<button type="button" style={buttonStyle} disabled={gatewayBusy} onClick={onRotateCancel}>
|
|
@@ -11,8 +11,9 @@ export interface ProgressBarProps {
|
|
|
11
11
|
|
|
12
12
|
function barColor(percent: number): string {
|
|
13
13
|
if (percent >= 90) return "var(--dsw-alias-state-error-primary, #d92d20)";
|
|
14
|
-
if (percent >= 75) return "var(--dsw-alias-state-
|
|
15
|
-
|
|
14
|
+
if (percent >= 75) return "var(--dsw-alias-state-warn-primary, #e06c00)";
|
|
15
|
+
// Prefer info fill over brand-primary: dark theme inverts brand-primary to near-white.
|
|
16
|
+
return "var(--dsw-alias-button-info-fill, var(--dsw-static-deepseek-500, #4f6ef7))";
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function ProgressBar({ value, label, meta }: ProgressBarProps) {
|
|
@@ -19,7 +19,7 @@ const trackStyle = (checked: boolean, disabled: boolean): CSSProperties => ({
|
|
|
19
19
|
borderRadius: 11,
|
|
20
20
|
flex: "0 0 auto",
|
|
21
21
|
background: checked
|
|
22
|
-
? "var(--dsw-alias-
|
|
22
|
+
? "var(--dsw-alias-button-primary-fill)"
|
|
23
23
|
: "var(--dsw-alias-border-l4, rgba(127, 127, 127, 0.45))",
|
|
24
24
|
opacity: disabled ? 0.5 : 1,
|
|
25
25
|
cursor: disabled ? "not-allowed" : "pointer",
|
|
@@ -35,7 +35,9 @@ const thumbStyle = (checked: boolean): CSSProperties => ({
|
|
|
35
35
|
width: 18,
|
|
36
36
|
height: 18,
|
|
37
37
|
borderRadius: "50%",
|
|
38
|
-
|
|
38
|
+
// Match DSH primary fill/foreground pairing so the thumb stays visible when
|
|
39
|
+
// dark theme inverts brand-primary to near-white.
|
|
40
|
+
background: checked ? "var(--dsw-alias-label-primary-foreground)" : "var(--dsw-alias-button-elevated-fill)",
|
|
39
41
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.25)",
|
|
40
42
|
transition: TRANSITION,
|
|
41
43
|
});
|
package/src/client/constants.ts
CHANGED
package/src/client/locales.ts
CHANGED
|
@@ -226,8 +226,10 @@ export const en = {
|
|
|
226
226
|
remoteLoginHelp:
|
|
227
227
|
"On a remote DSH host, open Settings here and use device-code sign-in for each provider. Complete the code on any browser that can reach the provider, then return to chat and pick the provider route model.",
|
|
228
228
|
pluginVersion: "Plugin version {version}",
|
|
229
|
+
aboutTitle: "About",
|
|
229
230
|
aboutDocsHint:
|
|
230
231
|
"See the plugin README and INSTALL docs in the repository for setup, supported providers, and gateway safety notes.",
|
|
232
|
+
aboutDocsLink: "Open README on GitHub",
|
|
231
233
|
otherLoginMethods: "Other sign-in methods",
|
|
232
234
|
hideOtherLoginMethods: "Hide other methods",
|
|
233
235
|
signInStepOpen: "Open the provider authorization page",
|
|
@@ -466,7 +468,9 @@ export const zh: { [Key in GrokBuildSettingsKey]: string } = {
|
|
|
466
468
|
remoteLoginHelp:
|
|
467
469
|
"在远程 DSH 主机上,打开此处 Settings,对每个供应商使用设备码登录。在能访问供应商的任意浏览器完成验证码,再回到聊天选择对应路由模型。",
|
|
468
470
|
pluginVersion: "插件版本 {version}",
|
|
471
|
+
aboutTitle: "关于",
|
|
469
472
|
aboutDocsHint: "仓库中的 README 与 INSTALL 文档介绍了安装步骤、支持的供应商以及网关安全注意事项。",
|
|
473
|
+
aboutDocsLink: "在 GitHub 打开 README",
|
|
470
474
|
otherLoginMethods: "其他登录方式",
|
|
471
475
|
hideOtherLoginMethods: "收起其他方式",
|
|
472
476
|
signInStepOpen: "打开供应商授权页面",
|
package/src/client/styles.ts
CHANGED
|
@@ -61,9 +61,11 @@ export const buttonStyle: CSSProperties = {
|
|
|
61
61
|
};
|
|
62
62
|
export const primaryButtonStyle: CSSProperties = {
|
|
63
63
|
...buttonStyle,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
// DSH dark theme flips brand-primary to near-white; use the button/foreground
|
|
65
|
+
// pair so primary CTAs stay readable in both light and dark mode.
|
|
66
|
+
border: "none",
|
|
67
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
68
|
+
color: "var(--dsw-alias-label-primary-foreground)",
|
|
67
69
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.28)",
|
|
68
70
|
fontWeight: 600,
|
|
69
71
|
};
|
|
@@ -80,7 +82,9 @@ export const warningStyle: CSSProperties = {
|
|
|
80
82
|
...bodyStyle,
|
|
81
83
|
padding: "10px 12px",
|
|
82
84
|
borderRadius: 8,
|
|
83
|
-
|
|
85
|
+
border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e06c00) 35%, transparent)",
|
|
86
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary, #e06c00) 10%, transparent)",
|
|
87
|
+
color: "var(--dsw-alias-label-primary)",
|
|
84
88
|
};
|
|
85
89
|
export const tipStyle: CSSProperties = {
|
|
86
90
|
...bodyStyle,
|
|
@@ -234,9 +238,9 @@ export const stepNumberStyle: CSSProperties = {
|
|
|
234
238
|
};
|
|
235
239
|
export const stepNumberActiveStyle: CSSProperties = {
|
|
236
240
|
...stepNumberStyle,
|
|
237
|
-
background: "var(--dsw-alias-
|
|
238
|
-
borderColor: "var(--dsw-alias-
|
|
239
|
-
color: "
|
|
241
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
242
|
+
borderColor: "var(--dsw-alias-button-primary-fill)",
|
|
243
|
+
color: "var(--dsw-alias-label-primary-foreground)",
|
|
240
244
|
};
|
|
241
245
|
|
|
242
246
|
export type StatusTone = "success" | "error" | "warning" | "info" | "neutral";
|
|
@@ -248,11 +252,15 @@ export function statusToneColor(tone: StatusTone): string {
|
|
|
248
252
|
case "error":
|
|
249
253
|
return "var(--dsw-alias-state-error-primary, #d92d20)";
|
|
250
254
|
case "warning":
|
|
251
|
-
|
|
255
|
+
// DSH token is `state-warn-*` (not `state-warning-*`).
|
|
256
|
+
return "var(--dsw-alias-state-warn-primary, #e06c00)";
|
|
252
257
|
case "info":
|
|
258
|
+
// Accent/text color (not a solid fill + white text pair).
|
|
253
259
|
return "var(--dsw-alias-brand-primary, #1677ff)";
|
|
254
260
|
default:
|
|
255
|
-
|
|
261
|
+
// Prefer tertiary over dimmed: dimmed is near-invisible on light cards
|
|
262
|
+
// and too dark on dark cards.
|
|
263
|
+
return "var(--dsw-alias-label-tertiary, #81858c)";
|
|
256
264
|
}
|
|
257
265
|
}
|
|
258
266
|
|
|
@@ -279,14 +287,14 @@ export function dotStyle(
|
|
|
279
287
|
installed = true,
|
|
280
288
|
): CSSProperties {
|
|
281
289
|
const color = !installed
|
|
282
|
-
? "var(--dsw-alias-label-
|
|
290
|
+
? "var(--dsw-alias-label-tertiary, #81858c)"
|
|
283
291
|
: status === "signed-in" || status === "available"
|
|
284
292
|
? "var(--dsw-alias-state-success-primary, #22a06b)"
|
|
285
293
|
: status === "error"
|
|
286
294
|
? "var(--dsw-alias-state-error-primary, #d92d20)"
|
|
287
295
|
: status === "signing-in" || status === "loading"
|
|
288
296
|
? "var(--dsw-alias-brand-primary, #1677ff)"
|
|
289
|
-
: "var(--dsw-alias-label-
|
|
297
|
+
: "var(--dsw-alias-label-tertiary, #81858c)";
|
|
290
298
|
return { width: 9, height: 9, borderRadius: "50%", flex: "0 0 auto", background: color };
|
|
291
299
|
}
|
|
292
300
|
|
|
@@ -297,10 +305,3 @@ export function providerStatusTone(status: ProviderStatus["status"], installed =
|
|
|
297
305
|
if (status === "signing-in") return "info";
|
|
298
306
|
return "neutral";
|
|
299
307
|
}
|
|
300
|
-
|
|
301
|
-
/** @deprecated Use segmentedTabStyle / segmentedTabActiveStyle */
|
|
302
|
-
export const tabNavStyle: CSSProperties = segmentedNavStyle;
|
|
303
|
-
/** @deprecated Use segmentedTabStyle */
|
|
304
|
-
export const tabButtonStyle: CSSProperties = segmentedTabStyle;
|
|
305
|
-
/** @deprecated Use segmentedTabActiveStyle */
|
|
306
|
-
export const tabButtonActiveStyle: CSSProperties = segmentedTabActiveStyle;
|