@matdata/yasqe 5.13.0 → 5.15.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/build/ts/src/defaults.d.ts +1 -1
- package/build/ts/src/index.d.ts +7 -2
- package/build/ts/src/index.js +130 -3
- package/build/ts/src/index.js.map +1 -1
- package/build/yasqe.min.css +1 -1
- package/build/yasqe.min.css.map +3 -3
- package/build/yasqe.min.js +80 -80
- package/build/yasqe.min.js.map +3 -3
- package/package.json +1 -1
- package/src/index.ts +150 -4
- package/src/scss/buttons.scss +110 -18
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -61,6 +61,9 @@ export class Yasqe extends CodeMirror {
|
|
|
61
61
|
private queryBtn: HTMLButtonElement | undefined;
|
|
62
62
|
private saveBtn: HTMLButtonElement | undefined;
|
|
63
63
|
private fullscreenBtn: HTMLButtonElement | undefined;
|
|
64
|
+
private hamburgerBtn: HTMLButtonElement | undefined;
|
|
65
|
+
private hamburgerMenu: HTMLDivElement | undefined;
|
|
66
|
+
private shareBtn: HTMLButtonElement | undefined;
|
|
64
67
|
private isFullscreen: boolean = false;
|
|
65
68
|
private horizontalResizeWrapper?: HTMLDivElement;
|
|
66
69
|
private snippetsBar?: HTMLDivElement;
|
|
@@ -318,6 +321,7 @@ export class Yasqe extends CodeMirror {
|
|
|
318
321
|
shareLinkWrapper.setAttribute("aria-label", "Share query");
|
|
319
322
|
shareLinkWrapper.appendChild(shareIcon);
|
|
320
323
|
buttons.appendChild(shareLinkWrapper);
|
|
324
|
+
this.shareBtn = shareLinkWrapper;
|
|
321
325
|
shareLinkWrapper.addEventListener("click", (event: MouseEvent) => showSharePopup(event));
|
|
322
326
|
shareLinkWrapper.addEventListener("keydown", (event: KeyboardEvent) => {
|
|
323
327
|
if (event.code === "Enter") {
|
|
@@ -463,6 +467,7 @@ export class Yasqe extends CodeMirror {
|
|
|
463
467
|
urlBtn.className = "yasqe_btn yasqe_btn-sm yasqe_shareBtn";
|
|
464
468
|
buttonContainer.appendChild(urlBtn);
|
|
465
469
|
urlBtn.onclick = async () => {
|
|
470
|
+
if (!this.config.createShareableLink) return;
|
|
466
471
|
const url = this.config.createShareableLink(this);
|
|
467
472
|
await copyToClipboard(url, "URL");
|
|
468
473
|
};
|
|
@@ -478,6 +483,7 @@ export class Yasqe extends CodeMirror {
|
|
|
478
483
|
shortenBtn.disabled = true;
|
|
479
484
|
shortenBtn.innerText = "Shortening...";
|
|
480
485
|
try {
|
|
486
|
+
if (!this.config.createShareableLink) return;
|
|
481
487
|
const longUrl = this.config.createShareableLink(this);
|
|
482
488
|
const shortUrl = await createShortLink(this, longUrl);
|
|
483
489
|
await copyToClipboard(shortUrl, "Shortened URL");
|
|
@@ -533,9 +539,25 @@ export class Yasqe extends CodeMirror {
|
|
|
533
539
|
// Position popup after layout is complete
|
|
534
540
|
const positionPopup = () => {
|
|
535
541
|
if (!popup) return;
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
542
|
+
const buttonsRect = buttons.getBoundingClientRect();
|
|
543
|
+
const popupHeight = popup.offsetHeight || 300; // Estimated height
|
|
544
|
+
const viewportHeight = window.innerHeight;
|
|
545
|
+
const spaceAbove = buttonsRect.top;
|
|
546
|
+
const spaceBelow = viewportHeight - buttonsRect.bottom;
|
|
547
|
+
|
|
548
|
+
// If there's enough space above (with some padding), position above
|
|
549
|
+
// Otherwise position below (will use scrolling if needed)
|
|
550
|
+
if (spaceAbove >= popupHeight + 20) {
|
|
551
|
+
popup.style.bottom = (buttons.clientHeight || 46) + "px";
|
|
552
|
+
popup.style.top = "auto";
|
|
553
|
+
popup.style.right = "0px";
|
|
554
|
+
} else {
|
|
555
|
+
// Not enough space above, use fixed positioning at top of viewport
|
|
556
|
+
popup.style.position = "fixed";
|
|
557
|
+
popup.style.bottom = "auto";
|
|
558
|
+
popup.style.top = "20px";
|
|
559
|
+
popup.style.right = "20px";
|
|
560
|
+
}
|
|
539
561
|
};
|
|
540
562
|
|
|
541
563
|
if (typeof window !== "undefined" && typeof window.requestAnimationFrame === "function") {
|
|
@@ -609,6 +631,130 @@ export class Yasqe extends CodeMirror {
|
|
|
609
631
|
this.fullscreenBtn.title = "Toggle fullscreen (F11)";
|
|
610
632
|
this.fullscreenBtn.setAttribute("aria-label", "Toggle fullscreen");
|
|
611
633
|
buttons.appendChild(this.fullscreenBtn);
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Draw hamburger menu button and dropdown (for mobile)
|
|
637
|
+
*/
|
|
638
|
+
this.hamburgerBtn = document.createElement("button");
|
|
639
|
+
addClass(this.hamburgerBtn, "yasqe_hamburgerButton");
|
|
640
|
+
const hamburgerIcon = document.createElement("i");
|
|
641
|
+
addClass(hamburgerIcon, "fas");
|
|
642
|
+
addClass(hamburgerIcon, "fa-bars");
|
|
643
|
+
hamburgerIcon.setAttribute("aria-hidden", "true");
|
|
644
|
+
this.hamburgerBtn.appendChild(hamburgerIcon);
|
|
645
|
+
this.hamburgerBtn.title = "More options";
|
|
646
|
+
this.hamburgerBtn.setAttribute("aria-label", "More options");
|
|
647
|
+
this.hamburgerBtn.setAttribute("aria-expanded", "false");
|
|
648
|
+
buttons.appendChild(this.hamburgerBtn);
|
|
649
|
+
|
|
650
|
+
// Create hamburger menu
|
|
651
|
+
this.hamburgerMenu = document.createElement("div");
|
|
652
|
+
this.hamburgerMenu.className = "yasqe_hamburgerMenu";
|
|
653
|
+
buttons.appendChild(this.hamburgerMenu);
|
|
654
|
+
|
|
655
|
+
// Add menu items
|
|
656
|
+
if (this.config.createShareableLink) {
|
|
657
|
+
const shareItem = document.createElement("button");
|
|
658
|
+
shareItem.className = "yasqe_hamburgerMenuItem";
|
|
659
|
+
const shareIconMenu = document.createElement("i");
|
|
660
|
+
addClass(shareIconMenu, "fas");
|
|
661
|
+
addClass(shareIconMenu, "fa-share-nodes");
|
|
662
|
+
shareIconMenu.setAttribute("aria-hidden", "true");
|
|
663
|
+
shareItem.appendChild(shareIconMenu);
|
|
664
|
+
const shareLabel = document.createElement("span");
|
|
665
|
+
shareLabel.textContent = "Share";
|
|
666
|
+
shareItem.appendChild(shareLabel);
|
|
667
|
+
shareItem.onclick = () => {
|
|
668
|
+
this.closeHamburgerMenu();
|
|
669
|
+
this.shareBtn?.click();
|
|
670
|
+
};
|
|
671
|
+
this.hamburgerMenu.appendChild(shareItem);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const saveItem = document.createElement("button");
|
|
675
|
+
saveItem.className = "yasqe_hamburgerMenuItem";
|
|
676
|
+
const saveIconMenu = document.createElement("i");
|
|
677
|
+
addClass(saveIconMenu, "fas");
|
|
678
|
+
addClass(saveIconMenu, "fa-save");
|
|
679
|
+
saveIconMenu.setAttribute("aria-hidden", "true");
|
|
680
|
+
saveItem.appendChild(saveIconMenu);
|
|
681
|
+
const saveLabel = document.createElement("span");
|
|
682
|
+
saveLabel.textContent = "Save";
|
|
683
|
+
saveItem.appendChild(saveLabel);
|
|
684
|
+
saveItem.onclick = () => {
|
|
685
|
+
this.closeHamburgerMenu();
|
|
686
|
+
this.emit("saveManagedQuery");
|
|
687
|
+
};
|
|
688
|
+
this.hamburgerMenu.appendChild(saveItem);
|
|
689
|
+
|
|
690
|
+
if (this.config.showFormatButton) {
|
|
691
|
+
const formatItem = document.createElement("button");
|
|
692
|
+
formatItem.className = "yasqe_hamburgerMenuItem";
|
|
693
|
+
const formatIconMenu = document.createElement("i");
|
|
694
|
+
addClass(formatIconMenu, "fas");
|
|
695
|
+
addClass(formatIconMenu, "fa-align-left");
|
|
696
|
+
formatIconMenu.setAttribute("aria-hidden", "true");
|
|
697
|
+
formatItem.appendChild(formatIconMenu);
|
|
698
|
+
const formatLabel = document.createElement("span");
|
|
699
|
+
formatLabel.textContent = "Format";
|
|
700
|
+
formatItem.appendChild(formatLabel);
|
|
701
|
+
formatItem.onclick = () => {
|
|
702
|
+
this.closeHamburgerMenu();
|
|
703
|
+
this.format();
|
|
704
|
+
};
|
|
705
|
+
this.hamburgerMenu.appendChild(formatItem);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
const fullscreenItem = document.createElement("button");
|
|
709
|
+
fullscreenItem.className = "yasqe_hamburgerMenuItem";
|
|
710
|
+
const fullscreenIconMenu = document.createElement("i");
|
|
711
|
+
addClass(fullscreenIconMenu, "fas");
|
|
712
|
+
addClass(fullscreenIconMenu, "fa-expand");
|
|
713
|
+
fullscreenIconMenu.setAttribute("aria-hidden", "true");
|
|
714
|
+
fullscreenItem.appendChild(fullscreenIconMenu);
|
|
715
|
+
const fullscreenLabel = document.createElement("span");
|
|
716
|
+
fullscreenLabel.textContent = "Fullscreen";
|
|
717
|
+
fullscreenItem.appendChild(fullscreenLabel);
|
|
718
|
+
fullscreenItem.onclick = () => {
|
|
719
|
+
this.closeHamburgerMenu();
|
|
720
|
+
this.toggleFullscreen();
|
|
721
|
+
};
|
|
722
|
+
this.hamburgerMenu.appendChild(fullscreenItem);
|
|
723
|
+
|
|
724
|
+
// Toggle hamburger menu
|
|
725
|
+
this.hamburgerBtn.onclick = (e) => {
|
|
726
|
+
e.stopPropagation();
|
|
727
|
+
this.toggleHamburgerMenu();
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// Close hamburger menu when clicking outside
|
|
731
|
+
document.addEventListener("click", (e) => {
|
|
732
|
+
if (
|
|
733
|
+
this.hamburgerMenu &&
|
|
734
|
+
this.hamburgerBtn &&
|
|
735
|
+
!this.hamburgerMenu.contains(e.target as Node) &&
|
|
736
|
+
!this.hamburgerBtn.contains(e.target as Node)
|
|
737
|
+
) {
|
|
738
|
+
this.closeHamburgerMenu();
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
private toggleHamburgerMenu() {
|
|
744
|
+
if (!this.hamburgerMenu || !this.hamburgerBtn) return;
|
|
745
|
+
const isActive = this.hamburgerMenu.classList.contains("active");
|
|
746
|
+
if (isActive) {
|
|
747
|
+
this.closeHamburgerMenu();
|
|
748
|
+
} else {
|
|
749
|
+
addClass(this.hamburgerMenu, "active");
|
|
750
|
+
this.hamburgerBtn.setAttribute("aria-expanded", "true");
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
private closeHamburgerMenu() {
|
|
755
|
+
if (!this.hamburgerMenu || !this.hamburgerBtn) return;
|
|
756
|
+
removeClass(this.hamburgerMenu, "active");
|
|
757
|
+
this.hamburgerBtn.setAttribute("aria-expanded", "false");
|
|
612
758
|
}
|
|
613
759
|
public toggleFullscreen() {
|
|
614
760
|
this.isFullscreen = !this.isFullscreen;
|
|
@@ -1830,7 +1976,7 @@ export interface Config extends Partial<CodeMirror.EditorConfiguration> {
|
|
|
1830
1976
|
* By default, this feature is enabled, and the only the query value is appended to the link.
|
|
1831
1977
|
* ps. This function should return an object which is parseable by jQuery.param (http://api.jquery.com/jQuery.param/)
|
|
1832
1978
|
*/
|
|
1833
|
-
createShareableLink: (yasqe: Yasqe) => string;
|
|
1979
|
+
createShareableLink: ((yasqe: Yasqe) => string) | undefined | null;
|
|
1834
1980
|
createShortLink: ((yasqe: Yasqe, longLink: string) => Promise<string>) | undefined;
|
|
1835
1981
|
consumeShareLink: ((yasqe: Yasqe) => void) | undefined | null;
|
|
1836
1982
|
/**
|
package/src/scss/buttons.scss
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
$queryButtonHeight: 40px;
|
|
4
4
|
|
|
5
5
|
.yasqe_btn {
|
|
6
|
-
color: #333;
|
|
6
|
+
color: var(--yasgui-text-primary, #333);
|
|
7
7
|
border: 1px solid transparent;
|
|
8
|
-
background-color: #fff;
|
|
9
|
-
border-color: #ccc;
|
|
8
|
+
background-color: var(--yasgui-bg-primary, #fff);
|
|
9
|
+
border-color: var(--yasgui-border-color, #ccc);
|
|
10
10
|
border-width: 1px;
|
|
11
11
|
display: inline-block;
|
|
12
12
|
text-align: center;
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
|
|
34
34
|
&:hover {
|
|
35
35
|
outline: 0;
|
|
36
|
-
background-color: #ebebeb;
|
|
37
|
-
border-color: #adadad;
|
|
36
|
+
background-color: var(--yasgui-bg-secondary, #ebebeb);
|
|
37
|
+
border-color: var(--yasgui-text-muted, #adadad);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
&:focus,
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
&.btn_icon:focus {
|
|
49
|
-
color: #333;
|
|
49
|
+
color: var(--yasgui-text-primary, #333);
|
|
50
50
|
border: 1px solid transparent;
|
|
51
|
-
background-color: #fff;
|
|
52
|
-
border-color: #ccc;
|
|
51
|
+
background-color: var(--yasgui-bg-primary, #fff);
|
|
52
|
+
border-color: var(--yasgui-border-color, #ccc);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
&.yasqe_btn-sm {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
|
|
63
63
|
.yasqe_buttons {
|
|
64
64
|
position: absolute;
|
|
65
|
-
|
|
65
|
+
bottom: 10px;
|
|
66
66
|
right: 20px;
|
|
67
67
|
z-index: 5;
|
|
68
68
|
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
margin-left: 8px;
|
|
78
78
|
height: 36px;
|
|
79
79
|
width: 36px;
|
|
80
|
-
color: #505050;
|
|
80
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
81
81
|
|
|
82
82
|
i {
|
|
83
83
|
font-size: 20px;
|
|
@@ -96,22 +96,25 @@
|
|
|
96
96
|
position: absolute;
|
|
97
97
|
padding: 12px;
|
|
98
98
|
margin-left: 0px;
|
|
99
|
-
background-color: #fff;
|
|
100
|
-
border: 1px solid #e3e3e3;
|
|
99
|
+
background-color: var(--yasgui-bg-primary, #fff);
|
|
100
|
+
border: 1px solid var(--yasgui-border-color, #e3e3e3);
|
|
101
101
|
border-radius: 4px;
|
|
102
102
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
103
103
|
width: auto;
|
|
104
104
|
min-width: 300px;
|
|
105
105
|
max-width: 400px;
|
|
106
|
+
max-height: calc(100vh - 100px);
|
|
107
|
+
overflow-y: auto;
|
|
106
108
|
height: auto;
|
|
107
109
|
display: flex;
|
|
108
110
|
flex-direction: column;
|
|
109
111
|
gap: 8px;
|
|
112
|
+
z-index: 10001;
|
|
110
113
|
|
|
111
114
|
.yasqe_sharePopup_title {
|
|
112
115
|
font-weight: 600;
|
|
113
116
|
font-size: 14px;
|
|
114
|
-
color: #333;
|
|
117
|
+
color: var(--yasgui-text-primary, #333);
|
|
115
118
|
margin-bottom: 4px;
|
|
116
119
|
}
|
|
117
120
|
|
|
@@ -301,7 +304,7 @@
|
|
|
301
304
|
margin-left: 8px;
|
|
302
305
|
height: 36px;
|
|
303
306
|
width: 36px;
|
|
304
|
-
color: #505050;
|
|
307
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
305
308
|
|
|
306
309
|
i {
|
|
307
310
|
font-size: 20px;
|
|
@@ -323,7 +326,7 @@
|
|
|
323
326
|
margin-left: 8px;
|
|
324
327
|
height: 36px;
|
|
325
328
|
width: 36px;
|
|
326
|
-
color: #505050;
|
|
329
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
327
330
|
|
|
328
331
|
i {
|
|
329
332
|
font-size: 20px;
|
|
@@ -345,7 +348,7 @@
|
|
|
345
348
|
margin-left: 8px;
|
|
346
349
|
height: 36px;
|
|
347
350
|
width: 36px;
|
|
348
|
-
color: #505050;
|
|
351
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
349
352
|
|
|
350
353
|
i {
|
|
351
354
|
font-size: 20px;
|
|
@@ -359,6 +362,95 @@
|
|
|
359
362
|
color: #337ab7;
|
|
360
363
|
}
|
|
361
364
|
}
|
|
365
|
+
|
|
366
|
+
.yasqe_hamburgerButton {
|
|
367
|
+
display: none;
|
|
368
|
+
align-items: center;
|
|
369
|
+
justify-content: center;
|
|
370
|
+
border: none;
|
|
371
|
+
background: none;
|
|
372
|
+
cursor: pointer;
|
|
373
|
+
padding: 6px;
|
|
374
|
+
margin-left: 8px;
|
|
375
|
+
height: 36px;
|
|
376
|
+
width: 36px;
|
|
377
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
378
|
+
|
|
379
|
+
i {
|
|
380
|
+
font-size: 20px;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
&:hover {
|
|
384
|
+
color: #337ab7;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
&[aria-expanded="true"] {
|
|
388
|
+
color: #337ab7;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.yasqe_hamburgerMenu {
|
|
393
|
+
display: none;
|
|
394
|
+
position: absolute;
|
|
395
|
+
bottom: 46px;
|
|
396
|
+
right: 0;
|
|
397
|
+
background-color: var(--yasgui-bg-primary, #fff);
|
|
398
|
+
border: 1px solid var(--yasgui-border-color, #e3e3e3);
|
|
399
|
+
border-radius: 4px;
|
|
400
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
401
|
+
padding: 4px;
|
|
402
|
+
min-width: 180px;
|
|
403
|
+
z-index: 10000;
|
|
404
|
+
|
|
405
|
+
&.active {
|
|
406
|
+
display: block;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.yasqe_hamburgerMenuItem {
|
|
410
|
+
display: flex;
|
|
411
|
+
align-items: center;
|
|
412
|
+
gap: 10px;
|
|
413
|
+
width: 100%;
|
|
414
|
+
padding: 10px 12px;
|
|
415
|
+
border: none;
|
|
416
|
+
background: none;
|
|
417
|
+
text-align: left;
|
|
418
|
+
cursor: pointer;
|
|
419
|
+
font-size: 14px;
|
|
420
|
+
color: var(--yasgui-text-primary, #333);
|
|
421
|
+
border-radius: 2px;
|
|
422
|
+
|
|
423
|
+
i {
|
|
424
|
+
font-size: 16px;
|
|
425
|
+
width: 20px;
|
|
426
|
+
color: var(--yasgui-text-secondary, #505050);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
&:hover {
|
|
430
|
+
background-color: var(--yasgui-bg-secondary, #f0f0f0);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
&:active {
|
|
434
|
+
background-color: var(--yasgui-bg-tertiary, #e0e0e0);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Responsive: Show hamburger menu on smaller screens
|
|
441
|
+
@media (max-width: 768px) {
|
|
442
|
+
.yasqe_buttons {
|
|
443
|
+
.yasqe_share,
|
|
444
|
+
.yasqe_saveButton,
|
|
445
|
+
.yasqe_formatButton,
|
|
446
|
+
.yasqe_fullscreenButton {
|
|
447
|
+
display: none !important;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.yasqe_hamburgerButton {
|
|
451
|
+
display: inline-flex;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
362
454
|
}
|
|
363
455
|
|
|
364
456
|
&.fullscreen {
|
|
@@ -368,7 +460,7 @@
|
|
|
368
460
|
right: 0;
|
|
369
461
|
bottom: 0;
|
|
370
462
|
z-index: 9998;
|
|
371
|
-
background: white;
|
|
463
|
+
background: var(--yasgui-bg-primary, white);
|
|
372
464
|
margin: 0;
|
|
373
465
|
padding-top: 100px;
|
|
374
466
|
|
|
@@ -378,7 +470,7 @@
|
|
|
378
470
|
|
|
379
471
|
.yasqe_buttons {
|
|
380
472
|
position: fixed;
|
|
381
|
-
|
|
473
|
+
bottom: 40px;
|
|
382
474
|
right: 20px;
|
|
383
475
|
z-index: 10000;
|
|
384
476
|
}
|