dsh-subscriptions 0.1.3 → 0.1.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/README.md +64 -0
- package/lib/auth/rpc.d.ts +3 -1
- package/lib/auth/rpc.js +10 -1
- package/lib/client/ProviderAccountManager.js +34 -41
- package/lib/client/ProviderModelEditor.js +5 -9
- package/lib/client/SpeedSelect.js +8 -7
- package/lib/client/SubscriptionUsageBadge.js +6 -5
- package/lib/client/SubscriptionsSection.d.ts +22 -0
- package/lib/client/SubscriptionsSection.js +128 -38
- package/lib/client/UsageBadgeDisplaySetting.js +4 -8
- package/lib/client/host-contract.d.ts +1 -1
- package/lib/client/host-contract.js +22 -0
- package/lib/client/locales.d.ts +58 -0
- package/lib/client/locales.js +58 -0
- package/lib/client/provider-settings-styles.d.ts +3 -0
- package/lib/client/provider-settings-styles.js +206 -0
- package/lib/client/reset-action.d.ts +14 -0
- package/lib/client/reset-action.js +15 -0
- package/lib/client/reset-credits-view.d.ts +53 -0
- package/lib/client/reset-credits-view.js +103 -0
- package/lib/client.js +937 -310
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +9 -0
- package/lib/index.js +1099 -608
- package/lib/providers/account-preferences.js +3 -2
- package/lib/providers/catalog-store.d.ts +3 -2
- package/lib/providers/catalog-store.js +57 -26
- package/lib/providers/claude.d.ts +22 -3
- package/lib/providers/claude.js +113 -15
- package/lib/providers/codex.d.ts +15 -2
- package/lib/providers/codex.js +72 -4
- package/lib/providers/common.d.ts +25 -0
- package/lib/providers/common.js +22 -18
- package/lib/providers/copilot.d.ts +2 -1
- package/lib/providers/copilot.js +10 -3
- package/lib/providers/grok.d.ts +2 -2
- package/lib/providers/grok.js +2 -2
- package/lib/providers/pool-health.d.ts +2 -0
- package/lib/providers/pool-health.js +9 -0
- package/lib/providers/pool-usage.d.ts +13 -1
- package/lib/providers/pool-usage.js +39 -7
- package/lib/providers/pool.d.ts +7 -5
- package/lib/providers/pool.js +89 -12
- package/lib/providers/rate-limit.d.ts +0 -14
- package/lib/providers/rate-limit.js +0 -26
- package/lib/providers/replay.d.ts +4 -0
- package/lib/providers/replay.js +50 -0
- package/lib/providers/reset-redemption.d.ts +51 -0
- package/lib/providers/reset-redemption.js +102 -0
- package/lib/translate/anthropic.d.ts +21 -2
- package/lib/translate/anthropic.js +35 -11
- package/lib/translate/antigravity.js +13 -6
- package/lib/translate/chat-completions.js +1 -1
- package/lib/translate/resolved.d.ts +21 -0
- package/lib/translate/resolved.js +63 -3
- package/lib/translate/responses.js +8 -6
- package/lib/translate/sse.js +8 -0
- package/package.json +1 -1
|
@@ -10,15 +10,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
10
10
|
* design-platform.css values flip under `body[data-ds-dark-theme]`), and
|
|
11
11
|
* every user-visible string goes through the locale-bound `t` of the
|
|
12
12
|
* 'settings.subscriptions' namespace. Buttons and inputs take the
|
|
13
|
-
*
|
|
14
|
-
* express.
|
|
13
|
+
* native settings vocabulary with shared, scoped control states.
|
|
15
14
|
*/
|
|
16
15
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
17
16
|
import { en } from './locales.js';
|
|
17
|
+
import { resetActionBlock } from './reset-action.js';
|
|
18
18
|
import { ProviderAccountManager } from './ProviderAccountManager.js';
|
|
19
|
+
import { providerSettingsCss } from './provider-settings-styles.js';
|
|
19
20
|
import { ExternalUsageCards } from './ExternalUsageCards.js';
|
|
20
21
|
import { CursorCard } from './CursorCard.js';
|
|
21
22
|
import { UsageMeter } from './UsageMeter.js';
|
|
23
|
+
import { ResetCreditsDisclosure, ResetCreditsErrorLine, showsResetCredits } from './reset-credits-view.js';
|
|
22
24
|
import { displayUsedPercent } from './usage-pace.js';
|
|
23
25
|
import { UsageBadgeDisplaySetting } from './UsageBadgeDisplaySetting.js';
|
|
24
26
|
import { USAGE_BADGE_REFRESH_EVENT } from './usage-badge-preferences.js';
|
|
@@ -80,7 +82,10 @@ const styles = {
|
|
|
80
82
|
color: 'var(--dsw-alias-label-primary)',
|
|
81
83
|
},
|
|
82
84
|
intro: { margin: 0, color: 'var(--dsw-alias-label-tertiary)', fontSize: 14, lineHeight: '22px' },
|
|
83
|
-
card: cardStyles.card,
|
|
85
|
+
card: { ...cardStyles.card,
|
|
86
|
+
border: '0.5px solid var(--dsw-alias-settings-card-stroke, var(--dsw-alias-border-l4))',
|
|
87
|
+
borderRadius: 'var(--dsw-radius-xl, 20px)', background: 'var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2))',
|
|
88
|
+
},
|
|
84
89
|
cardHeader: cardStyles.header,
|
|
85
90
|
dot: cardStyles.dot,
|
|
86
91
|
name: cardStyles.name,
|
|
@@ -88,44 +93,46 @@ const styles = {
|
|
|
88
93
|
clientVersion: { fontSize: 12, lineHeight: '18px', color: 'var(--dsw-alias-label-tertiary)', fontVariantNumeric: 'tabular-nums' },
|
|
89
94
|
errorLine: cardStyles.error,
|
|
90
95
|
actions: cardStyles.actions,
|
|
91
|
-
|
|
92
|
-
usage: cardStyles.usage,
|
|
96
|
+
usage: { ...cardStyles.usage, borderTop: '0.5px solid var(--dsw-alias-border-l2)' },
|
|
93
97
|
usageHeader: cardStyles.usageHeader,
|
|
94
98
|
usageTitle: cardStyles.usageTitle,
|
|
95
99
|
usagePlan: cardStyles.usagePlan,
|
|
96
|
-
usageRefresh:
|
|
100
|
+
usageRefresh: { minHeight: 22, height: 22, padding: '0 8px', marginLeft: 'auto' },
|
|
97
101
|
usageRow: cardStyles.usageRow,
|
|
98
102
|
usageMeta: cardStyles.usageMeta,
|
|
99
|
-
accountRow: cardStyles.account,
|
|
103
|
+
accountRow: { ...cardStyles.account, border: '0.5px solid var(--dsw-alias-border-l2)', borderRadius: 'var(--dsw-radius-lg, 16px)' },
|
|
100
104
|
accountHeader: cardStyles.accountHeader,
|
|
101
105
|
accountName: cardStyles.accountName,
|
|
102
106
|
starButton: {
|
|
103
|
-
border: 'none',
|
|
107
|
+
border: 'none', padding: 0, width: 28,
|
|
104
108
|
font: 'inherit', fontSize: 14, lineHeight: '20px', cursor: 'pointer',
|
|
105
109
|
color: 'var(--dsw-alias-state-warn-label)',
|
|
106
110
|
},
|
|
107
111
|
deviceCode: {
|
|
108
112
|
marginTop: 4, display: 'flex', flexDirection: 'column', gap: 6,
|
|
109
|
-
border: '
|
|
113
|
+
border: '0.5px solid var(--dsw-alias-border-l2)', borderRadius: 'var(--dsw-radius-lg, 16px)',
|
|
110
114
|
padding: '10px 12px', background: 'var(--dsw-alias-bg-layer-1)',
|
|
111
115
|
},
|
|
112
116
|
deviceCodeText: {
|
|
113
117
|
fontFamily: 'monospace', fontSize: 18, lineHeight: '24px', letterSpacing: 2,
|
|
114
118
|
color: 'var(--dsw-alias-label-primary)', userSelect: 'all',
|
|
115
119
|
},
|
|
120
|
+
manual: { fontSize: 13, lineHeight: '20px' },
|
|
121
|
+
manualRow: { display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center', marginTop: 8 },
|
|
122
|
+
manualInput: { flex: '1 1 200px', minWidth: 0 },
|
|
116
123
|
modalOverlay: {
|
|
117
124
|
position: 'fixed', inset: 0, zIndex: 1000,
|
|
118
125
|
display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16,
|
|
119
|
-
background: '
|
|
126
|
+
background: 'var(--dsw-alias-bg-mask-1, #0006)', backdropFilter: 'var(--dsw-mask-blur, none)',
|
|
120
127
|
},
|
|
121
128
|
modal: {
|
|
122
129
|
width: 460, maxWidth: '100%', maxHeight: '90vh', overflowY: 'auto',
|
|
123
130
|
boxSizing: 'border-box', display: 'flex', flexDirection: 'column', gap: 12,
|
|
124
|
-
padding: '16px 18px', borderRadius:
|
|
125
|
-
background: 'var(--dsw-alias-bg-layer-
|
|
131
|
+
padding: '16px 18px', borderRadius: 'var(--dsw-radius-panel, 28px)',
|
|
132
|
+
background: 'var(--dsw-alias-bg-layer-2)', border: 0, boxShadow: 'var(--dsw-elevation-prominent)',
|
|
126
133
|
},
|
|
127
134
|
modalHeader: { display: 'flex', alignItems: 'center', gap: 8 },
|
|
128
|
-
modalTitle: { fontWeight:
|
|
135
|
+
modalTitle: { fontWeight: 500, fontSize: 16, lineHeight: '24px', color: 'var(--dsw-alias-label-primary)' },
|
|
129
136
|
};
|
|
130
137
|
/** Status dot color for one provider state. */
|
|
131
138
|
function dotColor(status) {
|
|
@@ -265,10 +272,24 @@ export function SubscriptionsSection(props) {
|
|
|
265
272
|
const [observedAt, setObservedAt] = useState({});
|
|
266
273
|
const [usageErrors, setUsageErrors] = useState({});
|
|
267
274
|
const [usageLoading, setUsageLoading] = useState({});
|
|
275
|
+
const [resetConfirmation, setResetConfirmation] = useState();
|
|
276
|
+
const [resetBusy, setResetBusy] = useState(false);
|
|
277
|
+
const [resetAcknowledged, setResetAcknowledged] = useState(false);
|
|
278
|
+
const [resetMessage, setResetMessage] = useState('');
|
|
279
|
+
const [resetAccount, setResetAccount] = useState();
|
|
280
|
+
const resetDialogRef = useRef(null);
|
|
281
|
+
useEffect(() => {
|
|
282
|
+
if (resetConfirmation)
|
|
283
|
+
resetDialogRef.current?.showModal();
|
|
284
|
+
else
|
|
285
|
+
resetDialogRef.current?.close();
|
|
286
|
+
}, [resetConfirmation]);
|
|
287
|
+
const resetInflight = useRef(false);
|
|
268
288
|
const mountedRef = useRef(true);
|
|
269
289
|
const pollersRef = useRef(new Map());
|
|
270
290
|
/** Accounts with a `usage` call in flight; guards the auto-fetch effect against re-entry. */
|
|
271
|
-
|
|
291
|
+
/** In-flight usage reads per key, holding the promise so a forced read can wait one out. */
|
|
292
|
+
const usageInflightRef = useRef(new Map());
|
|
272
293
|
const usageRosterSignatureRef = useRef();
|
|
273
294
|
const [managedProvider, setManagedProvider] = useState();
|
|
274
295
|
const setProviderError = useCallback((provider, message) => {
|
|
@@ -362,34 +383,91 @@ export function SubscriptionsSection(props) {
|
|
|
362
383
|
};
|
|
363
384
|
}, [refresh, startPolling]);
|
|
364
385
|
const loadUsage = useCallback(async (provider, account, force = false) => {
|
|
386
|
+
if (rpc === undefined)
|
|
387
|
+
return;
|
|
365
388
|
const key = `${provider}:${account}`;
|
|
389
|
+
const pending = usageInflightRef.current.get(key);
|
|
390
|
+
// A forced read must never be dropped behind a poll that started before the
|
|
391
|
+
// state changed. The refresh after a credit redemption is the only thing
|
|
392
|
+
// that picks up the new numbers, and the next automatic poll is minutes
|
|
393
|
+
// away, so waiting the earlier read out is cheaper than showing a stale
|
|
394
|
+
// percentage next to a success message.
|
|
395
|
+
if (pending !== undefined) {
|
|
396
|
+
if (!force)
|
|
397
|
+
return;
|
|
398
|
+
await pending;
|
|
399
|
+
}
|
|
366
400
|
if (rpc === undefined || usageInflightRef.current.has(key))
|
|
367
401
|
return;
|
|
368
|
-
|
|
369
|
-
|
|
402
|
+
const read = (async () => {
|
|
403
|
+
setUsageLoading(prev => ({ ...prev, [key]: true }));
|
|
404
|
+
try {
|
|
405
|
+
const usage = await callSubscriptionsAuth(rpc, 'usage', { provider, account, ...force ? { force: true } : {} });
|
|
406
|
+
if (!mountedRef.current)
|
|
407
|
+
return;
|
|
408
|
+
setUsages(prev => ({ ...prev, [key]: usage }));
|
|
409
|
+
setObservedAt(prev => ({ ...prev, [key]: usage.observedAt ?? Date.now() }));
|
|
410
|
+
window.dispatchEvent(new Event(USAGE_BADGE_REFRESH_EVENT));
|
|
411
|
+
setUsageErrors((prev) => {
|
|
412
|
+
const next = { ...prev };
|
|
413
|
+
delete next[key];
|
|
414
|
+
return next;
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
if (mountedRef.current)
|
|
419
|
+
setUsageErrors(prev => ({ ...prev, [key]: messageOf(error) }));
|
|
420
|
+
}
|
|
421
|
+
finally {
|
|
422
|
+
usageInflightRef.current.delete(key);
|
|
423
|
+
if (mountedRef.current)
|
|
424
|
+
setUsageLoading(prev => ({ ...prev, [key]: false }));
|
|
425
|
+
}
|
|
426
|
+
})();
|
|
427
|
+
usageInflightRef.current.set(key, read);
|
|
428
|
+
await read;
|
|
429
|
+
}, [rpc]);
|
|
430
|
+
async function prepareReset(account) {
|
|
431
|
+
if (!rpc || resetInflight.current)
|
|
432
|
+
return;
|
|
433
|
+
resetInflight.current = true;
|
|
434
|
+
setResetBusy(true);
|
|
435
|
+
setResetAccount(account);
|
|
436
|
+
setResetConfirmation(undefined);
|
|
437
|
+
setResetMessage('');
|
|
370
438
|
try {
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
setUsages(prev => ({ ...prev, [key]: usage }));
|
|
375
|
-
setObservedAt(prev => ({ ...prev, [key]: usage.observedAt ?? Date.now() }));
|
|
376
|
-
window.dispatchEvent(new Event(USAGE_BADGE_REFRESH_EVENT));
|
|
377
|
-
setUsageErrors((prev) => {
|
|
378
|
-
const next = { ...prev };
|
|
379
|
-
delete next[key];
|
|
380
|
-
return next;
|
|
381
|
-
});
|
|
439
|
+
const result = await callSubscriptionsAuth(rpc, 'prepareReset', { account });
|
|
440
|
+
setResetAcknowledged(false);
|
|
441
|
+
setResetConfirmation({ ...result, account });
|
|
382
442
|
}
|
|
383
443
|
catch (error) {
|
|
384
|
-
|
|
385
|
-
setUsageErrors(prev => ({ ...prev, [key]: messageOf(error) }));
|
|
444
|
+
setResetMessage(messageOf(error));
|
|
386
445
|
}
|
|
387
446
|
finally {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
setUsageLoading(prev => ({ ...prev, [key]: false }));
|
|
447
|
+
resetInflight.current = false;
|
|
448
|
+
setResetBusy(false);
|
|
391
449
|
}
|
|
392
|
-
}
|
|
450
|
+
}
|
|
451
|
+
async function consumeReset() {
|
|
452
|
+
if (!rpc || !resetConfirmation || !resetAcknowledged || resetInflight.current)
|
|
453
|
+
return;
|
|
454
|
+
const { account, ticket } = resetConfirmation;
|
|
455
|
+
resetInflight.current = true;
|
|
456
|
+
setResetBusy(true);
|
|
457
|
+
setResetConfirmation(undefined);
|
|
458
|
+
try {
|
|
459
|
+
await callSubscriptionsAuth(rpc, 'consumeReset', { account, ticket });
|
|
460
|
+
setResetMessage(t('resetUseSuccess'));
|
|
461
|
+
}
|
|
462
|
+
catch (error) {
|
|
463
|
+
setResetMessage(messageOf(error));
|
|
464
|
+
}
|
|
465
|
+
finally {
|
|
466
|
+
await loadUsage('codex', account, true);
|
|
467
|
+
resetInflight.current = false;
|
|
468
|
+
setResetBusy(false);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
393
471
|
// Fetch usage once an account is logged in; drop the snapshots of accounts
|
|
394
472
|
// that vanished so a re-login refetches. A failed lookup does not auto-retry
|
|
395
473
|
// — the per-account Refresh button is the retry path.
|
|
@@ -514,7 +592,7 @@ export function SubscriptionsSection(props) {
|
|
|
514
592
|
if (rpc === undefined) {
|
|
515
593
|
return _jsx("p", { style: styles.intro, children: t('unavailable') });
|
|
516
594
|
}
|
|
517
|
-
return (_jsxs("div", { style: styles.section, children: [_jsx("p", { style: styles.intro, children: t('intro') }), _jsx(UsageBadgeDisplaySetting, { t: t }), PROVIDERS.map(({ id, name }) => {
|
|
595
|
+
return (_jsxs("div", { className: "dsh-subscriptions-settings", style: styles.section, children: [_jsx("style", { children: providerSettingsCss }), _jsx("p", { style: styles.intro, children: t('intro') }), _jsx(UsageBadgeDisplaySetting, { t: t }), PROVIDERS.map(({ id, name }) => {
|
|
518
596
|
const status = statuses[id];
|
|
519
597
|
const busy = status?.busy === true;
|
|
520
598
|
const deviceCode = deviceCodes[id];
|
|
@@ -524,17 +602,29 @@ export function SubscriptionsSection(props) {
|
|
|
524
602
|
const usage = usages[usageKey];
|
|
525
603
|
const usageError = usageErrors[usageKey];
|
|
526
604
|
const display = account.account ?? account.key;
|
|
605
|
+
const sortedCredits = [...(usage?.resetCredits ?? [])].sort((a, b) => (a.expiresAt ?? Infinity) - (b.expiresAt ?? Infinity));
|
|
606
|
+
const nextReset = sortedCredits.find(c => c.expiresAt === undefined || c.expiresAt > Date.now());
|
|
607
|
+
const resetBlock = usage ? resetActionBlock(usage) : 'resetUseRefresh';
|
|
608
|
+
const resetDisabled = resetBusy || resetBlock !== undefined;
|
|
527
609
|
// Providers without a usage endpoint answer supported:false — no block.
|
|
528
610
|
const showUsage = usage?.supported !== false
|
|
529
611
|
&& (usage !== undefined || usageError !== undefined || usageLoading[usageKey] === true);
|
|
530
612
|
return (_jsxs("div", { style: styles.accountRow, children: [_jsxs("div", { style: styles.accountHeader, children: [_jsx("button", { type: "button", style: styles.starButton, title: account.isDefault ? t('defaultBadge') : t('setDefault'), onClick: () => {
|
|
531
613
|
if (!account.isDefault)
|
|
532
614
|
void setDefault(id, account.key);
|
|
533
|
-
}, children: account.isDefault ? '★' : '☆' }), _jsx("span", { style: styles.accountName, children: display }), account.plan !== undefined && (_jsx("span", { style: styles.usagePlan, children: account.plan })), account.expiresAt !== undefined && (_jsx("span", { style: styles.statusLine, children: t('accountExpires', { date: new Date(account.expiresAt).toLocaleString() }) })), _jsx("button", { type: "button", style: {
|
|
615
|
+
}, children: account.isDefault ? '★' : '☆' }), _jsx("span", { style: styles.accountName, children: display }), account.plan !== undefined && (_jsx("span", { style: styles.usagePlan, children: account.plan })), account.expiresAt !== undefined && (_jsx("span", { style: styles.statusLine, children: t('accountExpires', { date: new Date(account.expiresAt).toLocaleString() }) })), _jsx("button", { type: "button", style: { marginLeft: 'auto', flexShrink: 0 }, onClick: () => { void logout(id, account.key, display, name); }, children: t('logout') })] }), showUsage && (_jsxs("div", { style: styles.usage, children: [_jsxs("div", { style: styles.usageHeader, children: [_jsx("span", { style: styles.usageTitle, children: t('usageTitle') }), usage?.plan !== undefined && (_jsx("span", { style: styles.usagePlan, children: t('usagePlan', { plan: usage.plan }) })), _jsx("button", { type: "button", style: styles.usageRefresh, disabled: usageLoading[usageKey] === true, onClick: () => { void loadUsage(id, account.key, true); }, children: t('usageRefresh') })] }), usage === undefined && usageError === undefined && (_jsx("p", { style: styles.statusLine, children: t('usageLoading') })), usageError !== undefined && (_jsx("p", { style: styles.errorLine, children: t('usageError', { message: usageError }) })), usage?.windows !== undefined && usage.windows.length === 0 && (_jsx("p", { style: styles.statusLine, children: t('usageEmpty') })), (usage?.windows ?? []).map((window, index) => {
|
|
534
616
|
const percent = displayUsedPercent(window.usedPercent);
|
|
535
617
|
return (_jsxs("div", { style: styles.usageRow, children: [_jsxs("div", { style: styles.usageMeta, children: [_jsx("span", { children: usageWindowLabel(t, window) }), _jsxs("span", { children: [percent === undefined ? t('usageMeterInvalid') : `${percent}%`, window.resetsAt !== undefined
|
|
536
618
|
&& ` · ${t('usageResets', { date: new Date(window.resetsAt).toLocaleString() })}`] })] }), _jsx(UsageMeter, { window: window, t: t, observedAt: observedAt[usageKey], stale: usageError !== undefined || usage.stale === true })] }, index));
|
|
537
|
-
})
|
|
538
|
-
|
|
539
|
-
|
|
619
|
+
}), (id === 'codex' || id === 'claude') && usage?.resetCreditsError !== undefined && (_jsx(ResetCreditsErrorLine, { provider: id, message: usage.resetCreditsError, t: t })), (id === 'codex' || id === 'claude') && showsResetCredits(id, usage?.resetCredits) && (_jsx(ResetCreditsDisclosure, { mode: id === 'claude' ? 'grants' : 'credits', credits: sortedCredits, t: t, ...nextReset !== undefined ? { nextCredit: nextReset } : {}, ...id === 'codex' ? { useAction: {
|
|
620
|
+
accountKey: account.key,
|
|
621
|
+
busy: resetBusy && resetAccount === account.key,
|
|
622
|
+
disabled: resetDisabled,
|
|
623
|
+
title: t(resetBusy ? 'resetUseChecking' : resetBlock ?? 'resetUseReady'),
|
|
624
|
+
label: t('resetUseButton'),
|
|
625
|
+
onUse: () => { if (!resetDisabled)
|
|
626
|
+
void prepareReset(account.key); },
|
|
627
|
+
} } : {}, ...resetAccount === account.key && resetMessage !== '' ? { statusMessage: resetMessage } : {} }))] }))] }, account.key));
|
|
628
|
+
}), _jsxs("div", { style: styles.actions, children: [!busy && accounts.length === 0 && (_jsx("button", { type: "button", onClick: () => { void login(id); }, children: t('login') })), !busy && accounts.length > 0 && id === 'claude' && (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => { void login(id, 'oauth'); }, children: t('addAccountOAuth') }), _jsx("button", { type: "button", onClick: () => { void login(id, 'keychain'); }, children: t('addAccountKeychain') })] })), !busy && accounts.length > 0 && id !== 'claude' && (_jsx("button", { type: "button", onClick: () => { void login(id); }, children: t('addAccount') })), _jsx("button", { type: "button", "aria-haspopup": "dialog", onClick: () => setManagedProvider({ id, name }), children: t('accountsManage') }), busy && (_jsx("button", { type: "button", onClick: () => { void cancel(id); }, children: t('cancel') }))] }), !busy && accounts.length > 0 && (_jsx("p", { style: styles.statusLine, children: t('addAccountHint') })), busy && deviceCode !== undefined && (_jsxs("div", { style: styles.deviceCode, children: [_jsx("span", { style: styles.statusLine, children: t('deviceCodePrompt') }), _jsx("span", { style: styles.deviceCodeText, children: deviceCode.userCode }), _jsxs("div", { style: styles.actions, children: [_jsx("button", { type: "button", onClick: () => { copyDeviceCode(id, deviceCode.userCode); }, children: copiedCode === id ? t('deviceCodeCopied') : t('deviceCodeCopy') }), _jsx("button", { type: "button", onClick: () => { window.open(deviceCode.verificationUrl, '_blank', 'noopener'); }, children: t('deviceCodeOpenPage') })] })] })), busy && deviceCode === undefined && (_jsxs("details", { style: styles.manual, children: [_jsx("summary", { children: t('manualSummary') }), _jsxs("div", { style: styles.manualRow, children: [_jsx("input", { style: styles.manualInput, value: manualDrafts[id], placeholder: t('manualPlaceholder'), onChange: event => setManualDrafts(prev => ({ ...prev, [id]: event.target.value })) }), _jsx("button", { type: "button", onClick: () => { void submitManual(id); }, children: t('submit') })] })] }))] }, id));
|
|
629
|
+
}), _jsx(CursorCard, { rpc: rpc, t: t }), _jsx(ExternalUsageCards, { rpc: rpc, t: t }), managedProvider && _jsx(ProviderAccountManager, { provider: managedProvider.id, name: managedProvider.name, rpc: rpc, t: t, onClose: () => setManagedProvider(undefined) }), _jsx("style", { children: '.subscriptions-reset-dialog::backdrop { background: var(--dsw-alias-bg-mask-1, #0006); backdrop-filter: var(--dsw-mask-blur, none); }' }), _jsx("dialog", { ref: resetDialogRef, className: "subscriptions-reset-dialog", "aria-labelledby": "subscriptions-reset-title", onCancel: () => setResetConfirmation(undefined), onClose: () => setResetConfirmation(undefined), style: { ...styles.modal, display: resetConfirmation ? 'flex' : 'none', margin: 'auto', color: 'var(--dsw-alias-label-primary)' }, children: resetConfirmation && _jsxs(_Fragment, { children: [_jsx("h3", { id: "subscriptions-reset-title", style: { ...styles.modalTitle, margin: 0 }, children: t('resetUseConfirmTitle') }), _jsx("p", { style: { ...styles.statusLine, overflowWrap: 'anywhere' }, children: statuses.codex?.accounts.find(a => a.key === resetConfirmation.account)?.account ?? resetConfirmation.account }), _jsxs("div", { style: { ...styles.usageMeta, gap: 12 }, children: [_jsx("span", { children: t('usageWeekly') }), _jsxs("strong", { children: [Math.round(resetConfirmation.weeklyUsedPercent), "%"] })] }), _jsx("div", { style: styles.usageMeta, children: _jsx("span", { children: resetConfirmation.creditExpiresAt === undefined ? t('resetCreditExpiryUnknown') : t('resetCreditExpires', { date: new Date(resetConfirmation.creditExpiresAt).toLocaleString() }) }) }), _jsx("p", { style: { ...styles.statusLine, margin: '4px 0' }, children: t('resetUseWarning') }), _jsxs("label", { style: { display: 'flex', gap: 8, alignItems: 'flex-start', fontSize: 12 }, children: [_jsx("input", { type: "checkbox", checked: resetAcknowledged, onChange: e => setResetAcknowledged(e.target.checked) }), t('resetUseAcknowledge')] }), _jsxs("div", { className: "dsh-subscription-dialog-actions", style: { ...styles.actions, justifyContent: 'flex-end', marginTop: 8 }, children: [_jsx("button", { type: "button", autoFocus: true, onClick: () => setResetConfirmation(undefined), children: t('cancel') }), _jsx("button", { type: "button", className: "dsh-subscription-primary", disabled: !resetAcknowledged || resetBusy, onClick: () => { void consumeReset(); }, children: t('resetUseConfirm') })] })] }) })] }));
|
|
540
630
|
}
|
|
@@ -39,15 +39,11 @@ export function UsageBadgeDisplaySetting({ t }) {
|
|
|
39
39
|
}
|
|
40
40
|
const styles = {
|
|
41
41
|
card: {
|
|
42
|
-
border: '
|
|
42
|
+
border: '0.5px solid var(--dsw-alias-settings-card-stroke, var(--dsw-alias-border-l4))',
|
|
43
|
+
borderRadius: 'var(--dsw-radius-xl, 20px)', background: 'var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2))',
|
|
43
44
|
padding: '12px 14px', display: 'flex', flexDirection: 'column', gap: 6,
|
|
44
45
|
},
|
|
45
|
-
field: { display: 'flex', flexDirection: 'column', gap:
|
|
46
|
-
select: {
|
|
47
|
-
height: 32, width: '100%', boxSizing: 'border-box',
|
|
48
|
-
border: '1px solid var(--dsw-alias-border-l2)', borderRadius: 8,
|
|
49
|
-
padding: '0 10px', font: 'inherit',
|
|
50
|
-
background: 'var(--dsw-alias-bg-layer-1)', color: 'var(--dsw-alias-label-primary)',
|
|
51
|
-
},
|
|
46
|
+
field: { display: 'flex', flexDirection: 'column', gap: 6, fontSize: 13, fontWeight: 500, lineHeight: '20px' },
|
|
47
|
+
select: { width: '100%' },
|
|
52
48
|
hint: { margin: 0, fontSize: 12, lineHeight: '18px', color: 'var(--dsw-alias-label-tertiary)' },
|
|
53
49
|
};
|
|
@@ -83,7 +83,7 @@ export declare const HOST_CONTRACT: {
|
|
|
83
83
|
/** Design tokens the client styles with; the host theme must define each one. */
|
|
84
84
|
readonly tokens: {
|
|
85
85
|
readonly package: "@deepseek-ai/dsh-client-ui-theme";
|
|
86
|
-
readonly names: readonly ["--dsw-alias-bg-layer-1", "--dsw-alias-bg-skeleton", "--dsw-alias-border-l2", "--dsw-alias-border-l2-darkmode-thin", "--dsw-alias-interactive-bg-hover", "--dsw-alias-interactive-bg-hover-solid", "--dsw-alias-label-dimmed", "--dsw-alias-label-primary", "--dsw-alias-label-secondary", "--dsw-alias-label-tertiary", "--dsw-alias-state-error-primary", "--dsw-alias-state-success-primary", "--dsw-alias-state-warn-label", "--dsw-elevation-prominent", "--dsw-menu-backdrop-filter", "--dsw-specific-menu"];
|
|
86
|
+
readonly names: readonly ["--dsw-alias-bg-layer-1", "--dsw-alias-bg-layer-2", "--dsw-alias-bg-layer-3", "--dsw-alias-bg-mask-1", "--dsw-alias-bg-skeleton", "--dsw-alias-border-l1", "--dsw-alias-border-l2", "--dsw-alias-border-l2-darkmode-thin", "--dsw-alias-border-l3", "--dsw-alias-border-l4", "--dsw-alias-brand-primary", "--dsw-alias-button-primary-fill", "--dsw-alias-button-primary-hover", "--dsw-alias-interactive-bg-active", "--dsw-alias-interactive-bg-hover", "--dsw-alias-interactive-bg-hover-solid", "--dsw-alias-label-dimmed", "--dsw-alias-label-primary", "--dsw-alias-label-primary-foreground", "--dsw-alias-label-secondary", "--dsw-alias-label-tertiary", "--dsw-alias-settings-card-fill", "--dsw-alias-settings-card-stroke", "--dsw-alias-state-business-primary", "--dsw-alias-state-error-primary", "--dsw-alias-state-success-primary", "--dsw-alias-state-warn-label", "--dsw-elevation-prominent", "--dsw-focus-ring-color", "--dsw-focus-ring-width", "--dsw-mask-blur", "--dsw-menu-backdrop-filter", "--dsw-radius-lg", "--dsw-radius-md", "--dsw-radius-panel", "--dsw-radius-sm", "--dsw-radius-xl", "--dsw-specific-menu"];
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
89
|
/** A glyph name listed in {@link HOST_CONTRACT}; hostIcon() accepts no other. */
|
|
@@ -82,20 +82,42 @@ export const HOST_CONTRACT = {
|
|
|
82
82
|
package: '@deepseek-ai/dsh-client-ui-theme',
|
|
83
83
|
names: [
|
|
84
84
|
'--dsw-alias-bg-layer-1',
|
|
85
|
+
'--dsw-alias-bg-layer-2',
|
|
86
|
+
'--dsw-alias-bg-layer-3',
|
|
87
|
+
'--dsw-alias-bg-mask-1',
|
|
85
88
|
'--dsw-alias-bg-skeleton',
|
|
89
|
+
'--dsw-alias-border-l1',
|
|
86
90
|
'--dsw-alias-border-l2',
|
|
87
91
|
'--dsw-alias-border-l2-darkmode-thin',
|
|
92
|
+
'--dsw-alias-border-l3',
|
|
93
|
+
'--dsw-alias-border-l4',
|
|
94
|
+
'--dsw-alias-brand-primary',
|
|
95
|
+
'--dsw-alias-button-primary-fill',
|
|
96
|
+
'--dsw-alias-button-primary-hover',
|
|
97
|
+
'--dsw-alias-interactive-bg-active',
|
|
88
98
|
'--dsw-alias-interactive-bg-hover',
|
|
89
99
|
'--dsw-alias-interactive-bg-hover-solid',
|
|
90
100
|
'--dsw-alias-label-dimmed',
|
|
91
101
|
'--dsw-alias-label-primary',
|
|
102
|
+
'--dsw-alias-label-primary-foreground',
|
|
92
103
|
'--dsw-alias-label-secondary',
|
|
93
104
|
'--dsw-alias-label-tertiary',
|
|
105
|
+
'--dsw-alias-settings-card-fill',
|
|
106
|
+
'--dsw-alias-settings-card-stroke',
|
|
107
|
+
'--dsw-alias-state-business-primary',
|
|
94
108
|
'--dsw-alias-state-error-primary',
|
|
95
109
|
'--dsw-alias-state-success-primary',
|
|
96
110
|
'--dsw-alias-state-warn-label',
|
|
97
111
|
'--dsw-elevation-prominent',
|
|
112
|
+
'--dsw-focus-ring-color',
|
|
113
|
+
'--dsw-focus-ring-width',
|
|
114
|
+
'--dsw-mask-blur',
|
|
98
115
|
'--dsw-menu-backdrop-filter',
|
|
116
|
+
'--dsw-radius-lg',
|
|
117
|
+
'--dsw-radius-md',
|
|
118
|
+
'--dsw-radius-panel',
|
|
119
|
+
'--dsw-radius-sm',
|
|
120
|
+
'--dsw-radius-xl',
|
|
99
121
|
'--dsw-specific-menu',
|
|
100
122
|
],
|
|
101
123
|
},
|
package/lib/client/locales.d.ts
CHANGED
|
@@ -104,6 +104,35 @@ export declare const en: {
|
|
|
104
104
|
usageColorPaceHint: string;
|
|
105
105
|
usageColorRemainingHint: string;
|
|
106
106
|
usagePlan: string;
|
|
107
|
+
resetCreditsTitle: string;
|
|
108
|
+
resetCreditsAvailable: string;
|
|
109
|
+
resetCreditsError: string;
|
|
110
|
+
resetCreditsErrorFixed: string;
|
|
111
|
+
resetCreditReadOnly: string;
|
|
112
|
+
resetCreditReadOnlyLabel: string;
|
|
113
|
+
resetCreditAvailable: string;
|
|
114
|
+
resetCreditNotUsable: string;
|
|
115
|
+
resetCreditPaused: string;
|
|
116
|
+
resetCreditExhausted: string;
|
|
117
|
+
resetCreditExpired: string;
|
|
118
|
+
resetCreditRemaining: string;
|
|
119
|
+
resetCreditLeft: string;
|
|
120
|
+
resetCreditRemainingUnknown: string;
|
|
121
|
+
resetCreditCooldownUntil: string;
|
|
122
|
+
resetUseButton: string;
|
|
123
|
+
resetUseChecking: string;
|
|
124
|
+
resetUseGuard: string;
|
|
125
|
+
resetUseRestart: string;
|
|
126
|
+
resetUseRefresh: string;
|
|
127
|
+
resetUseReady: string;
|
|
128
|
+
resetUseConfirmTitle: string;
|
|
129
|
+
resetUseWarning: string;
|
|
130
|
+
resetUseAcknowledge: string;
|
|
131
|
+
resetUseConfirm: string;
|
|
132
|
+
resetUseSuccess: string;
|
|
133
|
+
resetCreditFull: string;
|
|
134
|
+
resetCreditExpires: string;
|
|
135
|
+
resetCreditExpiryUnknown: string;
|
|
107
136
|
externalUsageTitle: string;
|
|
108
137
|
externalUsageConnected: string;
|
|
109
138
|
externalUsageNotConfigured: string;
|
|
@@ -276,6 +305,35 @@ export declare const zh: {
|
|
|
276
305
|
usageColorPaceHint: string;
|
|
277
306
|
usageColorRemainingHint: string;
|
|
278
307
|
usagePlan: string;
|
|
308
|
+
resetCreditsTitle: string;
|
|
309
|
+
resetCreditsAvailable: string;
|
|
310
|
+
resetCreditsError: string;
|
|
311
|
+
resetCreditsErrorFixed: string;
|
|
312
|
+
resetCreditReadOnly: string;
|
|
313
|
+
resetCreditReadOnlyLabel: string;
|
|
314
|
+
resetCreditAvailable: string;
|
|
315
|
+
resetCreditNotUsable: string;
|
|
316
|
+
resetCreditPaused: string;
|
|
317
|
+
resetCreditExhausted: string;
|
|
318
|
+
resetCreditExpired: string;
|
|
319
|
+
resetCreditRemaining: string;
|
|
320
|
+
resetCreditLeft: string;
|
|
321
|
+
resetCreditRemainingUnknown: string;
|
|
322
|
+
resetCreditCooldownUntil: string;
|
|
323
|
+
resetUseButton: string;
|
|
324
|
+
resetUseChecking: string;
|
|
325
|
+
resetUseGuard: string;
|
|
326
|
+
resetUseRestart: string;
|
|
327
|
+
resetUseRefresh: string;
|
|
328
|
+
resetUseReady: string;
|
|
329
|
+
resetUseConfirmTitle: string;
|
|
330
|
+
resetUseWarning: string;
|
|
331
|
+
resetUseAcknowledge: string;
|
|
332
|
+
resetUseConfirm: string;
|
|
333
|
+
resetUseSuccess: string;
|
|
334
|
+
resetCreditFull: string;
|
|
335
|
+
resetCreditExpires: string;
|
|
336
|
+
resetCreditExpiryUnknown: string;
|
|
279
337
|
externalUsageTitle: string;
|
|
280
338
|
externalUsageConnected: string;
|
|
281
339
|
externalUsageNotConfigured: string;
|
package/lib/client/locales.js
CHANGED
|
@@ -104,6 +104,35 @@ export const en = {
|
|
|
104
104
|
usageColorPaceHint: 'Yellow when usage leads elapsed time by {allowance} points; red at 90% used takes priority. Saved in this browser; only colors change.',
|
|
105
105
|
usageColorRemainingHint: 'Red at 90% used; no yellow pace warnings. Reliable time markers remain visible. Saved in this browser.',
|
|
106
106
|
usagePlan: 'Plan: {plan}',
|
|
107
|
+
resetCreditsTitle: 'Usage limit resets',
|
|
108
|
+
resetCreditsAvailable: '{count} available',
|
|
109
|
+
resetCreditsError: 'Usage limit resets unavailable: {message}',
|
|
110
|
+
resetCreditsErrorFixed: 'Usage limit resets are unavailable. Refresh usage to try again.',
|
|
111
|
+
resetCreditReadOnly: 'Read only. This page cannot spend a Claude reset.',
|
|
112
|
+
resetCreditReadOnlyLabel: 'Read only',
|
|
113
|
+
resetCreditAvailable: 'Available',
|
|
114
|
+
resetCreditNotUsable: 'Not yet usable',
|
|
115
|
+
resetCreditPaused: 'Paused',
|
|
116
|
+
resetCreditExhausted: 'Exhausted',
|
|
117
|
+
resetCreditExpired: 'Expired',
|
|
118
|
+
resetCreditRemaining: '{left} of {total} left',
|
|
119
|
+
resetCreditLeft: '{left} left',
|
|
120
|
+
resetCreditRemainingUnknown: 'Remaining count unavailable',
|
|
121
|
+
resetCreditCooldownUntil: 'Usable after {date}',
|
|
122
|
+
resetUseButton: 'Use…',
|
|
123
|
+
resetUseChecking: 'Checking…',
|
|
124
|
+
resetUseGuard: 'You can use this reset when weekly usage reaches at least 80%.',
|
|
125
|
+
resetUseRestart: 'Reset details are missing. Restart DSH, reload this page, then refresh usage.',
|
|
126
|
+
resetUseRefresh: 'Refresh usage to verify current limits and reset availability.',
|
|
127
|
+
resetUseReady: 'Use this reset — the earliest-expiring credit. Confirmation required.',
|
|
128
|
+
resetUseConfirmTitle: 'Confirm full reset',
|
|
129
|
+
resetUseWarning: 'This consumes one credit and resets weekly + 5-hour limits. This interface cannot undo it. Confirmation expires in 60 seconds.',
|
|
130
|
+
resetUseAcknowledge: 'I understand that one credit will be consumed.',
|
|
131
|
+
resetUseConfirm: 'Consume 1 reset',
|
|
132
|
+
resetUseSuccess: 'Reset confirmed. Usage refreshed.',
|
|
133
|
+
resetCreditFull: 'Full reset',
|
|
134
|
+
resetCreditExpires: 'Expires {date}',
|
|
135
|
+
resetCreditExpiryUnknown: 'Expiry date unavailable',
|
|
107
136
|
externalUsageTitle: 'Built-in provider usage',
|
|
108
137
|
externalUsageConnected: 'API key configured',
|
|
109
138
|
externalUsageNotConfigured: 'Not configured',
|
|
@@ -276,6 +305,35 @@ export const zh = {
|
|
|
276
305
|
usageColorPaceHint: '用量领先时间进度 {allowance} 个百分点时变黄;已用达到 90% 时优先变红。自动保存到当前浏览器,仅改变配色。',
|
|
277
306
|
usageColorRemainingHint: '已用达到 90% 时变红,不显示黄色节奏警告。可靠的时间标记仍保留,自动保存到当前浏览器。',
|
|
278
307
|
usagePlan: '计划:{plan}',
|
|
308
|
+
resetCreditsTitle: '用量限制重置',
|
|
309
|
+
resetCreditsAvailable: '可用 {count} 次',
|
|
310
|
+
resetCreditsError: '用量限制重置查询失败:{message}',
|
|
311
|
+
resetCreditsErrorFixed: '用量限制重置暂不可用,请刷新用量后重试。',
|
|
312
|
+
resetCreditReadOnly: '只读。此页面不能消耗 Claude 的重置额度。',
|
|
313
|
+
resetCreditReadOnlyLabel: '只读',
|
|
314
|
+
resetCreditAvailable: '可用',
|
|
315
|
+
resetCreditNotUsable: '暂不可用',
|
|
316
|
+
resetCreditPaused: '已暂停',
|
|
317
|
+
resetCreditExhausted: '已用尽',
|
|
318
|
+
resetCreditExpired: '已过期',
|
|
319
|
+
resetCreditRemaining: '剩余 {left} / {total}',
|
|
320
|
+
resetCreditLeft: '剩余 {left}',
|
|
321
|
+
resetCreditRemainingUnknown: '剩余次数不可用',
|
|
322
|
+
resetCreditCooldownUntil: '{date} 后可用',
|
|
323
|
+
resetUseButton: '使用…',
|
|
324
|
+
resetUseChecking: '正在检查…',
|
|
325
|
+
resetUseGuard: '每周用量达到 80% 后才可使用此重置。',
|
|
326
|
+
resetUseRestart: '缺少重置详情。请重启 DSH、重新加载页面并刷新用量。',
|
|
327
|
+
resetUseRefresh: '请刷新用量以验证当前限制和重置可用性。',
|
|
328
|
+
resetUseReady: '使用此最早到期的重置额度,操作前需要确认。',
|
|
329
|
+
resetUseConfirmTitle: '确认完整重置',
|
|
330
|
+
resetUseWarning: '将消耗一次额度并重置每周和 5 小时限制,无法撤销。确认将在 60 秒后过期。',
|
|
331
|
+
resetUseAcknowledge: '我理解将消耗一次额度。',
|
|
332
|
+
resetUseConfirm: '消耗一次重置',
|
|
333
|
+
resetUseSuccess: '重置已确认,用量已刷新。',
|
|
334
|
+
resetCreditFull: '完整重置',
|
|
335
|
+
resetCreditExpires: '{date} 到期',
|
|
336
|
+
resetCreditExpiryUnknown: '到期时间不可用',
|
|
279
337
|
externalUsageTitle: '内置供应商用量',
|
|
280
338
|
externalUsageConnected: '已配置 API 密钥',
|
|
281
339
|
externalUsageNotConfigured: '未配置',
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const providerSettingsCss = "\n.dsh-subscription-manager {\n box-sizing: border-box;\n padding: 0;\n border: 0;\n border-radius: var(--dsw-radius-panel, 16px);\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n color: var(--dsw-alias-label-primary);\n box-shadow: var(--dsw-elevation-prominent, 0 20px 70px #0004);\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-subscriptions-settings {\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-subscription-manager::backdrop {\n background: var(--dsw-alias-bg-mask-1, #0006);\n backdrop-filter: var(--dsw-mask-blur, none);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) h2 {\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) h3 {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) strong,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) .dsh-subscription-label {\n font-size: 13px;\n line-height: 1.5;\n font-weight: 500;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) legend {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) small,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) .dsh-subscription-hint,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) [role=\"status\"] {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) [role=\"alert\"] {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary, #b42318);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input:not([type=\"checkbox\"]),\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) select {\n box-sizing: border-box;\n min-width: 0;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4, var(--dsw-alias-border-l2));\n border-radius: var(--dsw-radius-md, 8px);\n background: var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-1));\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n font-weight: 400;\n line-height: 1.5;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input::placeholder {\n color: var(--dsw-alias-label-tertiary);\n opacity: 1;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input:not([type=\"checkbox\"]):focus-visible,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) select:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary));\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input:not([type=\"checkbox\"]):disabled,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) select:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input[aria-invalid=\"true\"] {\n border-color: var(--dsw-alias-state-error-primary, #b42318);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) option {\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n color: var(--dsw-alias-label-primary);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) label:has(> input[type=\"checkbox\"]) {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n font-size: 14px;\n line-height: 20px;\n cursor: pointer;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input[type=\"checkbox\"] {\n flex: 0 0 auto;\n width: 16px;\n height: 16px;\n margin: 2px 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: inherit;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) label:has(> input[type=\"checkbox\"]:disabled) {\n cursor: default;\n opacity: 0.5;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n min-height: 28px;\n padding: 0 10px;\n border: 0.5px solid var(--dsw-alias-border-l3, var(--dsw-alias-border-l2));\n border-radius: var(--dsw-radius-sm, 6px);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-layer-3));\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button:active:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-active, var(--dsw-alias-bg-layer-3));\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button:disabled {\n opacity: 0.4;\n cursor: default;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button.dsh-subscription-quiet {\n border-color: transparent;\n color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) :is(footer, .dsh-subscription-dialog-actions) button {\n min-height: 34px;\n padding: 0 14px;\n border-radius: var(--dsw-radius-md, 8px);\n font-size: 13px;\n line-height: 1.5;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button.dsh-subscription-primary {\n border-color: transparent;\n background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-label-primary));\n color: var(--dsw-alias-label-primary-foreground, var(--dsw-alias-bg-layer-1));\n font-weight: 500;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button.dsh-subscription-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover, var(--dsw-alias-label-secondary));\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) button:focus-visible,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) input[type=\"checkbox\"]:focus-visible,\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) summary:focus-visible {\n outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 2px;\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) summary {\n border-radius: var(--dsw-radius-sm, 6px);\n}\n:is(.dsh-subscription-manager, .dsh-subscriptions-settings) summary:hover {\n color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));\n}\n";
|
|
2
|
+
/** Composer controls retain their own geometry, separate from settings forms. */
|
|
3
|
+
export declare const subscriptionChromeCss = "\n.dsh-subscription-usage-pill { corner-shape: round; }\n.dsh-subscription-usage-panel {\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n backdrop-filter: var(--dsw-menu-backdrop-filter, none);\n}\n.dsh-subscription-speed button:hover:not(:disabled) {\n --dsh-subscription-speed-hover: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-subscription-speed button:active:not(:disabled) {\n --dsh-subscription-speed-hover: var(--dsw-alias-interactive-bg-active);\n}\n.dsh-subscription-speed button:disabled { opacity: 0.4; cursor: default; }\n.dsh-subscription-speed button:focus-visible,\n.dsh-subscription-usage-pill:focus-visible {\n outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n outline-offset: 2px;\n}\n";
|