x4js 2.0.12 → 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 (284) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/README.md +20 -15
  3. package/{lib/src/demo → demo}/assets/radio.svg +3 -3
  4. package/{lib/src/demo → demo}/index.html +11 -11
  5. package/{lib/src/demo → demo}/main.scss +23 -21
  6. package/{lib/src/demo/main.tsx → demo/main.ts} +324 -323
  7. package/demo/package.json +26 -0
  8. package/demo/scss.d.ts +4 -0
  9. package/demo/svg.d.ts +1 -0
  10. package/demo/tsconfig.json +14 -0
  11. package/lib/README.txt +20 -15
  12. package/lib/cjs/x4.css +1 -1
  13. package/lib/cjs/x4.js +2 -1
  14. package/lib/esm/x4.css +1 -1
  15. package/lib/esm/x4.mjs +2 -1
  16. package/lib/src/components/base.scss +25 -26
  17. package/lib/src/components/boxes/boxes.module.scss +54 -37
  18. package/lib/src/components/boxes/boxes.ts +278 -125
  19. package/lib/src/components/breadcrumb/breadcrumb.scss +56 -0
  20. package/lib/src/components/breadcrumb/breadcrumb.ts +93 -0
  21. package/lib/src/components/breadcrumb/chevron-right.svg +1 -0
  22. package/lib/src/components/btngroup/btngroup.module.scss +40 -28
  23. package/lib/src/components/btngroup/btngroup.ts +152 -101
  24. package/lib/src/components/button/button.module.scss +172 -153
  25. package/lib/src/components/button/button.ts +185 -117
  26. package/lib/src/components/calendar/calendar.module.scss +162 -162
  27. package/lib/src/components/calendar/calendar.ts +326 -325
  28. package/lib/src/components/canvas/canvas.module.scss +25 -0
  29. package/lib/src/components/canvas/canvas.ts +189 -0
  30. package/lib/src/components/canvas/canvas_ex.ts +269 -0
  31. package/lib/src/components/checkbox/check.svg +3 -3
  32. package/lib/src/components/checkbox/checkbox.module.scss +141 -141
  33. package/lib/src/components/checkbox/checkbox.ts +139 -124
  34. package/lib/src/components/colorinput/colorinput.module.scss +64 -64
  35. package/lib/src/components/colorinput/colorinput.ts +90 -87
  36. package/lib/src/components/colorpicker/colorpicker.module.scss +132 -132
  37. package/lib/src/components/colorpicker/colorpicker.ts +481 -476
  38. package/lib/src/components/combobox/combobox.module.scss +132 -120
  39. package/lib/src/components/combobox/combobox.ts +275 -190
  40. package/lib/src/components/combobox/updown.svg +3 -3
  41. package/lib/src/components/components.ts +41 -0
  42. package/lib/src/components/dialog/dialog.module.scss +105 -71
  43. package/lib/src/components/dialog/dialog.ts +212 -92
  44. package/lib/src/components/filedrop/cloud-arrow-up.svg +1 -0
  45. package/lib/src/components/filedrop/filedrop.module.scss +70 -0
  46. package/lib/src/components/filedrop/filedrop.ts +131 -0
  47. package/lib/src/components/form/form.module.scss +38 -34
  48. package/lib/src/components/form/form.ts +172 -36
  49. package/lib/src/components/gridview/arrow-down-light.svg +1 -0
  50. package/lib/src/components/gridview/arrow-up-light.svg +1 -0
  51. package/lib/src/components/gridview/gridview.module.scss +324 -0
  52. package/lib/src/components/gridview/gridview.ts +1175 -0
  53. package/lib/src/components/header/header.module.scss +39 -39
  54. package/lib/src/components/header/header.ts +129 -123
  55. package/lib/src/components/icon/icon.module.scss +30 -30
  56. package/lib/src/components/icon/icon.ts +139 -134
  57. package/lib/src/components/image/image.module.scss +27 -20
  58. package/lib/src/components/image/image.ts +168 -67
  59. package/lib/src/components/input/input.module.scss +74 -69
  60. package/lib/src/components/input/input.ts +398 -274
  61. package/lib/src/components/keyboard/arrow-up.svg +1 -0
  62. package/lib/src/components/keyboard/delete-left.svg +1 -0
  63. package/lib/src/components/keyboard/eye-slash.svg +1 -0
  64. package/lib/src/components/keyboard/keyboard.module.scss +134 -0
  65. package/lib/src/components/keyboard/keyboard.ts +525 -0
  66. package/lib/src/components/label/label.module.scss +76 -52
  67. package/lib/src/components/label/label.ts +97 -55
  68. package/lib/src/components/link/link.ts +81 -0
  69. package/lib/src/components/listbox/listbox.module.scss +161 -103
  70. package/lib/src/components/listbox/listbox.ts +539 -427
  71. package/lib/src/components/menu/menu.module.scss +116 -107
  72. package/lib/src/components/menu/menu.ts +174 -168
  73. package/lib/src/components/messages/messages.module.scss +92 -47
  74. package/lib/src/components/messages/messages.ts +215 -64
  75. package/lib/src/components/messages/pen-field.svg +1 -0
  76. package/lib/src/components/normalize.scss +391 -386
  77. package/lib/src/components/notification/notification.module.scss +83 -81
  78. package/lib/src/components/notification/notification.ts +107 -108
  79. package/lib/src/components/panel/panel.module.scss +59 -47
  80. package/lib/src/components/panel/panel.ts +57 -56
  81. package/lib/src/components/popup/popup.module.scss +45 -43
  82. package/lib/src/components/popup/popup.ts +440 -395
  83. package/lib/src/components/progress/progress.module.scss +56 -56
  84. package/lib/src/components/progress/progress.ts +43 -42
  85. package/lib/src/components/propgrid/folder-closed.svg +1 -0
  86. package/lib/src/components/propgrid/folder-open.svg +1 -0
  87. package/lib/src/components/propgrid/progrid.module.scss +108 -0
  88. package/lib/src/components/propgrid/propgrid.ts +271 -0
  89. package/lib/src/components/propgrid/updown.svg +4 -0
  90. package/lib/src/components/radio/radio.module.scss +147 -0
  91. package/lib/src/components/radio/radio.svg +4 -0
  92. package/lib/src/components/radio/radio.ts +142 -0
  93. package/lib/src/components/rating/rating.module.scss +22 -22
  94. package/lib/src/components/rating/rating.ts +131 -125
  95. package/lib/src/components/select/select.module.scss +9 -0
  96. package/lib/src/components/select/select.ts +134 -0
  97. package/lib/src/components/shared.scss +137 -76
  98. package/lib/src/components/sizers/sizer.module.scss +89 -89
  99. package/lib/src/components/sizers/sizer.ts +130 -119
  100. package/lib/src/components/slider/slider.module.scss +117 -70
  101. package/lib/src/components/slider/slider.ts +197 -142
  102. package/lib/src/components/switch/switch.module.scss +126 -126
  103. package/lib/src/components/switch/switch.ts +61 -55
  104. package/lib/src/components/tabs/tabs.module.scss +45 -46
  105. package/lib/src/components/tabs/tabs.ts +199 -157
  106. package/lib/src/components/textarea/textarea.module.scss +63 -59
  107. package/lib/src/components/textarea/textarea.ts +125 -54
  108. package/lib/src/components/textedit/textedit.module.scss +115 -113
  109. package/lib/src/components/textedit/textedit.ts +110 -82
  110. package/lib/src/components/themes.scss +88 -77
  111. package/lib/src/components/tickline/tickline.module.scss +26 -0
  112. package/lib/src/components/tickline/tickline.ts +82 -0
  113. package/lib/src/components/tooltips/comments-question.svg +1 -0
  114. package/lib/src/components/tooltips/tooltips.scss +71 -50
  115. package/lib/src/components/tooltips/tooltips.ts +108 -102
  116. package/lib/src/components/treeview/treeview.module.scss +184 -115
  117. package/lib/src/components/treeview/treeview.ts +445 -403
  118. package/lib/src/components/viewport/viewport.module.scss +31 -24
  119. package/lib/src/components/viewport/viewport.ts +41 -38
  120. package/lib/src/core/component.ts +1072 -979
  121. package/lib/src/core/core_application.ts +264 -0
  122. package/lib/src/core/core_colors.ts +249 -249
  123. package/lib/src/core/core_data.ts +1309 -0
  124. package/lib/src/core/core_dom.ts +471 -471
  125. package/lib/src/core/core_dragdrop.ts +200 -200
  126. package/lib/src/core/core_element.ts +109 -97
  127. package/lib/src/core/core_events.ts +177 -149
  128. package/lib/src/core/core_i18n.ts +393 -377
  129. package/lib/src/core/core_react.ts +79 -0
  130. package/lib/src/core/core_router.ts +237 -221
  131. package/lib/src/core/core_styles.ts +214 -214
  132. package/lib/src/core/core_svg.ts +711 -550
  133. package/lib/src/core/core_tools.ts +906 -673
  134. package/lib/src/types/scss.d.ts +4 -4
  135. package/lib/src/types/x4react.d.ts +8 -8
  136. package/lib/src/x4.scss +18 -18
  137. package/lib/src/x4.ts +31 -62
  138. package/lib/src/x4tsx.d.ts +25 -0
  139. package/lib/styles/x4.css +1 -1
  140. package/lib/types/x4js.d.ts +853 -127
  141. package/package.json +5 -6
  142. package/scripts/build.mjs +378 -0
  143. package/scripts/prepack.mjs +346 -0
  144. package/src/components/base.scss +25 -0
  145. package/src/components/boxes/boxes.module.scss +54 -0
  146. package/src/components/boxes/boxes.ts +278 -0
  147. package/src/components/breadcrumb/breadcrumb.scss +56 -0
  148. package/src/components/breadcrumb/breadcrumb.ts +93 -0
  149. package/src/components/breadcrumb/chevron-right.svg +1 -0
  150. package/src/components/btngroup/btngroup.module.scss +41 -0
  151. package/src/components/btngroup/btngroup.ts +153 -0
  152. package/src/components/button/button.module.scss +173 -0
  153. package/src/components/button/button.ts +185 -0
  154. package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
  155. package/src/components/calendar/calendar.module.scss +163 -0
  156. package/src/components/calendar/calendar.ts +327 -0
  157. package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
  158. package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
  159. package/src/components/canvas/canvas.module.scss +25 -0
  160. package/src/components/canvas/canvas.ts +189 -0
  161. package/src/components/canvas/canvas_ex.ts +269 -0
  162. package/src/components/checkbox/check.svg +4 -0
  163. package/src/components/checkbox/checkbox.module.scss +142 -0
  164. package/src/components/checkbox/checkbox.ts +140 -0
  165. package/src/components/colorinput/colorinput.module.scss +65 -0
  166. package/src/components/colorinput/colorinput.ts +91 -0
  167. package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
  168. package/src/components/colorpicker/colorpicker.module.scss +133 -0
  169. package/src/components/colorpicker/colorpicker.ts +482 -0
  170. package/src/components/combobox/combobox.module.scss +133 -0
  171. package/src/components/combobox/combobox.ts +275 -0
  172. package/src/components/combobox/updown.svg +4 -0
  173. package/src/components/components.ts +41 -0
  174. package/src/components/dialog/dialog.module.scss +105 -0
  175. package/src/components/dialog/dialog.ts +212 -0
  176. package/src/components/dialog/xmark-sharp-light.svg +1 -0
  177. package/src/components/filedrop/cloud-arrow-up.svg +1 -0
  178. package/src/components/filedrop/filedrop.module.scss +70 -0
  179. package/src/components/filedrop/filedrop.ts +131 -0
  180. package/src/components/form/form.module.scss +38 -0
  181. package/src/components/form/form.ts +172 -0
  182. package/src/components/gridview/arrow-down-light.svg +1 -0
  183. package/src/components/gridview/arrow-up-light.svg +1 -0
  184. package/src/components/gridview/gridview.module.scss +324 -0
  185. package/src/components/gridview/gridview.ts +1175 -0
  186. package/src/components/header/header.module.scss +40 -0
  187. package/src/components/header/header.ts +130 -0
  188. package/src/components/icon/icon.module.scss +30 -0
  189. package/src/components/icon/icon.ts +139 -0
  190. package/src/components/image/image.module.scss +28 -0
  191. package/src/components/image/image.ts +168 -0
  192. package/src/components/input/input.module.scss +74 -0
  193. package/src/components/input/input.ts +398 -0
  194. package/src/components/keyboard/arrow-up.svg +1 -0
  195. package/src/components/keyboard/delete-left.svg +1 -0
  196. package/src/components/keyboard/eye-slash.svg +1 -0
  197. package/src/components/keyboard/keyboard.module.scss +134 -0
  198. package/src/components/keyboard/keyboard.ts +525 -0
  199. package/src/components/label/label.module.scss +76 -0
  200. package/src/components/label/label.ts +97 -0
  201. package/src/components/link/link.ts +81 -0
  202. package/src/components/listbox/listbox.module.scss +161 -0
  203. package/src/components/listbox/listbox.ts +539 -0
  204. package/src/components/menu/caret-right-solid.svg +1 -0
  205. package/src/components/menu/menu.module.scss +117 -0
  206. package/src/components/menu/menu.ts +174 -0
  207. package/src/components/messages/circle-exclamation.svg +1 -0
  208. package/src/components/messages/messages.module.scss +92 -0
  209. package/src/components/messages/messages.ts +215 -0
  210. package/src/components/messages/pen-field.svg +1 -0
  211. package/src/components/normalize.scss +391 -0
  212. package/src/components/notification/circle-check-solid.svg +1 -0
  213. package/src/components/notification/circle-exclamation-solid.svg +1 -0
  214. package/src/components/notification/circle-notch-light.svg +1 -0
  215. package/src/components/notification/notification.module.scss +84 -0
  216. package/src/components/notification/notification.ts +107 -0
  217. package/src/components/notification/xmark-sharp-light.svg +1 -0
  218. package/src/components/panel/panel.module.scss +60 -0
  219. package/src/components/panel/panel.ts +58 -0
  220. package/src/components/popup/popup.module.scss +45 -0
  221. package/src/components/popup/popup.ts +440 -0
  222. package/src/components/progress/progress.module.scss +57 -0
  223. package/src/components/progress/progress.ts +44 -0
  224. package/src/components/propgrid/folder-closed.svg +1 -0
  225. package/src/components/propgrid/folder-open.svg +1 -0
  226. package/src/components/propgrid/progrid.module.scss +108 -0
  227. package/src/components/propgrid/propgrid.ts +271 -0
  228. package/src/components/propgrid/updown.svg +4 -0
  229. package/src/components/radio/radio.module.scss +147 -0
  230. package/src/components/radio/radio.svg +4 -0
  231. package/src/components/radio/radio.ts +142 -0
  232. package/src/components/rating/rating.module.scss +23 -0
  233. package/src/components/rating/rating.ts +131 -0
  234. package/src/components/rating/star-sharp-light.svg +1 -0
  235. package/src/components/rating/star-sharp-solid.svg +1 -0
  236. package/src/components/select/select.module.scss +9 -0
  237. package/src/components/select/select.ts +134 -0
  238. package/src/components/shared.scss +137 -0
  239. package/src/components/sizers/sizer.module.scss +90 -0
  240. package/src/components/sizers/sizer.ts +131 -0
  241. package/src/components/slider/slider.module.scss +118 -0
  242. package/src/components/slider/slider.ts +198 -0
  243. package/src/components/switch/switch.module.scss +127 -0
  244. package/src/components/switch/switch.ts +62 -0
  245. package/src/components/tabs/tabs.module.scss +45 -0
  246. package/src/components/tabs/tabs.ts +199 -0
  247. package/src/components/textarea/textarea.module.scss +63 -0
  248. package/src/components/textarea/textarea.ts +125 -0
  249. package/src/components/textedit/textedit.module.scss +116 -0
  250. package/src/components/textedit/textedit.ts +110 -0
  251. package/src/components/themes.scss +88 -0
  252. package/src/components/tickline/tickline.module.scss +26 -0
  253. package/src/components/tickline/tickline.ts +82 -0
  254. package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
  255. package/src/components/tooltips/comments-question.svg +1 -0
  256. package/src/components/tooltips/tooltips.scss +72 -0
  257. package/src/components/tooltips/tooltips.ts +109 -0
  258. package/src/components/treeview/chevron-down-light.svg +1 -0
  259. package/src/components/treeview/treeview.module.scss +185 -0
  260. package/src/components/treeview/treeview.ts +445 -0
  261. package/src/components/viewport/viewport.module.scss +32 -0
  262. package/src/components/viewport/viewport.ts +41 -0
  263. package/src/core/component.ts +1072 -0
  264. package/src/core/core_application.ts +264 -0
  265. package/src/core/core_colors.ts +250 -0
  266. package/src/core/core_data.ts +1309 -0
  267. package/src/core/core_dom.ts +471 -0
  268. package/src/core/core_dragdrop.ts +201 -0
  269. package/src/core/core_element.ts +110 -0
  270. package/src/core/core_events.ts +177 -0
  271. package/src/core/core_i18n.ts +393 -0
  272. package/src/core/core_react.ts +79 -0
  273. package/src/core/core_router.ts +237 -0
  274. package/src/core/core_styles.ts +214 -0
  275. package/src/core/core_svg.ts +711 -0
  276. package/src/core/core_tools.ts +906 -0
  277. package/src/types/scss.d.ts +4 -0
  278. package/src/types/svg.d.ts +1 -0
  279. package/src/types/x4react.d.ts +9 -0
  280. package/src/x4.scss +19 -0
  281. package/src/x4.ts +31 -62
  282. package/src/x4tsx.d.ts +25 -0
  283. package/tsconfig.json +14 -0
  284. /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file core_application.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 { Component, componentFromDOM } from './component.js';
18
+ import { CoreElement } from './core_element.js';
19
+ import { CoreEvent, EventMap } from './core_events';
20
+ import { getFocusableElements, ITabHandler } from './core_tools.js';
21
+
22
+ const socket_sent = Symbol( 'socket' );
23
+
24
+
25
+ export interface EvMessage extends CoreEvent {
26
+ msg: string;
27
+ params: any;
28
+ }
29
+
30
+ export interface ApplicationEvents extends EventMap {
31
+ global: EvMessage;
32
+ message: EvMessage;
33
+ }
34
+
35
+ // signleton
36
+ let main_app: Application = null;
37
+
38
+
39
+
40
+ class Process {
41
+
42
+ /**
43
+ * can be use to see if we have some tactile input
44
+ * @returns max touch point count
45
+ */
46
+
47
+ getMaxTouchPoints( ) {
48
+ return navigator.maxTouchPoints;
49
+ }
50
+ }
51
+
52
+
53
+
54
+ export class Application<E extends ApplicationEvents = ApplicationEvents> extends CoreElement<E> {
55
+
56
+ private env = new Map<string,any>( );
57
+ private mainview: Component;
58
+
59
+ static readonly process = new Process( );
60
+
61
+ constructor( ) {
62
+ super( );
63
+
64
+ console.assert( main_app==null, "Application must be a singleton." );
65
+ main_app = this;
66
+ }
67
+
68
+ setMainView( view: Component ) {
69
+ this.mainview = view;
70
+ document.body.appendChild( view.dom );
71
+ this._setupKeyboard( );
72
+ }
73
+
74
+ static instance<P extends Application = Application>( ): P {
75
+ return main_app as P;
76
+ }
77
+
78
+ /**
79
+ *
80
+ */
81
+
82
+ getMainView( ) {
83
+ return this.mainview;
84
+ }
85
+
86
+ /**
87
+ *
88
+ */
89
+
90
+ setEnv( name: string, value: any ) {
91
+ this.env.set( name, value );
92
+ }
93
+
94
+ /**
95
+ *
96
+ */
97
+
98
+ getEnv( name: string, def_value?: any ) {
99
+ return this.env.get( name ) ?? def_value;
100
+ }
101
+
102
+ /**
103
+ * small shortcut for Application.instance().fire( "global", ... );
104
+ */
105
+
106
+ static fireGlobal( msg: string, params?: any ) {
107
+ Application.instance().fire( "global", { msg, params } );
108
+ }
109
+
110
+ /**
111
+ *
112
+ */
113
+
114
+ private _setupKeyboard( ) {
115
+
116
+ document.addEventListener( "keydown", (ev) => {
117
+ if( ev.key=="Tab" || ev.key=="Enter" ) {
118
+ if( this.focusNext( !ev.shiftKey ) ) {
119
+ ev.preventDefault( );
120
+ }
121
+ }
122
+ } );
123
+ }
124
+
125
+ focusNext( next: boolean ) {
126
+ let act = document.activeElement;
127
+ let topmost: HTMLElement;
128
+
129
+ while( act!=document.body ) {
130
+ const comp = componentFromDOM(act);
131
+ const ifx = comp.queryInterface( "tab-handler") as ITabHandler;
132
+
133
+ if( ifx ) {
134
+ return ifx.focusNext( next );
135
+ }
136
+
137
+ if( act.classList.contains("x4box") ) { // todo: that is too dirty
138
+ topmost = act as HTMLElement;
139
+ }
140
+
141
+ act = act.parentElement;
142
+ }
143
+
144
+ if( topmost ) {
145
+ const focusable = getFocusableElements( topmost );
146
+ if( !focusable.length ) {
147
+ return true;
148
+ }
149
+ else {
150
+ const first = focusable[0];
151
+ const last = focusable[focusable.length - 1];
152
+
153
+ let newf: HTMLElement;
154
+ if (!next && document.activeElement === first) {
155
+ newf = last as HTMLElement;
156
+ }
157
+ else if (next && document.activeElement === last) {
158
+ newf = first as HTMLElement;
159
+ }
160
+
161
+ if( newf ) {
162
+ newf.focus();
163
+ return true;
164
+ }
165
+ }
166
+ }
167
+
168
+ return false;
169
+ }
170
+
171
+
172
+ /**
173
+ *
174
+ */
175
+
176
+ setupSocketMessaging( path?: string, looseCallback?: ( ) => void ) {
177
+
178
+ const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
179
+ const address = path ? protocol+path : `${protocol}${window.location.hostname}:${window.location.port}/ws`;
180
+
181
+ let opened = 0;
182
+ let msg_socket:WebSocket = null;
183
+
184
+ // we trap all 'global' messages send via application
185
+ // then we send them on websocket
186
+
187
+ this.on( 'global', ( e: EvMessage ) => {
188
+ if( e.hasOwnProperty(socket_sent) ) {
189
+ return;
190
+ }
191
+
192
+ if( msg_socket ) {
193
+ msg_socket.send( JSON.stringify( {
194
+ msg: e.msg,
195
+ params: e.params,
196
+ } ) );
197
+ }
198
+ });
199
+
200
+ msg_socket = new WebSocket(address, 'messaging' );
201
+
202
+ msg_socket.onopen = ( ) => {
203
+ console.log( 'websocket opened' );
204
+ opened = 1;
205
+ }
206
+
207
+ // receive a message
208
+ msg_socket.onmessage = ( e ) => {
209
+ if( e.data!='ping' ) {
210
+ const message = JSON.parse(e.data);
211
+ message[socket_sent] = true;
212
+ this.fire( 'global', message );
213
+ }
214
+ }
215
+
216
+ // loose socket
217
+ msg_socket.onclose = ( ev ) => {
218
+ console.log( 'websocket closed:', ev );
219
+ msg_socket = null;
220
+
221
+ if( opened ) {
222
+ looseCallback( );
223
+ opened = 0;
224
+ }
225
+ }
226
+
227
+ //msg_socket.onerror = (ev )=> {
228
+ // console.log( 'websocket error:', ev );
229
+ //}
230
+ }
231
+
232
+ /**
233
+ * get a local storage value
234
+ * @param name name of the value
235
+ * @returns the value (string) or undefined
236
+ */
237
+
238
+ getStorage( name: string ) : string {
239
+ return localStorage.getItem( name );
240
+ }
241
+
242
+ getStorageJSON( name: string ) : any {
243
+ try {
244
+ return JSON.parse( localStorage.getItem( name ) );
245
+ }
246
+ catch( e ) {
247
+ return undefined;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * change a loclastorage value
253
+ * @param name name of the value
254
+ * @param value the value to store
255
+ */
256
+
257
+ setStorage( name: string, value: string | number ) {
258
+ localStorage.setItem( name, value+'' );
259
+ }
260
+
261
+ setStorageJSON( name: string, value: any ) {
262
+ localStorage.setItem( name, JSON.stringify( value ) );
263
+ }
264
+ }
@@ -0,0 +1,250 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file core_colors.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 { clamp, isString } from './core_tools';
18
+
19
+
20
+ function hx( v: number ) {
21
+ const hex = v.toString( 16 );
22
+ return hex.padStart( 2, '0' );
23
+ }
24
+
25
+ function round( v: number ) {
26
+ return Math.round(v);
27
+ }
28
+
29
+
30
+ export interface Rgb {
31
+ red: number;
32
+ green: number;
33
+ blue: number;
34
+ alpha: number;
35
+ }
36
+
37
+ export interface Hsv {
38
+ hue: number;
39
+ saturation: number;
40
+ value: number;
41
+ alpha: number;
42
+ }
43
+
44
+
45
+ export class Color {
46
+
47
+ private rgb: [red:number,green:number,blue:number,alpha:number] = [0,0,0,1];
48
+ private invalid = false;
49
+
50
+ constructor( value: string );
51
+ constructor( r: number, g: number, b: number, a?: number );
52
+ constructor( ...args: any[] ) {
53
+ if( isString(args[0] ) ) {
54
+ this.setValue( args[0] );
55
+ }
56
+ else {
57
+ this.setRgb( args[0], args[1], args[2], args[3] );
58
+ }
59
+ }
60
+
61
+ /**
62
+ * accepts:
63
+ * #aaa
64
+ * #ababab
65
+ * #ababab55
66
+ * rgb(a,b,c)
67
+ * rgba(a,b,c,d)
68
+ * var( --color-5 )
69
+ */
70
+
71
+ setValue( value: string ): this {
72
+
73
+ this.invalid = false;
74
+
75
+ if( value.length==4 && /#[0-9a-fA-F]{3}/.test(value) ) {
76
+ const r1 = parseInt( value[1], 16 );
77
+ const g1 = parseInt( value[2], 16 );
78
+ const b1 = parseInt( value[3], 16 );
79
+ return this.setRgb( r1<<4|r1, g1<<4|g1, b1<<4|b1, 1.0 );
80
+ }
81
+
82
+ if( value.length==7 && /#[0-9a-fA-F]{6}/.test(value) ) {
83
+ const r1 = parseInt( value[1], 16 );
84
+ const r2 = parseInt( value[2], 16 );
85
+ const g1 = parseInt( value[3], 16 );
86
+ const g2 = parseInt( value[4], 16 );
87
+ const b1 = parseInt( value[5], 16 );
88
+ const b2 = parseInt( value[6], 16 );
89
+ return this.setRgb( r1<<4|r2, g1<<4|g2, b1<<4|b2, 1.0 );
90
+ }
91
+
92
+ if( value.length==9 && /#[0-9a-fA-F]{8}/.test(value) ) {
93
+ const r1 = parseInt( value[1], 16 );
94
+ const r2 = parseInt( value[2], 16 );
95
+ const g1 = parseInt( value[3], 16 );
96
+ const g2 = parseInt( value[4], 16 );
97
+ const b1 = parseInt( value[5], 16 );
98
+ const b2 = parseInt( value[6], 16 );
99
+ const a1 = parseInt( value[7], 16 );
100
+ const a2 = parseInt( value[8], 16 );
101
+ return this.setRgb( r1<<4|r2, g1<<4|g2, b1<<4|b2, (a1<<4|a2) / 255.0 );
102
+ }
103
+
104
+ if( value.startsWith('rgba') ) {
105
+ const re = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*((\d+)|(\d*\.\d+)|(\.\d+))\s*\)/;
106
+ const m = re.exec( value );
107
+ if( m ) {
108
+ return this.setRgb( parseInt(m[1]), parseInt(m[2]), parseInt(m[3]), parseFloat(m[4]) );
109
+ }
110
+ }
111
+ else if( value.startsWith('rgb') ) {
112
+ const re = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
113
+ const m = re.exec( value );
114
+ if( m ) {
115
+ return this.setRgb( parseInt(m[1]), parseInt(m[2]), parseInt(m[3]), 1.0 );
116
+ }
117
+ }
118
+ else if( value.startsWith("var") ) {
119
+ const re = /var\s*\(([^)]*)\)/;
120
+ const m = re.exec( value );
121
+ if( m ) {
122
+ const expr = m[1].trim( );
123
+ const style = getComputedStyle( document.documentElement );
124
+ const value = style.getPropertyValue( expr );
125
+ return this.setValue( value );
126
+ }
127
+ }
128
+
129
+ this.invalid = true;
130
+ return this.setRgb(255,0,0,1);
131
+ }
132
+
133
+ setHsv( h: number, s: number, v: number, a = 1.0 ): this {
134
+
135
+ let i = Math.min(5, Math.floor(h * 6)),
136
+ f = h * 6 - i,
137
+ p = v * (1 - s),
138
+ q = v * (1 - f * s),
139
+ t = v * (1 - (1 - f) * s);
140
+
141
+ let R, G, B;
142
+
143
+ switch (i) {
144
+ case 0:
145
+ R = v;
146
+ G = t;
147
+ B = p;
148
+ break;
149
+ case 1:
150
+ R = q;
151
+ G = v;
152
+ B = p;
153
+ break;
154
+ case 2:
155
+ R = p;
156
+ G = v;
157
+ B = t;
158
+ break;
159
+ case 3:
160
+ R = p;
161
+ G = q;
162
+ B = v;
163
+ break;
164
+ case 4:
165
+ R = t;
166
+ G = p;
167
+ B = v;
168
+ break;
169
+ case 5:
170
+ R = v;
171
+ G = p;
172
+ B = q;
173
+ break;
174
+ }
175
+
176
+ return this.setRgb( R*255, G*255, B*255, a );
177
+ }
178
+
179
+
180
+ setRgb( r: number, g: number, b: number, a: number ): this {
181
+ this.rgb = [clamp(r|0,0,255),clamp(g|0,0,255),clamp(b|0,0,255),clamp(a,0,1)];
182
+ return this;
183
+ }
184
+
185
+ toRgbString( withAlpha?: boolean ): string {
186
+ const _ = this.rgb;
187
+ return withAlpha===false || _[3]==1 ? `rgb(${round(_[0])},${round(_[1])},${round(_[2])})` : `rgba(${round(_[0])},${round(_[1])},${round(_[2])},${_[3].toFixed(3)})`
188
+ }
189
+
190
+ toHexString( ): string {
191
+ const _ = this.rgb;
192
+ return _[3]==1 ? `#${hx(_[0])}${hx(_[1])}${hx(_[2])}` : `#${hx(_[0])}${hx(_[1])}${hx(_[2])}${(hx((_[3]*255)|0))}`
193
+ }
194
+
195
+ toRgb( ): Rgb {
196
+ const _ = this.rgb;
197
+ return { red: _[0], green: _[1], blue: _[2], alpha: _[3] };
198
+ }
199
+
200
+ toHsv( ): Hsv {
201
+
202
+ let el = this.toRgb( );
203
+
204
+ el.red /= 255.0;
205
+ el.green /= 255.0;
206
+ el.blue /= 255.0;
207
+
208
+ const max = Math.max(el.red, el.green, el.blue);
209
+ const min = Math.min(el.red, el.green, el.blue);
210
+ const delta = max - min;
211
+ const saturation = (max === 0) ? 0 : (delta / max);
212
+ const value = max;
213
+
214
+ let hue;
215
+
216
+ if (delta === 0) {
217
+ hue = 0;
218
+ }
219
+ else {
220
+ switch (max) {
221
+ case el.red:
222
+ hue = (el.green - el.blue) / delta / 6 + (el.green < el.blue ? 1 : 0);
223
+ break;
224
+
225
+ case el.green:
226
+ hue = (el.blue - el.red) / delta / 6 + 1 / 3;
227
+ break;
228
+
229
+ case el.blue:
230
+ hue = (el.red - el.green) / delta / 6 + 2 / 3;
231
+ break;
232
+ }
233
+ }
234
+
235
+ return { hue, saturation, value, alpha: el.alpha };
236
+ }
237
+
238
+ getAlpha( ) {
239
+ return this.rgb[3];
240
+ }
241
+
242
+ setAlpha( a: number ): this {
243
+ this.rgb[3] = clamp( a, 0, 1 );
244
+ return this;
245
+ }
246
+
247
+ isInvalid( ) {
248
+ return this.invalid;
249
+ }
250
+ }