x4js 2.3.21 → 2.3.23

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.
Files changed (58) hide show
  1. package/aicontext.md +91 -5
  2. package/package.json +1 -1
  3. package/src/components/btngroup/btngroup.module.scss +1 -1
  4. package/src/components/btngroup/btngroup.ts +6 -1
  5. package/src/components/button/button.module.scss +4 -4
  6. package/src/components/button/button.ts +20 -0
  7. package/src/components/calendar/calendar.module.scss +2 -1
  8. package/src/components/calendar/calendar.ts +2 -1
  9. package/src/components/chart/chart.module.scss +4 -4
  10. package/src/components/checkbox/checkbox.module.scss +2 -1
  11. package/src/components/checkbox/checkbox.ts +1 -0
  12. package/src/components/colorpicker/colorpicker.module.scss +0 -1
  13. package/src/components/components.ts +1 -0
  14. package/src/components/dialog/dialog.module.scss +2 -2
  15. package/src/components/dialog/dialog.ts +1 -0
  16. package/src/components/dockingview/dockingview.module.scss +9 -8
  17. package/src/components/dockingview/dockingview.ts +1 -0
  18. package/src/components/form/form.module.scss +2 -2
  19. package/src/components/form/form.ts +1 -1
  20. package/src/components/gauge/gauge.module.scss +2 -2
  21. package/src/components/gridview/gridview.module.scss +0 -1
  22. package/src/components/input/input.module.scss +2 -2
  23. package/src/components/input/input.ts +3 -0
  24. package/src/components/keyboard/keyboard.ts +25 -3
  25. package/src/components/label/label.module.scss +1 -1
  26. package/src/components/listbox/listbox.module.scss +6 -3
  27. package/src/components/listbox/listbox.ts +2 -0
  28. package/src/components/menu/menu.module.scss +1 -2
  29. package/src/components/messages/messages.module.scss +11 -11
  30. package/src/components/messages/messages.ts +7 -1
  31. package/src/components/messages/pen-field.svg +1 -1
  32. package/src/components/panel/panel.module.scss +4 -3
  33. package/src/components/panel/panel.ts +1 -0
  34. package/src/components/popup/popup.module.scss +2 -3
  35. package/src/components/popup/popup.ts +1 -0
  36. package/src/components/propgrid/progrid.module.scss +4 -4
  37. package/src/components/radio/radio.module.scss +9 -3
  38. package/src/components/radio/radio.ts +7 -1
  39. package/src/components/select/select.module.scss +17 -12
  40. package/src/components/select/select.ts +9 -0
  41. package/src/components/settingsview/settingsview.module.scss +178 -0
  42. package/src/components/settingsview/settingsview.ts +289 -0
  43. package/src/components/spreadsheet/spreadsheet.module.scss +0 -1
  44. package/src/components/switch/switch.module.scss +3 -2
  45. package/src/components/switch/switch.ts +1 -0
  46. package/src/components/tabs/tabs.module.scss +6 -3
  47. package/src/components/tabs/tabs.ts +3 -0
  48. package/src/components/tag/tag.module.scss +1 -1
  49. package/src/components/textarea/textarea.module.scss +8 -1
  50. package/src/components/textarea/textarea.ts +3 -0
  51. package/src/components/themes.scss +25 -12
  52. package/src/components/tickline/tickline.module.scss +1 -1
  53. package/src/components/tooltips/tooltips.scss +4 -3
  54. package/src/components/tooltips/tooltips.ts +1 -0
  55. package/src/components/treeview/treeview.module.scss +6 -2
  56. package/src/components/treeview/treeview.ts +1 -0
  57. package/src/core/core_colors.ts +112 -17
  58. package/src/core/core_i18n.ts +157 -0
package/aicontext.md CHANGED
@@ -41,7 +41,7 @@ CoreElement<E> named timers + event surface (no DOM)
41
41
  │ ├── CSizer → HSizer / VSizer
42
42
  │ ├── FileDialog, ScrollView, Viewport, DockingView, Flex, Space
43
43
  │ ├── HBox-based: ColorInput, Rating, Switch, Tag, Keyboard, TextEdit → AutoComplete, Breadcrumbs
44
- │ └── VBox-based: Calendar, ColorPicker, FileDrop, Panel, PropertyGrid, TextArea
44
+ │ └── VBox-based: Calendar, ColorPicker, FileDrop, Panel, PropertyGrid, TextArea, SettingsView, SettingItem
45
45
  └── Application<E> singleton, no DOM of its own
46
46
 
47
47
  EventSource<E> standalone event registry
@@ -1030,6 +1030,8 @@ interface ButtonProps extends ComponentProps {
1030
1030
  tabindex?: number | boolean
1031
1031
  autorepeat?: number | boolean // true=200ms; number=interval (first fire after 500ms)
1032
1032
  click?: EventCallback<EvClick>
1033
+ menu?: MenuElement[] | (() => MenuElement[]) // a click opens this Menu under the button, in place of the click event;
1034
+ // a function is called at each click; the button gets the class "with-menu"
1033
1035
  }
1034
1036
  class Button extends Component {
1035
1037
  click(): void // simulate a click
@@ -1153,6 +1155,78 @@ class Form extends Box {
1153
1155
 
1154
1156
  ---
1155
1157
 
1158
+ ## `SettingsView` — a page of settings, as the settings of VS Code
1159
+
1160
+ The summary of the sections on the left, the sections on the right, one after the other, each a panel with its title on a band; in a section, each `SettingItem` with its name, what it does, then its controls. A click in the summary brings its section to the top; the summary follows the scroll and marks the section at the top of the view.
1161
+
1162
+ ```ts
1163
+ interface SettingItemProps extends BoxProps {
1164
+ title: string
1165
+ description?: string // under the name
1166
+ content: Component | Component[] // its controls, on a line that wraps
1167
+ }
1168
+ class SettingItem extends VBox {
1169
+ getSearchText(): string // the title and the description: what a search looks in
1170
+ }
1171
+ // A SettingItem has no value of its own: its controls keep theirs. To read and write them together,
1172
+ // put the items in a Form (a section can hold a Form of SettingItem), give the controls a name,
1173
+ // and use getValues / setValues. The item is marked on its left while one of its controls has the focus.
1174
+
1175
+ interface SettingsSection {
1176
+ id: string
1177
+ title: string
1178
+ description?: string // under the title
1179
+ content: Component[] // SettingItem, Form of SettingItem, or any component
1180
+ }
1181
+ interface SettingsViewProps extends BoxProps {
1182
+ sections?: SettingsSection[]
1183
+ searchable?: boolean // a search field above the sections
1184
+ searchPlaceholder?: string // _tr.global.settings.search when missing
1185
+ noMatch?: string // shown when the search finds nothing; _tr.global.settings.nomatch when missing
1186
+ sectionChange?: EventCallback<EvSectionChange>
1187
+ }
1188
+ interface EvSectionChange extends ComponentEvent { readonly section: string } // the id of the section at the top
1189
+ class SettingsView<P extends SettingsViewProps = SettingsViewProps> extends VBox<P, SettingsViewEvents> {
1190
+ setSections(sections: SettingsSection[]): void // replaces the sections
1191
+ showSection(id: string, smooth = true): void // brings a section to the top
1192
+ getSection(): string // the id of the section at the top
1193
+ }
1194
+ // Search: the words typed are looked for without case nor accents; an item is shown when its title or
1195
+ // its description holds all of them. A section whose title or description holds them is shown whole;
1196
+ // otherwise only its items that hold them, and what holds those items (a Form, a box). What holds no
1197
+ // item (a table, a text) is shown with its whole section only. Escape empties the field.
1198
+ // The section marked in the summary is the last one whose top is above the top of the view (40px of
1199
+ // margin); the first one while the view is hidden (in a tab not shown). The last section shown is at
1200
+ // least as high as the view (class "last"): a click in the summary can bring any section to the top.
1201
+ // Classes: .x4settingsview > .search > .x4input, > .body > .toc (a Listbox), > .body > .sections;
1202
+ // .section(.last) > .title, .description; .sections > .nomatch; .x4settingitem > .name, .description, .controls
1203
+ // CSS variables: --settingsview-toc-width, --settingsview-section-background,
1204
+ // --settingsview-section-title-background, --settingsview-hover-background, --settingsview-marker
1205
+ ```
1206
+
1207
+ A page that builds its sections with references to its own components (`this.refs.x = ...`) cannot give them to `super()`: `this` is not there yet. It calls `setSections` after `super()`. `SettingsView` keeps its own parts in private fields, not in `refs`: `refs` is left to the classes that derive from it.
1208
+
1209
+ ```ts
1210
+ class MySettings extends SettingsView {
1211
+ declare protected refs: { size: Input }
1212
+
1213
+ constructor(props: BoxProps) {
1214
+ super({ ...props, searchable: true })
1215
+
1216
+ this.setSections([
1217
+ { id: "editor", title: "Editor", content: [
1218
+ new Form({ content: [
1219
+ new SettingItem({ title: "Font size", description: "The size of the text, in pixels.",
1220
+ content: this.refs.size = new Input({ type: "number", name: "fontSize", value: 14 }) }),
1221
+ ] }),
1222
+ ] },
1223
+ ])
1224
+ }
1225
+ }
1226
+ ```
1227
+
1228
+ ---
1229
+
1156
1230
  ## Sizers / viewport / misc
1157
1231
 
1158
1232
  ```ts
@@ -1184,7 +1258,10 @@ class ColorPicker extends VBox { // props: color, swatches?, nullable?
1184
1258
  }
1185
1259
  class Panel extends VBox { setTitle(title: string): void } // the text of its title: its icon stays
1186
1260
  class Breadcrumbs extends HBox { setItems(elements): void }
1187
- interface KeyboardProps extends BoxProps { locale?: string } // "fr-FR" (default), "de-CH", "pl"...
1261
+ interface KeyboardProps extends BoxProps {
1262
+ locale?: string // "fr-FR" (default), "de-CH", "pl"...
1263
+ numpadOnly?: boolean // number or date field: the pad has no "abc" key back to the letters
1264
+ }
1188
1265
  class Keyboard extends HBox { // virtual keyboard, shown while an <input> has the focus
1189
1266
  setLocale(locale: string): void
1190
1267
  setZoom(perc: number): void
@@ -1192,6 +1269,7 @@ class Keyboard extends HBox { // virtual keyboard, shown while an
1192
1269
  }
1193
1270
  // languages: cs da de en es et fi fr ga hr hu it lt lv mt nl pl pt ro sk sl sv
1194
1271
  // bottom row: 123 (numeric pad), the letters of the language (éè, none in en), the signs (#+=); Abc comes back
1272
+ // a key acts on pointerdown; the keys that draw the keyboard again (shift, 123, abc, accents, signs) on the click
1195
1273
  class TickLine extends Component
1196
1274
  class Header extends HBox // resizable column header; updates target style "--{name}-width"
1197
1275
  ```
@@ -1409,7 +1487,7 @@ dragManager.registerDropTarget(column, (cmd, el, infos) => {
1409
1487
 
1410
1488
  ## i18n (`core_i18n`)
1411
1489
 
1412
- Two built-in languages (`fr` default, and `en`).
1490
+ Four built-in languages: `fr` (default), `en` (based on `fr`), `es` and `de` (based on `en`). Dates: `D/M/Y` in fr and es, `M/D/Y` in en, `D.M.Y` in de.
1413
1491
 
1414
1492
  ```ts
1415
1493
  export let _tr // current translation object (proxy)
@@ -1426,7 +1504,8 @@ isLanguage(name: string): boolean
1426
1504
  // search search_tip required_field invalid_format invalid_email invalid_number invalid_date
1427
1505
  // empty_list err_403 property value copy cut paste filedrop
1428
1506
  // diff_date_seconds/minutes/hours, date_input_formats, date_format, date_time_format,
1429
- // day_short[] day_long[] month_short[] month_long[], keyboard.{next,numeric,alpha}
1507
+ // day_short[] day_long[] month_short[] month_long[], keyboard.{next,numeric,alpha},
1508
+ // settings.{search,nomatch}
1430
1509
  ```
1431
1510
 
1432
1511
  ---
@@ -1454,8 +1533,15 @@ class Timer { setTimeout; clearTimeout; setInterval; clearInterval; clearAllTime
1454
1533
 
1455
1534
  class Color {
1456
1535
  // new Color(value) | new Color(r,g,b,a?) a: 0..1, default 1
1536
+ // value: "#rgb", "#rrggbb", "#rrggbbaa", "rgb()", "rgba()", a name ("cyan", "transparent"), "var(--name)",
1537
+ // and any other colour the browser knows (hsl(), oklch(), color-mix()), read from the pixel it paints
1457
1538
  setValue(value): this; setRgb(r,g,b,a?): this; setHsv(h,s,v,a?): this; setAlpha(a): this
1458
- getAlpha(): number; lighten(percent): this
1539
+ getAlpha(): number
1540
+ lighten(percent): this; darken(percent): this // toward white / black, 0-100, each component rounded
1541
+ mix(other: Color, amount): this // amount 0-1: 0 keeps this color, 1 gives the other one; alpha too
1542
+ luminance(): number // WCAG relative luminance, 0 (black) to 1 (white); alpha not used
1543
+ contrast(other: Color): number // WCAG ratio, 1 to 21
1544
+ textColor(light?: Color, dark?: Color): Color // a copy of the one of the two that contrasts most with this color; white and black by default
1459
1545
  isInvalid(): boolean // the last setValue could not be read (the color is red); setRgb/setHsv make it valid
1460
1546
  toHexString(): string; toNumber(): number
1461
1547
  toRgbString(withAlpha = false): string // "rgb(r,g,b)"; true: "rgba(r,g,b,0.500)" when not opaque, "rgb(...)" when opaque
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "2.3.21",
3
+ "version": "2.3.23",
4
4
  "type": "module",
5
5
  "main": "src/x4.ts",
6
6
  "module": "src/x4.ts",
@@ -15,7 +15,7 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --btngroup-background: white;
18
+ --btngroup-background: var( --background-primary );
19
19
  }
20
20
 
21
21
  .x4btngroup {
@@ -56,7 +56,12 @@ interface BtnGroupProps extends Omit<ComponentProps,"content"> {
56
56
  }
57
57
 
58
58
  /**
59
- *
59
+ *
60
+ * @cssvar
61
+ * ```
62
+ * --btngroup-background
63
+ * ```
64
+ * a packed group draws its buttons with the --ol-button-* variables of Button
60
65
  */
61
66
 
62
67
  @class_ns( "x4" )
@@ -32,15 +32,15 @@
32
32
  --button-background-disabled: var( --disabled-background );
33
33
  --button-color-disabled: var( --disabled-color );
34
34
 
35
- --button-icon-color: rgb(255 255 255 / 64%);
35
+ --button-icon-color: var( --icon-color-active );
36
36
 
37
37
  // outline
38
38
  --ol-button-background: var( --background-primary );
39
- --ol-button-background-active: #ccc;
39
+ --ol-button-background-active: var( --background-active );
40
40
  --ol-button-color-active: var( --text-primary );
41
- --ol-button-background-hover: #eee;
41
+ --ol-button-background-hover: var( --background-hover );
42
42
  --ol-button-color-hover: var( --text-primary );
43
- --ol-button-color-disabled: #ccc;
43
+ --ol-button-color-disabled: var( --disabled-color-light );
44
44
 
45
45
  --ol-button-color: var( --text-primary );
46
46
  --ol-button-border: var( --border );
@@ -71,6 +71,14 @@ export interface ButtonProps extends ComponentProps {
71
71
  */
72
72
  click?: EventCallback<EvClick>;
73
73
 
74
+ /**
75
+ * A menu that a click opens under the button, in place of the click event.
76
+ * A function is called at each click: it gives the items of that time.
77
+ * The button gets the class "with-menu".
78
+ *
79
+ * @example
80
+ * new Button( { label: "File", menu: [ { text: "Open", click: open }, "-", { text: "Quit", click: quit } ] } );
81
+ */
74
82
  menu?: MenuElement[] | (( ) => MenuElement[]);
75
83
  }
76
84
 
@@ -90,7 +98,19 @@ export interface ButtonProps extends ComponentProps {
90
98
  * --button-background-disabled
91
99
  * --button-color-disabled
92
100
  * --button-icon-color
101
+ * --ol-button-background
102
+ * --ol-button-color
103
+ * --ol-button-border
104
+ * --ol-button-icon-color
105
+ * --ol-button-background-hover
106
+ * --ol-button-color-hover
107
+ * --ol-button-background-active
108
+ * --ol-button-color-active
109
+ * --ol-button-color-disabled
110
+ * --ol-button-border-focus
111
+ * --ol-button-color-focus
93
112
  * ```
113
+ * the --ol-button-* variables are the ones of the outline buttons
94
114
  */
95
115
 
96
116
  @class_ns( "x4" )
@@ -36,6 +36,7 @@
36
36
 
37
37
  --calendar-header-color: var( --text-primary );
38
38
  --calendar-out-color: var( --disabled-color-dark );
39
+ --calendar-day-color: var( --text-primary );
39
40
  }
40
41
 
41
42
  .x4calendar {
@@ -93,7 +94,7 @@
93
94
  min-width: 28px;
94
95
  min-height: 28px;
95
96
 
96
- color: var( --gray-900 );
97
+ color: var( --calendar-day-color );
97
98
  text-align: center;
98
99
 
99
100
  .text {
@@ -54,7 +54,7 @@ interface CalendarProps extends ComponentProps {
54
54
  * ```
55
55
  * --calendar-btn-background
56
56
  * --calendar-btn-color
57
- * --calendar-btn-color
57
+ * --calendar-btn-color-hover
58
58
  * --calendar-week-color
59
59
  * --calendar-week-color-hover
60
60
  * --calendard-day-background-hover
@@ -66,6 +66,7 @@ interface CalendarProps extends ComponentProps {
66
66
  * --calendar-today-border
67
67
  * --calendar-header-color
68
68
  * --calendar-out-color
69
+ * --calendar-day-color
69
70
  * ```
70
71
  */
71
72
 
@@ -15,10 +15,10 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --chart-background: white;
19
- --chart-text: #52514e;
20
- --chart-grid: #e6e5e0;
21
- --chart-axis: #b5b4ae;
18
+ --chart-background: var( --background-primary );
19
+ --chart-text: var( --text-ternary );
20
+ --chart-grid: var( --border );
21
+ --chart-axis: var( --border-hover );
22
22
 
23
23
  // series colors, used in this order
24
24
  --chart-color-1: #2a78d6;
@@ -24,6 +24,7 @@
24
24
  --checkbox-color-disabled: var( --disabled-background );
25
25
  --checkbox-check-border: var( --border );
26
26
  --checkbox-check-border-hover: var( --border-hover );
27
+ --checkbox-check-color: var( --accent-color );
27
28
  }
28
29
 
29
30
  .x4checkbox {
@@ -41,7 +42,7 @@
41
42
  .inner {
42
43
  height: 1rem;
43
44
  width: 1rem;
44
- color: white;
45
+ color: var( --checkbox-check-color );
45
46
  position: relative;
46
47
  order: 1;
47
48
 
@@ -41,6 +41,7 @@ interface CheckboxProps extends ComponentProps {
41
41
  * --checkbox-color-disabled
42
42
  * --checkbox-check-border
43
43
  * --checkbox-check-border-hover
44
+ * --checkbox-check-color
44
45
  * ```
45
46
  */
46
47
 
@@ -74,7 +74,6 @@
74
74
  overflow: hidden;
75
75
 
76
76
  background-image: linear-gradient(to right, rgb(255, 0, 0), rgb(255, 255, 0), rgb(0, 255, 0), rgb(0, 255, 212), rgb(0, 0, 255), rgb(255, 0, 255), rgb(255, 0, 0));
77
- border: 1px solid var( --color-gray-3 );
78
77
 
79
78
  .thumb {
80
79
  @include overlay-shadow;
@@ -35,6 +35,7 @@ export * from "./propgrid/propgrid"
35
35
  export * from "./radio/radio"
36
36
  export * from "./rating/rating"
37
37
  export * from "./select/select"
38
+ export * from "./settingsview/settingsview"
38
39
  export * from "./sizers/sizer"
39
40
  export * from "./slider/slider"
40
41
  export * from "./spreadsheet/spreadsheet"
@@ -19,6 +19,7 @@
19
19
  :root {
20
20
  --color-dialog-caption: var( --color-primary-a80 );
21
21
  --color-dialog-caption-text: var( --color-primary-a0 );
22
+ --color-dialog-background: var( --background-primary );
22
23
  }
23
24
 
24
25
  .x4dialog {
@@ -26,8 +27,7 @@
26
27
  @extend %vbox;
27
28
 
28
29
  position: absolute !important;
29
- background-color: white;
30
- border: 1px solid var( --border-dark );
30
+ background-color: var( --color-dialog-background );
31
31
  max-width: 99vw;
32
32
  outline: none;
33
33
 
@@ -54,6 +54,7 @@ interface DialogEvents extends PopupEvents {
54
54
  * ```
55
55
  * --color-dialog-caption
56
56
  * --color-dialog-caption-text
57
+ * --color-dialog-background
57
58
  * ```
58
59
  */
59
60
 
@@ -15,13 +15,14 @@
15
15
  **/
16
16
 
17
17
  .x4dockingview {
18
- --dock-line: var( --border, #cfdae0 ); // between two panels, under a title
19
- --dock-title-background: var( --background-secondary, #f3f7f9 );
20
- --dock-title-background-hover: color-mix( in srgb, var( --dock-accent ) 25%, transparent );
21
- --dock-title-color: var( --text-ternary, #607784 );
22
- --dock-title-color-active: var( --text-primary, #002a40 );
23
- --dock-accent: var( --accent-background, #126e9e ); // the tab in front, the sizer under the pointer, the preview
24
- --dock-float-background: var( --background-primary, white );
18
+ --dock-line: var( --border ); // between two panels, under a title
19
+ --dock-title-background: var( --background-secondary );
20
+ --dock-title-background-hover: var( --accent-background-light );
21
+ --dock-title-color: var( --text-ternary );
22
+ --dock-title-color-active: var( --text-primary );
23
+ --dock-accent: var( --accent-background ); // the tab in front, the sizer under the pointer, the border of the preview
24
+ --dock-preview-background: var( --accent-background-light ); // where the panel that is dragged will go
25
+ --dock-float-background: var( --background-primary );
25
26
  --dock-float-shadow: 0 6px 24px rgba( 0, 0, 0, 0.35 );
26
27
 
27
28
  position: relative;
@@ -279,7 +280,7 @@
279
280
  box-sizing: border-box;
280
281
  pointer-events: none;
281
282
 
282
- background: color-mix( in srgb, var( --dock-accent ) 30%, transparent );
283
+ background: var( --dock-preview-background );
283
284
  border: 1px solid var( --dock-accent );
284
285
  border-radius: 3px;
285
286
  }
@@ -179,6 +179,7 @@ interface Drag {
179
179
  * --dock-title-background-hover
180
180
  * --dock-title-color
181
181
  * --dock-title-color-active
182
+ * --dock-preview-background
182
183
  * --dock-float-background
183
184
  * --dock-float-shadow
184
185
  * ```
@@ -17,7 +17,7 @@
17
17
  @use "../shared.scss";
18
18
 
19
19
  :root {
20
- --form--background: var( --background-primary );
20
+ --form-background: transparent;
21
21
  }
22
22
 
23
23
  .x4form {
@@ -25,7 +25,7 @@
25
25
  @extend %flex;
26
26
 
27
27
  padding: 16px;
28
- background-color: var( --color-form );
28
+ background-color: var( --form-background );
29
29
 
30
30
  &.horizontal {
31
31
  flex-direction: row;
@@ -31,7 +31,7 @@ type ValidationFn = ( values: FormValues, is_valid: boolean ) => boolean;
31
31
  /**
32
32
  * @cssvar
33
33
  * ```
34
- * --form--background
34
+ * --form-background
35
35
  * ```
36
36
  */
37
37
 
@@ -16,8 +16,8 @@
16
16
 
17
17
  :root {
18
18
  --gauge-base-color: var( --color-primary-a70 );
19
- --gauge-needle-back: black;
20
- --gauge-needle-dot: rgb(58, 58, 58);
19
+ --gauge-needle-back: var( --text-primary );
20
+ --gauge-needle-dot: var( --text-ternary );
21
21
  }
22
22
 
23
23
  .x4gauge {
@@ -346,7 +346,6 @@
346
346
 
347
347
  .cell-out {
348
348
  position: absolute;
349
- background-color: var( --color-gray-0 );
350
349
  width: 100%;
351
350
  height: var( --row-height );
352
351
  }
@@ -15,8 +15,8 @@
15
15
  **/
16
16
 
17
17
  :root {
18
- --input-background: rgba(255, 255, 255, 0.6);
19
- --input-color: black;
18
+ --input-background: var( --background-input );
19
+ --input-color: var( --text-primary );
20
20
 
21
21
  --input-sel-background: var( --accent-background );
22
22
  --input-sel-color: var( --accent-color );
@@ -203,6 +203,9 @@ interface InputEvents extends ComponentEvent {
203
203
  *
204
204
  * @cssvar
205
205
  * ```
206
+ * --input-background
207
+ * --input-color
208
+ * --input-color-disabled
206
209
  * --input-sel-background
207
210
  * --input-sel-color
208
211
  * --input-placeholder
@@ -239,6 +239,14 @@ function accentLabel( layout: KbLayout, upper: boolean ): string {
239
239
  return ( upper ? upperKeys( label ) : label ).replace( " ", "" );
240
240
  }
241
241
 
242
+ /**
243
+ * the keys that draw the keyboard again: shift, 123, abc, accents, signs
244
+ */
245
+
246
+ function redrawKey( key: number ) {
247
+ return key==4 || key==5 || key==8 || key==10 || key==11;
248
+ }
249
+
242
250
 
243
251
  const RE_sel = /text|password|search|tel|url/i;
244
252
 
@@ -248,6 +256,12 @@ interface KeyboardProps extends BoxProps {
248
256
  * "de-CH", "pl"... "fr-FR" when it is not given
249
257
  */
250
258
  locale?: string;
259
+
260
+ /**
261
+ * on a number or date field, the keyboard stays on the pad: no "abc" key
262
+ * back to the letters. The other fields keep all the keys.
263
+ */
264
+ numpadOnly?: boolean;
251
265
  }
252
266
 
253
267
  /**
@@ -284,7 +298,8 @@ export class Keyboard extends HBox<KeyboardProps>
284
298
 
285
299
  this.hide( );
286
300
 
287
- // a key: each contact, a finger or the mouse, the second tap of a quick double tap too
301
+ // a key: each contact, a finger or the mouse, the second tap of a quick double tap too.
302
+ // not the keys that draw the keyboard again, they act on the click
288
303
  this.addDOMEvent( "pointerdown", (e) => {
289
304
  this.handleKeyEvent( e );
290
305
  });
@@ -352,7 +367,7 @@ export class Keyboard extends HBox<KeyboardProps>
352
367
  target = target.parentNode as HTMLElement;
353
368
  }
354
369
 
355
- if( !key ) {
370
+ if( !key || redrawKey( key ) ) {
356
371
  return;
357
372
  }
358
373
 
@@ -631,6 +646,11 @@ export class Keyboard extends HBox<KeyboardProps>
631
646
 
632
647
  if( this.mode=="number" || this.mode=="date" ) {
633
648
  lines = kb_pads[this.mode];
649
+
650
+ // no key back to the letters: its place stays empty
651
+ if( this.props.numpadOnly ) {
652
+ lines = lines.map( line => line.replace( "{8}", "{9}" ) );
653
+ }
634
654
  }
635
655
  else if( this.mode=="accents" ) {
636
656
  lines = accentLines( layout, this.upper );
@@ -765,7 +785,9 @@ export class Keyboard extends HBox<KeyboardProps>
765
785
  icon,
766
786
  autorepeat: repeat,
767
787
  click: ( e ) => {
768
- if( e.repeat ) {
788
+ // the keys that draw the keyboard again act on the click: the mousedown
789
+ // that follows a pointerdown would go to a key no longer in the page
790
+ if( e.repeat || redrawKey( key ) ) {
769
791
  this._handleKey( key )
770
792
  }
771
793
  }
@@ -19,7 +19,7 @@
19
19
  :root {
20
20
  --label-background: transparent;
21
21
  --label-color: var( --text-ternary );
22
- --label-icon-color: rgb(0 0 0 / 44%);
22
+ --label-icon-color: var( --icon-color );
23
23
  --label-color-disa: var( --disabled-color-dark );
24
24
  }
25
25
 
@@ -28,9 +28,12 @@
28
28
  --listbox-item-color-hover: var( --text-primary );;
29
29
  --listbox-item-background-hover: var( --background-secondary );
30
30
 
31
- --listbox-background: white;
31
+ --listbox-background: var( --background-primary );
32
32
  --listbox-border: var( --border );
33
33
  --listbox-border-focus: var( --accent-background-focus );
34
+
35
+ --listbox-title-background: var( --background-primary );
36
+ --listbox-title-color: var( --text-primary );
34
37
  }
35
38
 
36
39
  .x4listbox {
@@ -48,10 +51,10 @@
48
51
  }
49
52
 
50
53
  &>.title {
51
- background: white;
54
+ background: var( --listbox-title-background );
52
55
  padding: 4px;
53
56
  font-weight: bold;
54
- color: black;
57
+ color: var( --listbox-title-color );
55
58
  border-bottom: 1px solid var(--border);
56
59
  }
57
60
 
@@ -88,6 +88,8 @@ export interface ListboxProps extends Omit<ComponentProps,'content'> {
88
88
  * --listbox-background
89
89
  * --listbox-border
90
90
  * --listbox-border-focus
91
+ * --listbox-title-background
92
+ * --listbox-title-color
91
93
  * ```
92
94
  */
93
95
 
@@ -17,7 +17,7 @@
17
17
  @use "../shared.scss";
18
18
 
19
19
  :root {
20
- --menu-background: white;
20
+ --menu-background: var( --background-primary );
21
21
  --menu-border: var( --border-hover );
22
22
 
23
23
  --menuitem-color: var( --text-ternary );;
@@ -33,7 +33,6 @@
33
33
  position: absolute;
34
34
  overflow-y: auto;
35
35
 
36
- border-radius: var(--bradius);
37
36
  padding: 8px 0;
38
37
  min-width: 150px;
39
38