x4js 2.0.13 → 2.0.14

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 (258) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/README.md +5 -0
  3. package/{lib/src/demo → demo}/main.scss +3 -1
  4. package/{lib/src/demo/main.tsx → demo/main.ts} +37 -36
  5. package/demo/package.json +26 -0
  6. package/demo/scss.d.ts +4 -0
  7. package/demo/svg.d.ts +1 -0
  8. package/demo/tsconfig.json +14 -0
  9. package/lib/README.txt +5 -0
  10. package/lib/cjs/x4.css +1 -1
  11. package/lib/cjs/x4.js +2 -1
  12. package/lib/esm/x4.css +1 -1
  13. package/lib/esm/x4.mjs +2 -1
  14. package/lib/src/components/boxes/boxes.module.scss +17 -0
  15. package/lib/src/components/boxes/boxes.ts +162 -13
  16. package/lib/src/components/breadcrumb/breadcrumb.scss +56 -28
  17. package/lib/src/components/breadcrumb/breadcrumb.ts +93 -84
  18. package/lib/src/components/btngroup/btngroup.module.scss +12 -0
  19. package/lib/src/components/btngroup/btngroup.ts +41 -8
  20. package/lib/src/components/button/button.module.scss +23 -5
  21. package/lib/src/components/button/button.ts +72 -4
  22. package/lib/src/components/canvas/canvas.module.scss +25 -0
  23. package/lib/src/components/canvas/canvas.ts +189 -0
  24. package/lib/src/components/canvas/canvas_ex.ts +269 -0
  25. package/lib/src/components/checkbox/checkbox.ts +18 -4
  26. package/lib/src/components/combobox/combobox.module.scss +24 -15
  27. package/lib/src/components/combobox/combobox.ts +107 -24
  28. package/lib/src/components/components.ts +7 -0
  29. package/lib/src/components/dialog/dialog.module.scss +37 -3
  30. package/lib/src/components/dialog/dialog.ts +149 -31
  31. package/lib/src/components/filedrop/cloud-arrow-up.svg +1 -0
  32. package/lib/src/components/filedrop/filedrop.module.scss +70 -0
  33. package/lib/src/components/filedrop/filedrop.ts +131 -0
  34. package/lib/src/components/form/form.module.scss +4 -0
  35. package/lib/src/components/form/form.ts +137 -6
  36. package/lib/src/components/gridview/arrow-down-light.svg +1 -0
  37. package/lib/src/components/gridview/arrow-up-light.svg +1 -0
  38. package/lib/src/components/gridview/gridview.module.scss +324 -0
  39. package/lib/src/components/gridview/gridview.ts +1175 -0
  40. package/lib/src/components/icon/icon.module.scss +1 -1
  41. package/lib/src/components/icon/icon.ts +4 -1
  42. package/lib/src/components/image/image.module.scss +8 -1
  43. package/lib/src/components/image/image.ts +105 -6
  44. package/lib/src/components/input/input.module.scss +8 -3
  45. package/lib/src/components/input/input.ts +137 -14
  46. package/lib/src/components/keyboard/arrow-up.svg +1 -0
  47. package/lib/src/components/keyboard/delete-left.svg +1 -0
  48. package/lib/src/components/keyboard/eye-slash.svg +1 -0
  49. package/lib/src/components/keyboard/keyboard.module.scss +134 -0
  50. package/lib/src/components/keyboard/keyboard.ts +525 -0
  51. package/lib/src/components/label/label.module.scss +22 -4
  52. package/lib/src/components/label/label.ts +33 -0
  53. package/lib/src/components/link/link.ts +81 -78
  54. package/lib/src/components/listbox/listbox.module.scss +61 -3
  55. package/lib/src/components/listbox/listbox.ts +164 -56
  56. package/lib/src/components/menu/menu.module.scss +10 -1
  57. package/lib/src/components/menu/menu.ts +4 -1
  58. package/lib/src/components/messages/messages.module.scss +44 -0
  59. package/lib/src/components/messages/messages.ts +164 -18
  60. package/lib/src/components/messages/pen-field.svg +1 -0
  61. package/lib/src/components/normalize.scss +5 -0
  62. package/lib/src/components/notification/notification.module.scss +4 -2
  63. package/lib/src/components/notification/notification.ts +2 -4
  64. package/lib/src/components/panel/panel.module.scss +12 -0
  65. package/lib/src/components/popup/popup.module.scss +4 -2
  66. package/lib/src/components/popup/popup.ts +136 -92
  67. package/lib/src/components/propgrid/folder-closed.svg +1 -0
  68. package/lib/src/components/propgrid/folder-open.svg +1 -0
  69. package/lib/src/components/propgrid/progrid.module.scss +108 -0
  70. package/lib/src/components/propgrid/propgrid.ts +271 -0
  71. package/lib/src/components/propgrid/updown.svg +4 -0
  72. package/lib/src/components/radio/radio.module.scss +147 -0
  73. package/lib/src/components/radio/radio.svg +4 -0
  74. package/lib/src/components/radio/radio.ts +142 -0
  75. package/lib/src/components/select/select.module.scss +9 -0
  76. package/lib/src/components/select/select.ts +134 -0
  77. package/lib/src/components/shared.scss +47 -0
  78. package/lib/src/components/sizers/sizer.ts +9 -2
  79. package/lib/src/components/slider/slider.module.scss +77 -30
  80. package/lib/src/components/slider/slider.ts +72 -22
  81. package/lib/src/components/tabs/tabs.module.scss +1 -2
  82. package/lib/src/components/tabs/tabs.ts +43 -12
  83. package/lib/src/components/textarea/textarea.module.scss +6 -2
  84. package/lib/src/components/textarea/textarea.ts +73 -8
  85. package/lib/src/components/textedit/textedit.module.scss +3 -1
  86. package/lib/src/components/textedit/textedit.ts +31 -4
  87. package/lib/src/components/themes.scss +7 -0
  88. package/lib/src/components/tickline/tickline.module.scss +26 -0
  89. package/lib/src/components/tickline/tickline.ts +82 -0
  90. package/lib/src/components/tooltips/comments-question.svg +1 -0
  91. package/lib/src/components/tooltips/tooltips.scss +30 -9
  92. package/lib/src/components/tooltips/tooltips.ts +10 -5
  93. package/lib/src/components/treeview/treeview.module.scss +129 -60
  94. package/lib/src/components/treeview/treeview.ts +47 -12
  95. package/lib/src/components/viewport/viewport.module.scss +7 -0
  96. package/lib/src/core/component.ts +102 -32
  97. package/lib/src/core/core_application.ts +222 -2
  98. package/lib/src/core/core_colors.ts +2 -2
  99. package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +261 -250
  100. package/lib/src/core/core_dragdrop.ts +3 -3
  101. package/lib/src/core/core_element.ts +13 -1
  102. package/lib/src/core/core_events.ts +28 -0
  103. package/lib/src/core/core_i18n.ts +18 -2
  104. package/lib/src/core/core_react.ts +79 -0
  105. package/lib/src/core/core_router.ts +23 -7
  106. package/lib/src/core/core_styles.ts +5 -5
  107. package/lib/src/core/core_svg.ts +173 -12
  108. package/lib/src/core/core_tools.ts +305 -87
  109. package/lib/src/x4tsx.d.ts +25 -0
  110. package/lib/styles/x4.css +1 -1
  111. package/lib/types/x4js.d.ts +767 -92
  112. package/package.json +4 -4
  113. package/scripts/build.mjs +378 -0
  114. package/scripts/prepack.mjs +346 -0
  115. package/src/components/base.scss +25 -0
  116. package/src/components/boxes/boxes.module.scss +54 -0
  117. package/src/components/boxes/boxes.ts +278 -0
  118. package/src/components/breadcrumb/breadcrumb.scss +56 -0
  119. package/src/components/breadcrumb/breadcrumb.ts +93 -0
  120. package/src/components/breadcrumb/chevron-right.svg +1 -0
  121. package/src/components/btngroup/btngroup.module.scss +41 -0
  122. package/src/components/btngroup/btngroup.ts +153 -0
  123. package/src/components/button/button.module.scss +173 -0
  124. package/src/components/button/button.ts +185 -0
  125. package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  126. package/src/components/calendar/calendar.module.scss +163 -0
  127. package/src/components/calendar/calendar.ts +327 -0
  128. package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  129. package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  130. package/src/components/canvas/canvas.module.scss +25 -0
  131. package/src/components/canvas/canvas.ts +189 -0
  132. package/src/components/canvas/canvas_ex.ts +269 -0
  133. package/src/components/checkbox/check.svg +4 -0
  134. package/src/components/checkbox/checkbox.module.scss +142 -0
  135. package/src/components/checkbox/checkbox.ts +140 -0
  136. package/src/components/colorinput/colorinput.module.scss +65 -0
  137. package/src/components/colorinput/colorinput.ts +91 -0
  138. package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  139. package/src/components/colorpicker/colorpicker.module.scss +133 -0
  140. package/src/components/colorpicker/colorpicker.ts +482 -0
  141. package/src/components/combobox/combobox.module.scss +133 -0
  142. package/src/components/combobox/combobox.ts +275 -0
  143. package/src/components/combobox/updown.svg +4 -0
  144. package/src/components/components.ts +41 -0
  145. package/src/components/dialog/dialog.module.scss +105 -0
  146. package/src/components/dialog/dialog.ts +212 -0
  147. package/src/components/dialog/xmark-sharp-light.svg +1 -0
  148. package/src/components/filedrop/cloud-arrow-up.svg +1 -0
  149. package/src/components/filedrop/filedrop.module.scss +70 -0
  150. package/src/components/filedrop/filedrop.ts +131 -0
  151. package/src/components/form/form.module.scss +38 -0
  152. package/src/components/form/form.ts +172 -0
  153. package/src/components/gridview/arrow-down-light.svg +1 -0
  154. package/src/components/gridview/arrow-up-light.svg +1 -0
  155. package/src/components/gridview/gridview.module.scss +324 -0
  156. package/src/components/gridview/gridview.ts +1175 -0
  157. package/src/components/header/header.module.scss +40 -0
  158. package/src/components/header/header.ts +130 -0
  159. package/src/components/icon/icon.module.scss +30 -0
  160. package/src/components/icon/icon.ts +139 -0
  161. package/src/components/image/image.module.scss +28 -0
  162. package/src/components/image/image.ts +168 -0
  163. package/src/components/input/input.module.scss +74 -0
  164. package/src/components/input/input.ts +398 -0
  165. package/src/components/keyboard/arrow-up.svg +1 -0
  166. package/src/components/keyboard/delete-left.svg +1 -0
  167. package/src/components/keyboard/eye-slash.svg +1 -0
  168. package/src/components/keyboard/keyboard.module.scss +134 -0
  169. package/src/components/keyboard/keyboard.ts +525 -0
  170. package/src/components/label/label.module.scss +76 -0
  171. package/src/components/label/label.ts +97 -0
  172. package/src/components/link/link.ts +81 -0
  173. package/src/components/listbox/listbox.module.scss +161 -0
  174. package/src/components/listbox/listbox.ts +539 -0
  175. package/src/components/menu/caret-right-solid.svg +1 -0
  176. package/src/components/menu/menu.module.scss +117 -0
  177. package/src/components/menu/menu.ts +174 -0
  178. package/src/components/messages/circle-exclamation.svg +1 -0
  179. package/src/components/messages/messages.module.scss +92 -0
  180. package/src/components/messages/messages.ts +215 -0
  181. package/src/components/messages/pen-field.svg +1 -0
  182. package/src/components/normalize.scss +391 -0
  183. package/src/components/notification/circle-check-solid.svg +1 -0
  184. package/src/components/notification/circle-exclamation-solid.svg +1 -0
  185. package/src/components/notification/circle-notch-light.svg +1 -0
  186. package/src/components/notification/notification.module.scss +84 -0
  187. package/src/components/notification/notification.ts +107 -0
  188. package/src/components/notification/xmark-sharp-light.svg +1 -0
  189. package/src/components/panel/panel.module.scss +60 -0
  190. package/src/components/panel/panel.ts +58 -0
  191. package/src/components/popup/popup.module.scss +45 -0
  192. package/src/components/popup/popup.ts +440 -0
  193. package/src/components/progress/progress.module.scss +57 -0
  194. package/src/components/progress/progress.ts +44 -0
  195. package/src/components/propgrid/folder-closed.svg +1 -0
  196. package/src/components/propgrid/folder-open.svg +1 -0
  197. package/src/components/propgrid/progrid.module.scss +108 -0
  198. package/src/components/propgrid/propgrid.ts +271 -0
  199. package/src/components/propgrid/updown.svg +4 -0
  200. package/src/components/radio/radio.module.scss +147 -0
  201. package/src/components/radio/radio.svg +4 -0
  202. package/src/components/radio/radio.ts +142 -0
  203. package/src/components/rating/rating.module.scss +23 -0
  204. package/src/components/rating/rating.ts +131 -0
  205. package/src/components/rating/star-sharp-light.svg +1 -0
  206. package/src/components/rating/star-sharp-solid.svg +1 -0
  207. package/src/components/select/select.module.scss +9 -0
  208. package/src/components/select/select.ts +134 -0
  209. package/src/components/shared.scss +137 -0
  210. package/src/components/sizers/sizer.module.scss +90 -0
  211. package/src/components/sizers/sizer.ts +131 -0
  212. package/src/components/slider/slider.module.scss +118 -0
  213. package/src/components/slider/slider.ts +198 -0
  214. package/src/components/switch/switch.module.scss +127 -0
  215. package/src/components/switch/switch.ts +62 -0
  216. package/src/components/tabs/tabs.module.scss +45 -0
  217. package/src/components/tabs/tabs.ts +199 -0
  218. package/src/components/textarea/textarea.module.scss +63 -0
  219. package/src/components/textarea/textarea.ts +125 -0
  220. package/src/components/textedit/textedit.module.scss +116 -0
  221. package/src/components/textedit/textedit.ts +110 -0
  222. package/src/components/themes.scss +88 -0
  223. package/src/components/tickline/tickline.module.scss +26 -0
  224. package/src/components/tickline/tickline.ts +82 -0
  225. package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  226. package/src/components/tooltips/comments-question.svg +1 -0
  227. package/src/components/tooltips/tooltips.scss +72 -0
  228. package/src/components/tooltips/tooltips.ts +109 -0
  229. package/src/components/treeview/chevron-down-light.svg +1 -0
  230. package/src/components/treeview/treeview.module.scss +185 -0
  231. package/src/components/treeview/treeview.ts +445 -0
  232. package/src/components/viewport/viewport.module.scss +32 -0
  233. package/src/components/viewport/viewport.ts +41 -0
  234. package/src/core/component.ts +1072 -0
  235. package/src/core/core_application.ts +264 -0
  236. package/src/core/core_colors.ts +250 -0
  237. package/src/core/core_data.ts +1309 -0
  238. package/src/core/core_dom.ts +471 -0
  239. package/src/core/core_dragdrop.ts +201 -0
  240. package/src/core/core_element.ts +110 -0
  241. package/src/core/core_events.ts +177 -0
  242. package/src/core/core_i18n.ts +393 -0
  243. package/src/core/core_react.ts +79 -0
  244. package/src/core/core_router.ts +237 -0
  245. package/src/core/core_styles.ts +214 -0
  246. package/src/core/core_svg.ts +711 -0
  247. package/src/core/core_tools.ts +906 -0
  248. package/src/types/scss.d.ts +4 -0
  249. package/src/types/svg.d.ts +1 -0
  250. package/src/types/x4react.d.ts +9 -0
  251. package/src/x4.scss +19 -0
  252. package/src/x4tsx.d.ts +25 -0
  253. package/tsconfig.json +14 -0
  254. package/lib/src/components/grid/gridview.ts +0 -1108
  255. package/lib/src/components/grid/memdb.ts +0 -325
  256. /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
  257. /package/{lib/src/demo → demo}/assets/radio.svg +0 -0
  258. /package/{lib/src/demo → demo}/index.html +0 -0
@@ -26,6 +26,7 @@ interface CheckboxProps extends ComponentProps {
26
26
  label: string; // The text label for the checkbox.
27
27
  checked?: boolean; // Optional boolean indicating if the checkbox is checked by default.
28
28
  value?: boolean | number | string; // Optional value associated with the checkbox.
29
+ name?: string;
29
30
  change?: EventCallback<EvChange>;
30
31
  }
31
32
 
@@ -59,6 +60,7 @@ export class Checkbox extends Component<CheckboxProps,CheckBoxEvents> {
59
60
  this._input = new Input( {
60
61
  type:"checkbox",
61
62
  id: inputId,
63
+ name: props.name,
62
64
  checked: props.checked,
63
65
  dom_events: {
64
66
  change: ( ) => this._on_change( ),
@@ -77,6 +79,20 @@ export class Checkbox extends Component<CheckboxProps,CheckBoxEvents> {
77
79
  svgLoader.load( icon ).then( svg => {
78
80
  this.query<Label>( '.inner' ).dom.insertAdjacentHTML( "beforeend", svg );
79
81
  });
82
+
83
+ this.addDOMEvent('click', (e) => this._on_click(e)); // for outside click
84
+ }
85
+
86
+ /**
87
+ * handle click outside label & input
88
+ */
89
+
90
+ protected _on_click( ev: MouseEvent ) {
91
+ if( ev.target==this.dom ) {
92
+ (this._input.dom as HTMLInputElement).click( );
93
+ ev.preventDefault();
94
+ ev.stopPropagation();
95
+ }
80
96
  }
81
97
 
82
98
  /**
@@ -92,8 +108,7 @@ export class Checkbox extends Component<CheckboxProps,CheckBoxEvents> {
92
108
  */
93
109
 
94
110
  public getCheck() {
95
- const d = this._input.dom as HTMLInputElement;
96
- return d.checked;
111
+ return this._input.getCheck();
97
112
  }
98
113
 
99
114
  /**
@@ -102,8 +117,7 @@ export class Checkbox extends Component<CheckboxProps,CheckBoxEvents> {
102
117
  */
103
118
 
104
119
  public setCheck(ck: boolean) {
105
- const d = this._input.dom as HTMLInputElement;
106
- d.checked = ck;
120
+ this._input.setCheck( ck );
107
121
  }
108
122
 
109
123
  /**
@@ -28,7 +28,7 @@
28
28
  --combobox-btn-color-hover: var( --text-primary );
29
29
  }
30
30
 
31
- .x4dropdown {
31
+ .x4dropdownlist {
32
32
  @extend .shadow-xl;
33
33
  @extend .hbox;
34
34
 
@@ -44,35 +44,42 @@
44
44
  margin: 0;
45
45
  width: 100%;
46
46
  height: 200px;
47
+
48
+ .x4item {
49
+ white-space: nowrap;
50
+ }
47
51
  }
48
52
  }
49
53
 
50
54
  .x4combobox {
51
55
  @extend .hbox;
52
56
  margin: 5px;
57
+ gap: 6px;
53
58
 
54
- //&> #label {
55
- // padding: 0 6px;
56
- // border-bottom: 1px solid transparent;
57
-
59
+ &> #label {
60
+
58
61
  &> .x4label {
59
- padding: 0 6px;
62
+ padding: 0 6px 0 0;
60
63
  border-bottom: 1px solid transparent;
61
64
 
62
65
  height: 100%;
63
- padding: 0;
64
66
  font-weight: 500;
65
- gap: 0;
67
+ gap: 0px;
66
68
 
67
- #text::not(.empty)::after {
68
- content: ":"
69
+ #text:not(.empty) {
70
+ &::after {
71
+ content: ":"
72
+ }
69
73
  }
70
74
  }
71
- //}
75
+ }
72
76
 
73
77
  &>#edit {
74
78
  @extend .flex;
75
79
  border-bottom: 1px solid var( --combobox-border );
80
+ &:focus-within {
81
+ border-bottom-color: var( --combobox-border-focus );
82
+ }
76
83
 
77
84
  .x4input {
78
85
  @extend .flex;
@@ -97,10 +104,10 @@
97
104
  color: var( --combobox-btn-color-hover );
98
105
  }
99
106
 
100
- &:focus {
107
+ //&:focus {
101
108
  //background-color: var( --color-30 );
102
109
  //color: var( --color-10 );
103
- }
110
+ //}
104
111
  }
105
112
  }
106
113
 
@@ -116,9 +123,11 @@
116
123
  }
117
124
 
118
125
  &[required] {
119
- .x4label::before {
126
+ & > #label > .x4label::before {
120
127
  content: "*";
121
- color: var( --color-90 )
128
+ font-weight: bold;
129
+ color: var( --textedit-required );
130
+ margin-right: 2px;
122
131
  }
123
132
  }
124
133
  }
@@ -14,8 +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 { Component, ComponentEvent, ComponentProps, EvChange, EvSelectionChange, makeUniqueComponentId } from '../../core/component';
18
- import { Listbox, ListboxID, ListItem, kbNav } from '../listbox/listbox';
17
+ import { Component, ComponentEvents, ComponentProps, EvSelectionChange, makeUniqueComponentId } from '../../core/component';
18
+ import { class_ns, IComponentInterface, IFormElement, kbNav } from '@core/core_tools';
19
+ import { EventCallback } from '@core/core_events';
20
+
21
+ import { Listbox, ListboxID, ListItem } from '../listbox/listbox';
19
22
  import { Popup, PopupEvents, PopupProps } from '../popup/popup.js';
20
23
  import { Label } from '../label/label';
21
24
  import { Input } from '../input/input';
@@ -24,7 +27,6 @@ import { HBox } from '../boxes/boxes';
24
27
 
25
28
  import "./combobox.module.scss";
26
29
  import icon from "./updown.svg";
27
- import { class_ns } from '@core/core_tools.js';
28
30
 
29
31
 
30
32
 
@@ -37,8 +39,9 @@ interface DropdownProps extends Omit<PopupProps,"content"> {
37
39
  items: ListItem[];
38
40
  }
39
41
 
42
+
40
43
  @class_ns( "x4" )
41
- class Dropdown extends Popup<DropdownProps,DropdownEvents> {
44
+ export class DropdownList extends Popup<DropdownProps,DropdownEvents> {
42
45
 
43
46
  private _list: Listbox;
44
47
 
@@ -70,18 +73,26 @@ class Dropdown extends Popup<DropdownProps,DropdownEvents> {
70
73
  *
71
74
  */
72
75
 
76
+ interface ComboboxEvents extends ComponentEvents {
77
+ selectionChange: EvSelectionChange;
78
+ }
79
+
73
80
  interface ComboboxProps extends Omit<ComponentProps,"content"> {
74
81
  label?: string;
82
+ name?: string;
83
+ value?: string;
75
84
  labelWidth?: number | string;
76
85
  readonly?: boolean;
86
+ required?: boolean;
77
87
  items: ListItem[];
88
+ selectionChange?: EventCallback<EvSelectionChange>,
78
89
  }
79
90
 
80
91
  @class_ns( "x4" )
81
- export class Combobox extends Component<ComboboxProps> {
92
+ export class Combobox extends Component<ComboboxProps,ComboboxEvents> {
82
93
 
83
- private _dropdown: Dropdown;
84
- private _label: Label;
94
+ private _popup: DropdownList;
95
+ //private _label: Label;
85
96
  private _input: Input;
86
97
  private _button: Button;
87
98
  private _prevent_close = false;
@@ -92,25 +103,53 @@ export class Combobox extends Component<ComboboxProps> {
92
103
 
93
104
  const id = makeUniqueComponentId( );
94
105
 
106
+ this.mapPropEvents( props, "selectionChange" );
107
+
108
+ const readonly = props.readonly===false ? false : true; // by default
109
+
95
110
  this.setContent( [
96
111
  new HBox( { id: "label", content: new Label( { tag: "label", text: props.label, labelFor: id, width: props.labelWidth } ) } ),
97
112
  this._edit = new HBox( { id: "edit", content: [
98
- this._input = new Input( { type: "text", value: "", readonly: props.readonly }),
99
- this._button = new Button( { icon: icon } )
113
+ this._input = new Input( { id, type: "text", value: "", readonly: readonly, required: props.required }),
114
+ this._button = new Button( { icon: icon, tabindex: -1 } )
100
115
  ]} ),
101
116
  ])
102
117
 
103
- this._dropdown = new Dropdown( { items: props.items } );
118
+ if( props.name ) {
119
+ this.setAttribute( "name", props.name );
120
+ }
121
+
122
+ if( props.required ) {
123
+ this.setAttribute( "required", true );
124
+ }
125
+
126
+ this._popup = new DropdownList( { items: props.items } );
127
+ const list = this._popup.getList( );
128
+
129
+ const _select = ( sel: ListboxID ) => {
130
+ const itm = list.getItem(sel);
104
131
 
105
- this._dropdown.on( "selectionChange", ( ev ) => {
106
- const sel = ev.selection as ListItem;
107
- this._input.setValue( sel ? sel.text : "" );
132
+ //TODO: unsafehtml
133
+ //@ts-ignore
134
+ this._input.setValue( itm ? itm.text : "" );
108
135
 
109
136
  if( !this._prevent_close ) {
110
- this._dropdown.show( false );
137
+ this._popup.show( false );
138
+ }
139
+ }
140
+
141
+ this._popup.on( "selectionChange", ( ev ) => {
142
+ const [sel] = ev.selection as ListboxID[];
143
+ if( sel!==undefined ) { // no empty sel
144
+ _select( sel );
145
+ this.fire( "selectionChange", ev );
111
146
  }
112
147
  });
113
148
 
149
+ if( props.value ) {
150
+ _select( props.value );
151
+ }
152
+
114
153
  this._button.addDOMEvent( "click", ( ) => this._on_click( ) );
115
154
  this._input.addDOMEvent( "input", ( ) => this._on_input( ) );
116
155
  this._input.addDOMEvent( "keydown", ( ev ) => this._on_key( ev ) );
@@ -125,17 +164,17 @@ export class Combobox extends Component<ComboboxProps> {
125
164
  switch( ev.key ) {
126
165
  case "Enter":
127
166
  case "Escape": {
128
- this._dropdown.show( false );
167
+ this._popup.show( false );
129
168
  break;
130
169
  }
131
170
 
132
171
  case "ArrowUp":
133
172
  this._prevent_close = true;
134
- if( !this._dropdown.isOpen( ) ) {
173
+ if( !this._popup.isOpen( ) ) {
135
174
  this.showDropDown( );
136
175
  }
137
176
  else {
138
- this._dropdown.getList().navigate( kbNav.prev );
177
+ this._popup.getList().navigate( kbNav.prev );
139
178
  }
140
179
 
141
180
  this._prevent_close = false;
@@ -143,11 +182,11 @@ export class Combobox extends Component<ComboboxProps> {
143
182
 
144
183
  case "ArrowDown":
145
184
  this._prevent_close = true;
146
- if( !this._dropdown.isOpen( ) ) {
185
+ if( !this._popup.isOpen( ) ) {
147
186
  this.showDropDown( );
148
187
  }
149
188
  else {
150
- this._dropdown.getList().navigate( kbNav.next );
189
+ this._popup.getList().navigate( kbNav.next );
151
190
  }
152
191
 
153
192
  this._prevent_close = false;
@@ -163,15 +202,15 @@ export class Combobox extends Component<ComboboxProps> {
163
202
  }
164
203
 
165
204
  private _on_input( ) {
166
- if( !this._dropdown.isOpen( ) ) {
205
+ if( !this._popup.isOpen( ) ) {
167
206
  this.showDropDown( );
168
207
  }
169
208
 
170
- this._dropdown.getList().filter( this._input.getValue( ) );
209
+ this._popup.getList().filter( this._input.getValue( ) );
171
210
  }
172
211
 
173
212
  private _on_focusout( ) {
174
- this._dropdown.show( false );
213
+ this._popup.show( false );
175
214
  }
176
215
 
177
216
  private _on_click( ) {
@@ -184,8 +223,52 @@ export class Combobox extends Component<ComboboxProps> {
184
223
  }
185
224
 
186
225
  const rc = this._edit.getBoundingRect( );
187
- this._dropdown.setStyleValue( "width", rc.width+"px" );
188
- this._dropdown.displayNear( rc, "top left", "bottom left", {x:0,y:6} );
226
+ this._popup.setStyleValue( "minWidth", rc.width+"px" );
227
+ this._popup.displayNear( rc, "top left", "bottom left", {x:0,y:6} );
228
+ }
229
+
230
+ setItems( items: ListItem[] ) {
231
+ this._getList().setItems( items );
232
+ }
233
+
234
+ getValue( ) {
235
+ return this._input.getValue( );
236
+ }
237
+
238
+ setValue( value: string ) {
239
+ this._input.setValue( value );
240
+ }
241
+
242
+ selectItem( index: ListboxID ) {
243
+ this._getList( ).select( index );
244
+ }
245
+
246
+ getSelection( ) {
247
+ const [sel] = this._getList( ).getSelection( );
248
+ return sel;
249
+ }
250
+
251
+ private _getList( ) {
252
+ return this._popup.getList( );
253
+ }
254
+
255
+ /**
256
+ *
257
+ */
258
+
259
+ override queryInterface<T extends IComponentInterface>( name: string ): T {
260
+ if( name=="form-element" ) {
261
+ const i: IFormElement = {
262
+ getRawValue: ( ): any => { return this.getSelection(); },
263
+ setRawValue: ( v: any ) => { this.selectItem(v); },
264
+ isValid: ( ) => { return this._input.isValid(); }
265
+ };
266
+
267
+ //@ts-ignore
268
+ return i as T;
269
+ }
270
+
271
+ return super.queryInterface( name );
189
272
  }
190
273
  }
191
274
 
@@ -8,11 +8,14 @@ export * from "./colorinput/colorinput"
8
8
  export * from "./colorpicker/colorpicker"
9
9
  export * from "./combobox/combobox"
10
10
  export * from "./dialog/dialog"
11
+ export * from "./filedrop/filedrop"
11
12
  export * from "./form/form"
13
+ export * from "./gridview/gridview"
12
14
  export * from "./header/header"
13
15
  export * from "./icon/icon"
14
16
  export * from "./image/image"
15
17
  export * from "./input/input"
18
+ export * from "./keyboard/keyboard"
16
19
  export * from "./label/label"
17
20
  export * from "./link/link"
18
21
  export * from "./listbox/listbox"
@@ -22,7 +25,11 @@ export * from "./notification/notification"
22
25
  export * from "./panel/panel"
23
26
  export * from "./popup/popup"
24
27
  export * from "./progress/progress"
28
+ export * from "./propgrid/propgrid"
29
+ export * from "./radio/radio"
25
30
  export * from "./rating/rating"
31
+ export * from "./tickline/tickline"
32
+ export * from "./select/select"
26
33
  export * from "./sizers/sizer"
27
34
  export * from "./slider/slider"
28
35
  export * from "./switch/switch"
@@ -24,7 +24,7 @@
24
24
  .x4dialog {
25
25
  @extend .shadow-xl, .vbox;
26
26
 
27
- position: absolute;
27
+ position: absolute !important;
28
28
  background-color: white;
29
29
  border: 1px solid var( --border-dark );
30
30
  min-width: min-content;
@@ -38,6 +38,12 @@
38
38
  @extend .flex;
39
39
  color: var(--color-dialog-caption-text);
40
40
  font-weight: bold;
41
+ font-size: 120%;
42
+
43
+ #icon {
44
+ color: var(--color-dialog-caption-text);
45
+ fill: var(--color-dialog-caption-text);
46
+ }
41
47
  }
42
48
 
43
49
  & > #closebox {
@@ -52,8 +58,9 @@
52
58
  }
53
59
 
54
60
  &> #btnbar {
55
- border-top: 1px solid var( --color-separation );
56
- padding: 6px 16px;
61
+ border-top: 1px solid var( --border );
62
+ padding: 6px 20px;
63
+ margin: 0;
57
64
 
58
65
  justify-content: end;
59
66
  gap: 8px;
@@ -69,3 +76,30 @@
69
76
  }
70
77
  }
71
78
 
79
+
80
+ .x4dialog.danger {
81
+
82
+ &> .caption {
83
+ background-color: var( --alert-background );
84
+ color: var( --alert-color );
85
+
86
+ #closebox {
87
+ background-color: transparent;
88
+ color: var( --alert-color );
89
+ }
90
+ }
91
+
92
+ &> #btnbar {
93
+ &> .x4button:not(.outline) {
94
+ &:not(:disabled) {
95
+ background-color: var( --alert-background );
96
+ color: var( --alert-color );
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ .x4dialogex {
103
+ padding: 0;
104
+ margin: 0;
105
+ }
@@ -19,20 +19,25 @@ import { PopupEvents, PopupProps, Popup } from '../popup/popup.js';
19
19
  import { BtnGroup, BtnGroupItem } from "../btngroup/btngroup"
20
20
  import { HBox } from '../boxes/boxes.js';
21
21
  import { Label } from '../label/label.js';
22
- import { ComponentContent, ComponentEvent } from '../../core/component.js';
22
+ import { CoreEvent, EventCallback } from '@core/core_events.js';
23
+ import { class_ns, getFocusableElements, IComponentInterface, isString, ITabHandler } from '@core/core_tools.js';
24
+ import { ComponentEvent } from '../../core/component.js';
23
25
  import { Button } from '../button/button.js';
24
26
 
25
27
  import "./dialog.module.scss"
26
28
  import close_icon from "./xmark-sharp-light.svg";
27
- import { CoreEvent } from '@core/core_events.js';
28
- import { class_ns } from '@core/core_tools.js';
29
+
30
+
31
+ //let modal_stack: Popup[] = [];
29
32
 
30
33
  export interface DialogProps extends PopupProps {
31
34
  icon?: string;
32
35
  title: string;
33
- form: Form;
36
+ form?: Form;
34
37
  buttons: BtnGroupItem[];
35
- closable?: boolean;
38
+ closable?: boolean | string;
39
+ modal?: boolean;
40
+ btnclick?: EventCallback<EvBtnClick>;
36
41
  }
37
42
 
38
43
 
@@ -49,46 +54,159 @@ interface DialogEvents extends PopupEvents {
49
54
  *
50
55
  */
51
56
 
52
- @class_ns( "x4" )
53
- export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents = DialogEvents> extends Popup<P,E> {
57
+ @class_ns("x4")
58
+ export class Dialog<P extends DialogProps = DialogProps, E extends DialogEvents = DialogEvents> extends Popup<P, E> {
59
+
60
+ private form: Form;
61
+
62
+ constructor(props: P) {
63
+ super({ tag: "dialog", modal: true, ...props });
54
64
 
55
- constructor( props: P ) {
56
- super( props );
65
+ this._ismodal = this.props.modal;
57
66
 
58
- this.appendContent( [
59
- new HBox( {
67
+ this.mapPropEvents(props, "btnclick");
68
+
69
+ this.appendContent([
70
+ new HBox({
60
71
  cls: "caption",
61
72
  content: [
62
- new Label( {
63
- id: "title",
73
+ new Label({
74
+ id: "title",
64
75
  cls: "caption-element",
65
- icon: props.icon,
66
- text: props.title
67
- } ),
68
- props.closable ? new Button( {
69
- id: "closebox",
70
- icon: close_icon,
71
- click: ( ) => { this.close() }
72
- } ) : null,
76
+ icon: props.icon,
77
+ text: props.title
78
+ }),
79
+ props.closable ? new Button({
80
+ id: "closebox",
81
+ icon: close_icon,
82
+ tabindex: -1,
83
+ click: () => {
84
+ if( isString(props.closable) ) {
85
+ this.fire("btnclick", { button: props.closable } );
86
+ }
87
+ else {
88
+ this.close()
89
+ }
90
+ }
91
+ }) : null,
73
92
  ]
74
93
  }),
75
- props.form,
76
- new BtnGroup( {
94
+ this.form = props.form ? props.form : new Form({}),
95
+ new BtnGroup({
77
96
  id: "btnbar",
78
97
  reverse: true,
79
98
  items: props.buttons,
80
- btnclick: ( ev ) => { this.fire( "btnclick", ev ) }
81
- })
82
- ])
99
+ btnclick: (ev) => { this.fire("btnclick", ev) }
100
+ })
101
+ ]);
102
+
103
+ this.addDOMEvent("keydown", (ev) => {
104
+
105
+ if (ev.key == 'Escape') {
106
+ // todo cancel
107
+ ev.preventDefault();
108
+ ev.stopPropagation();
109
+ }
110
+ else if (ev.key == 'Enter') {
111
+ const def = this.query<Button>('button.default');
112
+ if (def) {
113
+ ev.preventDefault();
114
+ ev.stopPropagation();
115
+
116
+ def.click();
117
+ }
118
+ }
119
+ })
83
120
  }
84
121
 
85
- display( ) {
86
- super.displayCenter( );
122
+ private focusNext( next: boolean) : boolean {
123
+
124
+ const focusable = getFocusableElements( this.dom );
125
+
126
+ if (!focusable.length) {
127
+ return false;
128
+ }
129
+ else {
130
+ const first = focusable[0];
131
+ const last = focusable[focusable.length - 1];
132
+ const active = document.activeElement;
133
+
134
+ let newf: HTMLElement;
135
+ if (!next && active === first) {
136
+ newf = last as HTMLElement;
137
+ }
138
+ else if (next && active === last) {
139
+ newf = first as HTMLElement;
140
+ }
141
+ else {
142
+ const idx = focusable.indexOf(active);
143
+ if (!next) {
144
+ newf = focusable[idx - 1] as HTMLElement;
145
+ }
146
+ else {
147
+ newf = focusable[idx + 1] as HTMLElement
148
+ }
149
+ }
150
+
151
+ if (newf) {
152
+ newf.focus();
153
+ return true;
154
+ }
155
+
156
+ return false;
157
+ }
87
158
  }
88
159
 
89
- override close( ) {
90
- this.fire( "close", {} );
91
- super.close( );
160
+ /**
161
+ *
162
+ */
163
+
164
+ override setContent(form: Form) {
165
+ this.dom.replaceChild(this.form.dom, form.dom);
166
+ this.form = form;
167
+ }
168
+
169
+ /**
170
+ *
171
+ */
172
+
173
+ getForm() {
174
+ return this.form;
175
+ }
176
+
177
+ /**
178
+ *
179
+ */
180
+
181
+ getValues() {
182
+ return this.form.getValues();
183
+ }
184
+
185
+ /**
186
+ *
187
+ */
188
+
189
+ getButton(name: string) {
190
+ const btns = this.query<BtnGroup>("#btnbar");
191
+ return btns.getButton(name);
192
+ }
193
+
194
+ /**
195
+ *
196
+ */
197
+
198
+ override queryInterface<T extends IComponentInterface>( name: string ): T {
199
+ if( name=="tab-handler" ) {
200
+ const i: ITabHandler = {
201
+ focusNext: ( n: boolean ) => { return this.focusNext( n ); }
202
+ };
203
+
204
+ //@ts-ignore
205
+ return i as T;
206
+ }
207
+
208
+ return super.queryInterface( name );
92
209
  }
93
210
  }
94
211
 
212
+
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M144 480C64.5 480 0 415.5 0 336c0-62.8 40.2-116.2 96.2-135.9c-.1-2.7-.2-5.4-.2-8.1c0-88.4 71.6-160 160-160c59.3 0 111 32.2 138.7 80.2C409.9 102 428.3 96 448 96c53 0 96 43 96 96c0 12.2-2.3 23.8-6.4 34.6C596 238.4 640 290.1 640 352c0 70.7-57.3 128-128 128l-368 0zm79-217c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l39-39L296 392c0 13.3 10.7 24 24 24s24-10.7 24-24l0-134.1 39 39c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-80-80c-9.4-9.4-24.6-9.4-33.9 0l-80 80z"/></svg>