x4js 2.3.25 → 2.3.27

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 (68) hide show
  1. package/aicontext.md +87 -13
  2. package/package.json +1 -1
  3. package/src/components/autocomplete/autocomplete.ts +3 -3
  4. package/src/components/boxes/boxes.module.scss +16 -2
  5. package/src/components/boxes/boxes.ts +24 -11
  6. package/src/components/breadcrumb/breadcrumb.ts +1 -2
  7. package/src/components/btngroup/btngroup.ts +2 -2
  8. package/src/components/button/button.ts +2 -2
  9. package/src/components/calendar/calendar.ts +5 -3
  10. package/src/components/canvas/canvas.ts +1 -2
  11. package/src/components/chart/chart.ts +4 -4
  12. package/src/components/checkbox/checkbox.ts +2 -2
  13. package/src/components/colorinput/colorinput.ts +3 -2
  14. package/src/components/colorpicker/colorpicker.ts +5 -5
  15. package/src/components/combobox/combobox.ts +3 -3
  16. package/src/components/components.ts +1 -0
  17. package/src/components/dialog/dialog.ts +2 -2
  18. package/src/components/dockingview/dockingview.ts +2 -3
  19. package/src/components/filedrop/filedrop.ts +3 -2
  20. package/src/components/form/form.ts +4 -3
  21. package/src/components/gauge/gauge.ts +2 -2
  22. package/src/components/gridview/gridview.module.scss +8 -5
  23. package/src/components/gridview/gridview.ts +11 -13
  24. package/src/components/header/header.ts +2 -2
  25. package/src/components/icon/icon.ts +1 -2
  26. package/src/components/image/image.ts +1 -2
  27. package/src/components/input/input.ts +3 -2
  28. package/src/components/keyboard/keyboard.ts +2 -2
  29. package/src/components/label/label.ts +3 -3
  30. package/src/components/link/link.ts +3 -2
  31. package/src/components/listbox/listbox.ts +33 -47
  32. package/src/components/menu/menu.ts +5 -4
  33. package/src/components/messages/messages.module.scss +29 -5
  34. package/src/components/messages/messages.ts +42 -50
  35. package/src/components/monaco/monaco.ts +1 -2
  36. package/src/components/notification/notification.ts +3 -2
  37. package/src/components/panel/panel.ts +2 -2
  38. package/src/components/popup/popup.ts +4 -4
  39. package/src/components/progress/progress.ts +1 -2
  40. package/src/components/propgrid/progrid.module.scss +2 -3
  41. package/src/components/propgrid/propgrid.ts +2 -2
  42. package/src/components/radio/radio.ts +1 -2
  43. package/src/components/rating/rating.ts +3 -3
  44. package/src/components/select/select.ts +2 -2
  45. package/src/components/settingsview/settingsview.module.scss +6 -5
  46. package/src/components/settingsview/settingsview.ts +3 -3
  47. package/src/components/sizers/sizer.ts +21 -29
  48. package/src/components/slider/slider.ts +2 -2
  49. package/src/components/spreadsheet/spreadsheet.ts +8 -10
  50. package/src/components/switch/switch.ts +2 -2
  51. package/src/components/tabs/tabs.ts +4 -4
  52. package/src/components/tag/tag.ts +2 -2
  53. package/src/components/textarea/textarea.ts +3 -3
  54. package/src/components/textedit/textedit.ts +2 -2
  55. package/src/components/themes.scss +2 -0
  56. package/src/components/tickline/tickline.ts +3 -3
  57. package/src/components/timeline/timeline.module.scss +147 -0
  58. package/src/components/timeline/timeline.ts +146 -0
  59. package/src/components/tooltips/tooltips.ts +2 -2
  60. package/src/components/treeview/treeview.ts +19 -25
  61. package/src/components/video/video.ts +1 -2
  62. package/src/components/viewport/viewport.ts +4 -3
  63. package/src/core/component.ts +46 -26
  64. package/src/core/core_application.ts +29 -1
  65. package/src/core/core_i18n.ts +39 -0
  66. package/src/core/core_shortcuts.ts +2 -1
  67. package/src/core/core_svg.ts +1 -0
  68. package/src/core/core_tools.ts +83 -24
package/aicontext.md CHANGED
@@ -36,7 +36,7 @@ CoreElement<E> named timers + event surface (no DOM)
36
36
  │ │ ├── BtnGroup, Tabs, Video, Saturation
37
37
  │ ├── Button, Input, Icon, Label, SimpleText, Checkbox, Radio, Link, SimpleTextArea
38
38
  │ ├── Listbox, Gridview, Treeview, Select, Combobox, Slider, Gauge
39
- │ ├── Progress, TickLine, Canvas, Image, Spreadsheet, MonacoEditor
39
+ │ ├── Progress, TickLine, Timeline, Canvas, Image, Spreadsheet, MonacoEditor
40
40
  │ ├── SvgComponent → Chart
41
41
  │ ├── CSizer → HSizer / VSizer
42
42
  │ ├── FileDialog, ScrollView, Viewport, DockingView, Flex, Space
@@ -169,6 +169,15 @@ toggleClass(cls: string): void
169
169
  setClass(cls: string, set?: boolean): this
170
170
  ```
171
171
 
172
+ A component gets one class for each class of its chain: its name in lower case, after the prefix that class
173
+ declares itself with `static classPrefix` (not the one of its parent), then `x4`. Every component of x4 declares
174
+ `static classPrefix = "x4"` (a Button: `x4button x4`); a class of the application declares its own, or none.
175
+
176
+ ```ts
177
+ class Avatar extends Image { static classPrefix = "my"; } // classes: myavatar x4image x4
178
+ class Badge extends Label { } // classes: badge x4label x4
179
+ ```
180
+
172
181
  ### HTML attributes & ARIA
173
182
 
174
183
  ```ts
@@ -218,12 +227,16 @@ queryAll(selector: string): Component[]
218
227
  firstChild<T>(): T; lastChild<T>(): T
219
228
  nextElement<T>(): T; prevElement<T>(): T
220
229
  parentElement<T>(cls?: Constructor<T>): T
230
+ closest<T>(selector: string): T // this one or an ancestor whose element matches the css selector; null if none
231
+ contains(other: Component | Node): boolean // other (a node, or the element of a component) is the element of this one or inside it
221
232
  childCount(): number
222
233
  enumChildComponents(recursive: boolean): Component[]
223
234
  enumChildNodes(recursive: boolean): Node[]
224
235
  visitChildren(cb: (el: Component) => boolean): void
225
236
  static parentElement<T>(dom: Node, cls?: Constructor<T>): T // starts at the parent of dom, not at dom:
226
237
  // test componentFromDOM(dom) first for the component of dom itself
238
+ static closest<T>(dom: Element, selector: string): T // starts at dom itself: in a click handler,
239
+ // Component.closest(ev.target as Element, '.item')
227
240
  ```
228
241
 
229
242
  ### Visibility / state / focus / geometry
@@ -291,6 +304,11 @@ static fireGlobal(msg: string, params?: any): void
291
304
  static setTheme(name: string): void // the class x4theme-<name> on <html>: "" the light theme (default, no class),
292
305
  // "dark" the dark theme of x4, another name a theme of the application
293
306
  static getTheme(): string // "" for the light theme, "dark", or the name given to setTheme
307
+ static setLocale(locale: string, currency?: string): void // forces the locale of the formats (formatNumber, formatMoney,
308
+ // formatDate, formatDateTime) over the one of the language; null: the language's
309
+ // again. currency: "EUR" by default, kept when not given
310
+ static getLocale(): string // the forced one, else _tr.global.locale ("fr-FR" for fr, "en-US" for en)
311
+ static getCurrency(): string
294
312
  focusNext(next: boolean): boolean
295
313
  addShortcut(keys: string | string[], callback: (ev: KeyboardEvent) => void, options?: ShortcutOptions): void // see Shortcuts
296
314
  setupSocketMessaging(path?: string, looseCallback?: () => void): void
@@ -313,6 +331,9 @@ class VBox<P, E> extends Box<P, E>
313
331
  interface BoxProps extends ComponentProps { tag?: string }
314
332
  ```
315
333
 
334
+ A Box is a `<div>` (another element with `tag`). Disabled (`disable()`, the prop `disabled`), its content is inert
335
+ (no click, no focus, no input) and faded by `--box-disabled-opacity` (0.5); a disabled Box in it is not faded twice.
336
+
316
337
  ### `Box.refs` — typed directory of the children to reach again later
317
338
 
318
339
  Only a `Box` has `refs`: a class derived from `Component` (not from `Box`) has none, and `this.refs.x = ...` there
@@ -597,6 +618,41 @@ class Rating extends HBox {
597
618
  }
598
619
  ```
599
620
 
621
+ ### `Timeline` — events on a line, each with its icon in a round mark
622
+
623
+ ```ts
624
+ interface TimelineItem {
625
+ icon?: string // in the round mark
626
+ title: string | UnsafeHtml // in bold
627
+ text?: string | UnsafeHtml // the sentence under it, in grey
628
+ date?: Date // written relative to now, in the locale: "il y a 2 heures", "yesterday"; none: no time shown
629
+ done?: boolean // the mark in the accent; else a grey mark
630
+ }
631
+ interface TimelineProps extends ComponentProps {
632
+ items?: TimelineItem[]
633
+ vertical?: boolean // true by default; false: the events side by side
634
+ renderer?: (item: TimelineItem) => Component // what is beside the mark (the mark and the line stay)
635
+ click?: EventCallback<EvClick> // a click anywhere in an event: ev.context is its TimelineItem
636
+ }
637
+ interface TimelineEvents extends ComponentEvents { click: EvClick }
638
+ class Timeline extends Component<TimelineProps, TimelineEvents> {
639
+ setItems(items: TimelineItem[]): void // the relative times are written here, not updated after
640
+ }
641
+ // the line to the next mark: in the accent when the next event is done, dashed after an event not done
642
+ // CSS vars: --timeline-done-color --timeline-done-icon-color --timeline-todo-color --timeline-todo-icon-color
643
+ // --timeline-title-color --timeline-text-color --timeline-time-color
644
+ ```
645
+
646
+ ```ts
647
+ new Timeline({
648
+ items: [
649
+ { icon: branch, title: 'New branch', text: 'fix-notifications, from master', date: created, done: true },
650
+ { icon: review, title: 'Code review', text: 'Waiting for a reviewer' },
651
+ ],
652
+ click: ev => this.openStep(ev.context as TimelineItem),
653
+ })
654
+ ```
655
+
600
656
  ---
601
657
 
602
658
  ## Input components
@@ -1150,8 +1206,9 @@ class PromptBox extends Dialog {
1150
1206
  class ProgressionBox extends Dialog {
1151
1207
  constructor(title: string)
1152
1208
  addText(text: string|UnsafeHtml, perc: number): void
1153
- addError(text: string|UnsafeHtml, perc: number): void // its icon, in red; the title bar in red until clear()
1154
- addWarning(text: string|UnsafeHtml, perc: number): void // its icon, in orange
1209
+ addError(text: string|UnsafeHtml, perc: number): void // red, on a light red line, a red bar on its left;
1210
+ // the title bar in red until clear()
1211
+ addWarning(text: string|UnsafeHtml, perc: number): void // the same in orange
1155
1212
  addSection(title: string|UnsafeHtml, perc: number): void // a section (<details>, open): the lines that follow go
1156
1213
  // in it; a click on its title folds it; its title has the icon
1157
1214
  // of the worst of its lines. Without any, the lines go in the log
@@ -1162,10 +1219,11 @@ class ProgressionBox extends Dialog {
1162
1219
  // from _tr.global.progression), the icon of the worst;
1163
1220
  // else it counts "OK (5s)" and closes the box at 0
1164
1221
  }
1165
- // ProgressionBox: its lines in a <pre>, 10 lines high, scrolled both ways (the box keeps its size);
1222
+ // ProgressionBox: its lines in a <pre> in a fixed font, a <div> each (class "line", plus "error" or "warning"),
1223
+ // 10 lines high, scrolled both ways (the box keeps its size), every line as wide as the longest one;
1166
1224
  // a string is text, an UnsafeHtml html. Ctrl+A in the lines selects them only (a folded section too).
1167
- // Colours: --msgbox-log-background, -border, -border-focus, -error-color, -warning-color,
1168
- // -scrollbar (the thumb of its scroll bars; their track is its background).
1225
+ // Colours: --msgbox-log-background, -border, -border-focus, -error-color, -error-background,
1226
+ // -warning-color, -warning-background, -scrollbar (the thumb of its scroll bars; their track is its background).
1169
1227
  ```
1170
1228
 
1171
1229
  ### `Notification`
@@ -1188,7 +1246,8 @@ class Notification extends Popup { display(time_in_s?: number): void } // 0: u
1188
1246
  ```ts
1189
1247
  type FormValues = Record<string, any>
1190
1248
  interface FormProps extends BoxProps { autoComplete?: boolean }
1191
- class Form extends Box {
1249
+ class Form<P extends FormProps = FormProps, E extends ComponentEvents = ComponentEvents> extends Box<P, E> {
1250
+ // a class derived from Form declares its events: class EntryForm extends Form<EntryProps, EntryEvents>
1192
1251
  setValues(values: FormValues): void
1193
1252
  getValues<T extends FormValues>(): T
1194
1253
  setAutoComplete(on?: boolean): void // attribute on the <form>: fields without their own follow it, added later too
@@ -1285,9 +1344,11 @@ class VSplitBox extends VBox // panels stacked, resizable height:
1285
1344
  // new HSplitBox( { content: [ new Treeview( { width: 250 } ), new Panel( { flex: 1 } ) ] } )
1286
1345
 
1287
1346
  // Low level: only place sizers by hand when a SplitBox does not fit (popup edges, header cells...).
1288
- class CSizer extends Component // base splitter
1347
+ class CSizer extends Component // base splitter; events start, resize { size, width, height }, stop
1289
1348
  class HSizer extends CSizer // horizontal splitter
1290
1349
  class VSizer extends CSizer // vertical splitter
1350
+ // A pointercancel (a touch taken by the browser) ends the resize as a pointerup does: stop is fired.
1351
+ // The columns of a Gridview or a Spreadsheet are 16px wide at least (the min-width of a cell).
1291
1352
  class ScrollView extends Component { getViewport(): Component }
1292
1353
  class Viewport extends Component
1293
1354
  class Canvas extends Component { getContext(): CanvasRenderingContext2D; paint(): void }
@@ -1431,6 +1492,7 @@ component.addShortcut(keys, callback, options?) // a view: while the foc
1431
1492
  Application.instance().addShortcut(keys, callback, options?) // the whole application, wherever the focus is
1432
1493
 
1433
1494
  shortcutText(keys: string): string // for a tooltip or a menu: "Ctrl+Z", "⌘Z" on a Mac
1495
+ isMac: boolean // true on a Mac, an iPhone or an iPad: Mod is Cmd there
1434
1496
 
1435
1497
  class Shortcuts { // the list itself; rarely used directly
1436
1498
  add(keys: string | string[], callback: (ev: KeyboardEvent) => void, options?: ShortcutOptions): void
@@ -1552,10 +1614,18 @@ isLanguage(name: string): boolean
1552
1614
  // search search_tip required_field invalid_format invalid_email invalid_number invalid_date
1553
1615
  // empty_list err_403 property value copy cut paste filedrop
1554
1616
  // diff_date_seconds/minutes/hours, date_input_formats, date_format, date_time_format,
1617
+ // locale ("fr-FR", "en-US", "es-ES", "de-DE": the formats of numbers, amounts, dates),
1555
1618
  // day_short[] day_long[] month_short[] month_long[], keyboard.{next,numeric,alpha},
1556
- // settings.{search,nomatch}
1619
+ // settings.{search,nomatch}, progression.{error,errors,warning,warnings}
1620
+ getCurrentLocale(): string; getCurrentCurrency(): string // as Application.getLocale / getCurrency
1557
1621
  ```
1558
1622
 
1623
+ The language gives the texts and the locale of the formats: `selectLanguage("en")` changes both. A regional
1624
+ variant is a language based on another: `createLanguage("fr-ch", "fr")`, `addTranslation("fr-ch", { global: { locale: "fr-CH" } })`.
1625
+ `Application.setLocale(locale, currency)` forces the locale over the language's. The fields of date and the
1626
+ Calendar follow the patterns of the language (`date_format`...), not the locale. A field of type number is shown
1627
+ by the browser, in its own locale, whatever this one.
1628
+
1559
1629
  ---
1560
1630
 
1561
1631
  ## Theme (`themes.scss`)
@@ -1629,7 +1699,14 @@ pascalCase(s): string; camelCase(s): string; clamp<T>(v, min, max): T
1629
1699
  measureText(str, size, bold?): number // width in Helvetica, from core_pdf (see PDF)
1630
1700
 
1631
1701
  // Dates
1632
- date_format(date, options?): string // options not read yet: formatIntlDate(date)
1702
+ date_format(date, options?): string // options: Intl.DateTimeFormat in the locale; without: formatIntlDate(date)
1703
+
1704
+ // Formats in the current locale (Application.setLocale, else the one of the language), Intl made once by locale
1705
+ formatNumber(value, decimals?, grouping = true): string // "1 234,5" in fr-FR; decimals: the most shown
1706
+ formatMoney(value): string // "1 234,50 €": the currency of Application.getCurrency()
1707
+ formatDate(date): string // "22/10/2026"
1708
+ formatDateTime(date): string // "22/10/2026 14:05"
1709
+ // Gridview and Spreadsheet format their columns number, money, date, date-time with them (a formatter comes first)
1633
1710
  date_diff(date1, date2, options?): string // "30 secondes", "5 minutes", "2 heures 5 minutes" (either order); options not read
1634
1711
  date_to_sql(date, withHours): string; date_sql_utc(date): Date
1635
1712
  date_hash(date): number; date_clone(date): Date
@@ -1648,9 +1725,6 @@ getSystemMetrics(part: "scrollbar"|"zoom"): number
1648
1725
  setWaitCursor(wait: boolean): void; beep(): void
1649
1726
  isUnitLess(name): boolean; isFeatureAvailable(name: "eyedropper"): boolean
1650
1727
 
1651
- // Class decorator
1652
- class_ns(ns: string): ClassDecorator
1653
- const x4_class_ns_sym: symbol
1654
1728
  const unitless // set of unitless CSS props
1655
1729
 
1656
1730
  // System interfaces
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "2.3.25",
3
+ "version": "2.3.27",
4
4
  "type": "module",
5
5
  "main": "src/x4.ts",
6
6
  "module": "src/x4.ts",
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { Component, ComponentEvent, ComponentEvents, EvChange } from '../../core/component';
18
18
  import { EventCallback } from '../../core/core_events';
19
- import { class_ns, kbNav } from '../../core/core_tools';
19
+ import { kbNav } from '../../core/core_tools';
20
20
 
21
21
  import { HBox } from '../boxes/boxes';
22
22
  import { DropdownList } from '../combobox/combobox';
@@ -96,8 +96,8 @@ const render_id_item = ( item: ListItem ) => {
96
96
  * })
97
97
  */
98
98
 
99
- @class_ns( "x4" )
100
99
  export class AutoComplete extends TextEdit<AutoCompleteEvents> {
100
+ static classPrefix = "x4";
101
101
 
102
102
  private _popup: DropdownList;
103
103
 
@@ -268,7 +268,7 @@ export class AutoComplete extends TextEdit<AutoCompleteEvents> {
268
268
  private _on_focusout( ev: FocusEvent ) {
269
269
  // focus is moving inside the control
270
270
  const to = ev.relatedTarget as Node;
271
- if( to && this.dom.contains( to ) ) {
271
+ if( to && this.contains( to ) ) {
272
272
  return;
273
273
  }
274
274
 
@@ -16,16 +16,30 @@
16
16
 
17
17
  @use "../shared.scss";
18
18
 
19
+ :root {
20
+ --box-disabled-opacity: 0.5; // a disabled Box: its content faded
21
+ }
22
+
19
23
  .x4box {
20
- // reset fieldset
24
+ // reset a box built with tag: "fieldset"
21
25
  margin: 0;
22
- padding: 0;
26
+ padding: 0;
23
27
  border: none;
24
28
 
25
29
  min-width: 0;
26
30
  min-height: 0;
27
31
  flex-shrink: 0;
28
32
  align-self: stretch;
33
+
34
+ // disabled: its content inert (enable) and faded
35
+ &[disabled] {
36
+ opacity: var( --box-disabled-opacity );
37
+
38
+ // a disabled Box in a disabled Box: opacity 1 for it, so faded once, not twice
39
+ .x4box[disabled] {
40
+ opacity: 1;
41
+ }
42
+ }
29
43
  }
30
44
 
31
45
  .x4hbox {
@@ -14,7 +14,7 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- import { asap, class_ns, isArray, isNumber } from '../../core/core_tools';
17
+ import { asap, isArray, isNumber } from '../../core/core_tools';
18
18
  import { Component, ComponentEvents, ComponentProps, EvSelectionChange } from "../../core/component"
19
19
  import { EventCallback } from '../../core/core_events';
20
20
  import { HSizer, VSizer } from '../sizers/sizer';
@@ -28,6 +28,14 @@ export interface BoxProps extends ComponentProps {
28
28
 
29
29
  /**
30
30
  * A generic container component for grouping and laying out child components.
31
+ *
32
+ * A <div>. Disabled (disable( ), the prop disabled), its content is inert (no click, no
33
+ * focus, no input) and faded by --box-disabled-opacity.
34
+ *
35
+ * @cssvar
36
+ * ```
37
+ * --box-disabled-opacity
38
+ * ```
31
39
  *
32
40
  * The `refs` object is a typed directory of the children you need to reach
33
41
  * again later. Assign a child to `refs` as you build the content: the
@@ -60,11 +68,12 @@ export interface BoxProps extends ComponentProps {
60
68
  *
61
69
  */
62
70
 
63
- @class_ns( "x4" )
64
71
  export class Box<P extends BoxProps=BoxProps,E extends ComponentEvents=ComponentEvents> extends Component<P,E> {
72
+ static classPrefix = "x4";
73
+
65
74
  protected refs: Record<string,Component> = {};
66
75
  constructor( props: P ) {
67
- super( { tag: "fieldset", ...props } );
76
+ super( { tag: "div", ...props } );
68
77
  }
69
78
  }
70
79
 
@@ -74,8 +83,9 @@ export class Box<P extends BoxProps=BoxProps,E extends ComponentEvents=Component
74
83
  * Arranges child components in a horizontal line.
75
84
  */
76
85
 
77
- @class_ns( "x4" )
78
86
  export class HBox<P extends BoxProps=BoxProps,E extends ComponentEvents=ComponentEvents> extends Box<P,E> {
87
+ static classPrefix = "x4";
88
+
79
89
  }
80
90
 
81
91
  /**
@@ -84,8 +94,9 @@ export class HBox<P extends BoxProps=BoxProps,E extends ComponentEvents=Componen
84
94
  * The CSS class for this component is automatically generated as `x4vbox`.
85
95
  */
86
96
 
87
- @class_ns( "x4" )
88
97
  export class VBox<P extends BoxProps=BoxProps,E extends ComponentEvents=ComponentEvents> extends Box<P,E> {
98
+ static classPrefix = "x4";
99
+
89
100
  constructor( p: P ) {
90
101
  super( p );
91
102
  }
@@ -136,8 +147,9 @@ function split_content( panels: Component[], horz: boolean ) {
136
147
  * })
137
148
  */
138
149
 
139
- @class_ns( "x4" )
140
150
  export class HSplitBox<P extends SplitBoxProps=SplitBoxProps,E extends ComponentEvents=ComponentEvents> extends HBox<P,E> {
151
+ static classPrefix = "x4";
152
+
141
153
  constructor( props: P ) {
142
154
  super( { ...props, content: split_content( props.content, true ) } );
143
155
  }
@@ -149,8 +161,9 @@ export class HSplitBox<P extends SplitBoxProps=SplitBoxProps,E extends Component
149
161
  * The CSS class for this component is automatically generated as `x4vsplitbox`.
150
162
  */
151
163
 
152
- @class_ns( "x4" )
153
164
  export class VSplitBox<P extends SplitBoxProps=SplitBoxProps,E extends ComponentEvents=ComponentEvents> extends VBox<P,E> {
165
+ static classPrefix = "x4";
166
+
154
167
  constructor( props: P ) {
155
168
  super( { ...props, content: split_content( props.content, false ) } );
156
169
  }
@@ -206,8 +219,8 @@ interface StackItemEx extends StackItem {
206
219
  * The CSS class for this component is automatically generated as `x4stackbox`.
207
220
  */
208
221
 
209
- @class_ns( "x4" )
210
222
  export class StackBox<P extends StackBoxProps = StackBoxProps, E extends StackeBoxEvents = StackeBoxEvents> extends Box<StackBoxProps,StackeBoxEvents> {
223
+ static classPrefix = "x4";
211
224
 
212
225
  protected _items: StackItemEx[];
213
226
  protected _cur: number;
@@ -371,8 +384,8 @@ export class StackBox<P extends StackBoxProps = StackBoxProps, E extends StackeB
371
384
  * The CSS class for this component is automatically generated as `x4assistbox`.
372
385
  */
373
386
 
374
- @class_ns( "x4" )
375
387
  export class AssistBox extends StackBox {
388
+ static classPrefix = "x4";
376
389
 
377
390
  /**
378
391
  * Selects the next or previous page in the stack.
@@ -433,8 +446,8 @@ export interface GridBoxProps extends Omit<BoxProps,"content"> {
433
446
  * Auto-generates CSS class: `x4gridbox`.
434
447
  */
435
448
 
436
- @class_ns("x4")
437
449
  export class GridBox<P extends GridBoxProps=GridBoxProps,E extends ComponentEvents=ComponentEvents> extends Box<P,E> {
450
+ static classPrefix = "x4";
438
451
 
439
452
  constructor( props: P ) {
440
453
  super( props );
@@ -543,8 +556,8 @@ interface MasonryProps extends Omit<BoxProps,"content"> {
543
556
  * Auto-generates CSS class: `x4masonrybox`.
544
557
  */
545
558
 
546
- @class_ns("x4")
547
559
  export class MasonryBox extends Box<MasonryProps> {
560
+ static classPrefix = "x4";
548
561
 
549
562
  constructor(props: MasonryProps ) {
550
563
  super(props);
@@ -14,7 +14,6 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- import { class_ns } from '../../core/core_tools';
18
17
  import { parseRoute, Router } from '../../core/core_router';
19
18
 
20
19
  import { BoxProps, Button, HBox, Icon } from '../components';
@@ -64,8 +63,8 @@ interface BreadcrumbsProps extends BoxProps{
64
63
  * ```
65
64
  */
66
65
 
67
- @class_ns( "x4" )
68
66
  export class Breadcrumbs extends HBox<BreadcrumbsProps,BreadcrumbEvents> {
67
+ static classPrefix = "x4";
69
68
 
70
69
  constructor( props: BreadcrumbsProps ) {
71
70
  super( props );
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { Component, ComponentEvents, ComponentProps, Flex, Space } from '../../core/component';
18
18
  import { EventCallback } from '../../core/core_events';
19
- import { class_ns, isString } from '../../core/core_tools';
19
+ import { isString } from '../../core/core_tools';
20
20
  import { _tr } from '../../core/core_i18n'
21
21
 
22
22
  import { Button } from '../button/button';
@@ -64,8 +64,8 @@ interface BtnGroupProps extends Omit<ComponentProps,"content"> {
64
64
  * a packed group draws its buttons with the --ol-button-* variables of Button
65
65
  */
66
66
 
67
- @class_ns( "x4" )
68
67
  export class BtnGroup extends Box<BtnGroupProps,BtnGroupEvents> {
68
+ static classPrefix = "x4";
69
69
 
70
70
  constructor( props: BtnGroupProps ) {
71
71
  super( props );
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { Component, ComponentEvents, ComponentProps, EvClick } from "../../core/component"
18
18
  import { EventCallback } from '../../core/core_events';
19
- import { class_ns, isFunction, UnsafeHtml } from '../../core/core_tools';
19
+ import { isFunction, UnsafeHtml } from '../../core/core_tools';
20
20
 
21
21
  import { Icon } from "../icon/icon"
22
22
  import { Menu, MenuElement } from '../menu/menu';
@@ -113,8 +113,8 @@ export interface ButtonProps extends ComponentProps {
113
113
  * the --ol-button-* variables are the ones of the outline buttons
114
114
  */
115
115
 
116
- @class_ns( "x4" )
117
116
  export class Button extends Component<ButtonProps,ButtonEvents> {
117
+ static classPrefix = "x4";
118
118
 
119
119
  #text: Component;
120
120
 
@@ -15,7 +15,7 @@
15
15
  **/
16
16
 
17
17
  import { Component, ComponentEvents, ComponentProps, EvChange, Flex } from '../../core/component'
18
- import { class_ns, date_clone, date_hash, formatIntlDate, Point, unsafeHtml } from "../../core/core_tools"
18
+ import { date_clone, date_hash, formatIntlDate, Point, unsafeHtml } from "../../core/core_tools"
19
19
  import { _tr } from '../../core/core_i18n';
20
20
  import { EventCallback } from '../../core/core_events';
21
21
 
@@ -70,9 +70,10 @@ interface CalendarProps extends ComponentProps {
70
70
  * ```
71
71
  */
72
72
 
73
- @class_ns( "x4" )
74
73
  export class Calendar extends VBox<CalendarProps, CalendarEventMap>
75
74
  {
75
+ static classPrefix = "x4";
76
+
76
77
  private m_date: Date;
77
78
 
78
79
  constructor(props: CalendarProps) {
@@ -333,6 +334,7 @@ export class Calendar extends VBox<CalendarProps, CalendarEventMap>
333
334
  * /
334
335
 
335
336
  export class PopupCalendar extends Popup {
337
+ static classPrefix = "x4";
336
338
 
337
339
  m_cal: Calendar;
338
340
 
@@ -356,7 +358,7 @@ export class PopupCalendar extends Popup {
356
358
  let newfocus = <HTMLElement>e.target;
357
359
 
358
360
  // child of this: ok
359
- if (this.dom.contains(newfocus)) {
361
+ if (this.contains(newfocus)) {
360
362
  return;
361
363
  }
362
364
 
@@ -14,7 +14,6 @@
14
14
  * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
15
  **/
16
16
 
17
- import { class_ns } from '../../core/core_tools';
18
17
  import { Component, ComponentEvent, ComponentEvents, ComponentProps } from '../../core/component';
19
18
  import { EventCallback } from "../../core/core_events"
20
19
  import { CanvasEx, createPainter } from './canvas_ex';
@@ -45,8 +44,8 @@ export interface CanvasProps extends ComponentProps {
45
44
  * Standard Canvas
46
45
  */
47
46
 
48
- @class_ns( "x4" )
49
47
  export class Canvas extends Component<CanvasProps, CanvasEventMap> {
48
+ static classPrefix = "x4";
50
49
 
51
50
  private m_iwidth: number = -1;
52
51
  private m_iheight: number = -1;
@@ -17,7 +17,7 @@
17
17
  import { ComponentEvent, ComponentEvents } from '../../core/component';
18
18
  import { EventCallback } from '../../core/core_events';
19
19
  import { SvgBuilder, SvgComponent, SvgGroup, SvgPath, SvgProps, SvgShape } from '../../core/core_svg';
20
- import { class_ns, clamp, IRect, isNumber, sanitizeHtml } from '../../core/core_tools';
20
+ import { clamp, formatNumber, IRect, isNumber, sanitizeHtml } from '../../core/core_tools';
21
21
 
22
22
  import "./chart.module.scss"
23
23
 
@@ -91,7 +91,7 @@ export function chartFormatUnit( value: number, decimals = 2 ) {
91
91
 
92
92
  const pow = Math.pow(10, decimals);
93
93
  const roundedValue = Math.round(scaledValue * pow) / pow;
94
- const text = roundedValue % 1 == 0 ? `${roundedValue}` : roundedValue.toFixed(decimals).replace(/\.?0+$/, '');
94
+ const text = formatNumber( roundedValue, decimals ); // the decimal separator of the locale
95
95
 
96
96
  return ( value<0 && roundedValue!=0 ? '-' : '' ) + text + units[unitIndex];
97
97
  }
@@ -234,8 +234,8 @@ function drawBar( grp: SvgGroup, x: number, w: number, y0: number, y1: number, r
234
234
  * ```
235
235
  */
236
236
 
237
- @class_ns( "x4" )
238
237
  export class Chart extends SvgComponent<ChartProps,ChartEvents> {
238
+ static classPrefix = "x4";
239
239
 
240
240
  private _type: ChartType;
241
241
  private _series: ChartSerie[];
@@ -264,7 +264,7 @@ export class Chart extends SvgComponent<ChartProps,ChartEvents> {
264
264
 
265
265
  this.addDOMEvent( "click", ( e ) => {
266
266
  const el = ( e.target as Element ).closest( "[data-index]" );
267
- if( el && this.dom.contains( el ) ) {
267
+ if( el && this.contains( el ) ) {
268
268
  const serie = parseInt( el.getAttribute( "data-serie" ) );
269
269
  const index = parseInt( el.getAttribute( "data-index" ) );
270
270
  this.fire( "click", { serie, index, value: this._series[serie]?.values[index] } );
@@ -3,7 +3,6 @@ import { EventCallback } from '../../core/core_events';
3
3
 
4
4
  import { Input } from '../input/input';
5
5
  import { Label } from '../label/label';
6
- import { class_ns } from '../../core/core_tools';
7
6
 
8
7
  import icons from "../assets/icons";
9
8
 
@@ -45,8 +44,9 @@ interface CheckboxProps extends ComponentProps {
45
44
  * ```
46
45
  */
47
46
 
48
- @class_ns( "x4" )
49
47
  export class Checkbox extends Component<CheckboxProps,CheckBoxEvents> {
48
+ static classPrefix = "x4";
49
+
50
50
  readonly _input: Input;
51
51
 
52
52
  /**
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { Component, ComponentEvents } from '../../core/component';
18
18
  import { EventCallback } from '../../core/core_events';
19
- import { isFeatureAvailable, class_ns, isFunction, IComponentInterface, IFormElement } from '../../core/core_tools';
19
+ import { isFeatureAvailable, isFunction, IComponentInterface, IFormElement } from '../../core/core_tools';
20
20
  import { Color } from '../../core/core_colors';
21
21
 
22
22
  import { BoxProps, HBox } from '../boxes/boxes';
@@ -84,8 +84,9 @@ interface ColorInputEvents extends ComponentEvents {
84
84
  * ```
85
85
  */
86
86
 
87
- @class_ns( "x4" )
88
87
  export class ColorInput extends HBox<ColorInputProps,ColorInputEvents> {
88
+ static classPrefix = "x4";
89
+
89
90
  static "$cls-ns" = "x4";
90
91
 
91
92
  private _color: Color; // null: no color
@@ -15,7 +15,7 @@
15
15
  **/
16
16
 
17
17
  import { Color, Hsv } from '../../core/core_colors';
18
- import { Rect, clamp, class_ns, isFeatureAvailable } from '../../core/core_tools';
18
+ import { Rect, clamp, isFeatureAvailable } from '../../core/core_tools';
19
19
 
20
20
  import { Component, ComponentEvent, ComponentEvents, ComponentProps, EvChange } from '../../core/component';
21
21
  import { Box, BoxProps, HBox, VBox } from '../boxes/boxes';
@@ -58,8 +58,8 @@ interface CommonEvents extends ComponentEvents {
58
58
  *
59
59
  */
60
60
 
61
- @class_ns( "x4" )
62
61
  export class Saturation extends Box<BoxProps,CommonEvents> {
62
+ static classPrefix = "x4";
63
63
 
64
64
  private mdown = false;
65
65
  private irect: Rect;
@@ -191,8 +191,8 @@ export class Saturation extends Box<BoxProps,CommonEvents> {
191
191
  * @internal
192
192
  */
193
193
 
194
- @class_ns( "x4" )
195
194
  class HueSlider extends Box<BoxProps,CommonEvents> {
195
+ static classPrefix = "x4";
196
196
 
197
197
  private thumb: Component;
198
198
  private hsv: Hsv = { hue: 1, saturation: 1, value: 1, alpha: 1 };
@@ -271,8 +271,8 @@ class HueSlider extends Box<BoxProps,CommonEvents> {
271
271
  * @internal
272
272
  */
273
273
 
274
- @class_ns( "x4" )
275
274
  class AlphaSlider extends Box<BoxProps,CommonEvents> {
275
+ static classPrefix = "x4";
276
276
 
277
277
  private thumb: Component;
278
278
  private color: Component;
@@ -389,8 +389,8 @@ interface ColorPickerChangeEvents extends ComponentEvents {
389
389
  * ```
390
390
  */
391
391
 
392
- @class_ns( "x4" )
393
392
  export class ColorPicker extends VBox<ColorPickerProps,ColorPickerChangeEvents> {
393
+ static classPrefix = "x4";
394
394
 
395
395
  private _base: Color;
396
396
  private _hsv: Hsv;
@@ -15,7 +15,7 @@
15
15
  **/
16
16
 
17
17
  import { Component, ComponentEvents, ComponentProps, EvClick, EvSelectionChange, makeUniqueComponentId } from '../../core/component';
18
- import { class_ns, IComponentInterface, IFormElement, kbNav } from '../../core/core_tools';
18
+ import { IComponentInterface, IFormElement, kbNav } from '../../core/core_tools';
19
19
  import { EventCallback } from '../../core/core_events';
20
20
 
21
21
  import { Listbox, ListboxID, ListItem } from '../listbox/listbox';
@@ -42,8 +42,8 @@ interface DropdownProps extends Omit<PopupProps,"content"> {
42
42
  }
43
43
 
44
44
 
45
- @class_ns( "x4" )
46
45
  export class DropdownList extends Popup<DropdownProps,DropdownEvents> {
46
+ static classPrefix = "x4";
47
47
 
48
48
  private _list: Listbox;
49
49
 
@@ -108,8 +108,8 @@ interface ComboboxProps extends Omit<ComponentProps,"content"> {
108
108
  * ```
109
109
  */
110
110
 
111
- @class_ns( "x4" )
112
111
  export class Combobox extends Component<ComboboxProps,ComboboxEvents> {
112
+ static classPrefix = "x4";
113
113
 
114
114
  private _popup: DropdownList;
115
115
  //private _label: Label;