dsh-cool-theme 0.3.1 → 0.5.0
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 +9 -10
- package/README.zh.md +9 -10
- package/lib/client.js +2694 -215
- package/lib/index.js +304 -6
- package/lib/types/client/components.d.ts +43 -3
- package/lib/types/client/components.d.ts.map +1 -1
- package/lib/types/client/custom.d.ts +124 -0
- package/lib/types/client/custom.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +102 -0
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/presets/aura.d.ts +26 -0
- package/lib/types/client/presets/aura.d.ts.map +1 -0
- package/lib/types/client/presets/catppuccin-frappe.d.ts +26 -0
- package/lib/types/client/presets/catppuccin-frappe.d.ts.map +1 -0
- package/lib/types/client/presets/catppuccin-macchiato.d.ts +26 -0
- package/lib/types/client/presets/catppuccin-macchiato.d.ts.map +1 -0
- package/lib/types/client/presets/cobalt2.d.ts +26 -0
- package/lib/types/client/presets/cobalt2.d.ts.map +1 -0
- package/lib/types/client/presets/cursor.d.ts +26 -0
- package/lib/types/client/presets/cursor.d.ts.map +1 -0
- package/lib/types/client/presets/everforest.d.ts +26 -0
- package/lib/types/client/presets/everforest.d.ts.map +1 -0
- package/lib/types/client/presets/flexoki.d.ts +26 -0
- package/lib/types/client/presets/flexoki.d.ts.map +1 -0
- package/lib/types/client/presets/kanagawa.d.ts +26 -0
- package/lib/types/client/presets/kanagawa.d.ts.map +1 -0
- package/lib/types/client/presets/lucent-orng.d.ts +26 -0
- package/lib/types/client/presets/lucent-orng.d.ts.map +1 -0
- package/lib/types/client/presets/material.d.ts +26 -0
- package/lib/types/client/presets/material.d.ts.map +1 -0
- package/lib/types/client/presets/matrix.d.ts +26 -0
- package/lib/types/client/presets/matrix.d.ts.map +1 -0
- package/lib/types/client/presets/mercury.d.ts +26 -0
- package/lib/types/client/presets/mercury.d.ts.map +1 -0
- package/lib/types/client/presets/nightowl.d.ts +26 -0
- package/lib/types/client/presets/nightowl.d.ts.map +1 -0
- package/lib/types/client/presets/opencode.d.ts +26 -0
- package/lib/types/client/presets/opencode.d.ts.map +1 -0
- package/lib/types/client/presets/orng.d.ts +26 -0
- package/lib/types/client/presets/orng.d.ts.map +1 -0
- package/lib/types/client/presets/osaka-jade.d.ts +26 -0
- package/lib/types/client/presets/osaka-jade.d.ts.map +1 -0
- package/lib/types/client/presets/palenight.d.ts +26 -0
- package/lib/types/client/presets/palenight.d.ts.map +1 -0
- package/lib/types/client/presets/synthwave84.d.ts +26 -0
- package/lib/types/client/presets/synthwave84.d.ts.map +1 -0
- package/lib/types/client/presets/system.d.ts +26 -0
- package/lib/types/client/presets/system.d.ts.map +1 -0
- package/lib/types/client/presets/vercel.d.ts +26 -0
- package/lib/types/client/presets/vercel.d.ts.map +1 -0
- package/lib/types/client/presets/vesper.d.ts +26 -0
- package/lib/types/client/presets/vesper.d.ts.map +1 -0
- package/lib/types/client/presets.d.ts +537 -0
- package/lib/types/client/presets.d.ts.map +1 -1
- package/lib/types/client/theme-files.d.ts +37 -0
- package/lib/types/client/theme-files.d.ts.map +1 -0
- package/lib/types/client/theme.d.ts.map +1 -1
- package/lib/types/client/tokens.d.ts +16 -3
- package/lib/types/client/tokens.d.ts.map +1 -1
- package/lib/types/contract.d.ts +43 -0
- package/lib/types/contract.d.ts.map +1 -1
- package/lib/types/host/index.d.ts +6 -3
- package/lib/types/host/index.d.ts.map +1 -1
- package/lib/types/host/theme-files.d.ts +38 -0
- package/lib/types/host/theme-files.d.ts.map +1 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -34,6 +34,12 @@ window.__ModuleLoader__.load({
|
|
|
34
34
|
*/
|
|
35
35
|
const THEME_STORAGE_KEY = "cool-theme-preset";
|
|
36
36
|
const THEME_STORAGE_KEY_LEGACY = "cooltea-theme-preset";
|
|
37
|
+
const CUSTOM_PRESET_ID = "custom";
|
|
38
|
+
const CUSTOM_THEME_STORAGE_KEY = "cool-theme-custom";
|
|
39
|
+
const CUSTOM_LIST_STORAGE_KEY = "cool-theme-custom-list";
|
|
40
|
+
const CUSTOM_ACTIVE_STORAGE_KEY = "cool-theme-custom-active";
|
|
41
|
+
const CUSTOM_MIGRATED_STORAGE_KEY = "cool-theme-custom-migrated";
|
|
42
|
+
const THEME_API_PATH_THEMES = `/cool-theme/api/themes`;
|
|
37
43
|
//#endregion
|
|
38
44
|
//#region src/client/presets/_helpers.ts
|
|
39
45
|
/**
|
|
@@ -295,17 +301,66 @@ window.__ModuleLoader__.load({
|
|
|
295
301
|
};
|
|
296
302
|
}
|
|
297
303
|
//#endregion
|
|
304
|
+
//#region src/client/presets/aura.ts
|
|
305
|
+
const bluish$33 = buildScale("--dsw-static-neutral-bluish", "#EDE9FE", "#15141B", BLUISH_STEPS);
|
|
306
|
+
const neutral$33 = buildScale("--dsw-static-neutral", "#EDE9FE", "#15141B", NEUTRAL_STEPS);
|
|
307
|
+
const lightSemantic$33 = buildSemanticScales({
|
|
308
|
+
deepseek: "#7C3AED",
|
|
309
|
+
blue: "#7C3AED",
|
|
310
|
+
green: "#059669",
|
|
311
|
+
amber: "#D97706",
|
|
312
|
+
red: "#E11D48"
|
|
313
|
+
});
|
|
314
|
+
const darkSemantic$33 = buildSemanticScales({
|
|
315
|
+
deepseek: "#A277FF",
|
|
316
|
+
blue: "#A277FF",
|
|
317
|
+
green: "#61FFCA",
|
|
318
|
+
amber: "#FFCA85",
|
|
319
|
+
red: "#FF6767"
|
|
320
|
+
});
|
|
321
|
+
const aura = {
|
|
322
|
+
label: "Aura",
|
|
323
|
+
light: {
|
|
324
|
+
...bluish$33,
|
|
325
|
+
...neutral$33,
|
|
326
|
+
...lightSemantic$33,
|
|
327
|
+
"--shiki-token-constant": "#7C3AED",
|
|
328
|
+
"--shiki-token-string": "#059669",
|
|
329
|
+
"--shiki-token-comment": "#6B7280",
|
|
330
|
+
"--shiki-token-keyword": "#C026D3",
|
|
331
|
+
"--shiki-token-parameter": "#B45309",
|
|
332
|
+
"--shiki-token-function": "#7C3AED",
|
|
333
|
+
"--shiki-token-string-expression": "#059669",
|
|
334
|
+
"--shiki-token-punctuation": "#4B5563",
|
|
335
|
+
"--shiki-token-link": "#7C3AED"
|
|
336
|
+
},
|
|
337
|
+
dark: {
|
|
338
|
+
...bluish$33,
|
|
339
|
+
...neutral$33,
|
|
340
|
+
...darkSemantic$33,
|
|
341
|
+
"--shiki-token-constant": "#FFCA85",
|
|
342
|
+
"--shiki-token-string": "#61FFCA",
|
|
343
|
+
"--shiki-token-comment": "#6C6F93",
|
|
344
|
+
"--shiki-token-keyword": "#FF61EF",
|
|
345
|
+
"--shiki-token-parameter": "#FFCA85",
|
|
346
|
+
"--shiki-token-function": "#A277FF",
|
|
347
|
+
"--shiki-token-string-expression": "#61FFCA",
|
|
348
|
+
"--shiki-token-punctuation": "#B4B7CF",
|
|
349
|
+
"--shiki-token-link": "#A277FF"
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
//#endregion
|
|
298
353
|
//#region src/client/presets/ayu.ts
|
|
299
|
-
const bluish$
|
|
300
|
-
const neutral$
|
|
301
|
-
const lightSemantic$
|
|
354
|
+
const bluish$32 = buildScale("--dsw-static-neutral-bluish", "#FAFAFA", "#0D1017", BLUISH_STEPS);
|
|
355
|
+
const neutral$32 = buildScale("--dsw-static-neutral", "#FAFAFA", "#0F1419", NEUTRAL_STEPS);
|
|
356
|
+
const lightSemantic$32 = buildSemanticScales({
|
|
302
357
|
deepseek: "#4AA8C8",
|
|
303
358
|
blue: "#4AA8C8",
|
|
304
359
|
green: "#5FB978",
|
|
305
360
|
amber: "#EA9F41",
|
|
306
361
|
red: "#E6656A"
|
|
307
362
|
});
|
|
308
|
-
const darkSemantic$
|
|
363
|
+
const darkSemantic$32 = buildSemanticScales({
|
|
309
364
|
deepseek: "#3FB7E3",
|
|
310
365
|
blue: "#3FB7E3",
|
|
311
366
|
green: "#78D05C",
|
|
@@ -315,9 +370,9 @@ window.__ModuleLoader__.load({
|
|
|
315
370
|
const ayu = {
|
|
316
371
|
label: "Ayu",
|
|
317
372
|
light: {
|
|
318
|
-
...bluish$
|
|
319
|
-
...neutral$
|
|
320
|
-
...lightSemantic$
|
|
373
|
+
...bluish$32,
|
|
374
|
+
...neutral$32,
|
|
375
|
+
...lightSemantic$32,
|
|
321
376
|
"--shiki-token-constant": "#A37ACC",
|
|
322
377
|
"--shiki-token-string": "#6F8F00",
|
|
323
378
|
"--shiki-token-comment": "#6E7681",
|
|
@@ -329,9 +384,9 @@ window.__ModuleLoader__.load({
|
|
|
329
384
|
"--shiki-token-link": "#2F86B7"
|
|
330
385
|
},
|
|
331
386
|
dark: {
|
|
332
|
-
...bluish$
|
|
333
|
-
...neutral$
|
|
334
|
-
...darkSemantic$
|
|
387
|
+
...bluish$32,
|
|
388
|
+
...neutral$32,
|
|
389
|
+
...darkSemantic$32,
|
|
335
390
|
"--shiki-token-constant": "#D2A6FF",
|
|
336
391
|
"--shiki-token-string": "#AAD94C",
|
|
337
392
|
"--shiki-token-comment": "#5A6673",
|
|
@@ -345,16 +400,16 @@ window.__ModuleLoader__.load({
|
|
|
345
400
|
};
|
|
346
401
|
//#endregion
|
|
347
402
|
//#region src/client/presets/catppuccin.ts
|
|
348
|
-
const bluish$
|
|
349
|
-
const neutral$
|
|
350
|
-
const lightSemantic$
|
|
403
|
+
const bluish$31 = buildScale("--dsw-static-neutral-bluish", "#eff1f5", "#1e1e2e", BLUISH_STEPS);
|
|
404
|
+
const neutral$31 = buildScale("--dsw-static-neutral", "#eff1f5", "#1e1e2e", NEUTRAL_STEPS);
|
|
405
|
+
const lightSemantic$31 = buildSemanticScales({
|
|
351
406
|
deepseek: "#7287FD",
|
|
352
407
|
blue: "#7287FD",
|
|
353
408
|
green: "#40A02B",
|
|
354
409
|
amber: "#DF8E1D",
|
|
355
410
|
red: "#D20F39"
|
|
356
411
|
});
|
|
357
|
-
const darkSemantic$
|
|
412
|
+
const darkSemantic$31 = buildSemanticScales({
|
|
358
413
|
deepseek: "#B4BEFE",
|
|
359
414
|
blue: "#B4BEFE",
|
|
360
415
|
green: "#A6D189",
|
|
@@ -364,9 +419,9 @@ window.__ModuleLoader__.load({
|
|
|
364
419
|
const catppuccin = {
|
|
365
420
|
label: "Catppuccin",
|
|
366
421
|
light: {
|
|
367
|
-
...bluish$
|
|
368
|
-
...neutral$
|
|
369
|
-
...lightSemantic$
|
|
422
|
+
...bluish$31,
|
|
423
|
+
...neutral$31,
|
|
424
|
+
...lightSemantic$31,
|
|
370
425
|
"--shiki-token-constant": "#CA6702",
|
|
371
426
|
"--shiki-token-string": "#40A02B",
|
|
372
427
|
"--shiki-token-comment": "#6C7086",
|
|
@@ -378,9 +433,9 @@ window.__ModuleLoader__.load({
|
|
|
378
433
|
"--shiki-token-link": "#04A5E5"
|
|
379
434
|
},
|
|
380
435
|
dark: {
|
|
381
|
-
...bluish$
|
|
382
|
-
...neutral$
|
|
383
|
-
...darkSemantic$
|
|
436
|
+
...bluish$31,
|
|
437
|
+
...neutral$31,
|
|
438
|
+
...darkSemantic$31,
|
|
384
439
|
"--shiki-token-constant": "#FAB387",
|
|
385
440
|
"--shiki-token-string": "#A6D189",
|
|
386
441
|
"--shiki-token-comment": "#6C7086",
|
|
@@ -393,17 +448,213 @@ window.__ModuleLoader__.load({
|
|
|
393
448
|
}
|
|
394
449
|
};
|
|
395
450
|
//#endregion
|
|
451
|
+
//#region src/client/presets/catppuccin-frappe.ts
|
|
452
|
+
const bluish$30 = buildScale("--dsw-static-neutral-bluish", "#EFF1F5", "#303446", BLUISH_STEPS);
|
|
453
|
+
const neutral$30 = buildScale("--dsw-static-neutral", "#EFF1F5", "#303446", NEUTRAL_STEPS);
|
|
454
|
+
const lightSemantic$30 = buildSemanticScales({
|
|
455
|
+
deepseek: "#7287FD",
|
|
456
|
+
blue: "#7287FD",
|
|
457
|
+
green: "#40A02B",
|
|
458
|
+
amber: "#DF8E1D",
|
|
459
|
+
red: "#D20F39"
|
|
460
|
+
});
|
|
461
|
+
const darkSemantic$30 = buildSemanticScales({
|
|
462
|
+
deepseek: "#BABBF1",
|
|
463
|
+
blue: "#BABBF1",
|
|
464
|
+
green: "#A6D189",
|
|
465
|
+
amber: "#EF9F76",
|
|
466
|
+
red: "#E78284"
|
|
467
|
+
});
|
|
468
|
+
const catppuccinFrappe = {
|
|
469
|
+
label: "Catppuccin Frappe",
|
|
470
|
+
light: {
|
|
471
|
+
...bluish$30,
|
|
472
|
+
...neutral$30,
|
|
473
|
+
...lightSemantic$30,
|
|
474
|
+
"--shiki-token-constant": "#CA6702",
|
|
475
|
+
"--shiki-token-string": "#40A02B",
|
|
476
|
+
"--shiki-token-comment": "#6C7086",
|
|
477
|
+
"--shiki-token-keyword": "#8839EF",
|
|
478
|
+
"--shiki-token-parameter": "#1E66F5",
|
|
479
|
+
"--shiki-token-function": "#7287FD",
|
|
480
|
+
"--shiki-token-string-expression": "#40A02B",
|
|
481
|
+
"--shiki-token-punctuation": "#5C5F77",
|
|
482
|
+
"--shiki-token-link": "#04A5E5"
|
|
483
|
+
},
|
|
484
|
+
dark: {
|
|
485
|
+
...bluish$30,
|
|
486
|
+
...neutral$30,
|
|
487
|
+
...darkSemantic$30,
|
|
488
|
+
"--shiki-token-constant": "#EF9F76",
|
|
489
|
+
"--shiki-token-string": "#A6D189",
|
|
490
|
+
"--shiki-token-comment": "#838BA7",
|
|
491
|
+
"--shiki-token-keyword": "#CA9EE6",
|
|
492
|
+
"--shiki-token-parameter": "#8CAAEE",
|
|
493
|
+
"--shiki-token-function": "#BABBF1",
|
|
494
|
+
"--shiki-token-string-expression": "#A6D189",
|
|
495
|
+
"--shiki-token-punctuation": "#C6D0F5",
|
|
496
|
+
"--shiki-token-link": "#99D1DB"
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
//#endregion
|
|
500
|
+
//#region src/client/presets/catppuccin-macchiato.ts
|
|
501
|
+
const bluish$29 = buildScale("--dsw-static-neutral-bluish", "#EFF1F5", "#24273A", BLUISH_STEPS);
|
|
502
|
+
const neutral$29 = buildScale("--dsw-static-neutral", "#EFF1F5", "#24273A", NEUTRAL_STEPS);
|
|
503
|
+
const lightSemantic$29 = buildSemanticScales({
|
|
504
|
+
deepseek: "#7287FD",
|
|
505
|
+
blue: "#7287FD",
|
|
506
|
+
green: "#40A02B",
|
|
507
|
+
amber: "#DF8E1D",
|
|
508
|
+
red: "#D20F39"
|
|
509
|
+
});
|
|
510
|
+
const darkSemantic$29 = buildSemanticScales({
|
|
511
|
+
deepseek: "#B7BDF8",
|
|
512
|
+
blue: "#B7BDF8",
|
|
513
|
+
green: "#A6DA95",
|
|
514
|
+
amber: "#F5A97F",
|
|
515
|
+
red: "#ED8796"
|
|
516
|
+
});
|
|
517
|
+
const catppuccinMacchiato = {
|
|
518
|
+
label: "Catppuccin Macchiato",
|
|
519
|
+
light: {
|
|
520
|
+
...bluish$29,
|
|
521
|
+
...neutral$29,
|
|
522
|
+
...lightSemantic$29,
|
|
523
|
+
"--shiki-token-constant": "#CA6702",
|
|
524
|
+
"--shiki-token-string": "#40A02B",
|
|
525
|
+
"--shiki-token-comment": "#6C7086",
|
|
526
|
+
"--shiki-token-keyword": "#8839EF",
|
|
527
|
+
"--shiki-token-parameter": "#1E66F5",
|
|
528
|
+
"--shiki-token-function": "#7287FD",
|
|
529
|
+
"--shiki-token-string-expression": "#40A02B",
|
|
530
|
+
"--shiki-token-punctuation": "#5C5F77",
|
|
531
|
+
"--shiki-token-link": "#04A5E5"
|
|
532
|
+
},
|
|
533
|
+
dark: {
|
|
534
|
+
...bluish$29,
|
|
535
|
+
...neutral$29,
|
|
536
|
+
...darkSemantic$29,
|
|
537
|
+
"--shiki-token-constant": "#F5A97F",
|
|
538
|
+
"--shiki-token-string": "#A6DA95",
|
|
539
|
+
"--shiki-token-comment": "#8087A2",
|
|
540
|
+
"--shiki-token-keyword": "#C6A0F6",
|
|
541
|
+
"--shiki-token-parameter": "#8AADF4",
|
|
542
|
+
"--shiki-token-function": "#B7BDF8",
|
|
543
|
+
"--shiki-token-string-expression": "#A6DA95",
|
|
544
|
+
"--shiki-token-punctuation": "#CAD3F5",
|
|
545
|
+
"--shiki-token-link": "#91D7E3"
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
//#endregion
|
|
549
|
+
//#region src/client/presets/cobalt2.ts
|
|
550
|
+
const bluish$28 = buildScale("--dsw-static-neutral-bluish", "#EAF2FF", "#193549", BLUISH_STEPS);
|
|
551
|
+
const neutral$28 = buildScale("--dsw-static-neutral", "#EAF2FF", "#193549", NEUTRAL_STEPS);
|
|
552
|
+
const lightSemantic$28 = buildSemanticScales({
|
|
553
|
+
deepseek: "#0054A6",
|
|
554
|
+
blue: "#0054A6",
|
|
555
|
+
green: "#0E7A4A",
|
|
556
|
+
amber: "#8A6A00",
|
|
557
|
+
red: "#D42A2A"
|
|
558
|
+
});
|
|
559
|
+
const darkSemantic$28 = buildSemanticScales({
|
|
560
|
+
deepseek: "#0088FF",
|
|
561
|
+
blue: "#0088FF",
|
|
562
|
+
green: "#3AD900",
|
|
563
|
+
amber: "#FFC600",
|
|
564
|
+
red: "#FF628C"
|
|
565
|
+
});
|
|
566
|
+
const cobalt2 = {
|
|
567
|
+
label: "Cobalt2",
|
|
568
|
+
light: {
|
|
569
|
+
...bluish$28,
|
|
570
|
+
...neutral$28,
|
|
571
|
+
...lightSemantic$28,
|
|
572
|
+
"--shiki-token-constant": "#0054A6",
|
|
573
|
+
"--shiki-token-string": "#0E7A4A",
|
|
574
|
+
"--shiki-token-comment": "#6B7C8D",
|
|
575
|
+
"--shiki-token-keyword": "#A31515",
|
|
576
|
+
"--shiki-token-parameter": "#8A6A00",
|
|
577
|
+
"--shiki-token-function": "#0054A6",
|
|
578
|
+
"--shiki-token-string-expression": "#0E7A4A",
|
|
579
|
+
"--shiki-token-punctuation": "#334454",
|
|
580
|
+
"--shiki-token-link": "#0054A6"
|
|
581
|
+
},
|
|
582
|
+
dark: {
|
|
583
|
+
...bluish$28,
|
|
584
|
+
...neutral$28,
|
|
585
|
+
...darkSemantic$28,
|
|
586
|
+
"--shiki-token-constant": "#FFC600",
|
|
587
|
+
"--shiki-token-string": "#3AD900",
|
|
588
|
+
"--shiki-token-comment": "#7C8B9E",
|
|
589
|
+
"--shiki-token-keyword": "#FF9D00",
|
|
590
|
+
"--shiki-token-parameter": "#FFC600",
|
|
591
|
+
"--shiki-token-function": "#0088FF",
|
|
592
|
+
"--shiki-token-string-expression": "#3AD900",
|
|
593
|
+
"--shiki-token-punctuation": "#E1EFFF",
|
|
594
|
+
"--shiki-token-link": "#0088FF"
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/client/presets/cursor.ts
|
|
599
|
+
const bluish$27 = buildScale("--dsw-static-neutral-bluish", "#F2F2F3", "#0E0E10", BLUISH_STEPS);
|
|
600
|
+
const neutral$27 = buildScale("--dsw-static-neutral", "#FAFAFA", "#0E0E10", NEUTRAL_STEPS);
|
|
601
|
+
const lightSemantic$27 = buildSemanticScales({
|
|
602
|
+
deepseek: "#4F46E5",
|
|
603
|
+
blue: "#4F46E5",
|
|
604
|
+
green: "#059669",
|
|
605
|
+
amber: "#D97706",
|
|
606
|
+
red: "#DC2626"
|
|
607
|
+
});
|
|
608
|
+
const darkSemantic$27 = buildSemanticScales({
|
|
609
|
+
deepseek: "#5E6AD2",
|
|
610
|
+
blue: "#5E6AD2",
|
|
611
|
+
green: "#0DBF6A",
|
|
612
|
+
amber: "#FF8A00",
|
|
613
|
+
red: "#FF6467"
|
|
614
|
+
});
|
|
615
|
+
const cursor = {
|
|
616
|
+
label: "Cursor",
|
|
617
|
+
light: {
|
|
618
|
+
...bluish$27,
|
|
619
|
+
...neutral$27,
|
|
620
|
+
...lightSemantic$27,
|
|
621
|
+
"--shiki-token-constant": "#4F46E5",
|
|
622
|
+
"--shiki-token-string": "#059669",
|
|
623
|
+
"--shiki-token-comment": "#6B7280",
|
|
624
|
+
"--shiki-token-keyword": "#7C3AED",
|
|
625
|
+
"--shiki-token-parameter": "#B45309",
|
|
626
|
+
"--shiki-token-function": "#4F46E5",
|
|
627
|
+
"--shiki-token-string-expression": "#059669",
|
|
628
|
+
"--shiki-token-punctuation": "#3F3F46",
|
|
629
|
+
"--shiki-token-link": "#4F46E5"
|
|
630
|
+
},
|
|
631
|
+
dark: {
|
|
632
|
+
...bluish$27,
|
|
633
|
+
...neutral$27,
|
|
634
|
+
...darkSemantic$27,
|
|
635
|
+
"--shiki-token-constant": "#5E6AD2",
|
|
636
|
+
"--shiki-token-string": "#0DBF6A",
|
|
637
|
+
"--shiki-token-comment": "#6B7280",
|
|
638
|
+
"--shiki-token-keyword": "#A78BFA",
|
|
639
|
+
"--shiki-token-parameter": "#FF8A00",
|
|
640
|
+
"--shiki-token-function": "#5E6AD2",
|
|
641
|
+
"--shiki-token-string-expression": "#0DBF6A",
|
|
642
|
+
"--shiki-token-punctuation": "#A1A1AA",
|
|
643
|
+
"--shiki-token-link": "#5E6AD2"
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
//#endregion
|
|
396
647
|
//#region src/client/presets/dracula.ts
|
|
397
|
-
const bluish$
|
|
398
|
-
const neutral$
|
|
399
|
-
const lightSemantic$
|
|
648
|
+
const bluish$26 = buildScale("--dsw-static-neutral-bluish", "#FAFAFA", "#282a36", BLUISH_STEPS);
|
|
649
|
+
const neutral$26 = buildScale("--dsw-static-neutral", "#FAFAFA", "#282a36", NEUTRAL_STEPS);
|
|
650
|
+
const lightSemantic$26 = buildSemanticScales({
|
|
400
651
|
deepseek: "#7C3AED",
|
|
401
652
|
blue: "#7C3AED",
|
|
402
653
|
green: "#2A9D4A",
|
|
403
654
|
amber: "#B78100",
|
|
404
655
|
red: "#E63C3C"
|
|
405
656
|
});
|
|
406
|
-
const darkSemantic$
|
|
657
|
+
const darkSemantic$26 = buildSemanticScales({
|
|
407
658
|
deepseek: "#BD93F9",
|
|
408
659
|
blue: "#BD93F9",
|
|
409
660
|
green: "#50FA7B",
|
|
@@ -413,9 +664,9 @@ window.__ModuleLoader__.load({
|
|
|
413
664
|
const dracula = {
|
|
414
665
|
label: "Dracula",
|
|
415
666
|
light: {
|
|
416
|
-
...bluish$
|
|
417
|
-
...neutral$
|
|
418
|
-
...lightSemantic$
|
|
667
|
+
...bluish$26,
|
|
668
|
+
...neutral$26,
|
|
669
|
+
...lightSemantic$26,
|
|
419
670
|
"--shiki-token-constant": "#6A3FB5",
|
|
420
671
|
"--shiki-token-string": "#1A7A3A",
|
|
421
672
|
"--shiki-token-comment": "#6D7A9E",
|
|
@@ -427,9 +678,9 @@ window.__ModuleLoader__.load({
|
|
|
427
678
|
"--shiki-token-link": "#7C3AED"
|
|
428
679
|
},
|
|
429
680
|
dark: {
|
|
430
|
-
...bluish$
|
|
431
|
-
...neutral$
|
|
432
|
-
...darkSemantic$
|
|
681
|
+
...bluish$26,
|
|
682
|
+
...neutral$26,
|
|
683
|
+
...darkSemantic$26,
|
|
433
684
|
"--shiki-token-constant": "#8BE9FD",
|
|
434
685
|
"--shiki-token-string": "#50FA7B",
|
|
435
686
|
"--shiki-token-comment": "#99A3C4",
|
|
@@ -443,16 +694,16 @@ window.__ModuleLoader__.load({
|
|
|
443
694
|
};
|
|
444
695
|
//#endregion
|
|
445
696
|
//#region src/client/presets/dsh.ts
|
|
446
|
-
const bluish$
|
|
447
|
-
const neutral$
|
|
448
|
-
const lightSemantic$
|
|
697
|
+
const bluish$25 = buildScale("--dsw-static-neutral-bluish", "#FFFFFF", "#0F1115", BLUISH_STEPS);
|
|
698
|
+
const neutral$25 = buildScale("--dsw-static-neutral", "#FFFFFF", "#000000", NEUTRAL_STEPS);
|
|
699
|
+
const lightSemantic$25 = buildSemanticScales({
|
|
449
700
|
deepseek: "#4176E6",
|
|
450
701
|
blue: "#3B82F6",
|
|
451
702
|
green: "#22C55E",
|
|
452
703
|
amber: "#F59E0B",
|
|
453
704
|
red: "#EF4444"
|
|
454
705
|
});
|
|
455
|
-
const darkSemantic$
|
|
706
|
+
const darkSemantic$25 = buildSemanticScales({
|
|
456
707
|
deepseek: "#4176E6",
|
|
457
708
|
blue: "#3B82F6",
|
|
458
709
|
green: "#22C55E",
|
|
@@ -462,28 +713,126 @@ window.__ModuleLoader__.load({
|
|
|
462
713
|
const dsh = {
|
|
463
714
|
label: "DSH",
|
|
464
715
|
light: {
|
|
465
|
-
...bluish$
|
|
466
|
-
...neutral$
|
|
467
|
-
...lightSemantic$
|
|
716
|
+
...bluish$25,
|
|
717
|
+
...neutral$25,
|
|
718
|
+
...lightSemantic$25
|
|
468
719
|
},
|
|
469
720
|
dark: {
|
|
470
|
-
...bluish$
|
|
471
|
-
...neutral$
|
|
472
|
-
...darkSemantic$
|
|
721
|
+
...bluish$25,
|
|
722
|
+
...neutral$25,
|
|
723
|
+
...darkSemantic$25
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
//#endregion
|
|
727
|
+
//#region src/client/presets/everforest.ts
|
|
728
|
+
const bluish$24 = buildScale("--dsw-static-neutral-bluish", "#FDF6E3", "#2D353B", BLUISH_STEPS);
|
|
729
|
+
const neutral$24 = buildScale("--dsw-static-neutral", "#FDF6E3", "#2D353B", NEUTRAL_STEPS);
|
|
730
|
+
const lightSemantic$24 = buildSemanticScales({
|
|
731
|
+
deepseek: "#42675A",
|
|
732
|
+
blue: "#42675A",
|
|
733
|
+
green: "#8DA101",
|
|
734
|
+
amber: "#DFA000",
|
|
735
|
+
red: "#F85552"
|
|
736
|
+
});
|
|
737
|
+
const darkSemantic$24 = buildSemanticScales({
|
|
738
|
+
deepseek: "#7FBBB3",
|
|
739
|
+
blue: "#7FBBB3",
|
|
740
|
+
green: "#A7C080",
|
|
741
|
+
amber: "#DBBC7F",
|
|
742
|
+
red: "#E67E80"
|
|
743
|
+
});
|
|
744
|
+
const everforest = {
|
|
745
|
+
label: "Everforest",
|
|
746
|
+
light: {
|
|
747
|
+
...bluish$24,
|
|
748
|
+
...neutral$24,
|
|
749
|
+
...lightSemantic$24,
|
|
750
|
+
"--shiki-token-constant": "#8DA101",
|
|
751
|
+
"--shiki-token-string": "#4D7D0F",
|
|
752
|
+
"--shiki-token-comment": "#8B9A7E",
|
|
753
|
+
"--shiki-token-keyword": "#DF69A0",
|
|
754
|
+
"--shiki-token-parameter": "#DFA000",
|
|
755
|
+
"--shiki-token-function": "#42675A",
|
|
756
|
+
"--shiki-token-string-expression": "#4D7D0F",
|
|
757
|
+
"--shiki-token-punctuation": "#5C6A72",
|
|
758
|
+
"--shiki-token-link": "#3A94C5"
|
|
759
|
+
},
|
|
760
|
+
dark: {
|
|
761
|
+
...bluish$24,
|
|
762
|
+
...neutral$24,
|
|
763
|
+
...darkSemantic$24,
|
|
764
|
+
"--shiki-token-constant": "#DBBC7F",
|
|
765
|
+
"--shiki-token-string": "#A7C080",
|
|
766
|
+
"--shiki-token-comment": "#859289",
|
|
767
|
+
"--shiki-token-keyword": "#D699B6",
|
|
768
|
+
"--shiki-token-parameter": "#E69875",
|
|
769
|
+
"--shiki-token-function": "#7FBBB3",
|
|
770
|
+
"--shiki-token-string-expression": "#A7C080",
|
|
771
|
+
"--shiki-token-punctuation": "#D3C6AA",
|
|
772
|
+
"--shiki-token-link": "#83C092"
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
//#endregion
|
|
776
|
+
//#region src/client/presets/flexoki.ts
|
|
777
|
+
const bluish$23 = buildScale("--dsw-static-neutral-bluish", "#FFFCF0", "#100F0F", BLUISH_STEPS);
|
|
778
|
+
const neutral$23 = buildScale("--dsw-static-neutral", "#FFFCF0", "#100F0F", NEUTRAL_STEPS);
|
|
779
|
+
const lightSemantic$23 = buildSemanticScales({
|
|
780
|
+
deepseek: "#205EA6",
|
|
781
|
+
blue: "#205EA6",
|
|
782
|
+
green: "#66800B",
|
|
783
|
+
amber: "#AD8301",
|
|
784
|
+
red: "#AF3029"
|
|
785
|
+
});
|
|
786
|
+
const darkSemantic$23 = buildSemanticScales({
|
|
787
|
+
deepseek: "#4385BE",
|
|
788
|
+
blue: "#4385BE",
|
|
789
|
+
green: "#879A39",
|
|
790
|
+
amber: "#D0A215",
|
|
791
|
+
red: "#D14D41"
|
|
792
|
+
});
|
|
793
|
+
const flexoki = {
|
|
794
|
+
label: "Flexoki",
|
|
795
|
+
light: {
|
|
796
|
+
...bluish$23,
|
|
797
|
+
...neutral$23,
|
|
798
|
+
...lightSemantic$23,
|
|
799
|
+
"--shiki-token-constant": "#BC5215",
|
|
800
|
+
"--shiki-token-string": "#66800B",
|
|
801
|
+
"--shiki-token-comment": "#6F6E69",
|
|
802
|
+
"--shiki-token-keyword": "#A02F6F",
|
|
803
|
+
"--shiki-token-parameter": "#AD8301",
|
|
804
|
+
"--shiki-token-function": "#205EA6",
|
|
805
|
+
"--shiki-token-string-expression": "#66800B",
|
|
806
|
+
"--shiki-token-punctuation": "#575653",
|
|
807
|
+
"--shiki-token-link": "#205EA6"
|
|
808
|
+
},
|
|
809
|
+
dark: {
|
|
810
|
+
...bluish$23,
|
|
811
|
+
...neutral$23,
|
|
812
|
+
...darkSemantic$23,
|
|
813
|
+
"--shiki-token-constant": "#DA702C",
|
|
814
|
+
"--shiki-token-string": "#879A39",
|
|
815
|
+
"--shiki-token-comment": "#6F6E69",
|
|
816
|
+
"--shiki-token-keyword": "#CE5D97",
|
|
817
|
+
"--shiki-token-parameter": "#D0A215",
|
|
818
|
+
"--shiki-token-function": "#4385BE",
|
|
819
|
+
"--shiki-token-string-expression": "#879A39",
|
|
820
|
+
"--shiki-token-punctuation": "#CECDC3",
|
|
821
|
+
"--shiki-token-link": "#4385BE"
|
|
473
822
|
}
|
|
474
823
|
};
|
|
475
824
|
//#endregion
|
|
476
825
|
//#region src/client/presets/github.ts
|
|
477
|
-
const bluish$
|
|
478
|
-
const neutral$
|
|
479
|
-
const lightSemantic$
|
|
826
|
+
const bluish$22 = buildScale("--dsw-static-neutral-bluish", "#ffffff", "#0d1117", BLUISH_STEPS);
|
|
827
|
+
const neutral$22 = buildScale("--dsw-static-neutral", "#ffffff", "#0d1117", NEUTRAL_STEPS);
|
|
828
|
+
const lightSemantic$22 = buildSemanticScales({
|
|
480
829
|
deepseek: "#0969da",
|
|
481
830
|
blue: "#0969da",
|
|
482
831
|
green: "#1A7F37",
|
|
483
832
|
amber: "#9A6700",
|
|
484
833
|
red: "#CF222E"
|
|
485
834
|
});
|
|
486
|
-
const darkSemantic$
|
|
835
|
+
const darkSemantic$22 = buildSemanticScales({
|
|
487
836
|
deepseek: "#58A6FF",
|
|
488
837
|
blue: "#58A6FF",
|
|
489
838
|
green: "#3FB950",
|
|
@@ -493,9 +842,9 @@ window.__ModuleLoader__.load({
|
|
|
493
842
|
const github = {
|
|
494
843
|
label: "GitHub",
|
|
495
844
|
light: {
|
|
496
|
-
...bluish$
|
|
497
|
-
...neutral$
|
|
498
|
-
...lightSemantic$
|
|
845
|
+
...bluish$22,
|
|
846
|
+
...neutral$22,
|
|
847
|
+
...lightSemantic$22,
|
|
499
848
|
"--shiki-token-constant": "#0550AE",
|
|
500
849
|
"--shiki-token-string": "#0A3069",
|
|
501
850
|
"--shiki-token-comment": "#6E7781",
|
|
@@ -507,9 +856,9 @@ window.__ModuleLoader__.load({
|
|
|
507
856
|
"--shiki-token-link": "#0969DA"
|
|
508
857
|
},
|
|
509
858
|
dark: {
|
|
510
|
-
...bluish$
|
|
511
|
-
...neutral$
|
|
512
|
-
...darkSemantic$
|
|
859
|
+
...bluish$22,
|
|
860
|
+
...neutral$22,
|
|
861
|
+
...darkSemantic$22,
|
|
513
862
|
"--shiki-token-constant": "#79C0FF",
|
|
514
863
|
"--shiki-token-string": "#A5D6FF",
|
|
515
864
|
"--shiki-token-comment": "#8B949E",
|
|
@@ -523,16 +872,16 @@ window.__ModuleLoader__.load({
|
|
|
523
872
|
};
|
|
524
873
|
//#endregion
|
|
525
874
|
//#region src/client/presets/gruvbox.ts
|
|
526
|
-
const bluish$
|
|
527
|
-
const neutral$
|
|
528
|
-
const lightSemantic$
|
|
875
|
+
const bluish$21 = buildScale("--dsw-static-neutral-bluish", "#fbf1c7", "#282828", BLUISH_STEPS);
|
|
876
|
+
const neutral$21 = buildScale("--dsw-static-neutral", "#fbf1c7", "#282828", NEUTRAL_STEPS);
|
|
877
|
+
const lightSemantic$21 = buildSemanticScales({
|
|
529
878
|
deepseek: "#076678",
|
|
530
879
|
blue: "#076678",
|
|
531
880
|
green: "#98971A",
|
|
532
881
|
amber: "#D79921",
|
|
533
882
|
red: "#CC241D"
|
|
534
883
|
});
|
|
535
|
-
const darkSemantic$
|
|
884
|
+
const darkSemantic$21 = buildSemanticScales({
|
|
536
885
|
deepseek: "#83A598",
|
|
537
886
|
blue: "#83A598",
|
|
538
887
|
green: "#B8BB26",
|
|
@@ -542,9 +891,9 @@ window.__ModuleLoader__.load({
|
|
|
542
891
|
const gruvbox = {
|
|
543
892
|
label: "Gruvbox",
|
|
544
893
|
light: {
|
|
545
|
-
...bluish$
|
|
546
|
-
...neutral$
|
|
547
|
-
...lightSemantic$
|
|
894
|
+
...bluish$21,
|
|
895
|
+
...neutral$21,
|
|
896
|
+
...lightSemantic$21,
|
|
548
897
|
"--shiki-token-constant": "#076678",
|
|
549
898
|
"--shiki-token-string": "#79740E",
|
|
550
899
|
"--shiki-token-comment": "#928374",
|
|
@@ -556,9 +905,9 @@ window.__ModuleLoader__.load({
|
|
|
556
905
|
"--shiki-token-link": "#076678"
|
|
557
906
|
},
|
|
558
907
|
dark: {
|
|
559
|
-
...bluish$
|
|
560
|
-
...neutral$
|
|
561
|
-
...darkSemantic$
|
|
908
|
+
...bluish$21,
|
|
909
|
+
...neutral$21,
|
|
910
|
+
...darkSemantic$21,
|
|
562
911
|
"--shiki-token-constant": "#83A598",
|
|
563
912
|
"--shiki-token-string": "#B8BB26",
|
|
564
913
|
"--shiki-token-comment": "#B1A69B",
|
|
@@ -571,17 +920,262 @@ window.__ModuleLoader__.load({
|
|
|
571
920
|
}
|
|
572
921
|
};
|
|
573
922
|
//#endregion
|
|
923
|
+
//#region src/client/presets/kanagawa.ts
|
|
924
|
+
const bluish$20 = buildScale("--dsw-static-neutral-bluish", "#F2ECBC", "#1F1F28", BLUISH_STEPS);
|
|
925
|
+
const neutral$20 = buildScale("--dsw-static-neutral", "#F2ECBC", "#1F1F28", NEUTRAL_STEPS);
|
|
926
|
+
const lightSemantic$20 = buildSemanticScales({
|
|
927
|
+
deepseek: "#2D4F67",
|
|
928
|
+
blue: "#2D4F67",
|
|
929
|
+
green: "#587353",
|
|
930
|
+
amber: "#8A6A2E",
|
|
931
|
+
red: "#9E3A3D"
|
|
932
|
+
});
|
|
933
|
+
const darkSemantic$20 = buildSemanticScales({
|
|
934
|
+
deepseek: "#7E9CD8",
|
|
935
|
+
blue: "#7E9CD8",
|
|
936
|
+
green: "#98BB6C",
|
|
937
|
+
amber: "#E6C384",
|
|
938
|
+
red: "#E46876"
|
|
939
|
+
});
|
|
940
|
+
const kanagawa = {
|
|
941
|
+
label: "Kanagawa",
|
|
942
|
+
light: {
|
|
943
|
+
...bluish$20,
|
|
944
|
+
...neutral$20,
|
|
945
|
+
...lightSemantic$20,
|
|
946
|
+
"--shiki-token-constant": "#5A6A8A",
|
|
947
|
+
"--shiki-token-string": "#587353",
|
|
948
|
+
"--shiki-token-comment": "#8A9A7B",
|
|
949
|
+
"--shiki-token-keyword": "#957FB8",
|
|
950
|
+
"--shiki-token-parameter": "#8A6A2E",
|
|
951
|
+
"--shiki-token-function": "#2D4F67",
|
|
952
|
+
"--shiki-token-string-expression": "#587353",
|
|
953
|
+
"--shiki-token-punctuation": "#43436C",
|
|
954
|
+
"--shiki-token-link": "#2D4F67"
|
|
955
|
+
},
|
|
956
|
+
dark: {
|
|
957
|
+
...bluish$20,
|
|
958
|
+
...neutral$20,
|
|
959
|
+
...darkSemantic$20,
|
|
960
|
+
"--shiki-token-constant": "#DCA561",
|
|
961
|
+
"--shiki-token-string": "#98BB6C",
|
|
962
|
+
"--shiki-token-comment": "#727169",
|
|
963
|
+
"--shiki-token-keyword": "#957FB8",
|
|
964
|
+
"--shiki-token-parameter": "#FFA066",
|
|
965
|
+
"--shiki-token-function": "#7E9CD8",
|
|
966
|
+
"--shiki-token-string-expression": "#98BB6C",
|
|
967
|
+
"--shiki-token-punctuation": "#DCD7BA",
|
|
968
|
+
"--shiki-token-link": "#7FB4CA"
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
//#endregion
|
|
972
|
+
//#region src/client/presets/lucent-orng.ts
|
|
973
|
+
const bluish$19 = buildScale("--dsw-static-neutral-bluish", "#FFF7ED", "#1C130E", BLUISH_STEPS);
|
|
974
|
+
const neutral$19 = buildScale("--dsw-static-neutral", "#FFF7ED", "#1C130E", NEUTRAL_STEPS);
|
|
975
|
+
const lightSemantic$19 = buildSemanticScales({
|
|
976
|
+
deepseek: "#9A3412",
|
|
977
|
+
blue: "#9A3412",
|
|
978
|
+
green: "#166534",
|
|
979
|
+
amber: "#EA580C",
|
|
980
|
+
red: "#DC2626"
|
|
981
|
+
});
|
|
982
|
+
const darkSemantic$19 = buildSemanticScales({
|
|
983
|
+
deepseek: "#FF8904",
|
|
984
|
+
blue: "#FF8904",
|
|
985
|
+
green: "#4ADE80",
|
|
986
|
+
amber: "#FB923C",
|
|
987
|
+
red: "#F87171"
|
|
988
|
+
});
|
|
989
|
+
const lucentOrng = {
|
|
990
|
+
label: "Lucent Orng",
|
|
991
|
+
light: {
|
|
992
|
+
...bluish$19,
|
|
993
|
+
...neutral$19,
|
|
994
|
+
...lightSemantic$19,
|
|
995
|
+
"--shiki-token-constant": "#9A3412",
|
|
996
|
+
"--shiki-token-string": "#166534",
|
|
997
|
+
"--shiki-token-comment": "#9A8B7A",
|
|
998
|
+
"--shiki-token-keyword": "#C2410C",
|
|
999
|
+
"--shiki-token-parameter": "#EA580C",
|
|
1000
|
+
"--shiki-token-function": "#9A3412",
|
|
1001
|
+
"--shiki-token-string-expression": "#166534",
|
|
1002
|
+
"--shiki-token-punctuation": "#57534E",
|
|
1003
|
+
"--shiki-token-link": "#9A3412"
|
|
1004
|
+
},
|
|
1005
|
+
dark: {
|
|
1006
|
+
...bluish$19,
|
|
1007
|
+
...neutral$19,
|
|
1008
|
+
...darkSemantic$19,
|
|
1009
|
+
"--shiki-token-constant": "#FB923C",
|
|
1010
|
+
"--shiki-token-string": "#4ADE80",
|
|
1011
|
+
"--shiki-token-comment": "#8C7A65",
|
|
1012
|
+
"--shiki-token-keyword": "#FF8904",
|
|
1013
|
+
"--shiki-token-parameter": "#FDBA74",
|
|
1014
|
+
"--shiki-token-function": "#FF8904",
|
|
1015
|
+
"--shiki-token-string-expression": "#4ADE80",
|
|
1016
|
+
"--shiki-token-punctuation": "#F5E6D3",
|
|
1017
|
+
"--shiki-token-link": "#FF8904"
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
//#endregion
|
|
1021
|
+
//#region src/client/presets/material.ts
|
|
1022
|
+
const bluish$18 = buildScale("--dsw-static-neutral-bluish", "#FAFAFA", "#0F111A", BLUISH_STEPS);
|
|
1023
|
+
const neutral$18 = buildScale("--dsw-static-neutral", "#FAFAFA", "#0F111A", NEUTRAL_STEPS);
|
|
1024
|
+
const lightSemantic$18 = buildSemanticScales({
|
|
1025
|
+
deepseek: "#1565C0",
|
|
1026
|
+
blue: "#1565C0",
|
|
1027
|
+
green: "#2E7D32",
|
|
1028
|
+
amber: "#EF6C00",
|
|
1029
|
+
red: "#C62828"
|
|
1030
|
+
});
|
|
1031
|
+
const darkSemantic$18 = buildSemanticScales({
|
|
1032
|
+
deepseek: "#82AAFF",
|
|
1033
|
+
blue: "#82AAFF",
|
|
1034
|
+
green: "#C3E88D",
|
|
1035
|
+
amber: "#FFCB6B",
|
|
1036
|
+
red: "#F07178"
|
|
1037
|
+
});
|
|
1038
|
+
const material = {
|
|
1039
|
+
label: "Material",
|
|
1040
|
+
light: {
|
|
1041
|
+
...bluish$18,
|
|
1042
|
+
...neutral$18,
|
|
1043
|
+
...lightSemantic$18,
|
|
1044
|
+
"--shiki-token-constant": "#1565C0",
|
|
1045
|
+
"--shiki-token-string": "#2E7D32",
|
|
1046
|
+
"--shiki-token-comment": "#6B7C8D",
|
|
1047
|
+
"--shiki-token-keyword": "#7C4DFF",
|
|
1048
|
+
"--shiki-token-parameter": "#EF6C00",
|
|
1049
|
+
"--shiki-token-function": "#1565C0",
|
|
1050
|
+
"--shiki-token-string-expression": "#2E7D32",
|
|
1051
|
+
"--shiki-token-punctuation": "#37474F",
|
|
1052
|
+
"--shiki-token-link": "#1565C0"
|
|
1053
|
+
},
|
|
1054
|
+
dark: {
|
|
1055
|
+
...bluish$18,
|
|
1056
|
+
...neutral$18,
|
|
1057
|
+
...darkSemantic$18,
|
|
1058
|
+
"--shiki-token-constant": "#FFCB6B",
|
|
1059
|
+
"--shiki-token-string": "#C3E88D",
|
|
1060
|
+
"--shiki-token-comment": "#676E95",
|
|
1061
|
+
"--shiki-token-keyword": "#C792EA",
|
|
1062
|
+
"--shiki-token-parameter": "#FFCB6B",
|
|
1063
|
+
"--shiki-token-function": "#82AAFF",
|
|
1064
|
+
"--shiki-token-string-expression": "#C3E88D",
|
|
1065
|
+
"--shiki-token-punctuation": "#EEFFFF",
|
|
1066
|
+
"--shiki-token-link": "#82AAFF"
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
//#endregion
|
|
1070
|
+
//#region src/client/presets/matrix.ts
|
|
1071
|
+
const bluish$17 = buildScale("--dsw-static-neutral-bluish", "#E8F5E9", "#0D1A0D", BLUISH_STEPS);
|
|
1072
|
+
const neutral$17 = buildScale("--dsw-static-neutral", "#E8F5E9", "#001100", NEUTRAL_STEPS);
|
|
1073
|
+
const lightSemantic$17 = buildSemanticScales({
|
|
1074
|
+
deepseek: "#0A5300",
|
|
1075
|
+
blue: "#0A5300",
|
|
1076
|
+
green: "#0A5300",
|
|
1077
|
+
amber: "#5A7A00",
|
|
1078
|
+
red: "#8A1A1A"
|
|
1079
|
+
});
|
|
1080
|
+
const darkSemantic$17 = buildSemanticScales({
|
|
1081
|
+
deepseek: "#00FF41",
|
|
1082
|
+
blue: "#00FF41",
|
|
1083
|
+
green: "#00FF41",
|
|
1084
|
+
amber: "#76FF03",
|
|
1085
|
+
red: "#FF3D57"
|
|
1086
|
+
});
|
|
1087
|
+
const matrix = {
|
|
1088
|
+
label: "Matrix",
|
|
1089
|
+
light: {
|
|
1090
|
+
...bluish$17,
|
|
1091
|
+
...neutral$17,
|
|
1092
|
+
...lightSemantic$17,
|
|
1093
|
+
"--shiki-token-constant": "#0A5300",
|
|
1094
|
+
"--shiki-token-string": "#0A7A00",
|
|
1095
|
+
"--shiki-token-comment": "#5A7A5A",
|
|
1096
|
+
"--shiki-token-keyword": "#0A5300",
|
|
1097
|
+
"--shiki-token-parameter": "#5A7A00",
|
|
1098
|
+
"--shiki-token-function": "#0A5300",
|
|
1099
|
+
"--shiki-token-string-expression": "#0A7A00",
|
|
1100
|
+
"--shiki-token-punctuation": "#2E3B2E",
|
|
1101
|
+
"--shiki-token-link": "#0A5300"
|
|
1102
|
+
},
|
|
1103
|
+
dark: {
|
|
1104
|
+
...bluish$17,
|
|
1105
|
+
...neutral$17,
|
|
1106
|
+
...darkSemantic$17,
|
|
1107
|
+
"--shiki-token-constant": "#76FF03",
|
|
1108
|
+
"--shiki-token-string": "#00E676",
|
|
1109
|
+
"--shiki-token-comment": "#4A7A4A",
|
|
1110
|
+
"--shiki-token-keyword": "#00FF41",
|
|
1111
|
+
"--shiki-token-parameter": "#76FF03",
|
|
1112
|
+
"--shiki-token-function": "#00FF41",
|
|
1113
|
+
"--shiki-token-string-expression": "#00E676",
|
|
1114
|
+
"--shiki-token-punctuation": "#CCFFCC",
|
|
1115
|
+
"--shiki-token-link": "#00FF41"
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
//#endregion
|
|
1119
|
+
//#region src/client/presets/mercury.ts
|
|
1120
|
+
const bluish$16 = buildScale("--dsw-static-neutral-bluish", "#F8FAFC", "#0F172A", BLUISH_STEPS);
|
|
1121
|
+
const neutral$16 = buildScale("--dsw-static-neutral", "#F8FAFC", "#0F172A", NEUTRAL_STEPS);
|
|
1122
|
+
const lightSemantic$16 = buildSemanticScales({
|
|
1123
|
+
deepseek: "#334155",
|
|
1124
|
+
blue: "#334155",
|
|
1125
|
+
green: "#047857",
|
|
1126
|
+
amber: "#B45309",
|
|
1127
|
+
red: "#BE123C"
|
|
1128
|
+
});
|
|
1129
|
+
const darkSemantic$16 = buildSemanticScales({
|
|
1130
|
+
deepseek: "#38BDF8",
|
|
1131
|
+
blue: "#38BDF8",
|
|
1132
|
+
green: "#34D399",
|
|
1133
|
+
amber: "#FBBF24",
|
|
1134
|
+
red: "#F43F5E"
|
|
1135
|
+
});
|
|
1136
|
+
const mercury = {
|
|
1137
|
+
label: "Mercury",
|
|
1138
|
+
light: {
|
|
1139
|
+
...bluish$16,
|
|
1140
|
+
...neutral$16,
|
|
1141
|
+
...lightSemantic$16,
|
|
1142
|
+
"--shiki-token-constant": "#334155",
|
|
1143
|
+
"--shiki-token-string": "#047857",
|
|
1144
|
+
"--shiki-token-comment": "#64748B",
|
|
1145
|
+
"--shiki-token-keyword": "#7C3AED",
|
|
1146
|
+
"--shiki-token-parameter": "#B45309",
|
|
1147
|
+
"--shiki-token-function": "#334155",
|
|
1148
|
+
"--shiki-token-string-expression": "#047857",
|
|
1149
|
+
"--shiki-token-punctuation": "#334155",
|
|
1150
|
+
"--shiki-token-link": "#0284C7"
|
|
1151
|
+
},
|
|
1152
|
+
dark: {
|
|
1153
|
+
...bluish$16,
|
|
1154
|
+
...neutral$16,
|
|
1155
|
+
...darkSemantic$16,
|
|
1156
|
+
"--shiki-token-constant": "#38BDF8",
|
|
1157
|
+
"--shiki-token-string": "#34D399",
|
|
1158
|
+
"--shiki-token-comment": "#64748B",
|
|
1159
|
+
"--shiki-token-keyword": "#A78BFA",
|
|
1160
|
+
"--shiki-token-parameter": "#FBBF24",
|
|
1161
|
+
"--shiki-token-function": "#38BDF8",
|
|
1162
|
+
"--shiki-token-string-expression": "#34D399",
|
|
1163
|
+
"--shiki-token-punctuation": "#E2E8F0",
|
|
1164
|
+
"--shiki-token-link": "#38BDF8"
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
//#endregion
|
|
574
1168
|
//#region src/client/presets/monokai.ts
|
|
575
|
-
const bluish$
|
|
576
|
-
const neutral$
|
|
577
|
-
const lightSemantic$
|
|
1169
|
+
const bluish$15 = buildScale("--dsw-static-neutral-bluish", "#fcfcfa", "#2d2a2e", BLUISH_STEPS);
|
|
1170
|
+
const neutral$15 = buildScale("--dsw-static-neutral", "#fcfcfa", "#2d2a2e", NEUTRAL_STEPS);
|
|
1171
|
+
const lightSemantic$15 = buildSemanticScales({
|
|
578
1172
|
deepseek: "#6B42A0",
|
|
579
1173
|
blue: "#6B42A0",
|
|
580
1174
|
green: "#5A8A2A",
|
|
581
1175
|
amber: "#B87A00",
|
|
582
1176
|
red: "#FF6188"
|
|
583
1177
|
});
|
|
584
|
-
const darkSemantic$
|
|
1178
|
+
const darkSemantic$15 = buildSemanticScales({
|
|
585
1179
|
deepseek: "#AB9DF2",
|
|
586
1180
|
blue: "#AB9DF2",
|
|
587
1181
|
green: "#A9DC76",
|
|
@@ -591,9 +1185,9 @@ window.__ModuleLoader__.load({
|
|
|
591
1185
|
const monokai = {
|
|
592
1186
|
label: "Monokai",
|
|
593
1187
|
light: {
|
|
594
|
-
...bluish$
|
|
595
|
-
...neutral$
|
|
596
|
-
...lightSemantic$
|
|
1188
|
+
...bluish$15,
|
|
1189
|
+
...neutral$15,
|
|
1190
|
+
...lightSemantic$15,
|
|
597
1191
|
"--shiki-token-constant": "#6B42A0",
|
|
598
1192
|
"--shiki-token-string": "#2A7A2A",
|
|
599
1193
|
"--shiki-token-comment": "#8A8A8A",
|
|
@@ -605,9 +1199,9 @@ window.__ModuleLoader__.load({
|
|
|
605
1199
|
"--shiki-token-link": "#6B42A0"
|
|
606
1200
|
},
|
|
607
1201
|
dark: {
|
|
608
|
-
...bluish$
|
|
609
|
-
...neutral$
|
|
610
|
-
...darkSemantic$
|
|
1202
|
+
...bluish$15,
|
|
1203
|
+
...neutral$15,
|
|
1204
|
+
...darkSemantic$15,
|
|
611
1205
|
"--shiki-token-constant": "#AB9DF2",
|
|
612
1206
|
"--shiki-token-string": "#A9DC76",
|
|
613
1207
|
"--shiki-token-comment": "#A9A8A7",
|
|
@@ -620,17 +1214,66 @@ window.__ModuleLoader__.load({
|
|
|
620
1214
|
}
|
|
621
1215
|
};
|
|
622
1216
|
//#endregion
|
|
1217
|
+
//#region src/client/presets/nightowl.ts
|
|
1218
|
+
const bluish$14 = buildScale("--dsw-static-neutral-bluish", "#F7F9FF", "#011627", BLUISH_STEPS);
|
|
1219
|
+
const neutral$14 = buildScale("--dsw-static-neutral", "#F7F9FF", "#011627", NEUTRAL_STEPS);
|
|
1220
|
+
const lightSemantic$14 = buildSemanticScales({
|
|
1221
|
+
deepseek: "#0B2948",
|
|
1222
|
+
blue: "#0B2948",
|
|
1223
|
+
green: "#0A7A5A",
|
|
1224
|
+
amber: "#8A6A00",
|
|
1225
|
+
red: "#B93D3D"
|
|
1226
|
+
});
|
|
1227
|
+
const darkSemantic$14 = buildSemanticScales({
|
|
1228
|
+
deepseek: "#82AAFF",
|
|
1229
|
+
blue: "#82AAFF",
|
|
1230
|
+
green: "#22DA6E",
|
|
1231
|
+
amber: "#FFEB95",
|
|
1232
|
+
red: "#EF5350"
|
|
1233
|
+
});
|
|
1234
|
+
const nightowl = {
|
|
1235
|
+
label: "Night Owl",
|
|
1236
|
+
light: {
|
|
1237
|
+
...bluish$14,
|
|
1238
|
+
...neutral$14,
|
|
1239
|
+
...lightSemantic$14,
|
|
1240
|
+
"--shiki-token-constant": "#0B2948",
|
|
1241
|
+
"--shiki-token-string": "#0A7A5A",
|
|
1242
|
+
"--shiki-token-comment": "#6B7B8D",
|
|
1243
|
+
"--shiki-token-keyword": "#7C3AED",
|
|
1244
|
+
"--shiki-token-parameter": "#8A6A00",
|
|
1245
|
+
"--shiki-token-function": "#0B2948",
|
|
1246
|
+
"--shiki-token-string-expression": "#0A7A5A",
|
|
1247
|
+
"--shiki-token-punctuation": "#2C3E50",
|
|
1248
|
+
"--shiki-token-link": "#0B2948"
|
|
1249
|
+
},
|
|
1250
|
+
dark: {
|
|
1251
|
+
...bluish$14,
|
|
1252
|
+
...neutral$14,
|
|
1253
|
+
...darkSemantic$14,
|
|
1254
|
+
"--shiki-token-constant": "#FFEB95",
|
|
1255
|
+
"--shiki-token-string": "#22DA6E",
|
|
1256
|
+
"--shiki-token-comment": "#637777",
|
|
1257
|
+
"--shiki-token-keyword": "#C792EA",
|
|
1258
|
+
"--shiki-token-parameter": "#F78C6C",
|
|
1259
|
+
"--shiki-token-function": "#82AAFF",
|
|
1260
|
+
"--shiki-token-string-expression": "#22DA6E",
|
|
1261
|
+
"--shiki-token-punctuation": "#D6DEEB",
|
|
1262
|
+
"--shiki-token-link": "#7FDBCA"
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
//#endregion
|
|
623
1266
|
//#region src/client/presets/nord.ts
|
|
624
|
-
const bluish$
|
|
625
|
-
const neutral$
|
|
626
|
-
const lightSemantic$
|
|
1267
|
+
const bluish$13 = buildScale("--dsw-static-neutral-bluish", "#D8DEE9", "#2E3440", BLUISH_STEPS);
|
|
1268
|
+
const neutral$13 = buildScale("--dsw-static-neutral", "#D8DEE9", "#2E3440", NEUTRAL_STEPS);
|
|
1269
|
+
const lightSemantic$13 = buildSemanticScales({
|
|
627
1270
|
deepseek: "#5E81AC",
|
|
628
1271
|
blue: "#5E81AC",
|
|
629
1272
|
green: "#A3BE8C",
|
|
630
1273
|
amber: "#EBCB8B",
|
|
631
1274
|
red: "#BF616A"
|
|
632
1275
|
});
|
|
633
|
-
const darkSemantic$
|
|
1276
|
+
const darkSemantic$13 = buildSemanticScales({
|
|
634
1277
|
deepseek: "#88C0D0",
|
|
635
1278
|
blue: "#88C0D0",
|
|
636
1279
|
green: "#C6D7B8",
|
|
@@ -640,9 +1283,9 @@ window.__ModuleLoader__.load({
|
|
|
640
1283
|
const nord = {
|
|
641
1284
|
label: "Nord",
|
|
642
1285
|
light: {
|
|
643
|
-
...bluish$
|
|
644
|
-
...neutral$
|
|
645
|
-
...lightSemantic$
|
|
1286
|
+
...bluish$13,
|
|
1287
|
+
...neutral$13,
|
|
1288
|
+
...lightSemantic$13,
|
|
646
1289
|
"--shiki-token-constant": "#2E6EA6",
|
|
647
1290
|
"--shiki-token-string": "#3D7A1F",
|
|
648
1291
|
"--shiki-token-comment": "#6C7A8E",
|
|
@@ -654,9 +1297,9 @@ window.__ModuleLoader__.load({
|
|
|
654
1297
|
"--shiki-token-link": "#5E81AC"
|
|
655
1298
|
},
|
|
656
1299
|
dark: {
|
|
657
|
-
...bluish$
|
|
658
|
-
...neutral$
|
|
659
|
-
...darkSemantic$
|
|
1300
|
+
...bluish$13,
|
|
1301
|
+
...neutral$13,
|
|
1302
|
+
...darkSemantic$13,
|
|
660
1303
|
"--shiki-token-constant": "#8BE9FD",
|
|
661
1304
|
"--shiki-token-string": "#A3BE8C",
|
|
662
1305
|
"--shiki-token-comment": "#99A3C4",
|
|
@@ -670,16 +1313,16 @@ window.__ModuleLoader__.load({
|
|
|
670
1313
|
};
|
|
671
1314
|
//#endregion
|
|
672
1315
|
//#region src/client/presets/onedark.ts
|
|
673
|
-
const bluish$
|
|
674
|
-
const neutral$
|
|
675
|
-
const lightSemantic$
|
|
1316
|
+
const bluish$12 = buildScale("--dsw-static-neutral-bluish", "#FAFAFA", "#383A42", BLUISH_STEPS);
|
|
1317
|
+
const neutral$12 = buildScale("--dsw-static-neutral", "#FAFAFA", "#383A42", NEUTRAL_STEPS);
|
|
1318
|
+
const lightSemantic$12 = buildSemanticScales({
|
|
676
1319
|
deepseek: "#4078F2",
|
|
677
1320
|
blue: "#4078F2",
|
|
678
1321
|
green: "#50A14F",
|
|
679
1322
|
amber: "#C18401",
|
|
680
1323
|
red: "#E45649"
|
|
681
1324
|
});
|
|
682
|
-
const darkSemantic$
|
|
1325
|
+
const darkSemantic$12 = buildSemanticScales({
|
|
683
1326
|
deepseek: "#61AFEF",
|
|
684
1327
|
blue: "#61AFEF",
|
|
685
1328
|
green: "#98C379",
|
|
@@ -689,9 +1332,9 @@ window.__ModuleLoader__.load({
|
|
|
689
1332
|
const onedark = {
|
|
690
1333
|
label: "One Dark",
|
|
691
1334
|
light: {
|
|
692
|
-
...bluish$
|
|
693
|
-
...neutral$
|
|
694
|
-
...lightSemantic$
|
|
1335
|
+
...bluish$12,
|
|
1336
|
+
...neutral$12,
|
|
1337
|
+
...lightSemantic$12,
|
|
695
1338
|
"--shiki-token-constant": "#0B7EA4",
|
|
696
1339
|
"--shiki-token-string": "#1F7A3A",
|
|
697
1340
|
"--shiki-token-comment": "#76808F",
|
|
@@ -703,9 +1346,9 @@ window.__ModuleLoader__.load({
|
|
|
703
1346
|
"--shiki-token-link": "#4078F2"
|
|
704
1347
|
},
|
|
705
1348
|
dark: {
|
|
706
|
-
...bluish$
|
|
707
|
-
...neutral$
|
|
708
|
-
...darkSemantic$
|
|
1349
|
+
...bluish$12,
|
|
1350
|
+
...neutral$12,
|
|
1351
|
+
...darkSemantic$12,
|
|
709
1352
|
"--shiki-token-constant": "#56B6C2",
|
|
710
1353
|
"--shiki-token-string": "#98C379",
|
|
711
1354
|
"--shiki-token-comment": "#A0A6B0",
|
|
@@ -718,43 +1361,239 @@ window.__ModuleLoader__.load({
|
|
|
718
1361
|
}
|
|
719
1362
|
};
|
|
720
1363
|
//#endregion
|
|
721
|
-
//#region src/client/presets/
|
|
722
|
-
const bluish$
|
|
723
|
-
const neutral$
|
|
724
|
-
const lightSemantic$
|
|
725
|
-
deepseek: "#
|
|
726
|
-
blue: "#
|
|
727
|
-
green: "#
|
|
728
|
-
amber: "#
|
|
729
|
-
red: "#
|
|
1364
|
+
//#region src/client/presets/opencode.ts
|
|
1365
|
+
const bluish$11 = buildScale("--dsw-static-neutral-bluish", "#F5F5F5", "#0A0A0A", BLUISH_STEPS);
|
|
1366
|
+
const neutral$11 = buildScale("--dsw-static-neutral", "#F5F5F5", "#0A0A0A", NEUTRAL_STEPS);
|
|
1367
|
+
const lightSemantic$11 = buildSemanticScales({
|
|
1368
|
+
deepseek: "#4F46E5",
|
|
1369
|
+
blue: "#4F46E5",
|
|
1370
|
+
green: "#059669",
|
|
1371
|
+
amber: "#D97706",
|
|
1372
|
+
red: "#DC2626"
|
|
730
1373
|
});
|
|
731
|
-
const darkSemantic$
|
|
732
|
-
deepseek: "#
|
|
733
|
-
blue: "#
|
|
734
|
-
green: "#
|
|
735
|
-
amber: "#
|
|
736
|
-
red: "#
|
|
1374
|
+
const darkSemantic$11 = buildSemanticScales({
|
|
1375
|
+
deepseek: "#5E6AD2",
|
|
1376
|
+
blue: "#5E6AD2",
|
|
1377
|
+
green: "#0DBF6A",
|
|
1378
|
+
amber: "#FF8A00",
|
|
1379
|
+
red: "#FF6467"
|
|
737
1380
|
});
|
|
738
|
-
const
|
|
739
|
-
label: "
|
|
1381
|
+
const opencode = {
|
|
1382
|
+
label: "OpenCode",
|
|
740
1383
|
light: {
|
|
741
|
-
...bluish$
|
|
742
|
-
...neutral$
|
|
743
|
-
...lightSemantic$
|
|
744
|
-
"--shiki-token-constant": "#
|
|
745
|
-
"--shiki-token-string": "#
|
|
746
|
-
"--shiki-token-comment": "#
|
|
747
|
-
"--shiki-token-keyword": "#
|
|
748
|
-
"--shiki-token-parameter": "#
|
|
749
|
-
"--shiki-token-function": "#
|
|
750
|
-
"--shiki-token-string-expression": "#
|
|
751
|
-
"--shiki-token-punctuation": "#
|
|
752
|
-
"--shiki-token-link": "#
|
|
1384
|
+
...bluish$11,
|
|
1385
|
+
...neutral$11,
|
|
1386
|
+
...lightSemantic$11,
|
|
1387
|
+
"--shiki-token-constant": "#4F46E5",
|
|
1388
|
+
"--shiki-token-string": "#059669",
|
|
1389
|
+
"--shiki-token-comment": "#6B7280",
|
|
1390
|
+
"--shiki-token-keyword": "#7C3AED",
|
|
1391
|
+
"--shiki-token-parameter": "#B45309",
|
|
1392
|
+
"--shiki-token-function": "#4F46E5",
|
|
1393
|
+
"--shiki-token-string-expression": "#059669",
|
|
1394
|
+
"--shiki-token-punctuation": "#27272A",
|
|
1395
|
+
"--shiki-token-link": "#4F46E5"
|
|
753
1396
|
},
|
|
754
1397
|
dark: {
|
|
755
|
-
...bluish$
|
|
756
|
-
...neutral$
|
|
757
|
-
...darkSemantic$
|
|
1398
|
+
...bluish$11,
|
|
1399
|
+
...neutral$11,
|
|
1400
|
+
...darkSemantic$11,
|
|
1401
|
+
"--shiki-token-constant": "#5E6AD2",
|
|
1402
|
+
"--shiki-token-string": "#0DBF6A",
|
|
1403
|
+
"--shiki-token-comment": "#6B7280",
|
|
1404
|
+
"--shiki-token-keyword": "#A78BFA",
|
|
1405
|
+
"--shiki-token-parameter": "#FF8A00",
|
|
1406
|
+
"--shiki-token-function": "#5E6AD2",
|
|
1407
|
+
"--shiki-token-string-expression": "#0DBF6A",
|
|
1408
|
+
"--shiki-token-punctuation": "#A1A1AA",
|
|
1409
|
+
"--shiki-token-link": "#5E6AD2"
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
//#endregion
|
|
1413
|
+
//#region src/client/presets/orng.ts
|
|
1414
|
+
const bluish$10 = buildScale("--dsw-static-neutral-bluish", "#FFF4E6", "#1A0F00", BLUISH_STEPS);
|
|
1415
|
+
const neutral$10 = buildScale("--dsw-static-neutral", "#FFF4E6", "#1A0F00", NEUTRAL_STEPS);
|
|
1416
|
+
const lightSemantic$10 = buildSemanticScales({
|
|
1417
|
+
deepseek: "#9A3412",
|
|
1418
|
+
blue: "#9A3412",
|
|
1419
|
+
green: "#166534",
|
|
1420
|
+
amber: "#EA580C",
|
|
1421
|
+
red: "#DC2626"
|
|
1422
|
+
});
|
|
1423
|
+
const darkSemantic$10 = buildSemanticScales({
|
|
1424
|
+
deepseek: "#FF6B00",
|
|
1425
|
+
blue: "#FF6B00",
|
|
1426
|
+
green: "#22C55E",
|
|
1427
|
+
amber: "#FF8A00",
|
|
1428
|
+
red: "#F43F5E"
|
|
1429
|
+
});
|
|
1430
|
+
const orng = {
|
|
1431
|
+
label: "Orng",
|
|
1432
|
+
light: {
|
|
1433
|
+
...bluish$10,
|
|
1434
|
+
...neutral$10,
|
|
1435
|
+
...lightSemantic$10,
|
|
1436
|
+
"--shiki-token-constant": "#9A3412",
|
|
1437
|
+
"--shiki-token-string": "#166534",
|
|
1438
|
+
"--shiki-token-comment": "#9A8B7A",
|
|
1439
|
+
"--shiki-token-keyword": "#C2410C",
|
|
1440
|
+
"--shiki-token-parameter": "#EA580C",
|
|
1441
|
+
"--shiki-token-function": "#9A3412",
|
|
1442
|
+
"--shiki-token-string-expression": "#166534",
|
|
1443
|
+
"--shiki-token-punctuation": "#451A03",
|
|
1444
|
+
"--shiki-token-link": "#9A3412"
|
|
1445
|
+
},
|
|
1446
|
+
dark: {
|
|
1447
|
+
...bluish$10,
|
|
1448
|
+
...neutral$10,
|
|
1449
|
+
...darkSemantic$10,
|
|
1450
|
+
"--shiki-token-constant": "#FF8A00",
|
|
1451
|
+
"--shiki-token-string": "#22C55E",
|
|
1452
|
+
"--shiki-token-comment": "#8C6A4A",
|
|
1453
|
+
"--shiki-token-keyword": "#FF6B00",
|
|
1454
|
+
"--shiki-token-parameter": "#FDBA74",
|
|
1455
|
+
"--shiki-token-function": "#FF6B00",
|
|
1456
|
+
"--shiki-token-string-expression": "#22C55E",
|
|
1457
|
+
"--shiki-token-punctuation": "#FFEFD6",
|
|
1458
|
+
"--shiki-token-link": "#FF6B00"
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
//#endregion
|
|
1462
|
+
//#region src/client/presets/osaka-jade.ts
|
|
1463
|
+
const bluish$9 = buildScale("--dsw-static-neutral-bluish", "#F0FAF5", "#0F2A1F", BLUISH_STEPS);
|
|
1464
|
+
const neutral$9 = buildScale("--dsw-static-neutral", "#F0FAF5", "#0F2A1F", NEUTRAL_STEPS);
|
|
1465
|
+
const lightSemantic$9 = buildSemanticScales({
|
|
1466
|
+
deepseek: "#0F6F5C",
|
|
1467
|
+
blue: "#0F6F5C",
|
|
1468
|
+
green: "#0F6F5C",
|
|
1469
|
+
amber: "#8A6A00",
|
|
1470
|
+
red: "#9F1239"
|
|
1471
|
+
});
|
|
1472
|
+
const darkSemantic$9 = buildSemanticScales({
|
|
1473
|
+
deepseek: "#00A86B",
|
|
1474
|
+
blue: "#00A86B",
|
|
1475
|
+
green: "#00A86B",
|
|
1476
|
+
amber: "#E6C384",
|
|
1477
|
+
red: "#E46876"
|
|
1478
|
+
});
|
|
1479
|
+
const osakaJade = {
|
|
1480
|
+
label: "Osaka Jade",
|
|
1481
|
+
light: {
|
|
1482
|
+
...bluish$9,
|
|
1483
|
+
...neutral$9,
|
|
1484
|
+
...lightSemantic$9,
|
|
1485
|
+
"--shiki-token-constant": "#0F6F5C",
|
|
1486
|
+
"--shiki-token-string": "#0B7A3E",
|
|
1487
|
+
"--shiki-token-comment": "#6B8A7A",
|
|
1488
|
+
"--shiki-token-keyword": "#0F6F5C",
|
|
1489
|
+
"--shiki-token-parameter": "#8A6A00",
|
|
1490
|
+
"--shiki-token-function": "#0F6F5C",
|
|
1491
|
+
"--shiki-token-string-expression": "#0B7A3E",
|
|
1492
|
+
"--shiki-token-punctuation": "#1A3A2A",
|
|
1493
|
+
"--shiki-token-link": "#0F6F5C"
|
|
1494
|
+
},
|
|
1495
|
+
dark: {
|
|
1496
|
+
...bluish$9,
|
|
1497
|
+
...neutral$9,
|
|
1498
|
+
...darkSemantic$9,
|
|
1499
|
+
"--shiki-token-constant": "#6A9589",
|
|
1500
|
+
"--shiki-token-string": "#98BB6C",
|
|
1501
|
+
"--shiki-token-comment": "#6B8A7A",
|
|
1502
|
+
"--shiki-token-keyword": "#00A86B",
|
|
1503
|
+
"--shiki-token-parameter": "#E6C384",
|
|
1504
|
+
"--shiki-token-function": "#00A86B",
|
|
1505
|
+
"--shiki-token-string-expression": "#98BB6C",
|
|
1506
|
+
"--shiki-token-punctuation": "#D0E8D8",
|
|
1507
|
+
"--shiki-token-link": "#7FB4CA"
|
|
1508
|
+
}
|
|
1509
|
+
};
|
|
1510
|
+
//#endregion
|
|
1511
|
+
//#region src/client/presets/palenight.ts
|
|
1512
|
+
const bluish$8 = buildScale("--dsw-static-neutral-bluish", "#FAFAFA", "#292D3E", BLUISH_STEPS);
|
|
1513
|
+
const neutral$8 = buildScale("--dsw-static-neutral", "#FAFAFA", "#292D3E", NEUTRAL_STEPS);
|
|
1514
|
+
const lightSemantic$8 = buildSemanticScales({
|
|
1515
|
+
deepseek: "#3A4A6B",
|
|
1516
|
+
blue: "#3A4A6B",
|
|
1517
|
+
green: "#2E7D32",
|
|
1518
|
+
amber: "#B47A00",
|
|
1519
|
+
red: "#C62828"
|
|
1520
|
+
});
|
|
1521
|
+
const darkSemantic$8 = buildSemanticScales({
|
|
1522
|
+
deepseek: "#82AAFF",
|
|
1523
|
+
blue: "#82AAFF",
|
|
1524
|
+
green: "#C3E88D",
|
|
1525
|
+
amber: "#FFCB6B",
|
|
1526
|
+
red: "#F07178"
|
|
1527
|
+
});
|
|
1528
|
+
const palenight = {
|
|
1529
|
+
label: "Palenight",
|
|
1530
|
+
light: {
|
|
1531
|
+
...bluish$8,
|
|
1532
|
+
...neutral$8,
|
|
1533
|
+
...lightSemantic$8,
|
|
1534
|
+
"--shiki-token-constant": "#3A4A6B",
|
|
1535
|
+
"--shiki-token-string": "#2E7D32",
|
|
1536
|
+
"--shiki-token-comment": "#6B7C8D",
|
|
1537
|
+
"--shiki-token-keyword": "#7C4DFF",
|
|
1538
|
+
"--shiki-token-parameter": "#B47A00",
|
|
1539
|
+
"--shiki-token-function": "#3A4A6B",
|
|
1540
|
+
"--shiki-token-string-expression": "#2E7D32",
|
|
1541
|
+
"--shiki-token-punctuation": "#3C435E",
|
|
1542
|
+
"--shiki-token-link": "#3A4A6B"
|
|
1543
|
+
},
|
|
1544
|
+
dark: {
|
|
1545
|
+
...bluish$8,
|
|
1546
|
+
...neutral$8,
|
|
1547
|
+
...darkSemantic$8,
|
|
1548
|
+
"--shiki-token-constant": "#FFCB6B",
|
|
1549
|
+
"--shiki-token-string": "#C3E88D",
|
|
1550
|
+
"--shiki-token-comment": "#676E95",
|
|
1551
|
+
"--shiki-token-keyword": "#C792EA",
|
|
1552
|
+
"--shiki-token-parameter": "#FFCB6B",
|
|
1553
|
+
"--shiki-token-function": "#82AAFF",
|
|
1554
|
+
"--shiki-token-string-expression": "#C3E88D",
|
|
1555
|
+
"--shiki-token-punctuation": "#A6ACCD",
|
|
1556
|
+
"--shiki-token-link": "#82AAFF"
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
//#endregion
|
|
1560
|
+
//#region src/client/presets/rosepine.ts
|
|
1561
|
+
const bluish$7 = buildScale("--dsw-static-neutral-bluish", "#faf4ed", "#191724", BLUISH_STEPS);
|
|
1562
|
+
const neutral$7 = buildScale("--dsw-static-neutral", "#faf4ed", "#191724", NEUTRAL_STEPS);
|
|
1563
|
+
const lightSemantic$7 = buildSemanticScales({
|
|
1564
|
+
deepseek: "#907AA9",
|
|
1565
|
+
blue: "#907AA9",
|
|
1566
|
+
green: "#286983",
|
|
1567
|
+
amber: "#EA9D34",
|
|
1568
|
+
red: "#B4637A"
|
|
1569
|
+
});
|
|
1570
|
+
const darkSemantic$7 = buildSemanticScales({
|
|
1571
|
+
deepseek: "#C4A7E7",
|
|
1572
|
+
blue: "#C4A7E7",
|
|
1573
|
+
green: "#9CCFD8",
|
|
1574
|
+
amber: "#F6C177",
|
|
1575
|
+
red: "#EB6F92"
|
|
1576
|
+
});
|
|
1577
|
+
const rosepine = {
|
|
1578
|
+
label: "Rosé Pine",
|
|
1579
|
+
light: {
|
|
1580
|
+
...bluish$7,
|
|
1581
|
+
...neutral$7,
|
|
1582
|
+
...lightSemantic$7,
|
|
1583
|
+
"--shiki-token-constant": "#56949F",
|
|
1584
|
+
"--shiki-token-string": "#286983",
|
|
1585
|
+
"--shiki-token-comment": "#9893A5",
|
|
1586
|
+
"--shiki-token-keyword": "#907AA9",
|
|
1587
|
+
"--shiki-token-parameter": "#B4637A",
|
|
1588
|
+
"--shiki-token-function": "#907AA9",
|
|
1589
|
+
"--shiki-token-string-expression": "#286983",
|
|
1590
|
+
"--shiki-token-punctuation": "#575279",
|
|
1591
|
+
"--shiki-token-link": "#907AA9"
|
|
1592
|
+
},
|
|
1593
|
+
dark: {
|
|
1594
|
+
...bluish$7,
|
|
1595
|
+
...neutral$7,
|
|
1596
|
+
...darkSemantic$7,
|
|
758
1597
|
"--shiki-token-constant": "#9CCFD8",
|
|
759
1598
|
"--shiki-token-string": "#EBBCBA",
|
|
760
1599
|
"--shiki-token-comment": "#A19EB0",
|
|
@@ -768,16 +1607,16 @@ window.__ModuleLoader__.load({
|
|
|
768
1607
|
};
|
|
769
1608
|
//#endregion
|
|
770
1609
|
//#region src/client/presets/solarized.ts
|
|
771
|
-
const bluish$
|
|
772
|
-
const neutral$
|
|
773
|
-
const lightSemantic$
|
|
1610
|
+
const bluish$6 = buildScale("--dsw-static-neutral-bluish", "#fdf6e3", "#002b36", BLUISH_STEPS);
|
|
1611
|
+
const neutral$6 = buildScale("--dsw-static-neutral", "#fdf6e3", "#002b36", NEUTRAL_STEPS);
|
|
1612
|
+
const lightSemantic$6 = buildSemanticScales({
|
|
774
1613
|
deepseek: "#268BD2",
|
|
775
1614
|
blue: "#268BD2",
|
|
776
1615
|
green: "#859900",
|
|
777
1616
|
amber: "#B58900",
|
|
778
1617
|
red: "#DC322F"
|
|
779
1618
|
});
|
|
780
|
-
const darkSemantic$
|
|
1619
|
+
const darkSemantic$6 = buildSemanticScales({
|
|
781
1620
|
deepseek: "#78B7E3",
|
|
782
1621
|
blue: "#78B7E3",
|
|
783
1622
|
green: "#B3C061",
|
|
@@ -787,9 +1626,9 @@ window.__ModuleLoader__.load({
|
|
|
787
1626
|
const solarized = {
|
|
788
1627
|
label: "Solarized",
|
|
789
1628
|
light: {
|
|
790
|
-
...bluish$
|
|
791
|
-
...neutral$
|
|
792
|
-
...lightSemantic$
|
|
1629
|
+
...bluish$6,
|
|
1630
|
+
...neutral$6,
|
|
1631
|
+
...lightSemantic$6,
|
|
793
1632
|
"--shiki-token-constant": "#2AA198",
|
|
794
1633
|
"--shiki-token-string": "#586E75",
|
|
795
1634
|
"--shiki-token-comment": "#93A1A1",
|
|
@@ -801,9 +1640,9 @@ window.__ModuleLoader__.load({
|
|
|
801
1640
|
"--shiki-token-link": "#268BD2"
|
|
802
1641
|
},
|
|
803
1642
|
dark: {
|
|
804
|
-
...bluish$
|
|
805
|
-
...neutral$
|
|
806
|
-
...darkSemantic$
|
|
1643
|
+
...bluish$6,
|
|
1644
|
+
...neutral$6,
|
|
1645
|
+
...darkSemantic$6,
|
|
807
1646
|
"--shiki-token-constant": "#66BBB5",
|
|
808
1647
|
"--shiki-token-string": "#859900",
|
|
809
1648
|
"--shiki-token-comment": "#92A1A5",
|
|
@@ -816,17 +1655,115 @@ window.__ModuleLoader__.load({
|
|
|
816
1655
|
}
|
|
817
1656
|
};
|
|
818
1657
|
//#endregion
|
|
1658
|
+
//#region src/client/presets/synthwave84.ts
|
|
1659
|
+
const bluish$5 = buildScale("--dsw-static-neutral-bluish", "#F5F0FF", "#262335", BLUISH_STEPS);
|
|
1660
|
+
const neutral$5 = buildScale("--dsw-static-neutral", "#F5F0FF", "#262335", NEUTRAL_STEPS);
|
|
1661
|
+
const lightSemantic$5 = buildSemanticScales({
|
|
1662
|
+
deepseek: "#6B21A8",
|
|
1663
|
+
blue: "#6B21A8",
|
|
1664
|
+
green: "#0E7A5A",
|
|
1665
|
+
amber: "#9A6A00",
|
|
1666
|
+
red: "#C0265A"
|
|
1667
|
+
});
|
|
1668
|
+
const darkSemantic$5 = buildSemanticScales({
|
|
1669
|
+
deepseek: "#FF7EDB",
|
|
1670
|
+
blue: "#FF7EDB",
|
|
1671
|
+
green: "#36F9F6",
|
|
1672
|
+
amber: "#FEDE5D",
|
|
1673
|
+
red: "#F97E72"
|
|
1674
|
+
});
|
|
1675
|
+
const synthwave84 = {
|
|
1676
|
+
label: "Synthwave 84",
|
|
1677
|
+
light: {
|
|
1678
|
+
...bluish$5,
|
|
1679
|
+
...neutral$5,
|
|
1680
|
+
...lightSemantic$5,
|
|
1681
|
+
"--shiki-token-constant": "#6B21A8",
|
|
1682
|
+
"--shiki-token-string": "#0E7A5A",
|
|
1683
|
+
"--shiki-token-comment": "#8A7FA8",
|
|
1684
|
+
"--shiki-token-keyword": "#C0265A",
|
|
1685
|
+
"--shiki-token-parameter": "#9A6A00",
|
|
1686
|
+
"--shiki-token-function": "#6B21A8",
|
|
1687
|
+
"--shiki-token-string-expression": "#0E7A5A",
|
|
1688
|
+
"--shiki-token-punctuation": "#3A2E4A",
|
|
1689
|
+
"--shiki-token-link": "#6B21A8"
|
|
1690
|
+
},
|
|
1691
|
+
dark: {
|
|
1692
|
+
...bluish$5,
|
|
1693
|
+
...neutral$5,
|
|
1694
|
+
...darkSemantic$5,
|
|
1695
|
+
"--shiki-token-constant": "#FEDE5D",
|
|
1696
|
+
"--shiki-token-string": "#36F9F6",
|
|
1697
|
+
"--shiki-token-comment": "#848BBD",
|
|
1698
|
+
"--shiki-token-keyword": "#FF7EDB",
|
|
1699
|
+
"--shiki-token-parameter": "#FEDE5D",
|
|
1700
|
+
"--shiki-token-function": "#FF7EDB",
|
|
1701
|
+
"--shiki-token-string-expression": "#36F9F6",
|
|
1702
|
+
"--shiki-token-punctuation": "#FFFFFF",
|
|
1703
|
+
"--shiki-token-link": "#36F9F6"
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
//#endregion
|
|
1707
|
+
//#region src/client/presets/system.ts
|
|
1708
|
+
const bluish$4 = buildScale("--dsw-static-neutral-bluish", "#F5F5F7", "#1C1C1E", BLUISH_STEPS);
|
|
1709
|
+
const neutral$4 = buildScale("--dsw-static-neutral", "#F5F5F7", "#1C1C1E", NEUTRAL_STEPS);
|
|
1710
|
+
const lightSemantic$4 = buildSemanticScales({
|
|
1711
|
+
deepseek: "#007AFF",
|
|
1712
|
+
blue: "#007AFF",
|
|
1713
|
+
green: "#34C759",
|
|
1714
|
+
amber: "#FF9500",
|
|
1715
|
+
red: "#FF3B30"
|
|
1716
|
+
});
|
|
1717
|
+
const darkSemantic$4 = buildSemanticScales({
|
|
1718
|
+
deepseek: "#0A84FF",
|
|
1719
|
+
blue: "#0A84FF",
|
|
1720
|
+
green: "#30D158",
|
|
1721
|
+
amber: "#FF9F0A",
|
|
1722
|
+
red: "#FF453A"
|
|
1723
|
+
});
|
|
1724
|
+
const system = {
|
|
1725
|
+
label: "System",
|
|
1726
|
+
light: {
|
|
1727
|
+
...bluish$4,
|
|
1728
|
+
...neutral$4,
|
|
1729
|
+
...lightSemantic$4,
|
|
1730
|
+
"--shiki-token-constant": "#007AFF",
|
|
1731
|
+
"--shiki-token-string": "#34C759",
|
|
1732
|
+
"--shiki-token-comment": "#8E8E93",
|
|
1733
|
+
"--shiki-token-keyword": "#AF52DE",
|
|
1734
|
+
"--shiki-token-parameter": "#FF9500",
|
|
1735
|
+
"--shiki-token-function": "#007AFF",
|
|
1736
|
+
"--shiki-token-string-expression": "#34C759",
|
|
1737
|
+
"--shiki-token-punctuation": "#1C1C1E",
|
|
1738
|
+
"--shiki-token-link": "#007AFF"
|
|
1739
|
+
},
|
|
1740
|
+
dark: {
|
|
1741
|
+
...bluish$4,
|
|
1742
|
+
...neutral$4,
|
|
1743
|
+
...darkSemantic$4,
|
|
1744
|
+
"--shiki-token-constant": "#0A84FF",
|
|
1745
|
+
"--shiki-token-string": "#30D158",
|
|
1746
|
+
"--shiki-token-comment": "#8E8E93",
|
|
1747
|
+
"--shiki-token-keyword": "#BF5AF2",
|
|
1748
|
+
"--shiki-token-parameter": "#FF9F0A",
|
|
1749
|
+
"--shiki-token-function": "#0A84FF",
|
|
1750
|
+
"--shiki-token-string-expression": "#30D158",
|
|
1751
|
+
"--shiki-token-punctuation": "#F5F5F7",
|
|
1752
|
+
"--shiki-token-link": "#0A84FF"
|
|
1753
|
+
}
|
|
1754
|
+
};
|
|
1755
|
+
//#endregion
|
|
819
1756
|
//#region src/client/presets/tokyonight.ts
|
|
820
|
-
const bluish$
|
|
821
|
-
const neutral$
|
|
822
|
-
const lightSemantic$
|
|
1757
|
+
const bluish$3 = buildScale("--dsw-static-neutral-bluish", "#e6e7ed", "#1a1b26", BLUISH_STEPS);
|
|
1758
|
+
const neutral$3 = buildScale("--dsw-static-neutral", "#e6e7ed", "#1a1b26", NEUTRAL_STEPS);
|
|
1759
|
+
const lightSemantic$3 = buildSemanticScales({
|
|
823
1760
|
deepseek: "#34548A",
|
|
824
1761
|
blue: "#34548A",
|
|
825
1762
|
green: "#33635C",
|
|
826
1763
|
amber: "#8F5E15",
|
|
827
1764
|
red: "#C53B53"
|
|
828
1765
|
});
|
|
829
|
-
const darkSemantic$
|
|
1766
|
+
const darkSemantic$3 = buildSemanticScales({
|
|
830
1767
|
deepseek: "#7AA2F7",
|
|
831
1768
|
blue: "#7AA2F7",
|
|
832
1769
|
green: "#9ECE6A",
|
|
@@ -836,9 +1773,9 @@ window.__ModuleLoader__.load({
|
|
|
836
1773
|
const tokyonight = {
|
|
837
1774
|
label: "Tokyo Night",
|
|
838
1775
|
light: {
|
|
839
|
-
...bluish$
|
|
840
|
-
...neutral$
|
|
841
|
-
...lightSemantic$
|
|
1776
|
+
...bluish$3,
|
|
1777
|
+
...neutral$3,
|
|
1778
|
+
...lightSemantic$3,
|
|
842
1779
|
"--shiki-token-constant": "#0F4B6E",
|
|
843
1780
|
"--shiki-token-string": "#1A7A3A",
|
|
844
1781
|
"--shiki-token-comment": "#6E7A9E",
|
|
@@ -850,9 +1787,9 @@ window.__ModuleLoader__.load({
|
|
|
850
1787
|
"--shiki-token-link": "#34548A"
|
|
851
1788
|
},
|
|
852
1789
|
dark: {
|
|
853
|
-
...bluish$
|
|
854
|
-
...neutral$
|
|
855
|
-
...darkSemantic$
|
|
1790
|
+
...bluish$3,
|
|
1791
|
+
...neutral$3,
|
|
1792
|
+
...darkSemantic$3,
|
|
856
1793
|
"--shiki-token-constant": "#7DCFFF",
|
|
857
1794
|
"--shiki-token-string": "#9ECE6A",
|
|
858
1795
|
"--shiki-token-comment": "#9197B2",
|
|
@@ -865,6 +1802,104 @@ window.__ModuleLoader__.load({
|
|
|
865
1802
|
}
|
|
866
1803
|
};
|
|
867
1804
|
//#endregion
|
|
1805
|
+
//#region src/client/presets/vercel.ts
|
|
1806
|
+
const bluish$2 = buildScale("--dsw-static-neutral-bluish", "#FFFFFF", "#000000", BLUISH_STEPS);
|
|
1807
|
+
const neutral$2 = buildScale("--dsw-static-neutral", "#FFFFFF", "#000000", NEUTRAL_STEPS);
|
|
1808
|
+
const lightSemantic$2 = buildSemanticScales({
|
|
1809
|
+
deepseek: "#0070F3",
|
|
1810
|
+
blue: "#0070F3",
|
|
1811
|
+
green: "#0A7A42",
|
|
1812
|
+
amber: "#B45309",
|
|
1813
|
+
red: "#E00C1A"
|
|
1814
|
+
});
|
|
1815
|
+
const darkSemantic$2 = buildSemanticScales({
|
|
1816
|
+
deepseek: "#3291FF",
|
|
1817
|
+
blue: "#3291FF",
|
|
1818
|
+
green: "#0CCB6A",
|
|
1819
|
+
amber: "#F5A623",
|
|
1820
|
+
red: "#FF6166"
|
|
1821
|
+
});
|
|
1822
|
+
const vercel = {
|
|
1823
|
+
label: "Vercel",
|
|
1824
|
+
light: {
|
|
1825
|
+
...bluish$2,
|
|
1826
|
+
...neutral$2,
|
|
1827
|
+
...lightSemantic$2,
|
|
1828
|
+
"--shiki-token-constant": "#0070F3",
|
|
1829
|
+
"--shiki-token-string": "#0A7A42",
|
|
1830
|
+
"--shiki-token-comment": "#8A8A8A",
|
|
1831
|
+
"--shiki-token-keyword": "#000000",
|
|
1832
|
+
"--shiki-token-parameter": "#B45309",
|
|
1833
|
+
"--shiki-token-function": "#0070F3",
|
|
1834
|
+
"--shiki-token-string-expression": "#0A7A42",
|
|
1835
|
+
"--shiki-token-punctuation": "#000000",
|
|
1836
|
+
"--shiki-token-link": "#0070F3"
|
|
1837
|
+
},
|
|
1838
|
+
dark: {
|
|
1839
|
+
...bluish$2,
|
|
1840
|
+
...neutral$2,
|
|
1841
|
+
...darkSemantic$2,
|
|
1842
|
+
"--shiki-token-constant": "#3291FF",
|
|
1843
|
+
"--shiki-token-string": "#0CCB6A",
|
|
1844
|
+
"--shiki-token-comment": "#8A8A8A",
|
|
1845
|
+
"--shiki-token-keyword": "#FFFFFF",
|
|
1846
|
+
"--shiki-token-parameter": "#F5A623",
|
|
1847
|
+
"--shiki-token-function": "#3291FF",
|
|
1848
|
+
"--shiki-token-string-expression": "#0CCB6A",
|
|
1849
|
+
"--shiki-token-punctuation": "#FFFFFF",
|
|
1850
|
+
"--shiki-token-link": "#3291FF"
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1853
|
+
//#endregion
|
|
1854
|
+
//#region src/client/presets/vesper.ts
|
|
1855
|
+
const bluish$1 = buildScale("--dsw-static-neutral-bluish", "#FDFCFB", "#0A0A0B", BLUISH_STEPS);
|
|
1856
|
+
const neutral$1 = buildScale("--dsw-static-neutral", "#FDFCFB", "#0A0A0B", NEUTRAL_STEPS);
|
|
1857
|
+
const lightSemantic$1 = buildSemanticScales({
|
|
1858
|
+
deepseek: "#3A3A3A",
|
|
1859
|
+
blue: "#3A3A3A",
|
|
1860
|
+
green: "#5A7A3A",
|
|
1861
|
+
amber: "#8A6A2E",
|
|
1862
|
+
red: "#8A2A2E"
|
|
1863
|
+
});
|
|
1864
|
+
const darkSemantic$1 = buildSemanticScales({
|
|
1865
|
+
deepseek: "#E8E8E8",
|
|
1866
|
+
blue: "#E8E8E8",
|
|
1867
|
+
green: "#B8C8A8",
|
|
1868
|
+
amber: "#D6C8A8",
|
|
1869
|
+
red: "#C9A8A8"
|
|
1870
|
+
});
|
|
1871
|
+
const vesper = {
|
|
1872
|
+
label: "Vesper",
|
|
1873
|
+
light: {
|
|
1874
|
+
...bluish$1,
|
|
1875
|
+
...neutral$1,
|
|
1876
|
+
...lightSemantic$1,
|
|
1877
|
+
"--shiki-token-constant": "#3A3A3A",
|
|
1878
|
+
"--shiki-token-string": "#5A7A3A",
|
|
1879
|
+
"--shiki-token-comment": "#8A8A8A",
|
|
1880
|
+
"--shiki-token-keyword": "#3A3A3A",
|
|
1881
|
+
"--shiki-token-parameter": "#8A6A2E",
|
|
1882
|
+
"--shiki-token-function": "#3A3A3A",
|
|
1883
|
+
"--shiki-token-string-expression": "#5A7A3A",
|
|
1884
|
+
"--shiki-token-punctuation": "#2A2A2A",
|
|
1885
|
+
"--shiki-token-link": "#3A3A3A"
|
|
1886
|
+
},
|
|
1887
|
+
dark: {
|
|
1888
|
+
...bluish$1,
|
|
1889
|
+
...neutral$1,
|
|
1890
|
+
...darkSemantic$1,
|
|
1891
|
+
"--shiki-token-constant": "#E8E8E8",
|
|
1892
|
+
"--shiki-token-string": "#B8C8A8",
|
|
1893
|
+
"--shiki-token-comment": "#8A8A8A",
|
|
1894
|
+
"--shiki-token-keyword": "#E8E8E8",
|
|
1895
|
+
"--shiki-token-parameter": "#D6C8A8",
|
|
1896
|
+
"--shiki-token-function": "#E8E8E8",
|
|
1897
|
+
"--shiki-token-string-expression": "#B8C8A8",
|
|
1898
|
+
"--shiki-token-punctuation": "#E8E8E8",
|
|
1899
|
+
"--shiki-token-link": "#E8E8E8"
|
|
1900
|
+
}
|
|
1901
|
+
};
|
|
1902
|
+
//#endregion
|
|
868
1903
|
//#region src/client/presets/zenburn.ts
|
|
869
1904
|
const bluish = buildScale("--dsw-static-neutral-bluish", "#FFFFEF", "#3f3f3f", BLUISH_STEPS);
|
|
870
1905
|
const neutral = buildScale("--dsw-static-neutral", "#FFFFEF", "#3f3f3f", NEUTRAL_STEPS);
|
|
@@ -885,18 +1920,39 @@ window.__ModuleLoader__.load({
|
|
|
885
1920
|
//#endregion
|
|
886
1921
|
//#region src/client/presets.ts
|
|
887
1922
|
const PRESETS = {
|
|
1923
|
+
aura,
|
|
888
1924
|
ayu,
|
|
889
1925
|
catppuccin,
|
|
1926
|
+
"catppuccin-frappe": catppuccinFrappe,
|
|
1927
|
+
"catppuccin-macchiato": catppuccinMacchiato,
|
|
1928
|
+
cobalt2,
|
|
1929
|
+
cursor,
|
|
890
1930
|
dracula,
|
|
891
1931
|
dsh,
|
|
1932
|
+
everforest,
|
|
1933
|
+
flexoki,
|
|
892
1934
|
github,
|
|
893
1935
|
gruvbox,
|
|
1936
|
+
kanagawa,
|
|
1937
|
+
"lucent-orng": lucentOrng,
|
|
1938
|
+
material,
|
|
1939
|
+
matrix,
|
|
1940
|
+
mercury,
|
|
894
1941
|
monokai,
|
|
1942
|
+
nightowl,
|
|
895
1943
|
nord,
|
|
896
1944
|
onedark,
|
|
1945
|
+
opencode,
|
|
1946
|
+
orng,
|
|
1947
|
+
"osaka-jade": osakaJade,
|
|
1948
|
+
palenight,
|
|
897
1949
|
rosepine,
|
|
898
1950
|
solarized,
|
|
1951
|
+
synthwave84,
|
|
1952
|
+
system,
|
|
899
1953
|
tokyonight,
|
|
1954
|
+
vercel,
|
|
1955
|
+
vesper,
|
|
900
1956
|
zenburn: {
|
|
901
1957
|
label: "Zenburn",
|
|
902
1958
|
light: {
|
|
@@ -929,6 +1985,11 @@ window.__ModuleLoader__.load({
|
|
|
929
1985
|
}
|
|
930
1986
|
}
|
|
931
1987
|
};
|
|
1988
|
+
/**
|
|
1989
|
+
* Presets that override nothing: the shell keeps its own colours. The single
|
|
1990
|
+
* source of this set, so the token layer and the panel cannot drift on it.
|
|
1991
|
+
*/
|
|
1992
|
+
const NOOP_PRESET_IDS = /* @__PURE__ */ new Set(["native", "dsh"]);
|
|
932
1993
|
const presetOptions = [{
|
|
933
1994
|
value: "dsh",
|
|
934
1995
|
label: PRESETS.dsh.label
|
|
@@ -1107,10 +2168,17 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1107
2168
|
function buildBaseCss() {
|
|
1108
2169
|
return `${buildPrimitivesCss()}\n\n${SHIKI_CSS}`;
|
|
1109
2170
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
2171
|
+
/**
|
|
2172
|
+
* Accepts either a preset id or an already-built `PresetDef` (what a custom
|
|
2173
|
+
* theme produces). Both go through the identical merge, so a custom theme is
|
|
2174
|
+
* not a special case anywhere downstream.
|
|
2175
|
+
*/
|
|
2176
|
+
function resolvePreset(src) {
|
|
2177
|
+
let preset;
|
|
2178
|
+
if (typeof src === "string") {
|
|
2179
|
+
if (NOOP_PRESET_IDS.has(src)) return null;
|
|
2180
|
+
preset = PRESETS[src] ?? null;
|
|
2181
|
+
} else preset = src;
|
|
1114
2182
|
if (!preset) return null;
|
|
1115
2183
|
return {
|
|
1116
2184
|
light: {
|
|
@@ -1123,16 +2191,15 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1123
2191
|
}
|
|
1124
2192
|
};
|
|
1125
2193
|
}
|
|
1126
|
-
function buildOverrides(
|
|
1127
|
-
const resolved = resolvePreset(
|
|
2194
|
+
function buildOverrides(src) {
|
|
2195
|
+
const resolved = resolvePreset(src);
|
|
1128
2196
|
if (!resolved) return {};
|
|
1129
2197
|
return primitiveOverrides(resolved.light, resolved.dark);
|
|
1130
2198
|
}
|
|
1131
|
-
function buildFullCssFallback(
|
|
1132
|
-
const resolved = resolvePreset(
|
|
2199
|
+
function buildFullCssFallback(src) {
|
|
2200
|
+
const resolved = resolvePreset(src);
|
|
1133
2201
|
if (!resolved) return "";
|
|
1134
|
-
|
|
1135
|
-
return `:root{\n${toBlock(resolved.light)}\n}\nhtml[data-ds-dark-theme], body[data-ds-dark-theme]{\n${toBlock(resolved.dark)}\n}`;
|
|
2202
|
+
return buildPrimitivesCss(resolved.light, resolved.dark);
|
|
1136
2203
|
}
|
|
1137
2204
|
//#endregion
|
|
1138
2205
|
//#region src/client/style-injector.ts
|
|
@@ -1173,10 +2240,486 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1173
2240
|
};
|
|
1174
2241
|
}
|
|
1175
2242
|
//#endregion
|
|
2243
|
+
//#region src/client/custom.ts
|
|
2244
|
+
/** The nine `--shiki-token-*` slots, in stylesheet order. */
|
|
2245
|
+
const SHIKI_KEYS = [
|
|
2246
|
+
"constant",
|
|
2247
|
+
"string",
|
|
2248
|
+
"comment",
|
|
2249
|
+
"keyword",
|
|
2250
|
+
"parameter",
|
|
2251
|
+
"function",
|
|
2252
|
+
"string-expression",
|
|
2253
|
+
"punctuation",
|
|
2254
|
+
"link"
|
|
2255
|
+
];
|
|
2256
|
+
/** Seed values used when a source preset cannot supply one (e.g. the no-op `dsh`). */
|
|
2257
|
+
const SHIKI_FALLBACK = {
|
|
2258
|
+
light: {
|
|
2259
|
+
constant: "#1C7ED6",
|
|
2260
|
+
string: "#2F9E44",
|
|
2261
|
+
comment: "#868E96",
|
|
2262
|
+
keyword: "#D6336C",
|
|
2263
|
+
parameter: "#E8590C",
|
|
2264
|
+
function: "#6741D9",
|
|
2265
|
+
"string-expression": "#2B8A3E",
|
|
2266
|
+
punctuation: "#495057",
|
|
2267
|
+
link: "#1971C2"
|
|
2268
|
+
},
|
|
2269
|
+
dark: {
|
|
2270
|
+
constant: "#4DABF7",
|
|
2271
|
+
string: "#69DB7C",
|
|
2272
|
+
comment: "#ADB5BD",
|
|
2273
|
+
keyword: "#FAA2C1",
|
|
2274
|
+
parameter: "#FFA94D",
|
|
2275
|
+
function: "#B197FC",
|
|
2276
|
+
"string-expression": "#8CE99A",
|
|
2277
|
+
punctuation: "#CED4DA",
|
|
2278
|
+
link: "#74C0FC"
|
|
2279
|
+
}
|
|
2280
|
+
};
|
|
2281
|
+
const HEX = /^#([0-9a-f]{3,8})$/i;
|
|
2282
|
+
const RGB_FN = /^rgba?\(([^)]*)\)$/i;
|
|
2283
|
+
const HSL_FN = /^hsla?\(([^)]*)\)$/i;
|
|
2284
|
+
function isRecord$1(value) {
|
|
2285
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2286
|
+
}
|
|
2287
|
+
const clamp255 = (n) => Math.max(0, Math.min(255, Math.round(n)));
|
|
2288
|
+
const clamp01 = (n) => Math.max(0, Math.min(1, n));
|
|
2289
|
+
/** Accepts both `a, b, c` and the modern `a b c / d` argument syntax. */
|
|
2290
|
+
function fnArgs(body) {
|
|
2291
|
+
return body.replace(/\//g, " ").split(/[\s,]+/).filter(Boolean);
|
|
2292
|
+
}
|
|
2293
|
+
/** A colour channel: `128` or a percentage. Returns null for anything else. */
|
|
2294
|
+
function channel(token) {
|
|
2295
|
+
const pct = token.endsWith("%");
|
|
2296
|
+
const v = parseFloat(pct ? token.slice(0, -1) : token);
|
|
2297
|
+
if (!Number.isFinite(v)) return null;
|
|
2298
|
+
return pct ? v / 100 * 255 : v;
|
|
2299
|
+
}
|
|
2300
|
+
function hslToRgb(h, s, l) {
|
|
2301
|
+
const a = s * Math.min(l, 1 - l);
|
|
2302
|
+
const f = (n) => {
|
|
2303
|
+
const k = (n + h / 30) % 12;
|
|
2304
|
+
return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
2305
|
+
};
|
|
2306
|
+
return [
|
|
2307
|
+
clamp255(f(0) * 255),
|
|
2308
|
+
clamp255(f(8) * 255),
|
|
2309
|
+
clamp255(f(4) * 255)
|
|
2310
|
+
];
|
|
2311
|
+
}
|
|
2312
|
+
const toRgbHex = (rgb) => "#" + rgb.map((n) => clamp255(n).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
2313
|
+
/**
|
|
2314
|
+
* Parse a colour into `#RRGGBB`, or null when it is not a format we understand.
|
|
2315
|
+
*
|
|
2316
|
+
* Accepted: `#RGB`, `#RGBA`, `#RRGGBB`, `#RRGGBBAA`, `rgb()`/`rgba()` with
|
|
2317
|
+
* numbers or percentages, and `hsl()`/`hsla()`. Alpha is parsed but dropped —
|
|
2318
|
+
* every token these seeds drive is an opaque theme colour.
|
|
2319
|
+
*
|
|
2320
|
+
* `primitives.ts` stores `rgb(r, g, b)` while presets store hex, so both shapes
|
|
2321
|
+
* have to work; the extra forms are there for what users may type.
|
|
2322
|
+
*/
|
|
2323
|
+
function tryToHex(input) {
|
|
2324
|
+
if (typeof input !== "string") return null;
|
|
2325
|
+
const s = input.trim();
|
|
2326
|
+
if (!s) return null;
|
|
2327
|
+
const hex = s.match(HEX);
|
|
2328
|
+
if (hex) {
|
|
2329
|
+
const d = hex[1];
|
|
2330
|
+
const twice = (c) => c + c;
|
|
2331
|
+
if (d.length === 3 || d.length === 4) return `#${twice(d[0])}${twice(d[1])}${twice(d[2])}`.toUpperCase();
|
|
2332
|
+
if (d.length === 6 || d.length === 8) return `#${d.slice(0, 6)}`.toUpperCase();
|
|
2333
|
+
return null;
|
|
2334
|
+
}
|
|
2335
|
+
const rgbFn = s.match(RGB_FN);
|
|
2336
|
+
if (rgbFn) {
|
|
2337
|
+
const parts = fnArgs(rgbFn[1]);
|
|
2338
|
+
if (parts.length < 3) return null;
|
|
2339
|
+
const rgb = parts.slice(0, 3).map(channel);
|
|
2340
|
+
if (rgb.some((n) => n === null)) return null;
|
|
2341
|
+
return toRgbHex(rgb);
|
|
2342
|
+
}
|
|
2343
|
+
const hslFn = s.match(HSL_FN);
|
|
2344
|
+
if (hslFn) {
|
|
2345
|
+
const parts = fnArgs(hslFn[1]);
|
|
2346
|
+
if (parts.length < 3) return null;
|
|
2347
|
+
const h = parseFloat(parts[0].replace(/deg$/i, ""));
|
|
2348
|
+
const sat = parseFloat(parts[1]);
|
|
2349
|
+
const lig = parseFloat(parts[2]);
|
|
2350
|
+
if (![
|
|
2351
|
+
h,
|
|
2352
|
+
sat,
|
|
2353
|
+
lig
|
|
2354
|
+
].every(Number.isFinite)) return null;
|
|
2355
|
+
return toRgbHex(hslToRgb((h % 360 + 360) % 360, clamp01(sat / 100), clamp01(lig / 100)));
|
|
2356
|
+
}
|
|
2357
|
+
return null;
|
|
2358
|
+
}
|
|
2359
|
+
/** `tryToHex` with a black fallback, for call sites that need a guaranteed value. */
|
|
2360
|
+
function toHex(input) {
|
|
2361
|
+
return tryToHex(input) ?? "#000000";
|
|
2362
|
+
}
|
|
2363
|
+
function readSeed(map, fallback, key) {
|
|
2364
|
+
return toHex(map[key] ?? fallback[key]);
|
|
2365
|
+
}
|
|
2366
|
+
/**
|
|
2367
|
+
* Recover the seed inputs from an already-generated preset.
|
|
2368
|
+
*
|
|
2369
|
+
* Exact by construction: `buildScale` writes the `start`/`end` arguments to
|
|
2370
|
+
* steps 00/1000, and `buildTintShadeScale` writes the base to step 500. This is
|
|
2371
|
+
* what lets a user start from any preset without re-declaring its palette.
|
|
2372
|
+
*/
|
|
2373
|
+
function extractSeeds(base) {
|
|
2374
|
+
const seed = (key, mode) => readSeed(mode === "light" ? base.light : base.dark, mode === "light" ? PRIMITIVES_LIGHT : PRIMITIVES_DARK, key);
|
|
2375
|
+
const pair = (key) => ({
|
|
2376
|
+
light: seed(key, "light"),
|
|
2377
|
+
dark: seed(key, "dark")
|
|
2378
|
+
});
|
|
2379
|
+
/** Both ends of one appearance's ramp, read from that appearance's map. */
|
|
2380
|
+
const ramp = (mode) => ({
|
|
2381
|
+
lightest: seed("--dsw-static-neutral-bluish-00", mode),
|
|
2382
|
+
darkest: seed("--dsw-static-neutral-bluish-1000", mode)
|
|
2383
|
+
});
|
|
2384
|
+
const shiki = SHIKI_KEYS.reduce((acc, k) => {
|
|
2385
|
+
const cssKey = `--shiki-token-${k}`;
|
|
2386
|
+
const lightMap = base.light;
|
|
2387
|
+
const darkMap = base.dark;
|
|
2388
|
+
acc[k] = {
|
|
2389
|
+
light: toHex(lightMap[cssKey] ?? SHIKI_FALLBACK.light[k]),
|
|
2390
|
+
dark: toHex(darkMap[cssKey] ?? SHIKI_FALLBACK.dark[k])
|
|
2391
|
+
};
|
|
2392
|
+
return acc;
|
|
2393
|
+
}, {});
|
|
2394
|
+
return {
|
|
2395
|
+
neutral: {
|
|
2396
|
+
light: ramp("light"),
|
|
2397
|
+
dark: ramp("dark")
|
|
2398
|
+
},
|
|
2399
|
+
accent: pair("--dsw-static-deepseek-500"),
|
|
2400
|
+
green: pair("--dsw-static-green-500"),
|
|
2401
|
+
amber: pair("--dsw-static-amber-500"),
|
|
2402
|
+
red: pair("--dsw-static-red-500"),
|
|
2403
|
+
shiki
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
/** v1 carried one neutral ramp shared by both appearances. */
|
|
2407
|
+
const CUSTOM_SCHEMA_VERSION_LEGACY = 1;
|
|
2408
|
+
function encodeCustom(base, theme) {
|
|
2409
|
+
return JSON.stringify({
|
|
2410
|
+
v: 2,
|
|
2411
|
+
base,
|
|
2412
|
+
theme
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
/** Parse a stored blob. Returns null for absent/corrupt/foreign-version data. */
|
|
2416
|
+
function parseEnvelope(raw) {
|
|
2417
|
+
if (!raw) return null;
|
|
2418
|
+
try {
|
|
2419
|
+
const parsed = JSON.parse(raw);
|
|
2420
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
2421
|
+
if (parsed.v !== 2 && parsed.v !== CUSTOM_SCHEMA_VERSION_LEGACY) return null;
|
|
2422
|
+
return {
|
|
2423
|
+
v: 2,
|
|
2424
|
+
base: String(parsed.base ?? ""),
|
|
2425
|
+
theme: parsed.theme
|
|
2426
|
+
};
|
|
2427
|
+
} catch {
|
|
2428
|
+
return null;
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* The neutral seeds in the current shape. A pre-v2 blob carried one ramp shared
|
|
2433
|
+
* by both appearances; repeating it per appearance reproduces exactly what that
|
|
2434
|
+
* blob rendered before the split, so existing themes migrate without a visible
|
|
2435
|
+
* change.
|
|
2436
|
+
*/
|
|
2437
|
+
function neutralSeeds(src) {
|
|
2438
|
+
if (isRecord$1(src.neutral)) return src.neutral;
|
|
2439
|
+
const shared = {
|
|
2440
|
+
lightest: src.neutralLightest,
|
|
2441
|
+
darkest: src.neutralDarkest
|
|
2442
|
+
};
|
|
2443
|
+
return {
|
|
2444
|
+
light: shared,
|
|
2445
|
+
dark: shared
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2448
|
+
/** Repair a partially-invalid object against `fallback`, keeping every valid colour. */
|
|
2449
|
+
function normalizeCustom(raw, fallback) {
|
|
2450
|
+
const src = raw ?? {};
|
|
2451
|
+
const pick = (value, fb) => tryToHex(value) ?? fb;
|
|
2452
|
+
const pickPair = (value, fb) => {
|
|
2453
|
+
const v = value ?? {};
|
|
2454
|
+
return {
|
|
2455
|
+
light: pick(v.light, fb.light),
|
|
2456
|
+
dark: pick(v.dark, fb.dark)
|
|
2457
|
+
};
|
|
2458
|
+
};
|
|
2459
|
+
const pickRamp = (value, fb) => {
|
|
2460
|
+
const v = value ?? {};
|
|
2461
|
+
return {
|
|
2462
|
+
lightest: pick(v.lightest, fb.lightest),
|
|
2463
|
+
darkest: pick(v.darkest, fb.darkest)
|
|
2464
|
+
};
|
|
2465
|
+
};
|
|
2466
|
+
const shikiSrc = src.shiki ?? {};
|
|
2467
|
+
const shiki = SHIKI_KEYS.reduce((acc, k) => {
|
|
2468
|
+
acc[k] = pickPair(shikiSrc[k], fallback.shiki[k]);
|
|
2469
|
+
return acc;
|
|
2470
|
+
}, {});
|
|
2471
|
+
const neutral = neutralSeeds(src);
|
|
2472
|
+
return {
|
|
2473
|
+
neutral: {
|
|
2474
|
+
light: pickRamp(neutral.light, fallback.neutral.light),
|
|
2475
|
+
dark: pickRamp(neutral.dark, fallback.neutral.dark)
|
|
2476
|
+
},
|
|
2477
|
+
accent: pickPair(src.accent, fallback.accent),
|
|
2478
|
+
green: pickPair(src.green, fallback.green),
|
|
2479
|
+
amber: pickPair(src.amber, fallback.amber),
|
|
2480
|
+
red: pickPair(src.red, fallback.red),
|
|
2481
|
+
shiki
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Turn seeds into a full `PresetDef` using the presets' own helpers.
|
|
2486
|
+
*
|
|
2487
|
+
* Unlike the presets (which ship one ramp for both appearances), the ramp is
|
|
2488
|
+
* built once per appearance, so the light text and the dark text are no longer
|
|
2489
|
+
* the two ends of the same colour axis.
|
|
2490
|
+
*/
|
|
2491
|
+
function buildCustomPreset(v) {
|
|
2492
|
+
/** One appearance's ramp, published under both prefixes DSH reads from. */
|
|
2493
|
+
const ramp = (mode) => {
|
|
2494
|
+
const { lightest, darkest } = v.neutral[mode];
|
|
2495
|
+
return {
|
|
2496
|
+
...buildScale("--dsw-static-neutral-bluish", lightest, darkest, BLUISH_STEPS),
|
|
2497
|
+
...buildScale("--dsw-static-neutral", lightest, darkest, NEUTRAL_STEPS)
|
|
2498
|
+
};
|
|
2499
|
+
};
|
|
2500
|
+
const semantic = (mode) => buildSemanticScales({
|
|
2501
|
+
deepseek: v.accent[mode],
|
|
2502
|
+
blue: v.accent[mode],
|
|
2503
|
+
green: v.green[mode],
|
|
2504
|
+
amber: v.amber[mode],
|
|
2505
|
+
red: v.red[mode]
|
|
2506
|
+
});
|
|
2507
|
+
const shiki = (mode) => {
|
|
2508
|
+
const out = {};
|
|
2509
|
+
for (const k of SHIKI_KEYS) out[`--shiki-token-${k}`] = v.shiki[k][mode];
|
|
2510
|
+
return out;
|
|
2511
|
+
};
|
|
2512
|
+
return {
|
|
2513
|
+
label: "Custom",
|
|
2514
|
+
light: {
|
|
2515
|
+
...ramp("light"),
|
|
2516
|
+
...semantic("light"),
|
|
2517
|
+
...shiki("light")
|
|
2518
|
+
},
|
|
2519
|
+
dark: {
|
|
2520
|
+
...ramp("dark"),
|
|
2521
|
+
...semantic("dark"),
|
|
2522
|
+
...shiki("dark")
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
/** Collision-resistant enough for a local list, and stable across reloads. */
|
|
2527
|
+
function newThemeId() {
|
|
2528
|
+
return `ct_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`;
|
|
2529
|
+
}
|
|
2530
|
+
/**
|
|
2531
|
+
* Parse the saved list. Entries with a corrupt theme are repaired against
|
|
2532
|
+
* `fallbackFor(base)` rather than dropped, so one bad record cannot lose the
|
|
2533
|
+
* rest of the list; only structurally unusable entries are skipped.
|
|
2534
|
+
*/
|
|
2535
|
+
function decodeList(raw, fallbackFor) {
|
|
2536
|
+
if (!raw) return [];
|
|
2537
|
+
try {
|
|
2538
|
+
const parsed = JSON.parse(raw);
|
|
2539
|
+
const known = parsed?.v === 2 || parsed?.v === CUSTOM_SCHEMA_VERSION_LEGACY;
|
|
2540
|
+
if (!parsed || !known || !Array.isArray(parsed.items)) return [];
|
|
2541
|
+
const out = [];
|
|
2542
|
+
for (const item of parsed.items) {
|
|
2543
|
+
const e = item;
|
|
2544
|
+
if (typeof e?.id !== "string" || typeof e?.name !== "string") continue;
|
|
2545
|
+
const base = typeof e.base === "string" ? e.base : "";
|
|
2546
|
+
out.push({
|
|
2547
|
+
id: e.id,
|
|
2548
|
+
name: e.name,
|
|
2549
|
+
base,
|
|
2550
|
+
theme: normalizeCustom(e.theme, fallbackFor(base)),
|
|
2551
|
+
assets: Array.isArray(e.assets) ? e.assets : []
|
|
2552
|
+
});
|
|
2553
|
+
}
|
|
2554
|
+
return out;
|
|
2555
|
+
} catch {
|
|
2556
|
+
return [];
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
/** `${base} 1`, `${base} 2`, … skipping names already taken. */
|
|
2560
|
+
function nextThemeName(base, taken) {
|
|
2561
|
+
const used = new Set(taken);
|
|
2562
|
+
for (let n = 1;; n++) {
|
|
2563
|
+
const candidate = `${base} ${n}`;
|
|
2564
|
+
if (!used.has(candidate)) return candidate;
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
//#endregion
|
|
2568
|
+
//#region src/client/theme-files.ts
|
|
2569
|
+
/**
|
|
2570
|
+
* Browser half of the theme-file transport.
|
|
2571
|
+
*
|
|
2572
|
+
* The Host owns the files; this module is the only place that knows the wire
|
|
2573
|
+
* shape, so the rest of the client keeps working with plain `SavedTheme`
|
|
2574
|
+
* records. Every call is same-origin against the Host's own prefix route.
|
|
2575
|
+
*/
|
|
2576
|
+
/** Repair one stored document against the preset its seeds derive from. */
|
|
2577
|
+
function documentToSaved(doc, fallbackFor) {
|
|
2578
|
+
return {
|
|
2579
|
+
id: doc.id,
|
|
2580
|
+
name: doc.name,
|
|
2581
|
+
base: doc.base,
|
|
2582
|
+
theme: normalizeCustom(doc.theme, fallbackFor(doc.base)),
|
|
2583
|
+
assets: Array.isArray(doc.assets) ? doc.assets : []
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
/** The document payload for one entry; timestamps stay the Host's business. */
|
|
2587
|
+
function savedToDocument(entry) {
|
|
2588
|
+
return {
|
|
2589
|
+
v: 1,
|
|
2590
|
+
id: entry.id,
|
|
2591
|
+
name: entry.name,
|
|
2592
|
+
base: entry.base,
|
|
2593
|
+
theme: entry.theme,
|
|
2594
|
+
assets: entry.assets
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
function isRecord(value) {
|
|
2598
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2599
|
+
}
|
|
2600
|
+
/**
|
|
2601
|
+
* The Host answered as something other than this API — its route half is not
|
|
2602
|
+
* mounted (the usual cause is a DSH process started before this plugin's host
|
|
2603
|
+
* half existed). Distinguished from a write failure because only this one tells
|
|
2604
|
+
* the user to restart, and the browser copy is still intact meanwhile.
|
|
2605
|
+
*/
|
|
2606
|
+
var ThemeApiUnavailableError = class extends Error {};
|
|
2607
|
+
/** One JSON round trip; a non-OK status becomes an Error carrying the reason. */
|
|
2608
|
+
async function callApi(path, init) {
|
|
2609
|
+
const response = await fetch(path, {
|
|
2610
|
+
...init,
|
|
2611
|
+
headers: {
|
|
2612
|
+
"content-type": "application/json",
|
|
2613
|
+
...init?.headers
|
|
2614
|
+
}
|
|
2615
|
+
});
|
|
2616
|
+
let payload;
|
|
2617
|
+
try {
|
|
2618
|
+
payload = await response.json();
|
|
2619
|
+
} catch {
|
|
2620
|
+
throw new ThemeApiUnavailableError(`${String(response.status)} ${response.statusText}`);
|
|
2621
|
+
}
|
|
2622
|
+
if (!response.ok) {
|
|
2623
|
+
if (response.status === 404 || response.status === 405) throw new ThemeApiUnavailableError(`${String(response.status)} ${response.statusText}`);
|
|
2624
|
+
const reason = isRecord(payload) && typeof payload.error === "string" ? payload.error : response.statusText;
|
|
2625
|
+
throw new Error(reason);
|
|
2626
|
+
}
|
|
2627
|
+
return isRecord(payload) ? payload : {};
|
|
2628
|
+
}
|
|
2629
|
+
/**
|
|
2630
|
+
* The documents in one roster response, repaired into `SavedTheme` records.
|
|
2631
|
+
* Every call on this route answers with the same `{ themes: [...] }` body, so
|
|
2632
|
+
* both reads share this one parser: an entry missing an id or a name is skipped
|
|
2633
|
+
* rather than failing the whole roster.
|
|
2634
|
+
*/
|
|
2635
|
+
function payloadThemes(payload, fallbackFor) {
|
|
2636
|
+
const documents = Array.isArray(payload.themes) ? payload.themes : [];
|
|
2637
|
+
const out = [];
|
|
2638
|
+
for (const doc of documents) {
|
|
2639
|
+
if (!isRecord(doc) || typeof doc.id !== "string" || typeof doc.name !== "string") continue;
|
|
2640
|
+
out.push(documentToSaved({
|
|
2641
|
+
v: typeof doc.v === "number" ? doc.v : 1,
|
|
2642
|
+
id: doc.id,
|
|
2643
|
+
name: doc.name,
|
|
2644
|
+
base: typeof doc.base === "string" ? doc.base : "",
|
|
2645
|
+
theme: doc.theme,
|
|
2646
|
+
assets: Array.isArray(doc.assets) ? doc.assets : [],
|
|
2647
|
+
createdAt: "",
|
|
2648
|
+
updatedAt: ""
|
|
2649
|
+
}, fallbackFor));
|
|
2650
|
+
}
|
|
2651
|
+
return out;
|
|
2652
|
+
}
|
|
2653
|
+
/** Every stored theme, in the Host's creation-time order (oldest first). */
|
|
2654
|
+
async function fetchThemes(fallbackFor) {
|
|
2655
|
+
return payloadThemes(await callApi(THEME_API_PATH_THEMES), fallbackFor);
|
|
2656
|
+
}
|
|
2657
|
+
/** Insert or replace the given entries; resolves with what the Host stored. */
|
|
2658
|
+
async function pushThemes(entries, fallbackFor) {
|
|
2659
|
+
return payloadThemes(await callApi(THEME_API_PATH_THEMES, {
|
|
2660
|
+
method: "POST",
|
|
2661
|
+
body: JSON.stringify({ themes: entries.map(savedToDocument) })
|
|
2662
|
+
}), fallbackFor);
|
|
2663
|
+
}
|
|
2664
|
+
/** Remove one theme's directory. */
|
|
2665
|
+
async function removeTheme(id) {
|
|
2666
|
+
await callApi(`${THEME_API_PATH_THEMES}/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* The themes a browser saved before files became the store, minus those the
|
|
2670
|
+
* Host already has.
|
|
2671
|
+
*
|
|
2672
|
+
* Ids are the join key: a theme another browser already migrated must not be
|
|
2673
|
+
* written twice, while one this roster lacks would otherwise disappear from the
|
|
2674
|
+
* UI. Callers adopt the result, then stop reading the browser copy.
|
|
2675
|
+
*/
|
|
2676
|
+
function legacyThemesToAdopt(legacy, hostThemes) {
|
|
2677
|
+
const known = new Set(hostThemes.map((entry) => entry.id));
|
|
2678
|
+
return legacy.filter((entry) => !known.has(entry.id));
|
|
2679
|
+
}
|
|
2680
|
+
//#endregion
|
|
1176
2681
|
//#region src/client/components.tsx
|
|
1177
2682
|
/**
|
|
1178
|
-
* Theme settings UI: scheme selector
|
|
2683
|
+
* Theme settings UI: scheme selector, preset picker, and the custom colour editor.
|
|
2684
|
+
*/
|
|
2685
|
+
/** Reserved menu value that switches to the user-defined theme. */
|
|
2686
|
+
const CUSTOM_SELECTION = CUSTOM_PRESET_ID;
|
|
2687
|
+
/** Structural equality of the two seeds in one pair. */
|
|
2688
|
+
function samePair(a, b) {
|
|
2689
|
+
return a?.light === b?.light && a?.dark === b?.dark;
|
|
2690
|
+
}
|
|
2691
|
+
/** Structural equality of the two endpoints of one neutral ramp. */
|
|
2692
|
+
function sameRamp(a, b) {
|
|
2693
|
+
return a?.lightest === b?.lightest && a?.darkest === b?.darkest;
|
|
2694
|
+
}
|
|
2695
|
+
/** Structural equality over all 30 seeds, ignoring key order. */
|
|
2696
|
+
function sameSeeds(a, b) {
|
|
2697
|
+
if (!sameRamp(a.neutral?.light, b.neutral?.light) || !sameRamp(a.neutral?.dark, b.neutral?.dark)) return false;
|
|
2698
|
+
if (!samePair(a.accent, b.accent) || !samePair(a.green, b.green)) return false;
|
|
2699
|
+
if (!samePair(a.amber, b.amber) || !samePair(a.red, b.red)) return false;
|
|
2700
|
+
return SHIKI_KEYS.every((k) => samePair(a.shiki?.[k], b.shiki?.[k]));
|
|
2701
|
+
}
|
|
2702
|
+
/** The two roles one appearance's neutral ramp fills, in display order. */
|
|
2703
|
+
const NEUTRAL_ROLES = ["background", "foreground"];
|
|
2704
|
+
/**
|
|
2705
|
+
* The ramp end that paints an appearance's background or foreground. DSH points
|
|
2706
|
+
* its aliases at step 00 for light surfaces and step 1000 for light text, then
|
|
2707
|
+
* swaps both in dark (950 surfaces, 50 text), so the same end means opposite
|
|
2708
|
+
* things in the two appearances. Naming the role and resolving it per appearance
|
|
2709
|
+
* keeps the swatches in a stable background-then-foreground order.
|
|
1179
2710
|
*/
|
|
2711
|
+
function neutralEndForRole(mode, role) {
|
|
2712
|
+
return role === "background" === (mode === "light") ? "lightest" : "darkest";
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Whether the open editor holds work a close would throw away. A brand-new
|
|
2716
|
+
* theme has never been committed, so it always counts as unsaved; a reopened
|
|
2717
|
+
* entry is dirty only once its name or one of its seeds actually moved.
|
|
2718
|
+
*/
|
|
2719
|
+
function isDirty(open, current) {
|
|
2720
|
+
if (open.id === null) return true;
|
|
2721
|
+
return open.name.trim() !== open.originName.trim() || !sameSeeds(current, open.originTheme);
|
|
2722
|
+
}
|
|
1180
2723
|
function IconChevron() {
|
|
1181
2724
|
return react.createElement("svg", {
|
|
1182
2725
|
width: 14,
|
|
@@ -1189,25 +2732,23 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1189
2732
|
fill: "currentColor"
|
|
1190
2733
|
}));
|
|
1191
2734
|
}
|
|
1192
|
-
|
|
2735
|
+
/** The menu's selected-row tick: 16px, pushed to the trailing edge. */
|
|
2736
|
+
function IconCheck(props) {
|
|
2737
|
+
const { size = 16, className } = props;
|
|
1193
2738
|
return react.createElement("svg", {
|
|
1194
|
-
width:
|
|
1195
|
-
height:
|
|
2739
|
+
width: size,
|
|
2740
|
+
height: size,
|
|
1196
2741
|
viewBox: "0 0 16 16",
|
|
1197
2742
|
fill: "none",
|
|
1198
2743
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1199
|
-
|
|
1200
|
-
marginLeft: "auto",
|
|
1201
|
-
color: "var(--dsw-alias-label-primary)",
|
|
1202
|
-
display: "inline-flex"
|
|
1203
|
-
}
|
|
2744
|
+
className
|
|
1204
2745
|
}, react.createElement("path", {
|
|
1205
2746
|
d: "M15.0498 3.92579L8.49512 12.3818C8.25774 12.6881 8.04517 12.9645 7.84668 13.1689C7.63957 13.3823 7.38732 13.5841 7.04492 13.6719C6.86373 13.7183 6.6757 13.7346 6.48926 13.7197C6.13666 13.6915 5.8528 13.5355 5.6123 13.3604C5.38201 13.1926 5.12573 12.9567 4.83984 12.6953L1.03125 9.21289L1.96875 8.1875L5.77734 11.6699C6.08684 11.9529 6.27773 12.1249 6.43066 12.2363C6.50183 12.2882 6.54699 12.3135 6.57324 12.3252C6.58525 12.3305 6.59269 12.3322 6.5957 12.333C6.59802 12.3336 6.59961 12.334 6.59961 12.334C6.63317 12.3367 6.66758 12.3335 6.7002 12.3252C6.7002 12.3252 6.70211 12.3251 6.7041 12.3242C6.70698 12.3229 6.71348 12.319 6.72461 12.3115C6.74849 12.2956 6.78843 12.2642 6.84961 12.2012C6.98138 12.0654 7.13957 11.8628 7.39648 11.5313L13.9502 3.07422L15.0498 3.92579Z",
|
|
1206
2747
|
fill: "currentColor"
|
|
1207
2748
|
}));
|
|
1208
2749
|
}
|
|
1209
2750
|
function SchemeMenu(props) {
|
|
1210
|
-
const { value, options, onSelect } = props;
|
|
2751
|
+
const { value, options, onSelect, disabled } = props;
|
|
1211
2752
|
const [open, setOpen] = react.useState(false);
|
|
1212
2753
|
const rootRef = react.useRef(null);
|
|
1213
2754
|
const listRef = react.useRef(null);
|
|
@@ -1239,10 +2780,11 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1239
2780
|
}, react.createElement("button", {
|
|
1240
2781
|
type: "button",
|
|
1241
2782
|
className: "ct-select",
|
|
2783
|
+
disabled,
|
|
1242
2784
|
"aria-haspopup": "menu",
|
|
1243
|
-
"aria-expanded": open,
|
|
2785
|
+
"aria-expanded": open && !disabled,
|
|
1244
2786
|
onClick: () => setOpen(!open)
|
|
1245
|
-
}, react.createElement("span", { className: "ct-select-label" }, selected?.label ?? ""), react.createElement("span", { className: "ct-select-chevron" }, react.createElement(IconChevron, null))), open ? react.createElement("div", {
|
|
2787
|
+
}, react.createElement("span", { className: "ct-select-label" }, selected?.label ?? ""), react.createElement("span", { className: "ct-select-chevron" }, react.createElement(IconChevron, null))), open && !disabled ? react.createElement("div", {
|
|
1246
2788
|
ref: listRef,
|
|
1247
2789
|
className: "ct-menu-list",
|
|
1248
2790
|
style: {
|
|
@@ -1264,27 +2806,429 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1264
2806
|
setOpen(false);
|
|
1265
2807
|
onSelect(o.value);
|
|
1266
2808
|
}
|
|
1267
|
-
}, react.createElement("span", { className: "ct-menu-item-label" }, o.label), sel ? react.createElement(IconCheck,
|
|
2809
|
+
}, react.createElement("span", { className: "ct-menu-item-label" }, o.label), sel ? react.createElement(IconCheck, { className: "ct-menu-check" }) : null);
|
|
1268
2810
|
})) : null);
|
|
1269
2811
|
}
|
|
2812
|
+
/** Accessible on/off switch used to enable the custom theme. */
|
|
2813
|
+
function Switch(props) {
|
|
2814
|
+
const { checked, label, onChange } = props;
|
|
2815
|
+
return react.createElement("button", {
|
|
2816
|
+
type: "button",
|
|
2817
|
+
role: "switch",
|
|
2818
|
+
"aria-checked": checked,
|
|
2819
|
+
"aria-label": label,
|
|
2820
|
+
className: checked ? "ct-switch ct-switch-on" : "ct-switch",
|
|
2821
|
+
onClick: () => onChange(!checked)
|
|
2822
|
+
}, react.createElement("span", { className: "ct-switch-knob" }));
|
|
2823
|
+
}
|
|
2824
|
+
/**
|
|
2825
|
+
* Confirmation dialog for destructive actions, mirroring DSH's own Modal
|
|
2826
|
+
* (design-platform mask token + blur, r24 card on layer-2, prominent shadow).
|
|
2827
|
+
* Rendered inline rather than through a portal so it needs no react-dom import.
|
|
2828
|
+
*/
|
|
2829
|
+
function ConfirmDialog(props) {
|
|
2830
|
+
const { title, description, confirmLabel, cancelLabel, onConfirm, onCancel } = props;
|
|
2831
|
+
react.useEffect(() => {
|
|
2832
|
+
const onKey = (e) => {
|
|
2833
|
+
if (e.key === "Escape") onCancel();
|
|
2834
|
+
};
|
|
2835
|
+
document.addEventListener("keydown", onKey);
|
|
2836
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
2837
|
+
}, [onCancel]);
|
|
2838
|
+
return react.createElement("div", { className: "ct-modal-root" }, react.createElement("div", {
|
|
2839
|
+
className: "ct-modal-mask",
|
|
2840
|
+
"aria-hidden": true,
|
|
2841
|
+
onClick: onCancel
|
|
2842
|
+
}), react.createElement("div", {
|
|
2843
|
+
className: "ct-modal-card",
|
|
2844
|
+
role: "dialog",
|
|
2845
|
+
"aria-modal": true,
|
|
2846
|
+
"aria-label": title
|
|
2847
|
+
}, react.createElement("div", { className: "ct-modal-title" }, title), react.createElement("div", { className: "ct-modal-desc" }, description), react.createElement("div", { className: "ct-modal-footer" }, react.createElement("button", {
|
|
2848
|
+
type: "button",
|
|
2849
|
+
className: "ct-btn",
|
|
2850
|
+
onClick: onCancel
|
|
2851
|
+
}, cancelLabel), react.createElement("button", {
|
|
2852
|
+
type: "button",
|
|
2853
|
+
className: "ct-btn ct-btn-danger",
|
|
2854
|
+
onClick: onConfirm
|
|
2855
|
+
}, confirmLabel))));
|
|
2856
|
+
}
|
|
2857
|
+
/** Which banner a failed roster call deserves. */
|
|
2858
|
+
function toastKeyFor(error) {
|
|
2859
|
+
return error instanceof ThemeApiUnavailableError ? "custom.toast.unavailable" : "custom.toast.failed";
|
|
2860
|
+
}
|
|
2861
|
+
/**
|
|
2862
|
+
* Transient confirmation banner: a leading result badge plus the copy, top
|
|
2863
|
+
* center, sliding in, holding, fading out, then reporting done so the owner can
|
|
2864
|
+
* unmount it. Metrics, tokens, badge and timing follow DSH's own toast — the
|
|
2865
|
+
* badge is the success circle its confirmations wear — but the component is
|
|
2866
|
+
* local: the plugin must keep answering a save on a host that does not share
|
|
2867
|
+
* the primitives module.
|
|
2868
|
+
*
|
|
2869
|
+
* TOAST_HOLD_MS and TOAST_FADE_MS have to agree with the `ct-toast` animation
|
|
2870
|
+
* in the injected stylesheet, which owns the visual timing.
|
|
2871
|
+
* @param props.text - resolved, already-localized copy.
|
|
2872
|
+
* @param props.onDone - called once the fade completes; unmount the toast here.
|
|
2873
|
+
*/
|
|
2874
|
+
function Toast(props) {
|
|
2875
|
+
const { text, onDone } = props;
|
|
2876
|
+
react.useEffect(() => {
|
|
2877
|
+
const timer = setTimeout(onDone, 4e3);
|
|
2878
|
+
return () => clearTimeout(timer);
|
|
2879
|
+
}, [onDone]);
|
|
2880
|
+
return react.createElement("div", {
|
|
2881
|
+
className: "ct-toast",
|
|
2882
|
+
role: "status"
|
|
2883
|
+
}, react.createElement(ToastBadge), react.createElement("span", { className: "ct-toast-text" }, text));
|
|
2884
|
+
}
|
|
2885
|
+
/** The leading badge every confirmation wears: a success ring around the check. */
|
|
2886
|
+
function ToastBadge() {
|
|
2887
|
+
return react.createElement("span", {
|
|
2888
|
+
className: "ct-toast-icon",
|
|
2889
|
+
"aria-hidden": true
|
|
2890
|
+
}, react.createElement(IconCheck, { size: 12 }));
|
|
2891
|
+
}
|
|
2892
|
+
/**
|
|
2893
|
+
* Plus glyph for the add button, path data taken verbatim from DSH's own
|
|
2894
|
+
* `IconPlusOutline16` so the two controls read as the same affordance.
|
|
2895
|
+
*/
|
|
2896
|
+
function IconPlus(props) {
|
|
2897
|
+
const { size = 14 } = props;
|
|
2898
|
+
return react.createElement("svg", {
|
|
2899
|
+
width: size,
|
|
2900
|
+
height: size,
|
|
2901
|
+
viewBox: "0 0 16 16",
|
|
2902
|
+
fill: "none",
|
|
2903
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2904
|
+
"aria-hidden": true,
|
|
2905
|
+
focusable: false
|
|
2906
|
+
}, react.createElement("path", {
|
|
2907
|
+
d: "M8.64453 1.5V7.34961H14.5V8.65039H8.64453V14.5H7.34473V8.65039H1.5V7.34961H7.34473V1.5H8.64453Z",
|
|
2908
|
+
fill: "currentColor"
|
|
2909
|
+
}));
|
|
2910
|
+
}
|
|
2911
|
+
/**
|
|
2912
|
+
* One collapsed saved-theme card: the name activates the theme, and the trailing
|
|
2913
|
+
* controls open the editor or delete it. The card as a whole is a click target
|
|
2914
|
+
* too, but its controls own their clicks.
|
|
2915
|
+
*/
|
|
2916
|
+
function ThemeCard(props) {
|
|
2917
|
+
const { entry, active, disabled, t, onActivate, onEdit, onDelete } = props;
|
|
2918
|
+
/** One dense capsule action; `danger` is the borderless delete variant. */
|
|
2919
|
+
const action = (label, onClick, danger) => react.createElement("button", {
|
|
2920
|
+
type: "button",
|
|
2921
|
+
className: danger ? "ct-list-btn ct-list-btn-danger" : "ct-list-btn",
|
|
2922
|
+
onClick
|
|
2923
|
+
}, label);
|
|
2924
|
+
return react.createElement("div", {
|
|
2925
|
+
className: "ct-list-row",
|
|
2926
|
+
onClick: disabled ? void 0 : onActivate
|
|
2927
|
+
}, react.createElement("span", { className: "ct-list-identity" }, react.createElement("button", {
|
|
2928
|
+
className: "ct-list-name",
|
|
2929
|
+
type: "button",
|
|
2930
|
+
disabled,
|
|
2931
|
+
onClick: (e) => {
|
|
2932
|
+
e.stopPropagation();
|
|
2933
|
+
onActivate();
|
|
2934
|
+
}
|
|
2935
|
+
}, entry.name)), react.createElement("div", {
|
|
2936
|
+
className: "ct-list-actions",
|
|
2937
|
+
onClick: (e) => e.stopPropagation()
|
|
2938
|
+
}, active ? react.createElement("span", { className: "ct-list-badge" }, t("custom.inUse")) : null, action(t("custom.edit"), onEdit), action(t("custom.delete"), onDelete, true)));
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* Which appearance the colour dots edit. `system` resolves through the same
|
|
2942
|
+
* media query the shell uses, so the editor opens on what is on screen.
|
|
2943
|
+
*/
|
|
2944
|
+
function effectiveMode(scheme) {
|
|
2945
|
+
if (scheme === "dark") return "dark";
|
|
2946
|
+
if (scheme === "light") return "light";
|
|
2947
|
+
try {
|
|
2948
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
2949
|
+
} catch {
|
|
2950
|
+
return "light";
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
1270
2953
|
function ThemePanel(props) {
|
|
1271
|
-
const { theme,
|
|
2954
|
+
const { theme, getSelection, setSelection, getCustom, setCustom, setCustomBase, resetCustom, saved, getHostToast, t, onRequestClose } = props;
|
|
1272
2955
|
let initScheme = "system";
|
|
1273
2956
|
try {
|
|
1274
2957
|
const snap = theme?.getTheme();
|
|
1275
2958
|
if (snap?.preference) initScheme = snap.preference;
|
|
1276
2959
|
} catch {}
|
|
1277
2960
|
const [scheme, setScheme] = react.useState(initScheme);
|
|
1278
|
-
const [
|
|
1279
|
-
|
|
2961
|
+
const [seedMode, setSeedMode] = react.useState(() => effectiveMode(initScheme));
|
|
2962
|
+
react.useEffect(() => {
|
|
2963
|
+
setSeedMode(effectiveMode(scheme));
|
|
2964
|
+
}, [scheme]);
|
|
2965
|
+
const [selection, setSelectionState] = react.useState(() => getSelection());
|
|
2966
|
+
const [custom, setCustomState] = react.useState(() => getCustom().theme);
|
|
2967
|
+
const [shownPreset, setShownPreset] = react.useState(() => {
|
|
2968
|
+
const initial = getSelection();
|
|
2969
|
+
return initial === CUSTOM_SELECTION ? getCustom().base : initial;
|
|
2970
|
+
});
|
|
2971
|
+
const [list, setList] = react.useState(() => saved.list());
|
|
2972
|
+
const [activeId, setActiveId] = react.useState(() => saved.activeId());
|
|
2973
|
+
const [pendingDelete, setPendingDelete] = react.useState(null);
|
|
2974
|
+
const [editing, setEditing] = react.useState(null);
|
|
2975
|
+
const [confirmClose, setConfirmClose] = react.useState(false);
|
|
2976
|
+
const [confirmLeave, setConfirmLeave] = react.useState(false);
|
|
2977
|
+
const editingRef = react.useRef(null);
|
|
2978
|
+
editingRef.current = editing;
|
|
2979
|
+
const savingRef = react.useRef(false);
|
|
2980
|
+
const schemeRef = react.useRef(scheme);
|
|
2981
|
+
schemeRef.current = scheme;
|
|
2982
|
+
const dirtyRef = react.useRef(false);
|
|
2983
|
+
dirtyRef.current = editing !== null && isDirty(editing, custom);
|
|
2984
|
+
const confirmCloseRef = react.useRef(false);
|
|
2985
|
+
confirmCloseRef.current = confirmClose;
|
|
2986
|
+
const confirmLeaveRef = react.useRef(false);
|
|
2987
|
+
confirmLeaveRef.current = confirmLeave;
|
|
2988
|
+
const pendingDeleteRef = react.useRef(null);
|
|
2989
|
+
pendingDeleteRef.current = pendingDelete;
|
|
2990
|
+
const [toast, setToast] = react.useState(null);
|
|
2991
|
+
const toastSeq = react.useRef(0);
|
|
2992
|
+
function showToast(text) {
|
|
2993
|
+
toastSeq.current += 1;
|
|
2994
|
+
setToast({
|
|
2995
|
+
seq: toastSeq.current,
|
|
2996
|
+
text
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
/** Re-read both the list and the active pointer after any list mutation. */
|
|
3000
|
+
function syncSaved() {
|
|
3001
|
+
setList(saved.list());
|
|
3002
|
+
setActiveId(saved.activeId());
|
|
3003
|
+
}
|
|
3004
|
+
react.useEffect(() => {
|
|
3005
|
+
let cancelled = false;
|
|
3006
|
+
saved.refresh().then(() => {
|
|
3007
|
+
if (!cancelled) syncSaved();
|
|
3008
|
+
}).catch((error) => {
|
|
3009
|
+
if (!cancelled) showToast(t(toastKeyFor(error)));
|
|
3010
|
+
});
|
|
3011
|
+
return () => {
|
|
3012
|
+
cancelled = true;
|
|
3013
|
+
};
|
|
3014
|
+
}, []);
|
|
3015
|
+
/** Run one roster mutation, surfacing a failed round trip as a banner. */
|
|
3016
|
+
async function mutate(operation) {
|
|
3017
|
+
try {
|
|
3018
|
+
return await operation();
|
|
3019
|
+
} catch (error) {
|
|
3020
|
+
showToast(t(toastKeyFor(error)));
|
|
3021
|
+
return null;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
function onLoadSaved(id) {
|
|
3025
|
+
const next = saved.load(id);
|
|
3026
|
+
if (next) setCustomState(next);
|
|
3027
|
+
syncSaved();
|
|
3028
|
+
}
|
|
3029
|
+
/** Snapshot the state an edit must return to when it is cancelled. */
|
|
3030
|
+
function beginEditing(id, name, originName, originTheme) {
|
|
3031
|
+
return {
|
|
3032
|
+
id,
|
|
3033
|
+
name,
|
|
3034
|
+
originId: saved.activeId(),
|
|
3035
|
+
originDraft: getCustom().theme,
|
|
3036
|
+
originName,
|
|
3037
|
+
originTheme,
|
|
3038
|
+
originScheme: schemeRef.current
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
3041
|
+
/** Commit an appearance preference, through the Theme service when it is there. */
|
|
3042
|
+
function applyAppearance(id) {
|
|
1280
3043
|
setScheme(id);
|
|
1281
3044
|
try {
|
|
1282
3045
|
theme?.setTheme(id);
|
|
1283
3046
|
} catch {}
|
|
1284
3047
|
}
|
|
3048
|
+
/**
|
|
3049
|
+
* Preview an appearance on the whole page while its colours are edited: a
|
|
3050
|
+
* custom theme carries both variants, so the other one's seeds are only
|
|
3051
|
+
* visible once the page actually wears that appearance. A no-op when the page
|
|
3052
|
+
* already resolves to `mode` — clicking the active half of the toggle must not
|
|
3053
|
+
* quietly turn a `system` preference into a pinned one.
|
|
3054
|
+
*/
|
|
3055
|
+
function previewAppearance(mode) {
|
|
3056
|
+
if (effectiveMode(schemeRef.current) === mode) return;
|
|
3057
|
+
applyAppearance(mode);
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* End a preview: put the appearance the editor opened on back. The preference
|
|
3061
|
+
* is a global setting the mode toggle only borrows, so it must not survive the
|
|
3062
|
+
* editor — not even on save, which commits the colours alone.
|
|
3063
|
+
*/
|
|
3064
|
+
function restoreAppearance(open) {
|
|
3065
|
+
if (schemeRef.current === open.originScheme) return;
|
|
3066
|
+
applyAppearance(open.originScheme);
|
|
3067
|
+
}
|
|
3068
|
+
/**
|
|
3069
|
+
* Undo an open (unsaved) edit: editing previews live and persists on every
|
|
3070
|
+
* change, so abandoning the card has to write the pre-edit theme back.
|
|
3071
|
+
*/
|
|
3072
|
+
function revertEditing(open) {
|
|
3073
|
+
restoreAppearance(open);
|
|
3074
|
+
if (open.originId) onLoadSaved(open.originId);
|
|
3075
|
+
else {
|
|
3076
|
+
setCustom(open.originDraft);
|
|
3077
|
+
setCustomState(open.originDraft);
|
|
3078
|
+
saved.setActive(null);
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
react.useEffect(() => () => {
|
|
3082
|
+
const open = editingRef.current;
|
|
3083
|
+
if (!open || savingRef.current) return;
|
|
3084
|
+
if (schemeRef.current !== open.originScheme) try {
|
|
3085
|
+
theme?.setTheme(open.originScheme);
|
|
3086
|
+
} catch {}
|
|
3087
|
+
if (open.originId) saved.load(open.originId);
|
|
3088
|
+
else {
|
|
3089
|
+
setCustom(open.originDraft);
|
|
3090
|
+
saved.setActive(null);
|
|
3091
|
+
}
|
|
3092
|
+
}, []);
|
|
3093
|
+
react.useEffect(() => {
|
|
3094
|
+
/** The header button carrying the `settings.close` seat, if `node` is in it. */
|
|
3095
|
+
function isCloseButton(node) {
|
|
3096
|
+
const seat = node.ownerDocument.querySelector("[data-slot=\"settings.close\"]");
|
|
3097
|
+
const button = node.closest("button");
|
|
3098
|
+
return !!seat && !!button && button.contains(seat);
|
|
3099
|
+
}
|
|
3100
|
+
/** The settings panel itself; the close seat is unique to it. */
|
|
3101
|
+
function settingsPanel() {
|
|
3102
|
+
return document.querySelector("[data-slot=\"settings.close\"]")?.closest("[role=\"dialog\"]") ?? null;
|
|
3103
|
+
}
|
|
3104
|
+
function onKeyDown(e) {
|
|
3105
|
+
if (e.key !== "Escape") return;
|
|
3106
|
+
if (confirmCloseRef.current || confirmLeaveRef.current) {
|
|
3107
|
+
e.preventDefault();
|
|
3108
|
+
e.stopPropagation();
|
|
3109
|
+
setConfirmClose(false);
|
|
3110
|
+
setConfirmLeave(false);
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
if (!dirtyRef.current || !onRequestClose) return;
|
|
3114
|
+
e.preventDefault();
|
|
3115
|
+
e.stopPropagation();
|
|
3116
|
+
setConfirmClose(true);
|
|
3117
|
+
}
|
|
3118
|
+
function onClick(e) {
|
|
3119
|
+
if (!dirtyRef.current || confirmCloseRef.current || confirmLeaveRef.current || pendingDeleteRef.current) return;
|
|
3120
|
+
const target = e.target instanceof Element ? e.target : null;
|
|
3121
|
+
if (!target) return;
|
|
3122
|
+
if (target.closest("[data-ct-editor]")) return;
|
|
3123
|
+
const panel = settingsPanel();
|
|
3124
|
+
if (!!panel && !panel.contains(target) || isCloseButton(target)) {
|
|
3125
|
+
if (!onRequestClose) return;
|
|
3126
|
+
e.preventDefault();
|
|
3127
|
+
e.stopPropagation();
|
|
3128
|
+
setConfirmClose(true);
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
if (!panel || !panel.contains(target)) return;
|
|
3132
|
+
e.preventDefault();
|
|
3133
|
+
e.stopPropagation();
|
|
3134
|
+
setConfirmLeave(true);
|
|
3135
|
+
}
|
|
3136
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
3137
|
+
document.addEventListener("click", onClick, true);
|
|
3138
|
+
return () => {
|
|
3139
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
3140
|
+
document.removeEventListener("click", onClick, true);
|
|
3141
|
+
};
|
|
3142
|
+
}, [onRequestClose]);
|
|
3143
|
+
/** Open a fresh, unsaved theme seeded from the currently selected preset. */
|
|
3144
|
+
function startAdd() {
|
|
3145
|
+
const origin = beginEditing(null, nextThemeName(t("custom.defaultName"), list.map((e) => e.name)), "", getCustom().theme);
|
|
3146
|
+
setCustomBase(shownPreset);
|
|
3147
|
+
const draft = resetCustom();
|
|
3148
|
+
setEditing(origin);
|
|
3149
|
+
setCustomState(draft);
|
|
3150
|
+
}
|
|
3151
|
+
/** Open an existing card for editing; it also becomes the previewed theme. */
|
|
3152
|
+
function startEdit(entry) {
|
|
3153
|
+
const next = beginEditing(entry.id, entry.name, entry.name, entry.theme);
|
|
3154
|
+
setEditing(next);
|
|
3155
|
+
onLoadSaved(entry.id);
|
|
3156
|
+
}
|
|
3157
|
+
/** Discard the open editor and put the previously applied theme back. */
|
|
3158
|
+
function cancelEdit() {
|
|
3159
|
+
if (!editing) return;
|
|
3160
|
+
revertEditing(editing);
|
|
3161
|
+
setEditing(null);
|
|
3162
|
+
syncSaved();
|
|
3163
|
+
}
|
|
3164
|
+
/** Commit the open editor: create a new entry, or update the one being edited. */
|
|
3165
|
+
async function saveEdit() {
|
|
3166
|
+
if (!editing) return;
|
|
3167
|
+
const name = editing.name.trim() || t("custom.defaultName");
|
|
3168
|
+
const id = editing.id;
|
|
3169
|
+
savingRef.current = true;
|
|
3170
|
+
const next = await mutate(() => id === null ? saved.create(name) : saved.update(id, name));
|
|
3171
|
+
savingRef.current = false;
|
|
3172
|
+
if (next === null) return;
|
|
3173
|
+
setEditing(null);
|
|
3174
|
+
restoreAppearance(editing);
|
|
3175
|
+
syncSaved();
|
|
3176
|
+
setCustomState(getCustom().theme);
|
|
3177
|
+
showToast(t("custom.toast.saved"));
|
|
3178
|
+
}
|
|
3179
|
+
async function onConfirmDelete() {
|
|
3180
|
+
if (!pendingDelete) return;
|
|
3181
|
+
const id = pendingDelete.id;
|
|
3182
|
+
setPendingDelete(null);
|
|
3183
|
+
setEditing((cur) => cur?.id === id ? null : cur);
|
|
3184
|
+
const next = await mutate(() => saved.remove(id));
|
|
3185
|
+
if (next === null) return;
|
|
3186
|
+
setActiveId(saved.activeId());
|
|
3187
|
+
setCustomState(getCustom().theme);
|
|
3188
|
+
setList(saved.list());
|
|
3189
|
+
if (next.length === 0) {
|
|
3190
|
+
setEditing(null);
|
|
3191
|
+
setCustomBase(shownPreset);
|
|
3192
|
+
setCustomState(resetCustom());
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
function pickScheme(id) {
|
|
3196
|
+
applyAppearance(id);
|
|
3197
|
+
setEditing((cur) => cur ? {
|
|
3198
|
+
...cur,
|
|
3199
|
+
originScheme: id
|
|
3200
|
+
} : cur);
|
|
3201
|
+
}
|
|
3202
|
+
/**
|
|
3203
|
+
* The preset picker. Unreachable while custom mode is on — the picker is
|
|
3204
|
+
* disabled then — so this only ever applies the chosen preset.
|
|
3205
|
+
*/
|
|
1285
3206
|
function pickPreset(id) {
|
|
1286
|
-
|
|
1287
|
-
|
|
3207
|
+
setSelectionState(id);
|
|
3208
|
+
setSelection(id);
|
|
3209
|
+
setShownPreset(id);
|
|
3210
|
+
}
|
|
3211
|
+
/**
|
|
3212
|
+
* The custom switch. Preset and custom are independent selections: turning
|
|
3213
|
+
* custom on leaves the preset row untouched, and turning it off goes back to
|
|
3214
|
+
* the preset the user had chosen, not to the custom theme's own base.
|
|
3215
|
+
*/
|
|
3216
|
+
function toggleCustom(on) {
|
|
3217
|
+
if (on) {
|
|
3218
|
+
setSelectionState(CUSTOM_SELECTION);
|
|
3219
|
+
setSelection(CUSTOM_SELECTION);
|
|
3220
|
+
setCustomState(getCustom().theme);
|
|
3221
|
+
return;
|
|
3222
|
+
}
|
|
3223
|
+
if (editing) revertEditing(editing);
|
|
3224
|
+
setEditing(null);
|
|
3225
|
+
setSelectionState(shownPreset);
|
|
3226
|
+
setSelection(shownPreset);
|
|
3227
|
+
setShownPreset(shownPreset);
|
|
3228
|
+
}
|
|
3229
|
+
function editCustom(next) {
|
|
3230
|
+
setCustomState(next);
|
|
3231
|
+
setCustom(next);
|
|
1288
3232
|
}
|
|
1289
3233
|
const schemeOptions = [
|
|
1290
3234
|
{
|
|
@@ -1300,20 +3244,227 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1300
3244
|
label: t("scheme.system")
|
|
1301
3245
|
}
|
|
1302
3246
|
];
|
|
3247
|
+
const customOn = selection === CUSTOM_SELECTION;
|
|
3248
|
+
const children = [
|
|
3249
|
+
react.createElement("div", {
|
|
3250
|
+
className: "ct-row",
|
|
3251
|
+
key: "appearance"
|
|
3252
|
+
}, react.createElement("div", { className: "ct-row-main" }, react.createElement("div", { className: "ct-row-title" }, t("appearance.title")), react.createElement("div", { className: "ct-row-desc" }, t("appearance.desc"))), react.createElement(SchemeMenu, {
|
|
3253
|
+
value: scheme,
|
|
3254
|
+
options: schemeOptions,
|
|
3255
|
+
onSelect: pickScheme
|
|
3256
|
+
})),
|
|
3257
|
+
react.createElement("div", {
|
|
3258
|
+
className: "ct-row",
|
|
3259
|
+
key: "presets"
|
|
3260
|
+
}, react.createElement("div", { className: "ct-row-main" }, react.createElement("div", { className: "ct-row-title" }, t("presets.title")), react.createElement("div", { className: "ct-row-desc" }, t(customOn ? "presets.disabled" : "presets.desc"))), react.createElement(SchemeMenu, {
|
|
3261
|
+
value: customOn ? shownPreset : selection,
|
|
3262
|
+
options: presetOptions,
|
|
3263
|
+
onSelect: (v) => pickPreset(v),
|
|
3264
|
+
disabled: customOn
|
|
3265
|
+
})),
|
|
3266
|
+
react.createElement("div", {
|
|
3267
|
+
className: "ct-row ct-row-flush",
|
|
3268
|
+
key: "custom-toggle"
|
|
3269
|
+
}, react.createElement("div", { className: "ct-row-main" }, react.createElement("div", { className: "ct-row-title" }, t("custom.title")), react.createElement("div", { className: "ct-row-desc" }, t("custom.toggle.desc"))), react.createElement(Switch, {
|
|
3270
|
+
checked: customOn,
|
|
3271
|
+
label: t("custom.title"),
|
|
3272
|
+
onChange: toggleCustom
|
|
3273
|
+
}))
|
|
3274
|
+
];
|
|
3275
|
+
if (customOn) {
|
|
3276
|
+
/** A group row: its name on the left, every seed's dot on the right. */
|
|
3277
|
+
const dotRow = (key, label, dots) => react.createElement("div", {
|
|
3278
|
+
className: "ct-seed-row",
|
|
3279
|
+
key
|
|
3280
|
+
}, react.createElement("div", { className: "ct-seed-label" }, label), react.createElement("div", { className: "ct-seed-dots" }, ...dots.map((d) => react.createElement("label", {
|
|
3281
|
+
key: d.key,
|
|
3282
|
+
className: "ct-seed-dot",
|
|
3283
|
+
style: { background: d.value },
|
|
3284
|
+
"data-tip": d.name
|
|
3285
|
+
}, react.createElement("input", {
|
|
3286
|
+
className: "ct-seed-input",
|
|
3287
|
+
type: "color",
|
|
3288
|
+
value: d.value,
|
|
3289
|
+
"aria-label": `${d.name} — ${d.hint}`,
|
|
3290
|
+
onChange: (e) => d.onChange(e.target.value.toUpperCase())
|
|
3291
|
+
})))));
|
|
3292
|
+
const pair = (key, title, desc) => ({
|
|
3293
|
+
key,
|
|
3294
|
+
name: t(title),
|
|
3295
|
+
hint: t(desc),
|
|
3296
|
+
value: custom[key][seedMode],
|
|
3297
|
+
onChange: (v) => editCustom({
|
|
3298
|
+
...custom,
|
|
3299
|
+
[key]: {
|
|
3300
|
+
...custom[key],
|
|
3301
|
+
[seedMode]: v
|
|
3302
|
+
}
|
|
3303
|
+
})
|
|
3304
|
+
});
|
|
3305
|
+
const neutralDots = NEUTRAL_ROLES.map((role) => {
|
|
3306
|
+
const end = neutralEndForRole(seedMode, role);
|
|
3307
|
+
return {
|
|
3308
|
+
key: `neutral-${end}`,
|
|
3309
|
+
name: t(role === "background" ? "custom.neutral.roleBackground" : "custom.neutral.roleForeground"),
|
|
3310
|
+
hint: `${t("custom.neutral.title")} · ${t("custom.neutral.desc")} — ${t(end === "lightest" ? "custom.neutral.lightest" : "custom.neutral.darkest")}`,
|
|
3311
|
+
value: custom.neutral[seedMode][end],
|
|
3312
|
+
onChange: (v) => editCustom({
|
|
3313
|
+
...custom,
|
|
3314
|
+
neutral: {
|
|
3315
|
+
...custom.neutral,
|
|
3316
|
+
[seedMode]: {
|
|
3317
|
+
...custom.neutral[seedMode],
|
|
3318
|
+
[end]: v
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
})
|
|
3322
|
+
};
|
|
3323
|
+
});
|
|
3324
|
+
const seedDots = [
|
|
3325
|
+
pair("accent", "custom.accent.title", "custom.accent.desc"),
|
|
3326
|
+
...neutralDots,
|
|
3327
|
+
pair("green", "custom.green.title", "custom.green.desc"),
|
|
3328
|
+
pair("amber", "custom.amber.title", "custom.amber.desc"),
|
|
3329
|
+
pair("red", "custom.red.title", "custom.red.desc")
|
|
3330
|
+
];
|
|
3331
|
+
const shikiDots = SHIKI_KEYS.map((k) => ({
|
|
3332
|
+
key: k,
|
|
3333
|
+
name: t(`shiki.${k}`),
|
|
3334
|
+
hint: t("custom.shiki.desc"),
|
|
3335
|
+
value: custom.shiki[k][seedMode],
|
|
3336
|
+
onChange: (v) => editCustom({
|
|
3337
|
+
...custom,
|
|
3338
|
+
shiki: {
|
|
3339
|
+
...custom.shiki,
|
|
3340
|
+
[k]: {
|
|
3341
|
+
...custom.shiki[k],
|
|
3342
|
+
[seedMode]: v
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
})
|
|
3346
|
+
}));
|
|
3347
|
+
/** The light/dark segmented control above the dots. */
|
|
3348
|
+
const modeButton = (id, label) => react.createElement("button", {
|
|
3349
|
+
key: id,
|
|
3350
|
+
type: "button",
|
|
3351
|
+
className: seedMode === id ? "ct-mode-btn ct-mode-btn-on" : "ct-mode-btn",
|
|
3352
|
+
"aria-pressed": seedMode === id,
|
|
3353
|
+
onClick: () => {
|
|
3354
|
+
setSeedMode(id);
|
|
3355
|
+
previewAppearance(id);
|
|
3356
|
+
}
|
|
3357
|
+
}, label);
|
|
3358
|
+
const modeToggle = react.createElement("div", {
|
|
3359
|
+
className: "ct-mode",
|
|
3360
|
+
role: "group",
|
|
3361
|
+
"aria-label": t("custom.mode.label")
|
|
3362
|
+
}, modeButton("light", t("custom.seed.light")), modeButton("dark", t("custom.seed.dark")));
|
|
3363
|
+
const editorName = react.createElement("input", {
|
|
3364
|
+
className: "ct-editor-name",
|
|
3365
|
+
type: "text",
|
|
3366
|
+
value: editing?.name ?? "",
|
|
3367
|
+
placeholder: t("custom.name.placeholder"),
|
|
3368
|
+
"aria-label": t("custom.name.placeholder"),
|
|
3369
|
+
autoFocus: true,
|
|
3370
|
+
onChange: (e) => setEditing((cur) => cur ? {
|
|
3371
|
+
...cur,
|
|
3372
|
+
name: e.target.value
|
|
3373
|
+
} : cur),
|
|
3374
|
+
onKeyDown: (e) => {
|
|
3375
|
+
if (e.key === "Enter") saveEdit();
|
|
3376
|
+
else if (e.key === "Escape") cancelEdit();
|
|
3377
|
+
}
|
|
3378
|
+
});
|
|
3379
|
+
const editorActions = react.createElement("div", { className: "ct-editor-actions" }, react.createElement("button", {
|
|
3380
|
+
type: "button",
|
|
3381
|
+
className: "ct-btn",
|
|
3382
|
+
onClick: cancelEdit
|
|
3383
|
+
}, t("custom.cancel")), react.createElement("button", {
|
|
3384
|
+
type: "button",
|
|
3385
|
+
className: "ct-btn ct-btn-primary",
|
|
3386
|
+
onClick: () => void saveEdit()
|
|
3387
|
+
}, t("custom.save")));
|
|
3388
|
+
const editorCard = (key) => react.createElement("div", {
|
|
3389
|
+
className: "ct-editor",
|
|
3390
|
+
key,
|
|
3391
|
+
"data-ct-editor": "true"
|
|
3392
|
+
}, react.createElement("div", { className: "ct-editor-head" }, editorName, modeToggle), dotRow("seeds", t("custom.group.seeds"), seedDots), dotRow("shiki", t("custom.group.shiki"), shikiDots), editorActions);
|
|
3393
|
+
const cards = list.map((entry) => editing && editing.id === entry.id ? editorCard(entry.id) : react.createElement(ThemeCard, {
|
|
3394
|
+
key: entry.id,
|
|
3395
|
+
entry,
|
|
3396
|
+
active: activeId === entry.id,
|
|
3397
|
+
disabled: editing !== null,
|
|
3398
|
+
t,
|
|
3399
|
+
onActivate: () => onLoadSaved(entry.id),
|
|
3400
|
+
onEdit: () => startEdit(entry),
|
|
3401
|
+
onDelete: () => setPendingDelete(entry)
|
|
3402
|
+
}));
|
|
3403
|
+
if (editing && editing.id === null) cards.push(editorCard("new-editor"));
|
|
3404
|
+
children.push(react.createElement("div", {
|
|
3405
|
+
className: "ct-list",
|
|
3406
|
+
key: "saved-list"
|
|
3407
|
+
}, ...cards), react.createElement("button", {
|
|
3408
|
+
key: "add",
|
|
3409
|
+
type: "button",
|
|
3410
|
+
className: "ct-add-btn",
|
|
3411
|
+
disabled: editing !== null,
|
|
3412
|
+
onClick: startAdd
|
|
3413
|
+
}, react.createElement(IconPlus, null), t("custom.add")));
|
|
3414
|
+
}
|
|
3415
|
+
if (pendingDelete) children.push(react.createElement(ConfirmDialog, {
|
|
3416
|
+
key: "confirm-delete",
|
|
3417
|
+
title: t("custom.delete.title"),
|
|
3418
|
+
description: t("custom.delete.desc").replace("{0}", pendingDelete.name),
|
|
3419
|
+
confirmLabel: t("custom.delete"),
|
|
3420
|
+
cancelLabel: t("custom.cancel"),
|
|
3421
|
+
onConfirm: onConfirmDelete,
|
|
3422
|
+
onCancel: () => setPendingDelete(null)
|
|
3423
|
+
}));
|
|
3424
|
+
if (confirmClose && editing && onRequestClose) children.push(react.createElement(ConfirmDialog, {
|
|
3425
|
+
key: "confirm-close",
|
|
3426
|
+
title: t("custom.unsaved.title"),
|
|
3427
|
+
description: t("custom.unsaved.desc").replace("{0}", editing.name.trim() || t("custom.defaultName")),
|
|
3428
|
+
confirmLabel: t("custom.unsaved.confirm"),
|
|
3429
|
+
cancelLabel: t("custom.unsaved.cancel"),
|
|
3430
|
+
onConfirm: () => {
|
|
3431
|
+
setConfirmClose(false);
|
|
3432
|
+
onRequestClose();
|
|
3433
|
+
},
|
|
3434
|
+
onCancel: () => setConfirmClose(false)
|
|
3435
|
+
}));
|
|
3436
|
+
if (confirmLeave && editing) children.push(react.createElement(ConfirmDialog, {
|
|
3437
|
+
key: "confirm-leave",
|
|
3438
|
+
title: t("custom.unsaved.title"),
|
|
3439
|
+
description: t("custom.unsaved.leaveDesc").replace("{0}", editing.name.trim() || t("custom.defaultName")),
|
|
3440
|
+
confirmLabel: t("custom.unsaved.leaveConfirm"),
|
|
3441
|
+
cancelLabel: t("custom.unsaved.cancel"),
|
|
3442
|
+
onConfirm: () => {
|
|
3443
|
+
setConfirmLeave(false);
|
|
3444
|
+
cancelEdit();
|
|
3445
|
+
},
|
|
3446
|
+
onCancel: () => setConfirmLeave(false)
|
|
3447
|
+
}));
|
|
3448
|
+
if (toast) {
|
|
3449
|
+
const onDone = () => setToast((cur) => cur?.seq === toast.seq ? null : cur);
|
|
3450
|
+
const HostToast = getHostToast();
|
|
3451
|
+
children.push(HostToast ? react.createElement(HostToast, {
|
|
3452
|
+
key: `toast-${String(toast.seq)}`,
|
|
3453
|
+
text: toast.text,
|
|
3454
|
+
icon: react.createElement(ToastBadge),
|
|
3455
|
+
onDone
|
|
3456
|
+
}) : react.createElement(Toast, {
|
|
3457
|
+
key: `toast-${String(toast.seq)}`,
|
|
3458
|
+
text: toast.text,
|
|
3459
|
+
onDone
|
|
3460
|
+
}));
|
|
3461
|
+
}
|
|
1303
3462
|
return react.createElement("div", { style: {
|
|
1304
3463
|
display: "flex",
|
|
1305
3464
|
flexDirection: "column",
|
|
1306
3465
|
maxWidth: 760,
|
|
1307
3466
|
paddingBottom: 8
|
|
1308
|
-
} },
|
|
1309
|
-
value: scheme,
|
|
1310
|
-
options: schemeOptions,
|
|
1311
|
-
onSelect: pickScheme
|
|
1312
|
-
})), react.createElement("div", { className: "ct-row" }, react.createElement("div", { className: "ct-row-main" }, react.createElement("div", { className: "ct-row-title" }, t("presets.title")), react.createElement("div", { className: "ct-row-desc" }, t("presets.desc"))), react.createElement(SchemeMenu, {
|
|
1313
|
-
value: active,
|
|
1314
|
-
options: presetOptions,
|
|
1315
|
-
onSelect: (v) => pickPreset(v)
|
|
1316
|
-
})));
|
|
3467
|
+
} }, ...children);
|
|
1317
3468
|
}
|
|
1318
3469
|
//#endregion
|
|
1319
3470
|
//#region src/client/locales.ts
|
|
@@ -1329,9 +3480,60 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1329
3480
|
"appearance.desc": "深色 / 浅色 / 跟随系统",
|
|
1330
3481
|
"presets.title": "预设主题",
|
|
1331
3482
|
"presets.desc": "一键套用主流配色方案",
|
|
3483
|
+
"presets.disabled": "自定义主题已启用,关闭后才能选择预设",
|
|
1332
3484
|
"scheme.light": "浅色",
|
|
1333
3485
|
"scheme.dark": "深色",
|
|
1334
|
-
"scheme.system": "跟随系统"
|
|
3486
|
+
"scheme.system": "跟随系统",
|
|
3487
|
+
"custom.title": "自定义主题",
|
|
3488
|
+
"custom.toggle.desc": "创建属于自己的个性化主题",
|
|
3489
|
+
"custom.group.seeds": "主色/辅助色",
|
|
3490
|
+
"custom.group.shiki": "代码块",
|
|
3491
|
+
"custom.mode.label": "编辑的外观",
|
|
3492
|
+
"custom.neutral.title": "中性色",
|
|
3493
|
+
"custom.neutral.desc": "界面底色与正文。浅色与深色各一条色阶",
|
|
3494
|
+
"custom.neutral.lightest": "最浅色端",
|
|
3495
|
+
"custom.neutral.darkest": "最深色端",
|
|
3496
|
+
"custom.neutral.roleBackground": "背景色",
|
|
3497
|
+
"custom.neutral.roleForeground": "前景色",
|
|
3498
|
+
"custom.accent.title": "主色",
|
|
3499
|
+
"custom.accent.desc": "按钮与强调色(deepseek 与 blue 合并为一组)",
|
|
3500
|
+
"custom.green.title": "成功",
|
|
3501
|
+
"custom.green.desc": "成功状态",
|
|
3502
|
+
"custom.amber.title": "警告",
|
|
3503
|
+
"custom.amber.desc": "警告状态",
|
|
3504
|
+
"custom.red.title": "错误",
|
|
3505
|
+
"custom.red.desc": "错误状态",
|
|
3506
|
+
"custom.shiki.desc": "9 个语法标记的颜色",
|
|
3507
|
+
"custom.seed.light": "浅色",
|
|
3508
|
+
"custom.seed.dark": "深色",
|
|
3509
|
+
"custom.save": "保存",
|
|
3510
|
+
"custom.add": "添加自定义主题",
|
|
3511
|
+
"custom.edit": "编辑",
|
|
3512
|
+
"custom.name.placeholder": "主题名称",
|
|
3513
|
+
"custom.defaultName": "自定义主题",
|
|
3514
|
+
"custom.inUse": "使用中",
|
|
3515
|
+
"custom.delete": "删除",
|
|
3516
|
+
"custom.cancel": "取消",
|
|
3517
|
+
"custom.toast.saved": "已保存",
|
|
3518
|
+
"custom.toast.failed": "主题文件操作失败",
|
|
3519
|
+
"custom.toast.unavailable": "主题文件接口未就绪,请重启 DSH 服务",
|
|
3520
|
+
"custom.delete.title": "删除该自定义主题?",
|
|
3521
|
+
"custom.delete.desc": "将删除「{0}」,且无法恢复。",
|
|
3522
|
+
"custom.unsaved.title": "放弃未保存的修改?",
|
|
3523
|
+
"custom.unsaved.desc": "「{0}」的修改尚未保存,关闭设置后将丢失。",
|
|
3524
|
+
"custom.unsaved.confirm": "放弃并关闭",
|
|
3525
|
+
"custom.unsaved.leaveDesc": "「{0}」的修改尚未保存,是否确认放弃?",
|
|
3526
|
+
"custom.unsaved.leaveConfirm": "放弃修改",
|
|
3527
|
+
"custom.unsaved.cancel": "继续编辑",
|
|
3528
|
+
"shiki.constant": "常量",
|
|
3529
|
+
"shiki.string": "字符串",
|
|
3530
|
+
"shiki.comment": "注释",
|
|
3531
|
+
"shiki.keyword": "关键字",
|
|
3532
|
+
"shiki.parameter": "参数",
|
|
3533
|
+
"shiki.function": "函数",
|
|
3534
|
+
"shiki.string-expression": "模板字符串",
|
|
3535
|
+
"shiki.punctuation": "标点",
|
|
3536
|
+
"shiki.link": "链接"
|
|
1335
3537
|
};
|
|
1336
3538
|
/** English dictionary, checked complete against the zh key set. */
|
|
1337
3539
|
const en = {
|
|
@@ -1340,33 +3542,160 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1340
3542
|
"appearance.desc": "Dark / Light / System",
|
|
1341
3543
|
"presets.title": "Preset themes",
|
|
1342
3544
|
"presets.desc": "Apply popular color schemes in one click",
|
|
3545
|
+
"presets.disabled": "Custom theme is on — turn it off to choose a preset",
|
|
1343
3546
|
"scheme.light": "Light",
|
|
1344
3547
|
"scheme.dark": "Dark",
|
|
1345
|
-
"scheme.system": "System"
|
|
3548
|
+
"scheme.system": "System",
|
|
3549
|
+
"custom.title": "Custom theme",
|
|
3550
|
+
"custom.toggle.desc": "Create your own personalized theme",
|
|
3551
|
+
"custom.group.seeds": "Primary/supporting",
|
|
3552
|
+
"custom.group.shiki": "Code block",
|
|
3553
|
+
"custom.mode.label": "Appearance being edited",
|
|
3554
|
+
"custom.neutral.title": "Neutral",
|
|
3555
|
+
"custom.neutral.desc": "Surfaces and body text. One ramp per appearance",
|
|
3556
|
+
"custom.neutral.lightest": "Lightest end",
|
|
3557
|
+
"custom.neutral.darkest": "Darkest end",
|
|
3558
|
+
"custom.neutral.roleBackground": "Background",
|
|
3559
|
+
"custom.neutral.roleForeground": "Foreground",
|
|
3560
|
+
"custom.accent.title": "Accent",
|
|
3561
|
+
"custom.accent.desc": "Buttons and emphasis (deepseek and blue merged into one)",
|
|
3562
|
+
"custom.green.title": "Success",
|
|
3563
|
+
"custom.green.desc": "Success states",
|
|
3564
|
+
"custom.amber.title": "Warning",
|
|
3565
|
+
"custom.amber.desc": "Warning states",
|
|
3566
|
+
"custom.red.title": "Error",
|
|
3567
|
+
"custom.red.desc": "Error states",
|
|
3568
|
+
"custom.shiki.desc": "Colors for the nine syntax tokens",
|
|
3569
|
+
"custom.seed.light": "Light",
|
|
3570
|
+
"custom.seed.dark": "Dark",
|
|
3571
|
+
"custom.save": "Save",
|
|
3572
|
+
"custom.add": "Add custom theme",
|
|
3573
|
+
"custom.edit": "Edit",
|
|
3574
|
+
"custom.name.placeholder": "Theme name",
|
|
3575
|
+
"custom.defaultName": "Custom theme",
|
|
3576
|
+
"custom.inUse": "In use",
|
|
3577
|
+
"custom.delete": "Delete",
|
|
3578
|
+
"custom.cancel": "Cancel",
|
|
3579
|
+
"custom.toast.saved": "Saved",
|
|
3580
|
+
"custom.toast.failed": "Theme file operation failed",
|
|
3581
|
+
"custom.toast.unavailable": "Theme file API not ready — restart the DSH service",
|
|
3582
|
+
"custom.delete.title": "Delete this custom theme?",
|
|
3583
|
+
"custom.delete.desc": "\"{0}\" will be removed. This cannot be undone.",
|
|
3584
|
+
"custom.unsaved.title": "Discard unsaved changes?",
|
|
3585
|
+
"custom.unsaved.desc": "Changes to \"{0}\" have not been saved and will be lost when settings close.",
|
|
3586
|
+
"custom.unsaved.confirm": "Discard and close",
|
|
3587
|
+
"custom.unsaved.leaveDesc": "Changes to \"{0}\" have not been saved. Discard them?",
|
|
3588
|
+
"custom.unsaved.leaveConfirm": "Discard changes",
|
|
3589
|
+
"custom.unsaved.cancel": "Keep editing",
|
|
3590
|
+
"shiki.constant": "Constant",
|
|
3591
|
+
"shiki.string": "String",
|
|
3592
|
+
"shiki.comment": "Comment",
|
|
3593
|
+
"shiki.keyword": "Keyword",
|
|
3594
|
+
"shiki.parameter": "Parameter",
|
|
3595
|
+
"shiki.function": "Function",
|
|
3596
|
+
"shiki.string-expression": "Template string",
|
|
3597
|
+
"shiki.punctuation": "Punctuation",
|
|
3598
|
+
"shiki.link": "Link"
|
|
1346
3599
|
};
|
|
1347
3600
|
//#endregion
|
|
1348
3601
|
//#region src/client/theme.tsx
|
|
1349
3602
|
const BASE_CSS = [
|
|
1350
3603
|
".ct-select{box-sizing:border-box;display:inline-flex;align-items:center;gap:12px;height:36px;padding:0 14px;border:none;border-radius:18px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:14px;line-height:22px;white-space:nowrap;width:auto;min-width:0;max-width:100%;}",
|
|
1351
3604
|
".ct-select:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3605
|
+
".ct-select:disabled{opacity:.5;cursor:not-allowed;}",
|
|
1352
3606
|
".ct-select:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
1353
3607
|
".ct-select-label{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;}",
|
|
1354
3608
|
".ct-select-chevron{flex:none;color:var(--dsw-alias-label-tertiary);display:inline-flex;transition:transform 120ms ease;}",
|
|
1355
3609
|
".ct-select[aria-expanded=\"true\"] .ct-select-chevron{transform:rotate(180deg);}",
|
|
1356
|
-
".ct-menu-list{box-sizing:border-box;padding:4px;display:flex;flex-direction:column;gap:0;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);min-width:218px;max-width:360px;}",
|
|
3610
|
+
".ct-menu-list{box-sizing:border-box;padding:4px;display:flex;flex-direction:column;gap:0;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);min-width:218px;max-width:360px;max-height:min(320px,50vh);overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l2) transparent;scrollbar-gutter:stable;}",
|
|
3611
|
+
".ct-menu-list:not(:hover){scrollbar-color:transparent transparent;}",
|
|
3612
|
+
".ct-menu-list::-webkit-scrollbar{width:8px;height:8px;}",
|
|
3613
|
+
".ct-menu-list::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l2);border-radius:999px;border:2px solid var(--dsw-specific-menu);background-clip:content-box;transition:background 150ms ease, border-color 150ms ease;}",
|
|
3614
|
+
".ct-menu-list::-webkit-scrollbar-thumb:hover{background:var(--dsw-alias-label-tertiary);border:2px solid var(--dsw-specific-menu);background-clip:content-box;}",
|
|
3615
|
+
".ct-menu-list::-webkit-scrollbar-thumb:active{background:var(--dsw-alias-label-secondary, var(--dsw-alias-label-tertiary));border:2px solid var(--dsw-specific-menu);background-clip:content-box;}",
|
|
3616
|
+
".ct-menu-list:not(:hover)::-webkit-scrollbar-thumb{background:transparent;border-color:transparent;}",
|
|
3617
|
+
".ct-menu-list::-webkit-scrollbar-track{background:transparent;margin:4px 0;}",
|
|
3618
|
+
".ct-menu-list::-webkit-scrollbar-corner{background:transparent;}",
|
|
1357
3619
|
".ct-menu-item{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:none;border-radius:10px;background:transparent;cursor:pointer;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);text-align:left;font-family:inherit;}",
|
|
1358
3620
|
".ct-menu-item:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);}",
|
|
1359
3621
|
".ct-menu-check{flex:none;color:var(--dsw-alias-label-primary);display:inline-flex;margin-left:auto;}",
|
|
1360
3622
|
".ct-menu-item-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1361
3623
|
".ct-row{border-bottom:1px solid var(--dsw-alias-border-l2);padding:16px 2px;display:flex;align-items:center;gap:16px;}",
|
|
1362
3624
|
".ct-row:last-child{border-bottom:none;}",
|
|
3625
|
+
".ct-row-flush{border-bottom:none;}",
|
|
1363
3626
|
".ct-row-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;padding-right:48px;}",
|
|
1364
3627
|
".ct-row-title{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px;}",
|
|
1365
|
-
".ct-row-desc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px;}"
|
|
3628
|
+
".ct-row-desc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px;}",
|
|
3629
|
+
".ct-seed-row{display:flex;align-items:center;gap:16px;padding:12px 0;}",
|
|
3630
|
+
".ct-seed-label{flex:0 0 auto;min-width:96px;padding-left:3px;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);}",
|
|
3631
|
+
".ct-seed-dots{flex:1 1 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:10px;}",
|
|
3632
|
+
".ct-seed-dot{position:relative;box-sizing:border-box;display:inline-block;flex:none;width:26px;height:26px;border:1px solid var(--dsw-alias-border-l2);border-radius:50%;cursor:pointer;}",
|
|
3633
|
+
".ct-seed-input{position:absolute;inset:0;box-sizing:border-box;width:100%;height:100%;padding:0;border:none;background:transparent;opacity:0;cursor:pointer;}",
|
|
3634
|
+
".ct-seed-dot:focus-within{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3635
|
+
".ct-seed-dot::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 7px);left:50%;z-index:20;transform:translateX(-50%);padding:3px 8px;border-radius:6px;background:var(--dsw-alias-label-primary,#151517);color:var(--dsw-alias-bg-layer-3,#fff);font-size:11px;font-weight:400;line-height:17px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;}",
|
|
3636
|
+
".ct-seed-dot:hover::after,.ct-seed-dot:focus-within::after{opacity:1;}",
|
|
3637
|
+
".ct-list{margin-top:4px;display:flex;flex-direction:column;gap:8px;}",
|
|
3638
|
+
".ct-list-row{display:flex;align-items:center;gap:10px;padding:12px 14px;border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:transparent;cursor:pointer;transition:border-color .16s ease,background .16s ease;}",
|
|
3639
|
+
".ct-list-row:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3640
|
+
".ct-list-identity{display:inline-flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;}",
|
|
3641
|
+
".ct-list-name{min-width:0;text-align:left;border:none;background:transparent;cursor:pointer;font:inherit;font-size:14px;line-height:22px;font-weight:500;color:var(--dsw-alias-label-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:0;}",
|
|
3642
|
+
".ct-list-name:disabled{cursor:default;}",
|
|
3643
|
+
".ct-list-actions{display:inline-flex;align-items:center;gap:4px;flex:none;margin-left:auto;}",
|
|
3644
|
+
".ct-list-badge{display:inline-flex;align-items:center;height:28px;padding:0 10px;border-radius:14px;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary));font-size:12px;line-height:18px;white-space:nowrap;}",
|
|
3645
|
+
".ct-list-btn{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;height:28px;padding:0 10px;border:.5px solid var(--dsw-alias-border-l3);border-radius:14px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:12px;line-height:18px;}",
|
|
3646
|
+
".ct-list-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3647
|
+
".ct-list-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3648
|
+
".ct-list-btn-danger{border:none;color:var(--dsw-alias-state-error-primary);}",
|
|
3649
|
+
".ct-list-btn-danger:hover{background:var(--dsw-alias-interactive-bg-hover-danger);}",
|
|
3650
|
+
".ct-editor{padding:16px;border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:transparent;display:flex;flex-direction:column;gap:0;}",
|
|
3651
|
+
".ct-editor-head{display:flex;align-items:center;gap:10px;padding-bottom:12px;}",
|
|
3652
|
+
".ct-editor-name{flex:1 1 auto;min-width:0;box-sizing:border-box;height:36px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;}",
|
|
3653
|
+
".ct-editor-name::placeholder{color:var(--dsw-alias-label-tertiary);}",
|
|
3654
|
+
".ct-editor-name:hover{border-color:var(--dsw-alias-border-l3);}",
|
|
3655
|
+
".ct-editor-name:focus{outline:none;border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-bg-base);}",
|
|
3656
|
+
".ct-mode{box-sizing:border-box;display:inline-flex;flex:none;height:36px;padding:2px;border-radius:10px;background:var(--dsw-alias-bg-module-platform,var(--dsw-alias-bg-layer-2));}",
|
|
3657
|
+
".ct-mode-btn{box-sizing:border-box;height:32px;padding:0 10px;border:none;border-radius:8px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;font:inherit;font-size:12px;line-height:18px;}",
|
|
3658
|
+
".ct-mode-btn:hover{color:var(--dsw-alias-label-primary);}",
|
|
3659
|
+
".ct-mode-btn-on{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);}",
|
|
3660
|
+
".ct-mode-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3661
|
+
".ct-editor-actions{display:flex;justify-content:flex-end;gap:12px;padding-top:12px;}",
|
|
3662
|
+
".ct-add-btn{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:6px;width:100%;height:44px;margin-top:8px;padding:0 14px;border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:14px;line-height:22px;}",
|
|
3663
|
+
".ct-add-btn:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3664
|
+
".ct-add-btn:disabled{opacity:.4;cursor:default;}",
|
|
3665
|
+
".ct-add-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3666
|
+
".ct-modal-root{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;}",
|
|
3667
|
+
".ct-modal-mask{position:absolute;inset:0;background:var(--dsw-alias-bg-mask-1,rgba(0,0,0,.24));backdrop-filter:var(--dsw-mask-blur,blur(2px));}",
|
|
3668
|
+
".ct-modal-card{position:relative;z-index:1;display:flex;flex-direction:column;gap:12px;width:min(380px,100%);padding:24px;border-radius:24px;background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-elevation-prominent);}",
|
|
3669
|
+
".ct-modal-title{font-size:16px;line-height:24px;font-weight:600;color:var(--dsw-alias-label-primary);}",
|
|
3670
|
+
".ct-modal-desc{font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary);}",
|
|
3671
|
+
".ct-modal-footer{display:flex;justify-content:flex-end;gap:12px;margin-top:12px;}",
|
|
3672
|
+
".ct-switch{position:relative;flex:none;width:40px;height:24px;padding:0;border:none;border-radius:12px;background:var(--dsw-alias-border-l2);cursor:pointer;transition:background 150ms ease;}",
|
|
3673
|
+
".ct-switch-on{background:var(--dsw-static-deepseek-500,rgb(65,118,230));}",
|
|
3674
|
+
".ct-switch-knob{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform 150ms ease;}",
|
|
3675
|
+
".ct-switch-on .ct-switch-knob{transform:translateX(16px);}",
|
|
3676
|
+
".ct-switch:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3677
|
+
".ct-btn{box-sizing:border-box;display:inline-flex;align-items:center;height:34px;padding:0 16px;border:1px solid var(--dsw-alias-border-l2);border-radius:17px;background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:13px;line-height:20px;}",
|
|
3678
|
+
".ct-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3679
|
+
".ct-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3);}",
|
|
3680
|
+
".ct-btn-primary{background:var(--dsw-static-deepseek-500,rgb(65,118,230));border-color:transparent;color:#fff;}",
|
|
3681
|
+
".ct-btn-primary:hover{background:var(--dsw-static-deepseek-450,var(--dsw-static-deepseek-500,rgb(86,134,254)));}",
|
|
3682
|
+
".ct-btn-danger{background:var(--dsw-static-red-500,rgb(239,68,68));border-color:transparent;color:#fff;}",
|
|
3683
|
+
".ct-btn-danger:hover{background:var(--dsw-static-red-600,var(--dsw-static-red-500,rgb(236,19,19)));}",
|
|
3684
|
+
".ct-toast{position:fixed;top:40px;left:50%;z-index:1100;pointer-events:none;display:flex;align-items:center;gap:10px;width:max-content;max-width:min(640px,calc(100vw - 48px));padding:12px 16px;border-radius:14px;background:var(--dsw-alias-button-contrast-fill);color:var(--dsw-alias-label-primary-inverted);font-size:14px;line-height:22px;box-shadow:var(--dsw-shadow-lv3);transform:translateX(-50%);animation:ct-toast-in 160ms ease-out,ct-toast-fade 1s ease 3s forwards;}",
|
|
3685
|
+
".ct-toast-icon{display:grid;place-items:center;flex:none;width:18px;height:18px;border:1.5px solid var(--dsw-alias-state-success-primary);border-radius:50%;corner-shape:round;color:var(--dsw-alias-state-success-primary);}",
|
|
3686
|
+
".ct-toast-text{min-width:0;}",
|
|
3687
|
+
"@keyframes ct-toast-in{from{opacity:0;transform:translate(-50%,-6px);}to{opacity:1;transform:translate(-50%,0);}}",
|
|
3688
|
+
"@keyframes ct-toast-fade{to{opacity:0;}}",
|
|
3689
|
+
"@media (prefers-reduced-motion: reduce){.ct-toast{animation:ct-toast-fade 1s ease 3s forwards;}}"
|
|
1366
3690
|
].join("\n");
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
3691
|
+
function isValidSelection(v) {
|
|
3692
|
+
return !!v && (v === CUSTOM_SELECTION || NOOP_PRESET_IDS.has(v) || v in PRESETS);
|
|
3693
|
+
}
|
|
3694
|
+
function isPresetId(v) {
|
|
3695
|
+
return typeof v === "string" && v in PRESETS;
|
|
3696
|
+
}
|
|
3697
|
+
function presetDef(id) {
|
|
3698
|
+
return PRESETS[id] ?? PRESETS.dsh;
|
|
1370
3699
|
}
|
|
1371
3700
|
function registerTheme(ctx) {
|
|
1372
3701
|
const slots = ctx.get("slots");
|
|
@@ -1399,43 +3728,188 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1399
3728
|
if (!baselineDisposer) baselineDisposer = injector.insert(buildBaseCss());
|
|
1400
3729
|
} else if (baselineDisposer) baselineDisposer = release(baselineDisposer);
|
|
1401
3730
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
3731
|
+
/** Raw localStorage access; an absent or blocked store reads as empty, writes are dropped. */
|
|
3732
|
+
function readRaw(key) {
|
|
3733
|
+
try {
|
|
3734
|
+
return localStorage.getItem(key);
|
|
3735
|
+
} catch {
|
|
3736
|
+
return null;
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
function writeRaw(key, value) {
|
|
3740
|
+
try {
|
|
3741
|
+
if (value === null) localStorage.removeItem(key);
|
|
3742
|
+
else localStorage.setItem(key, value);
|
|
3743
|
+
} catch {}
|
|
3744
|
+
}
|
|
3745
|
+
function getSelection() {
|
|
3746
|
+
for (const key of [THEME_STORAGE_KEY, THEME_STORAGE_KEY_LEGACY]) {
|
|
3747
|
+
const cur = readRaw(key);
|
|
3748
|
+
if (!isValidSelection(cur)) continue;
|
|
1406
3749
|
const normalized = cur === "native" ? "dsh" : cur;
|
|
1407
|
-
if (cur !== normalized)
|
|
1408
|
-
localStorage.setItem(THEME_STORAGE_KEY, normalized);
|
|
1409
|
-
} catch {}
|
|
1410
|
-
else if (key === "cooltea-theme-preset") try {
|
|
1411
|
-
localStorage.setItem(THEME_STORAGE_KEY, cur);
|
|
1412
|
-
} catch {}
|
|
3750
|
+
if (cur !== normalized || key === "cooltea-theme-preset") writeRaw(THEME_STORAGE_KEY, normalized);
|
|
1413
3751
|
return normalized;
|
|
1414
|
-
}
|
|
3752
|
+
}
|
|
1415
3753
|
return "dsh";
|
|
1416
3754
|
}
|
|
1417
|
-
|
|
3755
|
+
/** The preset the custom seeds derive from, restored from the stored blob. */
|
|
3756
|
+
function customBase() {
|
|
3757
|
+
const env = parseEnvelope(readRaw(CUSTOM_THEME_STORAGE_KEY));
|
|
3758
|
+
if (env && isPresetId(env.base)) return env.base;
|
|
3759
|
+
return lastPreset;
|
|
3760
|
+
}
|
|
3761
|
+
function loadCustom() {
|
|
3762
|
+
const base = customBase();
|
|
3763
|
+
const fallback = extractSeeds(presetDef(base));
|
|
3764
|
+
return {
|
|
3765
|
+
base,
|
|
3766
|
+
theme: normalizeCustom(parseEnvelope(readRaw(CUSTOM_THEME_STORAGE_KEY))?.theme, fallback)
|
|
3767
|
+
};
|
|
3768
|
+
}
|
|
3769
|
+
function persistCustom(theme) {
|
|
3770
|
+
writeRaw(CUSTOM_THEME_STORAGE_KEY, encodeCustom(customBase(), theme));
|
|
3771
|
+
}
|
|
3772
|
+
/**
|
|
3773
|
+
* Choose the preset a future custom theme seeds from, without touching the
|
|
3774
|
+
* colours currently on screen. The custom editor stays the live theme; the
|
|
3775
|
+
* preset is only the template the next "add" inherits.
|
|
3776
|
+
*/
|
|
3777
|
+
function setCustomBase(base) {
|
|
3778
|
+
lastPreset = base;
|
|
3779
|
+
writeRaw(CUSTOM_THEME_STORAGE_KEY, encodeCustom(base, loadCustom().theme));
|
|
3780
|
+
}
|
|
3781
|
+
function apply(src) {
|
|
1418
3782
|
overrideDispose = release(overrideDispose);
|
|
1419
3783
|
fallbackDispose = release(fallbackDispose);
|
|
1420
|
-
|
|
3784
|
+
const target = src === CUSTOM_SELECTION ? buildCustomPreset(loadCustom().theme) : src;
|
|
3785
|
+
if (typeof target === "string" && NOOP_PRESET_IDS.has(target)) {
|
|
1421
3786
|
ensureBaseline(false);
|
|
1422
3787
|
return;
|
|
1423
3788
|
}
|
|
1424
3789
|
ensureBaseline(true);
|
|
1425
|
-
const overrides = buildOverrides(
|
|
3790
|
+
const overrides = buildOverrides(target);
|
|
1426
3791
|
if (theme?.overrideTokens) try {
|
|
1427
3792
|
overrideDispose = theme.overrideTokens("dsh-cool-theme", overrides);
|
|
1428
3793
|
return;
|
|
1429
3794
|
} catch {}
|
|
1430
|
-
fallbackDispose = injector.insert(buildFullCssFallback(
|
|
3795
|
+
fallbackDispose = injector.insert(buildFullCssFallback(target));
|
|
1431
3796
|
}
|
|
1432
|
-
function
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
applyPreset(id);
|
|
3797
|
+
function setSelection(id) {
|
|
3798
|
+
writeRaw(THEME_STORAGE_KEY, id);
|
|
3799
|
+
if (id !== CUSTOM_SELECTION) lastPreset = id;
|
|
3800
|
+
apply(id);
|
|
1437
3801
|
}
|
|
1438
|
-
|
|
3802
|
+
function setCustom(next) {
|
|
3803
|
+
persistCustom(next);
|
|
3804
|
+
apply(buildCustomPreset(next));
|
|
3805
|
+
}
|
|
3806
|
+
function resetCustom() {
|
|
3807
|
+
const theme = extractSeeds(presetDef(customBase()));
|
|
3808
|
+
persistCustom(theme);
|
|
3809
|
+
apply(buildCustomPreset(theme));
|
|
3810
|
+
return theme;
|
|
3811
|
+
}
|
|
3812
|
+
const fallbackForBase = (base) => extractSeeds(presetDef(isPresetId(base) ? base : lastPreset));
|
|
3813
|
+
/**
|
|
3814
|
+
* The roster as the Host last reported it; `null` means it has not answered
|
|
3815
|
+
* yet. Files are the source of truth, so this is a read-through cache the
|
|
3816
|
+
* panel renders from, and every mutation is a round trip plus a refresh.
|
|
3817
|
+
*/
|
|
3818
|
+
let themeCache = null;
|
|
3819
|
+
/** The legacy browser list, read only until the Host has answered. */
|
|
3820
|
+
const legacyList = () => decodeList(readRaw(CUSTOM_LIST_STORAGE_KEY), fallbackForBase);
|
|
3821
|
+
/** The roster to render and resolve ids against. */
|
|
3822
|
+
const readList = () => themeCache ?? legacyList();
|
|
3823
|
+
function readActiveId() {
|
|
3824
|
+
const id = readRaw(CUSTOM_ACTIVE_STORAGE_KEY);
|
|
3825
|
+
return id && readList().some((e) => e.id === id) ? id : null;
|
|
3826
|
+
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Adopt the themes this browser saved before they lived in files. Runs once:
|
|
3829
|
+
* the marker keeps a stale browser copy from being migrated twice, and is only
|
|
3830
|
+
* set after a confirmed write, so a failed migration retries next load.
|
|
3831
|
+
*/
|
|
3832
|
+
async function migrateLegacyThemes(hostThemes) {
|
|
3833
|
+
if (readRaw("cool-theme-custom-migrated") !== null) return hostThemes;
|
|
3834
|
+
const adopt = legacyThemesToAdopt(legacyList(), hostThemes);
|
|
3835
|
+
if (adopt.length > 0) await pushThemes(adopt, fallbackForBase);
|
|
3836
|
+
writeRaw(CUSTOM_MIGRATED_STORAGE_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
3837
|
+
writeRaw(CUSTOM_LIST_STORAGE_KEY, null);
|
|
3838
|
+
return adopt.length > 0 ? fetchThemes(fallbackForBase) : hostThemes;
|
|
3839
|
+
}
|
|
3840
|
+
/** Re-read the roster from the Host, migrating the legacy list on first load. */
|
|
3841
|
+
async function refreshSaved() {
|
|
3842
|
+
themeCache = await migrateLegacyThemes(await fetchThemes(fallbackForBase));
|
|
3843
|
+
return themeCache;
|
|
3844
|
+
}
|
|
3845
|
+
/** Load a saved entry into the draft and make it the active theme. */
|
|
3846
|
+
function loadSaved(id) {
|
|
3847
|
+
const entry = readList().find((e) => e.id === id);
|
|
3848
|
+
if (!entry) return null;
|
|
3849
|
+
if (isPresetId(entry.base)) lastPreset = entry.base;
|
|
3850
|
+
writeRaw(CUSTOM_ACTIVE_STORAGE_KEY, entry.id);
|
|
3851
|
+
writeRaw(CUSTOM_THEME_STORAGE_KEY, encodeCustom(entry.base, entry.theme));
|
|
3852
|
+
apply(buildCustomPreset(entry.theme));
|
|
3853
|
+
return entry.theme;
|
|
3854
|
+
}
|
|
3855
|
+
const saved = {
|
|
3856
|
+
/** The cached roster, or the legacy browser list until the Host answers. */
|
|
3857
|
+
list: readList,
|
|
3858
|
+
activeId: readActiveId,
|
|
3859
|
+
load: loadSaved,
|
|
3860
|
+
/** Point the "in use" badge at an entry, or clear it entirely. */
|
|
3861
|
+
setActive(id) {
|
|
3862
|
+
writeRaw(CUSTOM_ACTIVE_STORAGE_KEY, id);
|
|
3863
|
+
},
|
|
3864
|
+
refresh: refreshSaved,
|
|
3865
|
+
/** Persist the current draft as a new named entry and make it active. */
|
|
3866
|
+
async create(name) {
|
|
3867
|
+
const draft = loadCustom();
|
|
3868
|
+
const entry = {
|
|
3869
|
+
id: newThemeId(),
|
|
3870
|
+
name,
|
|
3871
|
+
base: draft.base,
|
|
3872
|
+
theme: draft.theme,
|
|
3873
|
+
assets: []
|
|
3874
|
+
};
|
|
3875
|
+
await pushThemes([entry], fallbackForBase);
|
|
3876
|
+
writeRaw(CUSTOM_ACTIVE_STORAGE_KEY, entry.id);
|
|
3877
|
+
return refreshSaved();
|
|
3878
|
+
},
|
|
3879
|
+
/** Write the current draft (and a new name) back to an existing entry. */
|
|
3880
|
+
async update(id, name) {
|
|
3881
|
+
const entry = readList().find((e) => e.id === id);
|
|
3882
|
+
if (!entry) return readList();
|
|
3883
|
+
const draft = loadCustom();
|
|
3884
|
+
await pushThemes([{
|
|
3885
|
+
...entry,
|
|
3886
|
+
name,
|
|
3887
|
+
theme: draft.theme
|
|
3888
|
+
}], fallbackForBase);
|
|
3889
|
+
return refreshSaved();
|
|
3890
|
+
},
|
|
3891
|
+
async remove(id) {
|
|
3892
|
+
if (readRaw("cool-theme-custom-active") === id) writeRaw(CUSTOM_ACTIVE_STORAGE_KEY, null);
|
|
3893
|
+
await removeTheme(id);
|
|
3894
|
+
const next = await refreshSaved();
|
|
3895
|
+
if (readActiveId() === null && next[0]) loadSaved(next[0].id);
|
|
3896
|
+
return next;
|
|
3897
|
+
}
|
|
3898
|
+
};
|
|
3899
|
+
const initialSelection = getSelection();
|
|
3900
|
+
let lastPreset = initialSelection === CUSTOM_SELECTION ? "dsh" : initialSelection;
|
|
3901
|
+
if (initialSelection === CUSTOM_SELECTION) {
|
|
3902
|
+
const env = parseEnvelope(readRaw(CUSTOM_THEME_STORAGE_KEY));
|
|
3903
|
+
if (env && isPresetId(env.base)) lastPreset = env.base;
|
|
3904
|
+
}
|
|
3905
|
+
apply(initialSelection);
|
|
3906
|
+
let sharedToast = null;
|
|
3907
|
+
const modules = ctx.get("modules");
|
|
3908
|
+
try {
|
|
3909
|
+
modules?.import?.("@deepseek-ai/dsh-client-ui-primitives").then((mod) => {
|
|
3910
|
+
if (typeof mod?.Toast === "function") sharedToast = mod.Toast;
|
|
3911
|
+
}).catch(() => {});
|
|
3912
|
+
} catch {}
|
|
1439
3913
|
ctx.effect(() => () => {
|
|
1440
3914
|
release(pluginCssDisposer);
|
|
1441
3915
|
baselineDisposer = release(baselineDisposer);
|
|
@@ -1454,8 +3928,15 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1454
3928
|
return slots.register(options, (props) => react.createElement(ThemePanel, {
|
|
1455
3929
|
t: props?.t ?? ((key) => zh[key]),
|
|
1456
3930
|
theme,
|
|
1457
|
-
|
|
1458
|
-
|
|
3931
|
+
getSelection,
|
|
3932
|
+
setSelection,
|
|
3933
|
+
getCustom: loadCustom,
|
|
3934
|
+
setCustom,
|
|
3935
|
+
setCustomBase,
|
|
3936
|
+
resetCustom,
|
|
3937
|
+
saved,
|
|
3938
|
+
getHostToast: () => sharedToast,
|
|
3939
|
+
onRequestClose: typeof props?.close === "function" ? props.close : null
|
|
1459
3940
|
}));
|
|
1460
3941
|
});
|
|
1461
3942
|
const PALETTE_SVG = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path d=\"M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\"/><circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/></g></svg>";
|
|
@@ -1466,18 +3947,16 @@ html[data-ds-dark-theme], body[data-ds-dark-theme] {
|
|
|
1466
3947
|
try {
|
|
1467
3948
|
currentLabel = t("nav");
|
|
1468
3949
|
} catch {}
|
|
1469
|
-
const candidates =
|
|
3950
|
+
const candidates = [
|
|
1470
3951
|
currentLabel,
|
|
1471
3952
|
zh.nav,
|
|
1472
3953
|
en.nav
|
|
1473
|
-
].filter(Boolean)
|
|
3954
|
+
].filter(Boolean);
|
|
1474
3955
|
const cells = document.querySelectorAll("[class*=\"navCell\"], button[class*=\"navCell\"]");
|
|
1475
|
-
const toPatch = [];
|
|
1476
|
-
if (cells.length > 0) cells.forEach((c) => toPatch.push(c));
|
|
1477
|
-
else document.querySelectorAll("[class*=\"nav\"] button").forEach((b) => toPatch.push(b));
|
|
3956
|
+
const toPatch = cells.length > 0 ? Array.from(cells) : Array.from(document.querySelectorAll("[class*=\"nav\"] button"));
|
|
1478
3957
|
for (const cell of toPatch) {
|
|
1479
3958
|
const text = ((cell.querySelector("[class*=\"navLabel\"]") || cell)?.textContent || cell.textContent || "").trim();
|
|
1480
|
-
if (!
|
|
3959
|
+
if (!candidates.some((lbl) => text === lbl || text.includes(lbl))) continue;
|
|
1481
3960
|
if (cell.querySelector("[data-palette-icon]")) continue;
|
|
1482
3961
|
const svg = cell.querySelector("svg");
|
|
1483
3962
|
if (!svg) continue;
|