x4js 2.0.28 → 2.0.31
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/.vscode/launch.json +14 -0
- package/.vscode/settings.json +2 -0
- package/ai-comments.txt +97 -0
- package/demo/assets/house-light.svg +1 -0
- package/demo/assets/radio.svg +4 -0
- package/demo/index.html +12 -0
- package/demo/main.scss +23 -0
- package/demo/main.ts +324 -0
- package/demo/package.json +26 -0
- package/demo/scss.d.ts +4 -0
- package/demo/svg.d.ts +1 -0
- package/demo/tsconfig.json +14 -0
- package/lib/types/x4js.d.ts +0 -2374
- package/package.json +23 -47
- package/src/colors.scss +246 -0
- package/src/components/boxes/boxes.module.scss +1 -1
- package/src/components/boxes/boxes.ts +139 -28
- package/src/components/button/button.ts +76 -29
- package/src/components/combobox/combobox.ts +1 -1
- package/src/components/dialog/dialog.ts +4 -0
- package/src/components/gridview/gridview.ts +104 -6
- package/src/components/icon/icon.ts +42 -14
- package/src/components/input/input.ts +146 -74
- package/src/components/keyboard/keyboard.module.scss +1 -1
- package/src/components/keyboard/keyboard.ts +31 -9
- package/src/components/label/label.module.scss +9 -0
- package/src/components/label/label.ts +10 -6
- package/src/components/link/link.module.scss +44 -0
- package/src/components/link/link.ts +7 -1
- package/src/components/listbox/listbox.module.scss +18 -4
- package/src/components/listbox/listbox.ts +32 -12
- package/src/components/menu/menu.module.scss +14 -2
- package/src/components/menu/menu.ts +1 -1
- package/src/components/messages/messages.ts +13 -5
- package/src/components/panel/panel.module.scss +7 -0
- package/src/components/popup/popup.ts +14 -10
- package/src/components/propgrid/propgrid.ts +1 -1
- package/src/components/shared.scss +4 -0
- package/src/components/spreadsheet/spreadsheet.ts +81 -34
- package/src/components/tabs/tabs.module.scss +1 -0
- package/src/components/textarea/textarea.ts +8 -2
- package/src/components/textedit/textedit.ts +7 -0
- package/src/components/themes.scss +2 -0
- package/src/components/tooltips/tooltips.ts +15 -3
- package/src/core/component.ts +358 -162
- package/src/core/core_application.ts +129 -32
- package/src/core/core_colors.ts +382 -119
- package/src/core/core_data.ts +73 -86
- package/src/core/core_dom.ts +10 -0
- package/src/core/core_dragdrop.ts +32 -7
- package/src/core/core_element.ts +111 -4
- package/src/core/core_events.ts +48 -11
- package/src/core/core_i18n.ts +2 -0
- package/src/core/core_pdf.ts +454 -0
- package/src/core/core_router.ts +64 -5
- package/src/core/core_state.ts +1 -0
- package/src/core/core_styles.ts +11 -12
- package/src/core/core_svg.ts +346 -51
- package/src/core/core_tools.ts +105 -17
- package/src/x4.d.ts +10 -0
- package/src/x4.ts +1 -0
- package/src/x4tsx.d.ts +2 -1
- package/tsconfig.json +11 -0
- package/lib/README.txt +0 -20
- package/lib/cjs/x4.css +0 -1
- package/lib/cjs/x4.js +0 -2
- package/lib/esm/x4.css +0 -1
- package/lib/esm/x4.mjs +0 -2
- package/lib/styles/x4.css +0 -1
|
@@ -56,6 +56,8 @@ export interface ListboxEvents extends ComponentEvents {
|
|
|
56
56
|
export interface ListboxProps extends Omit<ComponentProps,'content'> {
|
|
57
57
|
items?: ListItem[];
|
|
58
58
|
renderer?: ( item: ListItem ) => Component;
|
|
59
|
+
title?: string;
|
|
60
|
+
icon?: string;
|
|
59
61
|
header?: Header;
|
|
60
62
|
footer?: Component,
|
|
61
63
|
checkable?: true,
|
|
@@ -104,6 +106,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
this.setContent( [
|
|
109
|
+
(props.title || props.icon) ? new Label( { cls: 'title', text: props.title, icon: props.icon }) : null,
|
|
107
110
|
props.header ? props.header : null,
|
|
108
111
|
scroller,
|
|
109
112
|
props.footer,
|
|
@@ -117,7 +120,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
117
120
|
} );
|
|
118
121
|
|
|
119
122
|
if( props.items ) {
|
|
120
|
-
this.setItems( props.items );
|
|
123
|
+
this.setItems( props.items, false );
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
|
|
@@ -191,8 +194,15 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
191
194
|
}
|
|
192
195
|
else {
|
|
193
196
|
const selitem = this._itemWithID( this._lastsel );
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
|
|
198
|
+
let nel;
|
|
199
|
+
if( selitem ) {
|
|
200
|
+
nel = sens==kbNav.next ? selitem.nextElement() : selitem.prevElement();
|
|
201
|
+
nel = next_visible( nel, sens==kbNav.next );
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
nel = sens==kbNav.next ? this._view.firstChild() : this._view.lastChild( );
|
|
205
|
+
}
|
|
196
206
|
|
|
197
207
|
if( nel ) {
|
|
198
208
|
const id = nel.getInternalData( "id" );
|
|
@@ -406,10 +416,12 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
406
416
|
this._multisel.clear( );
|
|
407
417
|
}
|
|
408
418
|
|
|
409
|
-
clearSelection( ) {
|
|
419
|
+
clearSelection( fireEvent = true ) {
|
|
410
420
|
if( this._multisel.size ) {
|
|
411
421
|
this._clearSelection( );
|
|
412
|
-
|
|
422
|
+
if( fireEvent ) {
|
|
423
|
+
this.fire( "selectionChange", { selection: [], empty: true } );
|
|
424
|
+
}
|
|
413
425
|
}
|
|
414
426
|
}
|
|
415
427
|
|
|
@@ -425,24 +437,21 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
425
437
|
this._view.clearContent( );
|
|
426
438
|
this._items = items ?? [];
|
|
427
439
|
|
|
428
|
-
let
|
|
440
|
+
let update_sel = false;
|
|
429
441
|
|
|
430
442
|
if( this._items.length ) {
|
|
431
443
|
const content = items.map( x => this.renderItem(x) );
|
|
432
444
|
this._view.setContent( content );
|
|
433
445
|
|
|
434
|
-
if( keepSel ) {
|
|
446
|
+
if( keepSel && oldSel.length>0 ) {
|
|
435
447
|
this.select( oldSel );
|
|
436
448
|
}
|
|
437
|
-
else {
|
|
438
|
-
upsel = true;
|
|
439
|
-
}
|
|
440
449
|
}
|
|
441
450
|
else {
|
|
442
|
-
|
|
451
|
+
update_sel = oldSel.length>0;
|
|
443
452
|
}
|
|
444
453
|
|
|
445
|
-
if(
|
|
454
|
+
if( update_sel ) {
|
|
446
455
|
this.setTimeout( "sel", 100, ( ) => {
|
|
447
456
|
this.fire( "selectionChange", { selection: [], empty: true } );
|
|
448
457
|
} );
|
|
@@ -573,4 +582,15 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
573
582
|
getSelection( ) {
|
|
574
583
|
return Array.from( this._multisel );
|
|
575
584
|
}
|
|
585
|
+
|
|
586
|
+
ensureSelectionVisible( ) {
|
|
587
|
+
const sels = Array.from( this._multisel.values() );
|
|
588
|
+
if( sels.length) {
|
|
589
|
+
const item = this._itemWithID( sels[0] );
|
|
590
|
+
item?.scrollIntoView( {
|
|
591
|
+
behavior: "instant",
|
|
592
|
+
block: "nearest"
|
|
593
|
+
} )
|
|
594
|
+
}
|
|
595
|
+
}
|
|
576
596
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
@use "../shared.scss";
|
|
18
18
|
|
|
19
19
|
:root {
|
|
20
|
-
--menu-background: var( --background-
|
|
20
|
+
--menu-background: var( --background-ternary );
|
|
21
21
|
--menu-border: var( --border-hover );
|
|
22
22
|
|
|
23
23
|
--menuitem-color: var( --text-ternary );;
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
.x4menu {
|
|
31
|
-
@extend .shadow-
|
|
31
|
+
@extend .shadow-xxl;
|
|
32
32
|
|
|
33
33
|
position: absolute;
|
|
34
34
|
overflow-y: auto;
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
|
|
40
40
|
background-color: var(--menu-background);
|
|
41
41
|
border: 1px solid var(--menu-border);
|
|
42
|
+
border-left: 4px solid var( --accent-background );
|
|
42
43
|
|
|
43
44
|
max-height: calc( 100vh - 32px );
|
|
44
45
|
|
|
@@ -69,6 +70,17 @@
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
&.danger #icon {
|
|
74
|
+
.fa-primary {
|
|
75
|
+
fill: var( --color-danger-a50 );
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.fa-secondary {
|
|
79
|
+
fill: var( --color-danger-a30 );
|
|
80
|
+
opacity: 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
#text {
|
|
73
85
|
@extend .flex;
|
|
74
86
|
}
|
|
@@ -98,6 +98,11 @@ export class MessageBox extends Dialog<DialogProps>
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
interface InputOptions {
|
|
102
|
+
password?: boolean;
|
|
103
|
+
trim?: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
101
106
|
@class_ns( "x4" )
|
|
102
107
|
export class InputBox extends Dialog<DialogProps>
|
|
103
108
|
{
|
|
@@ -110,7 +115,10 @@ export class InputBox extends Dialog<DialogProps>
|
|
|
110
115
|
return input.getValue( );
|
|
111
116
|
}
|
|
112
117
|
|
|
113
|
-
private static _create( msg: string | UnsafeHtml, value: string, title: string ) {
|
|
118
|
+
private static _create( msg: string | UnsafeHtml, value: string, title: string, options?: InputOptions ) {
|
|
119
|
+
|
|
120
|
+
options = {trim: true, password: false, ...options };
|
|
121
|
+
|
|
114
122
|
const box = new InputBox({
|
|
115
123
|
modal: true,
|
|
116
124
|
title,
|
|
@@ -122,7 +130,7 @@ export class InputBox extends Dialog<DialogProps>
|
|
|
122
130
|
new Icon( { iconId: pen_icon }),
|
|
123
131
|
new VBox( { flex: 1, content: [
|
|
124
132
|
new Label( { text: msg } ),
|
|
125
|
-
new Input( { value, type: "text" } )
|
|
133
|
+
new Input( { value, type: options.password ? "password" : "text", trim: options.trim } )
|
|
126
134
|
]})
|
|
127
135
|
]
|
|
128
136
|
}),
|
|
@@ -138,11 +146,11 @@ export class InputBox extends Dialog<DialogProps>
|
|
|
138
146
|
* idem with promise
|
|
139
147
|
*/
|
|
140
148
|
|
|
141
|
-
static async showAsync( msg: string | UnsafeHtml, value: string, title?: string ) : Promise<string> {
|
|
149
|
+
static async showAsync( msg: string | UnsafeHtml, value: string, title?: string, options?: InputOptions ) : Promise<string> {
|
|
142
150
|
|
|
143
|
-
return new Promise( (resolve,
|
|
151
|
+
return new Promise( (resolve, _reject ) => {
|
|
144
152
|
|
|
145
|
-
const box = this._create( msg, value, title );
|
|
153
|
+
const box = this._create( msg, value, title, options );
|
|
146
154
|
|
|
147
155
|
box.on( "btnclick", ( ev ) => {
|
|
148
156
|
asap( ( ) => {
|
|
@@ -21,6 +21,7 @@ import { Rect, Point, class_ns, asap } from '../../core/core_tools';
|
|
|
21
21
|
import { Box } from '../boxes/boxes'
|
|
22
22
|
|
|
23
23
|
import "./popup.module.scss"
|
|
24
|
+
import { getGlobalZoom, getScrollbarSize } from '../../core/core_tools.js';
|
|
24
25
|
|
|
25
26
|
export interface PopupEvents extends ComponentEvents {
|
|
26
27
|
closed: ComponentEvent;
|
|
@@ -143,24 +144,27 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
143
144
|
*/
|
|
144
145
|
|
|
145
146
|
displayAt( x: number, y: number ) {
|
|
147
|
+
const zm = getGlobalZoom( );
|
|
148
|
+
|
|
146
149
|
//TODO: check is already visible
|
|
147
150
|
this.setStyle( {
|
|
148
|
-
left: x+"px",
|
|
149
|
-
top: y+"px",
|
|
151
|
+
left: (x/zm)+"px",
|
|
152
|
+
top: (y/zm)+"px",
|
|
150
153
|
})
|
|
151
154
|
|
|
152
155
|
this._do_show( ); // to compute size
|
|
153
156
|
|
|
154
|
-
const rc = this.getBoundingRect( );
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if( rc.right>
|
|
159
|
-
this.setStyleValue( "left",
|
|
157
|
+
const rc = this.getBoundingRect( ).scale( 1/zm );
|
|
158
|
+
const sbw = getScrollbarSize( );
|
|
159
|
+
|
|
160
|
+
const screen_width = window.innerWidth - sbw;
|
|
161
|
+
if( rc.right>screen_width ) {
|
|
162
|
+
this.setStyleValue( "left", screen_width-rc.width );
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
|
|
163
|
-
|
|
165
|
+
const screen_height = window.innerHeight - sbw;
|
|
166
|
+
if( rc.bottom>screen_height ) {
|
|
167
|
+
this.setStyleValue( "top", screen_height-rc.height );
|
|
164
168
|
}
|
|
165
169
|
}
|
|
166
170
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { Component, ComponentContent, ComponentEvents, ComponentProps, EvClick, EvContextMenu, EvDblClick, EvSelectionChange, componentFromDOM } from '../../core/component';
|
|
19
19
|
import { GridColumn } from '../gridview/gridview'
|
|
20
20
|
|
|
21
|
-
import { class_ns, isNumber, isString,
|
|
21
|
+
import { class_ns, isNumber, isString, UnsafeHtml } from '../../core/core_tools';
|
|
22
22
|
import { CoreEvent, EventCallback, EventMap } from '../../core/core_events';
|
|
23
23
|
import { kbNav } from '../../core/core_tools';
|
|
24
24
|
|
|
@@ -31,15 +31,21 @@ import { SimpleText } from '../label/label';
|
|
|
31
31
|
|
|
32
32
|
import check_icon from "../checkbox/check.svg";
|
|
33
33
|
import "./spreadsheet.module.scss"
|
|
34
|
-
import { CoreElement
|
|
34
|
+
import { CoreElement } from '../../x4.js';
|
|
35
35
|
|
|
36
36
|
interface CellRef {
|
|
37
37
|
col: number;
|
|
38
38
|
row: number;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export type CellClassifier = ( row: number, col: number ) => string; // return the cell computed class
|
|
42
|
+
export type RowClassifier = (row: number ) => string; // return the row computed class
|
|
41
43
|
export type CellRenderer = (row: number, col: number, content: any) => Component;
|
|
42
44
|
|
|
45
|
+
export interface SpreadsheetColumn extends Omit<GridColumn,"classifier"> {
|
|
46
|
+
cellClassifier?: CellClassifier;
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
|
|
44
50
|
function mkid(row: number, col: number) {
|
|
45
51
|
return ((row & 0xfffff) << 12) | (col & 0xfff);
|
|
@@ -85,6 +91,7 @@ export class Store extends CoreElement<StoreEvents> {
|
|
|
85
91
|
n.set(k, v);
|
|
86
92
|
}
|
|
87
93
|
});
|
|
94
|
+
this._data = n;
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
this._maxrows = rows;
|
|
@@ -108,6 +115,10 @@ export class Store extends CoreElement<StoreEvents> {
|
|
|
108
115
|
return this._data.get(mkid(row, col));
|
|
109
116
|
}
|
|
110
117
|
|
|
118
|
+
hasData( row: number, col?: number ) {
|
|
119
|
+
return this._data.has( col===undefined ? row : mkid(row, col));
|
|
120
|
+
}
|
|
121
|
+
|
|
111
122
|
lock() {
|
|
112
123
|
this._lock++;
|
|
113
124
|
}
|
|
@@ -121,6 +132,29 @@ export class Store extends CoreElement<StoreEvents> {
|
|
|
121
132
|
}
|
|
122
133
|
}
|
|
123
134
|
|
|
135
|
+
removeRow( row_num: number ) {
|
|
136
|
+
|
|
137
|
+
if( row_num>=this._maxrows ) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const n = new Map<number, any>();
|
|
142
|
+
this._data.forEach( (v, k) => {
|
|
143
|
+
const row = k >> 12;
|
|
144
|
+
if (row != row_num) {
|
|
145
|
+
if( row>row_num ) {
|
|
146
|
+
k = mkid(row-1,k&0xfff)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
n.set(k, v);
|
|
150
|
+
}
|
|
151
|
+
} );
|
|
152
|
+
this._data = n;
|
|
153
|
+
|
|
154
|
+
this._maxrows--;
|
|
155
|
+
this._changed( );
|
|
156
|
+
}
|
|
157
|
+
|
|
124
158
|
private _changed() {
|
|
125
159
|
if (!this._lock) {
|
|
126
160
|
this.fire("changed", {});
|
|
@@ -130,6 +164,12 @@ export class Store extends CoreElement<StoreEvents> {
|
|
|
130
164
|
this._change = true;
|
|
131
165
|
}
|
|
132
166
|
}
|
|
167
|
+
|
|
168
|
+
clear( ) {
|
|
169
|
+
this._data = new Map();
|
|
170
|
+
this._maxrows = 0;
|
|
171
|
+
this._changed( );
|
|
172
|
+
}
|
|
133
173
|
}
|
|
134
174
|
|
|
135
175
|
|
|
@@ -149,7 +189,9 @@ export interface SpreadsheetEvents extends ComponentEvents {
|
|
|
149
189
|
export interface SpreadsheetProps extends ComponentProps {
|
|
150
190
|
footer?: boolean;
|
|
151
191
|
store: Store;
|
|
152
|
-
columns:
|
|
192
|
+
columns: SpreadsheetColumn[];
|
|
193
|
+
rowClassifier?: RowClassifier;
|
|
194
|
+
|
|
153
195
|
|
|
154
196
|
click?: EventCallback<EvClick>;
|
|
155
197
|
dblClick?: EventCallback<EvDblClick>;
|
|
@@ -169,7 +211,7 @@ export interface SpreadsheetProps extends ComponentProps {
|
|
|
169
211
|
@class_ns("x4")
|
|
170
212
|
export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extends SpreadsheetEvents = SpreadsheetEvents> extends Component<P, E> {
|
|
171
213
|
|
|
172
|
-
private _columns:
|
|
214
|
+
private _columns: SpreadsheetColumn[];
|
|
173
215
|
private _store: Store;
|
|
174
216
|
|
|
175
217
|
private _lock: number;
|
|
@@ -427,9 +469,17 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
427
469
|
return;
|
|
428
470
|
}
|
|
429
471
|
|
|
430
|
-
//
|
|
431
|
-
this._selection.
|
|
432
|
-
|
|
472
|
+
// try to keep selection
|
|
473
|
+
if (ev.type == 'changed' && this._selection.size ) {
|
|
474
|
+
const nsel = new Set<number>();
|
|
475
|
+
this._selection.forEach(x => {
|
|
476
|
+
if( this._store.hasData( x ) ) {
|
|
477
|
+
nsel.add( x );
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
this._selection = nsel;
|
|
482
|
+
}
|
|
433
483
|
|
|
434
484
|
this._updateFlexs();
|
|
435
485
|
this._computeFullSize();
|
|
@@ -598,10 +648,10 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
598
648
|
return header;
|
|
599
649
|
}
|
|
600
650
|
/**
|
|
601
|
-
*
|
|
651
|
+
* extra_cls est input/output
|
|
602
652
|
*/
|
|
603
653
|
|
|
604
|
-
private _renderCell(row: number, column:
|
|
654
|
+
private _renderCell(row: number, column: SpreadsheetColumn, extra_cls: string[]): ComponentContent {
|
|
605
655
|
|
|
606
656
|
const col = column.id;
|
|
607
657
|
const type = column.type;
|
|
@@ -611,14 +661,14 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
611
661
|
return null;
|
|
612
662
|
}
|
|
613
663
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
664
|
+
let cls = "";
|
|
665
|
+
if( column.cellClassifier ) {
|
|
666
|
+
extra_cls.push( column.cellClassifier( row, col ) );
|
|
667
|
+
}
|
|
618
668
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
669
|
+
if( data instanceof UnsafeHtml ) {
|
|
670
|
+
return data;
|
|
671
|
+
}
|
|
622
672
|
|
|
623
673
|
if (column.formatter) {
|
|
624
674
|
return column.formatter(data);
|
|
@@ -661,7 +711,7 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
661
711
|
|
|
662
712
|
case "percent": {
|
|
663
713
|
return new Box({
|
|
664
|
-
cls: "percent" + cls,
|
|
714
|
+
cls: "percent " + cls,
|
|
665
715
|
content: new Component({ cls: "bar", width: data + "%" })
|
|
666
716
|
});
|
|
667
717
|
}
|
|
@@ -733,8 +783,16 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
733
783
|
|
|
734
784
|
els.push(el);
|
|
735
785
|
}
|
|
786
|
+
|
|
787
|
+
let row_cls = 'row';
|
|
788
|
+
if( this.props.rowClassifier ) {
|
|
789
|
+
const xtra = this.props.rowClassifier( rowid );
|
|
790
|
+
if( xtra ) {
|
|
791
|
+
row_cls += ' ' + xtra.trim();
|
|
792
|
+
}
|
|
793
|
+
}
|
|
736
794
|
|
|
737
|
-
return new Box({ cls:
|
|
795
|
+
return new Box({ cls: row_cls, style: { top: top.toFixed(2) + "px" }, content: els });
|
|
738
796
|
}
|
|
739
797
|
|
|
740
798
|
/**
|
|
@@ -968,11 +1026,7 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
968
1026
|
this._addSelection(ref.ref,true);
|
|
969
1027
|
}
|
|
970
1028
|
|
|
971
|
-
this.
|
|
972
|
-
|
|
973
|
-
debugger;
|
|
974
|
-
//const rec = this._dataview.getByIndex( row );
|
|
975
|
-
//this.fire( "dblClick", { context: rec } );
|
|
1029
|
+
this.fire( "dblClick", { context: { row: ref.row, col: ref.col } } );
|
|
976
1030
|
}
|
|
977
1031
|
});
|
|
978
1032
|
|
|
@@ -986,9 +1040,10 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
986
1040
|
this._addSelection(ref.ref, true );
|
|
987
1041
|
}
|
|
988
1042
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1043
|
+
this.fire( "contextMenu", { uievent: e, context: { row: ref.row, col: ref.col } } );
|
|
1044
|
+
}
|
|
1045
|
+
else {
|
|
1046
|
+
this.fire( "contextMenu", { uievent: e, context: null } );
|
|
992
1047
|
}
|
|
993
1048
|
|
|
994
1049
|
e.preventDefault();
|
|
@@ -1017,14 +1072,6 @@ export class Spreadsheet<P extends SpreadsheetProps = SpreadsheetProps, E extend
|
|
|
1017
1072
|
this._computeFullSize();
|
|
1018
1073
|
}
|
|
1019
1074
|
|
|
1020
|
-
/**
|
|
1021
|
-
*
|
|
1022
|
-
*/
|
|
1023
|
-
|
|
1024
|
-
protected _on_dblclk(e: UIEvent, row: number, col: number) {
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
1075
|
/**
|
|
1029
1076
|
*
|
|
1030
1077
|
*/
|
|
@@ -32,6 +32,7 @@ interface TextAreaProps extends BaseProps {
|
|
|
32
32
|
value?: string;
|
|
33
33
|
resize?: boolean;
|
|
34
34
|
readonly?: boolean;
|
|
35
|
+
trim?: boolean;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
|
|
@@ -39,7 +40,7 @@ interface TextAreaProps extends BaseProps {
|
|
|
39
40
|
*
|
|
40
41
|
*/
|
|
41
42
|
|
|
42
|
-
class SimpleTextArea extends Component {
|
|
43
|
+
class SimpleTextArea extends Component<TextAreaProps> {
|
|
43
44
|
|
|
44
45
|
constructor( props: TextAreaProps ) {
|
|
45
46
|
super( { ...props, tag: "textarea" } );
|
|
@@ -61,7 +62,12 @@ class SimpleTextArea extends Component {
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
getText( ) {
|
|
64
|
-
|
|
65
|
+
let text = (this.dom as HTMLTextAreaElement).value;
|
|
66
|
+
if( this.props.trim!==false ) {
|
|
67
|
+
text = text.trim();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return text;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
queryInterface<T>(name: string): T {
|
|
@@ -88,7 +88,14 @@ export class TextEdit extends HBox {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const gadgets = props.inputGadgets ?? [];
|
|
91
|
+
gadgets.forEach( g => {
|
|
92
|
+
g.addClass( "gadget" );
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
|
|
91
96
|
const iprops: InputProps = { ...props, id: props.inputId, attrs: props.inputAttrs, width: props.inputWidth };
|
|
97
|
+
// no propagation...
|
|
98
|
+
delete iprops.cls;
|
|
92
99
|
|
|
93
100
|
this.setContent( [
|
|
94
101
|
props.label ? new HBox( { id: "label", width: props.labelWidth, content: [
|
|
@@ -33,6 +33,7 @@ $color--interval: 8.4%;
|
|
|
33
33
|
--color-primary-a90: #{darken($color--base, $color--interval * 4)};
|
|
34
34
|
--color-primary-a100: #000000;
|
|
35
35
|
|
|
36
|
+
--color-danger-a30: #{lighten(#c01010,30%)};
|
|
36
37
|
--color-danger-a50: #c01010;
|
|
37
38
|
--color-danger-a60: #{darken(#c01010,10%)};
|
|
38
39
|
|
|
@@ -46,6 +47,7 @@ $color--interval: 8.4%;
|
|
|
46
47
|
// Backgrounds
|
|
47
48
|
--background-primary: var(--color-primary-a0); // Fond principal
|
|
48
49
|
--background-secondary: var(--color-primary-a10); // Fond secondaire
|
|
50
|
+
--background-ternary: #f4f4f4; // Fond secondaire
|
|
49
51
|
|
|
50
52
|
// Texts
|
|
51
53
|
--text-primary: var(--color-primary-a100); // Texte principal
|
|
@@ -28,6 +28,7 @@ import icon from "./comments-question.svg"
|
|
|
28
28
|
|
|
29
29
|
let last_hit: HTMLElement = null;
|
|
30
30
|
let tooltip: Tooltip = null;
|
|
31
|
+
let mouse_pos: Point = {x:0, y:0 };
|
|
31
32
|
|
|
32
33
|
const timer = new Timer( );
|
|
33
34
|
|
|
@@ -53,15 +54,20 @@ export function initTooltips( ) {
|
|
|
53
54
|
|
|
54
55
|
}, true );
|
|
55
56
|
|
|
56
|
-
document.addEventListener( "mouseleave", ( ev:
|
|
57
|
+
document.addEventListener( "mouseleave", ( ev: MouseEvent ) => {
|
|
57
58
|
//console.log( "leave", ev.target );
|
|
58
|
-
|
|
59
59
|
if( last_hit && ev.target==last_hit ) {
|
|
60
60
|
last_hit = null;
|
|
61
61
|
closeTT( );
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
}, true );
|
|
65
|
+
|
|
66
|
+
document.addEventListener( "mousemove", ( ev: MouseEvent ) => {
|
|
67
|
+
if( last_hit ) {
|
|
68
|
+
mouse_pos = { x:ev.pageX, y:ev.pageY }
|
|
69
|
+
}
|
|
70
|
+
});
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
function showTT( text: string, rc: Rect, pt: Point ) {
|
|
@@ -71,8 +77,14 @@ function showTT( text: string, rc: Rect, pt: Point ) {
|
|
|
71
77
|
|
|
72
78
|
timer.setTimeout( null, 300, ( ) => {
|
|
73
79
|
tooltip.setText( unsafeHtml(text) );
|
|
80
|
+
|
|
81
|
+
let y = mouse_pos.y;
|
|
82
|
+
if( rc.contains(mouse_pos) ) {
|
|
83
|
+
y = rc.bottom;
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
//tooltip.displayNear( rc, "top left", "bottom left", {x:0,y:4} );
|
|
75
|
-
tooltip.displayAt(
|
|
87
|
+
tooltip.displayAt( mouse_pos.x+17, y+5 );
|
|
76
88
|
} );
|
|
77
89
|
}
|
|
78
90
|
|