dsh-ds-balance 2.1.1 → 2.1.3
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 +14 -1
- package/README_en.md +13 -1
- package/lib/adapters/console-logger.js +12 -4
- package/lib/adapters/domain-core-store.js +9 -3
- package/lib/adapters/http-deepseek-client.js +14 -4
- package/lib/adapters/salt-file.js +6 -2
- package/lib/client.js +372 -169
- package/lib/config.js +7 -1
- package/lib/domain/errors.js +10 -5
- package/lib/domain/select.js +5 -5
- package/lib/http/handlers.js +55 -13
- package/lib/index.js +34 -9
- package/lib/services/balance-service.d.ts +9 -0
- package/lib/services/balance-service.js +32 -9
- package/lib/services/scheduler.d.ts +23 -0
- package/lib/services/scheduler.js +34 -3
- package/lib/types/client/model.d.ts +25 -0
- package/lib/types/client/settings/fields.d.ts +3 -3
- package/lib/types/client/sidebar/PercentRing.d.ts +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +10 -1
package/lib/client.js
CHANGED
|
@@ -198,7 +198,10 @@ var en = {
|
|
|
198
198
|
"dev.hint": "UI development only; does not affect real configuration."
|
|
199
199
|
};
|
|
200
200
|
function interpolate(template, params) {
|
|
201
|
-
return template.replace(
|
|
201
|
+
return template.replace(
|
|
202
|
+
/\{(\w+)\}/g,
|
|
203
|
+
(whole, name) => Object.prototype.hasOwnProperty.call(params, name) ? params[name] : whole
|
|
204
|
+
);
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
// src/client/settings/fields.tsx
|
|
@@ -230,7 +233,6 @@ var fields_default = {
|
|
|
230
233
|
groupNote: "fields_groupNote",
|
|
231
234
|
fields: "fields_fields",
|
|
232
235
|
details: "fields_details",
|
|
233
|
-
detailsSummary: "fields_detailsSummary",
|
|
234
236
|
detailsBody: "fields_detailsBody",
|
|
235
237
|
field: "fields_field",
|
|
236
238
|
row: "fields_row",
|
|
@@ -241,10 +243,10 @@ var fields_default = {
|
|
|
241
243
|
label: "fields_label",
|
|
242
244
|
badges: "fields_badges",
|
|
243
245
|
reset: "fields_reset",
|
|
244
|
-
input: "fields_input",
|
|
245
246
|
inputStatic: "fields_inputStatic",
|
|
246
247
|
inputInvalid: "fields_inputInvalid",
|
|
247
248
|
inputWithAction: "fields_inputWithAction",
|
|
249
|
+
input: "fields_input",
|
|
248
250
|
reveal: "fields_reveal",
|
|
249
251
|
revealOn: "fields_revealOn",
|
|
250
252
|
selectorAnchor: "fields_selectorAnchor",
|
|
@@ -254,7 +256,6 @@ var fields_default = {
|
|
|
254
256
|
pairNote: "fields_pairNote",
|
|
255
257
|
invalid: "fields_invalid",
|
|
256
258
|
actions: "fields_actions",
|
|
257
|
-
actionButton: "fields_actionButton",
|
|
258
259
|
resultOk: "fields_resultOk",
|
|
259
260
|
resultFail: "fields_resultFail"
|
|
260
261
|
};
|
|
@@ -322,10 +323,10 @@ function FieldFrame(props) {
|
|
|
322
323
|
}
|
|
323
324
|
function TextControl(props) {
|
|
324
325
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
325
|
-
|
|
326
|
+
import_dsh_client_ui_primitives.Input,
|
|
326
327
|
{
|
|
327
328
|
id: props.id,
|
|
328
|
-
className: props.invalid ? fields_default.inputInvalid :
|
|
329
|
+
className: props.invalid ? fields_default.inputInvalid : void 0,
|
|
329
330
|
type: "text",
|
|
330
331
|
...props.numeric ? { inputMode: "numeric" } : {},
|
|
331
332
|
...props.invalid ? { "aria-invalid": true } : {},
|
|
@@ -340,10 +341,10 @@ function TextControl(props) {
|
|
|
340
341
|
}
|
|
341
342
|
function ReadOnlyControl(props) {
|
|
342
343
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
343
|
-
|
|
344
|
+
import_dsh_client_ui_primitives.Input,
|
|
344
345
|
{
|
|
345
346
|
id: props.id,
|
|
346
|
-
className:
|
|
347
|
+
className: fields_default.inputStatic,
|
|
347
348
|
type: "text",
|
|
348
349
|
value: "",
|
|
349
350
|
readOnly: true
|
|
@@ -352,20 +353,20 @@ function ReadOnlyControl(props) {
|
|
|
352
353
|
}
|
|
353
354
|
function DetailsGroup(props) {
|
|
354
355
|
const [open, setOpen] = (0, import_react.useState)(props.defaultOpen === true);
|
|
355
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
356
|
-
|
|
356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.details, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
357
|
+
import_dsh_client_ui_primitives.DisclosureRow,
|
|
357
358
|
{
|
|
358
|
-
|
|
359
|
+
icon: null,
|
|
360
|
+
title: props.title,
|
|
359
361
|
open,
|
|
360
|
-
|
|
361
|
-
|
|
362
|
+
expandable: true,
|
|
363
|
+
expandOnRowClick: true,
|
|
364
|
+
onToggle: () => {
|
|
365
|
+
setOpen((value) => !value);
|
|
362
366
|
},
|
|
363
|
-
children:
|
|
364
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { className: fields_default.detailsSummary, children: props.title }),
|
|
365
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.detailsBody, children: props.children })
|
|
366
|
-
]
|
|
367
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.detailsBody, children: props.children })
|
|
367
368
|
}
|
|
368
|
-
);
|
|
369
|
+
) });
|
|
369
370
|
}
|
|
370
371
|
function SelectorControl(props) {
|
|
371
372
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
@@ -410,16 +411,7 @@ function SelectorControl(props) {
|
|
|
410
411
|
}
|
|
411
412
|
function ActionRow(props) {
|
|
412
413
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
413
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.actions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
414
|
-
"button",
|
|
415
|
-
{
|
|
416
|
-
type: "button",
|
|
417
|
-
className: fields_default.actionButton,
|
|
418
|
-
disabled: props.disabled,
|
|
419
|
-
onClick: props.onClick,
|
|
420
|
-
children: props.label
|
|
421
|
-
}
|
|
422
|
-
) }),
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.actions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Button, { type: "button", variant: "outline", disabled: props.disabled, onClick: props.onClick, children: props.label }) }),
|
|
423
415
|
props.result === null ? null : (
|
|
424
416
|
// 成功只是通报,用 polite 的 status;失败需要用户处理,按 06 §6.7 的「行内错误」用 alert。
|
|
425
417
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -469,7 +461,13 @@ function selectField(field) {
|
|
|
469
461
|
var AUTO_CURRENCY = "auto";
|
|
470
462
|
var KNOWN_CURRENCIES = ["CNY", "USD"];
|
|
471
463
|
var THRESHOLD_PAIRS = [
|
|
472
|
-
{
|
|
464
|
+
{
|
|
465
|
+
currency: "CNY",
|
|
466
|
+
warn: "cnyWarn",
|
|
467
|
+
critical: "cnyCritical",
|
|
468
|
+
defaultWarn: 10,
|
|
469
|
+
defaultCritical: 5
|
|
470
|
+
},
|
|
473
471
|
{ currency: "USD", warn: "usdWarn", critical: "usdCritical", defaultWarn: 2, defaultCritical: 1 }
|
|
474
472
|
];
|
|
475
473
|
function pairNumber(state, fallback) {
|
|
@@ -512,8 +510,10 @@ var SPEC_BY_FIELD = new Map(
|
|
|
512
510
|
var TEST_LATENCY_MS = 800;
|
|
513
511
|
function probeFailure(baseUrl, apiKey, apiKeyRef) {
|
|
514
512
|
const url = baseUrl.trim();
|
|
515
|
-
if (url !== "" && !/^https?:\/\//i.test(url))
|
|
516
|
-
|
|
513
|
+
if (url !== "" && !/^https?:\/\//i.test(url))
|
|
514
|
+
return "base URL must start with http:// or https://";
|
|
515
|
+
if (apiKey.trim() === "" && apiKeyRef.trim() === "")
|
|
516
|
+
return "no API key or credential reference configured";
|
|
517
517
|
return null;
|
|
518
518
|
}
|
|
519
519
|
function isRecord(input) {
|
|
@@ -564,16 +564,72 @@ function fieldStateOf(snapshot, spec, edit) {
|
|
|
564
564
|
const effective = snapshot.value[spec.field];
|
|
565
565
|
const stored = Object.hasOwn(snapshot.user, spec.field);
|
|
566
566
|
if (edit === void 0) {
|
|
567
|
-
return isTextSpec(spec) ? {
|
|
567
|
+
return isTextSpec(spec) ? {
|
|
568
|
+
text: spec.format(effective),
|
|
569
|
+
value: void 0,
|
|
570
|
+
effective,
|
|
571
|
+
stored,
|
|
572
|
+
overridden: stored,
|
|
573
|
+
dirty: false,
|
|
574
|
+
invalid: false
|
|
575
|
+
} : {
|
|
576
|
+
text: "",
|
|
577
|
+
value: effective,
|
|
578
|
+
effective,
|
|
579
|
+
stored,
|
|
580
|
+
overridden: stored,
|
|
581
|
+
dirty: false,
|
|
582
|
+
invalid: false
|
|
583
|
+
};
|
|
568
584
|
}
|
|
569
585
|
if (edit.kind === "clear") {
|
|
570
|
-
return isTextSpec(spec) ? {
|
|
586
|
+
return isTextSpec(spec) ? {
|
|
587
|
+
text: "",
|
|
588
|
+
value: void 0,
|
|
589
|
+
effective,
|
|
590
|
+
stored,
|
|
591
|
+
overridden: false,
|
|
592
|
+
dirty: stored,
|
|
593
|
+
invalid: false
|
|
594
|
+
} : {
|
|
595
|
+
text: "",
|
|
596
|
+
value: effective,
|
|
597
|
+
effective,
|
|
598
|
+
stored,
|
|
599
|
+
overridden: false,
|
|
600
|
+
dirty: stored,
|
|
601
|
+
invalid: false
|
|
602
|
+
};
|
|
571
603
|
}
|
|
572
604
|
if (!isTextSpec(spec)) {
|
|
573
|
-
return edit.kind === "value" ? {
|
|
605
|
+
return edit.kind === "value" ? {
|
|
606
|
+
text: "",
|
|
607
|
+
value: edit.value,
|
|
608
|
+
effective,
|
|
609
|
+
stored,
|
|
610
|
+
overridden: true,
|
|
611
|
+
dirty: edit.value !== effective,
|
|
612
|
+
invalid: false
|
|
613
|
+
} : {
|
|
614
|
+
text: "",
|
|
615
|
+
value: effective,
|
|
616
|
+
effective,
|
|
617
|
+
stored,
|
|
618
|
+
overridden: stored,
|
|
619
|
+
dirty: false,
|
|
620
|
+
invalid: false
|
|
621
|
+
};
|
|
574
622
|
}
|
|
575
623
|
if (edit.kind !== "text") {
|
|
576
|
-
return {
|
|
624
|
+
return {
|
|
625
|
+
text: "",
|
|
626
|
+
value: void 0,
|
|
627
|
+
effective,
|
|
628
|
+
stored,
|
|
629
|
+
overridden: stored,
|
|
630
|
+
dirty: false,
|
|
631
|
+
invalid: false
|
|
632
|
+
};
|
|
577
633
|
}
|
|
578
634
|
const write = spec.parse(edit.text);
|
|
579
635
|
const dirty = write === void 0 ? true : write.kind === "clear" ? stored : edit.text !== spec.format(effective);
|
|
@@ -618,10 +674,7 @@ function useConfigForm(form) {
|
|
|
618
674
|
cacheRef.current = { value, user, writable, available, snapshot: snapshot2 };
|
|
619
675
|
return snapshot2;
|
|
620
676
|
}, [form]);
|
|
621
|
-
const subscribe = (0, import_react2.useCallback)(
|
|
622
|
-
(listener) => form.subscribe(listener),
|
|
623
|
-
[form]
|
|
624
|
-
);
|
|
677
|
+
const subscribe = (0, import_react2.useCallback)((listener) => form.subscribe(listener), [form]);
|
|
625
678
|
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, readSnapshot);
|
|
626
679
|
const [staged, setStaged] = (0, import_react2.useState)(() => /* @__PURE__ */ new Map());
|
|
627
680
|
const [saving, setSaving] = (0, import_react2.useState)(false);
|
|
@@ -631,18 +684,23 @@ function useConfigForm(form) {
|
|
|
631
684
|
const [test, setTest] = (0, import_react2.useState)({ running: false, ok: null, message: "" });
|
|
632
685
|
const testTimerRef = (0, import_react2.useRef)(null);
|
|
633
686
|
const testRunningRef = (0, import_react2.useRef)(false);
|
|
634
|
-
(0, import_react2.useEffect)(
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
687
|
+
(0, import_react2.useEffect)(
|
|
688
|
+
() => () => {
|
|
689
|
+
if (testTimerRef.current !== null) clearTimeout(testTimerRef.current);
|
|
690
|
+
testTimerRef.current = null;
|
|
691
|
+
testRunningRef.current = false;
|
|
692
|
+
},
|
|
693
|
+
[]
|
|
694
|
+
);
|
|
639
695
|
const plan = (0, import_react2.useMemo)(() => planWrites(snapshot, staged), [snapshot, staged]);
|
|
640
696
|
const pairsInvalid = (0, import_react2.useMemo)(
|
|
641
|
-
() => THRESHOLD_PAIRS.some(
|
|
642
|
-
pair
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
697
|
+
() => THRESHOLD_PAIRS.some(
|
|
698
|
+
(pair) => !thresholdsOk(
|
|
699
|
+
pair,
|
|
700
|
+
fieldOf(snapshot, pair.warn, staged.get(pair.warn)),
|
|
701
|
+
fieldOf(snapshot, pair.critical, staged.get(pair.critical))
|
|
702
|
+
)
|
|
703
|
+
),
|
|
646
704
|
[snapshot, staged]
|
|
647
705
|
);
|
|
648
706
|
const invalid = plan.some((item) => item.write === void 0) || pairsInvalid;
|
|
@@ -659,17 +717,28 @@ function useConfigForm(form) {
|
|
|
659
717
|
testTimerRef.current = null;
|
|
660
718
|
}
|
|
661
719
|
testRunningRef.current = false;
|
|
662
|
-
setTest(
|
|
720
|
+
setTest(
|
|
721
|
+
(current) => current.running || current.ok !== null ? { running: false, ok: null, message: "" } : current
|
|
722
|
+
);
|
|
663
723
|
}, []);
|
|
664
|
-
const edit = (0, import_react2.useCallback)(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
stage
|
|
669
|
-
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
|
|
724
|
+
const edit = (0, import_react2.useCallback)(
|
|
725
|
+
(field2, text) => {
|
|
726
|
+
stage(field2, { kind: "text", text });
|
|
727
|
+
},
|
|
728
|
+
[stage]
|
|
729
|
+
);
|
|
730
|
+
const setValue = (0, import_react2.useCallback)(
|
|
731
|
+
(field2, value) => {
|
|
732
|
+
stage(field2, { kind: "value", value });
|
|
733
|
+
},
|
|
734
|
+
[stage]
|
|
735
|
+
);
|
|
736
|
+
const resetField = (0, import_react2.useCallback)(
|
|
737
|
+
(field2) => {
|
|
738
|
+
stage(field2, { kind: "clear" });
|
|
739
|
+
},
|
|
740
|
+
[stage]
|
|
741
|
+
);
|
|
673
742
|
const discard = (0, import_react2.useCallback)(() => {
|
|
674
743
|
setStaged((current) => current.size === 0 ? current : /* @__PURE__ */ new Map());
|
|
675
744
|
setFailed(false);
|
|
@@ -678,7 +747,9 @@ function useConfigForm(form) {
|
|
|
678
747
|
testTimerRef.current = null;
|
|
679
748
|
}
|
|
680
749
|
testRunningRef.current = false;
|
|
681
|
-
setTest(
|
|
750
|
+
setTest(
|
|
751
|
+
(current) => current.running || current.ok !== null ? { running: false, ok: null, message: "" } : current
|
|
752
|
+
);
|
|
682
753
|
}, []);
|
|
683
754
|
const save = (0, import_react2.useCallback)(async () => {
|
|
684
755
|
if (savingRef.current) return;
|
|
@@ -692,9 +763,11 @@ function useConfigForm(form) {
|
|
|
692
763
|
for (const item of writes) {
|
|
693
764
|
const write = item.write;
|
|
694
765
|
if (write === void 0) continue;
|
|
695
|
-
ops.push(
|
|
766
|
+
ops.push(
|
|
767
|
+
write.kind === "clear" ? { op: "unset", path: [item.field] } : { op: "set", path: [item.field], value: write.value }
|
|
768
|
+
);
|
|
696
769
|
}
|
|
697
|
-
let landed
|
|
770
|
+
let landed;
|
|
698
771
|
try {
|
|
699
772
|
landed = await form.mutate(ops, form.getSnapshot().revision);
|
|
700
773
|
} catch {
|
|
@@ -720,7 +793,9 @@ function useConfigForm(form) {
|
|
|
720
793
|
testTimerRef.current = setTimeout(() => {
|
|
721
794
|
testTimerRef.current = null;
|
|
722
795
|
testRunningRef.current = false;
|
|
723
|
-
setTest(
|
|
796
|
+
setTest(
|
|
797
|
+
failure === null ? { running: false, ok: true, message: "" } : { running: false, ok: false, message: failure }
|
|
798
|
+
);
|
|
724
799
|
}, TEST_LATENCY_MS);
|
|
725
800
|
}, [readSnapshot, staged]);
|
|
726
801
|
const field = (0, import_react2.useCallback)(
|
|
@@ -871,8 +946,7 @@ var BalanceSettingsCard_default = {
|
|
|
871
946
|
readOnly: "BalanceSettingsCard_readOnly",
|
|
872
947
|
footer: "BalanceSettingsCard_footer",
|
|
873
948
|
failed: "BalanceSettingsCard_failed",
|
|
874
|
-
notice: "BalanceSettingsCard_notice"
|
|
875
|
-
save: "BalanceSettingsCard_save"
|
|
949
|
+
notice: "BalanceSettingsCard_notice"
|
|
876
950
|
};
|
|
877
951
|
|
|
878
952
|
// src/client/settings/BalanceSettingsCard.tsx
|
|
@@ -922,7 +996,8 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
922
996
|
const toggleGroup = (key) => {
|
|
923
997
|
setGroupOpen((current) => ({ ...current, [key]: !current[key] }));
|
|
924
998
|
};
|
|
925
|
-
const groupOpenNow = (key) => groupOpen[key] || GROUP_FIELDS[key].some((name) => form.field(name).invalid) ||
|
|
999
|
+
const groupOpenNow = (key) => groupOpen[key] || GROUP_FIELDS[key].some((name) => form.field(name).invalid) || // 成对校验不是字段级 invalid,得单独问一次:否则收起的阈值组会挡住「保存为什么是灰的」。
|
|
1000
|
+
key === "thresholds" && THRESHOLD_PAIRS.some((pair) => !form.thresholdPairOk(pair.currency));
|
|
926
1001
|
const { available, writable, dirty, invalid, saving, failed } = form.state;
|
|
927
1002
|
const disabled = !writable || saving;
|
|
928
1003
|
const credentialStatus = (name) => {
|
|
@@ -1079,7 +1154,10 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1079
1154
|
{
|
|
1080
1155
|
id: FIELD_IDS.apiKeyState ?? "apiKeyState",
|
|
1081
1156
|
label: t("settings.field.apiKey"),
|
|
1082
|
-
status: {
|
|
1157
|
+
status: {
|
|
1158
|
+
label: t(CREDENTIAL_BADGE[credentialView]),
|
|
1159
|
+
tone: credentialView === "notConfigured" ? "quiet" : "neutral"
|
|
1160
|
+
},
|
|
1083
1161
|
pending: false,
|
|
1084
1162
|
resettable: false,
|
|
1085
1163
|
pendingLabel: t("settings.unsaved"),
|
|
@@ -1089,12 +1167,7 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1089
1167
|
disabled: true,
|
|
1090
1168
|
onReset: () => {
|
|
1091
1169
|
},
|
|
1092
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1093
|
-
ReadOnlyControl,
|
|
1094
|
-
{
|
|
1095
|
-
id: FIELD_IDS.apiKeyState ?? "apiKeyState"
|
|
1096
|
-
}
|
|
1097
|
-
)
|
|
1170
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReadOnlyControl, { id: FIELD_IDS.apiKeyState ?? "apiKeyState" })
|
|
1098
1171
|
}
|
|
1099
1172
|
),
|
|
1100
1173
|
textRow("baseUrl", "settings.field.baseUrl", "settings.hint.baseUrl", false),
|
|
@@ -1153,19 +1226,31 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1153
1226
|
},
|
|
1154
1227
|
last: true,
|
|
1155
1228
|
children: [
|
|
1156
|
-
numberRow(
|
|
1157
|
-
|
|
1158
|
-
|
|
1229
|
+
numberRow(
|
|
1230
|
+
"serverRefreshSeconds",
|
|
1231
|
+
"settings.field.serverRefreshSeconds",
|
|
1232
|
+
"settings.hint.serverRefreshSeconds"
|
|
1233
|
+
),
|
|
1234
|
+
numberRow(
|
|
1235
|
+
"clientPollSeconds",
|
|
1236
|
+
"settings.field.clientPollSeconds",
|
|
1237
|
+
"settings.hint.clientPollSeconds"
|
|
1238
|
+
),
|
|
1239
|
+
numberRow(
|
|
1240
|
+
"manualRefreshCooldownSeconds",
|
|
1241
|
+
"settings.field.manualRefreshCooldownSeconds",
|
|
1242
|
+
"settings.hint.manualRefreshCooldownSeconds"
|
|
1243
|
+
)
|
|
1159
1244
|
]
|
|
1160
1245
|
}
|
|
1161
1246
|
),
|
|
1162
1247
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: BalanceSettingsCard_default.footer, children: [
|
|
1163
1248
|
footerNote === null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: footerNote.className, role: "status", children: footerNote.text }),
|
|
1164
1249
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1165
|
-
|
|
1250
|
+
import_dsh_client_ui_primitives2.Button,
|
|
1166
1251
|
{
|
|
1167
1252
|
type: "button",
|
|
1168
|
-
|
|
1253
|
+
variant: "primary",
|
|
1169
1254
|
disabled: !dirty || invalid || saving || !writable,
|
|
1170
1255
|
onClick: () => {
|
|
1171
1256
|
void form.save();
|
|
@@ -1283,6 +1368,14 @@ function currentAgeMs(seenAt, seenAgeMs, now) {
|
|
|
1283
1368
|
const base = Number.isFinite(seenAgeMs) ? Math.max(0, seenAgeMs) : 0;
|
|
1284
1369
|
return Math.max(0, base + (now - seenAt));
|
|
1285
1370
|
}
|
|
1371
|
+
var MS_PER_SECOND = 1e3;
|
|
1372
|
+
function cooldownUntilOf(now, configuredSeconds, rejectedRemainingMs) {
|
|
1373
|
+
const span = rejectedRemainingMs === null ? Math.max(0, configuredSeconds) * MS_PER_SECOND : Math.max(0, rejectedRemainingMs);
|
|
1374
|
+
return now + span;
|
|
1375
|
+
}
|
|
1376
|
+
function cooldownSecondsOf(until, now) {
|
|
1377
|
+
return Math.max(0, Math.ceil((until - now) / MS_PER_SECOND));
|
|
1378
|
+
}
|
|
1286
1379
|
|
|
1287
1380
|
// src/client/mock/scenarios.ts
|
|
1288
1381
|
var T0 = 176e10;
|
|
@@ -1315,9 +1408,17 @@ var scenarios = {
|
|
|
1315
1408
|
/** 正常。 */
|
|
1316
1409
|
ok: make({}),
|
|
1317
1410
|
/** 余额偏低但可用。 */
|
|
1318
|
-
warn: make({
|
|
1411
|
+
warn: make({
|
|
1412
|
+
severity: "warn",
|
|
1413
|
+
balances: [cny("8.00000000", "0.00000000", "8.00000000")],
|
|
1414
|
+
selected: { currency: "CNY", total: "8.00000000" }
|
|
1415
|
+
}),
|
|
1319
1416
|
/** 余额告急。 */
|
|
1320
|
-
critical: make({
|
|
1417
|
+
critical: make({
|
|
1418
|
+
severity: "critical",
|
|
1419
|
+
balances: [cny("3.00000000", "0.00000000", "3.00000000")],
|
|
1420
|
+
selected: { currency: "CNY", total: "3.00000000" }
|
|
1421
|
+
}),
|
|
1321
1422
|
/** 账户不可用(余额耗尽 / 欠费)。 */
|
|
1322
1423
|
unavailable: make({
|
|
1323
1424
|
severity: "unavailable",
|
|
@@ -1326,7 +1427,14 @@ var scenarios = {
|
|
|
1326
1427
|
selected: { currency: "CNY", total: "0.00000000" }
|
|
1327
1428
|
}),
|
|
1328
1429
|
/** 有旧值但本次刷新失败。 */
|
|
1329
|
-
stale: make({
|
|
1430
|
+
stale: make({
|
|
1431
|
+
state: "stale",
|
|
1432
|
+
stale: true,
|
|
1433
|
+
severity: "unknown",
|
|
1434
|
+
ageMs: 36e5,
|
|
1435
|
+
fetchedAt: T0 - 36e5,
|
|
1436
|
+
error: { code: "NO_NETWORK", message: "fetch failed" }
|
|
1437
|
+
}),
|
|
1330
1438
|
/** 无值失败。 */
|
|
1331
1439
|
error: make({
|
|
1332
1440
|
state: "error",
|
|
@@ -1339,14 +1447,35 @@ var scenarios = {
|
|
|
1339
1447
|
error: { code: "UPSTREAM_5XX", message: "upstream returned 500" }
|
|
1340
1448
|
}),
|
|
1341
1449
|
/** 未配置。 */
|
|
1342
|
-
empty: make({
|
|
1450
|
+
empty: make({
|
|
1451
|
+
state: "empty",
|
|
1452
|
+
severity: "unknown",
|
|
1453
|
+
isAvailable: false,
|
|
1454
|
+
balances: [],
|
|
1455
|
+
selected: null,
|
|
1456
|
+
ageMs: 0
|
|
1457
|
+
}),
|
|
1343
1458
|
/** 未配置且带 NO_KEY 错误。 */
|
|
1344
|
-
noKey: make({
|
|
1459
|
+
noKey: make({
|
|
1460
|
+
state: "empty",
|
|
1461
|
+
severity: "unknown",
|
|
1462
|
+
isAvailable: false,
|
|
1463
|
+
balances: [],
|
|
1464
|
+
selected: null,
|
|
1465
|
+
ageMs: 0,
|
|
1466
|
+
error: { code: "NO_KEY", message: "no API key configured" }
|
|
1467
|
+
}),
|
|
1345
1468
|
/** 多币种。`selected` 显式写出,不靠 `make()` 的默认值兜。 */
|
|
1346
1469
|
multiCurrency: make({
|
|
1347
|
-
balances: [
|
|
1470
|
+
balances: [
|
|
1471
|
+
cny("110.00000000", "10.00000000", "100.00000000"),
|
|
1472
|
+
{ currency: "USD", total: "20.00000000", granted: "0.00000000", toppedUp: "20.00000000" }
|
|
1473
|
+
],
|
|
1348
1474
|
selected: { currency: "CNY", total: "110.00000000" },
|
|
1349
|
-
thresholds: {
|
|
1475
|
+
thresholds: {
|
|
1476
|
+
CNY: { warn: "10.00000000", critical: "5.00000000" },
|
|
1477
|
+
USD: { warn: "2.00000000", critical: "1.00000000" }
|
|
1478
|
+
}
|
|
1350
1479
|
}),
|
|
1351
1480
|
/**
|
|
1352
1481
|
* 选定了账户里没有的币种(USD),账户只有 CNY。
|
|
@@ -1561,9 +1690,12 @@ function BalancePopover(props) {
|
|
|
1561
1690
|
const cooling = cooldownSeconds > 0;
|
|
1562
1691
|
let statusText = "";
|
|
1563
1692
|
if (refreshing) statusText = t("popover.refreshing");
|
|
1564
|
-
else if (cooling)
|
|
1693
|
+
else if (cooling)
|
|
1694
|
+
statusText = interpolate(t("popover.cooldown"), { value: String(cooldownSeconds) });
|
|
1565
1695
|
const refreshLabel = t("sidebar.aria.refresh");
|
|
1566
|
-
const pluginsLabel = t(
|
|
1696
|
+
const pluginsLabel = t(
|
|
1697
|
+
pluginsAction?.reachesConfig === true ? "popover.action.openPluginConfig" : "popover.action.openPlugins"
|
|
1698
|
+
);
|
|
1567
1699
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1568
1700
|
"section",
|
|
1569
1701
|
{
|
|
@@ -1609,7 +1741,16 @@ function BalancePopover(props) {
|
|
|
1609
1741
|
] }),
|
|
1610
1742
|
shown !== null && !selection.matchesPreference ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: BalancePopover_default.notice, children: [
|
|
1611
1743
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: BalancePopover_default.noticeText, children: interpolate(t("popover.mismatch"), { wanted: displayCurrency, shown: shown.currency }) }),
|
|
1612
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: BalancePopover_default.noticeActions, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: BalancePopover_default.noticeActions, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1745
|
+
import_dsh_client_ui_primitives3.Button,
|
|
1746
|
+
{
|
|
1747
|
+
size: "sm",
|
|
1748
|
+
variant: "outline",
|
|
1749
|
+
disabled: useShownDisabled === true,
|
|
1750
|
+
onClick: onUseShown,
|
|
1751
|
+
children: interpolate(t("popover.action.useShown"), { shown: shown.currency })
|
|
1752
|
+
}
|
|
1753
|
+
) })
|
|
1613
1754
|
] }) : null,
|
|
1614
1755
|
configSlotWarning === null ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: BalancePopover_default.notice, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: BalancePopover_default.noticeText, children: configSlotWarning }) }),
|
|
1615
1756
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: BalancePopover_default.footer, children: [
|
|
@@ -1654,7 +1795,13 @@ var CROSS_ARM = (2 * RADIUS - STROKE) / 2 / Math.SQRT2;
|
|
|
1654
1795
|
function round3(value) {
|
|
1655
1796
|
return Math.round(value * 1e3) / 1e3;
|
|
1656
1797
|
}
|
|
1657
|
-
function PercentRing({
|
|
1798
|
+
function PercentRing({
|
|
1799
|
+
state,
|
|
1800
|
+
marker = null,
|
|
1801
|
+
ratio = 1,
|
|
1802
|
+
size = 18,
|
|
1803
|
+
title
|
|
1804
|
+
}) {
|
|
1658
1805
|
const clamped = Number.isFinite(ratio) ? Math.min(1, Math.max(0, ratio)) : 1;
|
|
1659
1806
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1660
1807
|
"svg",
|
|
@@ -1720,8 +1867,8 @@ var REFRESH_SIMULATION_MS = 600;
|
|
|
1720
1867
|
var PANEL_GAP = 8;
|
|
1721
1868
|
var PANEL_MARGIN = 12;
|
|
1722
1869
|
var MEASURE_STYLE = { visibility: "hidden", left: 0, top: 0 };
|
|
1723
|
-
var
|
|
1724
|
-
var TICK_MS =
|
|
1870
|
+
var MS_PER_SECOND2 = 1e3;
|
|
1871
|
+
var TICK_MS = MS_PER_SECOND2;
|
|
1725
1872
|
function useConfigSlotState(probe) {
|
|
1726
1873
|
const [state, setState] = (0, import_react5.useState)(() => probe.getSnapshot());
|
|
1727
1874
|
(0, import_react5.useEffect)(() => {
|
|
@@ -1747,8 +1894,10 @@ function usePluginsNavigation(navigation) {
|
|
|
1747
1894
|
return action;
|
|
1748
1895
|
}
|
|
1749
1896
|
function stateLabelKey(response, selection) {
|
|
1750
|
-
if (response.state === "error")
|
|
1751
|
-
|
|
1897
|
+
if (response.state === "error")
|
|
1898
|
+
return response.error?.code === "NO_KEY" ? "state.noKey" : "state.error";
|
|
1899
|
+
if (response.state === "empty")
|
|
1900
|
+
return response.error?.code === "NO_KEY" ? "state.noKey" : "state.empty";
|
|
1752
1901
|
if (response.state === "stale") return "state.stale";
|
|
1753
1902
|
if (!response.isAvailable) return "state.unavailable";
|
|
1754
1903
|
if (selection.shown === null) return "state.noBalance";
|
|
@@ -1793,16 +1942,19 @@ function SidebarBalance({
|
|
|
1793
1942
|
}, []);
|
|
1794
1943
|
const preference = config.displayCurrency;
|
|
1795
1944
|
const selection = (0, import_react5.useMemo)(() => selectionOf(response, preference), [response, preference]);
|
|
1796
|
-
(0, import_react5.useEffect)(
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1945
|
+
(0, import_react5.useEffect)(
|
|
1946
|
+
() => subscribeScenario((key) => {
|
|
1947
|
+
const active = resolveScenario() !== null;
|
|
1948
|
+
setMock(active);
|
|
1949
|
+
if (!active || lastScenario.current === key) return;
|
|
1950
|
+
lastScenario.current = key;
|
|
1951
|
+
acceptBalance(currentBalance());
|
|
1952
|
+
setRefreshing(false);
|
|
1953
|
+
setCooldownUntil(0);
|
|
1954
|
+
setOpen(false);
|
|
1955
|
+
}),
|
|
1956
|
+
[acceptBalance]
|
|
1957
|
+
);
|
|
1806
1958
|
(0, import_react5.useEffect)(() => {
|
|
1807
1959
|
if (mock) return;
|
|
1808
1960
|
let cancelled = false;
|
|
@@ -1818,17 +1970,30 @@ function SidebarBalance({
|
|
|
1818
1970
|
}
|
|
1819
1971
|
};
|
|
1820
1972
|
void load();
|
|
1821
|
-
const id = window.setInterval(
|
|
1822
|
-
|
|
1823
|
-
|
|
1973
|
+
const id = window.setInterval(
|
|
1974
|
+
() => {
|
|
1975
|
+
void load();
|
|
1976
|
+
},
|
|
1977
|
+
Math.max(5, config.clientPollSeconds) * MS_PER_SECOND2
|
|
1978
|
+
);
|
|
1824
1979
|
return () => {
|
|
1825
1980
|
cancelled = true;
|
|
1826
1981
|
window.clearInterval(id);
|
|
1827
1982
|
};
|
|
1828
|
-
}, [
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1983
|
+
}, [
|
|
1984
|
+
mock,
|
|
1985
|
+
preference,
|
|
1986
|
+
config.clientPollSeconds,
|
|
1987
|
+
config.configSignature,
|
|
1988
|
+
acceptBalance,
|
|
1989
|
+
showUnreachable
|
|
1990
|
+
]);
|
|
1991
|
+
(0, import_react5.useEffect)(
|
|
1992
|
+
() => () => {
|
|
1993
|
+
if (refreshTimer.current !== void 0) window.clearTimeout(refreshTimer.current);
|
|
1994
|
+
},
|
|
1995
|
+
[]
|
|
1996
|
+
);
|
|
1832
1997
|
const closeNow = (0, import_react5.useCallback)(() => {
|
|
1833
1998
|
setOpen(false);
|
|
1834
1999
|
}, []);
|
|
@@ -1843,9 +2008,12 @@ function SidebarBalance({
|
|
|
1843
2008
|
gap: PANEL_GAP,
|
|
1844
2009
|
margin: PANEL_MARGIN
|
|
1845
2010
|
});
|
|
1846
|
-
(0, import_react5.
|
|
2011
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
1847
2012
|
if (!open) return;
|
|
1848
2013
|
setNow(Date.now());
|
|
2014
|
+
}, [open]);
|
|
2015
|
+
(0, import_react5.useEffect)(() => {
|
|
2016
|
+
if (!open) return;
|
|
1849
2017
|
const id = window.setInterval(() => {
|
|
1850
2018
|
setNow(Date.now());
|
|
1851
2019
|
}, TICK_MS);
|
|
@@ -1853,6 +2021,17 @@ function SidebarBalance({
|
|
|
1853
2021
|
window.clearInterval(id);
|
|
1854
2022
|
};
|
|
1855
2023
|
}, [open]);
|
|
2024
|
+
(0, import_react5.useEffect)(() => {
|
|
2025
|
+
if (cooldownUntil === 0) return;
|
|
2026
|
+
const remaining = cooldownUntil - Date.now();
|
|
2027
|
+
if (remaining <= 0) return;
|
|
2028
|
+
const id = window.setTimeout(() => {
|
|
2029
|
+
setNow(Date.now());
|
|
2030
|
+
}, remaining);
|
|
2031
|
+
return () => {
|
|
2032
|
+
window.clearTimeout(id);
|
|
2033
|
+
};
|
|
2034
|
+
}, [cooldownUntil]);
|
|
1856
2035
|
(0, import_react5.useEffect)(() => {
|
|
1857
2036
|
if (!open) return;
|
|
1858
2037
|
const onKeyDown = (event) => {
|
|
@@ -1868,31 +2047,46 @@ function SidebarBalance({
|
|
|
1868
2047
|
if (refreshing) return;
|
|
1869
2048
|
if (Date.now() < cooldownUntil) return;
|
|
1870
2049
|
setRefreshing(true);
|
|
1871
|
-
const finish = () => {
|
|
2050
|
+
const finish = (rejectedRemainingMs) => {
|
|
2051
|
+
const at = Date.now();
|
|
1872
2052
|
setRefreshing(false);
|
|
1873
|
-
setCooldownUntil(
|
|
2053
|
+
setCooldownUntil(
|
|
2054
|
+
cooldownUntilOf(at, config.manualRefreshCooldownSeconds, rejectedRemainingMs)
|
|
2055
|
+
);
|
|
2056
|
+
setNow(at);
|
|
1874
2057
|
};
|
|
1875
2058
|
if (mock) {
|
|
1876
2059
|
refreshTimer.current = window.setTimeout(() => {
|
|
1877
2060
|
refreshTimer.current = void 0;
|
|
1878
2061
|
markFresh();
|
|
1879
|
-
finish();
|
|
2062
|
+
finish(null);
|
|
1880
2063
|
}, REFRESH_SIMULATION_MS);
|
|
1881
2064
|
return;
|
|
1882
2065
|
}
|
|
1883
2066
|
void (async () => {
|
|
2067
|
+
let rejectedRemainingMs = null;
|
|
1884
2068
|
try {
|
|
1885
|
-
await requestRefresh({ reason: "manual" });
|
|
2069
|
+
const result = await requestRefresh({ reason: "manual" });
|
|
2070
|
+
if (!result.triggered) rejectedRemainingMs = Math.max(0, result.cooldownMs);
|
|
1886
2071
|
const next = await requestBalance({ currency: preference });
|
|
1887
2072
|
loadedRef.current = true;
|
|
1888
2073
|
acceptBalance(next);
|
|
1889
2074
|
} catch (error) {
|
|
1890
2075
|
if (!loadedRef.current) showUnreachable(error);
|
|
1891
2076
|
} finally {
|
|
1892
|
-
finish();
|
|
2077
|
+
finish(rejectedRemainingMs);
|
|
1893
2078
|
}
|
|
1894
2079
|
})();
|
|
1895
|
-
}, [
|
|
2080
|
+
}, [
|
|
2081
|
+
cooldownUntil,
|
|
2082
|
+
config.manualRefreshCooldownSeconds,
|
|
2083
|
+
mock,
|
|
2084
|
+
preference,
|
|
2085
|
+
refreshing,
|
|
2086
|
+
acceptBalance,
|
|
2087
|
+
showUnreachable,
|
|
2088
|
+
markFresh
|
|
2089
|
+
]);
|
|
1896
2090
|
const handleUseShown = (0, import_react5.useCallback)(() => {
|
|
1897
2091
|
const current = selection.shown;
|
|
1898
2092
|
if (current === null) return;
|
|
@@ -1933,7 +2127,7 @@ function SidebarBalance({
|
|
|
1933
2127
|
if (stateText !== null && stateText !== markerLabel) ariaParts.push(stateText);
|
|
1934
2128
|
if (markerLabel !== null) ariaParts.push(markerLabel);
|
|
1935
2129
|
const ariaLabel = ariaParts.join(" ");
|
|
1936
|
-
const cooldownSeconds =
|
|
2130
|
+
const cooldownSeconds = cooldownSecondsOf(cooldownUntil, now);
|
|
1937
2131
|
const ageMs = currentAgeMs(view.seenAt, view.seenAgeMs, now);
|
|
1938
2132
|
const ringTitle = !wide && stateText !== null ? `${t("sidebar.aria.ring")} ${stateText}` : void 0;
|
|
1939
2133
|
const hoverLabel = shown === null ? stateText : formatMoney(shown.total, shown.currency);
|
|
@@ -1949,42 +2143,42 @@ function SidebarBalance({
|
|
|
1949
2143
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: SidebarBalance_default.icon, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PercentRing, { state: ring.state, marker: ring.marker, ratio: ringRatio, size: 16 }) }),
|
|
1950
2144
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: SidebarBalance_default.label, children: t("sidebar.label") }),
|
|
1951
2145
|
markerLabel === null ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives4.Tooltip, { label: markerHint, side: "bottom", delayMs: 500, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: SidebarBalance_default.marker, role: "img", "aria-label": markerLabel, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives4.IconWarningOutlineRegular, { size: 12 }) }) })
|
|
1952
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
children: [
|
|
1963
|
-
wide && hoverLabel !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives4.Tooltip, { label: hoverLabel, side: "right", delayMs: 500, disabled: open, children: trigger }) : trigger,
|
|
1964
|
-
open ? (0, import_react_dom.createPortal)(
|
|
1965
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1966
|
-
BalancePopover,
|
|
1967
|
-
{
|
|
1968
|
-
t,
|
|
1969
|
-
selection,
|
|
1970
|
-
displayCurrency: preference,
|
|
1971
|
-
ageMs,
|
|
1972
|
-
refreshing,
|
|
1973
|
-
cooldownSeconds,
|
|
1974
|
-
configSlotWarning: configSlotState === "missing" ? CONFIG_SLOT_WARNING : null,
|
|
1975
|
-
panelRef,
|
|
1976
|
-
style: pos ?? MEASURE_STYLE,
|
|
1977
|
-
onRefresh: handleRefresh,
|
|
1978
|
-
onUseShown: handleUseShown,
|
|
1979
|
-
useShownDisabled: !config.writable,
|
|
1980
|
-
pluginsAction: popoverPluginsAction
|
|
1981
|
-
}
|
|
1982
|
-
),
|
|
1983
|
-
document.body
|
|
1984
|
-
) : null
|
|
1985
|
-
]
|
|
2146
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2147
|
+
PercentRing,
|
|
2148
|
+
{
|
|
2149
|
+
state: ring.state,
|
|
2150
|
+
marker: ring.marker,
|
|
2151
|
+
ratio: ringRatio,
|
|
2152
|
+
size: 18,
|
|
2153
|
+
title: ringTitle
|
|
2154
|
+
}
|
|
2155
|
+
)
|
|
1986
2156
|
}
|
|
1987
2157
|
);
|
|
2158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: rootRef, className: SidebarBalance_default.root, "data-mode": wide ? "wide" : "rail", tabIndex: -1, children: [
|
|
2159
|
+
wide && hoverLabel !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives4.Tooltip, { label: hoverLabel, side: "right", delayMs: 500, disabled: open, children: trigger }) : trigger,
|
|
2160
|
+
open ? (0, import_react_dom.createPortal)(
|
|
2161
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2162
|
+
BalancePopover,
|
|
2163
|
+
{
|
|
2164
|
+
t,
|
|
2165
|
+
selection,
|
|
2166
|
+
displayCurrency: preference,
|
|
2167
|
+
ageMs,
|
|
2168
|
+
refreshing,
|
|
2169
|
+
cooldownSeconds,
|
|
2170
|
+
configSlotWarning: configSlotState === "missing" ? CONFIG_SLOT_WARNING : null,
|
|
2171
|
+
panelRef,
|
|
2172
|
+
style: pos ?? MEASURE_STYLE,
|
|
2173
|
+
onRefresh: handleRefresh,
|
|
2174
|
+
onUseShown: handleUseShown,
|
|
2175
|
+
useShownDisabled: !config.writable,
|
|
2176
|
+
pluginsAction: popoverPluginsAction
|
|
2177
|
+
}
|
|
2178
|
+
),
|
|
2179
|
+
document.body
|
|
2180
|
+
) : null
|
|
2181
|
+
] });
|
|
1988
2182
|
}
|
|
1989
2183
|
|
|
1990
2184
|
// src/client/index.tsx
|
|
@@ -2142,7 +2336,10 @@ function apply(ctx) {
|
|
|
2142
2336
|
const candidate = face["openBundle"];
|
|
2143
2337
|
if (typeof candidate !== "function") return;
|
|
2144
2338
|
const openBundle = candidate.bind(face);
|
|
2145
|
-
navCtx.effect(
|
|
2339
|
+
navCtx.effect(
|
|
2340
|
+
() => pluginsNavigation.attachDeepLink(openBundle),
|
|
2341
|
+
"ds-balance: bundle config deep link"
|
|
2342
|
+
);
|
|
2146
2343
|
});
|
|
2147
2344
|
ctx.inject(["layout"], (layoutCtx) => {
|
|
2148
2345
|
if (!("layout" in layoutCtx)) return;
|
|
@@ -2160,25 +2357,31 @@ function apply(ctx) {
|
|
|
2160
2357
|
ctx.inject(["configForms"], (configCtx) => {
|
|
2161
2358
|
configSlotProbe.markDeclared();
|
|
2162
2359
|
const form = configCtx.configForms.get(ENTRY_ID);
|
|
2163
|
-
ctx.slots.inject(
|
|
2164
|
-
|
|
2165
|
-
(
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2360
|
+
ctx.slots.inject(
|
|
2361
|
+
CONFIG_SLOT,
|
|
2362
|
+
() => ctx.slots.register(
|
|
2363
|
+
{ name: CONFIG_SLOT, key: BUNDLE_CONFIG_KEY, locale: NS },
|
|
2364
|
+
(seat) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SettingsSeatComponent, { seat, form })
|
|
2365
|
+
)
|
|
2366
|
+
);
|
|
2367
|
+
ctx.slots.inject(
|
|
2368
|
+
"sidebar.footer.action",
|
|
2369
|
+
() => ctx.slots.register(
|
|
2370
|
+
{ name: "sidebar.footer.action", id: SIDEBAR_ENTRY_ID, order: 0, locale: NS },
|
|
2371
|
+
(seat) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2372
|
+
SidebarSeatComponent,
|
|
2373
|
+
{
|
|
2374
|
+
seat,
|
|
2375
|
+
form,
|
|
2376
|
+
configSlotProbe,
|
|
2377
|
+
pluginsNavigation
|
|
2378
|
+
}
|
|
2379
|
+
)
|
|
2177
2380
|
)
|
|
2178
|
-
)
|
|
2381
|
+
);
|
|
2179
2382
|
});
|
|
2180
2383
|
}
|
|
2181
|
-
var __dsbCss = "/* src/client/settings/fields.module.css */\n.fields_group {\n padding: 12px 0 0;\n}\n.fields_groupLast {\n padding-bottom: 12px;\n}\n.fields_groupNote {\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.fields_fields {\n display: flex;\n flex-direction: column;\n}\n.fields_fields > * + * {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.fields_details {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n margin-top: 12px;\n padding-top: 12px;\n}\n.fields_detailsSummary {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n list-style: none;\n}\n.fields_detailsSummary::-webkit-details-marker {\n display: none;\n}\n.fields_detailsSummary::before {\n content: \"\";\n flex: none;\n width: 5px;\n height: 5px;\n border-right: 1.5px solid currentColor;\n border-bottom: 1.5px solid currentColor;\n transform: translate(-0.5px, -1px) rotate(-45deg);\n transition: transform 120ms ease;\n}\n.fields_details[open] > .fields_detailsSummary::before {\n transform: translate(-0.5px, -1px) rotate(45deg);\n}\n.fields_detailsBody {\n padding-top: 10px;\n}\n.fields_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.fields_row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n}\n.fields_rowText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-right: 48px;\n}\n.fields_rowTitleLine {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_rowTitle {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_badges {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.fields_reset {\n border: none;\n background: none;\n padding: 0;\n font: inherit;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n.fields_reset:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n.fields_reset:disabled {\n cursor: default;\n}\n.fields_input {\n box-sizing: border-box;\n width: 100%;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.fields_input:disabled {\n color: var(--dsw-alias-label-tertiary);\n opacity: 0.6;\n cursor: default;\n}\ninput.fields_inputStatic,\ninput.fields_inputStatic:hover,\ninput.fields_inputStatic:focus,\ninput.fields_inputStatic:focus-visible,\ninput.fields_inputStatic:active {\n border-color: var(--dsw-alias-border-l4);\n background: var(--dsw-alias-bg-layer-3);\n outline: none;\n box-shadow: none;\n cursor: default;\n pointer-events: none;\n}\n.fields_inputInvalid {\n box-sizing: border-box;\n width: 100%;\n height: 34px;\n padding: 0 12px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_inputInvalid:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.fields_inputInvalid:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.fields_inputWithAction {\n position: relative;\n display: flex;\n align-items: center;\n}\n.fields_inputWithAction .fields_input,\n.fields_inputWithAction .fields_inputInvalid {\n padding-right: 38px;\n}\n.fields_reveal {\n position: absolute;\n right: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.fields_reveal:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n.fields_revealOn {\n color: var(--dsw-alias-label-primary);\n}\n.fields_reveal:disabled {\n cursor: default;\n opacity: 0.4;\n}\n.fields_selectorAnchor {\n flex: none;\n}\n.fields_selector {\n display: inline-flex;\n align-items: center;\n gap: 12px;\n flex: none;\n max-width: 100%;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n background: var(--dsw-alias-bg-module-platform);\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n text-align: left;\n cursor: pointer;\n}\n.fields_selector:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.fields_selector:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.fields_selectorChevron {\n flex: none;\n}\n.fields_hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.fields_pairNote {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-warn-primary);\n}\n.fields_pairNote::before {\n content: \"\";\n flex: none;\n width: 5px;\n height: 5px;\n border-radius: 999px;\n corner-shape: round;\n background: currentColor;\n}\n.fields_invalid {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n.fields_actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_actionButton {\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n.fields_actionButton:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.fields_actionButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.fields_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n.fields_resultOk {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-success-primary);\n}\n.fields_resultFail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n\n/* src/client/settings/BalanceSettingsCard.module.css */\n.BalanceSettingsCard_form {\n display: flex;\n flex-direction: column;\n}\n.BalanceSettingsCard_readOnly {\n margin: 0 0 12px;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalanceSettingsCard_footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 16px;\n}\n.BalanceSettingsCard_failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n.BalanceSettingsCard_notice {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalanceSettingsCard_save {\n appearance: none;\n border: 0.5px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n.BalanceSettingsCard_save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.BalanceSettingsCard_save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* src/client/sidebar/BalancePopover.module.css */\n.BalancePopover_panel {\n position: fixed;\n isolation: isolate;\n z-index: 1100;\n box-sizing: border-box;\n width: max-content;\n min-width: min(300px, calc(100vw - 24px));\n max-width: min(440px, calc(100vw - 24px));\n padding: 16px;\n border: 0;\n border-radius: 12px;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n.BalancePopover_panel::before {\n position: absolute;\n z-index: -1;\n inset: 0;\n border-radius: inherit;\n background: var(--dsw-specific-menu);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n content: \"\";\n pointer-events: none;\n}\n.BalancePopover_title {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 8px;\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n.BalancePopover_titleLabel {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n cursor: pointer;\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.BalancePopover_titleLabel:hover,\n.BalancePopover_titleLabel:visited {\n color: inherit;\n}\n.BalancePopover_titleLabel svg {\n flex: none;\n width: 14px;\n height: auto;\n}\n.BalancePopover_iconButton {\n position: relative;\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n corner-shape: round;\n padding: 0;\n background: transparent;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n}\n.BalancePopover_iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.BalancePopover_iconButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.BalancePopover_titleRule {\n margin-bottom: 10px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.BalancePopover_details {\n display: grid;\n grid-template-columns: minmax(76px, auto) minmax(0, 1fr);\n gap: 6px 16px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_details dt,\n.BalancePopover_details dd {\n min-width: 0;\n margin: 0;\n}\n.BalancePopover_details dd {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n.BalancePopover_notice {\n margin-top: 12px;\n}\n.BalancePopover_noticeText {\n margin: 0 0 8px;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_noticeActions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n}\n.BalancePopover_footer {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 12px;\n}\n.BalancePopover_updated {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_status {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: right;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_refresh {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.BalancePopover_refresh:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n.BalancePopover_refresh:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n.BalancePopover_refresh:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.BalancePopover_refresh[data-cooling] {\n color: var(--dsw-alias-label-caption);\n}\n.BalancePopover_refresh[data-refreshing] svg {\n animation: BalancePopover_balance-refresh-spin 900ms linear infinite;\n}\n@keyframes BalancePopover_balance-refresh-spin {\n to {\n transform: rotate(360deg);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .BalancePopover_refresh[data-refreshing] svg {\n animation-duration: 2400ms;\n }\n}\n\n/* src/client/sidebar/PercentRing.module.css */\n.PercentRing_ring {\n display: block;\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n}\n.PercentRing_ring[data-state=done] {\n color: var(--dsw-alias-state-success-primary);\n}\n.PercentRing_ring[data-state=warning] {\n color: var(--dsw-alias-state-warn-primary);\n}\n.PercentRing_ring[data-state=error] {\n color: var(--dsw-alias-state-error-primary);\n}\n.PercentRing_ring[data-state=idle] {\n color: var(--dsw-alias-state-idle-primary);\n}\n.PercentRing_track {\n fill: none;\n stroke: var(--dsw-alias-border-l3);\n stroke-width: 1;\n}\n.PercentRing_fill {\n fill: none;\n stroke: currentColor;\n stroke-width: 1;\n stroke-linecap: round;\n}\n.PercentRing_cross {\n fill: none;\n stroke: currentColor;\n stroke-width: 1;\n stroke-linecap: round;\n}\n\n/* src/client/sidebar/SidebarBalance.module.css */\n.SidebarBalance_root {\n position: relative;\n display: flex;\n min-width: 0;\n}\n.SidebarBalance_root[data-mode=wide] {\n flex: none;\n width: calc(100% + 4px);\n margin: 4px -2px 0;\n}\n.SidebarBalance_root[data-mode=rail] {\n flex: none;\n margin: 8px 0 0;\n}\n.SidebarBalance_trigger {\n display: flex;\n align-items: center;\n box-sizing: border-box;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n overflow: hidden;\n}\n.SidebarBalance_trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.SidebarBalance_trigger:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.SidebarBalance_root[data-mode=wide] .SidebarBalance_trigger {\n flex: none;\n gap: 8px;\n width: 100%;\n height: 42px;\n padding: 0 10px 0 8px;\n border-radius: 12px;\n}\n.SidebarBalance_root[data-mode=rail] .SidebarBalance_trigger {\n flex: none;\n justify-content: center;\n width: 36px;\n height: 36px;\n padding: 0;\n border-radius: 12px;\n}\n.SidebarBalance_icon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n}\n.SidebarBalance_label {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.SidebarBalance_marker {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-tertiary);\n position: relative;\n top: 1.63px;\n}\n\n/* src/client/sidebar/footer-stack.module.css */\ndiv:has(> [data-slot=\"sidebar.footer.action\"]) {\n flex-direction: column;\n}\n";
|
|
2384
|
+
var __dsbCss = "/* src/client/settings/fields.module.css */\n.fields_group {\n padding: 12px 0 0;\n}\n.fields_groupLast {\n padding-bottom: 12px;\n}\n.fields_groupNote {\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.fields_fields {\n display: flex;\n flex-direction: column;\n}\n.fields_fields > * + * {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.fields_details {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n margin-top: 12px;\n padding-top: 12px;\n}\n.fields_detailsBody {\n padding-top: 10px;\n}\n.fields_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.fields_row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n}\n.fields_rowText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding-right: 48px;\n}\n.fields_rowTitleLine {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_rowTitle {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.fields_badges {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.fields_reset {\n border: none;\n background: none;\n padding: 0;\n font: inherit;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n.fields_reset:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n.fields_reset:disabled {\n cursor: default;\n}\n.fields_inputStatic,\n.fields_inputStatic:hover {\n pointer-events: none;\n}\n.fields_inputStatic input,\n.fields_inputStatic input:hover,\n.fields_inputStatic input:focus,\n.fields_inputStatic input:focus-visible,\n.fields_inputStatic input:active {\n border-color: var(--dsw-alias-border-l4);\n background: var(--dsw-alias-bg-layer-3);\n outline: none;\n box-shadow: none;\n cursor: default;\n}\n.fields_inputInvalid input {\n border: 1px solid var(--dsw-alias-state-error-primary);\n}\n.fields_inputInvalid input:focus-visible {\n border-color: var(--dsw-alias-brand-primary);\n}\n.fields_inputWithAction {\n position: relative;\n display: flex;\n align-items: center;\n}\n.fields_inputWithAction .fields_input,\n.fields_inputWithAction .fields_inputInvalid {\n padding-right: 38px;\n}\n.fields_reveal {\n position: absolute;\n right: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.fields_reveal:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n.fields_revealOn {\n color: var(--dsw-alias-label-primary);\n}\n.fields_reveal:disabled {\n cursor: default;\n opacity: 0.4;\n}\n.fields_selectorAnchor {\n flex: none;\n}\n.fields_selector {\n display: inline-flex;\n align-items: center;\n gap: 12px;\n flex: none;\n max-width: 100%;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n background: var(--dsw-alias-bg-module-platform);\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n text-align: left;\n cursor: pointer;\n}\n.fields_selector:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.fields_selector:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.fields_selectorChevron {\n flex: none;\n}\n.fields_hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.fields_pairNote {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-warn-primary);\n}\n.fields_pairNote::before {\n content: \"\";\n flex: none;\n width: 5px;\n height: 5px;\n border-radius: 999px;\n corner-shape: round;\n background: currentColor;\n}\n.fields_invalid {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n.fields_actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.fields_resultOk {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-success-primary);\n}\n.fields_resultFail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n\n/* src/client/settings/BalanceSettingsCard.module.css */\n.BalanceSettingsCard_form {\n display: flex;\n flex-direction: column;\n}\n.BalanceSettingsCard_readOnly {\n margin: 0 0 12px;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalanceSettingsCard_footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 16px;\n}\n.BalanceSettingsCard_failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n.BalanceSettingsCard_notice {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* src/client/sidebar/BalancePopover.module.css */\n.BalancePopover_panel {\n position: fixed;\n isolation: isolate;\n z-index: 1100;\n box-sizing: border-box;\n width: max-content;\n min-width: min(300px, calc(100vw - 24px));\n max-width: min(440px, calc(100vw - 24px));\n padding: 16px;\n border: 0;\n border-radius: 12px;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n box-shadow: var(--dsw-elevation-prominent);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n.BalancePopover_panel::before {\n position: absolute;\n z-index: -1;\n inset: 0;\n border-radius: inherit;\n background: var(--dsw-specific-menu);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n content: \"\";\n pointer-events: none;\n}\n.BalancePopover_title {\n display: flex;\n justify-content: space-between;\n gap: 16px;\n margin-bottom: 8px;\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n.BalancePopover_titleLabel {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n cursor: pointer;\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n.BalancePopover_titleLabel:hover,\n.BalancePopover_titleLabel:visited {\n color: inherit;\n}\n.BalancePopover_titleLabel svg {\n flex: none;\n width: 14px;\n height: auto;\n}\n.BalancePopover_iconButton {\n position: relative;\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 50%;\n corner-shape: round;\n padding: 0;\n background: transparent;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n}\n.BalancePopover_iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.BalancePopover_iconButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.BalancePopover_titleRule {\n margin-bottom: 10px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.BalancePopover_details {\n display: grid;\n grid-template-columns: minmax(76px, auto) minmax(0, 1fr);\n gap: 6px 16px;\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_details dt,\n.BalancePopover_details dd {\n min-width: 0;\n margin: 0;\n}\n.BalancePopover_details dd {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n text-align: right;\n}\n.BalancePopover_notice {\n margin-top: 12px;\n}\n.BalancePopover_noticeText {\n margin: 0 0 8px;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_noticeActions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n}\n.BalancePopover_footer {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 12px;\n}\n.BalancePopover_updated {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_status {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n text-align: right;\n color: var(--dsw-alias-label-tertiary);\n}\n.BalancePopover_refresh {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: none;\n border-radius: 999px;\n corner-shape: round;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.BalancePopover_refresh:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n.BalancePopover_refresh:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n.BalancePopover_refresh:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.BalancePopover_refresh[data-cooling] {\n color: var(--dsw-alias-label-caption);\n}\n.BalancePopover_refresh[data-refreshing] svg {\n animation: BalancePopover_balance-refresh-spin 900ms linear infinite;\n}\n@keyframes BalancePopover_balance-refresh-spin {\n to {\n transform: rotate(360deg);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .BalancePopover_refresh[data-refreshing] svg {\n animation-duration: 2400ms;\n }\n}\n\n/* src/client/sidebar/PercentRing.module.css */\n.PercentRing_ring {\n display: block;\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n}\n.PercentRing_ring[data-state=done] {\n color: var(--dsw-alias-state-success-primary);\n}\n.PercentRing_ring[data-state=warning] {\n color: var(--dsw-alias-state-warn-primary);\n}\n.PercentRing_ring[data-state=error] {\n color: var(--dsw-alias-state-error-primary);\n}\n.PercentRing_ring[data-state=idle] {\n color: var(--dsw-alias-state-idle-primary);\n}\n.PercentRing_track {\n fill: none;\n stroke: var(--dsw-alias-border-l3);\n stroke-width: 1;\n}\n.PercentRing_fill {\n fill: none;\n stroke: currentColor;\n stroke-width: 1;\n stroke-linecap: round;\n}\n.PercentRing_cross {\n fill: none;\n stroke: currentColor;\n stroke-width: 1;\n stroke-linecap: round;\n}\n\n/* src/client/sidebar/SidebarBalance.module.css */\n.SidebarBalance_root {\n position: relative;\n display: flex;\n min-width: 0;\n}\n.SidebarBalance_root[data-mode=wide] {\n flex: none;\n width: calc(100% + 4px);\n margin: 4px -2px 0;\n}\n.SidebarBalance_root[data-mode=rail] {\n flex: none;\n margin: 8px 0 0;\n}\n.SidebarBalance_trigger {\n display: flex;\n align-items: center;\n box-sizing: border-box;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n overflow: hidden;\n}\n.SidebarBalance_trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.SidebarBalance_trigger:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.SidebarBalance_root[data-mode=wide] .SidebarBalance_trigger {\n flex: none;\n gap: 8px;\n width: 100%;\n height: 42px;\n padding: 0 10px 0 8px;\n border-radius: 12px;\n}\n.SidebarBalance_root[data-mode=rail] .SidebarBalance_trigger {\n flex: none;\n justify-content: center;\n width: 36px;\n height: 36px;\n padding: 0;\n border-radius: 12px;\n}\n.SidebarBalance_icon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n}\n.SidebarBalance_label {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.SidebarBalance_marker {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-tertiary);\n position: relative;\n top: 1.63px;\n}\n\n/* src/client/sidebar/footer-stack.module.css */\ndiv:has(> [data-slot=\"sidebar.footer.action\"]) {\n flex-direction: column;\n}\n";
|
|
2182
2385
|
var __dsbTagId = "dsh-ds-balance/client.css";
|
|
2183
2386
|
if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="' + __dsbTagId + '"]') === null) {
|
|
2184
2387
|
var __dsbTag = document.createElement('style');
|