x4js 2.0.14 → 2.0.17

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 (75) hide show
  1. package/lib/cjs/x4.css +1 -1
  2. package/lib/cjs/x4.js +2 -2
  3. package/lib/esm/x4.css +1 -1
  4. package/lib/esm/x4.mjs +2 -2
  5. package/lib/src/components/boxes/boxes.ts +101 -9
  6. package/lib/src/components/canvas/canvas_ex.ts +13 -6
  7. package/lib/src/components/components.ts +2 -1
  8. package/lib/src/components/dialog/dialog.module.scss +3 -4
  9. package/lib/src/components/dialog/dialog.ts +19 -2
  10. package/lib/src/components/form/form.ts +1 -1
  11. package/lib/src/components/icon/icon.module.scss +1 -0
  12. package/lib/src/components/icon/icon.ts +0 -2
  13. package/lib/src/components/input/input.ts +46 -22
  14. package/lib/src/components/keyboard/keyboard.ts +29 -28
  15. package/lib/src/components/menu/menu.ts +2 -2
  16. package/lib/src/components/popup/popup.module.scss +6 -0
  17. package/lib/src/components/popup/popup.ts +5 -3
  18. package/lib/src/components/propgrid/progrid.module.scss +4 -0
  19. package/lib/src/components/propgrid/propgrid.ts +22 -5
  20. package/lib/src/components/sizers/sizer.ts +2 -1
  21. package/lib/src/components/tabs/tabs.ts +6 -0
  22. package/lib/src/components/textedit/textedit.ts +26 -21
  23. package/lib/src/core/component.ts +15 -21
  24. package/lib/src/core/core_application.ts +2 -1
  25. package/lib/src/core/core_data.ts +9 -8
  26. package/lib/src/core/core_element.ts +5 -0
  27. package/lib/src/core/core_i18n.ts +1 -1
  28. package/lib/src/core/core_router.ts +2 -2
  29. package/lib/src/core/core_state.ts +62 -0
  30. package/lib/src/core/core_svg.ts +1 -0
  31. package/lib/src/x4.ts +4 -0
  32. package/lib/styles/x4.css +1 -1
  33. package/lib/types/x4js.d.ts +369 -234
  34. package/package.json +18 -28
  35. package/src/components/boxes/boxes.ts +101 -9
  36. package/src/components/canvas/canvas.ts +1 -1
  37. package/src/components/canvas/canvas_ex.ts +13 -6
  38. package/src/components/components.ts +2 -1
  39. package/src/components/dialog/dialog.module.scss +3 -4
  40. package/src/components/dialog/dialog.ts +19 -2
  41. package/src/components/form/form.ts +1 -1
  42. package/src/components/icon/icon.module.scss +1 -0
  43. package/src/components/icon/icon.ts +0 -2
  44. package/src/components/input/input.ts +46 -22
  45. package/src/components/keyboard/keyboard.ts +29 -28
  46. package/src/components/menu/menu.ts +2 -2
  47. package/src/components/popup/popup.module.scss +6 -0
  48. package/src/components/popup/popup.ts +5 -3
  49. package/src/components/propgrid/progrid.module.scss +4 -0
  50. package/src/components/propgrid/propgrid.ts +22 -5
  51. package/src/components/sizers/sizer.ts +2 -1
  52. package/src/components/tabs/tabs.ts +6 -0
  53. package/src/components/textedit/textedit.ts +26 -21
  54. package/src/core/component.ts +15 -21
  55. package/src/core/core_application.ts +2 -1
  56. package/src/core/core_data.ts +9 -8
  57. package/src/core/core_element.ts +5 -0
  58. package/src/core/core_i18n.ts +1 -1
  59. package/src/core/core_router.ts +2 -2
  60. package/src/core/core_state.ts +62 -0
  61. package/src/core/core_svg.ts +1 -0
  62. package/src/x4.ts +4 -0
  63. package/.vscode/launch.json +0 -14
  64. package/demo/assets/house-light.svg +0 -1
  65. package/demo/assets/radio.svg +0 -4
  66. package/demo/index.html +0 -12
  67. package/demo/main.scss +0 -23
  68. package/demo/main.ts +0 -324
  69. package/demo/package.json +0 -26
  70. package/demo/scss.d.ts +0 -4
  71. package/demo/svg.d.ts +0 -1
  72. package/demo/tsconfig.json +0 -14
  73. package/scripts/build.mjs +0 -378
  74. package/scripts/prepack.mjs +0 -346
  75. package/tsconfig.json +0 -14
package/package.json CHANGED
@@ -1,13 +1,8 @@
1
1
  {
2
2
  "name": "x4js",
3
- "version": "2.0.14",
3
+ "version": "2.0.17",
4
4
  "description": "X4 framework",
5
5
  "author": "etienne cochard",
6
- "main": "src/x4.ts",
7
- "typess": "lib/types/x4js.d.ts",
8
- "filess": [
9
- "lib/**/*"
10
- ],
11
6
  "license": "MIT",
12
7
  "repository": {
13
8
  "type": "git",
@@ -25,37 +20,32 @@
25
20
  "application"
26
21
  ],
27
22
  "scripts": {
28
- "build": "node scripts/build.mjs --watch --hmr --serve",
29
- "build-release": "node scripts/build.mjs --release",
23
+ "build": "x4build --watch --hmr --serve",
24
+ "build-release": "x4build --release",
30
25
  "prepack": "node scripts/prepack.mjs"
31
26
  },
32
27
  "homepage": "https://x4js.org",
33
- "module": "lib/esm/x4.mjs",
34
- "exportss": {
28
+ "files": ["lib","src"],
29
+ "types": "./src/x4.ts",
30
+ "module": "./lib/esm/x4.mjs",
31
+ "main": "./lib/cjs/x4.js",
32
+ "exports": {
35
33
  ".": {
36
- "import": {
37
- "types": "./lib/types/x4.d.ts",
38
- "default": "./lib/esm/x4.mjs"
39
- },
40
- "require": {
41
- "types": "./lib/types/x4.d.ts",
42
- "default": "./lib/cjs/x4.js"
43
- }
34
+ "types": "./src/x4.ts",
35
+ "module": "./lib/esm/x4.mjs",
36
+ "require": "./lib/cjs/x4.js"
44
37
  }
45
38
  },
46
- "devDependencies": {
47
- "chalk": "^5.3",
48
- "esbuild": "^0.24",
49
- "esbuild-plugin-d.ts": "^1.3",
50
- "esbuild-sass-plugin": "^3.3",
51
- "typescript": "^5.6.3",
52
- "watcher": "^2.3",
53
- "ws": "^8.18"
54
- },
55
39
  "x4build": {
56
40
  "entryPoints": [
57
41
  "src/x4.ts"
58
42
  ],
59
- "outdir": "build"
43
+ "outdir": "lib"
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^5.8.3",
47
+ "x4build": "^1.6.8",
48
+ "esbuild-plugin-d.ts": "^1.3",
49
+ "esbuild-sass-plugin": "^3.3"
60
50
  }
61
51
  }
@@ -14,10 +14,11 @@
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, isArray, isNumber, isString } from '@core/core_tools.js';
18
- import { Component, ComponentContent, ComponentEvents, ComponentProps } from "../../core/component"
17
+ import { asap, class_ns, isArray, isNumber, isString } from '@core/core_tools.js';
18
+ import { Component, ComponentContent, ComponentEvents, ComponentProps, EvSelectionChange } from "../../core/component"
19
19
 
20
20
  import "./boxes.module.scss";
21
+ import { EventCallback } from '@core/core_events.js';
21
22
 
22
23
  export interface BoxProps extends ComponentProps {
23
24
  tag?: string;
@@ -61,24 +62,46 @@ type ContentBuilder = ( ) => Component;
61
62
  interface StackItem {
62
63
  name: string;
63
64
  content: Component | ContentBuilder;
65
+ title?: string;
64
66
  }
65
67
 
66
- interface StackedLayoutProps extends Omit<ComponentProps,"content"> {
68
+ /**
69
+ *
70
+ */
71
+
72
+ interface StackeBoxEvents extends ComponentEvents {
73
+ pageChange?: EvSelectionChange;
74
+ }
75
+
76
+ export interface StackBoxProps extends Omit<ComponentProps,"content"> {
67
77
  default: string;
68
78
  items: StackItem[];
79
+ pageChange?: EventCallback<EvSelectionChange>;
69
80
  }
70
81
 
82
+ /**
83
+ *
84
+ */
85
+
71
86
  interface StackItemEx extends StackItem {
72
87
  page: Component;
73
88
  }
74
89
 
90
+ /**
91
+ *
92
+ */
93
+
75
94
  @class_ns( "x4" )
76
- export class StackBox extends Box<StackedLayoutProps> {
77
- private _items: StackItemEx[];
95
+ export class StackBox<P extends StackBoxProps = StackBoxProps, E extends StackeBoxEvents = StackeBoxEvents> extends Box<StackBoxProps,StackeBoxEvents> {
96
+
97
+ protected _items: StackItemEx[];
98
+ protected _cur: number;
78
99
 
79
- constructor( props: StackedLayoutProps ) {
100
+ constructor( props: StackBoxProps ) {
80
101
  super( props );
81
102
 
103
+ this.mapPropEvents( props, "pageChange" );
104
+
82
105
  this._items = props.items?.map( itm => {
83
106
  return { ...itm, page: null as any};
84
107
  });
@@ -105,7 +128,9 @@ export class StackBox extends Box<StackedLayoutProps> {
105
128
  sel.setClass( "selected", false );
106
129
  }
107
130
 
108
- const pg = this._items.find( x => x.name==name );
131
+ this._cur = this._items.findIndex( x => x.name==name );
132
+ const pg = this._items[this._cur];
133
+
109
134
  if( pg ) {
110
135
  if( !pg.page ) {
111
136
  pg.page = this._createPage( pg );
@@ -117,6 +142,8 @@ export class StackBox extends Box<StackedLayoutProps> {
117
142
  (sel as any).activate?.( );
118
143
  sel.setClass( "selected", true );
119
144
  }
145
+
146
+ asap( ( ) => this.fire( "pageChange", { selection: pg.name, empty: !sel } ) );
120
147
  }
121
148
 
122
149
  return pg?.page;
@@ -149,18 +176,68 @@ export class StackBox extends Box<StackedLayoutProps> {
149
176
  const pg = this._items.find( x => x.name==name );
150
177
  return pg ? pg.content : null;
151
178
  }
179
+
180
+ getItem( name: string ) {
181
+ const pg = this._items.find( x => x.name==name );
182
+ return pg;
183
+ }
184
+
185
+ /**
186
+ *
187
+ */
188
+
189
+ getCurPage( ) {
190
+ const c = this._items[this._cur];
191
+ return c?.name;
192
+ }
152
193
  }
153
194
 
195
+ // :: ASSIST BOX ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
196
+
197
+
198
+ @class_ns( "x4" )
199
+ export class AssistBox extends StackBox {
200
+ selectNextPage( nxt = true ) {
201
+ let p;
202
+ if( nxt && this._cur<this._items.length-1 ) {
203
+ p = this._items[this._cur+1];
204
+ }
205
+ else if( !nxt && this._cur>0 ) {
206
+ p = this._items[this._cur-1];
207
+ }
208
+
209
+ if( p ) {
210
+ this.select( p.name );
211
+ }
212
+ }
213
+
214
+ isFirstPage( ) {
215
+ return this._cur==0;
216
+ }
217
+
218
+ isLastPage( ) {
219
+ return this._cur==this._items.length-1;
220
+ }
221
+ }
222
+
223
+
224
+
154
225
  // :: GRIDBOX ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
155
226
 
227
+ interface GridBoxItem {
228
+ row: number; // starts at 0
229
+ col: number; // starts at 0
230
+ item: Component;
231
+ }
156
232
 
157
- export interface GridboxProps extends BoxProps {
233
+ export interface GridBoxProps extends Omit<BoxProps,"content"> {
158
234
  rows?: number | string | string[];
159
235
  columns?: number | string | string[];
236
+ items?: GridBoxItem[];
160
237
  }
161
238
 
162
239
  @class_ns("x4")
163
- export class GridBox<P extends GridboxProps=GridboxProps,E extends ComponentEvents=ComponentEvents> extends Box<P,E> {
240
+ export class GridBox<P extends GridBoxProps=GridBoxProps,E extends ComponentEvents=ComponentEvents> extends Box<P,E> {
164
241
 
165
242
  constructor( props: P ) {
166
243
  super( props );
@@ -172,6 +249,10 @@ export class GridBox<P extends GridboxProps=GridboxProps,E extends ComponentEven
172
249
  if( props.columns!==undefined ) {
173
250
  this.setCols( props.columns );
174
251
  }
252
+
253
+ if( props.items ) {
254
+ this.setItems( props.items );
255
+ }
175
256
  }
176
257
 
177
258
  setRows( r: number | string | string[] ) {
@@ -212,6 +293,17 @@ export class GridBox<P extends GridboxProps=GridboxProps,E extends ComponentEven
212
293
  setTemplate( t: string[] ) {
213
294
  this.setAttribute( "grid-template-area", t.map( x => '"' + x + '"' ).join(" ") );
214
295
  }
296
+
297
+ setItems( items: GridBoxItem[] ) {
298
+ items.forEach( x => {
299
+ x.item.setStyle( {
300
+ gridColumn: (x.col+1)+"",
301
+ gridRow: (x.row+1)+"",
302
+ } );
303
+ });
304
+
305
+ this.setContent( items.map( x => x.item ) );
306
+ }
215
307
  }
216
308
 
217
309
 
@@ -29,7 +29,7 @@ interface CanvasEventMap extends ComponentEvents {
29
29
  paint: EvPaint;
30
30
  }
31
31
 
32
- interface CanvasProps extends ComponentProps {
32
+ export interface CanvasProps extends ComponentProps {
33
33
  paint: EventCallback<EvPaint>
34
34
  clear?: boolean;
35
35
  }
@@ -14,6 +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 { Point } from "../../core/core_tools"
17
18
 
18
19
  export interface CanvasEx extends CanvasRenderingContext2D {
19
20
  width: number;
@@ -46,12 +47,17 @@ export function createPainter(c2d: CanvasRenderingContext2D, w: number, h: numbe
46
47
  return cp;
47
48
  }
48
49
 
50
+ /**
51
+ *
52
+ */
53
+
49
54
  function smoothLine( this: CanvasRenderingContext2D, points: any[], path: CanvasPath = null, move = true) {
50
55
  if (points.length < 2) {
51
56
  return;
52
57
  }
53
58
 
54
59
  if (!path) {
60
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
55
61
  path = this;
56
62
  }
57
63
 
@@ -67,14 +73,14 @@ function smoothLine( this: CanvasRenderingContext2D, points: any[], path: Canvas
67
73
  return;
68
74
  }
69
75
 
70
- function midPointBtw(p1: IPoint, p2: IPoint ) {
76
+ function midPointBtw(p1: Point, p2: Point ) {
71
77
  return {
72
78
  x: p1.x + (p2.x - p1.x) / 2,
73
79
  y: p1.y + (p2.y - p1.y) / 2
74
80
  };
75
81
  }
76
82
 
77
- function getQuadraticXY(t: number, sx: number, sy: number, cp1x: number, cp1y: number, ex: number, ey: number) : IPoint {
83
+ function getQuadraticXY(t: number, sx: number, sy: number, cp1x: number, cp1y: number, ex: number, ey: number) : Point {
78
84
  return {
79
85
  x: (1 - t) * (1 - t) * sx + 2 * (1 - t) * t * cp1x + t * t * ex,
80
86
  y: (1 - t) * (1 - t) * sy + 2 * (1 - t) * t * cp1y + t * t * ey
@@ -146,7 +152,7 @@ function smoothLineEx(this: CanvasRenderingContext2D, _points: any[], tension: n
146
152
 
147
153
  for (; i < numOfSeg; i++) {
148
154
 
149
- var st = i / numOfSeg,
155
+ const st = i / numOfSeg,
150
156
  st2 = st * st,
151
157
  st3 = st2 * st,
152
158
  st23 = st3 * 2,
@@ -173,9 +179,9 @@ function smoothLineEx(this: CanvasRenderingContext2D, _points: any[], tension: n
173
179
 
174
180
  function parse(pts: number[], cache: Float32Array, l: number) {
175
181
 
176
- for (var i = 2, t; i < l; i += 2) {
182
+ for (let i = 2, t; i < l; i += 2) {
177
183
 
178
- var pt1 = pts[i],
184
+ let pt1 = pts[i],
179
185
  pt2 = pts[i + 1],
180
186
  pt3 = pts[i + 2],
181
187
  pt4 = pts[i + 3],
@@ -187,7 +193,7 @@ function smoothLineEx(this: CanvasRenderingContext2D, _points: any[], tension: n
187
193
 
188
194
  for (t = 0; t < numOfSeg; t++) {
189
195
 
190
- var c = t << 2, //t * 4;
196
+ let c = t << 2, //t * 4;
191
197
 
192
198
  c1 = cache[c],
193
199
  c2 = cache[c + 1],
@@ -206,6 +212,7 @@ function smoothLineEx(this: CanvasRenderingContext2D, _points: any[], tension: n
206
212
  res[rPos] = points[l + 1];
207
213
 
208
214
  if (!path) {
215
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
209
216
  path = this;
210
217
  }
211
218
 
@@ -3,6 +3,7 @@ export * from "./breadcrumb/breadcrumb"
3
3
  export * from "./btngroup/btngroup"
4
4
  export * from "./button/button"
5
5
  export * from "./calendar/calendar"
6
+ export * from "./canvas/canvas"
6
7
  export * from "./checkbox/checkbox"
7
8
  export * from "./colorinput/colorinput"
8
9
  export * from "./colorpicker/colorpicker"
@@ -28,7 +29,6 @@ export * from "./progress/progress"
28
29
  export * from "./propgrid/propgrid"
29
30
  export * from "./radio/radio"
30
31
  export * from "./rating/rating"
31
- export * from "./tickline/tickline"
32
32
  export * from "./select/select"
33
33
  export * from "./sizers/sizer"
34
34
  export * from "./slider/slider"
@@ -36,6 +36,7 @@ export * from "./switch/switch"
36
36
  export * from "./tabs/tabs"
37
37
  export * from "./textarea/textarea"
38
38
  export * from "./textedit/textedit"
39
+ export * from "./tickline/tickline"
39
40
  export * from "./tooltips/tooltips"
40
41
  export * from "./treeview/treeview"
41
42
  export * from "./viewport/viewport"
@@ -27,9 +27,7 @@
27
27
  position: absolute !important;
28
28
  background-color: white;
29
29
  border: 1px solid var( --border-dark );
30
- min-width: min-content;
31
- min-height: min-content;
32
-
30
+
33
31
  &> .caption {
34
32
  padding: 8px;
35
33
  background-color: var(--color-dialog-caption);
@@ -52,9 +50,10 @@
52
50
  }
53
51
  }
54
52
 
55
- &> .form {
53
+ &> .x4form {
56
54
  min-height: 128px;
57
55
  min-width: 450px;
56
+ flex: 1;
58
57
  }
59
58
 
60
59
  &> #btnbar {
@@ -58,6 +58,7 @@ interface DialogEvents extends PopupEvents {
58
58
  export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents = DialogEvents> extends Popup<P, E> {
59
59
 
60
60
  private form: Form;
61
+ private _title: Label;
61
62
 
62
63
  constructor(props: P) {
63
64
  super({ tag: "dialog", modal: true, ...props });
@@ -70,7 +71,7 @@ export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents
70
71
  new HBox({
71
72
  cls: "caption",
72
73
  content: [
73
- new Label({
74
+ this._title = new Label({
74
75
  id: "title",
75
76
  cls: "caption-element",
76
77
  icon: props.icon,
@@ -187,7 +188,7 @@ export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents
187
188
  */
188
189
 
189
190
  getButton(name: string) {
190
- const btns = this.query<BtnGroup>("#btnbar");
191
+ const btns = this.getBtnBar( );
191
192
  return btns.getButton(name);
192
193
  }
193
194
 
@@ -207,6 +208,22 @@ export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents
207
208
 
208
209
  return super.queryInterface( name );
209
210
  }
211
+
212
+ /**
213
+ *
214
+ */
215
+
216
+ setTitle( title: string ) {
217
+ this._title.setText( title );
218
+ }
219
+
220
+ /**
221
+ *
222
+ */
223
+
224
+ getBtnBar( ) {
225
+ return this.query<BtnGroup>("#btnbar");
226
+ }
210
227
  }
211
228
 
212
229
 
@@ -69,7 +69,7 @@ export class Form<P extends FormProps = FormProps> extends Box<P> {
69
69
 
70
70
  if( ifx ) {
71
71
  const nme = x.getAttribute( "name" );
72
- if( values.hasOwnProperty( nme) ) {
72
+ if( Object.prototype.hasOwnProperty.call(values,nme) ) {
73
73
  ifx.setRawValue( values[nme] );
74
74
  }
75
75
  }
@@ -22,6 +22,7 @@
22
22
  min-width: 10px;
23
23
  height: 10px;
24
24
  overflow: hidden;
25
+ aspect-ratio: 1 / 1;
25
26
 
26
27
  svg {
27
28
  width: 100%;
@@ -48,7 +48,6 @@ class SvgLoader {
48
48
  this.waiters.set( file, [resolve] );
49
49
  this._load( file )
50
50
  .then( ( data: string ) => {
51
- console.timeEnd( file );
52
51
  this.cache.set( file, data );
53
52
  const ww = this.waiters.get( file );
54
53
  ww.forEach( cb => cb(data ) );
@@ -58,7 +57,6 @@ class SvgLoader {
58
57
  }
59
58
 
60
59
  private async _load( file: string ): Promise<string> {
61
- console.time( file );
62
60
  const res = await fetch( file );
63
61
  if( res.ok ) {
64
62
  return res.text( );
@@ -16,14 +16,17 @@
16
16
 
17
17
  import { EventCallback } from '@core/core_events.js';
18
18
  import { Component, ComponentEvent, ComponentProps, EvChange, EvFocus } from '../../core/component';
19
- import { class_ns, IComponentInterface, IFormElement, isString } from '../../core/core_tools.js';
19
+ import { class_ns, formatIntlDate, IComponentInterface, IFormElement, isString } from '../../core/core_tools.js';
20
20
 
21
21
  import "./input.module.scss"
22
22
 
23
23
  export interface BaseProps extends ComponentProps {
24
24
  name?: string;
25
25
  autofocus?: boolean;
26
-
26
+ required?: boolean;
27
+ readonly?: boolean;
28
+ placeholder?: string;
29
+
27
30
  focus?: EventCallback<EvFocus>;
28
31
  change?: EventCallback<EvChange>;
29
32
  }
@@ -36,54 +39,60 @@ interface CheckboxProps extends BaseProps {
36
39
 
37
40
  interface RadioProps extends BaseProps {
38
41
  type: "radio";
39
- value: boolean | number | string;
42
+ value?: boolean | number | string;
40
43
  checked?: boolean;
41
44
  }
42
45
 
43
46
  export interface RangeProps extends BaseProps {
44
47
  type: "range";
45
- value: number;
48
+ value?: number;
46
49
  min: number;
47
50
  max: number;
48
51
  step?: number;
49
52
  }
50
53
 
51
- interface DateProps extends BaseProps {
54
+ export interface FileProps extends BaseProps {
55
+ type: "file";
56
+ accept: string | string[];
57
+ value?: never;
58
+ }
59
+
60
+
61
+ export interface DateProps extends BaseProps {
52
62
  type: "date";
63
+ value?: Date | string;
64
+ }
65
+
66
+ export interface TimeProps extends BaseProps {
67
+ type: "time";
53
68
  readonly?: boolean;
54
69
  required?: boolean;
55
- value: Date | string;
70
+ value?: string;
56
71
  }
57
72
 
58
- interface NumberProps extends BaseProps {
73
+ export interface NumberProps extends BaseProps {
59
74
  type: "number";
60
75
  readonly?: boolean;
61
76
  required?: boolean;
62
- value: number | string;
77
+ value?: number | string;
63
78
  min?: number;
64
79
  max?: number;
65
80
  step?: number;
66
81
  }
67
82
 
68
- interface FileProps extends BaseProps {
69
- type: "file";
70
- accept: string | string[];
71
- }
72
-
73
83
  export interface TextInputProps extends BaseProps {
74
- type: "text" | "email" | "password" | "date" | "number";
84
+ type?: "text" | "email" | "password";
75
85
  readonly?: boolean;
76
86
  required?: boolean;
77
87
  pattern?: string;
78
88
  value?: string | number;
79
- placeholder?: string;
80
89
  spellcheck?: boolean;
81
90
  minlength?: number;
82
91
  maxlength?: number;
83
92
  }
84
93
 
85
94
 
86
- export type InputProps = CheckboxProps | RadioProps | TextInputProps | RangeProps | DateProps | NumberProps | FileProps;
95
+ export type InputProps = TextInputProps | CheckboxProps | RadioProps | RangeProps | DateProps | NumberProps | FileProps | TimeProps;
87
96
 
88
97
 
89
98
  interface InputEvents extends ComponentEvent {
@@ -131,7 +140,7 @@ export class Input extends Component<InputProps,InputEvents> {
131
140
 
132
141
  case "number": {
133
142
  const p = this.props as NumberProps;
134
-
143
+
135
144
  this.setAttribute( "required", p.required );
136
145
  this.setAttribute( "readonly", p.readonly );
137
146
  this.setAttribute( "min", p.min );
@@ -159,9 +168,9 @@ export class Input extends Component<InputProps,InputEvents> {
159
168
 
160
169
  let v = props.value;
161
170
  if( v instanceof Date ) {
162
- //this.setAttribute( "value", formatDate( v, "Y-M-D" ) );
171
+ this.setAttribute( "value", formatIntlDate( v, "Y-M-D" ) );
163
172
  }
164
- else {
173
+ else if( props.value!==null && props.value!==undefined ) {
165
174
  this.setAttribute( "value", v );
166
175
  }
167
176
 
@@ -181,6 +190,14 @@ export class Input extends Component<InputProps,InputEvents> {
181
190
  break;
182
191
  }
183
192
 
193
+ case "time": {
194
+ this.setAttribute( "required", props.required );
195
+ if( props.value!==null && props.value!==undefined ) {
196
+ this.setAttribute( "value", props.value );
197
+ }
198
+ break;
199
+ }
200
+
184
201
  default: {
185
202
  this.setAttribute( "required", props.required );
186
203
  this.setAttribute( "readonly", props.readonly );
@@ -267,8 +284,12 @@ export class Input extends Component<InputProps,InputEvents> {
267
284
  * @returns
268
285
  */
269
286
 
270
- public getNumValue( ) {
271
- return parseFloat( this.getValue() );
287
+ public getNumValue( defNan?: number ) {
288
+ const v = parseFloat( this.getValue() );
289
+ if( isNaN(v) && defNan!==undefined ) {
290
+ return defNan;
291
+ }
292
+ return v;
272
293
  }
273
294
 
274
295
  /**
@@ -283,10 +304,13 @@ export class Input extends Component<InputProps,InputEvents> {
283
304
  if( ndec==-2 && this.props.type=='number' ) {
284
305
  const p = this.props as NumberProps;
285
306
 
286
- if( p.step ) {
307
+ if( p.step<1 ) {
287
308
  let ndec = -Math.floor(Math.log10(p.step ?? 1) );
288
309
  return this.setValue( value.toFixed(ndec) );
289
310
  }
311
+ else if( p.step>1 ) {
312
+ return this.setValue( value.toFixed() );
313
+ }
290
314
  }
291
315
  else if( ndec>=0 ) {
292
316
  return this.setValue( value.toFixed(ndec) );