@kerkhoff-ict/solora 2.1.0 → 2.1.1
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.css +232 -51
- package/dist/index.js +347 -1
- package/package.json +2 -1
package/dist/index.css
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
/* src/components/button.css */
|
|
2
|
-
:root {
|
|
3
|
-
--color-primary: #0071e3;
|
|
4
|
-
--color-secondary: #f5f5f5;
|
|
5
|
-
--color-success: #28a745;
|
|
6
|
-
--color-warning: #ffc107;
|
|
7
|
-
--color-danger: #dc3545;
|
|
8
|
-
--color-text-light: #ffffff;
|
|
9
|
-
--color-text-dark: #000000;
|
|
10
|
-
}
|
|
11
2
|
.btn {
|
|
12
3
|
font-weight: 600;
|
|
13
4
|
border: none;
|
|
14
5
|
border-radius: 9999px;
|
|
15
6
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
16
|
-
border-radius: 9999px;
|
|
17
7
|
cursor: pointer;
|
|
18
8
|
transition: background 0.2s, filter 0.2s;
|
|
19
9
|
}
|
|
10
|
+
.btn-rounded {
|
|
11
|
+
padding: 0 !important;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
20
18
|
.btn-sm {
|
|
21
19
|
padding: 0.1875rem 1rem;
|
|
22
20
|
font-size: 0.9375rem;
|
|
@@ -115,7 +113,7 @@
|
|
|
115
113
|
[class*="btn-["]:hover {
|
|
116
114
|
filter: brightness(0.85);
|
|
117
115
|
}
|
|
118
|
-
|
|
116
|
+
:root.dark {
|
|
119
117
|
.btn-primary {
|
|
120
118
|
background: #0558be;
|
|
121
119
|
color: var(--color-text-light, #fff);
|
|
@@ -367,7 +365,7 @@
|
|
|
367
365
|
.codeblock pre::-webkit-scrollbar-track {
|
|
368
366
|
background: transparent;
|
|
369
367
|
}
|
|
370
|
-
|
|
368
|
+
:root.dark {
|
|
371
369
|
.codeblock {
|
|
372
370
|
background: #1e1e2f88;
|
|
373
371
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
@@ -476,7 +474,7 @@
|
|
|
476
474
|
margin-top: 0.5rem;
|
|
477
475
|
overflow: hidden;
|
|
478
476
|
overflow-y: auto;
|
|
479
|
-
background:
|
|
477
|
+
background: transparent;
|
|
480
478
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
481
479
|
backdrop-filter: blur(12px);
|
|
482
480
|
-webkit-backdrop-filter: blur(12px);
|
|
@@ -538,44 +536,227 @@
|
|
|
538
536
|
color: rgba(0, 0, 0, 0.6);
|
|
539
537
|
cursor: default;
|
|
540
538
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
.
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
.
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
.
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
.
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
.
|
|
577
|
-
background: rgba(255, 255, 255, 0.2);
|
|
578
|
-
}
|
|
539
|
+
:root.dark .dropdown-btn {
|
|
540
|
+
background: #1c1c1e;
|
|
541
|
+
color: #f0f0f0;
|
|
542
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
543
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
|
544
|
+
}
|
|
545
|
+
:root.dark .dropdown-btn:hover {
|
|
546
|
+
background: rgba(255, 255, 255, 0.05);
|
|
547
|
+
}
|
|
548
|
+
:root.dark .dropdown-content {
|
|
549
|
+
background: transparent;
|
|
550
|
+
backdrop-filter: blur(12px);
|
|
551
|
+
-webkit-backdrop-filter: blur(12px);
|
|
552
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
|
|
553
|
+
}
|
|
554
|
+
:root.dark .dropdown-item {
|
|
555
|
+
color: #f0f0f0;
|
|
556
|
+
}
|
|
557
|
+
:root.dark .dropdown-item:hover {
|
|
558
|
+
background: rgba(255, 255, 255, 0.08);
|
|
559
|
+
}
|
|
560
|
+
:root.dark .dropdown-item.active {
|
|
561
|
+
background: rgba(255, 255, 255, 0.12);
|
|
562
|
+
}
|
|
563
|
+
:root.dark .dropdown-divider {
|
|
564
|
+
background: rgba(255, 255, 255, 0.2);
|
|
565
|
+
}
|
|
566
|
+
:root.dark .dropdown-item[aria-disabled=true],
|
|
567
|
+
:root.dark .dropdown-item.placeholder {
|
|
568
|
+
color: rgba(255, 255, 255, 0.4);
|
|
569
|
+
}
|
|
570
|
+
:root.dark .dropdown-label {
|
|
571
|
+
color: rgba(255, 255, 255, 0.6);
|
|
572
|
+
}
|
|
573
|
+
:root.dark .dropdown-content::-webkit-scrollbar-thumb {
|
|
574
|
+
background: rgba(255, 255, 255, 0.2);
|
|
579
575
|
}
|
|
580
576
|
|
|
577
|
+
/* src/components/input.css */
|
|
578
|
+
.sol-input-group {
|
|
579
|
+
display: flex;
|
|
580
|
+
flex-direction: column;
|
|
581
|
+
gap: 0.4rem;
|
|
582
|
+
font-family:
|
|
583
|
+
-apple-system,
|
|
584
|
+
BlinkMacSystemFont,
|
|
585
|
+
"Segoe UI",
|
|
586
|
+
Roboto,
|
|
587
|
+
Helvetica,
|
|
588
|
+
Arial,
|
|
589
|
+
sans-serif;
|
|
590
|
+
width: 100%;
|
|
591
|
+
}
|
|
592
|
+
.sol-label {
|
|
593
|
+
font-size: 0.85rem;
|
|
594
|
+
font-weight: 500;
|
|
595
|
+
color: var(--color-text-dark, #000);
|
|
596
|
+
opacity: 0.6;
|
|
597
|
+
margin-left: 0.2rem;
|
|
598
|
+
}
|
|
599
|
+
.sol-input {
|
|
600
|
+
appearance: none;
|
|
601
|
+
-webkit-appearance: none;
|
|
602
|
+
width: 100%;
|
|
603
|
+
padding: 0.3rem 0.4rem;
|
|
604
|
+
font-size: 0.95rem;
|
|
605
|
+
border-radius: 12px;
|
|
606
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
607
|
+
background: var(--color-bg, #fefefe);
|
|
608
|
+
color: var(--color-text-dark, #000);
|
|
609
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
610
|
+
transition: all 0.2s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
611
|
+
outline: none;
|
|
612
|
+
}
|
|
613
|
+
.sol-input::placeholder {
|
|
614
|
+
color: var(--color-text-dark, #000);
|
|
615
|
+
opacity: 0.3;
|
|
616
|
+
}
|
|
617
|
+
.sol-input:hover {
|
|
618
|
+
border-color: rgba(0, 0, 0, 0.2);
|
|
619
|
+
background: var(--color-bg-hover, #ffffff);
|
|
620
|
+
}
|
|
621
|
+
.sol-input:focus {
|
|
622
|
+
border-color: var(--color-primary, #0071e3);
|
|
623
|
+
box-shadow: 0 0 0 4px var(--color-focus-glow, rgba(0, 113, 227, 0.15)), 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
624
|
+
background: var(--color-bg-hover, #ffffff);
|
|
625
|
+
}
|
|
626
|
+
.sol-input:disabled {
|
|
627
|
+
background: var(--color-secondary, #f5f5f5);
|
|
628
|
+
color: var(--color-text-dark, #000);
|
|
629
|
+
opacity: 0.5;
|
|
630
|
+
cursor: not-allowed;
|
|
631
|
+
box-shadow: none;
|
|
632
|
+
}
|
|
633
|
+
.sol-input-error {
|
|
634
|
+
border-color: var(--color-danger, #dc3545) !important;
|
|
635
|
+
}
|
|
636
|
+
.sol-input-error:focus {
|
|
637
|
+
box-shadow: 0 0 0 4px var(--color-error-glow, rgba(220, 53, 69, 0.15)) !important;
|
|
638
|
+
}
|
|
639
|
+
:root.dark .sol-label {
|
|
640
|
+
color: var(--color-text-light, #fff);
|
|
641
|
+
opacity: 0.6;
|
|
642
|
+
}
|
|
643
|
+
:root.dark .sol-input {
|
|
644
|
+
background: rgba(28, 28, 30, 0.8);
|
|
645
|
+
color: var(--color-text-light, #fff);
|
|
646
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
647
|
+
backdrop-filter: blur(12px);
|
|
648
|
+
-webkit-backdrop-filter: blur(12px);
|
|
649
|
+
box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.05), 0 4px 12px rgba(0, 0, 0, 0.4);
|
|
650
|
+
}
|
|
651
|
+
:root.dark .sol-input::placeholder {
|
|
652
|
+
color: var(--color-text-light, #fff);
|
|
653
|
+
opacity: 0.3;
|
|
654
|
+
}
|
|
655
|
+
:root.dark .sol-input:hover {
|
|
656
|
+
background: rgba(44, 44, 46, 0.9);
|
|
657
|
+
border-color: rgba(255, 255, 255, 0.25);
|
|
658
|
+
}
|
|
659
|
+
:root.dark .sol-input:focus {
|
|
660
|
+
background: rgba(44, 44, 46, 1);
|
|
661
|
+
border-color: var(--color-primary-dark, #0a84ff);
|
|
662
|
+
box-shadow: 0 0 0 4px var(--color-focus-glow-dark, rgba(10, 132, 255, 0.2)), 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
663
|
+
}
|
|
664
|
+
:root.dark .sol-input-error {
|
|
665
|
+
border-color: var(--color-danger, #ff453a) !important;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/* src/components/contextMenu.css */
|
|
669
|
+
.sol-context-menu {
|
|
670
|
+
position: fixed;
|
|
671
|
+
display: none;
|
|
672
|
+
z-index: 9999;
|
|
673
|
+
min-width: 180px;
|
|
674
|
+
background: transparent;
|
|
675
|
+
backdrop-filter: blur(12px) saturate(180%);
|
|
676
|
+
-webkit-backdrop-filter: blur(12px) saturate(180%);
|
|
677
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
678
|
+
border-radius: 12px;
|
|
679
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
|
|
680
|
+
padding: 5px;
|
|
681
|
+
font-family:
|
|
682
|
+
-apple-system,
|
|
683
|
+
BlinkMacSystemFont,
|
|
684
|
+
"Segoe UI",
|
|
685
|
+
Roboto,
|
|
686
|
+
Helvetica,
|
|
687
|
+
Arial,
|
|
688
|
+
sans-serif;
|
|
689
|
+
user-select: none;
|
|
690
|
+
opacity: 0;
|
|
691
|
+
transform: translateY(-10px) scale(0.95);
|
|
692
|
+
transition: opacity 0.15s ease, transform 0.15s cubic-bezier(0.25, 0.8, 0.25, 1);
|
|
693
|
+
}
|
|
694
|
+
.sol-context-menu.visible {
|
|
695
|
+
display: block;
|
|
696
|
+
opacity: 1;
|
|
697
|
+
transform: translateY(0) scale(1);
|
|
698
|
+
}
|
|
699
|
+
.sol-menu-item {
|
|
700
|
+
display: flex;
|
|
701
|
+
align-items: center;
|
|
702
|
+
justify-content: space-between;
|
|
703
|
+
padding: 0.2rem 0.3rem;
|
|
704
|
+
font-size: 0.85rem;
|
|
705
|
+
color: var(--color-text-dark, #000);
|
|
706
|
+
border-radius: 8px;
|
|
707
|
+
cursor: pointer;
|
|
708
|
+
transition: background 0.1s, color 0.1s;
|
|
709
|
+
}
|
|
710
|
+
.sol-menu-item:hover {
|
|
711
|
+
background: var(--color-primary, #007aff);
|
|
712
|
+
color: #fff;
|
|
713
|
+
}
|
|
714
|
+
.sol-menu-shortcut {
|
|
715
|
+
font-size: 0.75rem;
|
|
716
|
+
opacity: 0.5;
|
|
717
|
+
margin-left: 20px;
|
|
718
|
+
}
|
|
719
|
+
.sol-menu-item:hover .sol-menu-shortcut {
|
|
720
|
+
color: #fff;
|
|
721
|
+
opacity: 0.8;
|
|
722
|
+
}
|
|
723
|
+
.sol-menu-divider {
|
|
724
|
+
height: 1px;
|
|
725
|
+
background: rgba(0, 0, 0, 0.08);
|
|
726
|
+
margin: 4px 0;
|
|
727
|
+
}
|
|
728
|
+
:root.dark .sol-context-menu {
|
|
729
|
+
background: rgba(28, 28, 30, 0.8);
|
|
730
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
731
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
732
|
+
}
|
|
733
|
+
:root.dark .sol-menu-item {
|
|
734
|
+
color: var(--color-text-light, #f0f0f0);
|
|
735
|
+
}
|
|
736
|
+
:root.dark .sol-menu-divider {
|
|
737
|
+
background: rgba(255, 255, 255, 0.1);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/* src/components/darkToggle.css */
|
|
741
|
+
|
|
581
742
|
/* src/index.css */
|
|
743
|
+
:root {
|
|
744
|
+
--font-body:
|
|
745
|
+
-apple-system,
|
|
746
|
+
BlinkMacSystemFont,
|
|
747
|
+
"SF Pro Text",
|
|
748
|
+
"Helvetica Neue",
|
|
749
|
+
Arial,
|
|
750
|
+
sans-serif;
|
|
751
|
+
--font-display:
|
|
752
|
+
"SF Pro Display",
|
|
753
|
+
-apple-system,
|
|
754
|
+
BlinkMacSystemFont,
|
|
755
|
+
"Helvetica Neue",
|
|
756
|
+
sans-serif;
|
|
757
|
+
--font-mono:
|
|
758
|
+
"SF Mono",
|
|
759
|
+
"Menlo",
|
|
760
|
+
"Consolas",
|
|
761
|
+
monospace;
|
|
762
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1917,16 +1917,362 @@ function initDropdowns() {
|
|
|
1917
1917
|
});
|
|
1918
1918
|
}
|
|
1919
1919
|
|
|
1920
|
+
// src/components/contextMenu.js
|
|
1921
|
+
function initContextMenu() {
|
|
1922
|
+
let menu = document.querySelector(".sol-context-menu");
|
|
1923
|
+
if (!menu) {
|
|
1924
|
+
menu = document.createElement("div");
|
|
1925
|
+
menu.className = "sol-context-menu";
|
|
1926
|
+
document.body.appendChild(menu);
|
|
1927
|
+
}
|
|
1928
|
+
let contextTarget = null;
|
|
1929
|
+
const showMenu = (e) => {
|
|
1930
|
+
e.preventDefault();
|
|
1931
|
+
contextTarget = e.target;
|
|
1932
|
+
const selection = window.getSelection().toString().trim();
|
|
1933
|
+
const link = e.target.closest("a");
|
|
1934
|
+
const img = e.target.closest("img");
|
|
1935
|
+
const input = e.target.closest("input, textarea, [contenteditable]");
|
|
1936
|
+
const isEditable = input || e.target.isContentEditable;
|
|
1937
|
+
const isTextInput = input && (input.type === "text" || input.type === "search" || input.type === "email" || input.type === "password" || input.tagName === "TEXTAREA" || input.isContentEditable);
|
|
1938
|
+
let menuHtml = "";
|
|
1939
|
+
if (selection.length > 0) {
|
|
1940
|
+
menuHtml += `
|
|
1941
|
+
<div class="sol-menu-label">Selectie</div>
|
|
1942
|
+
<div class="sol-menu-item" data-action="copy">
|
|
1943
|
+
Kopieer <span class="sol-menu-shortcut">\u2318C</span>
|
|
1944
|
+
</div>
|
|
1945
|
+
${isEditable ? `
|
|
1946
|
+
<div class="sol-menu-item" data-action="cut">
|
|
1947
|
+
Knippen <span class="sol-menu-shortcut">\u2318X</span>
|
|
1948
|
+
</div>` : ""}
|
|
1949
|
+
<div class="sol-menu-item" data-action="search-google">
|
|
1950
|
+
Zoek op Google: <em>"${selection.slice(0, 20)}${selection.length > 20 ? "\u2026" : ""}"</em>
|
|
1951
|
+
</div>
|
|
1952
|
+
<div class="sol-menu-item" data-action="search-wiki">
|
|
1953
|
+
Zoek op Wikipedia\u2026
|
|
1954
|
+
</div>
|
|
1955
|
+
<div class="sol-menu-item" data-action="translate">
|
|
1956
|
+
Vertaal selectie\u2026
|
|
1957
|
+
</div>
|
|
1958
|
+
<div class="sol-menu-divider"></div>
|
|
1959
|
+
`;
|
|
1960
|
+
}
|
|
1961
|
+
if (isTextInput) {
|
|
1962
|
+
menuHtml += `
|
|
1963
|
+
<div class="sol-menu-label">Tekstveld</div>
|
|
1964
|
+
${selection.length > 0 ? `
|
|
1965
|
+
<div class="sol-menu-item" data-action="cut">
|
|
1966
|
+
Knippen <span class="sol-menu-shortcut">\u2318X</span>
|
|
1967
|
+
</div>
|
|
1968
|
+
<div class="sol-menu-item" data-action="copy">
|
|
1969
|
+
Kopieer <span class="sol-menu-shortcut">\u2318C</span>
|
|
1970
|
+
</div>` : ""}
|
|
1971
|
+
<div class="sol-menu-item" data-action="paste">
|
|
1972
|
+
Plakken <span class="sol-menu-shortcut">\u2318V</span>
|
|
1973
|
+
</div>
|
|
1974
|
+
<div class="sol-menu-item" data-action="select-all">
|
|
1975
|
+
Alles selecteren <span class="sol-menu-shortcut">\u2318A</span>
|
|
1976
|
+
</div>
|
|
1977
|
+
<div class="sol-menu-item" data-action="clear-field">
|
|
1978
|
+
Veld wissen
|
|
1979
|
+
</div>
|
|
1980
|
+
<div class="sol-menu-divider"></div>
|
|
1981
|
+
`;
|
|
1982
|
+
}
|
|
1983
|
+
if (img) {
|
|
1984
|
+
menuHtml += `
|
|
1985
|
+
<div class="sol-menu-label">Afbeelding</div>
|
|
1986
|
+
<div class="sol-menu-item" data-action="open-img" data-url="${img.src}">
|
|
1987
|
+
Afbeelding openen in nieuw tabblad
|
|
1988
|
+
</div>
|
|
1989
|
+
<div class="sol-menu-item" data-action="copy-img-url" data-url="${img.src}">
|
|
1990
|
+
Kopieer afbeeldings-URL
|
|
1991
|
+
</div>
|
|
1992
|
+
<div class="sol-menu-item" data-action="download-img" data-url="${img.src}" data-filename="${img.alt || "afbeelding"}">
|
|
1993
|
+
Afbeelding opslaan\u2026
|
|
1994
|
+
</div>
|
|
1995
|
+
${img.alt ? `
|
|
1996
|
+
<div class="sol-menu-item" data-action="copy-alt" data-text="${img.alt}">
|
|
1997
|
+
Kopieer alt-tekst
|
|
1998
|
+
</div>` : ""}
|
|
1999
|
+
<div class="sol-menu-divider"></div>
|
|
2000
|
+
`;
|
|
2001
|
+
}
|
|
2002
|
+
if (link) {
|
|
2003
|
+
menuHtml += `
|
|
2004
|
+
<div class="sol-menu-label">Link</div>
|
|
2005
|
+
<div class="sol-menu-item" data-action="open-tab" data-url="${link.href}">
|
|
2006
|
+
Open in nieuw tabblad
|
|
2007
|
+
</div>
|
|
2008
|
+
<div class="sol-menu-item" data-action="open-window" data-url="${link.href}">
|
|
2009
|
+
Open in nieuw venster
|
|
2010
|
+
</div>
|
|
2011
|
+
<div class="sol-menu-item" data-action="copy-link" data-url="${link.href}">
|
|
2012
|
+
Kopieer link-adres
|
|
2013
|
+
</div>
|
|
2014
|
+
<div class="sol-menu-divider"></div>
|
|
2015
|
+
`;
|
|
2016
|
+
}
|
|
2017
|
+
menuHtml += `
|
|
2018
|
+
<div class="sol-menu-label">Navigatie</div>
|
|
2019
|
+
<div class="sol-menu-item${!history.length || history.state === null ? " disabled" : ""}" data-action="go-back">
|
|
2020
|
+
\u2190 Vorige pagina
|
|
2021
|
+
</div>
|
|
2022
|
+
<div class="sol-menu-item" data-action="go-forward">
|
|
2023
|
+
\u2192 Volgende pagina
|
|
2024
|
+
</div>
|
|
2025
|
+
<div class="sol-menu-item" data-action="reload">
|
|
2026
|
+
Vernieuwen <span class="sol-menu-shortcut">\u2318R</span>
|
|
2027
|
+
</div>
|
|
2028
|
+
<div class="sol-menu-item" data-action="hard-reload">
|
|
2029
|
+
Geforceerd vernieuwen <span class="sol-menu-shortcut">\u21E7\u2318R</span>
|
|
2030
|
+
</div>
|
|
2031
|
+
<div class="sol-menu-divider"></div>
|
|
2032
|
+
`;
|
|
2033
|
+
menuHtml += `
|
|
2034
|
+
<div class="sol-menu-label">Pagina</div>
|
|
2035
|
+
<div class="sol-menu-item" data-action="copy-page-url">
|
|
2036
|
+
Kopieer pagina-URL
|
|
2037
|
+
</div>
|
|
2038
|
+
<div class="sol-menu-item" data-action="view-source">
|
|
2039
|
+
Bekijk paginabron <span class="sol-menu-shortcut">\u2318U</span>
|
|
2040
|
+
</div>
|
|
2041
|
+
<div class="sol-menu-item" data-action="print">
|
|
2042
|
+
Printen <span class="sol-menu-shortcut">\u2318P</span>
|
|
2043
|
+
</div>
|
|
2044
|
+
<div class="sol-menu-item" data-action="save-page">
|
|
2045
|
+
Pagina opslaan <span class="sol-menu-shortcut">\u2318S</span>
|
|
2046
|
+
</div>
|
|
2047
|
+
<div class="sol-menu-item" data-action="scroll-top">
|
|
2048
|
+
Naar boven scrollen
|
|
2049
|
+
</div>
|
|
2050
|
+
<div class="sol-menu-divider"></div>
|
|
2051
|
+
`;
|
|
2052
|
+
menuHtml += `
|
|
2053
|
+
<div class="sol-menu-label">Ontwikkelaar</div>
|
|
2054
|
+
<div class="sol-menu-item" data-action="inspect">
|
|
2055
|
+
Inspecteer element <span class="sol-menu-shortcut">\u2325\u2318I</span>
|
|
2056
|
+
</div>
|
|
2057
|
+
<div class="sol-menu-item" data-action="copy-selector">
|
|
2058
|
+
Kopieer CSS-selector
|
|
2059
|
+
</div>
|
|
2060
|
+
<div class="sol-menu-item" data-action="log-element">
|
|
2061
|
+
Log element in console
|
|
2062
|
+
</div>
|
|
2063
|
+
`;
|
|
2064
|
+
menu.innerHTML = menuHtml;
|
|
2065
|
+
menu.style.display = "block";
|
|
2066
|
+
let posX = e.clientX;
|
|
2067
|
+
let posY = e.clientY;
|
|
2068
|
+
const menuWidth = menu.offsetWidth;
|
|
2069
|
+
const menuHeight = menu.offsetHeight;
|
|
2070
|
+
if (posX + menuWidth > window.innerWidth) posX -= menuWidth;
|
|
2071
|
+
if (posY + menuHeight > window.innerHeight) posY -= menuHeight;
|
|
2072
|
+
menu.style.left = `${posX}px`;
|
|
2073
|
+
menu.style.top = `${posY}px`;
|
|
2074
|
+
requestAnimationFrame(() => menu.classList.add("visible"));
|
|
2075
|
+
};
|
|
2076
|
+
const hideMenu = () => {
|
|
2077
|
+
menu.classList.remove("visible");
|
|
2078
|
+
setTimeout(() => {
|
|
2079
|
+
if (!menu.classList.contains("visible")) menu.style.display = "none";
|
|
2080
|
+
}, 150);
|
|
2081
|
+
};
|
|
2082
|
+
const getCssSelector = (el) => {
|
|
2083
|
+
if (!el) return "";
|
|
2084
|
+
const parts = [];
|
|
2085
|
+
while (el && el.nodeType === Node.ELEMENT_NODE) {
|
|
2086
|
+
let selector = el.nodeName.toLowerCase();
|
|
2087
|
+
if (el.id) {
|
|
2088
|
+
selector += `#${el.id}`;
|
|
2089
|
+
parts.unshift(selector);
|
|
2090
|
+
break;
|
|
2091
|
+
}
|
|
2092
|
+
if (el.className) {
|
|
2093
|
+
selector += "." + [...el.classList].join(".");
|
|
2094
|
+
}
|
|
2095
|
+
const siblings = el.parentNode ? [...el.parentNode.children].filter((s) => s.nodeName === el.nodeName) : [];
|
|
2096
|
+
if (siblings.length > 1) {
|
|
2097
|
+
selector += `:nth-of-type(${siblings.indexOf(el) + 1})`;
|
|
2098
|
+
}
|
|
2099
|
+
parts.unshift(selector);
|
|
2100
|
+
el = el.parentNode;
|
|
2101
|
+
}
|
|
2102
|
+
return parts.join(" > ");
|
|
2103
|
+
};
|
|
2104
|
+
document.addEventListener("contextmenu", showMenu);
|
|
2105
|
+
document.addEventListener("click", hideMenu);
|
|
2106
|
+
window.addEventListener("scroll", hideMenu);
|
|
2107
|
+
document.addEventListener("keydown", (e) => {
|
|
2108
|
+
if (e.key === "Escape") hideMenu();
|
|
2109
|
+
});
|
|
2110
|
+
menu.addEventListener("click", (e) => {
|
|
2111
|
+
const item = e.target.closest(".sol-menu-item");
|
|
2112
|
+
if (!item || item.classList.contains("disabled")) return;
|
|
2113
|
+
const action = item.dataset.action;
|
|
2114
|
+
const url = item.dataset.url;
|
|
2115
|
+
const text = item.dataset.text;
|
|
2116
|
+
const filename = item.dataset.filename;
|
|
2117
|
+
const sel = window.getSelection().toString().trim();
|
|
2118
|
+
switch (action) {
|
|
2119
|
+
// Tekst
|
|
2120
|
+
case "copy":
|
|
2121
|
+
document.execCommand("copy");
|
|
2122
|
+
break;
|
|
2123
|
+
case "cut":
|
|
2124
|
+
document.execCommand("cut");
|
|
2125
|
+
break;
|
|
2126
|
+
case "paste":
|
|
2127
|
+
navigator.clipboard.readText().then((t) => document.execCommand("insertText", false, t));
|
|
2128
|
+
break;
|
|
2129
|
+
case "select-all":
|
|
2130
|
+
document.execCommand("selectAll");
|
|
2131
|
+
break;
|
|
2132
|
+
case "clear-field":
|
|
2133
|
+
if (contextTarget?.closest("input, textarea")) contextTarget.closest("input, textarea").value = "";
|
|
2134
|
+
break;
|
|
2135
|
+
// Zoeken & vertalen
|
|
2136
|
+
case "search-google":
|
|
2137
|
+
window.open(`https://www.google.com/search?q=${encodeURIComponent(sel)}`, "_blank");
|
|
2138
|
+
break;
|
|
2139
|
+
case "search-wiki":
|
|
2140
|
+
window.open(`https://nl.wikipedia.org/wiki/Special:Search?search=${encodeURIComponent(sel)}`, "_blank");
|
|
2141
|
+
break;
|
|
2142
|
+
case "translate":
|
|
2143
|
+
window.open(`https://translate.google.com/?sl=auto&tl=nl&text=${encodeURIComponent(sel)}`, "_blank");
|
|
2144
|
+
break;
|
|
2145
|
+
// Afbeelding
|
|
2146
|
+
case "open-img":
|
|
2147
|
+
window.open(url, "_blank");
|
|
2148
|
+
break;
|
|
2149
|
+
case "copy-img-url":
|
|
2150
|
+
navigator.clipboard.writeText(url);
|
|
2151
|
+
break;
|
|
2152
|
+
case "copy-alt":
|
|
2153
|
+
navigator.clipboard.writeText(text);
|
|
2154
|
+
break;
|
|
2155
|
+
case "download-img": {
|
|
2156
|
+
const a = document.createElement("a");
|
|
2157
|
+
a.href = url;
|
|
2158
|
+
a.download = filename || "afbeelding";
|
|
2159
|
+
a.click();
|
|
2160
|
+
break;
|
|
2161
|
+
}
|
|
2162
|
+
// Link
|
|
2163
|
+
case "open-tab":
|
|
2164
|
+
window.open(url, "_blank");
|
|
2165
|
+
break;
|
|
2166
|
+
case "open-window":
|
|
2167
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
2168
|
+
break;
|
|
2169
|
+
case "copy-link":
|
|
2170
|
+
navigator.clipboard.writeText(url);
|
|
2171
|
+
break;
|
|
2172
|
+
// Navigatie
|
|
2173
|
+
case "go-back":
|
|
2174
|
+
history.back();
|
|
2175
|
+
break;
|
|
2176
|
+
case "go-forward":
|
|
2177
|
+
history.forward();
|
|
2178
|
+
break;
|
|
2179
|
+
case "reload":
|
|
2180
|
+
location.reload();
|
|
2181
|
+
break;
|
|
2182
|
+
case "hard-reload":
|
|
2183
|
+
location.href = location.href;
|
|
2184
|
+
break;
|
|
2185
|
+
// Pagina
|
|
2186
|
+
case "copy-page-url":
|
|
2187
|
+
navigator.clipboard.writeText(location.href);
|
|
2188
|
+
break;
|
|
2189
|
+
case "view-source":
|
|
2190
|
+
window.open(`view-source:${location.href}`, "_blank");
|
|
2191
|
+
break;
|
|
2192
|
+
case "print":
|
|
2193
|
+
window.print();
|
|
2194
|
+
break;
|
|
2195
|
+
case "save-page":
|
|
2196
|
+
document.execCommand("SaveAs");
|
|
2197
|
+
break;
|
|
2198
|
+
case "scroll-top":
|
|
2199
|
+
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
2200
|
+
break;
|
|
2201
|
+
// Ontwikkelaar
|
|
2202
|
+
case "inspect":
|
|
2203
|
+
console.log("%c[Inspecteer element]", "color:#6c63ff;font-weight:bold", contextTarget);
|
|
2204
|
+
break;
|
|
2205
|
+
case "copy-selector":
|
|
2206
|
+
navigator.clipboard.writeText(getCssSelector(contextTarget));
|
|
2207
|
+
break;
|
|
2208
|
+
case "log-element":
|
|
2209
|
+
console.log("%c[Sol Context Menu] Geselecteerd element:", "color:#6c63ff", contextTarget);
|
|
2210
|
+
console.table({
|
|
2211
|
+
tag: contextTarget?.tagName,
|
|
2212
|
+
id: contextTarget?.id,
|
|
2213
|
+
classes: contextTarget?.className,
|
|
2214
|
+
selector: getCssSelector(contextTarget),
|
|
2215
|
+
innerText: contextTarget?.innerText?.slice(0, 80)
|
|
2216
|
+
});
|
|
2217
|
+
break;
|
|
2218
|
+
}
|
|
2219
|
+
hideMenu();
|
|
2220
|
+
});
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
// src/components/darkToggle.js
|
|
2224
|
+
function initThemeToggle(elementSelector = ".sol-theme-toggle") {
|
|
2225
|
+
const html = document.documentElement;
|
|
2226
|
+
const toggles = document.querySelectorAll(elementSelector);
|
|
2227
|
+
const STORAGE_KEY = "solora-theme";
|
|
2228
|
+
const applyTheme = (theme) => {
|
|
2229
|
+
if (theme === "dark") {
|
|
2230
|
+
html.classList.add("dark");
|
|
2231
|
+
html.classList.remove("light");
|
|
2232
|
+
} else {
|
|
2233
|
+
html.classList.add("light");
|
|
2234
|
+
html.classList.remove("dark");
|
|
2235
|
+
}
|
|
2236
|
+
toggles.forEach((btn) => {
|
|
2237
|
+
btn.innerHTML = `<span>${theme === "dark" ? "\u2600\uFE0F" : "\u{1F319}"}</span>`;
|
|
2238
|
+
btn.setAttribute("aria-label", `Switch to ${theme === "dark" ? "light" : "dark"} mode`);
|
|
2239
|
+
});
|
|
2240
|
+
localStorage.setItem(STORAGE_KEY, theme);
|
|
2241
|
+
};
|
|
2242
|
+
const getInitialTheme = () => {
|
|
2243
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
2244
|
+
if (saved) return saved;
|
|
2245
|
+
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
2246
|
+
return prefersDark ? "dark" : "light";
|
|
2247
|
+
};
|
|
2248
|
+
applyTheme(getInitialTheme());
|
|
2249
|
+
toggles.forEach((btn) => {
|
|
2250
|
+
btn.addEventListener("click", () => {
|
|
2251
|
+
const isDark = html.classList.contains("dark");
|
|
2252
|
+
applyTheme(isDark ? "light" : "dark");
|
|
2253
|
+
});
|
|
2254
|
+
});
|
|
2255
|
+
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
|
2256
|
+
if (!localStorage.getItem(STORAGE_KEY)) {
|
|
2257
|
+
applyTheme(e.matches ? "dark" : "light");
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
|
|
1920
2262
|
// src/index.js
|
|
1921
2263
|
if (typeof window !== "undefined") {
|
|
1922
2264
|
document.addEventListener("DOMContentLoaded", () => {
|
|
1923
2265
|
initCodeblocks();
|
|
1924
2266
|
initDropdowns();
|
|
2267
|
+
initContextMenu();
|
|
2268
|
+
initThemeToggle();
|
|
1925
2269
|
});
|
|
1926
2270
|
}
|
|
1927
2271
|
export {
|
|
1928
2272
|
initCodeblocks,
|
|
1929
|
-
|
|
2273
|
+
initContextMenu,
|
|
2274
|
+
initDropdowns,
|
|
2275
|
+
initThemeToggle
|
|
1930
2276
|
};
|
|
1931
2277
|
/*! Bundled license information:
|
|
1932
2278
|
|