@matdata/yasgui 5.7.0 → 5.8.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 +157 -3
- package/build/ts/src/Tab.d.ts +8 -0
- package/build/ts/src/Tab.js +76 -0
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/version.d.ts +1 -1
- package/build/ts/src/version.js +1 -1
- package/build/yasgui.min.css +1 -1
- package/build/yasgui.min.css.map +3 -3
- package/build/yasgui.min.js +102 -102
- package/build/yasgui.min.js.map +4 -4
- package/package.json +3 -3
- package/src/Tab.ts +100 -0
- package/src/TabElements.scss +22 -2
- package/src/index.scss +17 -0
- package/src/tab.scss +82 -23
- package/src/themes.scss +2 -4
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matdata/yasgui",
|
|
3
3
|
"description": "Yet Another SPARQL GUI",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.8.0",
|
|
5
5
|
"main": "build/yasgui.min.js",
|
|
6
6
|
"types": "build/ts/src/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"jsuri": "^1.3.1",
|
|
34
34
|
"lodash-es": "^4.17.15",
|
|
35
35
|
"sortablejs": "^1.10.2",
|
|
36
|
-
"@matdata/yasgui-graph-plugin": "^1.
|
|
37
|
-
"@matdata/yasgui-table-plugin": "^1.
|
|
36
|
+
"@matdata/yasgui-graph-plugin": "^1.4.0",
|
|
37
|
+
"@matdata/yasgui-table-plugin": "^1.1.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/autosuggest-highlight": "^3.1.0",
|
package/src/Tab.ts
CHANGED
|
@@ -78,6 +78,8 @@ export class Tab extends EventEmitter {
|
|
|
78
78
|
private settingsModal?: TabSettingsModal;
|
|
79
79
|
private currentOrientation: "vertical" | "horizontal";
|
|
80
80
|
private orientationToggleButton?: HTMLButtonElement;
|
|
81
|
+
private verticalResizerEl?: HTMLDivElement;
|
|
82
|
+
private editorWrapperEl?: HTMLDivElement;
|
|
81
83
|
|
|
82
84
|
constructor(yasgui: Yasgui, conf: PersistedJson) {
|
|
83
85
|
super();
|
|
@@ -115,6 +117,7 @@ export class Tab extends EventEmitter {
|
|
|
115
117
|
// Useful for adding an infos div that goes alongside the editor without needing to rebuild the whole Yasgui class
|
|
116
118
|
const editorWrapper = document.createElement("div");
|
|
117
119
|
editorWrapper.className = "editorwrapper";
|
|
120
|
+
this.editorWrapperEl = editorWrapper;
|
|
118
121
|
const controlbarAndYasqeDiv = document.createElement("div");
|
|
119
122
|
//controlbar
|
|
120
123
|
this.controlBarEl = document.createElement("div");
|
|
@@ -132,6 +135,10 @@ export class Tab extends EventEmitter {
|
|
|
132
135
|
|
|
133
136
|
this.initTabSettingsMenu();
|
|
134
137
|
this.rootEl.appendChild(editorWrapper);
|
|
138
|
+
|
|
139
|
+
// Add vertical resizer for horizontal layout
|
|
140
|
+
this.drawVerticalResizer();
|
|
141
|
+
|
|
135
142
|
this.rootEl.appendChild(this.yasrWrapperEl);
|
|
136
143
|
this.initControlbar();
|
|
137
144
|
this.initYasqe();
|
|
@@ -321,6 +328,12 @@ export class Tab extends EventEmitter {
|
|
|
321
328
|
tab.updateOrientationToggleIcon();
|
|
322
329
|
}
|
|
323
330
|
|
|
331
|
+
// Reset editor wrapper width when switching orientations
|
|
332
|
+
if (tab.editorWrapperEl) {
|
|
333
|
+
tab.editorWrapperEl.style.width = "";
|
|
334
|
+
tab.editorWrapperEl.style.flex = "";
|
|
335
|
+
}
|
|
336
|
+
|
|
324
337
|
// Refresh components to adjust to new layout
|
|
325
338
|
if (tab.yasqe) {
|
|
326
339
|
tab.yasqe.refresh();
|
|
@@ -986,7 +999,94 @@ WHERE {
|
|
|
986
999
|
});
|
|
987
1000
|
}
|
|
988
1001
|
|
|
1002
|
+
private drawVerticalResizer() {
|
|
1003
|
+
if (this.verticalResizerEl || !this.rootEl) return;
|
|
1004
|
+
this.verticalResizerEl = document.createElement("div");
|
|
1005
|
+
addClass(this.verticalResizerEl, "verticalResizeWrapper");
|
|
1006
|
+
const chip = document.createElement("div");
|
|
1007
|
+
addClass(chip, "verticalResizeChip");
|
|
1008
|
+
this.verticalResizerEl.appendChild(chip);
|
|
1009
|
+
this.verticalResizerEl.addEventListener("mousedown", this.initVerticalDrag, false);
|
|
1010
|
+
this.verticalResizerEl.addEventListener("dblclick", this.resetVerticalSplit, false);
|
|
1011
|
+
this.rootEl.appendChild(this.verticalResizerEl);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
private initVerticalDrag = () => {
|
|
1015
|
+
document.documentElement.addEventListener("mousemove", this.doVerticalDrag, false);
|
|
1016
|
+
document.documentElement.addEventListener("mouseup", this.stopVerticalDrag, false);
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
private calculateVerticalDragOffset(event: MouseEvent): number {
|
|
1020
|
+
if (!this.rootEl) return 0;
|
|
1021
|
+
|
|
1022
|
+
let parentOffset = 0;
|
|
1023
|
+
if (this.rootEl.offsetParent) {
|
|
1024
|
+
parentOffset = (this.rootEl.offsetParent as HTMLElement).offsetLeft;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
let scrollOffset = 0;
|
|
1028
|
+
let parentElement = this.rootEl.parentElement;
|
|
1029
|
+
while (parentElement) {
|
|
1030
|
+
scrollOffset += parentElement.scrollLeft;
|
|
1031
|
+
parentElement = parentElement.parentElement;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
return event.clientX - parentOffset - this.rootEl.offsetLeft + scrollOffset;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
private doVerticalDrag = (event: MouseEvent) => {
|
|
1038
|
+
if (!this.editorWrapperEl || !this.rootEl) return;
|
|
1039
|
+
|
|
1040
|
+
const offset = this.calculateVerticalDragOffset(event);
|
|
1041
|
+
const totalWidth = this.rootEl.offsetWidth;
|
|
1042
|
+
|
|
1043
|
+
// Ensure minimum widths (at least 200px for each panel)
|
|
1044
|
+
const minWidth = 200;
|
|
1045
|
+
const maxWidth = totalWidth - minWidth - 10; // 10px for resizer
|
|
1046
|
+
|
|
1047
|
+
const newWidth = Math.max(minWidth, Math.min(maxWidth, offset));
|
|
1048
|
+
this.editorWrapperEl.style.width = newWidth + "px";
|
|
1049
|
+
this.editorWrapperEl.style.flex = "0 0 " + newWidth + "px";
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
private stopVerticalDrag = () => {
|
|
1053
|
+
document.documentElement.removeEventListener("mousemove", this.doVerticalDrag, false);
|
|
1054
|
+
document.documentElement.removeEventListener("mouseup", this.stopVerticalDrag, false);
|
|
1055
|
+
|
|
1056
|
+
// Refresh editors after resizing
|
|
1057
|
+
if (this.yasqe) {
|
|
1058
|
+
this.yasqe.refresh();
|
|
1059
|
+
}
|
|
1060
|
+
if (this.yasr) {
|
|
1061
|
+
this.yasr.refresh();
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
private resetVerticalSplit = () => {
|
|
1066
|
+
if (!this.editorWrapperEl) return;
|
|
1067
|
+
|
|
1068
|
+
// Reset to 50/50 split
|
|
1069
|
+
this.editorWrapperEl.style.width = "";
|
|
1070
|
+
this.editorWrapperEl.style.flex = "1 1 50%";
|
|
1071
|
+
|
|
1072
|
+
// Refresh editors after resizing
|
|
1073
|
+
if (this.yasqe) {
|
|
1074
|
+
this.yasqe.refresh();
|
|
1075
|
+
}
|
|
1076
|
+
if (this.yasr) {
|
|
1077
|
+
this.yasr.refresh();
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
|
|
989
1081
|
destroy() {
|
|
1082
|
+
// Clean up vertical resizer event listeners
|
|
1083
|
+
if (this.verticalResizerEl) {
|
|
1084
|
+
this.verticalResizerEl.removeEventListener("mousedown", this.initVerticalDrag, false);
|
|
1085
|
+
this.verticalResizerEl.removeEventListener("dblclick", this.resetVerticalSplit, false);
|
|
1086
|
+
}
|
|
1087
|
+
document.documentElement.removeEventListener("mousemove", this.doVerticalDrag, false);
|
|
1088
|
+
document.documentElement.removeEventListener("mouseup", this.stopVerticalDrag, false);
|
|
1089
|
+
|
|
990
1090
|
this.removeAllListeners();
|
|
991
1091
|
this.settingsModal?.destroy();
|
|
992
1092
|
this.endpointSelect?.destroy();
|
package/src/TabElements.scss
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
@use "sass:color";
|
|
2
|
+
|
|
2
3
|
$minTabHeight: 35px;
|
|
4
|
+
|
|
3
5
|
.yasgui {
|
|
4
6
|
.tabsList {
|
|
7
|
+
flex-shrink: 0; // Prevent tabs from shrinking
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-wrap: wrap;
|
|
10
|
+
|
|
5
11
|
.sortable-placeholder {
|
|
6
12
|
min-width: 100px;
|
|
7
13
|
min-height: $minTabHeight;
|
|
8
14
|
border: 2px dotted color.adjust(#555, $lightness: 20%);
|
|
9
15
|
}
|
|
10
|
-
|
|
11
|
-
flex-wrap: wrap;
|
|
16
|
+
|
|
12
17
|
a {
|
|
13
18
|
cursor: pointer;
|
|
14
19
|
display: flex;
|
|
@@ -18,6 +23,7 @@ $minTabHeight: 35px;
|
|
|
18
23
|
border-bottom: 2px solid transparent;
|
|
19
24
|
box-sizing: border-box;
|
|
20
25
|
}
|
|
26
|
+
|
|
21
27
|
.themeToggle {
|
|
22
28
|
cursor: pointer;
|
|
23
29
|
height: 100%;
|
|
@@ -60,10 +66,12 @@ $minTabHeight: 35px;
|
|
|
60
66
|
&:focus-visible {
|
|
61
67
|
transform: scale(1.1);
|
|
62
68
|
}
|
|
69
|
+
|
|
63
70
|
&:focus {
|
|
64
71
|
color: #faa857;
|
|
65
72
|
}
|
|
66
73
|
}
|
|
74
|
+
|
|
67
75
|
.tab {
|
|
68
76
|
position: relative;
|
|
69
77
|
$activeColor: #337ab7;
|
|
@@ -82,6 +90,7 @@ $minTabHeight: 35px;
|
|
|
82
90
|
animation-timing-function: ease;
|
|
83
91
|
animation-iteration-count: infinite;
|
|
84
92
|
}
|
|
93
|
+
|
|
85
94
|
@keyframes slide {
|
|
86
95
|
0% {
|
|
87
96
|
left: 0;
|
|
@@ -96,24 +105,30 @@ $minTabHeight: 35px;
|
|
|
96
105
|
right: 0;
|
|
97
106
|
}
|
|
98
107
|
}
|
|
108
|
+
|
|
99
109
|
&.active .loader {
|
|
100
110
|
background-color: $hoverColor;
|
|
101
111
|
}
|
|
112
|
+
|
|
102
113
|
&:hover .loader {
|
|
103
114
|
background-color: $activeColor;
|
|
104
115
|
}
|
|
116
|
+
|
|
105
117
|
&.querying .loader {
|
|
106
118
|
display: block;
|
|
107
119
|
}
|
|
120
|
+
|
|
108
121
|
&.active a {
|
|
109
122
|
border-bottom-color: $activeColor;
|
|
110
123
|
color: var(--yasgui-text-primary, #555);
|
|
111
124
|
}
|
|
125
|
+
|
|
112
126
|
input {
|
|
113
127
|
display: none;
|
|
114
128
|
outline: none;
|
|
115
129
|
border: none;
|
|
116
130
|
}
|
|
131
|
+
|
|
117
132
|
&.renaming {
|
|
118
133
|
span {
|
|
119
134
|
display: none;
|
|
@@ -125,6 +140,7 @@ $minTabHeight: 35px;
|
|
|
125
140
|
display: block;
|
|
126
141
|
}
|
|
127
142
|
}
|
|
143
|
+
|
|
128
144
|
a {
|
|
129
145
|
font-weight: 600;
|
|
130
146
|
color: var(--yasgui-text-secondary, color.adjust(#555, $lightness: 20%));
|
|
@@ -135,14 +151,17 @@ $minTabHeight: 35px;
|
|
|
135
151
|
padding: 0px 24px 0px 30px;
|
|
136
152
|
white-space: nowrap;
|
|
137
153
|
overflow: hidden;
|
|
154
|
+
|
|
138
155
|
&:hover {
|
|
139
156
|
border-bottom-color: $hoverColor;
|
|
140
157
|
color: var(--yasgui-text-primary, #555);
|
|
141
158
|
}
|
|
159
|
+
|
|
142
160
|
&:focus {
|
|
143
161
|
border-bottom-color: #faa857;
|
|
144
162
|
color: var(--yasgui-text-primary, #555);
|
|
145
163
|
}
|
|
164
|
+
|
|
146
165
|
.closeTab {
|
|
147
166
|
color: var(--yasgui-text-primary, #000);
|
|
148
167
|
margin-left: 7px;
|
|
@@ -151,6 +170,7 @@ $minTabHeight: 35px;
|
|
|
151
170
|
opacity: 0.2;
|
|
152
171
|
font-weight: 700;
|
|
153
172
|
padding: 2px;
|
|
173
|
+
|
|
154
174
|
&:hover {
|
|
155
175
|
opacity: 0.5;
|
|
156
176
|
}
|
package/src/index.scss
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
// Main YASGUI container - fills 100% of parent element
|
|
2
|
+
// Parent element (typically body) should have height: 100%; width: 100%
|
|
1
3
|
.yasgui {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
height: 100%;
|
|
7
|
+
width: 100%;
|
|
8
|
+
min-height: 800px; // Minimum to ensure usable UI (control bar + editor + yasr min)
|
|
9
|
+
|
|
2
10
|
a {
|
|
3
11
|
color: #337ab7;
|
|
4
12
|
text-decoration: none;
|
|
@@ -28,6 +36,15 @@
|
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
|
|
39
|
+
// Container for tab panels - takes remaining height after tabsList
|
|
40
|
+
> div:not(.tabsList) {
|
|
41
|
+
flex: 1;
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
min-height: 0; // Required for flex children to shrink properly
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
//css taken from https://www.muicss.com/docs/v1/css-js/forms
|
|
32
49
|
$focusColor: #337ab7;
|
|
33
50
|
$font-size: 15px;
|
package/src/tab.scss
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
.tabPanel {
|
|
3
3
|
display: none;
|
|
4
4
|
position: relative;
|
|
5
|
+
flex: 1;
|
|
6
|
+
min-height: 0;
|
|
7
|
+
|
|
5
8
|
&.active {
|
|
6
|
-
display:
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.yasrWrapperEl {
|
|
14
|
+
height: 100%;
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
// Hide editor wrapper when yasr is in fullscreen
|
|
@@ -34,45 +42,95 @@
|
|
|
34
42
|
display: flex;
|
|
35
43
|
flex-direction: row;
|
|
36
44
|
gap: 10px;
|
|
37
|
-
|
|
38
|
-
min-height: var(--yasgui-min-height);
|
|
39
|
-
max-height: calc(100vh - var(--yasgui-header-height));
|
|
45
|
+
height: 100%;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
.editorwrapper {
|
|
43
|
-
flex: 1
|
|
49
|
+
flex: 1 1 50%;
|
|
44
50
|
display: flex;
|
|
45
51
|
flex-direction: column;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.yasqe {
|
|
50
|
-
display: flex;
|
|
51
|
-
flex-direction: column;
|
|
52
|
-
flex: 1;
|
|
53
|
-
min-height: 0;
|
|
52
|
+
min-width: 400px;
|
|
53
|
+
max-width: 50%;
|
|
54
|
+
height: 100%;
|
|
54
55
|
overflow: hidden;
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
// Unnamed div container needs full height
|
|
58
|
+
> div {
|
|
59
|
+
height: 100%;
|
|
60
|
+
flex: 1;
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
|
|
64
|
+
// Container for tab panels - takes remaining height after tabsList
|
|
65
|
+
> div:not(.controlbar) {
|
|
66
|
+
flex: 1;
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
min-height: 0; // Required for flex children to shrink properly
|
|
70
|
+
overflow: hidden;
|
|
71
|
+
|
|
72
|
+
// Make YASQE fill the vertical space in horizontal mode
|
|
73
|
+
.yasqe {
|
|
74
|
+
flex: 1;
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
height: 100%;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
|
|
80
|
+
.CodeMirror {
|
|
81
|
+
flex: 1;
|
|
82
|
+
height: 100%;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
58
86
|
}
|
|
59
87
|
}
|
|
60
88
|
|
|
61
89
|
.yasrWrapperEl {
|
|
62
|
-
flex: 1
|
|
90
|
+
flex: 1 1 50%;
|
|
63
91
|
min-width: 0;
|
|
64
|
-
height:
|
|
65
|
-
overflow: hidden;
|
|
92
|
+
min-height: 400px;
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
.yasr {
|
|
69
96
|
margin-top: 0;
|
|
70
97
|
height: 100%;
|
|
71
98
|
}
|
|
99
|
+
|
|
100
|
+
// Hide horizontal resize wrapper in horizontal mode (vertical resizer is used instead)
|
|
101
|
+
.horizontalResizeWrapper {
|
|
102
|
+
display: none;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Vertical resizer for horizontal layout
|
|
107
|
+
.verticalResizeWrapper {
|
|
108
|
+
display: none; // Hidden by default (shown only in horizontal mode)
|
|
109
|
+
width: 10px;
|
|
110
|
+
flex-shrink: 0;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
cursor: col-resize;
|
|
114
|
+
position: relative;
|
|
115
|
+
z-index: 10;
|
|
116
|
+
|
|
117
|
+
&:hover .verticalResizeChip {
|
|
118
|
+
visibility: visible;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.verticalResizeChip {
|
|
123
|
+
width: 4px;
|
|
124
|
+
height: 20%;
|
|
125
|
+
background-color: #d1d1d1;
|
|
126
|
+
visibility: hidden;
|
|
127
|
+
border-radius: 2px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Show vertical resizer only in horizontal mode
|
|
131
|
+
&.orientation-horizontal .verticalResizeWrapper {
|
|
132
|
+
display: flex;
|
|
72
133
|
}
|
|
73
|
-
}
|
|
74
|
-
.yasr {
|
|
75
|
-
margin-top: 5px;
|
|
76
134
|
}
|
|
77
135
|
|
|
78
136
|
.tabContextButton {
|
|
@@ -91,9 +149,9 @@
|
|
|
91
149
|
.svgImg {
|
|
92
150
|
width: 15px;
|
|
93
151
|
height: 15px;
|
|
94
|
-
font-family: initial;
|
|
152
|
+
font-family: initial;
|
|
95
153
|
}
|
|
96
|
-
|
|
154
|
+
|
|
97
155
|
svg {
|
|
98
156
|
width: 20px;
|
|
99
157
|
height: 20px;
|
|
@@ -108,6 +166,7 @@
|
|
|
108
166
|
.controlbar {
|
|
109
167
|
display: flex;
|
|
110
168
|
align-content: center;
|
|
169
|
+
flex-shrink: 0;
|
|
111
170
|
max-height: 35px;
|
|
112
171
|
}
|
|
113
172
|
}
|
package/src/themes.scss
CHANGED
|
@@ -38,10 +38,8 @@
|
|
|
38
38
|
--yasgui-nav-bg: #eee;
|
|
39
39
|
--yasgui-match-highlight-bg: #dbdeed;
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
--yasgui-
|
|
43
|
-
--yasgui-tabList-height: 70px; // Height to subtract from yasr in horizontal layout
|
|
44
|
-
--yasgui-min-height: 400px; // Minimum height for horizontal layout panels
|
|
41
|
+
// Minimum heights
|
|
42
|
+
--yasgui-yasr-min-height: 400px; // Minimum height for yasr
|
|
45
43
|
|
|
46
44
|
--yasgui-endpoint-button-bg: #337ab7;
|
|
47
45
|
--yasgui-endpoint-button-border: #337ab7;
|
package/src/version.ts
CHANGED