x4js 2.3.27 → 2.3.29
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/LICENSE +21 -0
- package/README.md +5 -0
- package/aicontext.md +412 -24
- package/package.json +8 -3
- package/src/components/autocomplete/autocomplete.ts +5 -1
- 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/boxes/boxes.ts +2 -2
- package/src/components/button/button.module.scss +4 -3
- 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/checkbox/checkbox.module.scss +67 -1
- package/src/components/checkbox/checkbox.ts +22 -6
- package/src/components/colorinput/colorinput.module.scss +1 -0
- package/src/components/combobox/combobox.module.scss +6 -2
- package/src/components/components.ts +3 -0
- package/src/components/gantt/gantt.module.scss +462 -0
- package/src/components/gantt/gantt.ts +1254 -0
- package/src/components/gridview/gridview.module.scss +6 -0
- package/src/components/input/input.module.scss +1 -1
- 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/messages/messages.module.scss +9 -4
- package/src/components/planner/planner.module.scss +688 -0
- package/src/components/planner/planner.ts +1792 -0
- package/src/components/propgrid/progrid.module.scss +13 -5
- package/src/components/radio/radio.module.scss +58 -32
- package/src/components/radio/radio.ts +12 -1
- package/src/components/sizers/sizer.ts +17 -5
- package/src/components/slider/slider.module.scss +22 -20
- package/src/components/spreadsheet/spreadsheet.module.scss +6 -0
- package/src/components/switch/switch.module.scss +68 -44
- package/src/components/switch/switch.ts +6 -3
- package/src/components/tabs/tabs.module.scss +2 -0
- package/src/components/tabs/tabs.ts +1 -0
- package/src/components/tag/tag.module.scss +4 -4
- package/src/components/textarea/textarea.module.scss +9 -0
- package/src/components/textarea/textarea.ts +1 -0
- package/src/components/textedit/textedit.module.scss +5 -2
- package/src/components/themes.scss +20 -6
- package/src/components/treeview/treeview.module.scss +6 -1
- package/src/components/treeview/treeview.ts +1 -0
- package/src/components/video/video.module.scss +5 -2
- package/src/components/video/video.ts +14 -1
- package/src/core/core_i18n.ts +65 -0
- package/src/core/core_pdf.ts +17 -0
- package/src/core/core_react.ts +12 -18
- package/src/core/core_svg.ts +9 -6
- package/src/core/core_tools.ts +44 -0
- package/src/x4doc.ts +3 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
--propertygrid-gadget-background: var( --background-primary );
|
|
10
10
|
--propertygrid-gadget-color: var( --text-primary );
|
|
11
11
|
|
|
12
|
-
--propertygrid-odd-background: var(--
|
|
12
|
+
--propertygrid-odd-background: var( --background-odd );
|
|
13
13
|
--propertygrid-even-background: transparent;
|
|
14
14
|
--propertygrid-disabled-background: rgb(170 170 170 / 14%);
|
|
15
15
|
--propertygrid-hover-background: var(--color-primary-a10);
|
|
@@ -54,8 +54,6 @@
|
|
|
54
54
|
padding: 6px 4px 4px 4px;
|
|
55
55
|
min-height: 2em;
|
|
56
56
|
background-color: var( --propertygrid-group-background );
|
|
57
|
-
margin-bottom: 8px;
|
|
58
|
-
box-shadow: 4px 3px 8px rgba(0, 0, 0, 0.4);
|
|
59
57
|
color: var( --propertygrid-group-color );
|
|
60
58
|
display: flex;
|
|
61
59
|
align-items: center;
|
|
@@ -81,9 +79,14 @@
|
|
|
81
79
|
font-weight: bold;
|
|
82
80
|
}
|
|
83
81
|
|
|
82
|
+
// the button that folds the group: as high as the title, its icon in the colour
|
|
83
|
+
// of the group when it has the focus (its background stays transparent)
|
|
84
84
|
&>.x4button {
|
|
85
|
+
--button-color-focus: var( --propertygrid-group-color );
|
|
85
86
|
background-color: transparent;
|
|
86
87
|
color: var( --propertygrid-group-color );
|
|
88
|
+
margin: 0;
|
|
89
|
+
padding: 0;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
&>.x4label {
|
|
@@ -99,14 +102,19 @@
|
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
|
|
105
|
+
// under the title, in the box of the header
|
|
106
|
+
.desc {
|
|
103
107
|
font-style: italic;
|
|
104
108
|
font-weight: normal;
|
|
105
|
-
font-size:
|
|
109
|
+
font-size: 80%;
|
|
110
|
+
padding-top: 4px;
|
|
111
|
+
padding-left: 1em;
|
|
106
112
|
color: var( --text-ternary );
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
// the space is between the last row of a group and the next group, none under the title
|
|
109
116
|
&:not(:first-child ) {
|
|
117
|
+
margin-top: 8px;
|
|
110
118
|
//border-top: 1px solid var(--color-primary-a50);
|
|
111
119
|
}
|
|
112
120
|
|
|
@@ -16,8 +16,36 @@
|
|
|
16
16
|
|
|
17
17
|
:root {
|
|
18
18
|
--radio-background: var( --background-primary );
|
|
19
|
+
--radio-check-background: var( --accent-background );
|
|
19
20
|
--radio-check-color: var( --accent-color );
|
|
20
|
-
--radio-
|
|
21
|
+
--radio-focus: var( --accent-background );
|
|
22
|
+
|
|
23
|
+
--radio-button-border: var( --border );
|
|
24
|
+
--radio-button-color: var( --text-ternary );
|
|
25
|
+
--radio-button-color-checked: var( --accent-background-active );
|
|
26
|
+
--radio-button-background-checked: var( --background-secondary );
|
|
27
|
+
--radio-button-border-checked: var( --accent-background );
|
|
28
|
+
|
|
29
|
+
--radio-danger-color: var( --alert-background );
|
|
30
|
+
--radio-danger-background: var( --alert-background-light );
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// button: the round hidden, its input still in the page (not display: none),
|
|
34
|
+
// so that Tab and the arrows reach it; the focus of the keyboard shown around the radio
|
|
35
|
+
%radio-no-round {
|
|
36
|
+
gap: 0; // no space kept for the round
|
|
37
|
+
|
|
38
|
+
.inner {
|
|
39
|
+
width: 0;
|
|
40
|
+
height: 0;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
opacity: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&:has(input:focus-visible) {
|
|
46
|
+
outline: 1px dotted var( --radio-focus );
|
|
47
|
+
outline-offset: 2px;
|
|
48
|
+
}
|
|
21
49
|
}
|
|
22
50
|
|
|
23
51
|
.x4radio {
|
|
@@ -25,11 +53,14 @@
|
|
|
25
53
|
flex-direction: row;
|
|
26
54
|
align-items: center;
|
|
27
55
|
|
|
28
|
-
|
|
56
|
+
// the room of a checkbox
|
|
57
|
+
margin: 5px;
|
|
58
|
+
padding: 4px;
|
|
29
59
|
gap: 4px;
|
|
30
60
|
cursor: pointer;
|
|
31
61
|
|
|
32
62
|
.inner {
|
|
63
|
+
align-self: center; // a Box stretches: the round in the middle of the line
|
|
33
64
|
position: relative;
|
|
34
65
|
height: 1rem;
|
|
35
66
|
width: 1rem;
|
|
@@ -69,7 +100,7 @@
|
|
|
69
100
|
height: 100%;
|
|
70
101
|
|
|
71
102
|
.fa-primary {
|
|
72
|
-
fill: var( --
|
|
103
|
+
fill: var( --radio-check-background );
|
|
73
104
|
}
|
|
74
105
|
|
|
75
106
|
.fa-secondary {
|
|
@@ -98,20 +129,20 @@
|
|
|
98
129
|
}
|
|
99
130
|
}
|
|
100
131
|
|
|
101
|
-
|
|
132
|
+
// square: its former name, kept for the code that has it (not documented)
|
|
133
|
+
.x4radio.button,
|
|
134
|
+
.x4radio.square {
|
|
102
135
|
--size: 24px;
|
|
103
136
|
|
|
104
137
|
&.outline {
|
|
105
138
|
border-radius: 22px;;
|
|
106
139
|
}
|
|
107
140
|
|
|
108
|
-
border: 1px solid
|
|
141
|
+
border: 1px solid var( --radio-button-border );
|
|
109
142
|
padding: 8px;
|
|
110
143
|
margin: 0;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
display: none;
|
|
114
|
-
}
|
|
144
|
+
|
|
145
|
+
@extend %radio-no-round;
|
|
115
146
|
|
|
116
147
|
label {
|
|
117
148
|
display: flex;
|
|
@@ -121,49 +152,44 @@
|
|
|
121
152
|
#text {
|
|
122
153
|
flex-grow: 1;
|
|
123
154
|
text-align: center;
|
|
124
|
-
color: var( --
|
|
155
|
+
color: var( --radio-button-color );
|
|
125
156
|
}
|
|
126
|
-
|
|
157
|
+
|
|
158
|
+
// fill and color: an icon is drawn in its fill, or in currentColor
|
|
127
159
|
#icon {
|
|
128
|
-
fill: var( --
|
|
160
|
+
fill: var( --radio-button-color );
|
|
161
|
+
color: var( --radio-button-color );
|
|
129
162
|
width: var( --size );
|
|
130
163
|
height: var( --size );
|
|
131
164
|
}
|
|
132
165
|
}
|
|
133
166
|
|
|
134
167
|
&:has(input:checked) {
|
|
135
|
-
background-color: var( --background-
|
|
136
|
-
border-color:
|
|
168
|
+
background-color: var( --radio-button-background-checked );
|
|
169
|
+
border-color: var( --radio-button-border-checked );
|
|
137
170
|
|
|
138
171
|
.x4label {
|
|
172
|
+
// no bold: the width of the button would change with its state
|
|
139
173
|
#text {
|
|
140
|
-
color: var( --
|
|
141
|
-
font-weight: bold;
|
|
174
|
+
color: var( --radio-button-color-checked );
|
|
142
175
|
}
|
|
143
176
|
|
|
144
177
|
#icon {
|
|
145
|
-
fill: var( --
|
|
178
|
+
fill: var( --radio-button-color-checked );
|
|
179
|
+
color: var( --radio-button-color-checked );
|
|
146
180
|
}
|
|
147
181
|
|
|
148
182
|
.fa-primary {
|
|
149
|
-
fill: var( --
|
|
183
|
+
fill: var( --radio-button-color-checked );
|
|
150
184
|
}
|
|
151
185
|
}
|
|
152
186
|
}
|
|
153
187
|
}
|
|
154
188
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
display: none;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
&:has(input:checked) {
|
|
165
|
-
background-color: var( --accent-background-active );
|
|
166
|
-
border-color: var( --radio-square-border-checked );
|
|
167
|
-
font-weight: 700;
|
|
168
|
-
}
|
|
189
|
+
// danger: checked in the red of the alerts, its round or its button
|
|
190
|
+
.x4radio.danger {
|
|
191
|
+
--radio-check-background: var( --radio-danger-color );
|
|
192
|
+
--radio-button-color-checked: var( --radio-danger-color );
|
|
193
|
+
--radio-button-background-checked: var( --radio-danger-background );
|
|
194
|
+
--radio-button-border-checked: var( --radio-danger-color );
|
|
169
195
|
}
|
|
@@ -47,12 +47,23 @@ interface RadioProps extends ComponentProps {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
+
* A radio: the ones with the same name are a group. Its look, by its class (cls): "button"
|
|
51
|
+
* (a button, "button outline" rounded), "danger" (checked in red, its round or its button).
|
|
52
|
+
* Without the round, its input is still reached by Tab.
|
|
50
53
|
*
|
|
51
54
|
* @cssvar
|
|
52
55
|
* ```
|
|
53
56
|
* --radio-background
|
|
57
|
+
* --radio-check-background
|
|
54
58
|
* --radio-check-color
|
|
55
|
-
* --radio-
|
|
59
|
+
* --radio-focus
|
|
60
|
+
* --radio-button-border
|
|
61
|
+
* --radio-button-color
|
|
62
|
+
* --radio-button-color-checked
|
|
63
|
+
* --radio-button-background-checked
|
|
64
|
+
* --radio-button-border-checked
|
|
65
|
+
* --radio-danger-color
|
|
66
|
+
* --radio-danger-background
|
|
56
67
|
* ```
|
|
57
68
|
*/
|
|
58
69
|
|
|
@@ -167,7 +167,9 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
167
167
|
if( this._type.includes("-prev") || this._type.includes("-next") ) {
|
|
168
168
|
const neighbour = this._type.includes("-prev") ? this.prevElement( ) : this.nextElement( );
|
|
169
169
|
if( neighbour ) {
|
|
170
|
-
|
|
170
|
+
// shrink 1: no larger than the space the box has left (the flex neighbour at its
|
|
171
|
+
// padding); 0 at least, a negative basis is not a value
|
|
172
|
+
this._ref.setStyleValue( "flex", `0 1 ${Math.max( 0, size )}px` );
|
|
171
173
|
}
|
|
172
174
|
else {
|
|
173
175
|
this._ref.setStyle( nr );
|
|
@@ -185,18 +187,28 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
|
|
190
|
+
/**
|
|
191
|
+
* a sizer between two children of a HBox: it resizes the one before it or the one after it
|
|
192
|
+
* (a boolean, as in older code: true after, false before)
|
|
193
|
+
*/
|
|
194
|
+
|
|
188
195
|
export class HSizer extends CSizer {
|
|
189
196
|
static classPrefix = "x4";
|
|
190
197
|
|
|
191
|
-
constructor(
|
|
192
|
-
super(
|
|
198
|
+
constructor( side: "before" | "after" | boolean = "after" ) {
|
|
199
|
+
super( side === "before" || side === false ? "hsize-prev" : "hsize-next" );
|
|
193
200
|
}
|
|
194
201
|
}
|
|
195
202
|
|
|
203
|
+
/**
|
|
204
|
+
* a sizer between two children of a VBox: it resizes the one before it (above) or the one
|
|
205
|
+
* after it (under); a boolean as for HSizer
|
|
206
|
+
*/
|
|
207
|
+
|
|
196
208
|
export class VSizer extends CSizer {
|
|
197
209
|
static classPrefix = "x4";
|
|
198
210
|
|
|
199
|
-
constructor(
|
|
200
|
-
super(
|
|
211
|
+
constructor( side: "before" | "after" | boolean = "after" ) {
|
|
212
|
+
super( side === "before" || side === false ? "vsize-prev" : "vsize-next" );
|
|
201
213
|
}
|
|
202
214
|
}
|
|
@@ -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
|
}
|
|
@@ -72,6 +72,11 @@
|
|
|
72
72
|
background-color: var( --spreadsheet-background );
|
|
73
73
|
border: 1px solid var( --spreadsheet-border );
|
|
74
74
|
color: var( --spreadsheet-cell-color );
|
|
75
|
+
|
|
76
|
+
// disabled: faded as a Box (a Spreadsheet is not one)
|
|
77
|
+
&[disabled] {
|
|
78
|
+
opacity: var( --box-disabled-opacity );
|
|
79
|
+
}
|
|
75
80
|
|
|
76
81
|
.cell {
|
|
77
82
|
padding: 4px;
|
|
@@ -179,6 +184,7 @@
|
|
|
179
184
|
}
|
|
180
185
|
|
|
181
186
|
.percent {
|
|
187
|
+
align-self: center; // a Box stretches (top of the cell): centered in the row
|
|
182
188
|
width: 100%;
|
|
183
189
|
border: 1px solid var( --border );
|
|
184
190
|
height: 8px;
|
|
@@ -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
|
} ),
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
--tab-color-hover: var( --text-primary );
|
|
7
7
|
--tab-color: var( --text-primary );
|
|
8
8
|
--tab-color-selected: var( --text-primary );
|
|
9
|
+
--tab-icon-color: var( --icon-color );
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
.x4tabs {
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
border: none;
|
|
25
26
|
border-bottom: 2px solid transparent;
|
|
26
27
|
color: var( --tab-color );
|
|
28
|
+
--ol-button-icon-color: var( --tab-icon-color );
|
|
27
29
|
margin: 0;
|
|
28
30
|
outline: none;
|
|
29
31
|
transition: border-color 0.2s ease;
|
|
@@ -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
|
}
|