x4js 2.3.28 → 2.3.30
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 +1 -1
- package/aicontext.md +385 -21
- package/package.json +8 -3
- package/src/components/assets/icons.ts +2 -0
- package/src/components/bargraph/bargraph.module.scss +44 -0
- package/src/components/bargraph/bargraph.ts +362 -0
- package/src/components/base.scss +71 -1
- package/src/components/calendar/calendar.module.scss +6 -5
- package/src/components/calendar/calendar.ts +14 -8
- package/src/components/canvas/canvas.ts +5 -4
- package/src/components/carousel/carousel.module.scss +165 -0
- package/src/components/carousel/carousel.ts +423 -0
- package/src/components/chart/chart.module.scss +8 -0
- package/src/components/chart/chart.ts +170 -12
- package/src/components/combobox/combobox.module.scss +2 -1
- package/src/components/components.ts +3 -0
- package/src/components/dialog/dialog.module.scss +2 -0
- package/src/components/dialog/dialog.ts +1 -0
- package/src/components/gantt/gantt.module.scss +462 -0
- package/src/components/gantt/gantt.ts +1254 -0
- package/src/components/knob/knob.module.scss +113 -0
- package/src/components/knob/knob.ts +355 -0
- package/src/components/mapview/mapview.module.scss +177 -0
- package/src/components/mapview/mapview.ts +764 -0
- package/src/components/menu/menu.module.scss +4 -6
- package/src/components/menu/menu.ts +4 -2
- package/src/components/planner/planner.module.scss +688 -0
- package/src/components/planner/planner.ts +1792 -0
- package/src/components/popup/popup.ts +29 -3
- package/src/components/radio/radio.module.scss +4 -1
- package/src/components/shared.scss +2 -1
- package/src/components/slider/slider.module.scss +22 -20
- package/src/components/switch/switch.module.scss +68 -44
- package/src/components/switch/switch.ts +6 -3
- package/src/components/tag/tag.module.scss +4 -4
- package/src/components/textedit/textedit.module.scss +5 -2
- package/src/components/themes.scss +27 -6
- package/src/components/tooltips/tooltips.scss +8 -0
- package/src/components/tooltips/tooltips.ts +31 -0
- package/src/core/core_i18n.ts +65 -0
- package/src/core/core_tools.ts +44 -0
- package/src/x4doc.ts +3 -0
- package/src/components/menu/caret-right-solid.svg +0 -1
|
@@ -62,6 +62,32 @@ function dismissLast( e: UIEvent ) {
|
|
|
62
62
|
autoclose_list[autoclose_list.length-1].dismiss( );
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* a wheel outside every popup is ignored: the page under them does not scroll, it would leave
|
|
67
|
+
* them where they were. In a popup (a long menu), it scrolls as usual
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
function ignoreWheel( e: WheelEvent ) {
|
|
71
|
+
if( !autoclose_list.some( x => x.contains( e.target as Node ) ) ) {
|
|
72
|
+
e.preventDefault( );
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* the listeners of the document while a popup that closes by itself is shown
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
function watchOutside( on: boolean ) {
|
|
81
|
+
if( on ) {
|
|
82
|
+
document.addEventListener( "pointerdown", dismissLast, true );
|
|
83
|
+
document.addEventListener( "wheel", ignoreWheel, { capture: true, passive: false } );
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
document.removeEventListener( "pointerdown", dismissLast, true );
|
|
87
|
+
document.removeEventListener( "wheel", ignoreWheel, true );
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
65
91
|
/**
|
|
66
92
|
* @cssvar
|
|
67
93
|
* ```
|
|
@@ -256,7 +282,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
256
282
|
if( idx>=0 ) {
|
|
257
283
|
autoclose_list.splice( idx, 1 );
|
|
258
284
|
if( autoclose_list.length==0 ) {
|
|
259
|
-
|
|
285
|
+
watchOutside( false );
|
|
260
286
|
}
|
|
261
287
|
}
|
|
262
288
|
}
|
|
@@ -295,7 +321,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
295
321
|
|
|
296
322
|
if( this.props.autoClose ) {
|
|
297
323
|
if( autoclose_list.length==0 ) {
|
|
298
|
-
|
|
324
|
+
watchOutside( true );
|
|
299
325
|
}
|
|
300
326
|
|
|
301
327
|
autoclose_list.push( this );
|
|
@@ -384,7 +410,7 @@ export class Popup<P extends PopupProps = PopupProps, E extends PopupEvents = Po
|
|
|
384
410
|
const list = inc_group.reverse( );
|
|
385
411
|
autoclose_list = excl_group;
|
|
386
412
|
if( autoclose_list.length==0 ) {
|
|
387
|
-
|
|
413
|
+
watchOutside( false );
|
|
388
414
|
}
|
|
389
415
|
|
|
390
416
|
list.forEach( x => x.close() );
|
|
@@ -53,11 +53,14 @@
|
|
|
53
53
|
flex-direction: row;
|
|
54
54
|
align-items: center;
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
// the room of a checkbox
|
|
57
|
+
margin: 5px;
|
|
58
|
+
padding: 4px;
|
|
57
59
|
gap: 4px;
|
|
58
60
|
cursor: pointer;
|
|
59
61
|
|
|
60
62
|
.inner {
|
|
63
|
+
align-self: center; // a Box stretches: the round in the middle of the line
|
|
61
64
|
position: relative;
|
|
62
65
|
height: 1rem;
|
|
63
66
|
width: 1rem;
|
|
@@ -62,8 +62,9 @@
|
|
|
62
62
|
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// its colour from the theme (--shadow-color): darker on a dark background
|
|
65
66
|
%shadow-xl {
|
|
66
|
-
box-shadow: 0 20px 25px -5px
|
|
67
|
+
box-shadow: 0 20px 25px -5px var( --shadow-color ), 0 8px 10px -6px var( --shadow-color );
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
%shadow-xxl {
|
|
@@ -21,15 +21,17 @@
|
|
|
21
21
|
--slider-thumb-border-focus: var( --border-focus );
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// all in rem: the thumb, its focus, the track and the box keep their proportions whatever the
|
|
25
|
+
// size of <html>
|
|
24
26
|
.x4slider {
|
|
25
27
|
outline: none;
|
|
26
28
|
touch-action: none;
|
|
27
29
|
overflow: hidden;
|
|
28
30
|
|
|
29
31
|
&:not(.vertical) {
|
|
30
|
-
padding:
|
|
31
|
-
margin:
|
|
32
|
-
height:
|
|
32
|
+
padding: 0.625rem 0.75rem;
|
|
33
|
+
margin: 0.3125rem 0;
|
|
34
|
+
height: 1.75rem;
|
|
33
35
|
|
|
34
36
|
.track {
|
|
35
37
|
background-color: var( --slider-track );
|
|
@@ -37,13 +39,13 @@
|
|
|
37
39
|
|
|
38
40
|
position: relative;
|
|
39
41
|
top: 50%;
|
|
40
|
-
height:
|
|
42
|
+
height: 0.1875rem;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
.bar {
|
|
44
46
|
position: absolute;
|
|
45
47
|
width: 61%;
|
|
46
|
-
height:
|
|
48
|
+
height: 0.1875rem;
|
|
47
49
|
//padding: 4px 0;
|
|
48
50
|
//background-color: var( --color-60 );
|
|
49
51
|
}
|
|
@@ -54,12 +56,12 @@
|
|
|
54
56
|
outline: none;
|
|
55
57
|
|
|
56
58
|
background-color: var( --slider-thumb-background );
|
|
57
|
-
border:
|
|
58
|
-
border-radius:
|
|
59
|
+
border: 0.1875rem solid var( --slider-thumb-border );
|
|
60
|
+
border-radius: 50%;
|
|
59
61
|
|
|
60
62
|
top: 50%;
|
|
61
|
-
width:
|
|
62
|
-
height:
|
|
63
|
+
width: 1rem;
|
|
64
|
+
height: 1rem;
|
|
63
65
|
|
|
64
66
|
transform: translate(-50%,-50%);
|
|
65
67
|
cursor: pointer;
|
|
@@ -67,9 +69,9 @@
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
&.vertical {
|
|
70
|
-
padding:
|
|
71
|
-
margin: 0
|
|
72
|
-
width:
|
|
72
|
+
padding: 0.75rem 0.625rem;
|
|
73
|
+
margin: 0 0.3125rem;
|
|
74
|
+
width: 1.75rem;
|
|
73
75
|
|
|
74
76
|
.track {
|
|
75
77
|
background-color: var( --slider-track );
|
|
@@ -77,12 +79,12 @@
|
|
|
77
79
|
|
|
78
80
|
position: relative;
|
|
79
81
|
left: 50%;
|
|
80
|
-
width:
|
|
82
|
+
width: 0.1875rem;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
.bar {
|
|
84
86
|
position: absolute;
|
|
85
|
-
width:
|
|
87
|
+
width: 0.1875rem;
|
|
86
88
|
height: 61%;
|
|
87
89
|
//padding: 4px 0;
|
|
88
90
|
//background-color: var( --color-60 );
|
|
@@ -94,12 +96,12 @@
|
|
|
94
96
|
outline: none;
|
|
95
97
|
|
|
96
98
|
background-color: var( --slider-thumb-background );
|
|
97
|
-
border:
|
|
98
|
-
border-radius:
|
|
99
|
+
border: 0.1875rem solid var( --slider-thumb-border );
|
|
100
|
+
border-radius: 50%;
|
|
99
101
|
|
|
100
102
|
top: 61%;
|
|
101
|
-
width:
|
|
102
|
-
height:
|
|
103
|
+
width: 1rem;
|
|
104
|
+
height: 1rem;
|
|
103
105
|
|
|
104
106
|
transform: translate(-50%,-50%);
|
|
105
107
|
cursor: pointer;
|
|
@@ -110,9 +112,9 @@
|
|
|
110
112
|
|
|
111
113
|
|
|
112
114
|
&:focus .thumb {
|
|
113
|
-
outline-offset:
|
|
115
|
+
outline-offset: 0.1875rem;
|
|
114
116
|
outline-color: var(--slider-thumb-border-focus);
|
|
115
117
|
outline-style: solid;
|
|
116
|
-
outline-width:
|
|
118
|
+
outline-width: 0.0625rem;
|
|
117
119
|
}
|
|
118
120
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
2
|
* ___ ___ __
|
|
3
3
|
* \ \/ / / _
|
|
4
4
|
* \ / /_| |_
|
|
5
|
-
* / \____ _|
|
|
5
|
+
* / \____ _|
|
|
6
6
|
* /__/\__\ |_|
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* @file switch.module.scss
|
|
9
|
-
* @author Etienne Cochard
|
|
10
|
-
*
|
|
9
|
+
* @author Etienne Cochard
|
|
10
|
+
*
|
|
11
11
|
* @copyright (c) 2026 R-libre ingenierie
|
|
12
12
|
*
|
|
13
|
-
* Use of this source code is governed by an MIT-style license
|
|
13
|
+
* Use of this source code is governed by an MIT-style license
|
|
14
14
|
* that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
15
15
|
**/
|
|
16
16
|
|
|
@@ -21,15 +21,21 @@
|
|
|
21
21
|
--switch-background: var( --background-hover );
|
|
22
22
|
--switch-background-disabled: var( --disabled-background );
|
|
23
23
|
--switch-checked: var( --accent-background );
|
|
24
|
+
--switch-danger: var( --alert-background );
|
|
24
25
|
--switch-thumb: var( --background-primary );
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
// The sizes come from H, the height of the track: 1.125rem rounded to an even number of pixels
|
|
29
|
+
// (18px when <html> has 16px). The width is 2H - 2, the thumb H - 2 at 1px of the edges (inside
|
|
30
|
+
// the border): all in whole pixels, the switch is drawn the same wherever it falls in the page.
|
|
31
|
+
// The px values first: a browser without round() keeps them.
|
|
32
|
+
|
|
27
33
|
.x4switch {
|
|
28
34
|
display: flex;
|
|
29
35
|
flex-direction: row;
|
|
30
36
|
align-items: center;
|
|
31
37
|
position: relative;
|
|
32
|
-
|
|
38
|
+
|
|
33
39
|
gap: 4px;
|
|
34
40
|
margin-left: 5px;
|
|
35
41
|
padding: 4px;
|
|
@@ -47,62 +53,79 @@
|
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
// the track; the input over it takes the click, the focus, and the value for a Form
|
|
50
57
|
.switch {
|
|
51
|
-
width: 2.2rem;
|
|
52
|
-
height: 18px;
|
|
53
58
|
position: relative;
|
|
59
|
+
flex: none;
|
|
60
|
+
|
|
61
|
+
width: 34px;
|
|
62
|
+
width: calc( round( 1.125rem, 2px ) * 2 - 2px );
|
|
63
|
+
height: 18px;
|
|
64
|
+
height: round( 1.125rem, 2px );
|
|
65
|
+
|
|
66
|
+
border: 1px solid var( --switch-border );
|
|
67
|
+
border-radius: 9px;
|
|
68
|
+
border-radius: calc( round( 1.125rem, 2px ) / 2 );
|
|
69
|
+
background-color: var( --switch-background );
|
|
70
|
+
|
|
71
|
+
transition: background-color ease 0.2s, border-color ease 0.2s;
|
|
54
72
|
|
|
55
73
|
input {
|
|
56
74
|
position: absolute;
|
|
57
|
-
width: 100%;
|
|
58
|
-
height: 100%;
|
|
59
|
-
appearance: none;
|
|
60
|
-
padding: 0;
|
|
61
|
-
margin: 0;
|
|
62
|
-
left: 0;
|
|
63
|
-
top: 0;
|
|
64
|
-
cursor: pointer;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.track {
|
|
68
|
-
position: absolute;
|
|
69
|
-
pointer-events: none;
|
|
70
75
|
left: 0;
|
|
71
76
|
top: 0;
|
|
72
77
|
width: 100%;
|
|
73
78
|
height: 100%;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
transition: background-color ease 0.2s;
|
|
79
|
+
margin: 0;
|
|
80
|
+
padding: 0;
|
|
81
|
+
appearance: none;
|
|
82
|
+
opacity: 0; // none of the look of a field (its background): the track is under it
|
|
83
|
+
cursor: pointer;
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
.thumb {
|
|
83
87
|
position: absolute;
|
|
84
88
|
pointer-events: none;
|
|
85
|
-
left: 0
|
|
86
|
-
top:
|
|
89
|
+
left: 0;
|
|
90
|
+
top: 0;
|
|
87
91
|
|
|
88
|
-
width:
|
|
89
|
-
|
|
92
|
+
width: 16px;
|
|
93
|
+
width: calc( round( 1.125rem, 2px ) - 2px );
|
|
94
|
+
height: 16px;
|
|
95
|
+
height: calc( round( 1.125rem, 2px ) - 2px );
|
|
90
96
|
|
|
91
|
-
border-radius:
|
|
97
|
+
border-radius: 50%;
|
|
92
98
|
background-color: var( --switch-thumb );
|
|
93
99
|
box-shadow: 0 0 2px rgba(0,0,0,0.5);
|
|
94
100
|
|
|
95
|
-
transition:
|
|
101
|
+
transition: transform ease 0.2s;
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
// on: the colour on all the track, its border too; the thumb at the other end (H - 2 further)
|
|
106
|
+
&:has(input:checked) .switch {
|
|
107
|
+
background-color: var( --switch-checked );
|
|
108
|
+
border-color: var( --switch-checked );
|
|
109
|
+
|
|
110
|
+
.thumb {
|
|
111
|
+
transform: translateX( 16px );
|
|
112
|
+
transform: translateX( calc( round( 1.125rem, 2px ) - 2px ) );
|
|
102
113
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// danger: the colour of an alert when on
|
|
117
|
+
&.danger {
|
|
118
|
+
--switch-checked: var( --switch-danger );
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// square: the corners of the track and of the thumb barely rounded
|
|
122
|
+
&.square .switch {
|
|
123
|
+
border-radius: 3px;
|
|
124
|
+
border-radius: round( 0.1875rem, 1px );
|
|
125
|
+
|
|
126
|
+
.thumb {
|
|
127
|
+
border-radius: 2px;
|
|
128
|
+
border-radius: round( 0.125rem, 1px );
|
|
106
129
|
}
|
|
107
130
|
}
|
|
108
131
|
|
|
@@ -110,7 +133,7 @@
|
|
|
110
133
|
&, * {
|
|
111
134
|
cursor: not-allowed;
|
|
112
135
|
}
|
|
113
|
-
|
|
136
|
+
|
|
114
137
|
input {
|
|
115
138
|
pointer-events: none;
|
|
116
139
|
}
|
|
@@ -120,9 +143,10 @@
|
|
|
120
143
|
color: var( --checkbox-color-disabled );
|
|
121
144
|
}
|
|
122
145
|
|
|
123
|
-
.switch
|
|
124
|
-
&.x4switch:has(input:checked) .switch
|
|
146
|
+
.switch,
|
|
147
|
+
&.x4switch:has(input:checked) .switch {
|
|
125
148
|
background-color: var( --switch-background-disabled );
|
|
149
|
+
border-color: var( --switch-border );
|
|
126
150
|
}
|
|
127
151
|
}
|
|
128
|
-
}
|
|
152
|
+
}
|
|
@@ -31,13 +31,16 @@ interface SwitchProps extends ComponentProps {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* cls "square": the track and the thumb with corners barely rounded; "danger": the colour of an
|
|
35
|
+
* alert when on.
|
|
36
|
+
*
|
|
35
37
|
* @cssvar
|
|
36
38
|
* ```
|
|
37
39
|
* --switch-border
|
|
38
40
|
* --switch-background
|
|
39
41
|
* --switch-background-disabled
|
|
40
42
|
* --switch-checked
|
|
43
|
+
* --switch-danger
|
|
41
44
|
* --switch-thumb
|
|
42
45
|
* ```
|
|
43
46
|
*/
|
|
@@ -51,12 +54,12 @@ export class Switch extends HBox<SwitchProps> {
|
|
|
51
54
|
const inputId = makeUniqueComponentId( );
|
|
52
55
|
|
|
53
56
|
this.setContent( [
|
|
57
|
+
// the track, its thumb in it; the input over them (role switch: a screen reader says "switch, on")
|
|
54
58
|
new Component( {
|
|
55
59
|
cls: "switch",
|
|
56
60
|
content: [
|
|
57
61
|
// value: sent by a <form> of the browser when checked; a Form of x4 reads a boolean
|
|
58
|
-
new Input( { type: "checkbox", id: inputId, name: props.name, value: props.value, checked: props.checked } ),
|
|
59
|
-
new Component( { cls: "track" } ),
|
|
62
|
+
new Input( { type: "checkbox", id: inputId, name: props.name, value: props.value, checked: props.checked, attrs: { role: "switch" } } ),
|
|
60
63
|
new Component( { cls: "thumb" } ),
|
|
61
64
|
]
|
|
62
65
|
} ),
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
--tag-border: var( --border );
|
|
20
20
|
--tag-border-focus: var( --border-focus );
|
|
21
21
|
--tag-background: var( --accent-background );
|
|
22
|
-
--tag-color: var( --
|
|
23
|
-
--tag-icon-color: var( --tag-color );
|
|
22
|
+
--tag-color: var( --accent-color );
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
.x4tag {
|
|
@@ -37,9 +36,10 @@
|
|
|
37
36
|
display: none;
|
|
38
37
|
}
|
|
39
38
|
|
|
39
|
+
// --tag-icon-color is not set by x4: the icon has the color of the text of its tag
|
|
40
40
|
.x4icon {
|
|
41
41
|
height: 1em;
|
|
42
|
-
color: var( --tag-icon-color );
|
|
42
|
+
color: var( --tag-icon-color, var( --tag-color ) );
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
&> .x4simpletext {
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
|
|
51
51
|
&.alert {
|
|
52
52
|
--tag-color: var( --alert-color );
|
|
53
|
-
background
|
|
53
|
+
--tag-background: var( --alert-background );
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
--textedit-border-focus: var( --border-focus );
|
|
22
22
|
--textedit-required: var( --alert-background );
|
|
23
23
|
|
|
24
|
-
--textedit-btn-background: inherit
|
|
24
|
+
--textedit-btn-background: var( --background-input ); // the one of its field: inherit was the page (dark theme)
|
|
25
25
|
--textedit-btn-color: var( --text-secondary );
|
|
26
26
|
--textedit-btn-color-hover: var( --text-primary );
|
|
27
27
|
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
.x4button {
|
|
65
65
|
margin: 0;
|
|
66
66
|
padding: 0;
|
|
67
|
+
align-self: stretch; // the height of the field: no strip of the page above and under it
|
|
67
68
|
background-color: var( --textedit-btn-background );
|
|
68
69
|
color: var( --textedit-btn-color );
|
|
69
70
|
|
|
@@ -108,7 +109,9 @@
|
|
|
108
109
|
color: var( --textedit-color-disabled );
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
// the field and its gadgets lose their background together
|
|
113
|
+
#edit input,
|
|
114
|
+
#edit .x4button {
|
|
112
115
|
color: var( --textedit-color-disabled );
|
|
113
116
|
background-color: unset;
|
|
114
117
|
}
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
$color--base: #569cd6;
|
|
20
20
|
$color--interval: 8.4%;
|
|
21
21
|
|
|
22
|
+
// the blues of the dark theme, from their own base, with the intervals of the light one: its accent
|
|
23
|
+
// (a60, the base less one interval) #245883
|
|
24
|
+
$color--dark-base: #2d6fa5;
|
|
25
|
+
|
|
22
26
|
:root {
|
|
23
27
|
--color-primary-a0: #ffffff;
|
|
24
28
|
--color-primary-a5: #{color.adjust($color--base, $lightness: 35%)};
|
|
@@ -90,6 +94,9 @@ $color--interval: 8.4%;
|
|
|
90
94
|
--border-hover: color-mix(in srgb, var(--color-primary-a100) 23.9%, var(--color-primary-a0)); // #c2c2c2
|
|
91
95
|
--border-focus: var(--accent-background);
|
|
92
96
|
|
|
97
|
+
// the shadow of what floats over the page (%shadow-xl: a dialog, a list, a notification, a tooltip)
|
|
98
|
+
--shadow-color: rgb(0 0 0 / 0.1);
|
|
99
|
+
|
|
93
100
|
// the red, orange and green do not follow the scale: their text stays white
|
|
94
101
|
--alert-background: var(--color-danger-a50);
|
|
95
102
|
--alert-background-active: var(--color-danger-a60);
|
|
@@ -119,12 +126,16 @@ html.x4theme-dark {
|
|
|
119
126
|
--color-primary-a10: #2a2d2e; // list.hoverBackground
|
|
120
127
|
--color-primary-a20: #37373d; // list.inactiveSelectionBackground
|
|
121
128
|
--color-primary-a30: #3c3c3c; // input.border
|
|
122
|
-
|
|
123
|
-
--
|
|
124
|
-
|
|
125
|
-
--color-primary-
|
|
126
|
-
--color-primary-
|
|
127
|
-
--color-primary-
|
|
129
|
+
|
|
130
|
+
// the blues: from $color--dark-base (chosen), as the light theme makes them; a40, a selection,
|
|
131
|
+
// where VS Code has list.activeSelectionBackground
|
|
132
|
+
--color-primary-a40: #{color.adjust($color--dark-base, $lightness: -19.4%)}; // a selection
|
|
133
|
+
--color-primary-a50: #{$color--dark-base};
|
|
134
|
+
--color-primary-a55: #{color.adjust($color--dark-base, $lightness: -5%)}; // the accent hovered
|
|
135
|
+
--color-primary-a60: #{color.adjust($color--dark-base, $lightness: -$color--interval)}; // the accent
|
|
136
|
+
--color-primary-a70: #{color.adjust($color--dark-base, $lightness: -$color--interval * 2)}; // focused
|
|
137
|
+
--color-primary-a80: #{color.adjust($color--dark-base, $lightness: -$color--interval * 3)}; // active
|
|
138
|
+
|
|
128
139
|
--color-primary-a90: #cccccc;
|
|
129
140
|
--color-primary-a100: #cccccc; // foreground
|
|
130
141
|
|
|
@@ -155,6 +166,16 @@ html.x4theme-dark {
|
|
|
155
166
|
--color-dialog-caption: #181818; // titleBar.activeBackground
|
|
156
167
|
--color-dialog-caption-text: #cccccc; // titleBar.activeForeground
|
|
157
168
|
--color-dialog-background: #202020; // editorWidget.background
|
|
169
|
+
--color-dialog-border: #313131; // widget.border: its edge on the dark background
|
|
170
|
+
|
|
171
|
+
// a shadow seen on a dark background: darker
|
|
172
|
+
--shadow-color: rgb(0 0 0 / 0.5);
|
|
173
|
+
|
|
174
|
+
// the tiles of a MapView are light: turned dark, their colours kept
|
|
175
|
+
--mapview-tile-filter: invert( 1 ) hue-rotate( 180deg ) brightness( 0.95 ) contrast( 0.9 );
|
|
176
|
+
|
|
177
|
+
// the marks of the events out of the view of a Planner: the darkest blue (a90 is the text here)
|
|
178
|
+
--planner-edge-background: var( --accent-background-active );
|
|
158
179
|
|
|
159
180
|
color-scheme: dark; // the native parts: select, scroll bars, number spinners
|
|
160
181
|
}
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
--tooltip-color: var( --color-primary-a90 );
|
|
28
28
|
--tooltip-border: var( --color-primary-a20 );
|
|
29
29
|
--tooltip-image-background: var( --background-primary );
|
|
30
|
+
|
|
31
|
+
--tooltip-max-width: 30vw; // a long text goes on the next line; none: the width of the text
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
.x4tooltip {
|
|
@@ -41,6 +43,12 @@
|
|
|
41
43
|
border: 1px solid var( --tooltip-border );
|
|
42
44
|
background-color: var( --tooltip-background );
|
|
43
45
|
width: max-content;
|
|
46
|
+
max-width: var( --tooltip-max-width );
|
|
47
|
+
|
|
48
|
+
// its content (a Box: it does not shrink) as wide as the tooltip at most: the text goes on the next line
|
|
49
|
+
> .x4hbox {
|
|
50
|
+
flex-shrink: 1;
|
|
51
|
+
}
|
|
44
52
|
|
|
45
53
|
.x4icon {
|
|
46
54
|
padding: 2px 4px;
|
|
@@ -72,6 +72,14 @@ export function initTooltips( ) {
|
|
|
72
72
|
|
|
73
73
|
}, true );
|
|
74
74
|
|
|
75
|
+
// a click: no tooltip, it would stay over what the click opens
|
|
76
|
+
document.addEventListener( "mousedown", ( ) => {
|
|
77
|
+
if( last_hit ) {
|
|
78
|
+
last_hit = null;
|
|
79
|
+
closeTT( );
|
|
80
|
+
}
|
|
81
|
+
}, true );
|
|
82
|
+
|
|
75
83
|
document.addEventListener( "mousemove", ( ev: MouseEvent ) => {
|
|
76
84
|
if( last_hit ) {
|
|
77
85
|
mouse_pos = { x:ev.pageX, y:ev.pageY }
|
|
@@ -85,6 +93,11 @@ function showTT( text: string, rc: Rect, pt: Point ) {
|
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
timer.setTimeout( "update", 300, ( ) => {
|
|
96
|
+
// its element gone in the meantime
|
|
97
|
+
if( !last_hit || isGone( last_hit ) ) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
tooltip.setText( unsafeHtml(text) );
|
|
89
102
|
|
|
90
103
|
let y = mouse_pos.y;
|
|
@@ -94,12 +107,29 @@ function showTT( text: string, rc: Rect, pt: Point ) {
|
|
|
94
107
|
|
|
95
108
|
//tooltip.displayNear( rc, "top left", "bottom left", {x:0,y:4} );
|
|
96
109
|
tooltip.displayAt( mouse_pos.x+17, y+5 );
|
|
110
|
+
|
|
111
|
+
// an element removed or hidden under the mouse has no mouseleave: it is checked every second
|
|
112
|
+
timer.setInterval( "check", 1000, ( ) => {
|
|
113
|
+
if( !last_hit || isGone( last_hit ) ) {
|
|
114
|
+
last_hit = null;
|
|
115
|
+
closeTT( );
|
|
116
|
+
}
|
|
117
|
+
} );
|
|
97
118
|
} );
|
|
98
119
|
}
|
|
99
120
|
|
|
100
121
|
function closeTT( ) {
|
|
101
122
|
tooltip.show( false );
|
|
102
123
|
timer.clearTimeout( "update" );
|
|
124
|
+
timer.clearInterval( "check" );
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* the element of the tooltip, not shown any more: removed from the page, or hidden
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
function isGone( el: HTMLElement ) {
|
|
132
|
+
return !el.isConnected || el.getClientRects( ).length==0;
|
|
103
133
|
}
|
|
104
134
|
|
|
105
135
|
/**
|
|
@@ -114,6 +144,7 @@ function closeTT( ) {
|
|
|
114
144
|
* --tooltip-color
|
|
115
145
|
* --tooltip-border
|
|
116
146
|
* --tooltip-image-background
|
|
147
|
+
* --tooltip-max-width
|
|
117
148
|
* ```
|
|
118
149
|
*/
|
|
119
150
|
|