x4js 2.0.26 → 2.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/.vscode/settings.json +2 -0
  3. package/ai-comments.txt +97 -0
  4. package/demo/assets/house-light.svg +1 -0
  5. package/demo/assets/radio.svg +4 -0
  6. package/demo/index.html +12 -0
  7. package/demo/main.scss +23 -0
  8. package/demo/main.ts +324 -0
  9. package/demo/package.json +26 -0
  10. package/demo/scss.d.ts +4 -0
  11. package/demo/svg.d.ts +1 -0
  12. package/demo/tsconfig.json +14 -0
  13. package/lib/types/x4js.d.ts +0 -2374
  14. package/package.json +23 -47
  15. package/prepack.mjs +3 -0
  16. package/scripts/prepack.mjs +342 -0
  17. package/src/colors.scss +246 -0
  18. package/src/components/boxes/boxes.module.scss +1 -1
  19. package/src/components/boxes/boxes.ts +139 -28
  20. package/src/components/button/button.ts +80 -33
  21. package/src/components/combobox/combobox.ts +1 -1
  22. package/src/components/dialog/dialog.ts +4 -0
  23. package/src/components/gauge/gauge.module.scss +3 -0
  24. package/src/components/gauge/gauge.ts +1 -1
  25. package/src/components/gridview/gridview.ts +106 -8
  26. package/src/components/icon/icon.ts +42 -14
  27. package/src/components/input/input.ts +155 -76
  28. package/src/components/keyboard/keyboard.module.scss +1 -1
  29. package/src/components/keyboard/keyboard.ts +31 -9
  30. package/src/components/label/label.module.scss +9 -0
  31. package/src/components/label/label.ts +10 -6
  32. package/src/components/link/link.module.scss +44 -0
  33. package/src/components/link/link.ts +7 -1
  34. package/src/components/listbox/listbox.module.scss +18 -4
  35. package/src/components/listbox/listbox.ts +34 -15
  36. package/src/components/menu/menu.module.scss +14 -2
  37. package/src/components/menu/menu.ts +1 -1
  38. package/src/components/messages/messages.ts +13 -5
  39. package/src/components/panel/panel.module.scss +7 -0
  40. package/src/components/popup/popup.ts +14 -10
  41. package/src/components/propgrid/propgrid.ts +13 -3
  42. package/src/components/shared.scss +4 -0
  43. package/src/components/spreadsheet/spreadsheet.module.scss +308 -0
  44. package/src/components/spreadsheet/spreadsheet.ts +1223 -0
  45. package/src/components/tabs/tabs.module.scss +1 -0
  46. package/src/components/textarea/textarea.ts +8 -2
  47. package/src/components/textedit/textedit.ts +7 -0
  48. package/src/components/themes.scss +2 -0
  49. package/src/components/tooltips/tooltips.ts +15 -3
  50. package/src/core/component.ts +358 -162
  51. package/src/core/core_application.ts +129 -32
  52. package/src/core/core_colors.ts +382 -119
  53. package/src/core/core_data.ts +73 -86
  54. package/src/core/core_dom.ts +10 -0
  55. package/src/core/core_dragdrop.ts +32 -7
  56. package/src/core/core_element.ts +111 -4
  57. package/src/core/core_events.ts +48 -11
  58. package/src/core/core_i18n.ts +2 -0
  59. package/src/core/core_pdf.ts +454 -0
  60. package/src/core/core_router.ts +64 -5
  61. package/src/core/core_state.ts +1 -0
  62. package/src/core/core_styles.ts +11 -12
  63. package/src/core/core_svg.ts +348 -51
  64. package/src/core/core_tools.ts +105 -17
  65. package/src/x4.ts +1 -0
  66. package/src/x4tsx.d.ts +2 -1
  67. package/tsconfig.json +11 -0
  68. package/lib/README.txt +0 -20
  69. package/lib/cjs/x4.css +0 -1
  70. package/lib/cjs/x4.js +0 -2
  71. package/lib/esm/x4.css +0 -1
  72. package/lib/esm/x4.mjs +0 -2
  73. package/lib/styles/x4.css +0 -1
@@ -17,7 +17,7 @@
17
17
  import { Component, componentFromDOM } from './component';
18
18
  import { CoreElement } from './core_element';
19
19
  import { CoreEvent, EventMap } from './core_events';
20
- import { getFocusableElements, ITabHandler } from './core_tools';
20
+ import { asap, getFocusableElements, ITabHandler } from './core_tools';
21
21
 
22
22
  const socket_sent = Symbol( 'socket' );
23
23
 
@@ -32,10 +32,12 @@ export interface ApplicationEvents extends EventMap {
32
32
  message: EvMessage;
33
33
  }
34
34
 
35
- // signleton
35
+ // singleton
36
36
  let main_app: Application = null;
37
37
 
38
-
38
+ /**
39
+ * Provides information about the user's device and browser capabilities.
40
+ */
39
41
 
40
42
  class Process {
41
43
 
@@ -49,61 +51,131 @@ class Process {
49
51
  }
50
52
  }
51
53
 
54
+ /**
55
+ *
56
+ */
52
57
 
58
+ interface AppProps {
59
+ /** The CSS selector for the DOM element where the application's main view will be mounted (default: `'body'`). */
60
+ mountPoint?: string;
61
+ }
62
+
63
+ /**
64
+ * The main application class, acting as a singleton.
65
+ * It manages the main view, environment variables, keyboard navigation,
66
+ * and provides utilities for local storage and WebSocket communication.
67
+ *
68
+ * Assertions ensure only one instance of `Application` can exist.
69
+ */
53
70
 
54
71
  export class Application<E extends ApplicationEvents = ApplicationEvents> extends CoreElement<E> {
55
72
 
56
73
  private env = new Map<string,any>( );
57
74
  private mainview: Component;
75
+ private props: AppProps;
76
+ private mounted = false;
58
77
 
78
+ /**
79
+ * Provides access to process-related information, such as touch capabilities.
80
+ */
81
+
59
82
  static readonly process = new Process( );
60
83
 
61
- constructor( ) {
84
+ /**
85
+ * Creates an instance of the Application.
86
+ * This class is a singleton; an assertion will fail if multiple instances are created.
87
+ * @param props - Configuration properties for the application.
88
+ */
89
+
90
+ constructor( props: AppProps = {} ) {
62
91
  super( );
63
92
 
64
93
  console.assert( main_app==null, "Application must be a singleton." );
65
94
  // eslint-disable-next-line @typescript-eslint/no-this-alias
66
95
  main_app = this;
96
+
97
+ const loaded = ( ) => {
98
+ this.mount( props.mountPoint ?? 'body' )
99
+ }
100
+
101
+ if( document.readyState=='complete' ) {
102
+ asap( loaded );
103
+ }
104
+ else {
105
+ window.addEventListener( "load", loaded, { once: true } );
106
+ }
67
107
  }
68
108
 
109
+ /**
110
+ *
111
+ */
112
+
113
+ private mount( mountPoint = 'body' ) {
114
+ if( !this.mounted && this.mainview ) {
115
+ const ev = document.querySelector( mountPoint );
116
+ if( ev ) {
117
+ ev.appendChild( this.mainview.dom );
118
+ }
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Sets the main view component for the application.
124
+ * This component will be mounted to the DOM.
125
+ * @param view - The component to set as the main view.
126
+ */
127
+
69
128
  setMainView( view: Component ) {
70
129
  this.mainview = view;
71
- document.body.appendChild( view.dom );
72
130
  this._setupKeyboard( );
73
131
  }
74
132
 
133
+ /**
134
+ * Returns the singleton instance of the Application.
135
+ * @returns The application instance.
136
+ */
137
+
75
138
  static instance<P extends Application = Application>( ): P {
76
139
  return main_app as P;
77
140
  }
78
141
 
79
- /**
80
- *
81
- */
142
+ /**
143
+ * Retrieves the main view component of the application.
144
+ * @returns The application's main view component.
145
+ */
82
146
 
83
147
  getMainView( ) {
84
148
  return this.mainview;
85
149
  }
86
150
 
87
151
  /**
88
- *
89
- */
152
+ * Sets an environment variable in the application's environment map.
153
+ * @param name - The name of the environment variable.
154
+ * @param value - The value to store for the environment variable.
155
+ */
90
156
 
91
157
  setEnv( name: string, value: any ) {
92
158
  this.env.set( name, value );
93
159
  }
94
160
 
95
161
  /**
96
- *
97
- */
162
+ * Retrieves an environment variable from the application's environment map.
163
+ * @param name - The name of the environment variable.
164
+ * @param def_value - An optional default value to return if the variable is not found.
165
+ * @returns The value of the environment variable, or `def_value` if not found.
166
+ */
98
167
 
99
168
  getEnv( name: string, def_value?: any ) {
100
169
  return this.env.get( name ) ?? def_value;
101
170
  }
102
171
 
103
172
  /**
104
- * small shortcut for Application.instance().fire( "global", ... );
105
- */
106
-
173
+ * Retrieves an environment variable from the application's environment map.
174
+ * @param name - The name of the environment variable.
175
+ * @param def_value - An optional default value to return if the variable is not found.
176
+ * @returns The value of the environment variable, or `def_value` if not found.
177
+ */
178
+
107
179
  static fireGlobal( msg: string, params?: any ) {
108
180
  Application.instance().fire( "global", { msg, params } );
109
181
  }
@@ -123,20 +195,29 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
123
195
  } );
124
196
  }
125
197
 
198
+ /**
199
+ * Moves focus to the next or previous focusable element within the application.
200
+ * Handles Tab and Shift+Tab key presses.
201
+ * @param next - If `true`, focus moves to the next element; if `false`, to the previous.
202
+ * @returns `true` if focus was successfully moved, `false` otherwise.
203
+ */
204
+
126
205
  focusNext( next: boolean ) {
127
206
  let act = document.activeElement;
128
207
  let topmost: HTMLElement;
129
208
 
130
209
  while( act!=document.body ) {
131
210
  const comp = componentFromDOM(act);
132
- const ifx = comp.queryInterface( "tab-handler") as ITabHandler;
211
+ if( comp ) {
212
+ const ifx = comp.queryInterface( "tab-handler") as ITabHandler;
133
213
 
134
- if( ifx ) {
135
- return ifx.focusNext( next );
136
- }
214
+ if( ifx ) {
215
+ return ifx.focusNext( next );
216
+ }
137
217
 
138
- if( act.classList.contains("x4box") ) { // todo: that is too dirty
139
- topmost = act as HTMLElement;
218
+ if( act.classList.contains("x4box") ) { // todo: that is too dirty
219
+ topmost = act as HTMLElement;
220
+ }
140
221
  }
141
222
 
142
223
  act = act.parentElement;
@@ -169,10 +250,13 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
169
250
  return false;
170
251
  }
171
252
 
172
-
173
253
  /**
174
- *
175
- */
254
+ * Sets up WebSocket messaging for the application.
255
+ * All 'global' messages fired via the application will be sent over the WebSocket,
256
+ * and messages received from the WebSocket will be re-fired as 'global' messages.
257
+ * @param path - Optional WebSocket path. If not provided, it defaults to `ws://hostname:port/ws`.
258
+ * @param looseCallback - A callback function to be executed when the WebSocket connection is closed unexpectedly.
259
+ */
176
260
 
177
261
  setupSocketMessaging( path?: string, looseCallback?: ( ) => void ) {
178
262
 
@@ -231,15 +315,21 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
231
315
  }
232
316
 
233
317
  /**
234
- * get a local storage value
235
- * @param name name of the value
236
- * @returns the value (string) or undefined
237
- */
318
+ * Retrieves a value from the browser's local storage.
319
+ * @param name - The key of the value to retrieve.
320
+ * @returns The stored value as a string, or `null` if not found.
321
+ */
238
322
 
239
323
  getStorage( name: string ) : string {
240
324
  return localStorage.getItem( name );
241
325
  }
242
326
 
327
+ /**
328
+ * Retrieves and parses a JSON value from the browser's local storage.
329
+ * @param name - The key of the JSON value to retrieve.
330
+ * @returns The parsed JSON object, or `undefined` if not found or parsing fails.
331
+ */
332
+
243
333
  getStorageJSON( name: string ) : any {
244
334
  try {
245
335
  return JSON.parse( localStorage.getItem( name ) );
@@ -250,15 +340,22 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
250
340
  }
251
341
 
252
342
  /**
253
- * change a loclastorage value
254
- * @param name name of the value
255
- * @param value the value to store
256
- */
343
+ * Stores a string or number value in the browser's local storage.
344
+ * The value will be converted to a string before storage.
345
+ * @param name - The key under which to store the value.
346
+ * @param value - The value to store.
347
+ */
257
348
 
258
349
  setStorage( name: string, value: string | number ) {
259
350
  localStorage.setItem( name, value+'' );
260
351
  }
261
352
 
353
+ /**
354
+ * Stores an object as a JSON string in the browser's local storage.
355
+ * @param name - The key under which to store the JSON value.
356
+ * @param value - The object to serialize and store.
357
+ */
358
+
262
359
  setStorageJSON( name: string, value: any ) {
263
360
  localStorage.setItem( name, JSON.stringify( value ) );
264
361
  }