dsh-ds-balance 2.1.0 → 2.1.2
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 +5 -1
- package/README_en.md +5 -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 +410 -196
- 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.js +13 -5
- package/lib/services/scheduler.js +6 -2
- package/lib/types/client/locales.d.ts +1 -0
- package/lib/types/client/settings/fields.d.ts +3 -3
- package/lib/types/client/sidebar/BalancePopover.d.ts +16 -3
- package/lib/types/client/sidebar/PercentRing.d.ts +1 -1
- package/lib/types/client/sidebar/SidebarBalance.d.ts +6 -4
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +10 -1
package/lib/client.js
CHANGED
|
@@ -56,7 +56,10 @@ var zh = {
|
|
|
56
56
|
"popover.cooldown": "{value} \u79D2\u540E\u53EF\u518D\u6B21\u5237\u65B0",
|
|
57
57
|
"popover.mismatch": "\u672A\u627E\u5230 {wanted} \u4F59\u989D\uFF0C\u5F53\u524D\u663E\u793A {shown}",
|
|
58
58
|
"popover.action.useShown": "\u6539\u7528 {shown}",
|
|
59
|
+
// 右上角图标的两档措辞。落点由**宿主能力**决定(跨插件深链服务在不在),
|
|
60
|
+
// 措辞就跟着落点分档:一句含糊的话盖不住两种落点。见 BalancePopover 的 PluginsAction。
|
|
59
61
|
"popover.action.openPlugins": "\u6253\u5F00\u63D2\u4EF6\u9875",
|
|
62
|
+
"popover.action.openPluginConfig": "\u6253\u5F00\u63D2\u4EF6\u914D\u7F6E\u9875",
|
|
60
63
|
"state.unavailable": "\u8D26\u6237\u4E0D\u53EF\u7528",
|
|
61
64
|
"state.stale": "\u6570\u636E\u5DF2\u8FC7\u671F",
|
|
62
65
|
"state.error": "\u8BFB\u53D6\u5931\u8D25",
|
|
@@ -137,6 +140,7 @@ var en = {
|
|
|
137
140
|
"popover.mismatch": "No {wanted} balance found; showing {shown}",
|
|
138
141
|
"popover.action.useShown": "Use {shown}",
|
|
139
142
|
"popover.action.openPlugins": "Open the Plugins page",
|
|
143
|
+
"popover.action.openPluginConfig": "Open the plugin configuration page",
|
|
140
144
|
"state.unavailable": "Account unavailable",
|
|
141
145
|
"state.stale": "Data is stale",
|
|
142
146
|
"state.error": "Failed to load",
|
|
@@ -194,7 +198,10 @@ var en = {
|
|
|
194
198
|
"dev.hint": "UI development only; does not affect real configuration."
|
|
195
199
|
};
|
|
196
200
|
function interpolate(template, params) {
|
|
197
|
-
return template.replace(
|
|
201
|
+
return template.replace(
|
|
202
|
+
/\{(\w+)\}/g,
|
|
203
|
+
(whole, name) => Object.prototype.hasOwnProperty.call(params, name) ? params[name] : whole
|
|
204
|
+
);
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
// src/client/settings/fields.tsx
|
|
@@ -226,7 +233,6 @@ var fields_default = {
|
|
|
226
233
|
groupNote: "fields_groupNote",
|
|
227
234
|
fields: "fields_fields",
|
|
228
235
|
details: "fields_details",
|
|
229
|
-
detailsSummary: "fields_detailsSummary",
|
|
230
236
|
detailsBody: "fields_detailsBody",
|
|
231
237
|
field: "fields_field",
|
|
232
238
|
row: "fields_row",
|
|
@@ -237,10 +243,10 @@ var fields_default = {
|
|
|
237
243
|
label: "fields_label",
|
|
238
244
|
badges: "fields_badges",
|
|
239
245
|
reset: "fields_reset",
|
|
240
|
-
input: "fields_input",
|
|
241
246
|
inputStatic: "fields_inputStatic",
|
|
242
247
|
inputInvalid: "fields_inputInvalid",
|
|
243
248
|
inputWithAction: "fields_inputWithAction",
|
|
249
|
+
input: "fields_input",
|
|
244
250
|
reveal: "fields_reveal",
|
|
245
251
|
revealOn: "fields_revealOn",
|
|
246
252
|
selectorAnchor: "fields_selectorAnchor",
|
|
@@ -250,7 +256,6 @@ var fields_default = {
|
|
|
250
256
|
pairNote: "fields_pairNote",
|
|
251
257
|
invalid: "fields_invalid",
|
|
252
258
|
actions: "fields_actions",
|
|
253
|
-
actionButton: "fields_actionButton",
|
|
254
259
|
resultOk: "fields_resultOk",
|
|
255
260
|
resultFail: "fields_resultFail"
|
|
256
261
|
};
|
|
@@ -318,10 +323,10 @@ function FieldFrame(props) {
|
|
|
318
323
|
}
|
|
319
324
|
function TextControl(props) {
|
|
320
325
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
321
|
-
|
|
326
|
+
import_dsh_client_ui_primitives.Input,
|
|
322
327
|
{
|
|
323
328
|
id: props.id,
|
|
324
|
-
className: props.invalid ? fields_default.inputInvalid :
|
|
329
|
+
className: props.invalid ? fields_default.inputInvalid : void 0,
|
|
325
330
|
type: "text",
|
|
326
331
|
...props.numeric ? { inputMode: "numeric" } : {},
|
|
327
332
|
...props.invalid ? { "aria-invalid": true } : {},
|
|
@@ -336,10 +341,10 @@ function TextControl(props) {
|
|
|
336
341
|
}
|
|
337
342
|
function ReadOnlyControl(props) {
|
|
338
343
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
339
|
-
|
|
344
|
+
import_dsh_client_ui_primitives.Input,
|
|
340
345
|
{
|
|
341
346
|
id: props.id,
|
|
342
|
-
className:
|
|
347
|
+
className: fields_default.inputStatic,
|
|
343
348
|
type: "text",
|
|
344
349
|
value: "",
|
|
345
350
|
readOnly: true
|
|
@@ -348,20 +353,20 @@ function ReadOnlyControl(props) {
|
|
|
348
353
|
}
|
|
349
354
|
function DetailsGroup(props) {
|
|
350
355
|
const [open, setOpen] = (0, import_react.useState)(props.defaultOpen === true);
|
|
351
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
352
|
-
|
|
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,
|
|
353
358
|
{
|
|
354
|
-
|
|
359
|
+
icon: null,
|
|
360
|
+
title: props.title,
|
|
355
361
|
open,
|
|
356
|
-
|
|
357
|
-
|
|
362
|
+
expandable: true,
|
|
363
|
+
expandOnRowClick: true,
|
|
364
|
+
onToggle: () => {
|
|
365
|
+
setOpen((value) => !value);
|
|
358
366
|
},
|
|
359
|
-
children:
|
|
360
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { className: fields_default.detailsSummary, children: props.title }),
|
|
361
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.detailsBody, children: props.children })
|
|
362
|
-
]
|
|
367
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.detailsBody, children: props.children })
|
|
363
368
|
}
|
|
364
|
-
);
|
|
369
|
+
) });
|
|
365
370
|
}
|
|
366
371
|
function SelectorControl(props) {
|
|
367
372
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
@@ -407,10 +412,10 @@ function SelectorControl(props) {
|
|
|
407
412
|
function ActionRow(props) {
|
|
408
413
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
409
414
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: fields_default.actions, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
410
|
-
|
|
415
|
+
import_dsh_client_ui_primitives.Button,
|
|
411
416
|
{
|
|
412
417
|
type: "button",
|
|
413
|
-
|
|
418
|
+
variant: "outline",
|
|
414
419
|
disabled: props.disabled,
|
|
415
420
|
onClick: props.onClick,
|
|
416
421
|
children: props.label
|
|
@@ -465,7 +470,13 @@ function selectField(field) {
|
|
|
465
470
|
var AUTO_CURRENCY = "auto";
|
|
466
471
|
var KNOWN_CURRENCIES = ["CNY", "USD"];
|
|
467
472
|
var THRESHOLD_PAIRS = [
|
|
468
|
-
{
|
|
473
|
+
{
|
|
474
|
+
currency: "CNY",
|
|
475
|
+
warn: "cnyWarn",
|
|
476
|
+
critical: "cnyCritical",
|
|
477
|
+
defaultWarn: 10,
|
|
478
|
+
defaultCritical: 5
|
|
479
|
+
},
|
|
469
480
|
{ currency: "USD", warn: "usdWarn", critical: "usdCritical", defaultWarn: 2, defaultCritical: 1 }
|
|
470
481
|
];
|
|
471
482
|
function pairNumber(state, fallback) {
|
|
@@ -508,8 +519,10 @@ var SPEC_BY_FIELD = new Map(
|
|
|
508
519
|
var TEST_LATENCY_MS = 800;
|
|
509
520
|
function probeFailure(baseUrl, apiKey, apiKeyRef) {
|
|
510
521
|
const url = baseUrl.trim();
|
|
511
|
-
if (url !== "" && !/^https?:\/\//i.test(url))
|
|
512
|
-
|
|
522
|
+
if (url !== "" && !/^https?:\/\//i.test(url))
|
|
523
|
+
return "base URL must start with http:// or https://";
|
|
524
|
+
if (apiKey.trim() === "" && apiKeyRef.trim() === "")
|
|
525
|
+
return "no API key or credential reference configured";
|
|
513
526
|
return null;
|
|
514
527
|
}
|
|
515
528
|
function isRecord(input) {
|
|
@@ -560,16 +573,72 @@ function fieldStateOf(snapshot, spec, edit) {
|
|
|
560
573
|
const effective = snapshot.value[spec.field];
|
|
561
574
|
const stored = Object.hasOwn(snapshot.user, spec.field);
|
|
562
575
|
if (edit === void 0) {
|
|
563
|
-
return isTextSpec(spec) ? {
|
|
576
|
+
return isTextSpec(spec) ? {
|
|
577
|
+
text: spec.format(effective),
|
|
578
|
+
value: void 0,
|
|
579
|
+
effective,
|
|
580
|
+
stored,
|
|
581
|
+
overridden: stored,
|
|
582
|
+
dirty: false,
|
|
583
|
+
invalid: false
|
|
584
|
+
} : {
|
|
585
|
+
text: "",
|
|
586
|
+
value: effective,
|
|
587
|
+
effective,
|
|
588
|
+
stored,
|
|
589
|
+
overridden: stored,
|
|
590
|
+
dirty: false,
|
|
591
|
+
invalid: false
|
|
592
|
+
};
|
|
564
593
|
}
|
|
565
594
|
if (edit.kind === "clear") {
|
|
566
|
-
return isTextSpec(spec) ? {
|
|
595
|
+
return isTextSpec(spec) ? {
|
|
596
|
+
text: "",
|
|
597
|
+
value: void 0,
|
|
598
|
+
effective,
|
|
599
|
+
stored,
|
|
600
|
+
overridden: false,
|
|
601
|
+
dirty: stored,
|
|
602
|
+
invalid: false
|
|
603
|
+
} : {
|
|
604
|
+
text: "",
|
|
605
|
+
value: effective,
|
|
606
|
+
effective,
|
|
607
|
+
stored,
|
|
608
|
+
overridden: false,
|
|
609
|
+
dirty: stored,
|
|
610
|
+
invalid: false
|
|
611
|
+
};
|
|
567
612
|
}
|
|
568
613
|
if (!isTextSpec(spec)) {
|
|
569
|
-
return edit.kind === "value" ? {
|
|
614
|
+
return edit.kind === "value" ? {
|
|
615
|
+
text: "",
|
|
616
|
+
value: edit.value,
|
|
617
|
+
effective,
|
|
618
|
+
stored,
|
|
619
|
+
overridden: true,
|
|
620
|
+
dirty: edit.value !== effective,
|
|
621
|
+
invalid: false
|
|
622
|
+
} : {
|
|
623
|
+
text: "",
|
|
624
|
+
value: effective,
|
|
625
|
+
effective,
|
|
626
|
+
stored,
|
|
627
|
+
overridden: stored,
|
|
628
|
+
dirty: false,
|
|
629
|
+
invalid: false
|
|
630
|
+
};
|
|
570
631
|
}
|
|
571
632
|
if (edit.kind !== "text") {
|
|
572
|
-
return {
|
|
633
|
+
return {
|
|
634
|
+
text: "",
|
|
635
|
+
value: void 0,
|
|
636
|
+
effective,
|
|
637
|
+
stored,
|
|
638
|
+
overridden: stored,
|
|
639
|
+
dirty: false,
|
|
640
|
+
invalid: false
|
|
641
|
+
};
|
|
573
642
|
}
|
|
574
643
|
const write = spec.parse(edit.text);
|
|
575
644
|
const dirty = write === void 0 ? true : write.kind === "clear" ? stored : edit.text !== spec.format(effective);
|
|
@@ -614,10 +683,7 @@ function useConfigForm(form) {
|
|
|
614
683
|
cacheRef.current = { value, user, writable, available, snapshot: snapshot2 };
|
|
615
684
|
return snapshot2;
|
|
616
685
|
}, [form]);
|
|
617
|
-
const subscribe = (0, import_react2.useCallback)(
|
|
618
|
-
(listener) => form.subscribe(listener),
|
|
619
|
-
[form]
|
|
620
|
-
);
|
|
686
|
+
const subscribe = (0, import_react2.useCallback)((listener) => form.subscribe(listener), [form]);
|
|
621
687
|
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, readSnapshot);
|
|
622
688
|
const [staged, setStaged] = (0, import_react2.useState)(() => /* @__PURE__ */ new Map());
|
|
623
689
|
const [saving, setSaving] = (0, import_react2.useState)(false);
|
|
@@ -627,18 +693,23 @@ function useConfigForm(form) {
|
|
|
627
693
|
const [test, setTest] = (0, import_react2.useState)({ running: false, ok: null, message: "" });
|
|
628
694
|
const testTimerRef = (0, import_react2.useRef)(null);
|
|
629
695
|
const testRunningRef = (0, import_react2.useRef)(false);
|
|
630
|
-
(0, import_react2.useEffect)(
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
696
|
+
(0, import_react2.useEffect)(
|
|
697
|
+
() => () => {
|
|
698
|
+
if (testTimerRef.current !== null) clearTimeout(testTimerRef.current);
|
|
699
|
+
testTimerRef.current = null;
|
|
700
|
+
testRunningRef.current = false;
|
|
701
|
+
},
|
|
702
|
+
[]
|
|
703
|
+
);
|
|
635
704
|
const plan = (0, import_react2.useMemo)(() => planWrites(snapshot, staged), [snapshot, staged]);
|
|
636
705
|
const pairsInvalid = (0, import_react2.useMemo)(
|
|
637
|
-
() => THRESHOLD_PAIRS.some(
|
|
638
|
-
pair
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
706
|
+
() => THRESHOLD_PAIRS.some(
|
|
707
|
+
(pair) => !thresholdsOk(
|
|
708
|
+
pair,
|
|
709
|
+
fieldOf(snapshot, pair.warn, staged.get(pair.warn)),
|
|
710
|
+
fieldOf(snapshot, pair.critical, staged.get(pair.critical))
|
|
711
|
+
)
|
|
712
|
+
),
|
|
642
713
|
[snapshot, staged]
|
|
643
714
|
);
|
|
644
715
|
const invalid = plan.some((item) => item.write === void 0) || pairsInvalid;
|
|
@@ -655,17 +726,28 @@ function useConfigForm(form) {
|
|
|
655
726
|
testTimerRef.current = null;
|
|
656
727
|
}
|
|
657
728
|
testRunningRef.current = false;
|
|
658
|
-
setTest(
|
|
729
|
+
setTest(
|
|
730
|
+
(current) => current.running || current.ok !== null ? { running: false, ok: null, message: "" } : current
|
|
731
|
+
);
|
|
659
732
|
}, []);
|
|
660
|
-
const edit = (0, import_react2.useCallback)(
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
stage
|
|
665
|
-
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
733
|
+
const edit = (0, import_react2.useCallback)(
|
|
734
|
+
(field2, text) => {
|
|
735
|
+
stage(field2, { kind: "text", text });
|
|
736
|
+
},
|
|
737
|
+
[stage]
|
|
738
|
+
);
|
|
739
|
+
const setValue = (0, import_react2.useCallback)(
|
|
740
|
+
(field2, value) => {
|
|
741
|
+
stage(field2, { kind: "value", value });
|
|
742
|
+
},
|
|
743
|
+
[stage]
|
|
744
|
+
);
|
|
745
|
+
const resetField = (0, import_react2.useCallback)(
|
|
746
|
+
(field2) => {
|
|
747
|
+
stage(field2, { kind: "clear" });
|
|
748
|
+
},
|
|
749
|
+
[stage]
|
|
750
|
+
);
|
|
669
751
|
const discard = (0, import_react2.useCallback)(() => {
|
|
670
752
|
setStaged((current) => current.size === 0 ? current : /* @__PURE__ */ new Map());
|
|
671
753
|
setFailed(false);
|
|
@@ -674,7 +756,9 @@ function useConfigForm(form) {
|
|
|
674
756
|
testTimerRef.current = null;
|
|
675
757
|
}
|
|
676
758
|
testRunningRef.current = false;
|
|
677
|
-
setTest(
|
|
759
|
+
setTest(
|
|
760
|
+
(current) => current.running || current.ok !== null ? { running: false, ok: null, message: "" } : current
|
|
761
|
+
);
|
|
678
762
|
}, []);
|
|
679
763
|
const save = (0, import_react2.useCallback)(async () => {
|
|
680
764
|
if (savingRef.current) return;
|
|
@@ -688,9 +772,11 @@ function useConfigForm(form) {
|
|
|
688
772
|
for (const item of writes) {
|
|
689
773
|
const write = item.write;
|
|
690
774
|
if (write === void 0) continue;
|
|
691
|
-
ops.push(
|
|
775
|
+
ops.push(
|
|
776
|
+
write.kind === "clear" ? { op: "unset", path: [item.field] } : { op: "set", path: [item.field], value: write.value }
|
|
777
|
+
);
|
|
692
778
|
}
|
|
693
|
-
let landed
|
|
779
|
+
let landed;
|
|
694
780
|
try {
|
|
695
781
|
landed = await form.mutate(ops, form.getSnapshot().revision);
|
|
696
782
|
} catch {
|
|
@@ -716,7 +802,9 @@ function useConfigForm(form) {
|
|
|
716
802
|
testTimerRef.current = setTimeout(() => {
|
|
717
803
|
testTimerRef.current = null;
|
|
718
804
|
testRunningRef.current = false;
|
|
719
|
-
setTest(
|
|
805
|
+
setTest(
|
|
806
|
+
failure === null ? { running: false, ok: true, message: "" } : { running: false, ok: false, message: failure }
|
|
807
|
+
);
|
|
720
808
|
}, TEST_LATENCY_MS);
|
|
721
809
|
}, [readSnapshot, staged]);
|
|
722
810
|
const field = (0, import_react2.useCallback)(
|
|
@@ -867,8 +955,7 @@ var BalanceSettingsCard_default = {
|
|
|
867
955
|
readOnly: "BalanceSettingsCard_readOnly",
|
|
868
956
|
footer: "BalanceSettingsCard_footer",
|
|
869
957
|
failed: "BalanceSettingsCard_failed",
|
|
870
|
-
notice: "BalanceSettingsCard_notice"
|
|
871
|
-
save: "BalanceSettingsCard_save"
|
|
958
|
+
notice: "BalanceSettingsCard_notice"
|
|
872
959
|
};
|
|
873
960
|
|
|
874
961
|
// src/client/settings/BalanceSettingsCard.tsx
|
|
@@ -918,7 +1005,8 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
918
1005
|
const toggleGroup = (key) => {
|
|
919
1006
|
setGroupOpen((current) => ({ ...current, [key]: !current[key] }));
|
|
920
1007
|
};
|
|
921
|
-
const groupOpenNow = (key) => groupOpen[key] || GROUP_FIELDS[key].some((name) => form.field(name).invalid) ||
|
|
1008
|
+
const groupOpenNow = (key) => groupOpen[key] || GROUP_FIELDS[key].some((name) => form.field(name).invalid) || // 成对校验不是字段级 invalid,得单独问一次:否则收起的阈值组会挡住「保存为什么是灰的」。
|
|
1009
|
+
key === "thresholds" && THRESHOLD_PAIRS.some((pair) => !form.thresholdPairOk(pair.currency));
|
|
922
1010
|
const { available, writable, dirty, invalid, saving, failed } = form.state;
|
|
923
1011
|
const disabled = !writable || saving;
|
|
924
1012
|
const credentialStatus = (name) => {
|
|
@@ -1075,7 +1163,10 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1075
1163
|
{
|
|
1076
1164
|
id: FIELD_IDS.apiKeyState ?? "apiKeyState",
|
|
1077
1165
|
label: t("settings.field.apiKey"),
|
|
1078
|
-
status: {
|
|
1166
|
+
status: {
|
|
1167
|
+
label: t(CREDENTIAL_BADGE[credentialView]),
|
|
1168
|
+
tone: credentialView === "notConfigured" ? "quiet" : "neutral"
|
|
1169
|
+
},
|
|
1079
1170
|
pending: false,
|
|
1080
1171
|
resettable: false,
|
|
1081
1172
|
pendingLabel: t("settings.unsaved"),
|
|
@@ -1085,12 +1176,7 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1085
1176
|
disabled: true,
|
|
1086
1177
|
onReset: () => {
|
|
1087
1178
|
},
|
|
1088
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1089
|
-
ReadOnlyControl,
|
|
1090
|
-
{
|
|
1091
|
-
id: FIELD_IDS.apiKeyState ?? "apiKeyState"
|
|
1092
|
-
}
|
|
1093
|
-
)
|
|
1179
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReadOnlyControl, { id: FIELD_IDS.apiKeyState ?? "apiKeyState" })
|
|
1094
1180
|
}
|
|
1095
1181
|
),
|
|
1096
1182
|
textRow("baseUrl", "settings.field.baseUrl", "settings.hint.baseUrl", false),
|
|
@@ -1149,19 +1235,31 @@ function BalanceSettingsCard({ t, form: scopedForm }) {
|
|
|
1149
1235
|
},
|
|
1150
1236
|
last: true,
|
|
1151
1237
|
children: [
|
|
1152
|
-
numberRow(
|
|
1153
|
-
|
|
1154
|
-
|
|
1238
|
+
numberRow(
|
|
1239
|
+
"serverRefreshSeconds",
|
|
1240
|
+
"settings.field.serverRefreshSeconds",
|
|
1241
|
+
"settings.hint.serverRefreshSeconds"
|
|
1242
|
+
),
|
|
1243
|
+
numberRow(
|
|
1244
|
+
"clientPollSeconds",
|
|
1245
|
+
"settings.field.clientPollSeconds",
|
|
1246
|
+
"settings.hint.clientPollSeconds"
|
|
1247
|
+
),
|
|
1248
|
+
numberRow(
|
|
1249
|
+
"manualRefreshCooldownSeconds",
|
|
1250
|
+
"settings.field.manualRefreshCooldownSeconds",
|
|
1251
|
+
"settings.hint.manualRefreshCooldownSeconds"
|
|
1252
|
+
)
|
|
1155
1253
|
]
|
|
1156
1254
|
}
|
|
1157
1255
|
),
|
|
1158
1256
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: BalanceSettingsCard_default.footer, children: [
|
|
1159
1257
|
footerNote === null ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: footerNote.className, role: "status", children: footerNote.text }),
|
|
1160
1258
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1161
|
-
|
|
1259
|
+
import_dsh_client_ui_primitives2.Button,
|
|
1162
1260
|
{
|
|
1163
1261
|
type: "button",
|
|
1164
|
-
|
|
1262
|
+
variant: "primary",
|
|
1165
1263
|
disabled: !dirty || invalid || saving || !writable,
|
|
1166
1264
|
onClick: () => {
|
|
1167
1265
|
void form.save();
|
|
@@ -1311,9 +1409,17 @@ var scenarios = {
|
|
|
1311
1409
|
/** 正常。 */
|
|
1312
1410
|
ok: make({}),
|
|
1313
1411
|
/** 余额偏低但可用。 */
|
|
1314
|
-
warn: make({
|
|
1412
|
+
warn: make({
|
|
1413
|
+
severity: "warn",
|
|
1414
|
+
balances: [cny("8.00000000", "0.00000000", "8.00000000")],
|
|
1415
|
+
selected: { currency: "CNY", total: "8.00000000" }
|
|
1416
|
+
}),
|
|
1315
1417
|
/** 余额告急。 */
|
|
1316
|
-
critical: make({
|
|
1418
|
+
critical: make({
|
|
1419
|
+
severity: "critical",
|
|
1420
|
+
balances: [cny("3.00000000", "0.00000000", "3.00000000")],
|
|
1421
|
+
selected: { currency: "CNY", total: "3.00000000" }
|
|
1422
|
+
}),
|
|
1317
1423
|
/** 账户不可用(余额耗尽 / 欠费)。 */
|
|
1318
1424
|
unavailable: make({
|
|
1319
1425
|
severity: "unavailable",
|
|
@@ -1322,7 +1428,14 @@ var scenarios = {
|
|
|
1322
1428
|
selected: { currency: "CNY", total: "0.00000000" }
|
|
1323
1429
|
}),
|
|
1324
1430
|
/** 有旧值但本次刷新失败。 */
|
|
1325
|
-
stale: make({
|
|
1431
|
+
stale: make({
|
|
1432
|
+
state: "stale",
|
|
1433
|
+
stale: true,
|
|
1434
|
+
severity: "unknown",
|
|
1435
|
+
ageMs: 36e5,
|
|
1436
|
+
fetchedAt: T0 - 36e5,
|
|
1437
|
+
error: { code: "NO_NETWORK", message: "fetch failed" }
|
|
1438
|
+
}),
|
|
1326
1439
|
/** 无值失败。 */
|
|
1327
1440
|
error: make({
|
|
1328
1441
|
state: "error",
|
|
@@ -1335,14 +1448,35 @@ var scenarios = {
|
|
|
1335
1448
|
error: { code: "UPSTREAM_5XX", message: "upstream returned 500" }
|
|
1336
1449
|
}),
|
|
1337
1450
|
/** 未配置。 */
|
|
1338
|
-
empty: make({
|
|
1451
|
+
empty: make({
|
|
1452
|
+
state: "empty",
|
|
1453
|
+
severity: "unknown",
|
|
1454
|
+
isAvailable: false,
|
|
1455
|
+
balances: [],
|
|
1456
|
+
selected: null,
|
|
1457
|
+
ageMs: 0
|
|
1458
|
+
}),
|
|
1339
1459
|
/** 未配置且带 NO_KEY 错误。 */
|
|
1340
|
-
noKey: make({
|
|
1460
|
+
noKey: make({
|
|
1461
|
+
state: "empty",
|
|
1462
|
+
severity: "unknown",
|
|
1463
|
+
isAvailable: false,
|
|
1464
|
+
balances: [],
|
|
1465
|
+
selected: null,
|
|
1466
|
+
ageMs: 0,
|
|
1467
|
+
error: { code: "NO_KEY", message: "no API key configured" }
|
|
1468
|
+
}),
|
|
1341
1469
|
/** 多币种。`selected` 显式写出,不靠 `make()` 的默认值兜。 */
|
|
1342
1470
|
multiCurrency: make({
|
|
1343
|
-
balances: [
|
|
1471
|
+
balances: [
|
|
1472
|
+
cny("110.00000000", "10.00000000", "100.00000000"),
|
|
1473
|
+
{ currency: "USD", total: "20.00000000", granted: "0.00000000", toppedUp: "20.00000000" }
|
|
1474
|
+
],
|
|
1344
1475
|
selected: { currency: "CNY", total: "110.00000000" },
|
|
1345
|
-
thresholds: {
|
|
1476
|
+
thresholds: {
|
|
1477
|
+
CNY: { warn: "10.00000000", critical: "5.00000000" },
|
|
1478
|
+
USD: { warn: "2.00000000", critical: "1.00000000" }
|
|
1479
|
+
}
|
|
1346
1480
|
}),
|
|
1347
1481
|
/**
|
|
1348
1482
|
* 选定了账户里没有的币种(USD),账户只有 CNY。
|
|
@@ -1544,7 +1678,7 @@ function BalancePopover(props) {
|
|
|
1544
1678
|
onRefresh,
|
|
1545
1679
|
onUseShown,
|
|
1546
1680
|
useShownDisabled,
|
|
1547
|
-
|
|
1681
|
+
pluginsAction
|
|
1548
1682
|
} = props;
|
|
1549
1683
|
const shown = selection.shown;
|
|
1550
1684
|
const totalText = shown === null ? BALANCE_PLACEHOLDER : formatMoney(shown.total, shown.currency);
|
|
@@ -1557,8 +1691,12 @@ function BalancePopover(props) {
|
|
|
1557
1691
|
const cooling = cooldownSeconds > 0;
|
|
1558
1692
|
let statusText = "";
|
|
1559
1693
|
if (refreshing) statusText = t("popover.refreshing");
|
|
1560
|
-
else if (cooling)
|
|
1694
|
+
else if (cooling)
|
|
1695
|
+
statusText = interpolate(t("popover.cooldown"), { value: String(cooldownSeconds) });
|
|
1561
1696
|
const refreshLabel = t("sidebar.aria.refresh");
|
|
1697
|
+
const pluginsLabel = t(
|
|
1698
|
+
pluginsAction?.reachesConfig === true ? "popover.action.openPluginConfig" : "popover.action.openPlugins"
|
|
1699
|
+
);
|
|
1562
1700
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1563
1701
|
"section",
|
|
1564
1702
|
{
|
|
@@ -1582,13 +1720,13 @@ function BalancePopover(props) {
|
|
|
1582
1720
|
]
|
|
1583
1721
|
}
|
|
1584
1722
|
),
|
|
1585
|
-
|
|
1723
|
+
pluginsAction === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tooltip, { label: pluginsLabel, side: "top", delayMs: 500, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1586
1724
|
"button",
|
|
1587
1725
|
{
|
|
1588
1726
|
type: "button",
|
|
1589
1727
|
className: BalancePopover_default.iconButton,
|
|
1590
|
-
"aria-label":
|
|
1591
|
-
onClick:
|
|
1728
|
+
"aria-label": pluginsLabel,
|
|
1729
|
+
onClick: pluginsAction.open,
|
|
1592
1730
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconPluginPinwheelOutlineRegular, { size: 16 })
|
|
1593
1731
|
}
|
|
1594
1732
|
) })
|
|
@@ -1604,7 +1742,16 @@ function BalancePopover(props) {
|
|
|
1604
1742
|
] }),
|
|
1605
1743
|
shown !== null && !selection.matchesPreference ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: BalancePopover_default.notice, children: [
|
|
1606
1744
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: BalancePopover_default.noticeText, children: interpolate(t("popover.mismatch"), { wanted: displayCurrency, shown: shown.currency }) }),
|
|
1607
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: BalancePopover_default.noticeActions, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: BalancePopover_default.noticeActions, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1746
|
+
import_dsh_client_ui_primitives3.Button,
|
|
1747
|
+
{
|
|
1748
|
+
size: "sm",
|
|
1749
|
+
variant: "outline",
|
|
1750
|
+
disabled: useShownDisabled === true,
|
|
1751
|
+
onClick: onUseShown,
|
|
1752
|
+
children: interpolate(t("popover.action.useShown"), { shown: shown.currency })
|
|
1753
|
+
}
|
|
1754
|
+
) })
|
|
1608
1755
|
] }) : null,
|
|
1609
1756
|
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 }) }),
|
|
1610
1757
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: BalancePopover_default.footer, children: [
|
|
@@ -1649,7 +1796,13 @@ var CROSS_ARM = (2 * RADIUS - STROKE) / 2 / Math.SQRT2;
|
|
|
1649
1796
|
function round3(value) {
|
|
1650
1797
|
return Math.round(value * 1e3) / 1e3;
|
|
1651
1798
|
}
|
|
1652
|
-
function PercentRing({
|
|
1799
|
+
function PercentRing({
|
|
1800
|
+
state,
|
|
1801
|
+
marker = null,
|
|
1802
|
+
ratio = 1,
|
|
1803
|
+
size = 18,
|
|
1804
|
+
title
|
|
1805
|
+
}) {
|
|
1653
1806
|
const clamped = Number.isFinite(ratio) ? Math.min(1, Math.max(0, ratio)) : 1;
|
|
1654
1807
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1655
1808
|
"svg",
|
|
@@ -1728,22 +1881,24 @@ function useConfigSlotState(probe) {
|
|
|
1728
1881
|
return state;
|
|
1729
1882
|
}
|
|
1730
1883
|
function usePluginsNavigation(navigation) {
|
|
1731
|
-
const [
|
|
1884
|
+
const [action, setAction] = (0, import_react5.useState)(() => navigation?.getSnapshot());
|
|
1732
1885
|
(0, import_react5.useEffect)(() => {
|
|
1733
1886
|
if (navigation === void 0) {
|
|
1734
|
-
|
|
1887
|
+
setAction(void 0);
|
|
1735
1888
|
return;
|
|
1736
1889
|
}
|
|
1737
|
-
|
|
1890
|
+
setAction(navigation.getSnapshot());
|
|
1738
1891
|
return navigation.subscribe(() => {
|
|
1739
|
-
|
|
1892
|
+
setAction(navigation.getSnapshot());
|
|
1740
1893
|
});
|
|
1741
1894
|
}, [navigation]);
|
|
1742
|
-
return
|
|
1895
|
+
return action;
|
|
1743
1896
|
}
|
|
1744
1897
|
function stateLabelKey(response, selection) {
|
|
1745
|
-
if (response.state === "error")
|
|
1746
|
-
|
|
1898
|
+
if (response.state === "error")
|
|
1899
|
+
return response.error?.code === "NO_KEY" ? "state.noKey" : "state.error";
|
|
1900
|
+
if (response.state === "empty")
|
|
1901
|
+
return response.error?.code === "NO_KEY" ? "state.noKey" : "state.empty";
|
|
1747
1902
|
if (response.state === "stale") return "state.stale";
|
|
1748
1903
|
if (!response.isAvailable) return "state.unavailable";
|
|
1749
1904
|
if (selection.shown === null) return "state.noBalance";
|
|
@@ -1788,16 +1943,19 @@ function SidebarBalance({
|
|
|
1788
1943
|
}, []);
|
|
1789
1944
|
const preference = config.displayCurrency;
|
|
1790
1945
|
const selection = (0, import_react5.useMemo)(() => selectionOf(response, preference), [response, preference]);
|
|
1791
|
-
(0, import_react5.useEffect)(
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1946
|
+
(0, import_react5.useEffect)(
|
|
1947
|
+
() => subscribeScenario((key) => {
|
|
1948
|
+
const active = resolveScenario() !== null;
|
|
1949
|
+
setMock(active);
|
|
1950
|
+
if (!active || lastScenario.current === key) return;
|
|
1951
|
+
lastScenario.current = key;
|
|
1952
|
+
acceptBalance(currentBalance());
|
|
1953
|
+
setRefreshing(false);
|
|
1954
|
+
setCooldownUntil(0);
|
|
1955
|
+
setOpen(false);
|
|
1956
|
+
}),
|
|
1957
|
+
[acceptBalance]
|
|
1958
|
+
);
|
|
1801
1959
|
(0, import_react5.useEffect)(() => {
|
|
1802
1960
|
if (mock) return;
|
|
1803
1961
|
let cancelled = false;
|
|
@@ -1813,17 +1971,30 @@ function SidebarBalance({
|
|
|
1813
1971
|
}
|
|
1814
1972
|
};
|
|
1815
1973
|
void load();
|
|
1816
|
-
const id = window.setInterval(
|
|
1817
|
-
|
|
1818
|
-
|
|
1974
|
+
const id = window.setInterval(
|
|
1975
|
+
() => {
|
|
1976
|
+
void load();
|
|
1977
|
+
},
|
|
1978
|
+
Math.max(5, config.clientPollSeconds) * MS_PER_SECOND
|
|
1979
|
+
);
|
|
1819
1980
|
return () => {
|
|
1820
1981
|
cancelled = true;
|
|
1821
1982
|
window.clearInterval(id);
|
|
1822
1983
|
};
|
|
1823
|
-
}, [
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1984
|
+
}, [
|
|
1985
|
+
mock,
|
|
1986
|
+
preference,
|
|
1987
|
+
config.clientPollSeconds,
|
|
1988
|
+
config.configSignature,
|
|
1989
|
+
acceptBalance,
|
|
1990
|
+
showUnreachable
|
|
1991
|
+
]);
|
|
1992
|
+
(0, import_react5.useEffect)(
|
|
1993
|
+
() => () => {
|
|
1994
|
+
if (refreshTimer.current !== void 0) window.clearTimeout(refreshTimer.current);
|
|
1995
|
+
},
|
|
1996
|
+
[]
|
|
1997
|
+
);
|
|
1827
1998
|
const closeNow = (0, import_react5.useCallback)(() => {
|
|
1828
1999
|
setOpen(false);
|
|
1829
2000
|
}, []);
|
|
@@ -1865,7 +2036,9 @@ function SidebarBalance({
|
|
|
1865
2036
|
setRefreshing(true);
|
|
1866
2037
|
const finish = () => {
|
|
1867
2038
|
setRefreshing(false);
|
|
1868
|
-
setCooldownUntil(
|
|
2039
|
+
setCooldownUntil(
|
|
2040
|
+
Date.now() + Math.max(0, config.manualRefreshCooldownSeconds) * MS_PER_SECOND
|
|
2041
|
+
);
|
|
1869
2042
|
};
|
|
1870
2043
|
if (mock) {
|
|
1871
2044
|
refreshTimer.current = window.setTimeout(() => {
|
|
@@ -1887,17 +2060,32 @@ function SidebarBalance({
|
|
|
1887
2060
|
finish();
|
|
1888
2061
|
}
|
|
1889
2062
|
})();
|
|
1890
|
-
}, [
|
|
2063
|
+
}, [
|
|
2064
|
+
cooldownUntil,
|
|
2065
|
+
config.manualRefreshCooldownSeconds,
|
|
2066
|
+
mock,
|
|
2067
|
+
preference,
|
|
2068
|
+
refreshing,
|
|
2069
|
+
acceptBalance,
|
|
2070
|
+
showUnreachable,
|
|
2071
|
+
markFresh
|
|
2072
|
+
]);
|
|
1891
2073
|
const handleUseShown = (0, import_react5.useCallback)(() => {
|
|
1892
2074
|
const current = selection.shown;
|
|
1893
2075
|
if (current === null) return;
|
|
1894
2076
|
void onSelectCurrency(current.currency);
|
|
1895
2077
|
}, [selection, onSelectCurrency]);
|
|
1896
|
-
const
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
2078
|
+
const pluginsAction = usePluginsNavigation(pluginsNavigation);
|
|
2079
|
+
const popoverPluginsAction = (0, import_react5.useMemo)(
|
|
2080
|
+
() => pluginsAction === void 0 ? void 0 : {
|
|
2081
|
+
reachesConfig: pluginsAction.reachesConfig,
|
|
2082
|
+
open: () => {
|
|
2083
|
+
closeNow();
|
|
2084
|
+
pluginsAction.open();
|
|
2085
|
+
}
|
|
2086
|
+
},
|
|
2087
|
+
[closeNow, pluginsAction]
|
|
2088
|
+
);
|
|
1901
2089
|
const configSlotState = useConfigSlotState(configSlotProbe);
|
|
1902
2090
|
const shown = selection.shown;
|
|
1903
2091
|
const ring = ringSpecFor(response.severity);
|
|
@@ -1938,42 +2126,42 @@ function SidebarBalance({
|
|
|
1938
2126
|
/* @__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 }) }),
|
|
1939
2127
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: SidebarBalance_default.label, children: t("sidebar.label") }),
|
|
1940
2128
|
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 }) }) })
|
|
1941
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
children: [
|
|
1952
|
-
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,
|
|
1953
|
-
open ? (0, import_react_dom.createPortal)(
|
|
1954
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1955
|
-
BalancePopover,
|
|
1956
|
-
{
|
|
1957
|
-
t,
|
|
1958
|
-
selection,
|
|
1959
|
-
displayCurrency: preference,
|
|
1960
|
-
ageMs,
|
|
1961
|
-
refreshing,
|
|
1962
|
-
cooldownSeconds,
|
|
1963
|
-
configSlotWarning: configSlotState === "missing" ? CONFIG_SLOT_WARNING : null,
|
|
1964
|
-
panelRef,
|
|
1965
|
-
style: pos ?? MEASURE_STYLE,
|
|
1966
|
-
onRefresh: handleRefresh,
|
|
1967
|
-
onUseShown: handleUseShown,
|
|
1968
|
-
useShownDisabled: !config.writable,
|
|
1969
|
-
onOpenPlugins: openPlugins === void 0 ? void 0 : handleOpenPlugins
|
|
1970
|
-
}
|
|
1971
|
-
),
|
|
1972
|
-
document.body
|
|
1973
|
-
) : null
|
|
1974
|
-
]
|
|
2129
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2130
|
+
PercentRing,
|
|
2131
|
+
{
|
|
2132
|
+
state: ring.state,
|
|
2133
|
+
marker: ring.marker,
|
|
2134
|
+
ratio: ringRatio,
|
|
2135
|
+
size: 18,
|
|
2136
|
+
title: ringTitle
|
|
2137
|
+
}
|
|
2138
|
+
)
|
|
1975
2139
|
}
|
|
1976
2140
|
);
|
|
2141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: rootRef, className: SidebarBalance_default.root, "data-mode": wide ? "wide" : "rail", tabIndex: -1, children: [
|
|
2142
|
+
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,
|
|
2143
|
+
open ? (0, import_react_dom.createPortal)(
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2145
|
+
BalancePopover,
|
|
2146
|
+
{
|
|
2147
|
+
t,
|
|
2148
|
+
selection,
|
|
2149
|
+
displayCurrency: preference,
|
|
2150
|
+
ageMs,
|
|
2151
|
+
refreshing,
|
|
2152
|
+
cooldownSeconds,
|
|
2153
|
+
configSlotWarning: configSlotState === "missing" ? CONFIG_SLOT_WARNING : null,
|
|
2154
|
+
panelRef,
|
|
2155
|
+
style: pos ?? MEASURE_STYLE,
|
|
2156
|
+
onRefresh: handleRefresh,
|
|
2157
|
+
onUseShown: handleUseShown,
|
|
2158
|
+
useShownDisabled: !config.writable,
|
|
2159
|
+
pluginsAction: popoverPluginsAction
|
|
2160
|
+
}
|
|
2161
|
+
),
|
|
2162
|
+
document.body
|
|
2163
|
+
) : null
|
|
2164
|
+
] });
|
|
1977
2165
|
}
|
|
1978
2166
|
|
|
1979
2167
|
// src/client/index.tsx
|
|
@@ -2063,25 +2251,59 @@ function SettingsSeatComponent(props) {
|
|
|
2063
2251
|
}
|
|
2064
2252
|
var PLUGINS_PANEL_ID = "plugins";
|
|
2065
2253
|
function createPluginsNavigation() {
|
|
2066
|
-
let
|
|
2254
|
+
let selectPanel;
|
|
2255
|
+
let openBundle;
|
|
2256
|
+
let snapshot;
|
|
2067
2257
|
const listeners2 = /* @__PURE__ */ new Set();
|
|
2068
|
-
const
|
|
2069
|
-
if (
|
|
2070
|
-
|
|
2258
|
+
const open = () => {
|
|
2259
|
+
if (openBundle !== void 0) {
|
|
2260
|
+
try {
|
|
2261
|
+
openBundle(BUNDLE_CONFIG_KEY);
|
|
2262
|
+
return;
|
|
2263
|
+
} catch (error) {
|
|
2264
|
+
console.warn("[WARN] ds-balance: cannot open the bundle config page", error);
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
try {
|
|
2268
|
+
selectPanel?.();
|
|
2269
|
+
} catch (error) {
|
|
2270
|
+
console.warn("[WARN] ds-balance: cannot switch to the plugins panel", error);
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
const publish = () => {
|
|
2274
|
+
const reachesConfig = openBundle !== void 0;
|
|
2275
|
+
const next = selectPanel === void 0 ? void 0 : { open, reachesConfig };
|
|
2276
|
+
const unchanged = next === void 0 ? snapshot === void 0 : snapshot !== void 0 && snapshot.reachesConfig === reachesConfig;
|
|
2277
|
+
if (unchanged) return;
|
|
2278
|
+
snapshot = next;
|
|
2071
2279
|
for (const listener of [...listeners2]) listener();
|
|
2072
2280
|
};
|
|
2073
2281
|
return {
|
|
2074
|
-
getSnapshot: () =>
|
|
2282
|
+
getSnapshot: () => snapshot,
|
|
2075
2283
|
subscribe: (listener) => {
|
|
2076
2284
|
listeners2.add(listener);
|
|
2077
2285
|
return () => {
|
|
2078
2286
|
listeners2.delete(listener);
|
|
2079
2287
|
};
|
|
2080
2288
|
},
|
|
2081
|
-
|
|
2082
|
-
|
|
2289
|
+
attachPanel: (callback) => {
|
|
2290
|
+
selectPanel = callback;
|
|
2291
|
+
publish();
|
|
2083
2292
|
return () => {
|
|
2084
|
-
if (
|
|
2293
|
+
if (selectPanel === callback) {
|
|
2294
|
+
selectPanel = void 0;
|
|
2295
|
+
publish();
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
},
|
|
2299
|
+
attachDeepLink: (callback) => {
|
|
2300
|
+
openBundle = callback;
|
|
2301
|
+
publish();
|
|
2302
|
+
return () => {
|
|
2303
|
+
if (openBundle === callback) {
|
|
2304
|
+
openBundle = void 0;
|
|
2305
|
+
publish();
|
|
2306
|
+
}
|
|
2085
2307
|
};
|
|
2086
2308
|
}
|
|
2087
2309
|
};
|
|
@@ -2091,21 +2313,16 @@ function apply(ctx) {
|
|
|
2091
2313
|
const configSlotProbe = createConfigSlotProbe();
|
|
2092
2314
|
ctx.effect(() => () => configSlotProbe.dispose(), "ds-balance: config slot probe");
|
|
2093
2315
|
const pluginsNavigation = createPluginsNavigation();
|
|
2094
|
-
let openBundlePanel;
|
|
2095
2316
|
ctx.inject(["pluginNavigation"], (navCtx) => {
|
|
2096
2317
|
const face = navCtx["pluginNavigation"];
|
|
2097
2318
|
if (typeof face !== "object" || face === null) return;
|
|
2098
2319
|
const candidate = face["openBundle"];
|
|
2099
2320
|
if (typeof candidate !== "function") return;
|
|
2100
2321
|
const openBundle = candidate.bind(face);
|
|
2101
|
-
navCtx.effect(
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
return () => {
|
|
2106
|
-
openBundlePanel = void 0;
|
|
2107
|
-
};
|
|
2108
|
-
}, "ds-balance: bundle config deep link");
|
|
2322
|
+
navCtx.effect(
|
|
2323
|
+
() => pluginsNavigation.attachDeepLink(openBundle),
|
|
2324
|
+
"ds-balance: bundle config deep link"
|
|
2325
|
+
);
|
|
2109
2326
|
});
|
|
2110
2327
|
ctx.inject(["layout"], (layoutCtx) => {
|
|
2111
2328
|
if (!("layout" in layoutCtx)) return;
|
|
@@ -2113,44 +2330,41 @@ function apply(ctx) {
|
|
|
2113
2330
|
if (typeof face !== "object" || face === null) return;
|
|
2114
2331
|
if (!("selectPanel" in face) || typeof face.selectPanel !== "function") return;
|
|
2115
2332
|
const selectPanel = face.selectPanel.bind(face);
|
|
2116
|
-
layoutCtx.effect(
|
|
2117
|
-
|
|
2118
|
-
try {
|
|
2119
|
-
openBundlePanel(BUNDLE_CONFIG_KEY);
|
|
2120
|
-
return;
|
|
2121
|
-
} catch (error) {
|
|
2122
|
-
console.warn("[WARN] ds-balance: cannot open the bundle config page", error);
|
|
2123
|
-
}
|
|
2124
|
-
}
|
|
2125
|
-
try {
|
|
2333
|
+
layoutCtx.effect(
|
|
2334
|
+
() => pluginsNavigation.attachPanel(() => {
|
|
2126
2335
|
selectPanel(PLUGINS_PANEL_ID);
|
|
2127
|
-
}
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
}), "ds-balance: plugins panel navigation");
|
|
2336
|
+
}),
|
|
2337
|
+
"ds-balance: plugins panel navigation"
|
|
2338
|
+
);
|
|
2131
2339
|
});
|
|
2132
2340
|
ctx.inject(["configForms"], (configCtx) => {
|
|
2133
2341
|
configSlotProbe.markDeclared();
|
|
2134
2342
|
const form = configCtx.configForms.get(ENTRY_ID);
|
|
2135
|
-
ctx.slots.inject(
|
|
2136
|
-
|
|
2137
|
-
(
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
{ name: "sidebar.footer.action", id: SIDEBAR_ENTRY_ID, order: 0, locale: NS },
|
|
2141
|
-
(seat) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2142
|
-
SidebarSeatComponent,
|
|
2143
|
-
{
|
|
2144
|
-
seat,
|
|
2145
|
-
form,
|
|
2146
|
-
configSlotProbe,
|
|
2147
|
-
pluginsNavigation
|
|
2148
|
-
}
|
|
2343
|
+
ctx.slots.inject(
|
|
2344
|
+
CONFIG_SLOT,
|
|
2345
|
+
() => ctx.slots.register(
|
|
2346
|
+
{ name: CONFIG_SLOT, key: BUNDLE_CONFIG_KEY, locale: NS },
|
|
2347
|
+
(seat) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SettingsSeatComponent, { seat, form })
|
|
2149
2348
|
)
|
|
2150
|
-
)
|
|
2349
|
+
);
|
|
2350
|
+
ctx.slots.inject(
|
|
2351
|
+
"sidebar.footer.action",
|
|
2352
|
+
() => ctx.slots.register(
|
|
2353
|
+
{ name: "sidebar.footer.action", id: SIDEBAR_ENTRY_ID, order: 0, locale: NS },
|
|
2354
|
+
(seat) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2355
|
+
SidebarSeatComponent,
|
|
2356
|
+
{
|
|
2357
|
+
seat,
|
|
2358
|
+
form,
|
|
2359
|
+
configSlotProbe,
|
|
2360
|
+
pluginsNavigation
|
|
2361
|
+
}
|
|
2362
|
+
)
|
|
2363
|
+
)
|
|
2364
|
+
);
|
|
2151
2365
|
});
|
|
2152
2366
|
}
|
|
2153
|
-
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";
|
|
2367
|
+
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";
|
|
2154
2368
|
var __dsbTagId = "dsh-ds-balance/client.css";
|
|
2155
2369
|
if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="' + __dsbTagId + '"]') === null) {
|
|
2156
2370
|
var __dsbTag = document.createElement('style');
|