@qtoggle/qui 0.0.0

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 (202) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +492 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
  6. package/.github/workflows/main.yml +74 -0
  7. package/.pre-commit-config.yaml +8 -0
  8. package/LICENSE.txt +177 -0
  9. package/README.md +4 -0
  10. package/font/dejavusans-bold.woff +0 -0
  11. package/font/dejavusans-bolditalic.woff +0 -0
  12. package/font/dejavusans-italic.woff +0 -0
  13. package/font/dejavusans-regular.woff +0 -0
  14. package/img/qui-icons.svg +1937 -0
  15. package/js/base/base.js +47 -0
  16. package/js/base/condition-variable.js +92 -0
  17. package/js/base/errors.js +36 -0
  18. package/js/base/i18n.js +20 -0
  19. package/js/base/mixwith.js +135 -0
  20. package/js/base/require-js-compat.js +78 -0
  21. package/js/base/signal.js +91 -0
  22. package/js/base/singleton.js +66 -0
  23. package/js/base/timer.js +126 -0
  24. package/js/config.js +184 -0
  25. package/js/forms/common-fields/check-field.js +42 -0
  26. package/js/forms/common-fields/choice-buttons-field.js +30 -0
  27. package/js/forms/common-fields/color-combo-field.js +37 -0
  28. package/js/forms/common-fields/combo-field.js +108 -0
  29. package/js/forms/common-fields/common-fields.js +23 -0
  30. package/js/forms/common-fields/composite-field.js +132 -0
  31. package/js/forms/common-fields/custom-html-field.js +51 -0
  32. package/js/forms/common-fields/email-field.js +30 -0
  33. package/js/forms/common-fields/file-picker-field.js +46 -0
  34. package/js/forms/common-fields/jquery-ui-field.js +111 -0
  35. package/js/forms/common-fields/labels-field.js +69 -0
  36. package/js/forms/common-fields/numeric-field.js +39 -0
  37. package/js/forms/common-fields/password-field.js +28 -0
  38. package/js/forms/common-fields/phone-field.js +26 -0
  39. package/js/forms/common-fields/progress-disk-field.js +69 -0
  40. package/js/forms/common-fields/push-button-field.js +138 -0
  41. package/js/forms/common-fields/slider-field.js +51 -0
  42. package/js/forms/common-fields/text-area-field.js +34 -0
  43. package/js/forms/common-fields/text-field.js +89 -0
  44. package/js/forms/common-fields/up-down-field.js +85 -0
  45. package/js/forms/common-forms/common-forms.js +16 -0
  46. package/js/forms/common-forms/options-form.js +77 -0
  47. package/js/forms/common-forms/page-form.js +115 -0
  48. package/js/forms/form-button.js +202 -0
  49. package/js/forms/form-field.js +1183 -0
  50. package/js/forms/form.js +1181 -0
  51. package/js/forms/forms.js +68 -0
  52. package/js/global-glass.js +100 -0
  53. package/js/icons/default-stock.js +173 -0
  54. package/js/icons/icon.js +64 -0
  55. package/js/icons/icons.js +16 -0
  56. package/js/icons/multi-state-sprites-icon.js +362 -0
  57. package/js/icons/stock-icon.js +219 -0
  58. package/js/icons/stock.js +98 -0
  59. package/js/icons/stocks.js +57 -0
  60. package/js/index.js +232 -0
  61. package/js/lib/jquery.longpress.js +79 -0
  62. package/js/lib/jquery.module.js +4 -0
  63. package/js/lib/logger.module.js +4 -0
  64. package/js/lib/pep.module.js +4 -0
  65. package/js/lists/common-items/common-items.js +5 -0
  66. package/js/lists/common-items/icon-label-list-item.js +86 -0
  67. package/js/lists/common-lists/common-lists.js +5 -0
  68. package/js/lists/common-lists/page-list.js +53 -0
  69. package/js/lists/list-item.js +147 -0
  70. package/js/lists/list.js +636 -0
  71. package/js/lists/lists.js +26 -0
  72. package/js/main-ui/main-ui.js +64 -0
  73. package/js/main-ui/menu-bar.js +144 -0
  74. package/js/main-ui/options-bar.js +181 -0
  75. package/js/main-ui/status.js +185 -0
  76. package/js/main-ui/top-bar.js +59 -0
  77. package/js/messages/common-message-forms/common-message-forms.js +7 -0
  78. package/js/messages/common-message-forms/confirm-message-form.js +81 -0
  79. package/js/messages/common-message-forms/simple-message-form.js +67 -0
  80. package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
  81. package/js/messages/message-form.js +107 -0
  82. package/js/messages/messages.js +21 -0
  83. package/js/messages/sticky-modal-page.js +98 -0
  84. package/js/messages/sticky-modal-progress-message.js +27 -0
  85. package/js/messages/toast.js +164 -0
  86. package/js/navigation.js +654 -0
  87. package/js/pages/breadcrumbs.js +124 -0
  88. package/js/pages/common-pages/common-pages.js +6 -0
  89. package/js/pages/common-pages/modal-progress-page.js +83 -0
  90. package/js/pages/common-pages/structured-page.js +46 -0
  91. package/js/pages/page.js +1018 -0
  92. package/js/pages/pages-context.js +154 -0
  93. package/js/pages/pages.js +252 -0
  94. package/js/pwa.js +337 -0
  95. package/js/sections/section.js +612 -0
  96. package/js/sections/sections.js +300 -0
  97. package/js/tables/common-cells/common-cells.js +7 -0
  98. package/js/tables/common-cells/icon-label-table-cell.js +68 -0
  99. package/js/tables/common-cells/push-button-table-cell.js +133 -0
  100. package/js/tables/common-cells/simple-table-cell.js +37 -0
  101. package/js/tables/common-tables/common-tables.js +5 -0
  102. package/js/tables/common-tables/page-table.js +55 -0
  103. package/js/tables/table-cell.js +198 -0
  104. package/js/tables/table-row.js +126 -0
  105. package/js/tables/table.js +492 -0
  106. package/js/tables/tables.js +36 -0
  107. package/js/theme.js +304 -0
  108. package/js/utils/ajax.js +126 -0
  109. package/js/utils/array.js +194 -0
  110. package/js/utils/colors.js +445 -0
  111. package/js/utils/cookies.js +65 -0
  112. package/js/utils/crypto.js +439 -0
  113. package/js/utils/css.js +234 -0
  114. package/js/utils/date.js +300 -0
  115. package/js/utils/files.js +27 -0
  116. package/js/utils/gestures.js +165 -0
  117. package/js/utils/html.js +76 -0
  118. package/js/utils/misc.js +81 -0
  119. package/js/utils/object.js +324 -0
  120. package/js/utils/promise.js +49 -0
  121. package/js/utils/string.js +192 -0
  122. package/js/utils/url.js +187 -0
  123. package/js/utils/utils.js +3 -0
  124. package/js/utils/visibility-manager.js +211 -0
  125. package/js/views/common-views/common-views.js +7 -0
  126. package/js/views/common-views/icon-label-view.js +210 -0
  127. package/js/views/common-views/progress-view.js +89 -0
  128. package/js/views/common-views/structured-view.js +368 -0
  129. package/js/views/view.js +467 -0
  130. package/js/views/views.js +3 -0
  131. package/js/widgets/base-widget.js +23 -0
  132. package/js/widgets/common-widgets/check-button.js +109 -0
  133. package/js/widgets/common-widgets/choice-buttons.js +322 -0
  134. package/js/widgets/common-widgets/color-combo.js +104 -0
  135. package/js/widgets/common-widgets/combo.js +645 -0
  136. package/js/widgets/common-widgets/common-widgets.js +17 -0
  137. package/js/widgets/common-widgets/email-input.js +7 -0
  138. package/js/widgets/common-widgets/file-picker.js +133 -0
  139. package/js/widgets/common-widgets/labels.js +132 -0
  140. package/js/widgets/common-widgets/numeric-input.js +49 -0
  141. package/js/widgets/common-widgets/password-input.js +91 -0
  142. package/js/widgets/common-widgets/phone-input.js +7 -0
  143. package/js/widgets/common-widgets/progress-disk.js +174 -0
  144. package/js/widgets/common-widgets/push-button.js +155 -0
  145. package/js/widgets/common-widgets/slider.js +455 -0
  146. package/js/widgets/common-widgets/text-area.js +52 -0
  147. package/js/widgets/common-widgets/text-input.js +174 -0
  148. package/js/widgets/common-widgets/up-down.js +351 -0
  149. package/js/widgets/widgets.js +57 -0
  150. package/js/window.js +557 -0
  151. package/jsdoc.conf.json +20 -0
  152. package/less/base.less +123 -0
  153. package/less/forms/common-fields.less +101 -0
  154. package/less/forms/common-forms.less +5 -0
  155. package/less/forms/form-button.less +21 -0
  156. package/less/forms/form-field.less +266 -0
  157. package/less/forms/form.less +131 -0
  158. package/less/global-glass.less +64 -0
  159. package/less/icon-label-view.less +82 -0
  160. package/less/icons.less +144 -0
  161. package/less/lists.less +105 -0
  162. package/less/main-ui.less +328 -0
  163. package/less/messages.less +189 -0
  164. package/less/no-effects.less +24 -0
  165. package/less/pages/breadcrumbs.less +98 -0
  166. package/less/pages/common-pages.less +36 -0
  167. package/less/pages/page.less +70 -0
  168. package/less/progress-view.less +51 -0
  169. package/less/stock-icons.less +43 -0
  170. package/less/structured-view.less +245 -0
  171. package/less/tables.less +84 -0
  172. package/less/theme-dark.less +133 -0
  173. package/less/theme-light.less +132 -0
  174. package/less/theme.less +419 -0
  175. package/less/visibility-manager.less +11 -0
  176. package/less/widgets/check-button.less +96 -0
  177. package/less/widgets/choice-buttons.less +160 -0
  178. package/less/widgets/color-combo.less +33 -0
  179. package/less/widgets/combo.less +230 -0
  180. package/less/widgets/common-buttons.less +120 -0
  181. package/less/widgets/common.less +24 -0
  182. package/less/widgets/input.less +258 -0
  183. package/less/widgets/labels.less +81 -0
  184. package/less/widgets/progress-disk.less +70 -0
  185. package/less/widgets/slider.less +199 -0
  186. package/less/widgets/updown.less +115 -0
  187. package/less/widgets/various.less +36 -0
  188. package/package.json +47 -0
  189. package/pyproject.toml +45 -0
  190. package/qui/__init__.py +110 -0
  191. package/qui/constants.py +1 -0
  192. package/qui/exceptions.py +2 -0
  193. package/qui/j2template.py +71 -0
  194. package/qui/settings.py +60 -0
  195. package/qui/templates/manifest.json +25 -0
  196. package/qui/templates/qui.html +126 -0
  197. package/qui/templates/service-worker.js +188 -0
  198. package/qui/web/__init__.py +0 -0
  199. package/qui/web/tornado.py +220 -0
  200. package/scripts/postinstall.sh +10 -0
  201. package/webpack/webpack-adjust-css-urls-loader.js +36 -0
  202. package/webpack/webpack-common.js +384 -0
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Deals with color format conversions and color adjustments.
3
+ *
4
+ * Contains code taken from https://github.com/antimatter15/rgb-lab/
5
+ * @namespace qui.utils.colors
6
+ */
7
+
8
+ /* eslint-disable no-multi-spaces */
9
+
10
+
11
+ let cachedColorsRGBAByName = {}
12
+
13
+
14
+ /**
15
+ * Convert a tuple of (*hue*, *saturation*, *value*) components into (*red*, *green*, *blue*) equivalent.
16
+ *
17
+ * *red*, *green* and *blue* range from `0` to `255`. *hue* ranges from `0` to `359`, while *saturation* and *value*
18
+ * range from `0` to `1`.
19
+ *
20
+ * @alias qui.utils.colors.hsv2rgb
21
+ * @param {Number[]} hsv a 3 elements array representing the *hue*, *saturation* and *value* components
22
+ * @returns {Number[]} a 3 elements array representing the *red*, *green* and *blue* components
23
+ */
24
+ export function hsv2rgb(hsv) {
25
+ let h = hsv[0], s = hsv[1], v = hsv[2]
26
+ let hi = Math.floor(h / 60.0) % 6
27
+ let f = (h / 60.0) - Math.floor(h / 60.0)
28
+ let p = v * (1.0 - s)
29
+ let q = v * (1.0 - (f * s))
30
+ let t = v * (1.0 - ((1.0 - f) * s))
31
+
32
+ v *= 255
33
+ t *= 255
34
+ p *= 255
35
+ q *= 255
36
+
37
+ let rgb = [
38
+ [v, t, p],
39
+ [q, v, p],
40
+ [p, v, t],
41
+ [p, q, v],
42
+ [t, p, v],
43
+ [v, p, q]
44
+ ][hi]
45
+
46
+ return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2])]
47
+ }
48
+
49
+ /**
50
+ * Convert a tuple of (*red*, *green*, *blue*) components into (*hue*, *saturation*, *value*) equivalent.
51
+ *
52
+ * *red*, *green* and *blue* range from `0` to `255`. *hue* ranges from `0` to `359`, while *saturation* and *value*
53
+ * range from `0` to `1`.
54
+ *
55
+ * @alias qui.utils.colors.rgb2hsv
56
+ * @param {Number[]} rgb a 3 elements array representing the *red*, *green* and *blue* components
57
+ * @returns {Number[]} a 3 elements array representing the *hue*, *saturation* and *value* components
58
+ */
59
+ export function rgb2hsv(rgb) {
60
+ let r = rgb[0] / 255
61
+ let g = rgb[1] / 255
62
+ let b = rgb[2] / 255
63
+
64
+ let min = Math.min(r, g, b)
65
+ let max = Math.max(r, g, b)
66
+ let delta = max - min
67
+
68
+ let h = 0
69
+ let s = 0
70
+ let v = max
71
+
72
+ if (delta !== 0) {
73
+ s = delta / max
74
+ let dr = (((max - r) / 6) + (delta / 2)) / delta
75
+ let dg = (((max - g) / 6) + (delta / 2)) / delta
76
+ let db = (((max - b) / 6) + (delta / 2)) / delta
77
+
78
+ if (r === max) {
79
+ h = db - dg
80
+ }
81
+ else if (g === max) {
82
+ h = (1 / 3) + dr - db
83
+ }
84
+ else if (b === max) {
85
+ h = (2 / 3) + dg - dr
86
+ }
87
+
88
+ if (h < 0) {
89
+ h += 1
90
+ }
91
+ if (h > 1) {
92
+ h -= 1
93
+ }
94
+ }
95
+
96
+ h = Math.round(h * 360)
97
+
98
+ return [h, s, v]
99
+ }
100
+
101
+ /**
102
+ * Convert a color string into (*red*, *green*, *blue*, *alpha*) equivalent.
103
+ *
104
+ * *red*, *green* and *blue* range from `0` to `255`, while *alpha* ranges from `0` to `1`. Accepted string color
105
+ * formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
106
+ *
107
+ * @alias qui.utils.colors.str2rgba
108
+ * @param {String} strColor
109
+ * @returns {Number[]} a 4 elements array representing the *red*, *green*, *blue* and *alpha* components
110
+ */
111
+ export function str2rgba(strColor) {
112
+ if (!strColor) {
113
+ return [0, 0, 0, 1] /* Defaults to black */
114
+ }
115
+
116
+ let r = 0, g = 0, b = 0, a = 1
117
+ let start, stop, parts
118
+
119
+ if (strColor.startsWith('#')) {
120
+ if (strColor.length === 4) {
121
+ r = strColor.substr(1, 1)
122
+ g = strColor.substr(2, 1)
123
+ b = strColor.substr(3, 1)
124
+
125
+ r = parseInt(r + r, 16)
126
+ g = parseInt(g + g, 16)
127
+ b = parseInt(b + b, 16)
128
+ }
129
+ else if (strColor.length === 7) {
130
+ r = parseInt(strColor.substr(1, 2), 16)
131
+ g = parseInt(strColor.substr(3, 2), 16)
132
+ b = parseInt(strColor.substr(5, 2), 16)
133
+ }
134
+ }
135
+ else if (strColor.startsWith('rgba')) {
136
+ start = strColor.indexOf('(')
137
+ stop = strColor.indexOf(')')
138
+
139
+ if (start !== -1 && stop !== -1) {
140
+ strColor = strColor.substring(start + 1, stop)
141
+ parts = strColor.split(',')
142
+ if (parts.length === 4) {
143
+ r = parseInt(parts[0].trim())
144
+ g = parseInt(parts[1].trim())
145
+ b = parseInt(parts[2].trim())
146
+ a = parseFloat(parts[3].trim())
147
+ }
148
+ }
149
+ }
150
+ else if (strColor.startsWith('rgb')) {
151
+ start = strColor.indexOf('(')
152
+ stop = strColor.indexOf(')')
153
+
154
+ if (start !== -1 && stop !== -1) {
155
+ strColor = strColor.substring(start + 1, stop)
156
+ parts = strColor.split(',')
157
+ if (parts.length === 3) {
158
+ r = parseInt(parts[0].trim())
159
+ g = parseInt(parts[1].trim())
160
+ b = parseInt(parts[2].trim())
161
+ }
162
+ }
163
+ }
164
+ else { /* A color name */
165
+ let colorRGBA = cachedColorsRGBAByName[strColor]
166
+ if (colorRGBA) {
167
+ return colorRGBA
168
+ }
169
+
170
+ let div = document.createElement('div')
171
+ div.style.display = 'none'
172
+ div.style.color = strColor
173
+ document.body.appendChild(div)
174
+
175
+ let style = window.getComputedStyle(div)
176
+ let result = str2rgba(style.color)
177
+
178
+ document.body.removeChild(div)
179
+
180
+ cachedColorsRGBAByName[strColor] = result
181
+ return result
182
+ }
183
+
184
+ return [r, g, b, a]
185
+ }
186
+
187
+ /**
188
+ * Convert a tuple of (*red*, *green*, *blue*, *alpha*) components into color string equivalent.
189
+ *
190
+ * *red*, *green* and *blue* range from `0` to `255`, while *alpha* ranges from `0` to `1`. Returned string color format
191
+ * is `rgba(r, g, b, a)` or `#rrggbb`, depending on the presence of the alpha factor.
192
+ *
193
+ * @alias qui.utils.colors.rgba2str
194
+ * @param {Number[]} rgba a 4 elements array representing the *red*, *green*, *blue* and *alpha* components,
195
+ * respectively
196
+ * @returns {String}
197
+ */
198
+ export function rgba2str(rgba) {
199
+ function byte2hex(value) {
200
+ value = parseInt(value).toString(16)
201
+ if (value.length < 2) {
202
+ value = `0${value}`
203
+ }
204
+
205
+ return value
206
+ }
207
+
208
+ if (rgba.length === 3 || (rgba.length === 4 && rgba[3] === 1)) {
209
+ return `#${byte2hex(rgba[0])}${byte2hex(rgba[1])}${byte2hex(rgba[2])}`
210
+ }
211
+ else { /* Assuming the length is 4 */
212
+ return `rgba(${rgba[0]}, ${rgba[1]}, ${rgba[2]}, ${rgba[3]})`
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Convert a tuple of (*lightness*, *a*, *b*) components into (*red*, *green*, *blue*) equivalent. The *lightness*, *a*
218
+ * and *b* components are defined by the CIELAB color space.
219
+ *
220
+ * *red*, *green* and *blue* range from `0` to `255`. *lightness* ranges from `0` to `100`, while *a* and *b* range from
221
+ * `-100` to `100`.
222
+ *
223
+ * @alias qui.utils.colors.lab2rgb
224
+ * @param {Number[]} lab a 3 elements array representing the *lightness*, *a* and *b* components
225
+ * @returns {Number[]} a 3 elements array representing the *red*, *green* and *blue* components
226
+ */
227
+ export function lab2rgb(lab) {
228
+ let y = (lab[0] + 16) / 116
229
+ let x = lab[1] / 500 + y
230
+ let z = y - lab[2] / 200
231
+ let r, g, b
232
+
233
+ x = 0.95047 * ((x * x * x > 0.008856) ? x * x * x : (x - 16 / 116) / 7.787)
234
+ y = 1.00000 * ((y * y * y > 0.008856) ? y * y * y : (y - 16 / 116) / 7.787)
235
+ z = 1.08883 * ((z * z * z > 0.008856) ? z * z * z : (z - 16 / 116) / 7.787)
236
+
237
+ r = x * 3.2406 + y * -1.5372 + z * -0.4986
238
+ g = x * -0.9689 + y * 1.8758 + z * 0.0415
239
+ b = x * 0.0557 + y * -0.2040 + z * 1.0570
240
+
241
+ r = (r > 0.0031308) ? (1.055 * Math.pow(r, 1 / 2.4) - 0.055) : 12.92 * r
242
+ g = (g > 0.0031308) ? (1.055 * Math.pow(g, 1 / 2.4) - 0.055) : 12.92 * g
243
+ b = (b > 0.0031308) ? (1.055 * Math.pow(b, 1 / 2.4) - 0.055) : 12.92 * b
244
+
245
+ return [
246
+ Math.max(0, Math.min(1, r)) * 255,
247
+ Math.max(0, Math.min(1, g)) * 255,
248
+ Math.max(0, Math.min(1, b)) * 255
249
+ ]
250
+ }
251
+
252
+ /**
253
+ * Convert a tuple of (*red*, *green*, *blue*) components into (*lightness*, *a*, *b*) equivalent. The *lightness*, *a*
254
+ * and *b* components are defined by the CIELAB color space.
255
+ *
256
+ * *red*, *green* and *blue* range from `0` to `255`. *lightness* ranges from `0` to `100`, while *a* and *b* range from
257
+ * `-100` to `100`.
258
+ *
259
+ * @alias qui.utils.colors.rgb2lab
260
+ * @param {Number[]} rgb a 3 elements array representing the *red*, *green* and *blue* components
261
+ * @returns {Number[]} lab a 3 elements array representing the *lightness*, *a* and *b* components
262
+ */
263
+ export function rgb2lab(rgb) {
264
+ let r = rgb[0] / 255
265
+ let g = rgb[1] / 255
266
+ let b = rgb[2] / 255
267
+ let x, y, z
268
+
269
+ r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92
270
+ g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92
271
+ b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92
272
+
273
+ x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047
274
+ y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000
275
+ z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883
276
+
277
+ x = (x > 0.008856) ? Math.pow(x, 1 / 3) : (7.787 * x) + 16 / 116
278
+ y = (y > 0.008856) ? Math.pow(y, 1 / 3) : (7.787 * y) + 16 / 116
279
+ z = (z > 0.008856) ? Math.pow(z, 1 / 3) : (7.787 * z) + 16 / 116
280
+
281
+ return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)]
282
+ }
283
+
284
+ /**
285
+ * Compute the luminance of a color, as defined by https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef.
286
+ *
287
+ * *red*, *green* and *blue* range from `0` to `255`. *luminance* ranges from `0` to `1`.
288
+ *
289
+ * @alias qui.utils.colors.luminance
290
+ * @param {Number[]} rgb a 3 elements array representing the *red*, *green* and *blue* components
291
+ * @returns {Number}
292
+ */
293
+ export function luminance(rgb) {
294
+ let a = rgb.map(function (v) {
295
+ v /= 255
296
+
297
+ return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
298
+ })
299
+
300
+ return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722
301
+ }
302
+
303
+ /**
304
+ * Compute the contrast ratio between two colors, as defined by
305
+ * https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef.
306
+ *
307
+ * *red*, *green* and *blue* range from `0` to `255`. *contrast* ranges from `1` to `21`.
308
+ *
309
+ * @alias qui.utils.colors.contrast
310
+ * @param {Number[]} rgb1 a 3 elements array representing the *red*, *green* and *blue* components of the first color
311
+ * @param {Number[]} rgb2 a 3 elements array representing the *red*, *green* and *blue* components of the second color
312
+ * @returns {Number}
313
+ */
314
+ export function contrast(rgb1, rgb2) {
315
+ let c = (luminance(rgb1) + 0.05) / (luminance(rgb2) + 0.05)
316
+ if (c < 1) {
317
+ c = 1 / c
318
+ }
319
+
320
+ return c
321
+ }
322
+
323
+ /**
324
+ * Compute the distance between two colors, as defined by the *deltaE* CIE94 specification.
325
+ *
326
+ * *lightness* ranges from `0` to `100`, while *a* and *b* range from `-100` to `100`. *deltaE* ranges from `0` to
327
+ * `255`.
328
+ *
329
+ * @alias qui.utils.colors.deltaE
330
+ * @param {Number[]} lab1 a 3 elements array representing the *lightness*, *a* and *b* components of the first color
331
+ * @param {Number[]} lab2 a 3 elements array representing the *lightness*, *a* and *b* components of the second color
332
+ * @returns {Number}
333
+ */
334
+ export function deltaE(lab1, lab2) {
335
+ /* CIE94 implementation */
336
+ let deltaL = lab1[0] - lab2[0]
337
+ let deltaA = lab1[1] - lab2[1]
338
+ let deltaB = lab1[2] - lab2[2]
339
+ let c1 = Math.sqrt(lab1[1] * lab1[1] + lab1[2] * lab1[2])
340
+ let c2 = Math.sqrt(lab2[1] * lab2[1] + lab2[2] * lab2[2])
341
+ let deltaC = c1 - c2
342
+ let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC
343
+ deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH)
344
+ let sc = 1.0 + 0.045 * c1
345
+ let sh = 1.0 + 0.015 * c1
346
+ let deltaLklsl = deltaL / (1.0)
347
+ let deltaCkcsc = deltaC / (sc)
348
+ let deltaHkhsh = deltaH / (sh)
349
+ let i = deltaLklsl * deltaLklsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh
350
+
351
+ return i < 0 ? 0 : Math.min(Math.sqrt(i), 255)
352
+ }
353
+
354
+ /**
355
+ * Return a darker variant of a given color.
356
+ *
357
+ * Accepted string color formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
358
+ *
359
+ * @alias qui.utils.colors.darker
360
+ * @param {String} strColor
361
+ * @param {Number} amount the fraction used to alter the value component (from `0` to `1`)
362
+ * @returns {String}
363
+ */
364
+ export function darker(strColor, amount) {
365
+ let rgba = str2rgba(strColor)
366
+ let alpha = rgba[3]
367
+ let hsv = rgb2hsv(rgba.slice(0, 3))
368
+ hsv[2] /= amount
369
+
370
+ rgba = hsv2rgb(hsv)
371
+ rgba.push(alpha)
372
+
373
+ return rgba2str(rgba)
374
+ }
375
+
376
+ /**
377
+ * Return a lighter variant of a given color.
378
+ *
379
+ * Accepted string color formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
380
+ *
381
+ * @alias qui.utils.colors.lighter
382
+ * @param {String} strColor
383
+ * @param {Number} amount the fraction used to alter the value component (from `0` to `1`)
384
+ * @returns {String}
385
+ */
386
+ export function lighter(strColor, amount) {
387
+ return darker(strColor, 1 / amount)
388
+ }
389
+
390
+ /**
391
+ * Alter the alpha factor of a color.
392
+ *
393
+ * Accepted string color formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
394
+ *
395
+ * @alias qui.utils.colors.alpha
396
+ * @param {String} strColor
397
+ * @param {Number} factor the alpha factor (from `0` to `1`)
398
+ * @returns {String}
399
+ */
400
+ export function alpha(strColor, factor) {
401
+ let rgba = str2rgba(strColor)
402
+ rgba[3] = factor
403
+
404
+ return rgba2str(rgba)
405
+ }
406
+
407
+ /**
408
+ * Mix two colors.
409
+ *
410
+ * Accepted string color formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
411
+ *
412
+ * @alias qui.utils.colors.mix
413
+ * @param {String} strColor1
414
+ * @param {String} strColor2
415
+ * @param {Number} factor the ratio by which the two input colors contribute to the output color; `0` results in 100% of
416
+ * `strColor1` and `1` results in 100% of `strColor2`
417
+ * @returns {String}
418
+ */
419
+ export function mix(strColor1, strColor2, factor) {
420
+ let rgba1 = str2rgba(strColor1)
421
+ let rgba2 = str2rgba(strColor2)
422
+
423
+ let r = rgba1[0] * (1 - factor) + rgba2[0] * factor
424
+ let g = rgba1[1] * (1 - factor) + rgba2[1] * factor
425
+ let b = rgba1[2] * (1 - factor) + rgba2[2] * factor
426
+ let a = rgba1[3] * (1 - factor) + rgba2[3] * factor
427
+
428
+ return rgba2str([r, g, b, a])
429
+ }
430
+
431
+ /**
432
+ * Normalize a color by converting it to the most appropriate string format.
433
+ *
434
+ * Accepted string color formats are `rgb(r, g, b)`, `rgba(r, g, b, a)`, `#rrggbb` and an HTML color name.
435
+ *
436
+ * Colors with alpha factor are represented as `rgba(r, g, b, a)`, while those without alpha factor are represented as
437
+ * `#rrggbb`.
438
+ *
439
+ * @alias qui.utils.colors.normalize
440
+ * @param {String} strColor
441
+ * @returns {String}
442
+ */
443
+ export function normalize(strColor) {
444
+ return rgba2str(str2rgba(strColor))
445
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @namespace qui.utils.cookies
3
+ */
4
+
5
+ /**
6
+ * Return the value of a cookie.
7
+ * @alias qui.utils.cookies.get
8
+ * @param {String} name cookie name
9
+ * @param {*} def default value to return if cookie not found
10
+ * @returns {?String}
11
+ */
12
+ export function get(name, def = null) {
13
+ let cookie = document.cookie.substring(0)
14
+
15
+ if (cookie.length <= 0) {
16
+ return def
17
+ }
18
+
19
+ let start = cookie.indexOf(`${name}=`)
20
+ if (start === -1) {
21
+ return def
22
+ }
23
+
24
+ start = start + name.length + 1
25
+ let end = cookie.indexOf(';', start)
26
+ if (end === -1) {
27
+ end = cookie.length
28
+ }
29
+
30
+ return cookie.substring(start, end)
31
+ }
32
+
33
+ /**
34
+ * Set the value of a cookie, optionally indicating a validity period.
35
+ * @alias qui.utils.cookies.set
36
+ * @param {String} name cookie name
37
+ * @param {String} value cookie value
38
+ * @param {Number} [validDays] number of days of validity; defaults to `null`, in which case cookie never expires
39
+ */
40
+ export function set(name, value, validDays = null) {
41
+ let date, expires
42
+ if (validDays) {
43
+ date = new Date()
44
+ date.setTime(date.getTime() + (validDays * 24 * 60 * 60 * 1000))
45
+ expires = `expires=${date.toUTCString()}`
46
+ }
47
+ else {
48
+ expires = ''
49
+ }
50
+
51
+ document.cookie = `${name}=${value}; ${expires}; path=/`
52
+ }
53
+
54
+ /**
55
+ * Clear a cookie.
56
+ * @alias qui.utils.cookies.clear
57
+ * @param {String} name cookie name
58
+ */
59
+ export function clear(name) {
60
+ let date = new Date()
61
+ date.setTime(date.getTime() + (-1 * 24 * 60 * 60 * 1000))
62
+ let expires = `expires=${date.toUTCString()}`
63
+
64
+ document.cookie = `${name}=; ${expires}; path=/`
65
+ }