@markdy/renderer-dom 1.0.13 → 1.0.14
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/dist/index.js +578 -79
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2503,15 +2503,26 @@ function ensureSceneStyles(doc) {
|
|
|
2503
2503
|
will-change: opacity, transform;
|
|
2504
2504
|
}
|
|
2505
2505
|
.markdy-footer {
|
|
2506
|
-
font-family:
|
|
2506
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
2507
2507
|
width: 100%;
|
|
2508
2508
|
box-sizing: border-box;
|
|
2509
|
+
display: flex;
|
|
2510
|
+
align-items: center;
|
|
2511
|
+
justify-content: space-between;
|
|
2512
|
+
gap: 8px;
|
|
2513
|
+
padding: 6px 12px;
|
|
2514
|
+
background: var(--md-footer-bg, rgba(15, 23, 42, 0.85));
|
|
2515
|
+
backdrop-filter: blur(16px);
|
|
2516
|
+
-webkit-backdrop-filter: blur(16px);
|
|
2517
|
+
border-top: 1px solid var(--md-footer-border, rgba(148, 163, 184, 0.15));
|
|
2518
|
+
z-index: 20;
|
|
2509
2519
|
}
|
|
2510
2520
|
.markdy-controls {
|
|
2511
2521
|
display: flex;
|
|
2512
2522
|
align-items: center;
|
|
2513
|
-
|
|
2514
|
-
|
|
2523
|
+
justify-content: flex-start;
|
|
2524
|
+
width: 100%;
|
|
2525
|
+
gap: 8px;
|
|
2515
2526
|
max-width: 100%;
|
|
2516
2527
|
overflow-x: auto;
|
|
2517
2528
|
scrollbar-width: none;
|
|
@@ -2519,65 +2530,367 @@ function ensureSceneStyles(doc) {
|
|
|
2519
2530
|
.markdy-controls::-webkit-scrollbar {
|
|
2520
2531
|
display: none;
|
|
2521
2532
|
}
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2533
|
+
.markdy-controls-group {
|
|
2534
|
+
display: inline-flex;
|
|
2535
|
+
align-items: center;
|
|
2536
|
+
gap: 4px;
|
|
2537
|
+
flex-shrink: 0;
|
|
2538
|
+
}
|
|
2539
|
+
.markdy-controls-playback {
|
|
2540
|
+
display: inline-flex;
|
|
2541
|
+
align-items: center;
|
|
2542
|
+
gap: 4px;
|
|
2543
|
+
flex-shrink: 0;
|
|
2544
|
+
}
|
|
2545
|
+
.markdy-controls-timeline {
|
|
2546
|
+
display: flex;
|
|
2547
|
+
align-items: center;
|
|
2548
|
+
gap: 8px;
|
|
2549
|
+
flex: 1 1 180px;
|
|
2550
|
+
min-width: 110px;
|
|
2551
|
+
max-width: 340px;
|
|
2552
|
+
}
|
|
2553
|
+
.markdy-controls-tools {
|
|
2554
|
+
display: inline-flex;
|
|
2555
|
+
align-items: center;
|
|
2556
|
+
gap: 4px;
|
|
2557
|
+
flex-shrink: 0;
|
|
2558
|
+
margin-left: auto;
|
|
2559
|
+
}
|
|
2560
|
+
.markdy-control-divider {
|
|
2561
|
+
width: 1px;
|
|
2562
|
+
height: 14px;
|
|
2563
|
+
background: var(--md-divider, rgba(148, 163, 184, 0.2));
|
|
2564
|
+
margin: 0 2px;
|
|
2565
|
+
flex-shrink: 0;
|
|
2528
2566
|
}
|
|
2529
2567
|
.markdy-controls button {
|
|
2530
2568
|
appearance: none;
|
|
2569
|
+
-webkit-appearance: none;
|
|
2531
2570
|
touch-action: manipulation;
|
|
2532
2571
|
user-select: none;
|
|
2533
2572
|
-webkit-user-select: none;
|
|
2534
|
-
border: 1px solid var(--md-control-border, rgba(148, 163, 184, 0.
|
|
2535
|
-
border-radius:
|
|
2536
|
-
background: var(--md-control-bg, rgba(
|
|
2537
|
-
color: var(--md-control-text, #
|
|
2573
|
+
border: 1px solid var(--md-control-border, rgba(148, 163, 184, 0.2));
|
|
2574
|
+
border-radius: 7px;
|
|
2575
|
+
background: var(--md-control-bg, rgba(255, 255, 255, 0.04));
|
|
2576
|
+
color: var(--md-control-text, #94a3b8);
|
|
2538
2577
|
cursor: pointer;
|
|
2539
|
-
font: 600
|
|
2540
|
-
|
|
2541
|
-
min-
|
|
2542
|
-
|
|
2578
|
+
font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2579
|
+
height: 27px;
|
|
2580
|
+
min-width: 27px;
|
|
2581
|
+
padding: 0 6px;
|
|
2543
2582
|
display: inline-flex;
|
|
2544
2583
|
align-items: center;
|
|
2545
2584
|
justify-content: center;
|
|
2546
|
-
gap:
|
|
2585
|
+
gap: 5px;
|
|
2547
2586
|
white-space: nowrap;
|
|
2548
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.
|
|
2587
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
2549
2588
|
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
|
2550
2589
|
}
|
|
2551
2590
|
.markdy-controls button:hover:not([aria-pressed="true"]) {
|
|
2552
|
-
background: var(--md-control-hover-bg,
|
|
2553
|
-
color: var(--md-control-hover-text, #
|
|
2554
|
-
border-color: var(--md-control-hover-border,
|
|
2555
|
-
|
|
2591
|
+
background: var(--md-control-hover-bg, rgba(255, 255, 255, 0.1));
|
|
2592
|
+
color: var(--md-control-hover-text, #f8fafc);
|
|
2593
|
+
border-color: var(--md-control-hover-border, rgba(148, 163, 184, 0.35));
|
|
2594
|
+
transform: translateY(-1px);
|
|
2595
|
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.12);
|
|
2556
2596
|
}
|
|
2557
2597
|
.markdy-controls button[aria-pressed="true"] {
|
|
2558
|
-
background: #
|
|
2598
|
+
background: var(--accent, #10b981) !important;
|
|
2559
2599
|
color: #ffffff !important;
|
|
2560
|
-
border-color: #
|
|
2561
|
-
box-shadow: 0
|
|
2600
|
+
border-color: var(--accent, #10b981) !important;
|
|
2601
|
+
box-shadow: 0 0 10px var(--accent-glow, rgba(16, 185, 129, 0.4)) !important;
|
|
2562
2602
|
}
|
|
2563
2603
|
.markdy-controls button:focus-visible {
|
|
2564
|
-
outline: 2px solid #
|
|
2604
|
+
outline: 2px solid var(--accent, #10b981);
|
|
2565
2605
|
outline-offset: 1px;
|
|
2566
2606
|
}
|
|
2567
2607
|
.markdy-controls button:active {
|
|
2568
2608
|
transform: scale(0.95);
|
|
2569
2609
|
}
|
|
2570
|
-
.markdy-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
.markdy-control-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2610
|
+
.markdy-icon {
|
|
2611
|
+
display: inline-block;
|
|
2612
|
+
flex-shrink: 0;
|
|
2613
|
+
vertical-align: middle;
|
|
2614
|
+
}
|
|
2615
|
+
.markdy-control-play {
|
|
2616
|
+
background: var(--accent, #10b981) !important;
|
|
2617
|
+
color: #ffffff !important;
|
|
2618
|
+
border-color: var(--accent, #10b981) !important;
|
|
2619
|
+
padding: 0 10px !important;
|
|
2620
|
+
font-weight: 700 !important;
|
|
2621
|
+
box-shadow: 0 2px 8px var(--accent-glow, rgba(16, 185, 129, 0.35)) !important;
|
|
2622
|
+
}
|
|
2623
|
+
.markdy-control-play:hover {
|
|
2624
|
+
filter: brightness(1.08);
|
|
2625
|
+
box-shadow: 0 2px 12px var(--accent-glow, rgba(16, 185, 129, 0.55)) !important;
|
|
2626
|
+
transform: translateY(-1px) scale(1.02);
|
|
2627
|
+
}
|
|
2628
|
+
.markdy-badge {
|
|
2629
|
+
display: inline-flex;
|
|
2630
|
+
align-items: center;
|
|
2631
|
+
gap: 4px;
|
|
2632
|
+
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2633
|
+
font-size: 11px;
|
|
2634
|
+
font-weight: 600;
|
|
2635
|
+
color: var(--md-control-text, #94a3b8);
|
|
2636
|
+
text-decoration: none;
|
|
2637
|
+
padding: 3px 8px;
|
|
2638
|
+
border-radius: 999px;
|
|
2639
|
+
background: var(--md-control-bg, rgba(255, 255, 255, 0.05));
|
|
2640
|
+
border: 1px solid var(--md-control-border, rgba(148, 163, 184, 0.18));
|
|
2641
|
+
margin-left: auto;
|
|
2642
|
+
flex-shrink: 0;
|
|
2643
|
+
transition: all 0.15s ease;
|
|
2644
|
+
white-space: nowrap;
|
|
2645
|
+
}
|
|
2646
|
+
.markdy-badge:hover {
|
|
2647
|
+
color: var(--accent, #10b981);
|
|
2648
|
+
background: var(--accent-light, rgba(16, 185, 129, 0.12));
|
|
2649
|
+
border-color: var(--accent, #10b981);
|
|
2650
|
+
transform: translateY(-1px);
|
|
2651
|
+
}
|
|
2652
|
+
.markdy-speed-group {
|
|
2653
|
+
display: inline-flex;
|
|
2654
|
+
align-items: center;
|
|
2655
|
+
background: var(--md-segmented-bg, rgba(0, 0, 0, 0.18));
|
|
2656
|
+
border: 1px solid var(--md-control-border, rgba(148, 163, 184, 0.18));
|
|
2657
|
+
border-radius: 8px;
|
|
2658
|
+
padding: 2px;
|
|
2659
|
+
gap: 1px;
|
|
2660
|
+
}
|
|
2661
|
+
.markdy-speed-group .markdy-control-rate {
|
|
2662
|
+
border: none;
|
|
2663
|
+
background: transparent;
|
|
2664
|
+
border-radius: 5px;
|
|
2665
|
+
height: 22px;
|
|
2666
|
+
min-width: 25px;
|
|
2667
|
+
padding: 0 5px;
|
|
2668
|
+
font-size: 10px;
|
|
2669
|
+
font-weight: 700;
|
|
2670
|
+
color: var(--md-control-text, #94a3b8);
|
|
2671
|
+
box-shadow: none;
|
|
2672
|
+
}
|
|
2673
|
+
.markdy-speed-group .markdy-control-rate:hover:not([aria-pressed="true"]) {
|
|
2674
|
+
background: rgba(255, 255, 255, 0.08);
|
|
2675
|
+
color: #ffffff;
|
|
2676
|
+
transform: none;
|
|
2677
|
+
}
|
|
2678
|
+
.markdy-speed-group .markdy-control-rate[aria-pressed="true"] {
|
|
2679
|
+
background: var(--accent, #10b981) !important;
|
|
2680
|
+
color: #ffffff !important;
|
|
2681
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25) !important;
|
|
2682
|
+
}
|
|
2683
|
+
.markdy-control-seek {
|
|
2684
|
+
appearance: none;
|
|
2685
|
+
-webkit-appearance: none;
|
|
2686
|
+
width: 100%;
|
|
2687
|
+
height: 5px;
|
|
2688
|
+
border-radius: 999px;
|
|
2689
|
+
background: linear-gradient(
|
|
2690
|
+
to right,
|
|
2691
|
+
var(--accent, #10b981) 0%,
|
|
2692
|
+
var(--accent, #10b981) var(--seek-pct, 0%),
|
|
2693
|
+
rgba(148, 163, 184, 0.22) var(--seek-pct, 0%),
|
|
2694
|
+
rgba(148, 163, 184, 0.22) 100%
|
|
2695
|
+
);
|
|
2696
|
+
outline: none;
|
|
2697
|
+
cursor: pointer;
|
|
2698
|
+
margin: 0;
|
|
2699
|
+
transition: height 0.15s ease;
|
|
2700
|
+
}
|
|
2701
|
+
.markdy-control-seek:hover {
|
|
2702
|
+
height: 7px;
|
|
2703
|
+
}
|
|
2704
|
+
.markdy-control-seek::-webkit-slider-thumb {
|
|
2705
|
+
appearance: none;
|
|
2706
|
+
-webkit-appearance: none;
|
|
2707
|
+
width: 12px;
|
|
2708
|
+
height: 12px;
|
|
2709
|
+
border-radius: 50%;
|
|
2710
|
+
background: #ffffff;
|
|
2711
|
+
border: 2px solid var(--accent, #10b981);
|
|
2712
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
|
|
2713
|
+
cursor: pointer;
|
|
2714
|
+
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
2715
|
+
}
|
|
2716
|
+
.markdy-control-seek:hover::-webkit-slider-thumb {
|
|
2717
|
+
transform: scale(1.25);
|
|
2718
|
+
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2719
|
+
}
|
|
2720
|
+
.markdy-control-seek::-moz-range-thumb {
|
|
2721
|
+
width: 12px;
|
|
2722
|
+
height: 12px;
|
|
2723
|
+
border-radius: 50%;
|
|
2724
|
+
background: #ffffff;
|
|
2725
|
+
border: 2px solid var(--accent, #10b981);
|
|
2726
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
|
|
2727
|
+
cursor: pointer;
|
|
2728
|
+
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
2729
|
+
}
|
|
2730
|
+
.markdy-control-seek:hover::-moz-range-thumb {
|
|
2731
|
+
transform: scale(1.25);
|
|
2732
|
+
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2733
|
+
}
|
|
2734
|
+
.markdy-control-time {
|
|
2735
|
+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
2736
|
+
font-size: 10px;
|
|
2737
|
+
font-weight: 600;
|
|
2738
|
+
color: var(--md-control-text, #94a3b8);
|
|
2739
|
+
white-space: nowrap;
|
|
2740
|
+
flex-shrink: 0;
|
|
2741
|
+
letter-spacing: -0.02em;
|
|
2742
|
+
}
|
|
2743
|
+
.markdy-btn-flashed {
|
|
2744
|
+
background: rgba(16, 185, 129, 0.2) !important;
|
|
2745
|
+
color: #10b981 !important;
|
|
2746
|
+
border-color: #10b981 !important;
|
|
2747
|
+
}
|
|
2748
|
+
/* \u2500\u2500 Code panel overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
2749
|
+
.markdy-code-panel-overlay {
|
|
2750
|
+
position: fixed;
|
|
2751
|
+
inset: 0;
|
|
2752
|
+
z-index: 9000;
|
|
2753
|
+
background: rgba(2, 6, 23, 0.55);
|
|
2754
|
+
backdrop-filter: blur(3px);
|
|
2755
|
+
-webkit-backdrop-filter: blur(3px);
|
|
2756
|
+
display: flex;
|
|
2757
|
+
align-items: center;
|
|
2758
|
+
justify-content: center;
|
|
2759
|
+
padding: 24px;
|
|
2760
|
+
box-sizing: border-box;
|
|
2761
|
+
opacity: 0;
|
|
2762
|
+
animation: markdy-fade-in 0.18s ease forwards;
|
|
2763
|
+
}
|
|
2764
|
+
.markdy-code-panel-overlay[data-closing="1"] {
|
|
2765
|
+
animation: markdy-fade-out 0.15s ease forwards;
|
|
2766
|
+
}
|
|
2767
|
+
@keyframes markdy-fade-in {
|
|
2768
|
+
from { opacity: 0; }
|
|
2769
|
+
to { opacity: 1; }
|
|
2770
|
+
}
|
|
2771
|
+
@keyframes markdy-fade-out {
|
|
2772
|
+
from { opacity: 1; }
|
|
2773
|
+
to { opacity: 0; }
|
|
2774
|
+
}
|
|
2775
|
+
.markdy-code-panel {
|
|
2776
|
+
position: relative;
|
|
2777
|
+
background: #0f172a;
|
|
2778
|
+
border: 1px solid rgba(71, 85, 105, 0.7);
|
|
2779
|
+
border-radius: 12px;
|
|
2780
|
+
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
|
|
2781
|
+
width: 100%;
|
|
2782
|
+
max-width: 780px;
|
|
2783
|
+
max-height: min(680px, 82vh);
|
|
2784
|
+
display: flex;
|
|
2785
|
+
flex-direction: column;
|
|
2786
|
+
overflow: hidden;
|
|
2787
|
+
transform: translateY(10px) scale(0.98);
|
|
2788
|
+
animation: markdy-panel-in 0.2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
2789
|
+
}
|
|
2790
|
+
.markdy-code-panel-overlay[data-closing="1"] .markdy-code-panel {
|
|
2791
|
+
animation: markdy-panel-out 0.15s ease forwards;
|
|
2792
|
+
}
|
|
2793
|
+
@keyframes markdy-panel-in {
|
|
2794
|
+
from { transform: translateY(12px) scale(0.97); opacity: 0; }
|
|
2795
|
+
to { transform: translateY(0) scale(1); opacity: 1; }
|
|
2796
|
+
}
|
|
2797
|
+
@keyframes markdy-panel-out {
|
|
2798
|
+
from { transform: translateY(0) scale(1); opacity: 1; }
|
|
2799
|
+
to { transform: translateY(8px) scale(0.98); opacity: 0; }
|
|
2800
|
+
}
|
|
2801
|
+
.markdy-code-panel__header {
|
|
2802
|
+
display: flex;
|
|
2803
|
+
align-items: center;
|
|
2804
|
+
justify-content: space-between;
|
|
2805
|
+
padding: 12px 16px 10px;
|
|
2806
|
+
border-bottom: 1px solid rgba(71, 85, 105, 0.4);
|
|
2807
|
+
flex-shrink: 0;
|
|
2808
|
+
}
|
|
2809
|
+
.markdy-code-panel__title {
|
|
2810
|
+
font: 600 12px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
2811
|
+
color: #94a3b8;
|
|
2812
|
+
letter-spacing: 0.06em;
|
|
2813
|
+
text-transform: uppercase;
|
|
2814
|
+
}
|
|
2815
|
+
.markdy-code-panel__actions {
|
|
2816
|
+
display: flex;
|
|
2817
|
+
align-items: center;
|
|
2818
|
+
gap: 6px;
|
|
2819
|
+
}
|
|
2820
|
+
.markdy-code-panel__copy,
|
|
2821
|
+
.markdy-code-panel__playground,
|
|
2822
|
+
.markdy-code-panel__close {
|
|
2823
|
+
appearance: none;
|
|
2824
|
+
border: 1px solid rgba(71, 85, 105, 0.55);
|
|
2825
|
+
border-radius: 6px;
|
|
2826
|
+
background: rgba(30, 41, 59, 0.8);
|
|
2827
|
+
color: #94a3b8;
|
|
2828
|
+
cursor: pointer;
|
|
2829
|
+
font: 600 10.5px/1.2 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
2830
|
+
text-decoration: none;
|
|
2831
|
+
padding: 3px 9px;
|
|
2832
|
+
min-height: 24px;
|
|
2833
|
+
display: inline-flex;
|
|
2834
|
+
align-items: center;
|
|
2835
|
+
gap: 4px;
|
|
2836
|
+
transition: all 0.15s ease;
|
|
2837
|
+
white-space: nowrap;
|
|
2838
|
+
}
|
|
2839
|
+
.markdy-code-panel__playground {
|
|
2840
|
+
background: var(--accent-light, rgba(16, 185, 129, 0.15));
|
|
2841
|
+
color: var(--accent, #10b981);
|
|
2842
|
+
border-color: var(--accent, #10b981);
|
|
2843
|
+
font-weight: 700;
|
|
2844
|
+
}
|
|
2845
|
+
.markdy-code-panel__playground:hover {
|
|
2846
|
+
background: var(--accent, #10b981);
|
|
2847
|
+
color: #ffffff;
|
|
2848
|
+
border-color: var(--accent, #10b981);
|
|
2849
|
+
transform: translateY(-1px);
|
|
2850
|
+
}
|
|
2851
|
+
.markdy-code-panel__copy:hover,
|
|
2852
|
+
.markdy-code-panel__close:hover {
|
|
2853
|
+
background: rgba(51, 65, 85, 0.95);
|
|
2854
|
+
color: #e2e8f0;
|
|
2855
|
+
border-color: #64748b;
|
|
2856
|
+
}
|
|
2857
|
+
.markdy-code-panel__copy:focus-visible,
|
|
2858
|
+
.markdy-code-panel__playground:focus-visible,
|
|
2859
|
+
.markdy-code-panel__close:focus-visible {
|
|
2860
|
+
outline: 2px solid #3b82f6;
|
|
2861
|
+
outline-offset: 1px;
|
|
2862
|
+
}
|
|
2863
|
+
.markdy-code-panel__body {
|
|
2864
|
+
overflow-y: auto;
|
|
2865
|
+
flex: 1 1 auto;
|
|
2866
|
+
padding: 16px 20px;
|
|
2867
|
+
scrollbar-width: thin;
|
|
2868
|
+
scrollbar-color: rgba(71, 85, 105, 0.5) transparent;
|
|
2869
|
+
}
|
|
2870
|
+
.markdy-code-panel__body::-webkit-scrollbar {
|
|
2871
|
+
width: 5px;
|
|
2872
|
+
}
|
|
2873
|
+
.markdy-code-panel__body::-webkit-scrollbar-track {
|
|
2874
|
+
background: transparent;
|
|
2875
|
+
}
|
|
2876
|
+
.markdy-code-panel__body::-webkit-scrollbar-thumb {
|
|
2877
|
+
background: rgba(71, 85, 105, 0.5);
|
|
2878
|
+
border-radius: 9999px;
|
|
2879
|
+
}
|
|
2880
|
+
.markdy-code-panel__pre {
|
|
2881
|
+
margin: 0;
|
|
2882
|
+
font: 400 12.5px/1.65 "JetBrains Mono", ui-monospace, "Cascadia Code", "Fira Code", monospace;
|
|
2883
|
+
color: #e2e8f0;
|
|
2884
|
+
white-space: pre;
|
|
2885
|
+
tab-size: 2;
|
|
2886
|
+
overflow-x: auto;
|
|
2887
|
+
}
|
|
2888
|
+
/* Syntax tinting \u2014 purely decorative, lightweight regex-free colorization */
|
|
2889
|
+
.markdy-code-panel__pre .t-keyword { color: #7dd3fc; }
|
|
2890
|
+
.markdy-code-panel__pre .t-string { color: #86efac; }
|
|
2891
|
+
.markdy-code-panel__pre .t-comment { color: #64748b; font-style: italic; }
|
|
2892
|
+
.markdy-code-panel__pre .t-edge { color: #f9a8d4; }
|
|
2893
|
+
.markdy-code-panel__pre .t-number { color: #fcd34d; }
|
|
2581
2894
|
.markdy-control-rate {
|
|
2582
2895
|
font-family: "JetBrains Mono", monospace, system-ui;
|
|
2583
2896
|
font-size: 9px;
|
|
@@ -2849,7 +3162,9 @@ function createDiagram(opts) {
|
|
|
2849
3162
|
resetView: resetViewButton,
|
|
2850
3163
|
fullscreen: fullscreenButton,
|
|
2851
3164
|
svg: svgButton,
|
|
2852
|
-
share: shareButton
|
|
3165
|
+
share: shareButton,
|
|
3166
|
+
code: codeButton,
|
|
3167
|
+
theme: themeButton
|
|
2853
3168
|
} = player.controls;
|
|
2854
3169
|
const copyright = player.chrome.badge;
|
|
2855
3170
|
const progressMode = player.chrome.progress;
|
|
@@ -2926,22 +3241,13 @@ function createDiagram(opts) {
|
|
|
2926
3241
|
let badge = null;
|
|
2927
3242
|
if (copyright) {
|
|
2928
3243
|
badge = document.createElement("a");
|
|
3244
|
+
badge.className = "markdy-badge";
|
|
2929
3245
|
badge.href = `${MARKDY_PLAYGROUND_URL}#code=${encodeCodeForPlaygroundHash(code)}`;
|
|
2930
3246
|
badge.target = "_blank";
|
|
2931
3247
|
badge.rel = "noopener noreferrer";
|
|
2932
|
-
badge.
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
alignItems: "center",
|
|
2936
|
-
textAlign: "right",
|
|
2937
|
-
fontSize: "10px",
|
|
2938
|
-
fontFamily: "system-ui, sans-serif",
|
|
2939
|
-
color: "#999",
|
|
2940
|
-
textDecoration: "none",
|
|
2941
|
-
padding: "0",
|
|
2942
|
-
opacity: "0.7",
|
|
2943
|
-
marginLeft: "auto"
|
|
2944
|
-
});
|
|
3248
|
+
badge.title = "Open and edit in Markdy Playground";
|
|
3249
|
+
badge.style.marginLeft = "auto";
|
|
3250
|
+
badge.innerHTML = `<span style="opacity:0.9">\u26A1</span> Markdy`;
|
|
2945
3251
|
ensureFooter().appendChild(badge);
|
|
2946
3252
|
}
|
|
2947
3253
|
ensureSceneStyles(document);
|
|
@@ -3169,8 +3475,24 @@ function createDiagram(opts) {
|
|
|
3169
3475
|
let controlsPlayButton = null;
|
|
3170
3476
|
let controlsRateButtons = [];
|
|
3171
3477
|
let controlsSeekBar = null;
|
|
3478
|
+
let controlsTimeEl = null;
|
|
3172
3479
|
let controlsFitButton = null;
|
|
3173
3480
|
let fitViewActive = false;
|
|
3481
|
+
const ICONS2 = {
|
|
3482
|
+
play: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>',
|
|
3483
|
+
pause: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>',
|
|
3484
|
+
restart: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>',
|
|
3485
|
+
prevBeat: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h2v12H6zm3.5 6 8.5 6V6z"/></svg>',
|
|
3486
|
+
nextBeat: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/></svg>',
|
|
3487
|
+
fit: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>',
|
|
3488
|
+
resetView: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>',
|
|
3489
|
+
fullscreen: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg>',
|
|
3490
|
+
svg: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>',
|
|
3491
|
+
share: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>',
|
|
3492
|
+
code: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>',
|
|
3493
|
+
theme: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 3v18"/><path d="M12 3a9 9 0 0 1 0 18z" fill="currentColor"/></svg>',
|
|
3494
|
+
check: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>'
|
|
3495
|
+
};
|
|
3174
3496
|
function applyViewportTransform() {
|
|
3175
3497
|
viewportTransform.style.transform = `translate(${viewportPanX}px, ${viewportPanY}px) scale(${viewportScale})`;
|
|
3176
3498
|
}
|
|
@@ -3257,7 +3579,7 @@ function createDiagram(opts) {
|
|
|
3257
3579
|
function syncControls() {
|
|
3258
3580
|
if (controlsPlayButton) {
|
|
3259
3581
|
const playing = isPlaying;
|
|
3260
|
-
controlsPlayButton.
|
|
3582
|
+
controlsPlayButton.innerHTML = `${playing ? ICONS2.pause : ICONS2.play}${playing ? "Pause" : "Play"}`;
|
|
3261
3583
|
const playLabel = playing ? "Pause diagram" : "Play diagram";
|
|
3262
3584
|
controlsPlayButton.setAttribute("aria-label", playLabel);
|
|
3263
3585
|
controlsPlayButton.title = playLabel;
|
|
@@ -3267,7 +3589,16 @@ function createDiagram(opts) {
|
|
|
3267
3589
|
const active = Math.abs(rate - playbackRate) < 1e-3;
|
|
3268
3590
|
button.setAttribute("aria-pressed", active ? "true" : "false");
|
|
3269
3591
|
}
|
|
3270
|
-
if (controlsSeekBar)
|
|
3592
|
+
if (controlsSeekBar) {
|
|
3593
|
+
controlsSeekBar.value = String(sceneMs / 1e3);
|
|
3594
|
+
const pct = totalDurationMs > 0 ? sceneMs / totalDurationMs * 100 : 0;
|
|
3595
|
+
controlsSeekBar.style.setProperty("--seek-pct", `${pct}%`);
|
|
3596
|
+
}
|
|
3597
|
+
if (controlsTimeEl) {
|
|
3598
|
+
const cur = (sceneMs / 1e3).toFixed(1);
|
|
3599
|
+
const tot = durationSeconds.toFixed(1);
|
|
3600
|
+
controlsTimeEl.textContent = `${cur}s / ${tot}s`;
|
|
3601
|
+
}
|
|
3271
3602
|
if (controlsFitButton) {
|
|
3272
3603
|
controlsFitButton.setAttribute("aria-pressed", fitViewActive ? "true" : "false");
|
|
3273
3604
|
}
|
|
@@ -3377,17 +3708,21 @@ function createDiagram(opts) {
|
|
|
3377
3708
|
diagram.play();
|
|
3378
3709
|
}
|
|
3379
3710
|
}
|
|
3380
|
-
function makeControlButton(label, ariaLabel) {
|
|
3711
|
+
function makeControlButton(label, ariaLabel, iconSvg) {
|
|
3381
3712
|
const button = document.createElement("button");
|
|
3382
3713
|
button.type = "button";
|
|
3383
|
-
button.textContent = label;
|
|
3384
3714
|
button.setAttribute("aria-label", ariaLabel);
|
|
3385
3715
|
button.title = ariaLabel;
|
|
3716
|
+
if (iconSvg) {
|
|
3717
|
+
button.innerHTML = `${iconSvg}${label}`;
|
|
3718
|
+
} else {
|
|
3719
|
+
button.textContent = label;
|
|
3720
|
+
}
|
|
3386
3721
|
return button;
|
|
3387
3722
|
}
|
|
3388
3723
|
function mountPlayControl(toolbar) {
|
|
3389
3724
|
if (!playButton) return;
|
|
3390
|
-
controlsPlayButton = makeControlButton("Play", "Play diagram");
|
|
3725
|
+
controlsPlayButton = makeControlButton("Play", "Play diagram", ICONS2.play);
|
|
3391
3726
|
controlsPlayButton.className = "markdy-control-play";
|
|
3392
3727
|
controlsPlayButton.addEventListener("click", togglePlayback);
|
|
3393
3728
|
toolbar.appendChild(controlsPlayButton);
|
|
@@ -3396,14 +3731,15 @@ function createDiagram(opts) {
|
|
|
3396
3731
|
const wanted = position === "prev" ? prevBeatButton : nextBeatButton;
|
|
3397
3732
|
if (!wanted || plan.beats.length < 2) return;
|
|
3398
3733
|
const label = position === "prev" ? "Prev" : "Next";
|
|
3399
|
-
const
|
|
3734
|
+
const icon = position === "prev" ? ICONS2.prevBeat : ICONS2.nextBeat;
|
|
3735
|
+
const button = makeControlButton(label, `${label === "Prev" ? "Previous" : "Next"} beat`, icon);
|
|
3400
3736
|
button.className = `markdy-control-${position}-beat`;
|
|
3401
3737
|
button.addEventListener("click", () => position === "prev" ? diagram.prevBeat() : diagram.nextBeat());
|
|
3402
3738
|
toolbar.appendChild(button);
|
|
3403
3739
|
}
|
|
3404
3740
|
function mountRestartControl(toolbar) {
|
|
3405
3741
|
if (!restartButton) return;
|
|
3406
|
-
const button = makeControlButton("Restart", "Restart diagram");
|
|
3742
|
+
const button = makeControlButton("Restart", "Restart diagram", ICONS2.restart);
|
|
3407
3743
|
button.className = "markdy-control-restart";
|
|
3408
3744
|
button.addEventListener("click", () => {
|
|
3409
3745
|
diagram.seek(0);
|
|
@@ -3423,6 +3759,10 @@ function createDiagram(opts) {
|
|
|
3423
3759
|
controlsSeekBar.setAttribute("aria-label", "Seek diagram timeline");
|
|
3424
3760
|
controlsSeekBar.addEventListener("input", () => diagram.seek(Number(controlsSeekBar?.value ?? 0)));
|
|
3425
3761
|
toolbar.appendChild(controlsSeekBar);
|
|
3762
|
+
controlsTimeEl = document.createElement("span");
|
|
3763
|
+
controlsTimeEl.className = "markdy-control-time";
|
|
3764
|
+
controlsTimeEl.textContent = `${(sceneMs / 1e3).toFixed(1)}s / ${durationSeconds.toFixed(1)}s`;
|
|
3765
|
+
toolbar.appendChild(controlsTimeEl);
|
|
3426
3766
|
}
|
|
3427
3767
|
function mountSpeedControls(toolbar) {
|
|
3428
3768
|
if (!speedControls) return;
|
|
@@ -3437,11 +3777,14 @@ function createDiagram(opts) {
|
|
|
3437
3777
|
});
|
|
3438
3778
|
}
|
|
3439
3779
|
function flashControlLabel(button, message) {
|
|
3440
|
-
const
|
|
3441
|
-
|
|
3780
|
+
const originalHtml = button.innerHTML;
|
|
3781
|
+
const isSuccess = !message.toLowerCase().includes("fail");
|
|
3782
|
+
button.innerHTML = isSuccess ? `${ICONS2.check}${message}` : message;
|
|
3783
|
+
button.classList.add("markdy-btn-flashed");
|
|
3442
3784
|
setTimeout(() => {
|
|
3443
|
-
button.
|
|
3444
|
-
|
|
3785
|
+
button.innerHTML = originalHtml;
|
|
3786
|
+
button.classList.remove("markdy-btn-flashed");
|
|
3787
|
+
}, 1500);
|
|
3445
3788
|
}
|
|
3446
3789
|
function downloadFile(filename, contents, type) {
|
|
3447
3790
|
const blob = new Blob([contents], { type });
|
|
@@ -3457,7 +3800,7 @@ function createDiagram(opts) {
|
|
|
3457
3800
|
}
|
|
3458
3801
|
function mountSvgControl(toolbar) {
|
|
3459
3802
|
if (!svgButton) return;
|
|
3460
|
-
const button = makeControlButton("SVG", "Export diagram as SVG");
|
|
3803
|
+
const button = makeControlButton("SVG", "Export diagram as SVG", ICONS2.svg);
|
|
3461
3804
|
button.className = "markdy-control-svg";
|
|
3462
3805
|
button.addEventListener("click", async () => {
|
|
3463
3806
|
const resumeAt = sceneMs;
|
|
@@ -3469,6 +3812,7 @@ function createDiagram(opts) {
|
|
|
3469
3812
|
const svg = exportDiagramAsVectorSvg2(container);
|
|
3470
3813
|
const name = (plan.title || "markdy-diagram").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
3471
3814
|
downloadFile(`${name || "markdy-diagram"}.svg`, svg, "image/svg+xml");
|
|
3815
|
+
flashControlLabel(button, "Saved");
|
|
3472
3816
|
} catch (error) {
|
|
3473
3817
|
onWarning({ severity: "warning", message: `SVG export failed: ${String(error)}`, line: 0 });
|
|
3474
3818
|
flashControlLabel(button, "Failed");
|
|
@@ -3481,7 +3825,7 @@ function createDiagram(opts) {
|
|
|
3481
3825
|
}
|
|
3482
3826
|
function mountShareControl(toolbar) {
|
|
3483
3827
|
if (!shareButton) return;
|
|
3484
|
-
const button = makeControlButton("Share", "Copy a share link for this diagram");
|
|
3828
|
+
const button = makeControlButton("Share", "Copy a share link for this diagram", ICONS2.share);
|
|
3485
3829
|
button.className = "markdy-control-share";
|
|
3486
3830
|
button.addEventListener("click", async () => {
|
|
3487
3831
|
try {
|
|
@@ -3496,9 +3840,132 @@ function createDiagram(opts) {
|
|
|
3496
3840
|
});
|
|
3497
3841
|
toolbar.appendChild(button);
|
|
3498
3842
|
}
|
|
3843
|
+
function mountThemeControl(toolbar) {
|
|
3844
|
+
if (!themeButton) return;
|
|
3845
|
+
const button = makeControlButton("Theme", "Toggle dark/light theme palette", ICONS2.theme);
|
|
3846
|
+
button.className = "markdy-control-theme";
|
|
3847
|
+
button.addEventListener("click", () => {
|
|
3848
|
+
const darkThemes = ["midnight", "blueprint", "graphite", "nebula", "terminal"];
|
|
3849
|
+
const lightThemes = ["paper", "editorial", "sketchy"];
|
|
3850
|
+
const currentName = plan.theme.name || "paper";
|
|
3851
|
+
const isDark = darkThemes.includes(currentName);
|
|
3852
|
+
const targetThemes = isDark ? lightThemes : darkThemes;
|
|
3853
|
+
const nextTheme = targetThemes[Math.floor(Math.random() * targetThemes.length)];
|
|
3854
|
+
flashControlLabel(button, nextTheme);
|
|
3855
|
+
container.dispatchEvent(
|
|
3856
|
+
new CustomEvent("markdy-theme-switch", {
|
|
3857
|
+
bubbles: true,
|
|
3858
|
+
detail: { theme: nextTheme, isDark: !isDark }
|
|
3859
|
+
})
|
|
3860
|
+
);
|
|
3861
|
+
});
|
|
3862
|
+
toolbar.appendChild(button);
|
|
3863
|
+
}
|
|
3864
|
+
function tintCode(raw) {
|
|
3865
|
+
return raw.split("\n").map((line) => {
|
|
3866
|
+
if (/^\s*\/\//.test(line)) {
|
|
3867
|
+
return `<span class="t-comment">${escHtml(line)}</span>`;
|
|
3868
|
+
}
|
|
3869
|
+
line = line.replace(/(->|<-|~>|--|<~)/g, '<span class="t-edge">$1</span>');
|
|
3870
|
+
line = line.replace(/"([^"]*)"/g, '"<span class="t-string">$1</span>"');
|
|
3871
|
+
line = line.replace(
|
|
3872
|
+
/^(\s*)(scene|beat|group|player|show|frame|glow|focus|layout|edge|annotation|start|end|decision|service|browser|gateway|database|cache|queue|worker|function|pod|user|client|hub|station|metric|mobile)\b/,
|
|
3873
|
+
'$1<span class="t-keyword">$2</span>'
|
|
3874
|
+
);
|
|
3875
|
+
line = line.replace(/\b(\d[\d.]*(?:ms|px|s)?)\b/g, '<span class="t-number">$1</span>');
|
|
3876
|
+
return line;
|
|
3877
|
+
}).join("\n");
|
|
3878
|
+
}
|
|
3879
|
+
function escHtml(str) {
|
|
3880
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3881
|
+
}
|
|
3882
|
+
function mountCodeControl(toolbar) {
|
|
3883
|
+
if (!codeButton) return;
|
|
3884
|
+
const button = makeControlButton("Code", "View MarkdyScript source");
|
|
3885
|
+
button.className = "markdy-control-code";
|
|
3886
|
+
button.setAttribute("aria-haspopup", "dialog");
|
|
3887
|
+
button.addEventListener("click", () => {
|
|
3888
|
+
const overlay = document.createElement("div");
|
|
3889
|
+
overlay.className = "markdy-code-panel-overlay";
|
|
3890
|
+
overlay.setAttribute("role", "dialog");
|
|
3891
|
+
overlay.setAttribute("aria-modal", "true");
|
|
3892
|
+
overlay.setAttribute("aria-label", "MarkdyScript source code");
|
|
3893
|
+
const panel = document.createElement("div");
|
|
3894
|
+
panel.className = "markdy-code-panel";
|
|
3895
|
+
const header = document.createElement("div");
|
|
3896
|
+
header.className = "markdy-code-panel__header";
|
|
3897
|
+
const title = document.createElement("div");
|
|
3898
|
+
title.className = "markdy-code-panel__title";
|
|
3899
|
+
title.textContent = "MarkdyScript source";
|
|
3900
|
+
const actions = document.createElement("div");
|
|
3901
|
+
actions.className = "markdy-code-panel__actions";
|
|
3902
|
+
const copyBtn = document.createElement("button");
|
|
3903
|
+
copyBtn.type = "button";
|
|
3904
|
+
copyBtn.className = "markdy-code-panel__copy";
|
|
3905
|
+
copyBtn.textContent = "Copy";
|
|
3906
|
+
copyBtn.setAttribute("aria-label", "Copy source code to clipboard");
|
|
3907
|
+
copyBtn.addEventListener("click", async () => {
|
|
3908
|
+
try {
|
|
3909
|
+
await navigator.clipboard.writeText(code);
|
|
3910
|
+
copyBtn.textContent = "Copied \u2713";
|
|
3911
|
+
setTimeout(() => {
|
|
3912
|
+
copyBtn.textContent = "Copy";
|
|
3913
|
+
}, 1800);
|
|
3914
|
+
} catch {
|
|
3915
|
+
copyBtn.textContent = "Failed";
|
|
3916
|
+
setTimeout(() => {
|
|
3917
|
+
copyBtn.textContent = "Copy";
|
|
3918
|
+
}, 1800);
|
|
3919
|
+
}
|
|
3920
|
+
});
|
|
3921
|
+
const playgroundBtn = document.createElement("a");
|
|
3922
|
+
playgroundBtn.className = "markdy-code-panel__playground";
|
|
3923
|
+
playgroundBtn.href = `${shareUrl ?? MARKDY_PLAYGROUND_URL}#code=${encodeCodeForPlaygroundHash(code)}`;
|
|
3924
|
+
playgroundBtn.target = "_blank";
|
|
3925
|
+
playgroundBtn.rel = "noopener noreferrer";
|
|
3926
|
+
playgroundBtn.textContent = "Open in Studio \u2197";
|
|
3927
|
+
playgroundBtn.setAttribute("aria-label", "Open diagram in Markdy Studio playground");
|
|
3928
|
+
const closeBtn = document.createElement("button");
|
|
3929
|
+
closeBtn.type = "button";
|
|
3930
|
+
closeBtn.className = "markdy-code-panel__close";
|
|
3931
|
+
closeBtn.textContent = "\u2715 Close";
|
|
3932
|
+
closeBtn.setAttribute("aria-label", "Close code panel");
|
|
3933
|
+
actions.append(copyBtn, playgroundBtn, closeBtn);
|
|
3934
|
+
header.append(title, actions);
|
|
3935
|
+
const body = document.createElement("div");
|
|
3936
|
+
body.className = "markdy-code-panel__body";
|
|
3937
|
+
const pre = document.createElement("pre");
|
|
3938
|
+
pre.className = "markdy-code-panel__pre";
|
|
3939
|
+
pre.innerHTML = tintCode(code);
|
|
3940
|
+
body.appendChild(pre);
|
|
3941
|
+
panel.append(header, body);
|
|
3942
|
+
overlay.appendChild(panel);
|
|
3943
|
+
document.body.appendChild(overlay);
|
|
3944
|
+
closeBtn.focus();
|
|
3945
|
+
function closePanel() {
|
|
3946
|
+
overlay.dataset.closing = "1";
|
|
3947
|
+
overlay.addEventListener("animationend", () => overlay.remove(), { once: true });
|
|
3948
|
+
}
|
|
3949
|
+
closeBtn.addEventListener("click", closePanel);
|
|
3950
|
+
overlay.addEventListener("click", (e) => {
|
|
3951
|
+
if (e.target === overlay) closePanel();
|
|
3952
|
+
});
|
|
3953
|
+
function handleEscape(e) {
|
|
3954
|
+
if (e.key === "Escape") {
|
|
3955
|
+
closePanel();
|
|
3956
|
+
document.removeEventListener("keydown", handleEscape);
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
document.addEventListener("keydown", handleEscape);
|
|
3960
|
+
overlay.addEventListener("animationend", () => {
|
|
3961
|
+
if (overlay.dataset.closing === "1") document.removeEventListener("keydown", handleEscape);
|
|
3962
|
+
}, { once: true });
|
|
3963
|
+
});
|
|
3964
|
+
toolbar.appendChild(button);
|
|
3965
|
+
}
|
|
3499
3966
|
function mountFitControl(toolbar) {
|
|
3500
3967
|
if (!fitViewButton) return;
|
|
3501
|
-
controlsFitButton = makeControlButton("Fit", "Fit all items in view and ignore camera zoom");
|
|
3968
|
+
controlsFitButton = makeControlButton("Fit", "Fit all items in view and ignore camera zoom", ICONS2.fit);
|
|
3502
3969
|
controlsFitButton.className = "markdy-control-fit";
|
|
3503
3970
|
controlsFitButton.setAttribute("aria-pressed", "false");
|
|
3504
3971
|
controlsFitButton.addEventListener("click", toggleFitView);
|
|
@@ -3506,14 +3973,14 @@ function createDiagram(opts) {
|
|
|
3506
3973
|
}
|
|
3507
3974
|
function mountResetViewControl(toolbar) {
|
|
3508
3975
|
if (!resetViewButton) return;
|
|
3509
|
-
const button = makeControlButton("Reset", "Reset diagram view");
|
|
3976
|
+
const button = makeControlButton("Reset", "Reset diagram view", ICONS2.resetView);
|
|
3510
3977
|
button.className = "markdy-control-reset-view";
|
|
3511
3978
|
button.addEventListener("click", resetViewportTransform);
|
|
3512
3979
|
toolbar.appendChild(button);
|
|
3513
3980
|
}
|
|
3514
3981
|
function mountFullscreenControl(toolbar) {
|
|
3515
3982
|
if (!fullscreenButton) return;
|
|
3516
|
-
const button = makeControlButton("Full", "Toggle fullscreen view");
|
|
3983
|
+
const button = makeControlButton("Full", "Toggle fullscreen view", ICONS2.fullscreen);
|
|
3517
3984
|
button.className = "markdy-control-fullscreen";
|
|
3518
3985
|
button.setAttribute("aria-pressed", "false");
|
|
3519
3986
|
const host = container.parentElement ?? container;
|
|
@@ -3594,17 +4061,49 @@ function createDiagram(opts) {
|
|
|
3594
4061
|
for (const eventName of ["click", "dblclick", "pointerdown", "pointermove", "pointerup", "wheel"]) {
|
|
3595
4062
|
toolbar.addEventListener(eventName, (event) => event.stopPropagation());
|
|
3596
4063
|
}
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
4064
|
+
const playbackGroup = document.createElement("div");
|
|
4065
|
+
playbackGroup.className = "markdy-controls-group markdy-controls-playback";
|
|
4066
|
+
mountPlayControl(playbackGroup);
|
|
4067
|
+
mountBeatNavControls(playbackGroup, "prev");
|
|
4068
|
+
mountBeatNavControls(playbackGroup, "next");
|
|
4069
|
+
mountRestartControl(playbackGroup);
|
|
4070
|
+
if (playbackGroup.children.length > 0) toolbar.appendChild(playbackGroup);
|
|
4071
|
+
if (seekBar) {
|
|
4072
|
+
const timelineGroup = document.createElement("div");
|
|
4073
|
+
timelineGroup.className = "markdy-controls-group markdy-controls-timeline";
|
|
4074
|
+
mountSeekControl(timelineGroup);
|
|
4075
|
+
toolbar.appendChild(timelineGroup);
|
|
4076
|
+
}
|
|
4077
|
+
const toolsGroup = document.createElement("div");
|
|
4078
|
+
toolsGroup.className = "markdy-controls-group markdy-controls-tools";
|
|
4079
|
+
if (speedControls) {
|
|
4080
|
+
const speedGroup = document.createElement("div");
|
|
4081
|
+
speedGroup.className = "markdy-speed-group";
|
|
4082
|
+
mountSpeedControls(speedGroup);
|
|
4083
|
+
toolsGroup.appendChild(speedGroup);
|
|
4084
|
+
}
|
|
4085
|
+
if (fitViewButton || resetViewButton || fullscreenButton) {
|
|
4086
|
+
if (toolsGroup.children.length > 0) {
|
|
4087
|
+
const divider = document.createElement("div");
|
|
4088
|
+
divider.className = "markdy-control-divider";
|
|
4089
|
+
toolsGroup.appendChild(divider);
|
|
4090
|
+
}
|
|
4091
|
+
mountFitControl(toolsGroup);
|
|
4092
|
+
mountResetViewControl(toolsGroup);
|
|
4093
|
+
mountFullscreenControl(toolsGroup);
|
|
4094
|
+
}
|
|
4095
|
+
if (svgButton || shareButton || codeButton || themeButton) {
|
|
4096
|
+
if (toolsGroup.children.length > 0) {
|
|
4097
|
+
const divider = document.createElement("div");
|
|
4098
|
+
divider.className = "markdy-control-divider";
|
|
4099
|
+
toolsGroup.appendChild(divider);
|
|
4100
|
+
}
|
|
4101
|
+
mountThemeControl(toolsGroup);
|
|
4102
|
+
mountSvgControl(toolsGroup);
|
|
4103
|
+
mountShareControl(toolsGroup);
|
|
4104
|
+
mountCodeControl(toolsGroup);
|
|
4105
|
+
}
|
|
4106
|
+
if (toolsGroup.children.length > 0) toolbar.appendChild(toolsGroup);
|
|
3608
4107
|
ensureFooter().insertBefore(toolbar, badge ?? null);
|
|
3609
4108
|
syncControls();
|
|
3610
4109
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markdy/renderer-dom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Browser renderer for diagram-native animated MarkdyScript architecture diagrams, built on the Web Animations API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"html2canvas": "^1.4.1",
|
|
48
|
-
"@markdy/core": "1.0.
|
|
48
|
+
"@markdy/core": "1.0.14"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"jsdom": "^29.1.1",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
54
|
"vitest": "^4.1.7",
|
|
55
|
-
"@markdy/stdlib-systems": "1.0.
|
|
55
|
+
"@markdy/stdlib-systems": "1.0.14"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsup",
|