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.
Files changed (260) 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 +258 -17
  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 +276 -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 +40 -7
  30. package/lib/src/components/dialog/dialog.ts +166 -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 +2 -1
  41. package/lib/src/components/icon/icon.ts +4 -3
  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 +178 -31
  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 +526 -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 +6 -3
  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 +10 -2
  66. package/lib/src/components/popup/popup.ts +141 -95
  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 +112 -0
  70. package/lib/src/components/propgrid/propgrid.ts +288 -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 +10 -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 +49 -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 +47 -15
  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 +113 -40
  97. package/lib/src/core/core_application.ts +223 -2
  98. package/lib/src/core/core_colors.ts +2 -2
  99. package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +264 -252
  100. package/lib/src/core/core_dragdrop.ts +3 -3
  101. package/lib/src/core/core_element.ts +18 -1
  102. package/lib/src/core/core_events.ts +28 -0
  103. package/lib/src/core/core_i18n.ts +19 -3
  104. package/lib/src/core/core_react.ts +79 -0
  105. package/lib/src/core/core_router.ts +25 -9
  106. package/lib/src/core/core_state.ts +62 -0
  107. package/lib/src/core/core_styles.ts +5 -5
  108. package/lib/src/core/core_svg.ts +174 -12
  109. package/lib/src/core/core_tools.ts +305 -87
  110. package/lib/src/x4tsx.d.ts +25 -0
  111. package/lib/styles/x4.css +1 -1
  112. package/lib/types/x4js.d.ts +828 -119
  113. package/package.json +4 -4
  114. package/scripts/build.mjs +378 -0
  115. package/scripts/prepack.mjs +346 -0
  116. package/src/components/base.scss +25 -0
  117. package/src/components/boxes/boxes.module.scss +54 -0
  118. package/src/components/boxes/boxes.ts +370 -0
  119. package/src/components/breadcrumb/breadcrumb.scss +56 -0
  120. package/src/components/breadcrumb/breadcrumb.ts +93 -0
  121. package/src/components/breadcrumb/chevron-right.svg +1 -0
  122. package/src/components/btngroup/btngroup.module.scss +41 -0
  123. package/src/components/btngroup/btngroup.ts +153 -0
  124. package/src/components/button/button.module.scss +173 -0
  125. package/src/components/button/button.ts +185 -0
  126. package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  127. package/src/components/calendar/calendar.module.scss +163 -0
  128. package/src/components/calendar/calendar.ts +327 -0
  129. package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  130. package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  131. package/src/components/canvas/canvas.module.scss +25 -0
  132. package/src/components/canvas/canvas.ts +189 -0
  133. package/src/components/canvas/canvas_ex.ts +276 -0
  134. package/src/components/checkbox/check.svg +4 -0
  135. package/src/components/checkbox/checkbox.module.scss +142 -0
  136. package/src/components/checkbox/checkbox.ts +140 -0
  137. package/src/components/colorinput/colorinput.module.scss +65 -0
  138. package/src/components/colorinput/colorinput.ts +91 -0
  139. package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  140. package/src/components/colorpicker/colorpicker.module.scss +133 -0
  141. package/src/components/colorpicker/colorpicker.ts +482 -0
  142. package/src/components/combobox/combobox.module.scss +133 -0
  143. package/src/components/combobox/combobox.ts +275 -0
  144. package/src/components/combobox/updown.svg +4 -0
  145. package/src/components/components.ts +41 -0
  146. package/src/components/dialog/dialog.module.scss +104 -0
  147. package/src/components/dialog/dialog.ts +229 -0
  148. package/src/components/dialog/xmark-sharp-light.svg +1 -0
  149. package/src/components/filedrop/cloud-arrow-up.svg +1 -0
  150. package/src/components/filedrop/filedrop.module.scss +70 -0
  151. package/src/components/filedrop/filedrop.ts +131 -0
  152. package/src/components/form/form.module.scss +38 -0
  153. package/src/components/form/form.ts +172 -0
  154. package/src/components/gridview/arrow-down-light.svg +1 -0
  155. package/src/components/gridview/arrow-up-light.svg +1 -0
  156. package/src/components/gridview/gridview.module.scss +324 -0
  157. package/src/components/gridview/gridview.ts +1175 -0
  158. package/src/components/header/header.module.scss +40 -0
  159. package/src/components/header/header.ts +130 -0
  160. package/src/components/icon/icon.module.scss +31 -0
  161. package/src/components/icon/icon.ts +137 -0
  162. package/src/components/image/image.module.scss +28 -0
  163. package/src/components/image/image.ts +168 -0
  164. package/src/components/input/input.module.scss +74 -0
  165. package/src/components/input/input.ts +422 -0
  166. package/src/components/keyboard/arrow-up.svg +1 -0
  167. package/src/components/keyboard/delete-left.svg +1 -0
  168. package/src/components/keyboard/eye-slash.svg +1 -0
  169. package/src/components/keyboard/keyboard.module.scss +134 -0
  170. package/src/components/keyboard/keyboard.ts +526 -0
  171. package/src/components/label/label.module.scss +76 -0
  172. package/src/components/label/label.ts +97 -0
  173. package/src/components/link/link.ts +81 -0
  174. package/src/components/listbox/listbox.module.scss +161 -0
  175. package/src/components/listbox/listbox.ts +539 -0
  176. package/src/components/menu/caret-right-solid.svg +1 -0
  177. package/src/components/menu/menu.module.scss +117 -0
  178. package/src/components/menu/menu.ts +174 -0
  179. package/src/components/messages/circle-exclamation.svg +1 -0
  180. package/src/components/messages/messages.module.scss +92 -0
  181. package/src/components/messages/messages.ts +215 -0
  182. package/src/components/messages/pen-field.svg +1 -0
  183. package/src/components/normalize.scss +391 -0
  184. package/src/components/notification/circle-check-solid.svg +1 -0
  185. package/src/components/notification/circle-exclamation-solid.svg +1 -0
  186. package/src/components/notification/circle-notch-light.svg +1 -0
  187. package/src/components/notification/notification.module.scss +84 -0
  188. package/src/components/notification/notification.ts +107 -0
  189. package/src/components/notification/xmark-sharp-light.svg +1 -0
  190. package/src/components/panel/panel.module.scss +60 -0
  191. package/src/components/panel/panel.ts +58 -0
  192. package/src/components/popup/popup.module.scss +51 -0
  193. package/src/components/popup/popup.ts +442 -0
  194. package/src/components/progress/progress.module.scss +57 -0
  195. package/src/components/progress/progress.ts +44 -0
  196. package/src/components/propgrid/folder-closed.svg +1 -0
  197. package/src/components/propgrid/folder-open.svg +1 -0
  198. package/src/components/propgrid/progrid.module.scss +112 -0
  199. package/src/components/propgrid/propgrid.ts +288 -0
  200. package/src/components/propgrid/updown.svg +4 -0
  201. package/src/components/radio/radio.module.scss +147 -0
  202. package/src/components/radio/radio.svg +4 -0
  203. package/src/components/radio/radio.ts +142 -0
  204. package/src/components/rating/rating.module.scss +23 -0
  205. package/src/components/rating/rating.ts +131 -0
  206. package/src/components/rating/star-sharp-light.svg +1 -0
  207. package/src/components/rating/star-sharp-solid.svg +1 -0
  208. package/src/components/select/select.module.scss +9 -0
  209. package/src/components/select/select.ts +134 -0
  210. package/src/components/shared.scss +137 -0
  211. package/src/components/sizers/sizer.module.scss +90 -0
  212. package/src/components/sizers/sizer.ts +132 -0
  213. package/src/components/slider/slider.module.scss +118 -0
  214. package/src/components/slider/slider.ts +198 -0
  215. package/src/components/switch/switch.module.scss +127 -0
  216. package/src/components/switch/switch.ts +62 -0
  217. package/src/components/tabs/tabs.module.scss +45 -0
  218. package/src/components/tabs/tabs.ts +205 -0
  219. package/src/components/textarea/textarea.module.scss +63 -0
  220. package/src/components/textarea/textarea.ts +125 -0
  221. package/src/components/textedit/textedit.module.scss +116 -0
  222. package/src/components/textedit/textedit.ts +115 -0
  223. package/src/components/themes.scss +88 -0
  224. package/src/components/tickline/tickline.module.scss +26 -0
  225. package/src/components/tickline/tickline.ts +82 -0
  226. package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  227. package/src/components/tooltips/comments-question.svg +1 -0
  228. package/src/components/tooltips/tooltips.scss +72 -0
  229. package/src/components/tooltips/tooltips.ts +109 -0
  230. package/src/components/treeview/chevron-down-light.svg +1 -0
  231. package/src/components/treeview/treeview.module.scss +185 -0
  232. package/src/components/treeview/treeview.ts +445 -0
  233. package/src/components/viewport/viewport.module.scss +32 -0
  234. package/src/components/viewport/viewport.ts +41 -0
  235. package/src/core/component.ts +1075 -0
  236. package/src/core/core_application.ts +265 -0
  237. package/src/core/core_colors.ts +250 -0
  238. package/src/core/core_data.ts +1310 -0
  239. package/src/core/core_dom.ts +471 -0
  240. package/src/core/core_dragdrop.ts +201 -0
  241. package/src/core/core_element.ts +115 -0
  242. package/src/core/core_events.ts +177 -0
  243. package/src/core/core_i18n.ts +393 -0
  244. package/src/core/core_react.ts +79 -0
  245. package/src/core/core_router.ts +237 -0
  246. package/src/core/core_state.ts +62 -0
  247. package/src/core/core_styles.ts +214 -0
  248. package/src/core/core_svg.ts +712 -0
  249. package/src/core/core_tools.ts +906 -0
  250. package/src/types/scss.d.ts +4 -0
  251. package/src/types/svg.d.ts +1 -0
  252. package/src/types/x4react.d.ts +9 -0
  253. package/src/x4.scss +19 -0
  254. package/src/x4tsx.d.ts +25 -0
  255. package/tsconfig.json +14 -0
  256. package/lib/src/components/grid/gridview.ts +0 -1108
  257. package/lib/src/components/grid/memdb.ts +0 -325
  258. /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
  259. /package/{lib/src/demo → demo}/assets/radio.svg +0 -0
  260. /package/{lib/src/demo → demo}/index.html +0 -0
@@ -15,26 +15,20 @@
15
15
  **/
16
16
 
17
17
  import { Component, ComponentEvent, ComponentEvents, componentFromDOM, ComponentProps, EvChange, EvClick, EvContextMenu, EvDblClick, EvSelectionChange } from '../../core/component';
18
+ import { EventCallback } from '../../core/core_events.js';
19
+ import { kbNav, class_ns, isArray, UnsafeHtml } from '@core/core_tools.js';
18
20
 
19
21
  import { ScrollView, Viewport } from '../viewport/viewport';
20
22
  import { HBox } from '../boxes/boxes.js';
21
23
  import { Label } from '../label/label.js';
22
24
 
23
25
  import "./listbox.module.scss"
24
- import { class_ns } from '@core/core_tools.js';
25
-
26
- export enum kbNav {
27
- first,
28
- prev,
29
- next,
30
- last,
31
- }
32
26
 
33
27
  export type ListboxID = number | string;
34
28
 
35
29
  export interface ListItem {
36
30
  id: ListboxID;
37
- text: string;
31
+ text: string | UnsafeHtml;
38
32
 
39
33
  iconId?: string;
40
34
  data?: any;
@@ -46,7 +40,6 @@ export interface ListItem {
46
40
  *
47
41
  */
48
42
 
49
-
50
43
  interface ListboxEvents extends ComponentEvents {
51
44
  //change: EvChange;
52
45
  click?: EvClick;
@@ -63,7 +56,13 @@ interface ListboxProps extends Omit<ComponentProps,'content'> {
63
56
  items?: ListItem[];
64
57
  renderer?: ( item: ListItem ) => Component;
65
58
  //header?: Header;
59
+ footer?: Component,
66
60
  checkable?: true,
61
+ multisel?: true,
62
+
63
+ dblClick?: EventCallback<EvDblClick>;
64
+ selectionChange?: EventCallback<EvSelectionChange>;
65
+ contextMenu?: EventCallback<EvContextMenu>;
67
66
  }
68
67
 
69
68
  /**
@@ -74,8 +73,12 @@ interface ListboxProps extends Omit<ComponentProps,'content'> {
74
73
  export class Listbox extends Component<ListboxProps,ListboxEvents> {
75
74
 
76
75
  private _view: Viewport;
77
- private _selection: ListboxID;
78
- private _selitem: Component;
76
+ //private _selection: ListboxID;
77
+ //private _selitem: Component;
78
+
79
+ private _lastsel: ListboxID;
80
+
81
+ private _multisel: Set<ListboxID>;
79
82
  private _items: ListItem[];
80
83
 
81
84
  preventFocus = false;
@@ -84,13 +87,21 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
84
87
  super( { ...props } );
85
88
 
86
89
  this.setAttribute( "tabindex", 0 );
90
+ this.mapPropEvents( props, "dblClick", "selectionChange", "contextMenu" );
87
91
 
88
92
  const scroller = new ScrollView( { cls: "body" } );
89
93
  this._view = scroller.getViewport( );
94
+ this._multisel = new Set( );
95
+ this._items = [];
96
+
97
+ if( props.footer ) {
98
+ props.footer.setAttribute( "id", "footer" );
99
+ }
90
100
 
91
101
  this.setContent( [
92
102
  //props.header ? props.header : null,
93
103
  scroller,
104
+ props.footer,
94
105
  ] );
95
106
 
96
107
  this.setDOMEvents( {
@@ -149,7 +160,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
149
160
 
150
161
  navigate( sens: kbNav ) {
151
162
 
152
- if( !this._selitem ) {
163
+ if( !this._lastsel ) {
153
164
  if( sens==kbNav.next ) sens = kbNav.first;
154
165
  else sens = kbNav.last;
155
166
  }
@@ -168,18 +179,19 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
168
179
  fel = next_visible( fel, sens==kbNav.first );
169
180
 
170
181
  if( fel ) {
171
- const id = fel.getData( "id" );
172
- this._selectItem( id, fel );
182
+ const id = fel.getInternalData( "id" );
183
+ this._selectItem( id, fel, 'single' );
173
184
  return true;
174
185
  }
175
186
  }
176
187
  else {
177
- let nel = sens==kbNav.next ? this._selitem.nextElement() : this._selitem.prevElement();
188
+ const selitem = this._itemWithID( this._lastsel );
189
+ let nel = sens==kbNav.next ? selitem.nextElement() : selitem.prevElement();
178
190
  nel = next_visible( nel, sens==kbNav.next );
179
191
 
180
192
  if( nel ) {
181
- const id = nel.getData( "id" );
182
- this._selectItem( id, nel );
193
+ const id = nel.getInternalData( "id" );
194
+ this._selectItem( id, nel, 'single' );
183
195
  return true;
184
196
  }
185
197
  }
@@ -190,18 +202,31 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
190
202
  /**
191
203
  *
192
204
  */
193
-
194
- private _on_click( ev: UIEvent ) {
195
- ev.stopImmediatePropagation();
196
- ev.preventDefault( );
197
205
 
206
+ private _itemWithID( id: ListboxID ) {
207
+ //const itm = this.query( `[data-id="${id}"]` );
208
+ const all = this._view.enumChildComponents( false );
209
+ return all.find( x => x.getInternalData("id")===id )
210
+ }
211
+
212
+ /**
213
+ *
214
+ */
215
+
216
+ private _on_click( ev: MouseEvent ) {
198
217
  let target = ev.target as HTMLElement;
218
+
199
219
  while( target && target!=this.dom ) {
200
220
  const c = componentFromDOM( target );
221
+
222
+ // avoid trapping child ckick
223
+ if( c.dom.tagName==='INPUT' ) {
224
+ return;
225
+ }
226
+
201
227
  if( c && c.hasClass("x4item") ) {
202
- const id = c.getData( "id" );
228
+ const id = c.getInternalData( "id" );
203
229
  const fev: ComponentEvent = { context:id };
204
-
205
230
  if (ev.type == 'click') {
206
231
  this.fire('click', fev );
207
232
  }
@@ -210,7 +235,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
210
235
  }
211
236
 
212
237
  if (!fev.defaultPrevented) {
213
- this._selectItem( id, c );
238
+ this._selectItem( id, c, ev.ctrlKey ? 'toggle' : 'single' );
214
239
  }
215
240
 
216
241
  return;
@@ -220,6 +245,9 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
220
245
  }
221
246
 
222
247
  this.clearSelection( );
248
+
249
+ ev.stopImmediatePropagation();
250
+ ev.preventDefault( );
223
251
  }
224
252
 
225
253
  /**
@@ -234,9 +262,9 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
234
262
  while( target && target!=this.dom ) {
235
263
  const c = componentFromDOM( target );
236
264
  if( c && c.hasClass("x4item") ) {
237
- const id = c.getData( "id" );
265
+ const id = c.getInternalData( "id" );
238
266
 
239
- this._selectItem(id, c);
267
+ this._selectItem(id, c, 'single' );
240
268
  this.fire('contextMenu', {uievent: ev, context: id } );
241
269
 
242
270
  return;
@@ -252,35 +280,91 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
252
280
  *
253
281
  */
254
282
 
255
- private _selectItem( id: ListboxID, item: Component ) {
256
- if( this._selitem ) {
257
- this._selitem.removeClass( "selected" );
258
- this._selitem = undefined;
283
+ private _selectItem( id: ListboxID, item: Component, mode: "single" | "toggle" ) {
284
+
285
+ if( !this.props.multisel ) {
286
+ mode = 'single';
259
287
  }
260
288
 
261
- this._selitem = item;
262
- this._selection = id;
289
+ this._lastsel = id;
290
+
291
+ if( mode=='single' ) {
292
+ if( this._multisel.has(id) ) {
293
+ return;
294
+ }
263
295
 
296
+ this._clearSelection( );
297
+ if( item ) {
298
+ this._multisel.add( id );
299
+ item.addClass( "selected" );
300
+ }
301
+ }
302
+ else { // toggle
303
+ if( item ) {
304
+ if( this._multisel.has(id) ) {
305
+ item.removeClass( "selected" );
306
+ this._multisel.delete( id );
307
+ }
308
+ else {
309
+ this._multisel.add( id );
310
+ item.addClass( "selected" );
311
+ }
312
+ }
313
+ }
314
+
264
315
  if( item ) {
265
- item.addClass( "selected" );
266
316
  item.scrollIntoView( {
267
317
  behavior: "smooth",
268
318
  block: "nearest"
269
319
  } );
270
320
  }
271
321
 
272
- const itm = this._findItem( id );
273
- this.fire( "selectionChange", { selection: itm } );
322
+ this.fire( "selectionChange", { selection: this.getSelection(), empty: this._multisel.size==0 } );
274
323
  }
275
324
 
276
325
  /**
277
326
  *
278
327
  */
279
328
 
280
- private _findItem( id: ListboxID ) {
281
- return this._items.find( x => x.id==id );
329
+ getItem( id: ListboxID ): ListItem {
330
+ return this._items.find( x => x.id===id );
282
331
  }
283
332
 
333
+ /**
334
+ * select an item by it's id
335
+ */
336
+
337
+ select( ids: ListboxID | ListboxID[], notify = true ) {
338
+
339
+ if( !isArray(ids) ) {
340
+ ids = [ids];
341
+ }
342
+
343
+ if( !ids.length ) {
344
+ if( this._multisel.size ) {
345
+ this.clearSelection( );
346
+ }
347
+
348
+ return;
349
+ }
350
+
351
+ // if one of new selection not in old selection...
352
+ if( ids.some( x => !this._multisel.has(x)) ) {
353
+ this._clearSelection( );
354
+ const all = this._view.enumChildComponents( false );
355
+
356
+ ids.forEach( id => {
357
+ const itm = all.find( x => x.getInternalData("id")===id ); //this.query( `[data-id="${id}"]` );
358
+ if( itm ) {
359
+ this._multisel.add( id );
360
+ itm.addClass( "selected" );
361
+ }
362
+ });
363
+
364
+ this.fire( "selectionChange", { selection: this.getSelection(), empty: this._multisel.size==0 } );
365
+ }
366
+ }
367
+
284
368
  /**
285
369
  *
286
370
  */
@@ -293,29 +377,49 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
293
377
  *
294
378
  */
295
379
 
296
- clearSelection( ) {
297
- if( this._selitem ) {
298
- this._selitem.removeClass( "selected" );
299
- this._selitem = undefined;
380
+ private _clearSelection( ) {
381
+
382
+ const all = this._view.enumChildComponents( false );
383
+
384
+ if( this._multisel.size ) {
385
+ const ids = Array.from( this._multisel );
386
+ ids.forEach( id => {
387
+ const itm = all.find( x => x.getInternalData("id")===id ); //this.query( `[data-id="${id}"]` );
388
+ if( itm ) {
389
+ itm.removeClass( "selected" );
390
+ }
391
+ } );
300
392
  }
393
+
394
+ this._multisel.clear( );
395
+ }
301
396
 
302
- this._selection = undefined;
303
- this.fire( "selectionChange", { selection: undefined } );
397
+ clearSelection( ) {
398
+ if( this._multisel.size ) {
399
+ this._clearSelection( );
400
+ this.fire( "selectionChange", { selection: [], empty: true } );
401
+ }
304
402
  }
305
403
 
306
404
  /**
307
405
  *
308
406
  */
309
407
 
310
- setItems( items: ListItem[] ) {
408
+ setItems( items: ListItem[], keepSel = false ) {
409
+
410
+ const oldSel = this.getSelection( );
411
+
311
412
  this.clearSelection( );
312
-
313
413
  this._view.clearContent( );
314
414
  this._items = items;
315
415
 
316
416
  if( items ) {
317
417
  const content = items.map( x => this.renderItem(x) );
318
418
  this._view.setContent( content );
419
+
420
+ if( keepSel ) {
421
+ this.select( oldSel );
422
+ }
319
423
  }
320
424
  }
321
425
 
@@ -328,7 +432,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
328
432
  const line = renderer( item );
329
433
 
330
434
  line.addClass( "x4item" );
331
- line.setData( "id", item.id+"" );
435
+ line.setInternalData( "id", item.id );
332
436
 
333
437
  return line;
334
438
  }
@@ -362,7 +466,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
362
466
 
363
467
  // now hide all elements not in list
364
468
  childs.forEach( x => {
365
- x.show( filtred.includes( x.getData( "id" ) ) );
469
+ x.show( filtred.includes( x.getInternalData( "id" ) ) );
366
470
  });
367
471
  }
368
472
  }
@@ -377,7 +481,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
377
481
  appendItem( item: ListItem, prepend = false, select = true ) {
378
482
 
379
483
  if( select ) {
380
- this.clearSelection( );
484
+ this._clearSelection( );
381
485
  }
382
486
 
383
487
  let el = this.renderItem( item );
@@ -392,7 +496,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
392
496
  }
393
497
 
394
498
  if( select ) {
395
- this._selectItem( item.id, el );
499
+ this._selectItem( item.id, el, 'single' );
396
500
  }
397
501
  }
398
502
 
@@ -410,7 +514,7 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
410
514
 
411
515
  // take care of selection
412
516
  let was_sel = false;
413
- if( this._selection && this._selection===id ) {
517
+ if( this._multisel.has(id) ) {
414
518
  was_sel = true;
415
519
  }
416
520
 
@@ -418,14 +522,18 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
418
522
  this._items[idx] = item;
419
523
 
420
524
  // rebuild & replace it's line
421
- const oldDOM = this.query( `[data-id="${item.id}"]` )?.dom;
422
- if( oldDOM ) {
525
+ const old = this._itemWithID( item.id );
526
+ if( old?.dom ) {
423
527
  const _new = this.renderItem( item );
424
- this._view.dom.replaceChild( _new.dom, oldDOM );
425
-
426
528
  if( was_sel ) {
427
- this._selectItem( item.id, _new );
529
+ _new.addClass( "selected" );
428
530
  }
531
+
532
+ this._view.dom.replaceChild( _new.dom, old.dom );
429
533
  }
430
534
  }
535
+
536
+ getSelection( ) {
537
+ return Array.from( this._multisel );
538
+ }
431
539
  }
@@ -31,7 +31,7 @@
31
31
  @extend .shadow-lg;
32
32
 
33
33
  position: absolute;
34
- overflow-y: scroll;
34
+ overflow-y: auto;
35
35
 
36
36
  border-radius: var(--bradius);
37
37
  padding: 8px 0;
@@ -58,6 +58,15 @@
58
58
  #icon {
59
59
  width: 16px;
60
60
  height: 16px;
61
+
62
+ .fa-primary {
63
+ fill: var( --color-primary-a50 );
64
+ }
65
+
66
+ .fa-secondary {
67
+ fill: var( --color-primary-a30 );
68
+ opacity: 1;
69
+ }
61
70
  }
62
71
 
63
72
  #text {
@@ -38,7 +38,7 @@ export interface MenuItem {
38
38
  click?: DOMEventHandler;
39
39
  }
40
40
 
41
- type MenuElement = MenuItem | Component | string;
41
+ export type MenuElement = MenuItem | Component | string;
42
42
 
43
43
  export interface MenuProps extends Omit<PopupProps,"content"> {
44
44
  items: MenuElement[];
@@ -90,7 +90,10 @@ class CMenuItem extends Component {
90
90
  this.menu.on( "closed", ( ) => this.removeClass( "opened" ) );
91
91
  }
92
92
  else {
93
- this.addDOMEvent( "mouseenter", ( ) => { openTimer.setTimeout( "open", OPEN_DELAY, ( ) => {this.dismiss(true)}); } );
93
+ this.addDOMEvent( "mouseenter", ( ) => {
94
+ openTimer.setTimeout( "open", OPEN_DELAY, ( ) => {this.dismiss(true)});
95
+ } );
96
+
94
97
  this.addDOMEvent( "click", ( ) => {
95
98
  this.dismiss( false );
96
99
  if( itm.click ) {
@@ -146,7 +149,7 @@ class CMenuItem extends Component {
146
149
  export class Menu extends Popup {
147
150
 
148
151
  constructor( props: MenuProps ) {
149
- super( { ...props, autoClose: "menu", modal: false } );
152
+ super( { ...props, autoClose: "menu" } );
150
153
 
151
154
  this.addClass( "x4vbox" );
152
155
 
@@ -23,6 +23,7 @@
23
23
  }
24
24
 
25
25
  .x4messagebox {
26
+ max-width: 60vw;
26
27
 
27
28
  & > .caption {
28
29
  background-color: var( --msgbox-caption-background );
@@ -41,8 +42,51 @@
41
42
 
42
43
  .x4label {
43
44
  padding: 16px;
45
+ line-height: 1.8em;
44
46
  }
45
47
  }
46
48
  }
47
49
 
50
+ .x4inputbox,
51
+ .x4promptbox {
52
+ max-width: 60vw;
53
+
54
+ & > .caption {
55
+ background-color: var( --msgbox-caption-background );
56
+
57
+ & > #title {
58
+ color: var( --msgbox-caption-color );
59
+ }
60
+ }
61
+
62
+ & .x4form {
63
+ min-width: 400px;
64
+ .x4icon {
65
+ color: var( --msgbox-icon-color );
66
+ height: 64px;
67
+ }
68
+
69
+ .x4vbox {
70
+ padding: 16px;
71
+ gap: 16px;
72
+
73
+ .x4label {
74
+ line-height: 1.8em;
75
+ }
76
+
77
+ justify-content: center;
78
+ }
79
+ }
80
+
81
+ input {
82
+ padding: 8px;
83
+ border: 1px solid var( --border );
84
+
85
+ &:invalid {
86
+ border-color: var( --input-error );
87
+ }
88
+ }
89
+
90
+
91
+ }
48
92