x4js 2.0.13 → 2.0.15
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/.vscode/launch.json +14 -0
- package/README.md +5 -0
- package/{lib/src/demo → demo}/main.scss +3 -1
- package/{lib/src/demo/main.tsx → demo/main.ts} +37 -36
- package/demo/package.json +26 -0
- package/demo/scss.d.ts +4 -0
- package/demo/svg.d.ts +1 -0
- package/demo/tsconfig.json +14 -0
- package/lib/README.txt +5 -0
- package/lib/cjs/x4.css +1 -1
- package/lib/cjs/x4.js +2 -1
- package/lib/esm/x4.css +1 -1
- package/lib/esm/x4.mjs +2 -1
- package/lib/src/components/boxes/boxes.module.scss +17 -0
- package/lib/src/components/boxes/boxes.ts +258 -17
- package/lib/src/components/breadcrumb/breadcrumb.scss +56 -28
- package/lib/src/components/breadcrumb/breadcrumb.ts +93 -84
- package/lib/src/components/btngroup/btngroup.module.scss +12 -0
- package/lib/src/components/btngroup/btngroup.ts +41 -8
- package/lib/src/components/button/button.module.scss +23 -5
- package/lib/src/components/button/button.ts +72 -4
- package/lib/src/components/canvas/canvas.module.scss +25 -0
- package/lib/src/components/canvas/canvas.ts +189 -0
- package/lib/src/components/canvas/canvas_ex.ts +276 -0
- package/lib/src/components/checkbox/checkbox.ts +18 -4
- package/lib/src/components/combobox/combobox.module.scss +24 -15
- package/lib/src/components/combobox/combobox.ts +107 -24
- package/lib/src/components/components.ts +7 -0
- package/lib/src/components/dialog/dialog.module.scss +40 -7
- package/lib/src/components/dialog/dialog.ts +166 -31
- package/lib/src/components/filedrop/cloud-arrow-up.svg +1 -0
- package/lib/src/components/filedrop/filedrop.module.scss +70 -0
- package/lib/src/components/filedrop/filedrop.ts +131 -0
- package/lib/src/components/form/form.module.scss +4 -0
- package/lib/src/components/form/form.ts +137 -6
- package/lib/src/components/gridview/arrow-down-light.svg +1 -0
- package/lib/src/components/gridview/arrow-up-light.svg +1 -0
- package/lib/src/components/gridview/gridview.module.scss +324 -0
- package/lib/src/components/gridview/gridview.ts +1175 -0
- package/lib/src/components/icon/icon.module.scss +2 -1
- package/lib/src/components/icon/icon.ts +4 -3
- package/lib/src/components/image/image.module.scss +8 -1
- package/lib/src/components/image/image.ts +105 -6
- package/lib/src/components/input/input.module.scss +8 -3
- package/lib/src/components/input/input.ts +178 -31
- package/lib/src/components/keyboard/arrow-up.svg +1 -0
- package/lib/src/components/keyboard/delete-left.svg +1 -0
- package/lib/src/components/keyboard/eye-slash.svg +1 -0
- package/lib/src/components/keyboard/keyboard.module.scss +134 -0
- package/lib/src/components/keyboard/keyboard.ts +526 -0
- package/lib/src/components/label/label.module.scss +22 -4
- package/lib/src/components/label/label.ts +33 -0
- package/lib/src/components/link/link.ts +81 -78
- package/lib/src/components/listbox/listbox.module.scss +61 -3
- package/lib/src/components/listbox/listbox.ts +164 -56
- package/lib/src/components/menu/menu.module.scss +10 -1
- package/lib/src/components/menu/menu.ts +6 -3
- package/lib/src/components/messages/messages.module.scss +44 -0
- package/lib/src/components/messages/messages.ts +164 -18
- package/lib/src/components/messages/pen-field.svg +1 -0
- package/lib/src/components/normalize.scss +5 -0
- package/lib/src/components/notification/notification.module.scss +4 -2
- package/lib/src/components/notification/notification.ts +2 -4
- package/lib/src/components/panel/panel.module.scss +12 -0
- package/lib/src/components/popup/popup.module.scss +10 -2
- package/lib/src/components/popup/popup.ts +141 -95
- package/lib/src/components/propgrid/folder-closed.svg +1 -0
- package/lib/src/components/propgrid/folder-open.svg +1 -0
- package/lib/src/components/propgrid/progrid.module.scss +112 -0
- package/lib/src/components/propgrid/propgrid.ts +288 -0
- package/lib/src/components/propgrid/updown.svg +4 -0
- package/lib/src/components/radio/radio.module.scss +147 -0
- package/lib/src/components/radio/radio.svg +4 -0
- package/lib/src/components/radio/radio.ts +142 -0
- package/lib/src/components/select/select.module.scss +9 -0
- package/lib/src/components/select/select.ts +134 -0
- package/lib/src/components/shared.scss +47 -0
- package/lib/src/components/sizers/sizer.ts +10 -2
- package/lib/src/components/slider/slider.module.scss +77 -30
- package/lib/src/components/slider/slider.ts +72 -22
- package/lib/src/components/tabs/tabs.module.scss +1 -2
- package/lib/src/components/tabs/tabs.ts +49 -12
- package/lib/src/components/textarea/textarea.module.scss +6 -2
- package/lib/src/components/textarea/textarea.ts +73 -8
- package/lib/src/components/textedit/textedit.module.scss +3 -1
- package/lib/src/components/textedit/textedit.ts +47 -15
- package/lib/src/components/themes.scss +7 -0
- package/lib/src/components/tickline/tickline.module.scss +26 -0
- package/lib/src/components/tickline/tickline.ts +82 -0
- package/lib/src/components/tooltips/comments-question.svg +1 -0
- package/lib/src/components/tooltips/tooltips.scss +30 -9
- package/lib/src/components/tooltips/tooltips.ts +10 -5
- package/lib/src/components/treeview/treeview.module.scss +129 -60
- package/lib/src/components/treeview/treeview.ts +47 -12
- package/lib/src/components/viewport/viewport.module.scss +7 -0
- package/lib/src/core/component.ts +113 -40
- package/lib/src/core/core_application.ts +223 -2
- package/lib/src/core/core_colors.ts +2 -2
- package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +264 -252
- package/lib/src/core/core_dragdrop.ts +3 -3
- package/lib/src/core/core_element.ts +18 -1
- package/lib/src/core/core_events.ts +28 -0
- package/lib/src/core/core_i18n.ts +19 -3
- package/lib/src/core/core_react.ts +79 -0
- package/lib/src/core/core_router.ts +25 -9
- package/lib/src/core/core_state.ts +62 -0
- package/lib/src/core/core_styles.ts +5 -5
- package/lib/src/core/core_svg.ts +174 -12
- package/lib/src/core/core_tools.ts +305 -87
- package/lib/src/x4tsx.d.ts +25 -0
- package/lib/styles/x4.css +1 -1
- package/lib/types/x4js.d.ts +828 -119
- package/package.json +4 -4
- package/scripts/build.mjs +378 -0
- package/scripts/prepack.mjs +346 -0
- package/src/components/base.scss +25 -0
- package/src/components/boxes/boxes.module.scss +54 -0
- package/src/components/boxes/boxes.ts +370 -0
- package/src/components/breadcrumb/breadcrumb.scss +56 -0
- package/src/components/breadcrumb/breadcrumb.ts +93 -0
- package/src/components/breadcrumb/chevron-right.svg +1 -0
- package/src/components/btngroup/btngroup.module.scss +41 -0
- package/src/components/btngroup/btngroup.ts +153 -0
- package/src/components/button/button.module.scss +173 -0
- package/src/components/button/button.ts +185 -0
- package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
- package/src/components/calendar/calendar.module.scss +163 -0
- package/src/components/calendar/calendar.ts +327 -0
- package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
- package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
- package/src/components/canvas/canvas.module.scss +25 -0
- package/src/components/canvas/canvas.ts +189 -0
- package/src/components/canvas/canvas_ex.ts +276 -0
- package/src/components/checkbox/check.svg +4 -0
- package/src/components/checkbox/checkbox.module.scss +142 -0
- package/src/components/checkbox/checkbox.ts +140 -0
- package/src/components/colorinput/colorinput.module.scss +65 -0
- package/src/components/colorinput/colorinput.ts +91 -0
- package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
- package/src/components/colorpicker/colorpicker.module.scss +133 -0
- package/src/components/colorpicker/colorpicker.ts +482 -0
- package/src/components/combobox/combobox.module.scss +133 -0
- package/src/components/combobox/combobox.ts +275 -0
- package/src/components/combobox/updown.svg +4 -0
- package/src/components/components.ts +41 -0
- package/src/components/dialog/dialog.module.scss +104 -0
- package/src/components/dialog/dialog.ts +229 -0
- package/src/components/dialog/xmark-sharp-light.svg +1 -0
- package/src/components/filedrop/cloud-arrow-up.svg +1 -0
- package/src/components/filedrop/filedrop.module.scss +70 -0
- package/src/components/filedrop/filedrop.ts +131 -0
- package/src/components/form/form.module.scss +38 -0
- package/src/components/form/form.ts +172 -0
- package/src/components/gridview/arrow-down-light.svg +1 -0
- package/src/components/gridview/arrow-up-light.svg +1 -0
- package/src/components/gridview/gridview.module.scss +324 -0
- package/src/components/gridview/gridview.ts +1175 -0
- package/src/components/header/header.module.scss +40 -0
- package/src/components/header/header.ts +130 -0
- package/src/components/icon/icon.module.scss +31 -0
- package/src/components/icon/icon.ts +137 -0
- package/src/components/image/image.module.scss +28 -0
- package/src/components/image/image.ts +168 -0
- package/src/components/input/input.module.scss +74 -0
- package/src/components/input/input.ts +422 -0
- package/src/components/keyboard/arrow-up.svg +1 -0
- package/src/components/keyboard/delete-left.svg +1 -0
- package/src/components/keyboard/eye-slash.svg +1 -0
- package/src/components/keyboard/keyboard.module.scss +134 -0
- package/src/components/keyboard/keyboard.ts +526 -0
- package/src/components/label/label.module.scss +76 -0
- package/src/components/label/label.ts +97 -0
- package/src/components/link/link.ts +81 -0
- package/src/components/listbox/listbox.module.scss +161 -0
- package/src/components/listbox/listbox.ts +539 -0
- package/src/components/menu/caret-right-solid.svg +1 -0
- package/src/components/menu/menu.module.scss +117 -0
- package/src/components/menu/menu.ts +174 -0
- package/src/components/messages/circle-exclamation.svg +1 -0
- package/src/components/messages/messages.module.scss +92 -0
- package/src/components/messages/messages.ts +215 -0
- package/src/components/messages/pen-field.svg +1 -0
- package/src/components/normalize.scss +391 -0
- package/src/components/notification/circle-check-solid.svg +1 -0
- package/src/components/notification/circle-exclamation-solid.svg +1 -0
- package/src/components/notification/circle-notch-light.svg +1 -0
- package/src/components/notification/notification.module.scss +84 -0
- package/src/components/notification/notification.ts +107 -0
- package/src/components/notification/xmark-sharp-light.svg +1 -0
- package/src/components/panel/panel.module.scss +60 -0
- package/src/components/panel/panel.ts +58 -0
- package/src/components/popup/popup.module.scss +51 -0
- package/src/components/popup/popup.ts +442 -0
- package/src/components/progress/progress.module.scss +57 -0
- package/src/components/progress/progress.ts +44 -0
- package/src/components/propgrid/folder-closed.svg +1 -0
- package/src/components/propgrid/folder-open.svg +1 -0
- package/src/components/propgrid/progrid.module.scss +112 -0
- package/src/components/propgrid/propgrid.ts +288 -0
- package/src/components/propgrid/updown.svg +4 -0
- package/src/components/radio/radio.module.scss +147 -0
- package/src/components/radio/radio.svg +4 -0
- package/src/components/radio/radio.ts +142 -0
- package/src/components/rating/rating.module.scss +23 -0
- package/src/components/rating/rating.ts +131 -0
- package/src/components/rating/star-sharp-light.svg +1 -0
- package/src/components/rating/star-sharp-solid.svg +1 -0
- package/src/components/select/select.module.scss +9 -0
- package/src/components/select/select.ts +134 -0
- package/src/components/shared.scss +137 -0
- package/src/components/sizers/sizer.module.scss +90 -0
- package/src/components/sizers/sizer.ts +132 -0
- package/src/components/slider/slider.module.scss +118 -0
- package/src/components/slider/slider.ts +198 -0
- package/src/components/switch/switch.module.scss +127 -0
- package/src/components/switch/switch.ts +62 -0
- package/src/components/tabs/tabs.module.scss +45 -0
- package/src/components/tabs/tabs.ts +205 -0
- package/src/components/textarea/textarea.module.scss +63 -0
- package/src/components/textarea/textarea.ts +125 -0
- package/src/components/textedit/textedit.module.scss +116 -0
- package/src/components/textedit/textedit.ts +115 -0
- package/src/components/themes.scss +88 -0
- package/src/components/tickline/tickline.module.scss +26 -0
- package/src/components/tickline/tickline.ts +82 -0
- package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
- package/src/components/tooltips/comments-question.svg +1 -0
- package/src/components/tooltips/tooltips.scss +72 -0
- package/src/components/tooltips/tooltips.ts +109 -0
- package/src/components/treeview/chevron-down-light.svg +1 -0
- package/src/components/treeview/treeview.module.scss +185 -0
- package/src/components/treeview/treeview.ts +445 -0
- package/src/components/viewport/viewport.module.scss +32 -0
- package/src/components/viewport/viewport.ts +41 -0
- package/src/core/component.ts +1075 -0
- package/src/core/core_application.ts +265 -0
- package/src/core/core_colors.ts +250 -0
- package/src/core/core_data.ts +1310 -0
- package/src/core/core_dom.ts +471 -0
- package/src/core/core_dragdrop.ts +201 -0
- package/src/core/core_element.ts +115 -0
- package/src/core/core_events.ts +177 -0
- package/src/core/core_i18n.ts +393 -0
- package/src/core/core_react.ts +79 -0
- package/src/core/core_router.ts +237 -0
- package/src/core/core_state.ts +62 -0
- package/src/core/core_styles.ts +214 -0
- package/src/core/core_svg.ts +712 -0
- package/src/core/core_tools.ts +906 -0
- package/src/types/scss.d.ts +4 -0
- package/src/types/svg.d.ts +1 -0
- package/src/types/x4react.d.ts +9 -0
- package/src/x4.scss +19 -0
- package/src/x4tsx.d.ts +25 -0
- package/tsconfig.json +14 -0
- package/lib/src/components/grid/gridview.ts +0 -1108
- package/lib/src/components/grid/memdb.ts +0 -325
- /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
- /package/{lib/src/demo → demo}/assets/radio.svg +0 -0
- /package/{lib/src/demo → demo}/index.html +0 -0
|
@@ -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 { isArray, UnsafeHtml, isNumber, Rect, Constructor, class_ns, x4_class_ns_sym } from './core_tools';
|
|
17
|
+
import { isArray, UnsafeHtml, isNumber, Rect, Constructor, class_ns, x4_class_ns_sym, IRect } from './core_tools';
|
|
18
18
|
import { CoreElement } from './core_element';
|
|
19
19
|
import { ariaValues, unitless } from './core_styles';
|
|
20
20
|
import { CoreEvent, EventMap } from './core_events';
|
|
@@ -25,6 +25,7 @@ interface RefType<T extends Component> {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
type ComponentAttributes = Record<string,string|number|boolean>;
|
|
28
|
+
type CreateComponentCallBack = ( attrs: Record<string,string> ) => ComponentContent;
|
|
28
29
|
|
|
29
30
|
const FRAGMENT = Symbol( "fragment" );
|
|
30
31
|
const COMPONENT = Symbol( "component" );
|
|
@@ -41,14 +42,18 @@ const RE_NUMBER = /^-?\d+(\.\d*)?$/;
|
|
|
41
42
|
* to your class to avoid autogenerated css class names conflicts
|
|
42
43
|
*/
|
|
43
44
|
|
|
44
|
-
function genClassNames( x: any ) {
|
|
45
|
+
function genClassNames( x: any ): string[] {
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
const classes = [];
|
|
47
48
|
let self = Object.getPrototypeOf(x);
|
|
48
49
|
|
|
50
|
+
if( self.constructor==Component ) {
|
|
51
|
+
return ["x4-comp"];
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
while (self && self.constructor !== Component ) {
|
|
50
55
|
const clsname:string = self.constructor.name;
|
|
51
|
-
const clsns: string =
|
|
56
|
+
const clsns: string = Object.prototype.hasOwnProperty.call(self.constructor,x4_class_ns_sym) ? self.constructor[x4_class_ns_sym] : "";
|
|
52
57
|
classes.push( clsns+clsname.toLowerCase() );
|
|
53
58
|
self = Object.getPrototypeOf(self);
|
|
54
59
|
}
|
|
@@ -60,7 +65,7 @@ function genClassNames( x: any ) {
|
|
|
60
65
|
*
|
|
61
66
|
*/
|
|
62
67
|
|
|
63
|
-
export type ComponentContent = Component | string | UnsafeHtml | number | boolean
|
|
68
|
+
export type ComponentContent = Component | Component[] | string | string[] | UnsafeHtml| UnsafeHtml[] | number | boolean;
|
|
64
69
|
|
|
65
70
|
let gen_id = 1000;
|
|
66
71
|
|
|
@@ -89,6 +94,7 @@ export interface ComponentProps {
|
|
|
89
94
|
height?: string | number;
|
|
90
95
|
disabled?: true,
|
|
91
96
|
hidden?: true,
|
|
97
|
+
flex?: boolean | number;
|
|
92
98
|
|
|
93
99
|
tooltip?: string;
|
|
94
100
|
|
|
@@ -129,7 +135,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
129
135
|
readonly props: P;
|
|
130
136
|
protected readonly clsprefix: string; // internal class name prefix (x4 internal)
|
|
131
137
|
|
|
132
|
-
|
|
138
|
+
#store: Map<string|symbol,any>;
|
|
133
139
|
|
|
134
140
|
constructor( props: P ) {
|
|
135
141
|
super( );
|
|
@@ -159,6 +165,15 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
159
165
|
this.show( false );
|
|
160
166
|
}
|
|
161
167
|
|
|
168
|
+
if( props.flex===true ) {
|
|
169
|
+
this.addClass( "x4flex" );
|
|
170
|
+
}
|
|
171
|
+
else if( props.flex!==undefined ) {
|
|
172
|
+
this.setStyle( {
|
|
173
|
+
"flexGrow": props.flex+""
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
162
177
|
if( props.id!==undefined ) {
|
|
163
178
|
this.setAttribute( "id", props.id );
|
|
164
179
|
}
|
|
@@ -220,8 +235,9 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
220
235
|
|
|
221
236
|
addClass( cls: string ) {
|
|
222
237
|
if( !cls ) return;
|
|
223
|
-
|
|
238
|
+
|
|
224
239
|
if( cls.indexOf(' ')>=0 ) {
|
|
240
|
+
cls = cls.trim( );
|
|
225
241
|
const ccs = cls.split( " " );
|
|
226
242
|
this.dom.classList.add(...ccs);
|
|
227
243
|
}
|
|
@@ -231,11 +247,16 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
231
247
|
}
|
|
232
248
|
|
|
233
249
|
/**
|
|
234
|
-
*
|
|
250
|
+
* special case: '*' mean clear class list
|
|
235
251
|
*/
|
|
236
252
|
|
|
237
253
|
removeClass( cls: string ) {
|
|
238
254
|
if( !cls ) return;
|
|
255
|
+
|
|
256
|
+
if( cls=='*' ) {
|
|
257
|
+
this.dom.classList.value = "";
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
239
260
|
|
|
240
261
|
if( cls.indexOf(' ')>=0 ) {
|
|
241
262
|
const ccs = cls.split( " " );
|
|
@@ -283,9 +304,10 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
283
304
|
*
|
|
284
305
|
*/
|
|
285
306
|
|
|
286
|
-
setClass( cls: string, set: boolean = true ) {
|
|
307
|
+
setClass( cls: string, set: boolean = true ) : this {
|
|
287
308
|
if( set ) this.addClass(cls);
|
|
288
309
|
else this.removeClass( cls );
|
|
310
|
+
return this;
|
|
289
311
|
}
|
|
290
312
|
|
|
291
313
|
// :: ATTRIBUTES ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
@@ -294,12 +316,11 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
294
316
|
* attributes
|
|
295
317
|
*/
|
|
296
318
|
|
|
297
|
-
setAttributes( attrs: ComponentAttributes ) {
|
|
298
|
-
|
|
319
|
+
setAttributes( attrs: ComponentAttributes ): this {
|
|
299
320
|
for( const name in attrs ) {
|
|
300
|
-
|
|
301
|
-
this.setAttribute( name, value );
|
|
321
|
+
this.setAttribute( name, attrs[name] );
|
|
302
322
|
}
|
|
323
|
+
return this;
|
|
303
324
|
}
|
|
304
325
|
|
|
305
326
|
/**
|
|
@@ -331,6 +352,18 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
331
352
|
return this.getAttribute( "data-"+name );
|
|
332
353
|
}
|
|
333
354
|
|
|
355
|
+
/**
|
|
356
|
+
* @returns undefined if not a number
|
|
357
|
+
*/
|
|
358
|
+
getIntData( name: string ) : number {
|
|
359
|
+
const v = parseInt( this.getAttribute( "data-"+name ) );
|
|
360
|
+
if( Number.isFinite(v) ) {
|
|
361
|
+
return v;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
|
|
334
367
|
/**
|
|
335
368
|
*
|
|
336
369
|
*/
|
|
@@ -343,17 +376,17 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
343
376
|
* idem as setData but onot on dom, you can store anything
|
|
344
377
|
*/
|
|
345
378
|
|
|
346
|
-
setInternalData( name: string|
|
|
347
|
-
if( !this
|
|
348
|
-
this
|
|
379
|
+
setInternalData( name: string|symbol, value: any ): this {
|
|
380
|
+
if( !this.#store ) {
|
|
381
|
+
this.#store = new Map( );
|
|
349
382
|
}
|
|
350
383
|
|
|
351
|
-
this
|
|
384
|
+
this.#store.set( name, value );
|
|
352
385
|
return this;
|
|
353
386
|
}
|
|
354
387
|
|
|
355
|
-
getInternalData( name: string|
|
|
356
|
-
return this
|
|
388
|
+
getInternalData( name: string|symbol ): any {
|
|
389
|
+
return this.#store?.get(name);
|
|
357
390
|
}
|
|
358
391
|
|
|
359
392
|
|
|
@@ -387,7 +420,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
387
420
|
protected mapPropEvents<N extends keyof E>(props: P, ...elements: N[] ) {
|
|
388
421
|
const p = props as any;
|
|
389
422
|
elements.forEach( n => {
|
|
390
|
-
if (
|
|
423
|
+
if (Object.prototype.hasOwnProperty.call(p,n) && p[n]) {
|
|
391
424
|
this.on( n, p[n] );
|
|
392
425
|
}
|
|
393
426
|
});
|
|
@@ -465,17 +498,15 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
465
498
|
|
|
466
499
|
prependContent( content: ComponentContent ) {
|
|
467
500
|
const d = this.dom;
|
|
468
|
-
|
|
469
501
|
const set = ( c: Component | string | UnsafeHtml | number | boolean ) => {
|
|
470
502
|
if (c instanceof Component ) {
|
|
471
|
-
d.
|
|
503
|
+
d.insertAdjacentElement( 'afterbegin', c.dom );
|
|
472
504
|
}
|
|
473
505
|
else if( c instanceof UnsafeHtml) {
|
|
474
|
-
d.insertAdjacentHTML( '
|
|
506
|
+
d.insertAdjacentHTML( 'afterbegin', c.toString() );
|
|
475
507
|
}
|
|
476
508
|
else if (typeof c === "string" || typeof c === "number") {
|
|
477
|
-
|
|
478
|
-
d.insertBefore( d.firstChild, tnode );
|
|
509
|
+
d.insertAdjacentText( 'afterbegin', c.toString() );
|
|
479
510
|
}
|
|
480
511
|
else {
|
|
481
512
|
console.warn("Unknown type to append: ", c);
|
|
@@ -512,7 +543,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
512
543
|
queryAll( selector: string ): Component[] {
|
|
513
544
|
const all = this.dom.querySelectorAll( selector );
|
|
514
545
|
const rc = new Array( all.length );
|
|
515
|
-
all.forEach( (x,i) => rc[i]=
|
|
546
|
+
all.forEach( (x,i) => rc[i]=wrapDOM(x as HTMLElement) );
|
|
516
547
|
return rc;
|
|
517
548
|
}
|
|
518
549
|
|
|
@@ -525,6 +556,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
525
556
|
return componentFromDOM<T>(r);
|
|
526
557
|
}
|
|
527
558
|
|
|
559
|
+
|
|
528
560
|
// :: STYLES ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
529
561
|
|
|
530
562
|
|
|
@@ -657,8 +689,13 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
657
689
|
*
|
|
658
690
|
*/
|
|
659
691
|
|
|
660
|
-
focus( ) {
|
|
692
|
+
focus( ): this {
|
|
661
693
|
(this.dom as HTMLElement).focus( );
|
|
694
|
+
return this;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
hasFocus( ) {
|
|
698
|
+
return document.activeElement==this.dom;
|
|
662
699
|
}
|
|
663
700
|
|
|
664
701
|
/**
|
|
@@ -681,40 +718,49 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
681
718
|
*
|
|
682
719
|
*/
|
|
683
720
|
|
|
684
|
-
show( vis = true ) {
|
|
721
|
+
show( vis = true ): this {
|
|
685
722
|
this.setClass( 'x4hidden', !vis );
|
|
723
|
+
return this;
|
|
686
724
|
}
|
|
687
725
|
|
|
688
726
|
/**
|
|
689
727
|
*
|
|
690
728
|
*/
|
|
691
729
|
|
|
692
|
-
hide( ) {
|
|
730
|
+
hide( ): this {
|
|
693
731
|
this.show( false );
|
|
732
|
+
return this;
|
|
694
733
|
}
|
|
695
734
|
|
|
696
735
|
/**
|
|
697
736
|
* enable or disable a component (all sub HTMLElement will be also disabled)
|
|
698
737
|
*/
|
|
699
738
|
|
|
700
|
-
enable( ena = true ) {
|
|
701
|
-
this.setAttribute( "disabled", !ena );
|
|
739
|
+
enable( ena = true ): this {
|
|
740
|
+
this.setAttribute( "disabled", !ena ? 'true' : null );
|
|
741
|
+
|
|
742
|
+
if( this.dom instanceof HTMLInputElement || this.dom instanceof HTMLButtonElement ) {
|
|
743
|
+
this.dom.disabled = !ena;
|
|
744
|
+
}
|
|
702
745
|
|
|
703
746
|
// propagate diable state to all input children
|
|
704
747
|
const nodes = this.enumChildNodes( true );
|
|
705
748
|
nodes.forEach( x => {
|
|
706
|
-
if( x instanceof HTMLInputElement ) {
|
|
749
|
+
if( x instanceof HTMLInputElement || x instanceof HTMLButtonElement ) {
|
|
707
750
|
x.disabled = !ena;
|
|
708
751
|
}
|
|
709
752
|
});
|
|
753
|
+
|
|
754
|
+
return this;
|
|
710
755
|
}
|
|
711
756
|
|
|
712
757
|
/**
|
|
713
758
|
*
|
|
714
759
|
*/
|
|
715
760
|
|
|
716
|
-
disable( ) {
|
|
761
|
+
disable( ): this {
|
|
717
762
|
this.enable( false );
|
|
763
|
+
return this;
|
|
718
764
|
}
|
|
719
765
|
|
|
720
766
|
/**
|
|
@@ -749,10 +795,17 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
749
795
|
*/
|
|
750
796
|
|
|
751
797
|
parentElement<T extends Component>( cls?: Constructor<T> ): T {
|
|
752
|
-
|
|
798
|
+
return Component.parentElement<T>( this.dom, cls );
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* search for parent that match the given contructor
|
|
803
|
+
*/
|
|
804
|
+
|
|
805
|
+
static parentElement<T extends Component>( dom: Node, cls?: Constructor<T> ): T {
|
|
753
806
|
|
|
754
|
-
while(
|
|
755
|
-
const cp = componentFromDOM(
|
|
807
|
+
while( dom.parentElement ) {
|
|
808
|
+
const cp = componentFromDOM( dom.parentElement );
|
|
756
809
|
if( !cls ) {
|
|
757
810
|
return cp as T;
|
|
758
811
|
}
|
|
@@ -761,7 +814,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
761
814
|
return cp;
|
|
762
815
|
}
|
|
763
816
|
|
|
764
|
-
|
|
817
|
+
dom = dom.parentElement;
|
|
765
818
|
}
|
|
766
819
|
|
|
767
820
|
return null;
|
|
@@ -793,7 +846,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
793
846
|
|
|
794
847
|
enumChildComponents( recursive: boolean ) {
|
|
795
848
|
|
|
796
|
-
|
|
849
|
+
const children: Component[] = [];
|
|
797
850
|
|
|
798
851
|
const nodes = this.enumChildNodes( recursive );
|
|
799
852
|
nodes.forEach( ( c: Node ) => {
|
|
@@ -811,7 +864,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
811
864
|
*/
|
|
812
865
|
|
|
813
866
|
enumChildNodes( recursive: boolean ) {
|
|
814
|
-
|
|
867
|
+
const children: Node[] = Array.from( recursive ? this.dom.querySelectorAll( '*' ) : this.dom.children );
|
|
815
868
|
return children;
|
|
816
869
|
}
|
|
817
870
|
|
|
@@ -830,7 +883,7 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
830
883
|
* called by the compiler when a jsx element is seen
|
|
831
884
|
*/
|
|
832
885
|
|
|
833
|
-
static createElement( clsOrTag: string | ComponentConstructor |
|
|
886
|
+
static createElement( clsOrTag: string | ComponentConstructor | symbol | CreateComponentCallBack, attrs: any, ...children: Component[] ): Component | Component[] {
|
|
834
887
|
|
|
835
888
|
let comp: Component;
|
|
836
889
|
|
|
@@ -875,7 +928,11 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
875
928
|
// :: SPECIALS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
876
929
|
|
|
877
930
|
/**
|
|
931
|
+
* system interfaces:
|
|
932
|
+
* "form-element"
|
|
933
|
+
* "tab-handler"
|
|
878
934
|
*
|
|
935
|
+
* each app can create it's own interface
|
|
879
936
|
*/
|
|
880
937
|
|
|
881
938
|
queryInterface<T>( name: string ): T {
|
|
@@ -923,6 +980,13 @@ export class Flex extends Component {
|
|
|
923
980
|
}
|
|
924
981
|
}
|
|
925
982
|
|
|
983
|
+
// just a spacer element that push other
|
|
984
|
+
export class Space extends Component {
|
|
985
|
+
constructor( width?: number|string, cls?: string ) {
|
|
986
|
+
super( { width, cls } )
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
926
990
|
|
|
927
991
|
// :: HIGH LEVEL BASIC EVENTS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
928
992
|
|
|
@@ -945,6 +1009,14 @@ export interface EvChange extends ComponentEvent {
|
|
|
945
1009
|
readonly value: any;
|
|
946
1010
|
}
|
|
947
1011
|
|
|
1012
|
+
/**
|
|
1013
|
+
* Focus event
|
|
1014
|
+
*/
|
|
1015
|
+
|
|
1016
|
+
export interface EvFocus extends ComponentEvent {
|
|
1017
|
+
readonly focus_out: boolean;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
948
1020
|
/**
|
|
949
1021
|
* Selection Event
|
|
950
1022
|
* value is the new selection or null
|
|
@@ -955,6 +1027,7 @@ interface ISelection {
|
|
|
955
1027
|
|
|
956
1028
|
export interface EvSelectionChange extends ComponentEvent {
|
|
957
1029
|
readonly selection: ISelection;
|
|
1030
|
+
readonly empty: boolean;
|
|
958
1031
|
}
|
|
959
1032
|
|
|
960
1033
|
|
|
@@ -14,31 +14,252 @@
|
|
|
14
14
|
* that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
|
-
import { Component } from './component.js';
|
|
17
|
+
import { Component, componentFromDOM } from './component.js';
|
|
18
18
|
import { CoreElement } from './core_element.js';
|
|
19
|
-
import { EventMap } from './core_events';
|
|
19
|
+
import { CoreEvent, EventMap } from './core_events';
|
|
20
|
+
import { getFocusableElements, ITabHandler } from './core_tools.js';
|
|
20
21
|
|
|
22
|
+
const socket_sent = Symbol( 'socket' );
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export interface EvMessage extends CoreEvent {
|
|
26
|
+
msg: string;
|
|
27
|
+
params: any;
|
|
28
|
+
}
|
|
21
29
|
|
|
22
30
|
export interface ApplicationEvents extends EventMap {
|
|
31
|
+
global: EvMessage;
|
|
32
|
+
message: EvMessage;
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
// signleton
|
|
26
36
|
let main_app: Application = null;
|
|
27
37
|
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Process {
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* can be use to see if we have some tactile input
|
|
44
|
+
* @returns max touch point count
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
getMaxTouchPoints( ) {
|
|
48
|
+
return navigator.maxTouchPoints;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
28
54
|
export class Application<E extends ApplicationEvents = ApplicationEvents> extends CoreElement<E> {
|
|
29
55
|
|
|
56
|
+
private env = new Map<string,any>( );
|
|
57
|
+
private mainview: Component;
|
|
58
|
+
|
|
59
|
+
static readonly process = new Process( );
|
|
60
|
+
|
|
30
61
|
constructor( ) {
|
|
31
62
|
super( );
|
|
32
63
|
|
|
33
64
|
console.assert( main_app==null, "Application must be a singleton." );
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
34
66
|
main_app = this;
|
|
35
67
|
}
|
|
36
68
|
|
|
37
69
|
setMainView( view: Component ) {
|
|
70
|
+
this.mainview = view;
|
|
38
71
|
document.body.appendChild( view.dom );
|
|
72
|
+
this._setupKeyboard( );
|
|
39
73
|
}
|
|
40
74
|
|
|
41
75
|
static instance<P extends Application = Application>( ): P {
|
|
42
76
|
return main_app as P;
|
|
43
77
|
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
getMainView( ) {
|
|
84
|
+
return this.mainview;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
*
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
setEnv( name: string, value: any ) {
|
|
92
|
+
this.env.set( name, value );
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
getEnv( name: string, def_value?: any ) {
|
|
100
|
+
return this.env.get( name ) ?? def_value;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* small shortcut for Application.instance().fire( "global", ... );
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
static fireGlobal( msg: string, params?: any ) {
|
|
108
|
+
Application.instance().fire( "global", { msg, params } );
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
*
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
private _setupKeyboard( ) {
|
|
116
|
+
|
|
117
|
+
document.addEventListener( "keydown", (ev) => {
|
|
118
|
+
if( ev.key=="Tab" || ev.key=="Enter" ) {
|
|
119
|
+
if( this.focusNext( !ev.shiftKey ) ) {
|
|
120
|
+
ev.preventDefault( );
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} );
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
focusNext( next: boolean ) {
|
|
127
|
+
let act = document.activeElement;
|
|
128
|
+
let topmost: HTMLElement;
|
|
129
|
+
|
|
130
|
+
while( act!=document.body ) {
|
|
131
|
+
const comp = componentFromDOM(act);
|
|
132
|
+
const ifx = comp.queryInterface( "tab-handler") as ITabHandler;
|
|
133
|
+
|
|
134
|
+
if( ifx ) {
|
|
135
|
+
return ifx.focusNext( next );
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if( act.classList.contains("x4box") ) { // todo: that is too dirty
|
|
139
|
+
topmost = act as HTMLElement;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
act = act.parentElement;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if( topmost ) {
|
|
146
|
+
const focusable = getFocusableElements( topmost );
|
|
147
|
+
if( !focusable.length ) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const first = focusable[0];
|
|
152
|
+
const last = focusable[focusable.length - 1];
|
|
153
|
+
|
|
154
|
+
let newf: HTMLElement;
|
|
155
|
+
if (!next && document.activeElement === first) {
|
|
156
|
+
newf = last as HTMLElement;
|
|
157
|
+
}
|
|
158
|
+
else if (next && document.activeElement === last) {
|
|
159
|
+
newf = first as HTMLElement;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if( newf ) {
|
|
163
|
+
newf.focus();
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
|
|
177
|
+
setupSocketMessaging( path?: string, looseCallback?: ( ) => void ) {
|
|
178
|
+
|
|
179
|
+
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
|
180
|
+
const address = path ? protocol+path : `${protocol}${window.location.hostname}:${window.location.port}/ws`;
|
|
181
|
+
|
|
182
|
+
let opened = 0;
|
|
183
|
+
let msg_socket:WebSocket = null;
|
|
184
|
+
|
|
185
|
+
// we trap all 'global' messages send via application
|
|
186
|
+
// then we send them on websocket
|
|
187
|
+
|
|
188
|
+
this.on( 'global', ( e: EvMessage ) => {
|
|
189
|
+
if( Object.prototype.hasOwnProperty.call( e, socket_sent) ) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if( msg_socket ) {
|
|
194
|
+
msg_socket.send( JSON.stringify( {
|
|
195
|
+
msg: e.msg,
|
|
196
|
+
params: e.params,
|
|
197
|
+
} ) );
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
msg_socket = new WebSocket(address, 'messaging' );
|
|
202
|
+
|
|
203
|
+
msg_socket.onopen = ( ) => {
|
|
204
|
+
console.log( 'websocket opened' );
|
|
205
|
+
opened = 1;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// receive a message
|
|
209
|
+
msg_socket.onmessage = ( e ) => {
|
|
210
|
+
if( e.data!='ping' ) {
|
|
211
|
+
const message = JSON.parse(e.data);
|
|
212
|
+
message[socket_sent] = true;
|
|
213
|
+
this.fire( 'global', message );
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// loose socket
|
|
218
|
+
msg_socket.onclose = ( ev ) => {
|
|
219
|
+
console.log( 'websocket closed:', ev );
|
|
220
|
+
msg_socket = null;
|
|
221
|
+
|
|
222
|
+
if( opened ) {
|
|
223
|
+
looseCallback( );
|
|
224
|
+
opened = 0;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
//msg_socket.onerror = (ev )=> {
|
|
229
|
+
// console.log( 'websocket error:', ev );
|
|
230
|
+
//}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* get a local storage value
|
|
235
|
+
* @param name name of the value
|
|
236
|
+
* @returns the value (string) or undefined
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
getStorage( name: string ) : string {
|
|
240
|
+
return localStorage.getItem( name );
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
getStorageJSON( name: string ) : any {
|
|
244
|
+
try {
|
|
245
|
+
return JSON.parse( localStorage.getItem( name ) );
|
|
246
|
+
}
|
|
247
|
+
catch( e ) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* change a loclastorage value
|
|
254
|
+
* @param name name of the value
|
|
255
|
+
* @param value the value to store
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
setStorage( name: string, value: string | number ) {
|
|
259
|
+
localStorage.setItem( name, value+'' );
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
setStorageJSON( name: string, value: any ) {
|
|
263
|
+
localStorage.setItem( name, JSON.stringify( value ) );
|
|
264
|
+
}
|
|
44
265
|
}
|
|
@@ -178,7 +178,7 @@ export class Color {
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
setRgb( r: number, g: number, b: number, a: number ): this {
|
|
181
|
-
this.rgb = [clamp(r,0,255),clamp(g,0,255),clamp(b,0,255),clamp(a,0,1)];
|
|
181
|
+
this.rgb = [clamp(r|0,0,255),clamp(g|0,0,255),clamp(b|0,0,255),clamp(a,0,1)];
|
|
182
182
|
return this;
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -189,7 +189,7 @@ export class Color {
|
|
|
189
189
|
|
|
190
190
|
toHexString( ): string {
|
|
191
191
|
const _ = this.rgb;
|
|
192
|
-
return _[3]==1 ?
|
|
192
|
+
return _[3]==1 ? `#${hx(_[0])}${hx(_[1])}${hx(_[2])}` : `#${hx(_[0])}${hx(_[1])}${hx(_[2])}${(hx((_[3]*255)|0))}`
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
toRgb( ): Rgb {
|