x4js 2.0.32 → 2.0.33
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/package.json +1 -1
- package/src/components/base.scss +4 -0
- package/src/components/dialog/dialog.module.scss +2 -1
- package/src/components/gridview/folder-open.svg +1 -0
- package/src/components/gridview/gridview.module.scss +14 -0
- package/src/components/gridview/gridview.ts +51 -12
- package/src/components/label/label.module.scss +1 -0
- package/src/components/messages/messages.module.scss +37 -0
- package/src/components/messages/messages.ts +46 -3
- package/src/components/messages/spinner.svg +1 -0
- package/src/components/sizers/sizer.module.scss +18 -1
- package/src/components/sizers/sizer.ts +14 -11
- package/src/components/tabs/tabs.module.scss +21 -0
- package/src/components/tabs/tabs.ts +10 -5
- package/src/core/core_application.ts +1 -1
package/package.json
CHANGED
package/src/components/base.scss
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Pro 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2026 Fonticons, Inc.--><path opacity=".4" d="M32 96l0 200.6 21.7-54.3C65.9 211.9 95.3 192 128 192l320 0 0-32c0-17.7-14.3-32-32-32l-117.5 0c-25.5 0-49.9-10.1-67.9-28.1L204.1 73.4c-6-6-14.1-9.4-22.6-9.4L64 64C46.3 64 32 78.3 32 96zM49.1 426.1c-2 4.9-1.4 10.5 1.6 14.9s7.9 7 13.2 7l320 0 80 0c6.5 0 12.4-4 14.9-10.1l64-160c2-4.9 1.4-10.5-1.6-14.9s-7.9-7-13.2-7l-400 0c-6.5 0-12.4 4-14.9 10.1l-64 160z"/><path d="M448 160l0 32 32 0 0-32c0-35.3-28.7-64-64-64L298.5 96c-17 0-33.3-6.7-45.3-18.7L226.7 50.7c-12-12-28.3-18.7-45.3-18.7L64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0 80 0c19.6 0 37.3-11.9 44.6-30.2l64-160c5.9-14.8 4.1-31.5-4.8-44.7S543.9 224 528 224l-400 0c-19.6 0-37.3 11.9-44.6 30.2L32 382.8 32 96c0-17.7 14.3-32 32-32l117.5 0c8.5 0 16.6 3.4 22.6 9.4l22.6-22.6L204.1 73.4l26.5 26.5c18 18 42.4 28.1 67.9 28.1L416 128c17.7 0 32 14.3 32 32zM384 448L64 448c-5.3 0-10.3-2.6-13.2-7s-3.6-10-1.6-14.9l64-160c2.4-6.1 8.3-10.1 14.9-10.1l400 0c5.3 0 10.3 2.6 13.2 7s3.6 10 1.6 14.9l-64 160C476.4 444 470.5 448 464 448l-80 0z"/></svg>
|
|
@@ -109,7 +109,21 @@
|
|
|
109
109
|
bottom: var( --scrollbar-size );
|
|
110
110
|
left: 0;
|
|
111
111
|
top: 0;
|
|
112
|
+
|
|
113
|
+
.empty {
|
|
114
|
+
position: relative;
|
|
115
|
+
left: 50%;
|
|
116
|
+
top: 20%;
|
|
117
|
+
width: fit-content;
|
|
118
|
+
|
|
119
|
+
#icon {
|
|
120
|
+
height: 64px;
|
|
121
|
+
fill: var( --accent-background );
|
|
122
|
+
opacity: 50%;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
112
125
|
}
|
|
126
|
+
|
|
113
127
|
.row {
|
|
114
128
|
position: absolute;
|
|
115
129
|
left: 0;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
import { Component, ComponentContent, ComponentEvents, ComponentProps, EvClick, EvContextMenu, EvDblClick, EvSelectionChange
|
|
18
|
+
import { Component, ComponentContent, ComponentEvents, ComponentProps, EvClick, EvContextMenu, EvDblClick, EvSelectionChange } from '../../core/component';
|
|
19
19
|
import { class_ns, isNumber, isString, setWaitCursor, UnsafeHtml } from '../../core/core_tools';
|
|
20
20
|
import { DataModel, DataStore, DataView, DataRecord, EvViewChange } from '../../core/core_data';
|
|
21
21
|
import { EventCallback } from '../../core/core_events';
|
|
@@ -26,9 +26,13 @@ import { Image } from '../image/image'
|
|
|
26
26
|
import { Box } from '../boxes/boxes';
|
|
27
27
|
import { CSizer } from '../sizers/sizer'
|
|
28
28
|
import { Viewport } from '../viewport/viewport';
|
|
29
|
-
import { SimpleText } from '../label/label';
|
|
29
|
+
import { Label, SimpleText } from '../label/label';
|
|
30
|
+
|
|
31
|
+
import { _tr } from '../../core/core_i18n';
|
|
30
32
|
|
|
31
33
|
import check_icon from "../checkbox/check.svg";
|
|
34
|
+
import empty_icon from "./folder-open.svg";
|
|
35
|
+
|
|
32
36
|
import "./gridview.module.scss"
|
|
33
37
|
|
|
34
38
|
export type CellRenderer = (rec: DataRecord) => Component;
|
|
@@ -75,11 +79,16 @@ export interface GridviewProps extends ComponentProps {
|
|
|
75
79
|
footer?: boolean;
|
|
76
80
|
store: DataStore;
|
|
77
81
|
columns: GridColumn[];
|
|
82
|
+
emptyMsg?: string;
|
|
78
83
|
|
|
79
84
|
click?: EventCallback<EvClick>;
|
|
80
85
|
dblClick?: EventCallback<EvDblClick>;
|
|
81
86
|
contextMenu?: EventCallback<EvContextMenu>;
|
|
82
87
|
selectionChange?: EventCallback<EvSelectionChange>;
|
|
88
|
+
sort?: {
|
|
89
|
+
id: string;
|
|
90
|
+
asc?: boolean;
|
|
91
|
+
}
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
/**
|
|
@@ -121,6 +130,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
121
130
|
private _end: number;
|
|
122
131
|
|
|
123
132
|
private _selection: Set<number>;
|
|
133
|
+
|
|
124
134
|
|
|
125
135
|
// TODO: that
|
|
126
136
|
private _num_fmt = new Intl.NumberFormat('fr-FR');
|
|
@@ -172,8 +182,11 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
172
182
|
|
|
173
183
|
if (props.store) {
|
|
174
184
|
this.setStore(props.store);
|
|
175
|
-
}
|
|
176
185
|
|
|
186
|
+
if( props.sort ) {
|
|
187
|
+
this.sortCol( props.sort.id, props.sort.asc===true );
|
|
188
|
+
}
|
|
189
|
+
}
|
|
177
190
|
}
|
|
178
191
|
|
|
179
192
|
/**
|
|
@@ -240,7 +253,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
240
253
|
|
|
241
254
|
if( sens==kbNav.first || sens==kbNav.last ) {
|
|
242
255
|
let nel = sens==kbNav.first ? 0 : this._dataview.getCount()-1;
|
|
243
|
-
this._clearSelection();
|
|
256
|
+
this._clearSelection( false );
|
|
244
257
|
this._addSelection( nel );
|
|
245
258
|
this._scrollToIndex( nel );
|
|
246
259
|
return true;
|
|
@@ -249,7 +262,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
249
262
|
const fsel = this._selection.values().next().value;
|
|
250
263
|
let nel = sens==kbNav.next ? fsel+1 : fsel-1;
|
|
251
264
|
if( nel>=0 && nel<this._dataview.getCount() ) {
|
|
252
|
-
this._clearSelection();
|
|
265
|
+
this._clearSelection( false );
|
|
253
266
|
this._addSelection( nel );
|
|
254
267
|
this._scrollToIndex( nel );
|
|
255
268
|
return true;
|
|
@@ -271,7 +284,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
271
284
|
}
|
|
272
285
|
|
|
273
286
|
if( nel!=fsel ) {
|
|
274
|
-
this._clearSelection();
|
|
287
|
+
this._clearSelection( false );
|
|
275
288
|
this._addSelection( nel );
|
|
276
289
|
|
|
277
290
|
if (this._dataview.getCount() < SCROLL_LIMIT) {
|
|
@@ -785,6 +798,13 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
785
798
|
rowel.addClass("selected");
|
|
786
799
|
}
|
|
787
800
|
|
|
801
|
+
if( rowid&1 ) {
|
|
802
|
+
rowel.addClass( "even" );
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
rowel.addClass( "odd" );
|
|
806
|
+
}
|
|
807
|
+
|
|
788
808
|
return rowel;
|
|
789
809
|
}
|
|
790
810
|
|
|
@@ -922,7 +942,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
922
942
|
}
|
|
923
943
|
|
|
924
944
|
this.setStyleVariable("--fixed-width", maxfw + "px");
|
|
925
|
-
this._body.setStyleValue("height", maxh + "px");
|
|
945
|
+
this._body.setStyleValue("height", maxh==0 ? "100%" : maxh + "px");
|
|
926
946
|
this._body.setStyleValue("width", maxw + "px");
|
|
927
947
|
this._vheader.setStyleValue("height", maxh + "px");
|
|
928
948
|
}
|
|
@@ -998,10 +1018,13 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
998
1018
|
if (row!==undefined ) {
|
|
999
1019
|
//TODO: multiselection
|
|
1000
1020
|
if( !this._selection.has(row) ) {
|
|
1001
|
-
this._clearSelection();
|
|
1021
|
+
this._clearSelection( false );
|
|
1002
1022
|
this._addSelection(row);
|
|
1003
1023
|
}
|
|
1004
1024
|
}
|
|
1025
|
+
else {
|
|
1026
|
+
this._clearSelection( true );
|
|
1027
|
+
}
|
|
1005
1028
|
});
|
|
1006
1029
|
|
|
1007
1030
|
// DBLCLICK
|
|
@@ -1010,7 +1033,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1010
1033
|
if (row!==undefined ) {
|
|
1011
1034
|
//TODO: multiselection
|
|
1012
1035
|
if( !this._selection.has(row) ) {
|
|
1013
|
-
this._clearSelection();
|
|
1036
|
+
this._clearSelection( false );
|
|
1014
1037
|
this._addSelection(row);
|
|
1015
1038
|
}
|
|
1016
1039
|
|
|
@@ -1027,7 +1050,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1027
1050
|
if (row!==undefined ) {
|
|
1028
1051
|
//TODO: multiselection
|
|
1029
1052
|
if( !this._selection.has(row) ) {
|
|
1030
|
-
this._clearSelection();
|
|
1053
|
+
this._clearSelection( false );
|
|
1031
1054
|
this._addSelection(row);
|
|
1032
1055
|
}
|
|
1033
1056
|
|
|
@@ -1114,6 +1137,14 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1114
1137
|
|
|
1115
1138
|
// rows
|
|
1116
1139
|
const rowc = this._dataview ? this._dataview.getCount() : 0;
|
|
1140
|
+
|
|
1141
|
+
// empty ?
|
|
1142
|
+
if( rowc==0 ) {
|
|
1143
|
+
this._body.setContent( new Label( { cls: "empty vertical", icon: empty_icon, text: this.props.emptyMsg ?? _tr.global.empty_list } ) );
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
|
|
1117
1148
|
const mul = rowc < SCROLL_LIMIT ? this._row_height : 1;
|
|
1118
1149
|
|
|
1119
1150
|
const start = Math.floor(this._top / mul);
|
|
@@ -1190,10 +1221,14 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1190
1221
|
*/
|
|
1191
1222
|
|
|
1192
1223
|
clearSelection( ) {
|
|
1193
|
-
this._clearSelection( );
|
|
1224
|
+
this._clearSelection( false );
|
|
1194
1225
|
}
|
|
1195
1226
|
|
|
1196
|
-
private _clearSelection() {
|
|
1227
|
+
private _clearSelection( notify: boolean ) {
|
|
1228
|
+
if( !this._selection.size ) {
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1197
1232
|
for (const ref of this._selection.keys()) {
|
|
1198
1233
|
const els = this.queryAll(`.row[data-row="${ref}"]`)
|
|
1199
1234
|
els.forEach(el => {
|
|
@@ -1202,6 +1237,9 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1202
1237
|
}
|
|
1203
1238
|
|
|
1204
1239
|
this._selection.clear();
|
|
1240
|
+
if( notify ) {
|
|
1241
|
+
this.fire("selectionChange", { selection: [], empty: true } );
|
|
1242
|
+
}
|
|
1205
1243
|
}
|
|
1206
1244
|
|
|
1207
1245
|
/**
|
|
@@ -1274,3 +1312,4 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
1274
1312
|
}
|
|
1275
1313
|
}
|
|
1276
1314
|
|
|
1315
|
+
|
|
@@ -90,3 +90,40 @@
|
|
|
90
90
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
|
|
94
|
+
.x4progressionbox {
|
|
95
|
+
width: 640px;
|
|
96
|
+
height: 200px;
|
|
97
|
+
&> .x4form {
|
|
98
|
+
min-height: unset;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
& > .caption,
|
|
102
|
+
& > #btnbar {
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
& .x4form {
|
|
107
|
+
min-width: 400px;
|
|
108
|
+
.x4icon {
|
|
109
|
+
height: 64px;
|
|
110
|
+
animation: rotating 3s linear infinite;
|
|
111
|
+
fill: var(--accent-background);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.x4label,
|
|
115
|
+
.x4simpletext {
|
|
116
|
+
padding: 16px 16px 0 16px;
|
|
117
|
+
line-height: 1.8em;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.x4progress {
|
|
121
|
+
margin-left: 16px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
#sub-text {
|
|
125
|
+
max-height: 140px;
|
|
126
|
+
overflow-y: auto;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
// :: MESSAGEBOX ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
3
3
|
|
|
4
4
|
import { _tr } from '../../core/core_i18n';
|
|
5
|
-
import { asap, class_ns, UnsafeHtml } from '../../core/core_tools';
|
|
5
|
+
import { asap, class_ns, unsafeHtml, UnsafeHtml } from '../../core/core_tools';
|
|
6
6
|
|
|
7
7
|
import { HBox, VBox } from '../boxes/boxes';
|
|
8
8
|
import { Icon } from '../icon/icon';
|
|
9
|
-
import { Label } from '../label/label';
|
|
9
|
+
import { Label, SimpleText } from '../label/label';
|
|
10
10
|
import { Dialog, DialogProps } from "../dialog/dialog"
|
|
11
11
|
import { Form } from '../form/form';
|
|
12
12
|
import { BtnGroupItem } from '../btngroup/btngroup';
|
|
13
13
|
import { Input } from '../input/input';
|
|
14
|
+
import { Component } from '../../core/component';
|
|
15
|
+
import { Progress } from '../components.js';
|
|
14
16
|
|
|
15
17
|
import "./messages.module.scss";
|
|
16
18
|
|
|
17
19
|
import error_icon from "./circle-exclamation.svg";
|
|
18
20
|
import pen_icon from "./pen-field.svg";
|
|
19
|
-
import
|
|
21
|
+
import spinner from "./spinner.svg"
|
|
20
22
|
|
|
21
23
|
export interface MessageBoxProps extends DialogProps {
|
|
22
24
|
message: string;
|
|
@@ -235,3 +237,44 @@ export class PromptBox extends Dialog<DialogProps>
|
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
239
|
|
|
240
|
+
@class_ns( "x4" )
|
|
241
|
+
export class ProgressionBox extends Dialog {
|
|
242
|
+
|
|
243
|
+
#log: (string | UnsafeHtml)[];
|
|
244
|
+
|
|
245
|
+
constructor( title: string ) {
|
|
246
|
+
super( {
|
|
247
|
+
modal: true,
|
|
248
|
+
title: null,
|
|
249
|
+
movable: true,
|
|
250
|
+
form: new Form( {
|
|
251
|
+
content: [
|
|
252
|
+
new HBox( {
|
|
253
|
+
content: [
|
|
254
|
+
new Icon( { iconId: spinner }),
|
|
255
|
+
new VBox( { flex: 1, cls: "right", content: [
|
|
256
|
+
new SimpleText( { id: "title", text: title } ),
|
|
257
|
+
new Progress( { id:"prog", min: 0, max: 100, value: 0 } ),
|
|
258
|
+
new SimpleText( { id: "sub-text", text: "" } ),
|
|
259
|
+
]})
|
|
260
|
+
]
|
|
261
|
+
}),
|
|
262
|
+
]
|
|
263
|
+
}),
|
|
264
|
+
buttons: [ "ok.outline.default","cancel.outline" ]
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
this.#log = [];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
setText( text: string | UnsafeHtml, perc: number ) {
|
|
271
|
+
this.#log.push( text );
|
|
272
|
+
this.query<Label>( "#sub-text").setText( unsafeHtml(this.#log.join("<br/>")) );
|
|
273
|
+
this.query<Progress>( "#prog").setValue( perc );
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
clearText( ) {
|
|
277
|
+
this.#log = [];
|
|
278
|
+
this.query<Label>( "#sub-text").setText( '' );
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Pro 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2026 Fonticons, Inc.--><path d="M352 96C352 78.3 337.7 64 320 64C302.3 64 288 78.3 288 96C288 113.7 302.3 128 320 128C337.7 128 352 113.7 352 96zM352 544C352 526.3 337.7 512 320 512C302.3 512 288 526.3 288 544C288 561.7 302.3 576 320 576C337.7 576 352 561.7 352 544zM512 320C512 337.7 526.3 352 544 352C561.7 352 576 337.7 576 320C576 302.3 561.7 288 544 288C526.3 288 512 302.3 512 320zM96 352C113.7 352 128 337.7 128 320C128 302.3 113.7 288 96 288C78.3 288 64 302.3 64 320C64 337.7 78.3 352 96 352zM139 501C146.9 509.8 159 513.4 170.5 510.6C181.9 507.7 190.9 498.7 193.8 487.3C196.6 475.8 193 463.7 184.2 455.8C176.3 447 164.2 443.4 152.7 446.2C141.3 449.1 132.3 458.1 129.4 469.5C126.6 481 130.2 493.1 139 501zM455.8 501C463.7 509.8 475.8 513.4 487.3 510.6C498.7 507.7 507.7 498.7 510.6 487.3C513.4 475.8 509.8 463.7 501 455.8C493.1 447 481 443.4 469.5 446.2C458.1 449.1 449.1 458.1 446.2 469.5C443.4 481 447 493.1 455.8 501zM139 139C130.2 146.9 126.6 159 129.4 170.5C132.3 181.9 141.3 190.9 152.7 193.8C164.2 196.6 176.3 193 184.2 184.2C193 176.3 196.6 164.2 193.8 152.7C190.9 141.3 181.9 132.3 170.5 129.4C159 126.6 146.9 130.2 139 139z"/></svg>
|
|
@@ -26,6 +26,17 @@
|
|
|
26
26
|
cursor: ns-resize;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
&.inplace {
|
|
30
|
+
position: relative;
|
|
31
|
+
align-self: stretch;
|
|
32
|
+
min-width: 4px;
|
|
33
|
+
min-height: 4px;
|
|
34
|
+
|
|
35
|
+
&:hover {
|
|
36
|
+
background-color: var( --border );
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
&.top {
|
|
30
41
|
@include horz;
|
|
31
42
|
top: 0;
|
|
@@ -87,4 +98,10 @@
|
|
|
87
98
|
bottom: 0;
|
|
88
99
|
cursor: nw-resize;
|
|
89
100
|
}
|
|
90
|
-
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.x4hbox {
|
|
104
|
+
&>.x4csizer {
|
|
105
|
+
cursor: ew-resize;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -33,7 +33,7 @@ interface CSizerEvent extends ComponentEvents {
|
|
|
33
33
|
stop: ComponentEvent;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
type SizerType = "left" | "top" | "right" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" ;
|
|
36
|
+
type SizerType = "left" | "top" | "right" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "inplace";
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
@@ -52,15 +52,21 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
52
52
|
|
|
53
53
|
this._type = type;
|
|
54
54
|
this.addClass( type );
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
this.addDOMEvent( "pointerdown", ( e: PointerEvent ) => {
|
|
57
57
|
this.setCapture( e.pointerId );
|
|
58
|
-
|
|
58
|
+
|
|
59
|
+
let targ = target;
|
|
60
|
+
if( !targ && type=='inplace' ) {
|
|
61
|
+
targ = this.nextElement( );
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this._ref = targ ?? componentFromDOM( this.dom.parentElement );
|
|
59
65
|
|
|
60
66
|
this._delta = {x:0,y:0};
|
|
61
67
|
const rc = this._ref.getBoundingRect();
|
|
62
68
|
|
|
63
|
-
if( this._type.includes("left") ) {
|
|
69
|
+
if( this._type=="inplace" || this._type.includes("left") ) {
|
|
64
70
|
this._delta.x = e.pageX-rc.left;
|
|
65
71
|
}
|
|
66
72
|
else {
|
|
@@ -104,21 +110,18 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
104
110
|
nr.height = (rc.top+rc.height)-pt.y;
|
|
105
111
|
horz = false;
|
|
106
112
|
}
|
|
107
|
-
|
|
108
|
-
if( this._type.includes("bottom") ) {
|
|
113
|
+
else if( this._type.includes("bottom") ) {
|
|
109
114
|
//nr.top = rc.top;
|
|
110
115
|
nr.height = (pt.y-rc.top);
|
|
111
116
|
horz = false;
|
|
112
117
|
}
|
|
113
|
-
|
|
114
|
-
if( this._type.includes("left") ) {
|
|
118
|
+
else if( this._type=="inplace" || this._type.includes("left") ) {
|
|
115
119
|
nr.left = pt.x;
|
|
116
120
|
nr.width = ((rc.left+rc.width)-pt.x);
|
|
117
121
|
}
|
|
118
|
-
|
|
119
|
-
if( this._type.includes("right") ) {
|
|
122
|
+
else if( this._type.includes("right") ) {
|
|
120
123
|
nr.width = (pt.x-rc.left);
|
|
121
|
-
|
|
124
|
+
}
|
|
122
125
|
|
|
123
126
|
this._ref.setStyle( nr );
|
|
124
127
|
//this._ref.setStyleValue( "flexGrow", 0 );
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.x4tabs {
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-rows: auto 1fr;
|
|
11
|
+
|
|
12
|
+
|
|
9
13
|
.x4ctablist {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: row;
|
|
16
|
+
|
|
10
17
|
gap: 4px;
|
|
11
18
|
padding: 5px 5px 0 5px;
|
|
12
19
|
|
|
@@ -34,9 +41,23 @@
|
|
|
34
41
|
//color: var( --color-60 );
|
|
35
42
|
//}
|
|
36
43
|
}
|
|
44
|
+
}
|
|
37
45
|
|
|
46
|
+
&.vertical {
|
|
47
|
+
display: grid;
|
|
48
|
+
grid-template-rows: unset;
|
|
49
|
+
grid-template-columns: auto 1fr;
|
|
50
|
+
|
|
51
|
+
.x4ctablist {
|
|
52
|
+
align-items: start;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
border-top: 1px solid var(--border);
|
|
55
|
+
border-bottom: 1px solid var(--border);
|
|
56
|
+
border-left: 1px solid var(--border);
|
|
57
|
+
}
|
|
38
58
|
}
|
|
39
59
|
|
|
60
|
+
|
|
40
61
|
&> .body {
|
|
41
62
|
padding: 8px;
|
|
42
63
|
border: 1px solid var( --border );
|
|
@@ -17,7 +17,7 @@ import { Component, ComponentEvents, ComponentProps, EvClick } from '../../core/
|
|
|
17
17
|
import { CoreEvent } from '../../core/core_events';
|
|
18
18
|
|
|
19
19
|
import { Button, ButtonProps } from '../button/button';
|
|
20
|
-
import { HBox, VBox, StackBox } from '../boxes/boxes';
|
|
20
|
+
import { HBox, VBox, StackBox, Box } from '../boxes/boxes';
|
|
21
21
|
|
|
22
22
|
import "./tabs.module.scss"
|
|
23
23
|
import { class_ns } from '../../core/core_tools';
|
|
@@ -26,12 +26,13 @@ import { class_ns } from '../../core/core_tools';
|
|
|
26
26
|
*
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
type callback = ( ) => Component;
|
|
29
30
|
|
|
30
31
|
export interface TabItem {
|
|
31
32
|
name: string;
|
|
32
33
|
title: string;
|
|
33
34
|
icon?: string;
|
|
34
|
-
content: Component;
|
|
35
|
+
content: Component | callback;
|
|
35
36
|
cls?: string; // button class
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -64,6 +65,7 @@ interface TablistClickEvent extends CoreEvent {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
interface TablistProps extends ComponentProps {
|
|
68
|
+
vertical?: boolean;
|
|
67
69
|
click: ( ev: TablistClickEvent ) => void;
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -133,7 +135,8 @@ class CTabList extends HBox<TablistProps,TablistEvents> {
|
|
|
133
135
|
|
|
134
136
|
interface TabsProps extends Omit<ComponentProps,"content"> {
|
|
135
137
|
default: string;
|
|
136
|
-
items: TabItem[]
|
|
138
|
+
items: TabItem[];
|
|
139
|
+
vertical?: boolean;
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
/**
|
|
@@ -141,7 +144,7 @@ interface TabsProps extends Omit<ComponentProps,"content"> {
|
|
|
141
144
|
*/
|
|
142
145
|
|
|
143
146
|
@class_ns( "x4" )
|
|
144
|
-
export class Tabs extends
|
|
147
|
+
export class Tabs extends Box<TabsProps> {
|
|
145
148
|
|
|
146
149
|
private _list: CTabList;
|
|
147
150
|
private _stack: StackBox;
|
|
@@ -150,6 +153,8 @@ export class Tabs extends VBox<TabsProps> {
|
|
|
150
153
|
constructor( props: TabsProps ) {
|
|
151
154
|
super( props );
|
|
152
155
|
|
|
156
|
+
this.setClass( "vertical", props.vertical );
|
|
157
|
+
|
|
153
158
|
const pages = props.items?.map( x => {
|
|
154
159
|
return {
|
|
155
160
|
name: x.name,
|
|
@@ -160,7 +165,7 @@ export class Tabs extends VBox<TabsProps> {
|
|
|
160
165
|
this.setContent( [
|
|
161
166
|
this._list = new CTabList( {
|
|
162
167
|
click: ( ev ) => this._onclick( ev ) },
|
|
163
|
-
props.items
|
|
168
|
+
props.items
|
|
164
169
|
),
|
|
165
170
|
this._stack = new StackBox( {
|
|
166
171
|
cls: "body x4flex",
|