hyper-scheduler 1.0.1 → 1.1.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 +17 -0
- package/dist/devtools-Bxtz0rO_.cjs +1 -0
- package/dist/{devtools-4xVHTaUz.js → devtools-ByJU-Gv1.js} +378 -34
- package/dist/index.cjs +1 -1
- package/dist/index.js +91 -38
- package/dist/index.umd.cjs +1 -1
- package/docs/.vitepress/cache/deps/_metadata.json +31 -0
- package/docs/.vitepress/cache/deps/chunk-EKBJ2FPM.js +12798 -0
- package/docs/.vitepress/cache/deps/chunk-EKBJ2FPM.js.map +7 -0
- package/docs/.vitepress/cache/deps/package.json +3 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4505 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +9731 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs/.vitepress/cache/deps/vue.js +347 -0
- package/docs/.vitepress/cache/deps/vue.js.map +7 -0
- package/docs/.vitepress/config.ts +56 -0
- package/docs/.vitepress/theme/components/DemoFrame.vue +111 -0
- package/docs/.vitepress/theme/custom.css +6 -0
- package/docs/.vitepress/theme/index.ts +10 -0
- package/docs/README.md +120 -0
- package/docs/api/devtools.md +245 -0
- package/docs/api/index.md +178 -0
- package/docs/api/scheduler.md +342 -0
- package/docs/api/task.md +439 -0
- package/docs/api/types.md +365 -0
- package/docs/examples/index.md +342 -0
- package/docs/guide/best-practices.md +436 -0
- package/docs/guide/core-concepts.md +363 -0
- package/docs/guide/getting-started.md +176 -0
- package/docs/index.md +33 -0
- package/docs/public/logo.svg +54 -0
- package/package.json +9 -6
- package/dist/devtools-DdQ1I25H.cjs +0 -1
|
@@ -327,6 +327,9 @@ const themeStyles = `
|
|
|
327
327
|
--hs-panel-width: 400px;
|
|
328
328
|
--hs-panel-height: 300px;
|
|
329
329
|
|
|
330
|
+
/* 等宽数字字体 */
|
|
331
|
+
--hs-font-monospaced-num: var(--hs-font-mono);
|
|
332
|
+
|
|
330
333
|
/* Light Theme (Default) */
|
|
331
334
|
--hs-bg: #ffffff;
|
|
332
335
|
--hs-bg-secondary: #f3f4f6;
|
|
@@ -344,6 +347,7 @@ const themeStyles = `
|
|
|
344
347
|
--hs-radius: 6px;
|
|
345
348
|
--hs-header-height: 40px;
|
|
346
349
|
--hs-z-index: 9999;
|
|
350
|
+
--hs-z-index-overlay: 9998;
|
|
347
351
|
|
|
348
352
|
/* Default display styles for the host itself */
|
|
349
353
|
background: var(--hs-bg);
|
|
@@ -387,6 +391,8 @@ const ICONS = {
|
|
|
387
391
|
dockRight: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="18" rx="2" ry="2"></rect><line x1="15" y1="3" x2="15" y2="21"></line></svg>`,
|
|
388
392
|
chart: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg>`
|
|
389
393
|
};
|
|
394
|
+
const STORAGE_KEY_POS = "hs-trigger-position";
|
|
395
|
+
const STORAGE_KEY_COLLAPSED = "hs-trigger-collapsed";
|
|
390
396
|
class FloatingTrigger extends HTMLElement {
|
|
391
397
|
constructor() {
|
|
392
398
|
super();
|
|
@@ -395,43 +401,203 @@ class FloatingTrigger extends HTMLElement {
|
|
|
395
401
|
__publicField(this, "_position", "bottom-right");
|
|
396
402
|
__publicField(this, "_bgColor", "");
|
|
397
403
|
__publicField(this, "_textColor", "");
|
|
404
|
+
__publicField(this, "_isDragging", false);
|
|
405
|
+
__publicField(this, "_wasDragging", false);
|
|
406
|
+
// 标记是否发生过拖拽
|
|
407
|
+
__publicField(this, "_offsetX", 0);
|
|
408
|
+
__publicField(this, "_offsetY", 0);
|
|
409
|
+
__publicField(this, "_isCollapsed", false);
|
|
398
410
|
this._shadow = this.attachShadow({ mode: "open" });
|
|
399
411
|
}
|
|
412
|
+
// 新增:收起状态
|
|
400
413
|
static get observedAttributes() {
|
|
401
414
|
return ["position", "bg-color", "text-color"];
|
|
402
415
|
}
|
|
403
416
|
connectedCallback() {
|
|
417
|
+
this.loadState();
|
|
404
418
|
this.render();
|
|
405
419
|
this.addEventListeners();
|
|
420
|
+
this.applyPosition();
|
|
421
|
+
window.addEventListener("resize", this.onResize.bind(this));
|
|
422
|
+
}
|
|
423
|
+
disconnectedCallback() {
|
|
424
|
+
window.removeEventListener("resize", this.onResize.bind(this));
|
|
425
|
+
}
|
|
426
|
+
onResize() {
|
|
427
|
+
this.applyPosition();
|
|
406
428
|
}
|
|
407
429
|
attributeChangedCallback(name, _oldVal, newVal) {
|
|
408
|
-
console.log("[FloatingTrigger] attributeChangedCallback:", name, newVal);
|
|
409
430
|
if (name === "position") {
|
|
410
431
|
this._position = newVal || "bottom-right";
|
|
432
|
+
this.applyPosition();
|
|
411
433
|
} else if (name === "bg-color") {
|
|
412
434
|
this._bgColor = newVal || "";
|
|
435
|
+
this.updateStyles();
|
|
413
436
|
} else if (name === "text-color") {
|
|
414
437
|
this._textColor = newVal || "";
|
|
438
|
+
this.updateStyles();
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
loadState() {
|
|
442
|
+
try {
|
|
443
|
+
const savedPos = localStorage.getItem(STORAGE_KEY_POS);
|
|
444
|
+
if (savedPos) {
|
|
445
|
+
const { x, y } = JSON.parse(savedPos);
|
|
446
|
+
this.style.setProperty("--hs-trigger-left", `${x}px`);
|
|
447
|
+
this.style.setProperty("--hs-trigger-top", `${y}px`);
|
|
448
|
+
this.style.setProperty("--hs-trigger-position-set", "true");
|
|
449
|
+
}
|
|
450
|
+
const savedCollapsed = localStorage.getItem(STORAGE_KEY_COLLAPSED);
|
|
451
|
+
if (savedCollapsed === "true") {
|
|
452
|
+
this._isCollapsed = true;
|
|
453
|
+
}
|
|
454
|
+
} catch (e) {
|
|
455
|
+
console.warn("[FloatingTrigger] Failed to load state:", e);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
saveState() {
|
|
459
|
+
const button = this._shadow.querySelector("button");
|
|
460
|
+
if (!button) return;
|
|
461
|
+
const rect = button.getBoundingClientRect();
|
|
462
|
+
localStorage.setItem(STORAGE_KEY_POS, JSON.stringify({ x: rect.left, y: rect.top }));
|
|
463
|
+
localStorage.setItem(STORAGE_KEY_COLLAPSED, String(this._isCollapsed));
|
|
464
|
+
}
|
|
465
|
+
applyPosition() {
|
|
466
|
+
const button = this._shadow.querySelector("button");
|
|
467
|
+
if (!button) return;
|
|
468
|
+
const maxX = window.innerWidth - button.offsetWidth;
|
|
469
|
+
const maxY = window.innerHeight - button.offsetHeight;
|
|
470
|
+
if (!this.style.getPropertyValue("--hs-trigger-position-set")) {
|
|
471
|
+
const pos = this._position;
|
|
472
|
+
button.style.top = pos.includes("top") ? "20px" : "auto";
|
|
473
|
+
button.style.bottom = pos.includes("bottom") ? "20px" : "auto";
|
|
474
|
+
button.style.left = pos.includes("left") ? "20px" : "auto";
|
|
475
|
+
button.style.right = pos.includes("right") ? "20px" : "auto";
|
|
476
|
+
} else {
|
|
477
|
+
let currentX = parseFloat(this.style.getPropertyValue("--hs-trigger-left") || "0");
|
|
478
|
+
let currentY = parseFloat(this.style.getPropertyValue("--hs-trigger-top") || "0");
|
|
479
|
+
currentX = Math.max(0, Math.min(currentX, maxX));
|
|
480
|
+
currentY = Math.max(0, Math.min(currentY, maxY));
|
|
481
|
+
this.style.setProperty("--hs-trigger-left", `${currentX}px`);
|
|
482
|
+
this.style.setProperty("--hs-trigger-top", `${currentY}px`);
|
|
483
|
+
button.style.left = `${currentX}px`;
|
|
484
|
+
button.style.top = `${currentY}px`;
|
|
485
|
+
button.style.right = "auto";
|
|
486
|
+
button.style.bottom = "auto";
|
|
415
487
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
488
|
+
this.updateCollapsedState();
|
|
489
|
+
}
|
|
490
|
+
updateStyles() {
|
|
491
|
+
const button = this._shadow.querySelector("button");
|
|
492
|
+
if (button) {
|
|
493
|
+
button.style.background = this._bgColor || "var(--hs-primary)";
|
|
494
|
+
button.style.color = this._textColor || "white";
|
|
495
|
+
if (this._bgColor) {
|
|
496
|
+
button.style.setProperty("--hs-trigger-bg-hover", `${this._bgColor}; filter: brightness(1.1);`);
|
|
497
|
+
} else {
|
|
498
|
+
button.style.removeProperty("--hs-trigger-bg-hover");
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
updateCollapsedState() {
|
|
503
|
+
const button = this._shadow.querySelector("button");
|
|
504
|
+
if (button) {
|
|
505
|
+
if (this._isCollapsed) {
|
|
506
|
+
button.classList.add("collapsed");
|
|
507
|
+
} else {
|
|
508
|
+
button.classList.remove("collapsed");
|
|
509
|
+
}
|
|
420
510
|
}
|
|
421
511
|
}
|
|
422
512
|
addEventListeners() {
|
|
423
513
|
const btn = this._shadow.querySelector("button");
|
|
424
|
-
|
|
514
|
+
if (!btn) return;
|
|
515
|
+
btn.addEventListener("click", (e) => {
|
|
516
|
+
if (this._wasDragging) {
|
|
517
|
+
e.preventDefault();
|
|
518
|
+
e.stopPropagation();
|
|
519
|
+
this._wasDragging = false;
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
425
522
|
this.dispatchEvent(new CustomEvent("toggle", { bubbles: true, composed: true }));
|
|
426
523
|
});
|
|
524
|
+
const collapseBtn = this._shadow.querySelector(".collapse-btn");
|
|
525
|
+
collapseBtn == null ? void 0 : collapseBtn.addEventListener("click", (e) => {
|
|
526
|
+
e.stopPropagation();
|
|
527
|
+
e.preventDefault();
|
|
528
|
+
this._isCollapsed = !this._isCollapsed;
|
|
529
|
+
this.updateCollapsedState();
|
|
530
|
+
this.saveState();
|
|
531
|
+
});
|
|
532
|
+
btn.addEventListener("dblclick", (e) => {
|
|
533
|
+
if (this._isCollapsed) {
|
|
534
|
+
e.stopPropagation();
|
|
535
|
+
this._isCollapsed = false;
|
|
536
|
+
this.updateCollapsedState();
|
|
537
|
+
this.saveState();
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
btn.addEventListener("mousedown", (e) => {
|
|
541
|
+
if (e.button !== 0) return;
|
|
542
|
+
if (e.target.closest(".collapse-btn")) return;
|
|
543
|
+
this._isDragging = true;
|
|
544
|
+
this._wasDragging = false;
|
|
545
|
+
this._offsetX = e.clientX - btn.getBoundingClientRect().left;
|
|
546
|
+
this._offsetY = e.clientY - btn.getBoundingClientRect().top;
|
|
547
|
+
const startX = e.clientX;
|
|
548
|
+
const startY = e.clientY;
|
|
549
|
+
let hasMoved = false;
|
|
550
|
+
const onMouseMove = (moveEvent) => {
|
|
551
|
+
if (!this._isDragging) return;
|
|
552
|
+
if (!hasMoved && (Math.abs(moveEvent.clientX - startX) > 2 || Math.abs(moveEvent.clientY - startY) > 2)) {
|
|
553
|
+
hasMoved = true;
|
|
554
|
+
this._wasDragging = true;
|
|
555
|
+
btn.style.cursor = "grabbing";
|
|
556
|
+
btn.style.transition = "none";
|
|
557
|
+
}
|
|
558
|
+
if (hasMoved) {
|
|
559
|
+
let newX = moveEvent.clientX - this._offsetX;
|
|
560
|
+
let newY = moveEvent.clientY - this._offsetY;
|
|
561
|
+
const maxX = window.innerWidth - btn.offsetWidth;
|
|
562
|
+
const maxY = window.innerHeight - btn.offsetHeight;
|
|
563
|
+
newX = Math.max(0, Math.min(newX, maxX));
|
|
564
|
+
newY = Math.max(0, Math.min(newY, maxY));
|
|
565
|
+
btn.style.left = `${newX}px`;
|
|
566
|
+
btn.style.top = `${newY}px`;
|
|
567
|
+
btn.style.right = "auto";
|
|
568
|
+
btn.style.bottom = "auto";
|
|
569
|
+
this.style.setProperty("--hs-trigger-position-set", "true");
|
|
570
|
+
this.style.setProperty("--hs-trigger-left", `${newX}px`);
|
|
571
|
+
this.style.setProperty("--hs-trigger-top", `${newY}px`);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
const onMouseUp = () => {
|
|
575
|
+
if (!this._isDragging) return;
|
|
576
|
+
this._isDragging = false;
|
|
577
|
+
btn.style.cursor = "pointer";
|
|
578
|
+
btn.style.transition = "";
|
|
579
|
+
if (hasMoved) {
|
|
580
|
+
this.saveState();
|
|
581
|
+
const preventClick = (e2) => {
|
|
582
|
+
e2.stopPropagation();
|
|
583
|
+
e2.preventDefault();
|
|
584
|
+
};
|
|
585
|
+
window.addEventListener("click", preventClick, { capture: true, once: true });
|
|
586
|
+
}
|
|
587
|
+
window.removeEventListener("mousemove", onMouseMove);
|
|
588
|
+
window.removeEventListener("mouseup", onMouseUp);
|
|
589
|
+
};
|
|
590
|
+
window.addEventListener("mousemove", onMouseMove);
|
|
591
|
+
window.addEventListener("mouseup", onMouseUp);
|
|
592
|
+
});
|
|
427
593
|
}
|
|
428
594
|
render() {
|
|
429
|
-
const pos = this._position;
|
|
430
595
|
const posStyles = `
|
|
431
|
-
top: ${
|
|
432
|
-
bottom: ${
|
|
433
|
-
left: ${
|
|
434
|
-
right: ${
|
|
596
|
+
top: var(--hs-trigger-top, ${this._position.includes("top") ? "20px" : "auto"});
|
|
597
|
+
bottom: var(--hs-trigger-bottom, ${this._position.includes("bottom") ? "20px" : "auto"});
|
|
598
|
+
left: var(--hs-trigger-left, ${this._position.includes("left") ? "20px" : "auto"});
|
|
599
|
+
right: var(--hs-trigger-right, ${this._position.includes("right") ? "20px" : "auto"});
|
|
600
|
+
transform: ${this._isCollapsed ? "translateX(calc(100% - 12px))" : "translateX(0)"};
|
|
435
601
|
`;
|
|
436
602
|
const bgStyle = this._bgColor ? `background: ${this._bgColor};` : "";
|
|
437
603
|
const colorStyle = this._textColor ? `color: ${this._textColor};` : "";
|
|
@@ -443,33 +609,92 @@ class FloatingTrigger extends HTMLElement {
|
|
|
443
609
|
${posStyles}
|
|
444
610
|
width: 48px;
|
|
445
611
|
height: 48px;
|
|
446
|
-
border-radius:
|
|
612
|
+
border-radius: 12px; /* 更现代的圆角 */
|
|
447
613
|
background: var(--hs-primary);
|
|
448
614
|
color: white;
|
|
449
615
|
${bgStyle}
|
|
450
616
|
${colorStyle}
|
|
451
617
|
border: none;
|
|
452
|
-
box-shadow:
|
|
618
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15); /* 更柔和的阴影 */
|
|
453
619
|
cursor: pointer;
|
|
454
620
|
display: flex;
|
|
455
621
|
align-items: center;
|
|
456
622
|
justify-content: center;
|
|
457
623
|
font-family: var(--hs-font-family);
|
|
458
624
|
z-index: var(--hs-z-index);
|
|
459
|
-
transition: transform 0.2s;
|
|
625
|
+
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), background 0.2s, box-shadow 0.2s;
|
|
626
|
+
overflow: visible; /* 允许子元素(收起按钮)溢出或显示 */
|
|
460
627
|
}
|
|
461
628
|
button:hover {
|
|
462
629
|
${this._bgColor ? `background: ${this._bgColor}; filter: brightness(1.1);` : "background: var(--hs-primary-hover);"}
|
|
463
|
-
transform: scale(1.
|
|
630
|
+
transform: scale(1.05);
|
|
631
|
+
box-shadow: 0 6px 16px rgba(0,0,0,0.2);
|
|
464
632
|
}
|
|
465
633
|
button:active {
|
|
466
634
|
transform: scale(0.95);
|
|
467
635
|
}
|
|
636
|
+
|
|
637
|
+
/* 显式收起按钮 */
|
|
638
|
+
.collapse-btn {
|
|
639
|
+
position: absolute;
|
|
640
|
+
top: 0;
|
|
641
|
+
right: 0;
|
|
642
|
+
width: 20px;
|
|
643
|
+
height: 20px;
|
|
644
|
+
background: rgba(0,0,0,0.1);
|
|
645
|
+
border-bottom-left-radius: 8px;
|
|
646
|
+
display: flex;
|
|
647
|
+
align-items: center;
|
|
648
|
+
justify-content: center;
|
|
649
|
+
opacity: 1; /* 默认可见 */
|
|
650
|
+
transition: opacity 0.2s, background 0.2s;
|
|
651
|
+
color: white;
|
|
652
|
+
font-weight: bold;
|
|
653
|
+
}
|
|
654
|
+
.collapse-btn::before {
|
|
655
|
+
content: '—'; /* 最小化图标 */
|
|
656
|
+
font-size: 12px;
|
|
657
|
+
color: currentColor;
|
|
658
|
+
}
|
|
659
|
+
button:hover .collapse-btn {
|
|
660
|
+
opacity: 1;
|
|
661
|
+
}
|
|
662
|
+
.collapse-btn:hover {
|
|
663
|
+
background: rgba(0,0,0,0.3);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/* 收起状态样式 */
|
|
667
|
+
button.collapsed {
|
|
668
|
+
width: 36px;
|
|
669
|
+
height: 36px;
|
|
670
|
+
border-radius: 18px 0 0 18px;
|
|
671
|
+
transform: translateX(calc(100% - 12px));
|
|
672
|
+
opacity: 0.8;
|
|
673
|
+
}
|
|
674
|
+
button.collapsed:hover {
|
|
675
|
+
transform: translateX(calc(100% - 24px)); /* hover 时稍微伸出一点 */
|
|
676
|
+
opacity: 1;
|
|
677
|
+
}
|
|
678
|
+
button.collapsed .icon {
|
|
679
|
+
display: none;
|
|
680
|
+
}
|
|
681
|
+
button.collapsed .collapse-btn {
|
|
682
|
+
right: auto;
|
|
683
|
+
left: 0;
|
|
684
|
+
border-radius: 0 12px 12px 0;
|
|
685
|
+
}
|
|
686
|
+
button.collapsed .collapse-btn::before {
|
|
687
|
+
content: '›'; /* 展开图标 */
|
|
688
|
+
}
|
|
468
689
|
</style>
|
|
469
690
|
<button title="Toggle Hyper Scheduler DevTools">
|
|
470
|
-
|
|
691
|
+
<div class="collapse-btn" title="Minimize"></div>
|
|
692
|
+
<span class="icon">${ICONS.chart}</span>
|
|
471
693
|
</button>
|
|
472
694
|
`;
|
|
695
|
+
this.applyPosition();
|
|
696
|
+
this.updateCollapsedState();
|
|
697
|
+
this.updateStyles();
|
|
473
698
|
}
|
|
474
699
|
}
|
|
475
700
|
customElements.define("hs-floating-trigger", FloatingTrigger);
|
|
@@ -504,7 +729,7 @@ class TaskHeader extends HTMLElement {
|
|
|
504
729
|
this._fps = Math.round(val);
|
|
505
730
|
if (this.$fps) {
|
|
506
731
|
const color = this._fps < 30 ? "var(--hs-danger)" : this._fps < 50 ? "var(--hs-warning)" : "var(--hs-success)";
|
|
507
|
-
this.$fps.innerHTML = `⚡ ${t("stats.fps")}: <span style="color:${color}">${this._fps}</span> (${t("stats.mainThread")})`;
|
|
732
|
+
this.$fps.innerHTML = `⚡ ${t("stats.fps")}: <span style="color:${color}; font-family:var(--hs-font-monospaced-num);">${this._fps}</span> (${t("stats.mainThread")})`;
|
|
508
733
|
}
|
|
509
734
|
}
|
|
510
735
|
set stats(val) {
|
|
@@ -766,6 +991,7 @@ class TaskList extends HTMLElement {
|
|
|
766
991
|
__publicField(this, "_shadow");
|
|
767
992
|
__publicField(this, "_tasks", []);
|
|
768
993
|
__publicField(this, "_lastExecutionTimes", /* @__PURE__ */ new Map());
|
|
994
|
+
__publicField(this, "_expandedNamespaces", /* @__PURE__ */ new Set(["default"]));
|
|
769
995
|
this._shadow = this.attachShadow({ mode: "open" });
|
|
770
996
|
}
|
|
771
997
|
connectedCallback() {
|
|
@@ -782,6 +1008,17 @@ class TaskList extends HTMLElement {
|
|
|
782
1008
|
this._tasks = newTasks;
|
|
783
1009
|
this.renderRows();
|
|
784
1010
|
}
|
|
1011
|
+
groupTasksByNamespace(tasks) {
|
|
1012
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1013
|
+
tasks.forEach((task) => {
|
|
1014
|
+
const ns = task.namespace || "default";
|
|
1015
|
+
if (!groups.has(ns)) {
|
|
1016
|
+
groups.set(ns, []);
|
|
1017
|
+
}
|
|
1018
|
+
groups.get(ns).push(task);
|
|
1019
|
+
});
|
|
1020
|
+
return groups;
|
|
1021
|
+
}
|
|
785
1022
|
filter(text, map) {
|
|
786
1023
|
const all = Array.from(map.values());
|
|
787
1024
|
if (!text) {
|
|
@@ -789,7 +1026,7 @@ class TaskList extends HTMLElement {
|
|
|
789
1026
|
} else {
|
|
790
1027
|
const lower = text.toLowerCase();
|
|
791
1028
|
this._tasks = all.filter(
|
|
792
|
-
(t2) => t2.id.toLowerCase().includes(lower) || t2.tags.some((tag) => tag.toLowerCase().includes(lower))
|
|
1029
|
+
(t2) => t2.id.toLowerCase().includes(lower) || t2.tags.some((tag) => tag.toLowerCase().includes(lower)) || t2.namespace && t2.namespace.toLowerCase().includes(lower)
|
|
793
1030
|
);
|
|
794
1031
|
}
|
|
795
1032
|
this.renderRows();
|
|
@@ -862,18 +1099,21 @@ class TaskList extends HTMLElement {
|
|
|
862
1099
|
}
|
|
863
1100
|
return `<span class="driver-badge main" title="${t("list.driverMain")}">M</span>`;
|
|
864
1101
|
}
|
|
865
|
-
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1102
|
+
renderTaskRow(task, index, isNested = false) {
|
|
1103
|
+
const lastExec = this._lastExecutionTimes.get(task.id);
|
|
1104
|
+
const isRecentlyExecuted = lastExec && Date.now() - lastExec < 1e3;
|
|
1105
|
+
const rowClass = isRecentlyExecuted ? "recently-executed" : "";
|
|
1106
|
+
const nestedClass = isNested ? "nested-task" : "";
|
|
1107
|
+
return `
|
|
1108
|
+
<tr data-id="${task.id}" class="${rowClass} ${nestedClass}">
|
|
1109
|
+
<td class="col-num">
|
|
1110
|
+
${isNested ? "" : index + 1}
|
|
1111
|
+
</td>
|
|
875
1112
|
<td class="col-id">
|
|
876
|
-
<div class="task-id"
|
|
1113
|
+
<div class="task-id">
|
|
1114
|
+
${task.id}
|
|
1115
|
+
${task.namespace && task.namespace !== "default" && !isNested ? `<span class="namespace-badge" title="Namespace">${task.namespace}</span>` : ""}
|
|
1116
|
+
</div>
|
|
877
1117
|
<div class="tags">
|
|
878
1118
|
${task.tags && task.tags.length > 0 ? task.tags.map((t2) => `<span class="tag">${t2}</span>`).join("") : `<span class="no-tags">${t("list.noTags")}</span>`}
|
|
879
1119
|
</div>
|
|
@@ -892,7 +1132,38 @@ class TaskList extends HTMLElement {
|
|
|
892
1132
|
</td>
|
|
893
1133
|
</tr>
|
|
894
1134
|
`;
|
|
895
|
-
|
|
1135
|
+
}
|
|
1136
|
+
renderRows() {
|
|
1137
|
+
const tbody = this._shadow.querySelector("tbody");
|
|
1138
|
+
if (!tbody) return;
|
|
1139
|
+
const groups = this.groupTasksByNamespace(this._tasks);
|
|
1140
|
+
let html = "";
|
|
1141
|
+
let globalIndex = 0;
|
|
1142
|
+
const defaultTasks = groups.get("default");
|
|
1143
|
+
if (defaultTasks && defaultTasks.length > 0) {
|
|
1144
|
+
html += defaultTasks.map((task) => this.renderTaskRow(task, ++globalIndex, false)).join("");
|
|
1145
|
+
}
|
|
1146
|
+
groups.delete("default");
|
|
1147
|
+
const sortedNamespaces = Array.from(groups.keys()).sort((a, b) => a.localeCompare(b));
|
|
1148
|
+
sortedNamespaces.forEach((ns) => {
|
|
1149
|
+
const tasks = groups.get(ns);
|
|
1150
|
+
const isExpanded = this._expandedNamespaces.has(ns);
|
|
1151
|
+
const icon = isExpanded ? "▼" : "▶";
|
|
1152
|
+
html += `
|
|
1153
|
+
<tr class="namespace-row ${isExpanded ? "ns-expanded" : ""}" data-ns="${ns}">
|
|
1154
|
+
<td colspan="8">
|
|
1155
|
+
<span class="ns-toggle">${icon}</span>
|
|
1156
|
+
<span class="ns-icon">📂</span>
|
|
1157
|
+
<span class="ns-name">${ns}</span>
|
|
1158
|
+
<span class="ns-count">(${tasks.length})</span>
|
|
1159
|
+
</td>
|
|
1160
|
+
</tr>
|
|
1161
|
+
`;
|
|
1162
|
+
if (isExpanded) {
|
|
1163
|
+
html += tasks.map((task) => this.renderTaskRow(task, ++globalIndex, true)).join("");
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
tbody.innerHTML = html;
|
|
896
1167
|
}
|
|
897
1168
|
render() {
|
|
898
1169
|
this._shadow.innerHTML = `
|
|
@@ -974,6 +1245,18 @@ class TaskList extends HTMLElement {
|
|
|
974
1245
|
.task-id {
|
|
975
1246
|
font-weight: 600;
|
|
976
1247
|
}
|
|
1248
|
+
.namespace-badge {
|
|
1249
|
+
display: inline-block;
|
|
1250
|
+
background: var(--hs-bg-secondary);
|
|
1251
|
+
color: var(--hs-text-secondary);
|
|
1252
|
+
border: 1px solid var(--hs-border);
|
|
1253
|
+
border-radius: 4px;
|
|
1254
|
+
padding: 0 4px;
|
|
1255
|
+
font-size: 9px;
|
|
1256
|
+
margin-left: 6px;
|
|
1257
|
+
font-family: monospace;
|
|
1258
|
+
vertical-align: middle;
|
|
1259
|
+
}
|
|
977
1260
|
.tags {
|
|
978
1261
|
display: flex;
|
|
979
1262
|
gap: 4px;
|
|
@@ -1079,6 +1362,40 @@ class TaskList extends HTMLElement {
|
|
|
1079
1362
|
color: var(--hs-text-secondary);
|
|
1080
1363
|
border-color: var(--hs-border);
|
|
1081
1364
|
}
|
|
1365
|
+
/* Namespace Styles */
|
|
1366
|
+
.namespace-row {
|
|
1367
|
+
background: var(--hs-bg-secondary);
|
|
1368
|
+
cursor: pointer;
|
|
1369
|
+
font-weight: 600;
|
|
1370
|
+
user-select: none;
|
|
1371
|
+
}
|
|
1372
|
+
.namespace-row:hover {
|
|
1373
|
+
background: var(--hs-border);
|
|
1374
|
+
}
|
|
1375
|
+
.namespace-row td {
|
|
1376
|
+
padding: 8px 12px;
|
|
1377
|
+
border-bottom: 1px solid var(--hs-border);
|
|
1378
|
+
}
|
|
1379
|
+
.ns-toggle {
|
|
1380
|
+
display: inline-block;
|
|
1381
|
+
width: 20px;
|
|
1382
|
+
text-align: center;
|
|
1383
|
+
font-size: 10px;
|
|
1384
|
+
color: var(--hs-text-secondary);
|
|
1385
|
+
transition: transform 0.2s;
|
|
1386
|
+
}
|
|
1387
|
+
.ns-icon {
|
|
1388
|
+
margin-right: 4px;
|
|
1389
|
+
}
|
|
1390
|
+
.ns-count {
|
|
1391
|
+
font-weight: normal;
|
|
1392
|
+
color: var(--hs-text-secondary);
|
|
1393
|
+
font-size: 11px;
|
|
1394
|
+
margin-left: 4px;
|
|
1395
|
+
}
|
|
1396
|
+
.nested-task .col-id {
|
|
1397
|
+
padding-left: 32px !important;
|
|
1398
|
+
}
|
|
1082
1399
|
</style>
|
|
1083
1400
|
<div class="table-container">
|
|
1084
1401
|
<table>
|
|
@@ -1105,6 +1422,19 @@ class TaskList extends HTMLElement {
|
|
|
1105
1422
|
`;
|
|
1106
1423
|
this._shadow.addEventListener("click", (e) => {
|
|
1107
1424
|
const target = e.target;
|
|
1425
|
+
const nsRow = target.closest(".namespace-row");
|
|
1426
|
+
if (nsRow) {
|
|
1427
|
+
const ns = nsRow.dataset.ns;
|
|
1428
|
+
if (ns) {
|
|
1429
|
+
if (this._expandedNamespaces.has(ns)) {
|
|
1430
|
+
this._expandedNamespaces.delete(ns);
|
|
1431
|
+
} else {
|
|
1432
|
+
this._expandedNamespaces.add(ns);
|
|
1433
|
+
}
|
|
1434
|
+
this.renderRows();
|
|
1435
|
+
}
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1108
1438
|
const btn = target.closest("button");
|
|
1109
1439
|
if (btn) {
|
|
1110
1440
|
const action = btn.dataset.action;
|
|
@@ -1119,7 +1449,7 @@ class TaskList extends HTMLElement {
|
|
|
1119
1449
|
return;
|
|
1120
1450
|
}
|
|
1121
1451
|
const tr = target.closest("tr");
|
|
1122
|
-
if (tr && !target.closest(".col-actions")) {
|
|
1452
|
+
if (tr && !target.closest(".col-actions") && !tr.classList.contains("namespace-row")) {
|
|
1123
1453
|
const id = tr.dataset.id;
|
|
1124
1454
|
this.dispatchEvent(new CustomEvent("task-select", {
|
|
1125
1455
|
detail: id,
|
|
@@ -1744,6 +2074,7 @@ class DevTools extends HTMLElement {
|
|
|
1744
2074
|
__publicField(this, "$taskDetail");
|
|
1745
2075
|
__publicField(this, "$timeline");
|
|
1746
2076
|
__publicField(this, "$trigger");
|
|
2077
|
+
__publicField(this, "$overlay");
|
|
1747
2078
|
this._shadow = this.attachShadow({ mode: "open" });
|
|
1748
2079
|
this.store = new DevToolsStore();
|
|
1749
2080
|
}
|
|
@@ -1857,6 +2188,7 @@ class DevTools extends HTMLElement {
|
|
|
1857
2188
|
this.$taskDetail = this._shadow.querySelector("hs-task-detail");
|
|
1858
2189
|
this.$timeline = this._shadow.querySelector("hs-timeline");
|
|
1859
2190
|
this.$trigger = this._shadow.querySelector("hs-floating-trigger");
|
|
2191
|
+
this.$overlay = this._shadow.querySelector(".overlay");
|
|
1860
2192
|
}
|
|
1861
2193
|
bindStore() {
|
|
1862
2194
|
try {
|
|
@@ -1872,6 +2204,7 @@ class DevTools extends HTMLElement {
|
|
|
1872
2204
|
if (isOpen) {
|
|
1873
2205
|
this.$panel.classList.add("open");
|
|
1874
2206
|
this.$trigger.style.display = "none";
|
|
2207
|
+
this.$overlay.style.display = "block";
|
|
1875
2208
|
if (pos === "right") {
|
|
1876
2209
|
this.$panel.style.right = "0";
|
|
1877
2210
|
} else {
|
|
@@ -1880,6 +2213,7 @@ class DevTools extends HTMLElement {
|
|
|
1880
2213
|
} else {
|
|
1881
2214
|
this.$panel.classList.remove("open");
|
|
1882
2215
|
this.$trigger.style.display = "block";
|
|
2216
|
+
this.$overlay.style.display = "none";
|
|
1883
2217
|
if (pos === "right") {
|
|
1884
2218
|
this.$panel.style.right = `-${size.width}px`;
|
|
1885
2219
|
} else {
|
|
@@ -2024,9 +2358,8 @@ class DevTools extends HTMLElement {
|
|
|
2024
2358
|
const text = e.detail;
|
|
2025
2359
|
this.store.setFilterText(text);
|
|
2026
2360
|
});
|
|
2027
|
-
this.addEventListener("
|
|
2028
|
-
|
|
2029
|
-
this.store.setPanelSize(size);
|
|
2361
|
+
this.$overlay.addEventListener("click", () => {
|
|
2362
|
+
this.store.toggle();
|
|
2030
2363
|
});
|
|
2031
2364
|
this.$taskList.addEventListener("task-select", (e) => {
|
|
2032
2365
|
const id = e.detail;
|
|
@@ -2078,6 +2411,16 @@ class DevTools extends HTMLElement {
|
|
|
2078
2411
|
color: var(--hs-text);
|
|
2079
2412
|
line-height: var(--hs-line-height);
|
|
2080
2413
|
}
|
|
2414
|
+
.overlay {
|
|
2415
|
+
position: fixed;
|
|
2416
|
+
top: 0;
|
|
2417
|
+
left: 0;
|
|
2418
|
+
width: 100vw;
|
|
2419
|
+
height: 100vh;
|
|
2420
|
+
background: rgba(0, 0, 0, 0.5);
|
|
2421
|
+
z-index: calc(var(--hs-z-index) - 1); /* 确保在面板之下,但在应用之上 */
|
|
2422
|
+
display: none; /* 默认隐藏 */
|
|
2423
|
+
}
|
|
2081
2424
|
.panel {
|
|
2082
2425
|
position: fixed;
|
|
2083
2426
|
background: var(--hs-bg);
|
|
@@ -2141,6 +2484,7 @@ class DevTools extends HTMLElement {
|
|
|
2141
2484
|
}
|
|
2142
2485
|
</style>
|
|
2143
2486
|
|
|
2487
|
+
<div class="overlay"></div>
|
|
2144
2488
|
<hs-floating-trigger></hs-floating-trigger>
|
|
2145
2489
|
|
|
2146
2490
|
<div class="panel dock-right">
|