x4js 2.3.24 → 2.3.26

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 +101 -17
  2. package/aiguide.md +64 -15
  3. package/package.json +1 -1
  4. package/src/components/assets/icons.ts +2 -0
  5. package/src/components/autocomplete/autocomplete.ts +2 -2
  6. package/src/components/boxes/boxes.module.scss +16 -2
  7. package/src/components/boxes/boxes.ts +24 -11
  8. package/src/components/breadcrumb/breadcrumb.ts +1 -2
  9. package/src/components/btngroup/btngroup.ts +2 -2
  10. package/src/components/button/button.ts +7 -2
  11. package/src/components/calendar/calendar.ts +4 -2
  12. package/src/components/canvas/canvas.ts +1 -2
  13. package/src/components/chart/chart.ts +3 -3
  14. package/src/components/checkbox/checkbox.ts +2 -2
  15. package/src/components/colorinput/colorinput.ts +3 -2
  16. package/src/components/colorpicker/colorpicker.ts +5 -5
  17. package/src/components/combobox/combobox.ts +3 -3
  18. package/src/components/dialog/dialog.ts +8 -2
  19. package/src/components/dockingview/dockingview.ts +1 -2
  20. package/src/components/filedrop/filedrop.ts +3 -2
  21. package/src/components/form/form.module.scss +2 -1
  22. package/src/components/form/form.ts +7 -3
  23. package/src/components/gauge/gauge.ts +2 -2
  24. package/src/components/gridview/gridview.module.scss +8 -5
  25. package/src/components/gridview/gridview.ts +11 -13
  26. package/src/components/header/header.ts +2 -2
  27. package/src/components/icon/icon.ts +1 -2
  28. package/src/components/image/image.ts +1 -2
  29. package/src/components/input/input.ts +3 -2
  30. package/src/components/keyboard/keyboard.ts +2 -2
  31. package/src/components/label/label.ts +3 -3
  32. package/src/components/link/link.ts +3 -2
  33. package/src/components/listbox/listbox.module.scss +59 -2
  34. package/src/components/listbox/listbox.ts +133 -23
  35. package/src/components/menu/menu.ts +5 -4
  36. package/src/components/messages/messages.module.scss +95 -3
  37. package/src/components/messages/messages.ts +113 -27
  38. package/src/components/notification/notification.ts +6 -6
  39. package/src/components/panel/panel.ts +2 -2
  40. package/src/components/popup/popup.ts +17 -2
  41. package/src/components/progress/progress.ts +1 -2
  42. package/src/components/propgrid/progrid.module.scss +2 -3
  43. package/src/components/propgrid/propgrid.ts +32 -38
  44. package/src/components/radio/radio.ts +1 -2
  45. package/src/components/rating/rating.ts +2 -2
  46. package/src/components/select/select.ts +2 -2
  47. package/src/components/settingsview/settingsview.module.scss +6 -5
  48. package/src/components/settingsview/settingsview.ts +3 -3
  49. package/src/components/sizers/sizer.ts +21 -29
  50. package/src/components/slider/slider.ts +2 -2
  51. package/src/components/spreadsheet/spreadsheet.ts +8 -10
  52. package/src/components/switch/switch.ts +2 -2
  53. package/src/components/tabs/tabs.ts +4 -4
  54. package/src/components/tag/tag.ts +2 -2
  55. package/src/components/textarea/textarea.ts +3 -3
  56. package/src/components/textedit/textedit.ts +2 -2
  57. package/src/components/themes.scss +2 -0
  58. package/src/components/tickline/tickline.ts +3 -3
  59. package/src/components/tooltips/tooltips.ts +11 -2
  60. package/src/components/treeview/treeview.ts +3 -3
  61. package/src/components/video/video.ts +1 -2
  62. package/src/components/viewport/viewport.ts +4 -3
  63. package/src/core/component.ts +15 -24
  64. package/src/core/core_application.ts +36 -3
  65. package/src/core/core_events.ts +14 -2
  66. package/src/core/core_i18n.ts +67 -0
  67. package/src/core/core_svg.ts +1 -0
  68. package/src/core/core_tools.ts +83 -24
@@ -159,6 +159,8 @@ export class EventSource<E extends EventMap = EventMap > {
159
159
 
160
160
  /**
161
161
  * Dispatches an event with a given name and payload to all registered listeners.
162
+ * A listener that throws: its error goes to console.error, the next listeners are
163
+ * called, and fire returns normally.
162
164
  * @param name - The name of the event to fire (must be a key in `E`).
163
165
  * @param evx - The event payload (event object) to pass to the listeners.
164
166
  */
@@ -192,14 +194,24 @@ export class EventSource<E extends EventMap = EventMap > {
192
194
  ev.stopPropagation = stopPropagation;
193
195
  }
194
196
 
197
+ // a listener that throws stops neither the others nor the one that fires
198
+ const call = ( listener: EventCallback ) => {
199
+ try {
200
+ listener( ev );
201
+ }
202
+ catch( e ) {
203
+ console.error( e );
204
+ }
205
+ };
206
+
195
207
  // small optimisation
196
208
  if (listeners.length == 1) {
197
- listeners[0](ev);
209
+ call( listeners[0] );
198
210
  }
199
211
  else {
200
212
  const temp = listeners.slice();
201
213
  for (let i = 0, n = temp.length; i < n; i++) {
202
- temp[i](ev);
214
+ call( temp[i] );
203
215
  if (ev.propagationStopped) {
204
216
  break;
205
217
  }
@@ -255,6 +255,41 @@ export function getCurrentLanguage( ): string {
255
255
  return current.name;
256
256
  }
257
257
 
258
+ // :: LOCALE ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
259
+
260
+ // the formats of numbers, amounts and dates: the locale of the language (_tr.global.locale),
261
+ // unless one is forced (Application.setLocale); the currency of the amounts
262
+ let forced_locale: string = null;
263
+ let currency = "EUR";
264
+
265
+ /**
266
+ * @internal the locale forced (null: the one of the language), the currency when given
267
+ */
268
+
269
+ export function _setLocale( locale: string, cur?: string ) {
270
+ forced_locale = locale || null;
271
+ if( cur ) {
272
+ currency = cur;
273
+ }
274
+ }
275
+
276
+ /**
277
+ * the locale of the formats: the one forced by Application.setLocale, else the one of the
278
+ * language ("fr-FR" for fr)
279
+ */
280
+
281
+ export function getCurrentLocale( ): string {
282
+ return forced_locale ?? _tr.global.locale ?? "fr-FR";
283
+ }
284
+
285
+ /**
286
+ * the currency of the amounts: "EUR" unless Application.setLocale gave another
287
+ */
288
+
289
+ export function getCurrentCurrency( ): string {
290
+ return currency;
291
+ }
292
+
258
293
  /**
259
294
  *
260
295
  */
@@ -308,6 +343,7 @@ let fr = {
308
343
  date_input_formats: 'd/m/y|d.m.y|d m y|d-m-y|dmy',
309
344
  date_format: 'D/M/Y',
310
345
  date_time_format: 'D/M/Y H:I:S',
346
+ locale: 'fr-FR', // the formats of numbers, amounts, dates (Intl)
311
347
 
312
348
  day_short: [ 'dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam' ],
313
349
  day_long: [ 'dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi' ],
@@ -336,6 +372,13 @@ let fr = {
336
372
  search: 'Rechercher un paramètre',
337
373
  nomatch: 'Aucun paramètre trouvé',
338
374
  },
375
+
376
+ progression: {
377
+ error: '{0} erreur',
378
+ errors: '{0} erreurs',
379
+ warning: '{0} avertissement',
380
+ warnings: '{0} avertissements',
381
+ },
339
382
  }
340
383
  };
341
384
 
@@ -378,6 +421,7 @@ let en = {
378
421
  date_input_formats: 'm/d/y|m.d.y|m d y|m-d-y|mdy',
379
422
  date_format: 'M/D/Y',
380
423
  date_time_format: 'M/D/Y H:I:S',
424
+ locale: 'en-US', // the formats of numbers, amounts, dates (Intl)
381
425
 
382
426
  day_short: [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ],
383
427
  day_long: [ 'sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday' ],
@@ -406,6 +450,13 @@ let en = {
406
450
  search: 'Search settings',
407
451
  nomatch: 'No setting found',
408
452
  },
453
+
454
+ progression: {
455
+ error: '{0} error',
456
+ errors: '{0} errors',
457
+ warning: '{0} warning',
458
+ warnings: '{0} warnings',
459
+ },
409
460
  }
410
461
  };
411
462
 
@@ -448,6 +499,7 @@ let es = {
448
499
  date_input_formats: 'd/m/y|d.m.y|d m y|d-m-y|dmy',
449
500
  date_format: 'D/M/Y',
450
501
  date_time_format: 'D/M/Y H:I:S',
502
+ locale: 'es-ES', // the formats of numbers, amounts, dates (Intl)
451
503
 
452
504
  day_short: [ 'dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb' ],
453
505
  day_long: [ 'domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado' ],
@@ -476,6 +528,13 @@ let es = {
476
528
  search: 'Buscar un ajuste',
477
529
  nomatch: 'Ningún ajuste encontrado',
478
530
  },
531
+
532
+ progression: {
533
+ error: '{0} error',
534
+ errors: '{0} errores',
535
+ warning: '{0} advertencia',
536
+ warnings: '{0} advertencias',
537
+ },
479
538
  }
480
539
  };
481
540
 
@@ -518,6 +577,7 @@ let de = {
518
577
  date_input_formats: 'd.m.y|d/m/y|d m y|d-m-y|dmy',
519
578
  date_format: 'D.M.Y',
520
579
  date_time_format: 'D.M.Y H:I:S',
580
+ locale: 'de-DE', // the formats of numbers, amounts, dates (Intl)
521
581
 
522
582
  day_short: [ 'So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa' ],
523
583
  day_long: [ 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag' ],
@@ -546,6 +606,13 @@ let de = {
546
606
  search: 'Einstellungen durchsuchen',
547
607
  nomatch: 'Keine Einstellung gefunden',
548
608
  },
609
+
610
+ progression: {
611
+ error: '{0} Fehler',
612
+ errors: '{0} Fehler',
613
+ warning: '{0} Warnung',
614
+ warnings: '{0} Warnungen',
615
+ },
549
616
  }
550
617
  };
551
618
 
@@ -1013,6 +1013,7 @@ export interface SvgProps extends ComponentProps {
1013
1013
  */
1014
1014
 
1015
1015
  export class SvgComponent<P extends SvgProps = SvgProps, E extends ComponentEvents = ComponentEvents> extends Component<P,E> {
1016
+ static classPrefix = "x4";
1016
1017
 
1017
1018
  /**
1018
1019
  * Creates an instance of `SvgComponent`.
@@ -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 { _tr } from "./core_i18n.js";
17
+ import { _tr, _setLocale, getCurrentLocale, getCurrentCurrency } from "./core_i18n.js";
18
18
 
19
19
 
20
20
  // todo: split into 2 files
@@ -528,33 +528,103 @@ export function camelCase(text: string) {
528
528
 
529
529
  // :: DATES ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
530
530
 
531
- let cur_locale: string = 'fr-FR';
532
-
533
531
  /**
534
- * change the current locale for misc translations (date...)
535
- * @param locale
536
- * TODO: ????
532
+ * forces the locale of the formats (see Application.setLocale)
533
+ * @param locale
537
534
  */
538
535
 
539
536
  export function _date_set_locale(locale: string) {
540
- cur_locale = locale;
537
+ _setLocale( locale );
541
538
  }
542
539
 
543
540
  /**
544
- *
545
- * @param date
546
- * @param options
541
+ * a date as text: with options, the ones of Intl.DateTimeFormat in the current locale;
542
+ * without, the format of the language (_tr.global.date_format)
543
+ * @param date
544
+ * @param options
547
545
  * @example
548
546
  * let date = new Date( );
549
- * let options = { day: 'numeric', month: 'numeric', year: 'numeric', hour: 'numeric', minute: 'numeric' };
547
+ * let options = { day: 'numeric', month: 'long', year: 'numeric' };
550
548
  * let text = date_format( date, options );
551
549
  */
552
550
 
553
- export function date_format(date: Date, options?: any): string {
554
- //return new Intl.DateTimeFormat(cur_locale, options).format( date );
551
+ export function date_format(date: Date, options?: Intl.DateTimeFormatOptions): string {
552
+ if( options ) {
553
+ return new Intl.DateTimeFormat( getCurrentLocale( ), options ).format( date );
554
+ }
555
+
555
556
  return formatIntlDate(date);
556
557
  }
557
558
 
559
+ // :: FORMATS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
560
+
561
+ // numbers, amounts and dates in the current locale (the one of the language, or the one
562
+ // Application.setLocale forced): the objects of Intl, made once by locale and options
563
+ const intl_formats = new Map<string, Intl.NumberFormat | Intl.DateTimeFormat>( );
564
+
565
+ function numberFormat( key: string, options: Intl.NumberFormatOptions ) {
566
+ const locale = getCurrentLocale( );
567
+ const id = locale + "|" + key;
568
+ let fmt = intl_formats.get( id ) as Intl.NumberFormat;
569
+ if( !fmt ) {
570
+ fmt = new Intl.NumberFormat( locale, options );
571
+ intl_formats.set( id, fmt );
572
+ }
573
+ return fmt;
574
+ }
575
+
576
+ function dateFormat( key: string, options: Intl.DateTimeFormatOptions ) {
577
+ const locale = getCurrentLocale( );
578
+ const id = locale + "|" + key;
579
+ let fmt = intl_formats.get( id ) as Intl.DateTimeFormat;
580
+ if( !fmt ) {
581
+ fmt = new Intl.DateTimeFormat( locale, options );
582
+ intl_formats.set( id, fmt );
583
+ }
584
+ return fmt;
585
+ }
586
+
587
+ /**
588
+ * a number as text in the current locale: "1 234,5" in fr-FR, "1,234.5" in en-US
589
+ * @param value
590
+ * @param decimals - the most decimals shown (Intl: 3 when not given)
591
+ * @param grouping - the separator of thousands, true by default
592
+ */
593
+
594
+ export function formatNumber( value: number, decimals?: number, grouping = true ): string {
595
+ const options: Intl.NumberFormatOptions = { useGrouping: grouping };
596
+ if( decimals!==undefined ) {
597
+ options.maximumFractionDigits = decimals;
598
+ }
599
+
600
+ return numberFormat( "n" + decimals + grouping, options ).format( value );
601
+ }
602
+
603
+ /**
604
+ * an amount as text in the current locale and currency: "1 234,50 €" in fr-FR
605
+ */
606
+
607
+ export function formatMoney( value: number ): string {
608
+ const currency = getCurrentCurrency( );
609
+ return numberFormat( "m" + currency, { style: "currency", currency } ).format( value );
610
+ }
611
+
612
+ /**
613
+ * a date as text in the current locale: "22/10/2026" in fr-FR, "10/22/2026" in en-US
614
+ */
615
+
616
+ export function formatDate( date: Date ): string {
617
+ return dateFormat( "d", { } ).format( date );
618
+ }
619
+
620
+ /**
621
+ * a date and its time (hours, minutes) as text in the current locale: "22/10/2026 14:05" in fr-FR
622
+ */
623
+
624
+ export function formatDateTime( date: Date ): string {
625
+ return dateFormat( "dt", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" } ).format( date );
626
+ }
627
+
558
628
  /**
559
629
  * difference between 2 dates
560
630
  * @return text
@@ -1002,17 +1072,6 @@ export function getSystemMetrics( part: "scrollbar" | "zoom" ) {
1002
1072
 
1003
1073
 
1004
1074
 
1005
- /**
1006
- *
1007
- */
1008
-
1009
- export const x4_class_ns_sym = Symbol("class-ns");
1010
- export function class_ns(ns: string) {
1011
- return function (constructor: Function) {
1012
- (constructor as any)[x4_class_ns_sym] = ns;
1013
- }
1014
- }
1015
-
1016
1075
  /**
1017
1076
  *
1018
1077
  */