x4js 1.6.4 → 2.0.1

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 (282) hide show
  1. package/README.md +3 -14
  2. package/lib/README.txt +3 -14
  3. package/lib/src/assets/house-light.svg +1 -0
  4. package/lib/src/assets/radio.svg +4 -0
  5. package/lib/src/components/base.scss +26 -0
  6. package/lib/src/components/boxes/boxes.module.scss +37 -0
  7. package/lib/src/components/boxes/boxes.ts +125 -0
  8. package/lib/src/components/btngroup/btngroup.module.scss +29 -0
  9. package/lib/src/components/btngroup/btngroup.ts +106 -0
  10. package/lib/src/components/button/button.module.scss +154 -0
  11. package/lib/src/components/button/button.ts +117 -0
  12. package/lib/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  13. package/lib/src/components/calendar/calendar.module.scss +163 -0
  14. package/lib/src/{calendar.ts → components/calendar/calendar.ts} +81 -83
  15. package/lib/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  16. package/lib/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  17. package/lib/src/components/checkbox/check.svg +4 -0
  18. package/lib/src/components/checkbox/checkbox.module.scss +142 -0
  19. package/lib/src/components/checkbox/checkbox.ts +125 -0
  20. package/lib/src/components/colorinput/colorinput.module.scss +65 -0
  21. package/lib/src/components/colorinput/colorinput.ts +88 -0
  22. package/lib/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  23. package/lib/src/components/colorpicker/colorpicker.module.scss +133 -0
  24. package/lib/src/components/colorpicker/colorpicker.ts +477 -0
  25. package/lib/src/components/combobox/combobox.module.scss +121 -0
  26. package/lib/src/components/combobox/combobox.ts +190 -0
  27. package/lib/src/components/combobox/updown.svg +4 -0
  28. package/lib/src/components/dialog/dialog.module.scss +71 -0
  29. package/lib/src/components/dialog/dialog.ts +91 -0
  30. package/lib/src/components/dialog/xmark-sharp-light.svg +1 -0
  31. package/lib/src/components/form/form.module.scss +34 -0
  32. package/lib/src/components/form/form.ts +36 -0
  33. package/lib/src/components/header/header.module.scss +40 -0
  34. package/lib/src/components/header/header.ts +124 -0
  35. package/lib/src/components/icon/icon.module.scss +30 -0
  36. package/lib/src/components/icon/icon.ts +134 -0
  37. package/lib/src/components/image/image.module.scss +21 -0
  38. package/lib/src/components/image/image.ts +67 -0
  39. package/lib/src/components/input/input.module.scss +69 -0
  40. package/lib/src/components/input/input.ts +274 -0
  41. package/lib/src/components/label/label.module.scss +52 -0
  42. package/lib/src/components/label/label.ts +55 -0
  43. package/lib/src/components/listbox/listbox.module.scss +103 -0
  44. package/lib/src/components/listbox/listbox.ts +427 -0
  45. package/lib/src/components/menu/caret-right-solid.svg +1 -0
  46. package/lib/src/components/menu/menu.module.scss +108 -0
  47. package/lib/src/components/menu/menu.ts +168 -0
  48. package/lib/src/components/messages/circle-exclamation.svg +1 -0
  49. package/lib/src/components/messages/messages.module.scss +47 -0
  50. package/lib/src/components/messages/messages.ts +64 -0
  51. package/lib/src/components/normalize.scss +386 -0
  52. package/lib/src/components/notification/circle-check-solid.svg +1 -0
  53. package/lib/src/components/notification/circle-exclamation-solid.svg +1 -0
  54. package/lib/src/components/notification/circle-notch-light.svg +1 -0
  55. package/lib/src/components/notification/notification.module.scss +82 -0
  56. package/lib/src/components/notification/notification.ts +108 -0
  57. package/lib/src/components/notification/xmark-sharp-light.svg +1 -0
  58. package/lib/src/components/panel/panel.module.scss +48 -0
  59. package/lib/src/components/panel/panel.ts +57 -0
  60. package/lib/src/components/popup/popup.module.scss +43 -0
  61. package/lib/src/components/popup/popup.ts +395 -0
  62. package/lib/src/components/progress/progress.module.scss +57 -0
  63. package/lib/src/components/progress/progress.ts +43 -0
  64. package/lib/src/components/rating/rating.module.scss +23 -0
  65. package/lib/src/components/rating/rating.ts +125 -0
  66. package/lib/src/components/rating/star-sharp-light.svg +1 -0
  67. package/lib/src/components/rating/star-sharp-solid.svg +1 -0
  68. package/lib/src/components/shared.scss +76 -0
  69. package/lib/src/components/sizers/sizer.module.scss +90 -0
  70. package/lib/src/components/sizers/sizer.ts +120 -0
  71. package/lib/src/components/slider/slider.module.scss +71 -0
  72. package/lib/src/components/slider/slider.ts +143 -0
  73. package/lib/src/components/switch/switch.module.scss +127 -0
  74. package/lib/src/components/switch/switch.ts +56 -0
  75. package/lib/src/components/tabs/tabs.module.scss +46 -0
  76. package/lib/src/components/tabs/tabs.ts +157 -0
  77. package/lib/src/components/textarea/textarea.module.scss +59 -0
  78. package/lib/src/components/textarea/textarea.ts +54 -0
  79. package/lib/src/components/textedit/textedit.module.scss +114 -0
  80. package/lib/src/components/textedit/textedit.ts +82 -0
  81. package/lib/src/components/themes.scss +77 -0
  82. package/lib/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  83. package/lib/src/components/tooltips/tooltips.scss +51 -0
  84. package/lib/src/components/tooltips/tooltips.ts +103 -0
  85. package/lib/src/components/treeview/chevron-down-light.svg +1 -0
  86. package/lib/src/components/treeview/treeview.module.scss +116 -0
  87. package/lib/src/components/treeview/treeview.ts +403 -0
  88. package/lib/src/components/viewport/viewport.module.scss +25 -0
  89. package/lib/src/components/viewport/viewport.ts +38 -0
  90. package/lib/src/core/component.ts +979 -0
  91. package/lib/src/core/core_colors.ts +250 -0
  92. package/lib/src/{dom_events.ts → core/core_dom.ts} +195 -39
  93. package/lib/src/{drag_manager.ts → core/core_dragdrop.ts} +29 -44
  94. package/lib/src/core/core_element.ts +98 -0
  95. package/lib/src/core/core_events.ts +149 -0
  96. package/lib/src/{i18n.ts → core/core_i18n.ts} +43 -42
  97. package/lib/src/{router.ts → core/core_router.ts} +27 -40
  98. package/lib/src/core/core_styles.ts +215 -0
  99. package/lib/src/core/core_svg.ts +550 -0
  100. package/lib/src/core/core_tools.ts +673 -0
  101. package/lib/src/main.scss +21 -0
  102. package/lib/src/main.tsx +323 -0
  103. package/lib/src/x4.scss +19 -0
  104. package/lib/types/x4.d.ts +2624 -0
  105. package/package.json +67 -59
  106. package/scripts/build.mjs +351 -0
  107. package/scripts/prepack.mjs +15 -0
  108. package/src/assets/house-light.svg +1 -0
  109. package/src/assets/radio.svg +4 -0
  110. package/src/components/base.scss +26 -0
  111. package/src/components/boxes/boxes.module.scss +37 -0
  112. package/src/components/boxes/boxes.ts +125 -0
  113. package/src/components/btngroup/btngroup.module.scss +29 -0
  114. package/src/components/btngroup/btngroup.ts +106 -0
  115. package/src/components/button/button.module.scss +154 -0
  116. package/src/components/button/button.ts +117 -0
  117. package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  118. package/src/components/calendar/calendar.module.scss +163 -0
  119. package/src/components/calendar/calendar.ts +326 -0
  120. package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  121. package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  122. package/src/components/checkbox/check.svg +4 -0
  123. package/src/components/checkbox/checkbox.module.scss +142 -0
  124. package/src/components/checkbox/checkbox.ts +125 -0
  125. package/src/components/colorinput/colorinput.module.scss +65 -0
  126. package/src/components/colorinput/colorinput.ts +88 -0
  127. package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  128. package/src/components/colorpicker/colorpicker.module.scss +133 -0
  129. package/src/components/colorpicker/colorpicker.ts +477 -0
  130. package/src/components/combobox/combobox.module.scss +121 -0
  131. package/src/components/combobox/combobox.ts +190 -0
  132. package/src/components/combobox/updown.svg +4 -0
  133. package/src/components/dialog/dialog.module.scss +71 -0
  134. package/src/components/dialog/dialog.ts +91 -0
  135. package/src/components/dialog/xmark-sharp-light.svg +1 -0
  136. package/src/components/form/form.module.scss +34 -0
  137. package/src/components/form/form.ts +36 -0
  138. package/src/components/header/header.module.scss +40 -0
  139. package/src/components/header/header.ts +124 -0
  140. package/src/components/icon/icon.module.scss +30 -0
  141. package/src/components/icon/icon.ts +134 -0
  142. package/src/components/image/image.module.scss +21 -0
  143. package/src/components/image/image.ts +67 -0
  144. package/src/components/input/input.module.scss +69 -0
  145. package/src/components/input/input.ts +274 -0
  146. package/src/components/label/label.module.scss +52 -0
  147. package/src/components/label/label.ts +55 -0
  148. package/src/components/listbox/listbox.module.scss +103 -0
  149. package/src/components/listbox/listbox.ts +427 -0
  150. package/src/components/menu/caret-right-solid.svg +1 -0
  151. package/src/components/menu/menu.module.scss +108 -0
  152. package/src/components/menu/menu.ts +168 -0
  153. package/src/components/messages/circle-exclamation.svg +1 -0
  154. package/src/components/messages/messages.module.scss +47 -0
  155. package/src/components/messages/messages.ts +64 -0
  156. package/src/components/normalize.scss +386 -0
  157. package/src/components/notification/circle-check-solid.svg +1 -0
  158. package/src/components/notification/circle-exclamation-solid.svg +1 -0
  159. package/src/components/notification/circle-notch-light.svg +1 -0
  160. package/src/components/notification/notification.module.scss +82 -0
  161. package/src/components/notification/notification.ts +108 -0
  162. package/src/components/notification/xmark-sharp-light.svg +1 -0
  163. package/src/components/panel/panel.module.scss +48 -0
  164. package/src/components/panel/panel.ts +57 -0
  165. package/src/components/popup/popup.module.scss +43 -0
  166. package/src/components/popup/popup.ts +395 -0
  167. package/src/components/progress/progress.module.scss +57 -0
  168. package/src/components/progress/progress.ts +43 -0
  169. package/src/components/rating/rating.module.scss +23 -0
  170. package/src/components/rating/rating.ts +125 -0
  171. package/src/components/rating/star-sharp-light.svg +1 -0
  172. package/src/components/rating/star-sharp-solid.svg +1 -0
  173. package/src/components/shared.scss +76 -0
  174. package/src/components/sizers/sizer.module.scss +90 -0
  175. package/src/components/sizers/sizer.ts +120 -0
  176. package/src/components/slider/slider.module.scss +71 -0
  177. package/src/components/slider/slider.ts +143 -0
  178. package/src/components/switch/switch.module.scss +127 -0
  179. package/src/components/switch/switch.ts +56 -0
  180. package/src/components/tabs/tabs.module.scss +46 -0
  181. package/src/components/tabs/tabs.ts +157 -0
  182. package/src/components/textarea/textarea.module.scss +59 -0
  183. package/src/components/textarea/textarea.ts +54 -0
  184. package/src/components/textedit/textedit.module.scss +114 -0
  185. package/src/components/textedit/textedit.ts +82 -0
  186. package/src/components/themes.scss +77 -0
  187. package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  188. package/src/components/tooltips/tooltips.scss +51 -0
  189. package/src/components/tooltips/tooltips.ts +103 -0
  190. package/src/components/treeview/chevron-down-light.svg +1 -0
  191. package/src/components/treeview/treeview.module.scss +116 -0
  192. package/src/components/treeview/treeview.ts +403 -0
  193. package/src/components/viewport/viewport.module.scss +25 -0
  194. package/src/components/viewport/viewport.ts +38 -0
  195. package/src/core/component.ts +979 -0
  196. package/src/core/core_colors.ts +250 -0
  197. package/src/core/core_dom.ts +471 -0
  198. package/src/core/core_dragdrop.ts +201 -0
  199. package/src/core/core_element.ts +98 -0
  200. package/src/core/core_events.ts +149 -0
  201. package/src/core/core_i18n.ts +377 -0
  202. package/src/core/core_router.ts +221 -0
  203. package/src/core/core_styles.ts +215 -0
  204. package/src/core/core_svg.ts +550 -0
  205. package/src/core/core_tools.ts +673 -0
  206. package/src/main.scss +21 -0
  207. package/src/main.tsx +323 -0
  208. package/src/x4.scss +19 -0
  209. package/tsconfig.json +14 -0
  210. package/types/scss.d.ts +4 -0
  211. package/types/svg.d.ts +4 -0
  212. package/types/x4react.d.ts +9 -0
  213. package/lib/changelog.txt +0 -23
  214. package/lib/cjs/x4js.js +0 -39
  215. package/lib/cjs/x4js.js.map +0 -7
  216. package/lib/esm/x4js.mjs +0 -15972
  217. package/lib/esm/x4js.mjs.map +0 -7
  218. package/lib/licence.md +0 -21
  219. package/lib/src/MIT-license.md +0 -14
  220. package/lib/src/action.ts +0 -88
  221. package/lib/src/alpha.jpg +0 -0
  222. package/lib/src/app_sockets.ts +0 -81
  223. package/lib/src/application.ts +0 -262
  224. package/lib/src/autocomplete.ts +0 -232
  225. package/lib/src/base64.ts +0 -166
  226. package/lib/src/base_component.ts +0 -152
  227. package/lib/src/button.ts +0 -355
  228. package/lib/src/canvas.ts +0 -510
  229. package/lib/src/cardview.ts +0 -228
  230. package/lib/src/checkbox.ts +0 -188
  231. package/lib/src/color.ts +0 -752
  232. package/lib/src/colorpicker.ts +0 -1649
  233. package/lib/src/combobox.ts +0 -512
  234. package/lib/src/component.ts +0 -2367
  235. package/lib/src/copyright.txt +0 -27
  236. package/lib/src/datastore.ts +0 -1302
  237. package/lib/src/dialog.ts +0 -656
  238. package/lib/src/drawtext.ts +0 -355
  239. package/lib/src/fileupload.ts +0 -213
  240. package/lib/src/form.ts +0 -413
  241. package/lib/src/formatters.ts +0 -105
  242. package/lib/src/gridview.ts +0 -1185
  243. package/lib/src/icon.ts +0 -362
  244. package/lib/src/image.ts +0 -225
  245. package/lib/src/index.ts +0 -89
  246. package/lib/src/input.ts +0 -297
  247. package/lib/src/label.ts +0 -153
  248. package/lib/src/layout.ts +0 -442
  249. package/lib/src/link.ts +0 -86
  250. package/lib/src/listview.ts +0 -765
  251. package/lib/src/md5.ts +0 -438
  252. package/lib/src/menu.ts +0 -425
  253. package/lib/src/messagebox.ts +0 -224
  254. package/lib/src/panel.ts +0 -86
  255. package/lib/src/popup.ts +0 -494
  256. package/lib/src/property_editor.ts +0 -337
  257. package/lib/src/radiobtn.ts +0 -197
  258. package/lib/src/rating.ts +0 -135
  259. package/lib/src/request.ts +0 -300
  260. package/lib/src/settings.ts +0 -77
  261. package/lib/src/sidebarview.ts +0 -108
  262. package/lib/src/spreadsheet.ts +0 -1449
  263. package/lib/src/styles.ts +0 -343
  264. package/lib/src/svgcomponent.ts +0 -592
  265. package/lib/src/tabbar.ts +0 -151
  266. package/lib/src/tabview.ts +0 -110
  267. package/lib/src/textarea.ts +0 -235
  268. package/lib/src/textedit.ts +0 -533
  269. package/lib/src/toaster.ts +0 -80
  270. package/lib/src/tools.ts +0 -1473
  271. package/lib/src/tooltips.ts +0 -191
  272. package/lib/src/treeview.ts +0 -716
  273. package/lib/src/version.ts +0 -30
  274. package/lib/src/x4.less +0 -2242
  275. package/lib/src/x4dom.ts +0 -57
  276. package/lib/src/x4events.ts +0 -585
  277. package/lib/src/x4js.ts +0 -89
  278. package/lib/src/x4react.ts +0 -90
  279. package/lib/styles/x4.css +0 -1785
  280. package/lib/styles/x4.less +0 -2242
  281. package/lib/types/x4js.d.ts +0 -6728
  282. package/license.md +0 -21
@@ -0,0 +1,477 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file colorpicker.ts
9
+ * @author Etienne Cochard
10
+ *
11
+ * @copyright (c) 2024 R-libre ingenierie
12
+ *
13
+ * Use of this source code is governed by an MIT-style license
14
+ * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
+ **/
16
+
17
+ import { Color, Hsv } from '@core/core_colors';
18
+ import { Rect, clamp, isFeatureAvailable } from '@core/core_tools';
19
+
20
+ import { Component, ComponentEvent, ComponentEvents, ComponentProps } from '@core/component';
21
+ import { Box, BoxProps, HBox, VBox } from '../boxes/boxes';
22
+
23
+ import "./colorpicker.module.scss"
24
+
25
+ interface ColorPickerProps extends ComponentProps {
26
+ color: string | Color;
27
+ }
28
+
29
+ interface HueChangeEvent extends ComponentEvent {
30
+ hue: number;
31
+ }
32
+
33
+ interface AlphaChangeEvent extends ComponentEvent {
34
+ alpha: number;
35
+ }
36
+
37
+ interface SatChangeEvent extends ComponentEvent {
38
+ saturation: number;
39
+ value: number;
40
+ }
41
+
42
+ interface CommonEvents extends ComponentEvents {
43
+ hue_change: HueChangeEvent;
44
+ alpha_change: AlphaChangeEvent;
45
+ sat_change: SatChangeEvent;
46
+ }
47
+
48
+ /**
49
+ *
50
+ */
51
+
52
+ export class Saturation extends Box<BoxProps,CommonEvents> {
53
+
54
+ private mdown = false;
55
+ private irect: Rect;
56
+
57
+ private hsv: Hsv = { hue: 1, saturation: 1, value: 1, alpha: 1 };
58
+
59
+ private color: Component;
60
+ private thumb: Component;
61
+
62
+ constructor( props: BoxProps, init: Hsv ) {
63
+ super( props );
64
+
65
+ this.setContent( [
66
+ this.color = new Component( { cls: "overlay" } ),
67
+ new Component( { cls: "overlay", style: { backgroundImage: "linear-gradient(90deg, rgb(255, 255, 255), transparent)" } } ),
68
+ new Component( { cls: "overlay", style: { backgroundImage: "linear-gradient(0deg, rgb(0, 0, 0), transparent)" } } ),
69
+ this.thumb = new Component( { cls: "thumb" } ),
70
+ ]);
71
+
72
+ this.setDOMEvents( {
73
+ pointerdown: ( e ) => this.mousedown( e ),
74
+ pointermove: ( e ) => this.mousemove( e ),
75
+ pointerup: ( e ) => this.mouseup( e ),
76
+ created: () => this.updateThumbMarker( ),
77
+ } );
78
+
79
+ this.updateBaseColor( init );
80
+ }
81
+
82
+ mousedown( ev: PointerEvent ) {
83
+ this.mdown = true;
84
+ this.irect = this.getBoundingRect( );
85
+ this.setCapture( ev.pointerId );
86
+ }
87
+
88
+ mousemove( ev: PointerEvent ) {
89
+
90
+ if( this.mdown ) {
91
+ const ir = this.irect;
92
+
93
+ let hpos = clamp(ev.clientX - ir.left, 0, ir.width );
94
+ let hperc = hpos / ir.width;
95
+
96
+ let vpos = clamp(ev.clientY - ir.top, 0, ir.height );
97
+ let vperc = vpos / ir.height;
98
+
99
+ this.hsv.saturation = hperc;
100
+ this.hsv.value = 1-vperc;
101
+
102
+ this.updateThumbMarker( );
103
+ this.fire( "sat_change", { saturation: this.hsv.saturation, value: this.hsv.value } );
104
+ }
105
+ }
106
+
107
+ mouseup( ev: PointerEvent ) {
108
+ if( this.mdown ) {
109
+ this.releaseCapture( ev.pointerId );
110
+ this.mdown = false;
111
+ }
112
+ }
113
+
114
+ updateThumbMarker( ) {
115
+ const rc = this.color.getBoundingRect( );
116
+
117
+ this.thumb.setStyle( {
118
+ left: (this.hsv.saturation * rc.width ) + 'px',
119
+ bottom: ( this.hsv.value * rc.height ) + 'px'
120
+ } );
121
+ }
122
+
123
+ updateBaseColor( hsv: Hsv ) {
124
+ const base = new Color(0,0,0)
125
+ base.setHsv( hsv.hue, 1, 1, 1 );
126
+ this.color.setStyleValue( "backgroundColor", base.toRgbString(false) );
127
+ }
128
+
129
+ move( sens: string, delta: number ) {
130
+ switch( sens ) {
131
+ case 'saturation': {
132
+ this.hsv.saturation += delta;
133
+ if( this.hsv.saturation<0 ) {
134
+ this.hsv.saturation = 0;
135
+ }
136
+ else if( this.hsv.saturation>1 ) {
137
+ this.hsv.saturation = 1;
138
+ }
139
+
140
+ this.fire( "sat_change", { saturation: this.hsv.saturation, value: this.hsv.value } );
141
+ this.updateThumbMarker( );
142
+ break;
143
+ }
144
+
145
+ case 'value': {
146
+ this.hsv.value += delta;
147
+ if( this.hsv.value<0 ) {
148
+ this.hsv.value = 0;
149
+ }
150
+ else if( this.hsv.value>1 ) {
151
+ this.hsv.value = 1;
152
+ }
153
+
154
+ this.fire( "sat_change", { saturation: this.hsv.saturation, value: this.hsv.value } );
155
+ this.updateThumbMarker( );
156
+ break;
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+
163
+
164
+ /**
165
+ *
166
+ */
167
+
168
+ class HueSlider extends Box<BoxProps,CommonEvents> {
169
+
170
+ private thumb: Component;
171
+ private hsv: Hsv = { hue: 1, saturation: 1, value: 1, alpha: 1 };
172
+
173
+ private mdown = false;
174
+ private irect: Rect;
175
+
176
+ constructor( props: BoxProps, init: Hsv ) {
177
+ super( props );
178
+
179
+ this.setContent( [
180
+ this.thumb = new Component( { cls: "thumb", left: "50%" } ),
181
+ ]);
182
+
183
+ this.setDOMEvents( {
184
+ pointerdown: ( e ) => this.mousedown( e ),
185
+ pointermove: ( e ) => this.mousemove( e ),
186
+ pointerup: ( e ) => this.mouseup( e ),
187
+ } );
188
+
189
+ this.updateHue( init );
190
+ }
191
+
192
+ mousedown( ev: PointerEvent ) {
193
+ this.mdown = true;
194
+ this.irect = this.getBoundingRect( );
195
+ this.setCapture( ev.pointerId );
196
+ }
197
+
198
+ mousemove( ev: PointerEvent ) {
199
+
200
+ if( this.mdown ) {
201
+ const ir = this.irect;
202
+
203
+ let hpos = clamp(ev.clientX - ir.left, 0, ir.width );
204
+ let hperc = hpos / ir.width;
205
+
206
+ this.hsv.hue = hperc;
207
+
208
+ this.updateHue( this.hsv );
209
+ this.fire( "hue_change", { hue: this.hsv.hue } );
210
+ }
211
+ }
212
+
213
+ mouseup( ev: PointerEvent ) {
214
+ if( this.mdown ) {
215
+ this.releaseCapture( ev.pointerId );
216
+ this.mdown = false;
217
+ }
218
+ }
219
+
220
+ updateHue( hsv: Hsv ) {
221
+ this.hsv.hue = hsv.hue;
222
+ this.thumb.setStyleValue( "left", (hsv.hue*100)+'%' );
223
+ }
224
+
225
+ move( delta: number ) {
226
+ this.hsv.hue += delta;
227
+ if( this.hsv.hue<0 ) {
228
+ this.hsv.hue = 0;
229
+ }
230
+ else if( this.hsv.hue>1 ) {
231
+ this.hsv.hue = 1;
232
+ }
233
+
234
+ this.fire( "hue_change", { hue: this.hsv.hue } );
235
+ this.updateHue( this.hsv );
236
+ }
237
+ }
238
+
239
+
240
+ /**
241
+ *
242
+ */
243
+
244
+ class AlphaSlider extends Box<BoxProps,CommonEvents> {
245
+
246
+ private thumb: Component;
247
+ private color: Component;
248
+ private hsv: Hsv = { hue: 1, saturation: 1, value: 1, alpha: 1 };
249
+
250
+ private mdown = false;
251
+ private irect: Rect;
252
+
253
+ constructor( props: BoxProps, init: Hsv ) {
254
+ super( props );
255
+
256
+ this.setContent( [
257
+ new Component( { cls: "overlay checkers"} ),
258
+ this.color = new Component( { cls: "overlay color"} ),
259
+ this.thumb = new Component( { cls: "thumb", left: "50%" } ),
260
+ ]);
261
+
262
+ this.setDOMEvents( {
263
+ pointerdown: ( e ) => this._on_mousedown( e ),
264
+ pointermove: ( e ) => this._on_mousemove( e ),
265
+ pointerup: ( e ) => this._on_mouseup( e ),
266
+ } );
267
+
268
+ this.updateAlpha( );
269
+ this.updateBaseColor( init );
270
+ }
271
+
272
+ _on_mousedown( ev: PointerEvent ) {
273
+ this.mdown = true;
274
+ this.irect = this.getBoundingRect( );
275
+ this.setCapture( ev.pointerId );
276
+ }
277
+
278
+ _on_mousemove( ev: PointerEvent ) {
279
+
280
+ if( this.mdown ) {
281
+ const ir = this.irect;
282
+
283
+ let hpos = clamp(ev.clientX - ir.left, 0, ir.width );
284
+ let hperc = hpos / ir.width;
285
+
286
+ this.hsv.alpha = hperc;
287
+
288
+ this.updateAlpha( );
289
+ this.fire( "alpha_change", { alpha: this.hsv.alpha } );
290
+ }
291
+ }
292
+
293
+ _on_mouseup( ev: PointerEvent ) {
294
+ if( this.mdown ) {
295
+ this.releaseCapture( ev.pointerId );
296
+ this.mdown = false;
297
+ }
298
+ }
299
+
300
+ updateAlpha( ) {
301
+ this.thumb.setStyleValue( "left", (this.hsv.alpha*100)+'%' );
302
+ }
303
+
304
+ updateBaseColor( hsv: Hsv ) {
305
+ const base = new Color(0,0,0)
306
+ base.setHsv( hsv.hue, hsv.saturation, hsv.value, 1 );
307
+ this.color.setStyleValue( "backgroundImage", `linear-gradient(90deg, transparent, ${base.toRgbString(false)})` );
308
+ }
309
+
310
+ setColor( hsv: Hsv ) {
311
+ this.hsv = hsv;
312
+ this.updateBaseColor( hsv );
313
+ this.updateAlpha( );
314
+ }
315
+
316
+ move( delta: number ) {
317
+ this.hsv.alpha += delta;
318
+ if( this.hsv.alpha<0 ) {
319
+ this.hsv.alpha = 0;
320
+ }
321
+ else if( this.hsv.alpha>1 ) {
322
+ this.hsv.alpha = 1;
323
+ }
324
+
325
+ this.fire( "alpha_change", { alpha: this.hsv.alpha } );
326
+ this.updateAlpha( );
327
+ }
328
+ }
329
+
330
+
331
+ /**
332
+ *
333
+ */
334
+
335
+ interface ChangeEvent extends ComponentEvent {
336
+ color: Color;
337
+ }
338
+
339
+ interface ColorPickerChangeEvents extends ComponentEvents {
340
+ change: ChangeEvent
341
+ }
342
+
343
+ /**
344
+ *
345
+ */
346
+ export class ColorPicker extends VBox<ColorPickerProps,ColorPickerChangeEvents> {
347
+
348
+ private _base: Color;
349
+ private _sat: Saturation;
350
+ private _swatch: Component;
351
+ private _hue: HueSlider;
352
+ private _alpha: AlphaSlider;
353
+
354
+
355
+ constructor( props: ColorPickerProps ) {
356
+ super( props );
357
+
358
+ if( props.color instanceof Color ) {
359
+ this._base = props.color;
360
+ }
361
+ else {
362
+ this._base = new Color( props.color );
363
+ }
364
+
365
+ let hsv = this._base.toHsv( );
366
+
367
+ this.setAttribute( "tabindex", 0 );
368
+
369
+ this.setContent( [
370
+ this._sat = new Saturation( { }, hsv ),
371
+ new HBox( {
372
+ cls: "body",
373
+ content: [
374
+ new VBox( {cls: "x4flex", content: [
375
+ this._hue = new HueSlider( { }, hsv ),
376
+ this._alpha = new AlphaSlider( { }, hsv ),
377
+ ] } ),
378
+ new Box( { cls: "swatch", content: [
379
+ new Component( { cls: "overlay checkers" } ),
380
+ this._swatch = new Component( { cls: "overlay" } ),
381
+ ] } )
382
+ ]
383
+ })
384
+ ]);
385
+
386
+ this._sat.on( "sat_change", ( ev ) => {
387
+ hsv.saturation = ev.saturation;
388
+ hsv.value = ev.value;
389
+ updateColor( );
390
+ this._alpha.updateBaseColor( hsv );
391
+ } );
392
+
393
+ this._hue.on( 'hue_change', ( ev ) => {
394
+ hsv.hue = ev.hue;
395
+ this._sat.updateBaseColor( hsv );
396
+ this._alpha.updateBaseColor( hsv );
397
+ updateColor( );
398
+ } );
399
+
400
+ this._alpha.on( 'alpha_change', ( ev ) => {
401
+ hsv.alpha = ev.alpha;
402
+ updateColor( );
403
+ } );
404
+
405
+ const updateColor = ( ) => {
406
+ this._base.setHsv( hsv.hue, hsv.saturation, hsv.value, hsv.alpha );
407
+ this._swatch.setStyleValue( "backgroundColor", this._base.toRgbString() );
408
+ this._swatch.setAttribute( "tooltip", this._base.toRgbString() );
409
+
410
+ this.fire( "change", { color: this._base } );
411
+ }
412
+
413
+ if( isFeatureAvailable("eyedropper") ) {
414
+ this._swatch.addDOMEvent( "click", ( e ) => {
415
+ const eyeDropper = new (window as any).EyeDropper();
416
+ eyeDropper.open( ).then( ( result: any ) => {
417
+ const color = new Color( result.sRGBHex );
418
+ hsv = color.toHsv( );
419
+
420
+ this._alpha.setColor( hsv );
421
+
422
+ this._sat.updateBaseColor( hsv );
423
+ this._hue.updateHue( hsv );
424
+ updateColor( );
425
+ });
426
+ })
427
+ }
428
+
429
+ this.addDOMEvent( "keydown", ( ev ) => this._onkey( ev ) );
430
+
431
+ updateColor( );
432
+ }
433
+
434
+ private _onkey( ev: KeyboardEvent ) {
435
+ switch( ev.key ) {
436
+ case "ArrowLeft": {
437
+ if( ev.ctrlKey ) {
438
+ this._hue.move( -0.01 );
439
+ }
440
+ else {
441
+ this._sat.move( "saturation", -0.01 );
442
+ }
443
+ break;
444
+ }
445
+
446
+ case "ArrowRight": {
447
+ if( ev.ctrlKey ) {
448
+ this._hue.move( 0.01 );
449
+ }
450
+ else {
451
+ this._sat.move( "saturation", 0.01 );
452
+ }
453
+ break;
454
+ }
455
+
456
+ case "ArrowUp": {
457
+ if( ev.ctrlKey ) {
458
+ this._alpha.move( 0.01 );
459
+ }
460
+ else {
461
+ this._sat.move( "value", 0.01 );
462
+ }
463
+ break;
464
+ }
465
+
466
+ case "ArrowDown": {
467
+ if( ev.ctrlKey ) {
468
+ this._alpha.move( -0.01 );
469
+ }
470
+ else {
471
+ this._sat.move( "value", -0.01 );
472
+ }
473
+ break;
474
+ }
475
+ }
476
+ }
477
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file combobox.module.scss
9
+ * @author Etienne Cochard
10
+ *
11
+ * @copyright (c) 2024 R-libre ingenierie
12
+ *
13
+ * Use of this source code is governed by an MIT-style license
14
+ * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
+ **/
16
+
17
+ @use "../shared.scss";
18
+
19
+ :root {
20
+ --dropdown-border: var( --border-hover );
21
+ --dropdown-background: var( --background-primary );
22
+
23
+ --combobox-border: var( --border );
24
+ --combobox-border-focus: var( --border-focus );
25
+
26
+ --combobox-btn-background: inherit;
27
+ --combobox-btn-color: var( --text-secondary );
28
+ --combobox-btn-color-hover: var( --text-primary );
29
+ }
30
+
31
+ .x4dropdown {
32
+ @extend .shadow-xl;
33
+ @extend .hbox;
34
+
35
+ max-height: 250px;
36
+ position: absolute;
37
+ background-color: var( --dropdown-background );
38
+ border: 1px solid var( --dropdown-border );
39
+
40
+ .x4listbox {
41
+ @extend .flex;
42
+
43
+ border: none;
44
+ margin: 0;
45
+ width: 100%;
46
+ height: 200px;
47
+ }
48
+ }
49
+
50
+ .x4combobox {
51
+ @extend .hbox;
52
+ margin: 5px;
53
+
54
+ &> #label {
55
+ padding: 0 6px;
56
+ border-bottom: 1px solid transparent;
57
+
58
+ &> .x4label {
59
+ height: 100%;
60
+ padding: 0;
61
+ font-weight: 500;
62
+ gap: 0;
63
+ }
64
+
65
+ &::after {
66
+ content: ":"
67
+ }
68
+ }
69
+
70
+ &>#edit {
71
+ @extend .flex;
72
+ border-bottom: 1px solid var( --combobox-border );
73
+
74
+ .x4input {
75
+ @extend .flex;
76
+
77
+ &[readonly] {
78
+ cursor: pointer;
79
+ }
80
+ }
81
+
82
+ .x4button {
83
+ margin: 0;
84
+ padding: 0;
85
+ outline: none;
86
+ background-color: var( --combobox-btn-background );
87
+ color: var( --combobox-btn-color );
88
+
89
+ #icon {
90
+ color: var( --combobox-btn-color );
91
+ }
92
+
93
+ &:hover, &:hover #icon {
94
+ color: var( --combobox-btn-color-hover );
95
+ }
96
+
97
+ &:focus {
98
+ //background-color: var( --color-30 );
99
+ //color: var( --color-10 );
100
+ }
101
+ }
102
+ }
103
+
104
+ &[disabled] {
105
+ &, * {
106
+ cursor: not-allowed;
107
+ }
108
+
109
+ #label .x4label {
110
+ color: var( --disabled-color-dark );
111
+ pointer-events: none;
112
+ }
113
+ }
114
+
115
+ &[required] {
116
+ .x4label::before {
117
+ content: "*";
118
+ color: var( --color-90 )
119
+ }
120
+ }
121
+ }