@vandenberghinc/volt 1.1.4 → 1.1.6

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 (290) hide show
  1. package/backend/dist/cjs/database.d.ts +41 -68
  2. package/backend/dist/cjs/database.js +136 -78
  3. package/backend/dist/cjs/endpoint.d.ts +23 -9
  4. package/backend/dist/cjs/endpoint.js +98 -21
  5. package/backend/dist/cjs/file_watcher.js +2 -2
  6. package/backend/dist/cjs/frontend.d.ts +0 -2
  7. package/backend/dist/cjs/frontend.js +9 -9
  8. package/backend/dist/cjs/image_endpoint.d.ts +3 -1
  9. package/backend/dist/cjs/image_endpoint.js +2 -1
  10. package/backend/dist/cjs/payments/paddle.js +10 -2
  11. package/backend/dist/cjs/plugins/css.d.ts +6 -5
  12. package/backend/dist/cjs/plugins/css.js +32 -7
  13. package/backend/dist/cjs/plugins/ts/compiler.d.ts +6 -1
  14. package/backend/dist/cjs/plugins/ts/compiler.js +26 -2
  15. package/backend/dist/cjs/plugins/ts/preprocessing.js +5 -3
  16. package/backend/dist/cjs/server.d.ts +7 -13
  17. package/backend/dist/cjs/server.js +184 -303
  18. package/backend/dist/cjs/status.d.ts +1 -0
  19. package/backend/dist/cjs/status.js +2 -1
  20. package/backend/dist/cjs/stream.d.ts +5 -3
  21. package/backend/dist/cjs/stream.js +13 -4
  22. package/backend/dist/cjs/users.d.ts +1 -1
  23. package/backend/dist/cjs/users.js +87 -72
  24. package/backend/dist/cjs/utils.d.ts +17 -9
  25. package/backend/dist/cjs/utils.js +22 -64
  26. package/backend/dist/cjs/view.d.ts +2 -2
  27. package/backend/dist/cjs/view.js +38 -40
  28. package/backend/dist/cjs/volt.d.ts +3 -2
  29. package/backend/dist/cjs/volt.js +2 -2
  30. package/backend/dist/css/volt.css +5 -0
  31. package/backend/dist/esm/database.d.ts +41 -68
  32. package/backend/dist/esm/database.js +137 -79
  33. package/backend/dist/esm/endpoint.d.ts +23 -9
  34. package/backend/dist/esm/endpoint.js +99 -22
  35. package/backend/dist/esm/file_watcher.js +2 -2
  36. package/backend/dist/esm/frontend.d.ts +0 -2
  37. package/backend/dist/esm/frontend.js +9 -9
  38. package/backend/dist/esm/image_endpoint.d.ts +3 -1
  39. package/backend/dist/esm/image_endpoint.js +2 -1
  40. package/backend/dist/esm/payments/paddle.js +11 -3
  41. package/backend/dist/esm/plugins/css.d.ts +6 -5
  42. package/backend/dist/esm/plugins/css.js +32 -6
  43. package/backend/dist/esm/plugins/ts/compiler.d.ts +6 -1
  44. package/backend/dist/esm/plugins/ts/compiler.js +26 -2
  45. package/backend/dist/esm/plugins/ts/preprocessing.js +5 -3
  46. package/backend/dist/esm/server.d.ts +7 -13
  47. package/backend/dist/esm/server.js +182 -301
  48. package/backend/dist/esm/status.d.ts +1 -0
  49. package/backend/dist/esm/status.js +1 -0
  50. package/backend/dist/esm/stream.d.ts +5 -3
  51. package/backend/dist/esm/stream.js +13 -4
  52. package/backend/dist/esm/users.d.ts +1 -1
  53. package/backend/dist/esm/users.js +87 -72
  54. package/backend/dist/esm/utils.d.ts +17 -9
  55. package/backend/dist/esm/utils.js +21 -62
  56. package/backend/dist/esm/view.d.ts +2 -2
  57. package/backend/dist/esm/view.js +38 -40
  58. package/backend/dist/esm/volt.d.ts +3 -2
  59. package/backend/dist/esm/volt.js +2 -1
  60. package/backend/dist/esm-dev/blacklist.js +1 -1
  61. package/backend/dist/esm-dev/cli.js +2 -2
  62. package/backend/dist/esm-dev/database.d.ts +41 -68
  63. package/backend/dist/esm-dev/database.js +138 -80
  64. package/backend/dist/esm-dev/endpoint.d.ts +23 -9
  65. package/backend/dist/esm-dev/endpoint.js +100 -23
  66. package/backend/dist/esm-dev/file_watcher.js +3 -3
  67. package/backend/dist/esm-dev/frontend.d.ts +0 -2
  68. package/backend/dist/esm-dev/frontend.js +9 -9
  69. package/backend/dist/esm-dev/image_endpoint.d.ts +3 -1
  70. package/backend/dist/esm-dev/image_endpoint.js +2 -1
  71. package/backend/dist/esm-dev/logger.js +1 -1
  72. package/backend/dist/esm-dev/payments/paddle.js +12 -4
  73. package/backend/dist/esm-dev/plugins/css.d.ts +6 -5
  74. package/backend/dist/esm-dev/plugins/css.js +33 -7
  75. package/backend/dist/esm-dev/plugins/ts/compiler.d.ts +6 -1
  76. package/backend/dist/esm-dev/plugins/ts/compiler.js +27 -3
  77. package/backend/dist/esm-dev/plugins/ts/preprocessing.js +7 -5
  78. package/backend/dist/esm-dev/rate_limit.js +1 -1
  79. package/backend/dist/esm-dev/server.d.ts +7 -13
  80. package/backend/dist/esm-dev/server.js +184 -303
  81. package/backend/dist/esm-dev/status.d.ts +1 -0
  82. package/backend/dist/esm-dev/status.js +1 -0
  83. package/backend/dist/esm-dev/stream.d.ts +5 -3
  84. package/backend/dist/esm-dev/stream.js +13 -4
  85. package/backend/dist/esm-dev/users.d.ts +1 -1
  86. package/backend/dist/esm-dev/users.js +88 -73
  87. package/backend/dist/esm-dev/utils.d.ts +17 -9
  88. package/backend/dist/esm-dev/utils.js +22 -63
  89. package/backend/dist/esm-dev/view.d.ts +2 -2
  90. package/backend/dist/esm-dev/view.js +39 -41
  91. package/backend/dist/esm-dev/volt.d.ts +3 -2
  92. package/backend/dist/esm-dev/volt.js +2 -1
  93. package/backend/src/database.ts +173 -155
  94. package/backend/src/endpoint.ts +123 -31
  95. package/backend/src/file_watcher.ts +2 -2
  96. package/backend/src/frontend.ts +9 -8
  97. package/backend/src/image_endpoint.ts +4 -0
  98. package/backend/src/payments/paddle.ts +11 -3
  99. package/backend/src/plugins/css.ts +36 -8
  100. package/backend/src/plugins/ts/compiler.ts +37 -1
  101. package/backend/src/plugins/ts/preprocessing.ts +5 -3
  102. package/backend/src/server.ts +167 -306
  103. package/backend/src/status.ts +1 -0
  104. package/backend/src/stream.ts +28 -8
  105. package/backend/src/users.ts +87 -72
  106. package/backend/src/utils.ts +58 -25
  107. package/backend/src/view.ts +30 -28
  108. package/backend/src/{volt.js → volt.ts} +2 -1
  109. package/backend/tsconfig.cjs.json +3 -3
  110. package/backend/tsconfig.esm.json +3 -3
  111. package/frontend/dist/elements/base.d.ts +414 -432
  112. package/frontend/dist/elements/base.js +566 -329
  113. package/frontend/dist/elements/module.d.ts +26 -12
  114. package/frontend/dist/elements/module.js +69 -32
  115. package/frontend/dist/elements/register_element.d.ts +3 -0
  116. package/frontend/dist/elements/register_element.js +22 -0
  117. package/frontend/dist/modules/auth.d.ts +1 -0
  118. package/frontend/dist/modules/auth.js +6 -5
  119. package/frontend/dist/modules/color.d.ts +159 -0
  120. package/frontend/dist/modules/color.js +315 -0
  121. package/frontend/dist/modules/colors.d.ts +1 -26
  122. package/frontend/dist/modules/colors.js +417 -340
  123. package/frontend/dist/modules/cookies.d.ts +1 -0
  124. package/frontend/dist/modules/cookies.js +1 -0
  125. package/frontend/dist/modules/events.d.ts +1 -0
  126. package/frontend/dist/modules/events.js +1 -0
  127. package/frontend/dist/modules/google.d.ts +1 -0
  128. package/frontend/dist/modules/google.js +1 -0
  129. package/frontend/dist/modules/meta.d.ts +1 -0
  130. package/frontend/dist/modules/meta.js +1 -0
  131. package/frontend/dist/modules/mutex.d.ts +1 -2
  132. package/frontend/dist/modules/mutex.js +3 -4
  133. package/frontend/dist/modules/paddle.d.ts +1 -0
  134. package/frontend/dist/modules/paddle.js +14 -13
  135. package/frontend/dist/modules/scheme.d.ts +1 -0
  136. package/frontend/dist/modules/scheme.js +5 -3
  137. package/frontend/dist/modules/statics.d.ts +1 -0
  138. package/frontend/dist/modules/statics.js +1 -0
  139. package/frontend/dist/modules/support.d.ts +1 -0
  140. package/frontend/dist/modules/support.js +3 -2
  141. package/frontend/dist/modules/theme.d.ts +56 -0
  142. package/frontend/dist/{ui → modules}/theme.js +186 -75
  143. package/frontend/dist/modules/themes.d.ts +1 -1
  144. package/frontend/dist/modules/themes.js +1 -0
  145. package/frontend/dist/modules/user.d.ts +1 -0
  146. package/frontend/dist/modules/user.js +11 -10
  147. package/frontend/dist/modules/utils.d.ts +23 -2
  148. package/frontend/dist/modules/utils.js +93 -1
  149. package/frontend/dist/types/gradient.js +4 -0
  150. package/frontend/dist/ui/border_button.d.ts +0 -25
  151. package/frontend/dist/ui/border_button.js +50 -51
  152. package/frontend/dist/ui/button.d.ts +0 -21
  153. package/frontend/dist/ui/button.js +41 -46
  154. package/frontend/dist/ui/canvas.js +15 -15
  155. package/frontend/dist/ui/checkbox.d.ts +3 -17
  156. package/frontend/dist/ui/checkbox.js +36 -30
  157. package/frontend/dist/ui/code.d.ts +15 -82
  158. package/frontend/dist/ui/code.js +150 -125
  159. package/frontend/dist/ui/color.d.ts +0 -1
  160. package/frontend/dist/ui/color.js +1 -1
  161. package/frontend/dist/ui/context_menu.d.ts +4 -2
  162. package/frontend/dist/ui/context_menu.js +16 -17
  163. package/frontend/dist/ui/css.js +2 -0
  164. package/frontend/dist/ui/divider.d.ts +0 -7
  165. package/frontend/dist/ui/divider.js +21 -25
  166. package/frontend/dist/ui/dropdown.d.ts +13 -7
  167. package/frontend/dist/ui/dropdown.js +65 -30
  168. package/frontend/dist/ui/for_each.d.ts +0 -5
  169. package/frontend/dist/ui/for_each.js +17 -22
  170. package/frontend/dist/ui/form.d.ts +17 -12
  171. package/frontend/dist/ui/form.js +21 -18
  172. package/frontend/dist/ui/frame_modes.d.ts +9 -12
  173. package/frontend/dist/ui/frame_modes.js +8 -10
  174. package/frontend/dist/ui/google_map.d.ts +0 -11
  175. package/frontend/dist/ui/google_map.js +23 -28
  176. package/frontend/dist/ui/gradient.d.ts +0 -5
  177. package/frontend/dist/ui/gradient.js +17 -22
  178. package/frontend/dist/ui/image.d.ts +27 -58
  179. package/frontend/dist/ui/image.js +99 -93
  180. package/frontend/dist/ui/input.d.ts +20 -97
  181. package/frontend/dist/ui/input.js +192 -170
  182. package/frontend/dist/ui/link.d.ts +0 -18
  183. package/frontend/dist/ui/link.js +42 -48
  184. package/frontend/dist/ui/list.js +36 -37
  185. package/frontend/dist/ui/loader_button.d.ts +4 -19
  186. package/frontend/dist/ui/loader_button.js +35 -37
  187. package/frontend/dist/ui/loaders.d.ts +0 -8
  188. package/frontend/dist/ui/loaders.js +20 -25
  189. package/frontend/dist/ui/popup.d.ts +11 -8
  190. package/frontend/dist/ui/popup.js +183 -24
  191. package/frontend/dist/ui/pseudo.d.ts +3 -3
  192. package/frontend/dist/ui/pseudo.js +14 -17
  193. package/frontend/dist/ui/scroller.d.ts +10 -48
  194. package/frontend/dist/ui/scroller.js +306 -300
  195. package/frontend/dist/ui/slider.d.ts +9 -3
  196. package/frontend/dist/ui/slider.js +31 -17
  197. package/frontend/dist/ui/spacer.d.ts +0 -9
  198. package/frontend/dist/ui/spacer.js +21 -26
  199. package/frontend/dist/ui/span.js +13 -15
  200. package/frontend/dist/ui/stack.d.ts +14 -75
  201. package/frontend/dist/ui/stack.js +166 -169
  202. package/frontend/dist/ui/steps.d.ts +10 -23
  203. package/frontend/dist/ui/steps.js +47 -34
  204. package/frontend/dist/ui/style.d.ts +4 -3
  205. package/frontend/dist/ui/style.js +13 -18
  206. package/frontend/dist/ui/switch.d.ts +10 -4
  207. package/frontend/dist/ui/switch.js +24 -16
  208. package/frontend/dist/ui/table.d.ts +0 -23
  209. package/frontend/dist/ui/table.js +113 -119
  210. package/frontend/dist/ui/tabs.d.ts +3 -19
  211. package/frontend/dist/ui/tabs.js +35 -29
  212. package/frontend/dist/ui/text.d.ts +0 -8
  213. package/frontend/dist/ui/text.js +20 -25
  214. package/frontend/dist/ui/title.d.ts +0 -15
  215. package/frontend/dist/ui/title.js +39 -45
  216. package/frontend/dist/ui/ui.d.ts +0 -2
  217. package/frontend/dist/ui/ui.js +0 -2
  218. package/frontend/dist/ui/view.d.ts +3 -17
  219. package/frontend/dist/ui/view.js +27 -32
  220. package/frontend/dist/volt.d.ts +2 -1
  221. package/frontend/dist/volt.js +3 -1
  222. package/frontend/examples/dashboard/dashboard.ts +774 -0
  223. package/frontend/examples/theme/theme.ts +58 -0
  224. package/frontend/src/css/volt.css +5 -0
  225. package/frontend/src/elements/base.ts +767 -545
  226. package/frontend/src/elements/module.ts +90 -29
  227. package/frontend/src/elements/register_element.ts +24 -0
  228. package/frontend/src/modules/auth.ts +7 -6
  229. package/frontend/src/modules/color.ts +348 -0
  230. package/frontend/src/modules/colors.ts +468 -449
  231. package/frontend/src/modules/cookies.ts +1 -0
  232. package/frontend/src/modules/events.ts +1 -0
  233. package/frontend/src/modules/google.ts +1 -0
  234. package/frontend/src/modules/meta.ts +2 -1
  235. package/frontend/src/modules/mutex.ts +2 -4
  236. package/frontend/src/modules/paddle.ts +21 -20
  237. package/frontend/src/modules/scheme.ts +5 -4
  238. package/frontend/src/modules/statics.ts +2 -1
  239. package/frontend/src/modules/support.ts +3 -2
  240. package/frontend/src/modules/theme.ts +413 -0
  241. package/frontend/src/modules/themes.ts +2 -1
  242. package/frontend/src/modules/user.ts +12 -11
  243. package/frontend/src/modules/utils.ts +125 -2
  244. package/frontend/src/ui/border_button.ts +41 -37
  245. package/frontend/src/ui/button.ts +33 -32
  246. package/frontend/src/ui/canvas.ts +5 -2
  247. package/frontend/src/ui/checkbox.ts +21 -22
  248. package/frontend/src/ui/code.ts +92 -86
  249. package/frontend/src/ui/context_menu.ts +7 -5
  250. package/frontend/src/ui/css.ts +1 -1
  251. package/frontend/src/ui/divider.ts +15 -10
  252. package/frontend/src/ui/dropdown.ts +38 -21
  253. package/frontend/src/ui/for_each.ts +9 -8
  254. package/frontend/src/ui/form.ts +26 -21
  255. package/frontend/src/ui/frame_modes.ts +13 -17
  256. package/frontend/src/ui/google_map.ts +15 -13
  257. package/frontend/src/ui/gradient.ts +9 -8
  258. package/frontend/src/ui/image.ts +108 -86
  259. package/frontend/src/ui/input.ts +145 -144
  260. package/frontend/src/ui/link.ts +25 -23
  261. package/frontend/src/ui/list.ts +12 -6
  262. package/frontend/src/ui/loader_button.ts +26 -25
  263. package/frontend/src/ui/loaders.ts +12 -11
  264. package/frontend/src/ui/popup.ts +168 -14
  265. package/frontend/src/ui/pseudo.ts +5 -3
  266. package/frontend/src/ui/scroller.ts +303 -294
  267. package/frontend/src/ui/slider.ts +15 -10
  268. package/frontend/src/ui/spacer.ts +14 -11
  269. package/frontend/src/ui/span.ts +6 -2
  270. package/frontend/src/ui/stack.ts +196 -183
  271. package/frontend/src/ui/steps.ts +38 -22
  272. package/frontend/src/ui/style.ts +7 -4
  273. package/frontend/src/ui/switch.ts +16 -11
  274. package/frontend/src/ui/table.ts +42 -34
  275. package/frontend/src/ui/tabs.ts +20 -19
  276. package/frontend/src/ui/text.ts +12 -11
  277. package/frontend/src/ui/title.ts +22 -20
  278. package/frontend/src/ui/ui.ts +0 -2
  279. package/frontend/src/ui/view.ts +20 -19
  280. package/frontend/src/volt.ts +3 -1
  281. package/frontend/{compile.js → tools/compile.old.js} +2 -2
  282. package/frontend/tools/embed_scripts.js +69 -0
  283. package/frontend/tsconfig.json +26 -0
  284. package/package.json +7 -6
  285. package/frontend/dist/ui/theme.d.ts +0 -25
  286. package/frontend/exports.json +0 -1340
  287. package/frontend/src/modules/date.js +0 -535
  288. package/frontend/src/ui/color.ts +0 -117
  289. package/frontend/src/ui/theme.ts +0 -279
  290. /package/backend/src/{vinc.dev.js → vinc.dev.ts} +0 -0
@@ -0,0 +1,413 @@
1
+ /*
2
+ * Author: Daan van den Bergh
3
+ * Copyright: © 2022 - 2024 Daan van den Bergh.
4
+ */
5
+
6
+ // Imports.
7
+ import { Color } from "./color.js"
8
+ import { Themes as ThemesModule } from "./themes.js"
9
+
10
+ // Types.
11
+ type ThemeAttributeName = string;
12
+ type ThemeId = "dark" | "light";
13
+ const ThemeIdList = ["dark", "light"] as const;
14
+ type ThemesOptions<ThemeOptions extends {}> = { dark: ThemeOptions, light: ThemeOptions };
15
+ type OnActivateCallback<ThemeOptions extends {}> = (themes_class: Theme<ThemeOptions>, active_id: ThemeId) => void;
16
+
17
+ // Themes class.
18
+ /* @docs:
19
+ @nav: Frontend
20
+ @chapter: Themes
21
+ @note: The `ThemesClass` is also initializable under function `Themes`.
22
+ @desc:
23
+ A themes class to efficiently style the site using themes.
24
+
25
+ The constructor arguments must be a theme style per theme name. Every theme variable should exist in all themes or it may cause undefined behaviour. The theme name that is passed first will be the active theme by default.
26
+ ```
27
+ Theme("main-theme", {
28
+ light: {
29
+ text_fg: "#000000",
30
+ },
31
+ dark: {
32
+ text_fg: "#FFFFFF",
33
+ },
34
+ })
35
+ ```
36
+
37
+ When theme attributes are retrieved, by default they will be the active theme's attribute as a css variable. So this can be passed to an element.
38
+ However, some element functions do not accept css variables, in this case the `value()` function can be used to retrieve the raw value. Do not forget to apply an `on_theme_update()` callback on the elements where you use this.
39
+ */
40
+ export class Theme<ThemeOptions extends {}> {
41
+
42
+ // helper: union of all keys across all themes
43
+
44
+ // Attributes.
45
+ public active_id!: ThemeId;
46
+ public active!: ThemeOptions;
47
+ public _attrs: string[];
48
+ public _css_vars: Record<string, string | String>;
49
+ public _id: string;
50
+ public _on_activate_callback?: OnActivateCallback<ThemeOptions>;
51
+
52
+ constructor(
53
+ id: string,
54
+ themes: ThemesOptions<ThemeOptions>,
55
+ ) {
56
+
57
+ // Attributes.
58
+ this._attrs = [];
59
+ this._css_vars = {};
60
+ this._id = id;
61
+
62
+ // Assign themes.
63
+ Object.keys(themes).iterate((theme) => {
64
+
65
+ // Initialize.
66
+ const theme_style = themes[theme] as Record<string, any>;
67
+ this[theme] = theme_style;
68
+
69
+ // Activate first theme.
70
+ if (this.active_id === undefined) {
71
+ this.active_id = theme as ThemeId;
72
+ this.active = theme_style as any;
73
+ Object.keys(this.active as any).iterate((id) => {
74
+ document.documentElement.style.setProperty(`--${this._id}_${id}`, (this.active as any)[id] ?? "");
75
+ });
76
+ }
77
+
78
+ // Initialize attr funcs.
79
+ Object.keys(theme_style).iterate((id) => {
80
+ this._add_attr(id, theme as ThemeId);
81
+ })
82
+ })
83
+
84
+ // Ensure type.
85
+ if (this.active_id == null || this.active == null) {
86
+ throw new Error("No themes were specified in parameter \"themes\".");
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Initialize a specific theme.
92
+ * @note This function should be called after the constructor to ensure the most recent theme is activated, argument "id" can be left undefined.
93
+ */
94
+ initialize(id?: ThemeId): this {
95
+ if (id == null) {
96
+ id = (localStorage.getItem(this._id) ?? undefined) as any;
97
+ }
98
+ if (id != null && ThemeIdList.includes(id as any)) {
99
+ this.activate(id);
100
+ }
101
+ return this;
102
+ }
103
+
104
+ // ---------------------------------------------------------------------
105
+ // Theme selection methods.
106
+
107
+ /** Get full active theme id. */
108
+ get id(): string {
109
+ return `${this._id}.${String(this.active_id)}`
110
+ }
111
+
112
+ // Get cached active subtheme id.
113
+ get_active_id_cached(): string {
114
+ return localStorage.getItem(this._id) ?? "";
115
+ }
116
+
117
+ // Activate a theme.
118
+ activate(id: ThemeId, apply_theme_update: boolean = true): this {
119
+ if (ThemeIdList.includes(id) === false || (this as any)[id] === undefined) {
120
+ throw Error(`Theme "${id as string}" does not exist.`);
121
+ }
122
+ this.active_id = id;
123
+ this.active = (this as any)[id];
124
+ Object.keys(this.active as any).iterate((id) => {
125
+ document.documentElement.style.setProperty(`--${this._id}_${id}`, (this.active as any)[id] ?? "");
126
+ });
127
+ if (this._on_activate_callback != null) {
128
+ this._on_activate_callback(this, this.active_id);
129
+ }
130
+ if (apply_theme_update) {
131
+ ThemesModule.apply_theme_update();
132
+ }
133
+ localStorage.setItem(this._id, String(this.active_id));
134
+ return this;
135
+ }
136
+
137
+ // Set an on activate callback.
138
+ on_activate(): OnActivateCallback<ThemeOptions> | undefined;
139
+ on_activate(callback: OnActivateCallback<ThemeOptions>): this;
140
+ on_activate(callback?: OnActivateCallback<ThemeOptions>): this | OnActivateCallback<ThemeOptions> | undefined {
141
+ if (callback == null) { return this._on_activate_callback; }
142
+ this._on_activate_callback = callback;
143
+ return this;
144
+ }
145
+
146
+ // Toggle themes.
147
+ toggle(apply_theme_update: boolean = true): this {
148
+ const other: ThemeId = this.active_id === "dark" ? "light" : "dark";
149
+ this.activate(other, apply_theme_update);
150
+ return this;
151
+ }
152
+
153
+ // ---------------------------------------------------------------------
154
+ // Adding values.
155
+
156
+ // Add a new attribute.
157
+ _add_attr(id: string, theme?: ThemeId): void {
158
+ if (theme == null) {
159
+ this._css_vars[id] = `var(--${this._id}_${id})`;
160
+ } else {
161
+ const theme_style = (this as any)[theme];
162
+ if (
163
+ typeof theme_style[id] === "string" &&
164
+ (
165
+ theme_style[id].indexOf("linear-gradient") !== -1 ||
166
+ theme_style[id].indexOf("radial-gradient") !== -1
167
+ )
168
+ ) {
169
+ theme_style[id] = new String(theme_style[id]);
170
+ theme_style[id]._is_gradient = true;
171
+ this._css_vars[id] = new String(`var(--${this._id}_${id})`);
172
+ (this._css_vars[id] as any)._is_gradient = true;
173
+ } else {
174
+ this._css_vars[id] = `var(--${this._id}_${id})`;
175
+ }
176
+ }
177
+ Object.defineProperty(this, id, {
178
+ get: function () {
179
+ return this._css_vars[id];
180
+ },
181
+ set: function (v: any) {
182
+ // only for support this does not work however.
183
+ // document.documentElement.style.setProperty(`--${this._id}_${id}`, (this.active as any)[id] ?? "");
184
+ // return this;
185
+ },
186
+ enumerable: true,
187
+ configurable: true,
188
+ });
189
+ this._attrs.append(id);
190
+ }
191
+
192
+ // Assign a new value.
193
+ set(theme: ThemeId, key: string, value: any): this {
194
+
195
+ // Update theme.
196
+ const theme_style = (this as any)[theme];
197
+ if (typeof value === "string" && (value.indexOf("linear-gradient") !== -1 || value.indexOf("radial-gradient") !== -1)) {
198
+ theme_style[key] = new String(value);
199
+ theme_style[key]._is_gradient = true;
200
+ this._css_vars[key] = new String(`var(--${this._id}_${key})`);
201
+ (this._css_vars[key] as any)._is_gradient = true;
202
+ } else {
203
+ theme_style[key] = value;
204
+ this._css_vars[key] = `var(--${this._id}_${key})`;
205
+ }
206
+
207
+ // Set property.
208
+ if (this.active_id === theme) {
209
+ document.documentElement.style.setProperty(`--${this._id}_${key}`, (this.active as any)[key] ?? "");
210
+ }
211
+
212
+ // Response.
213
+ return this;
214
+ }
215
+
216
+ get raw(): ThemeOptions {
217
+ return this.active;
218
+ }
219
+
220
+ // Get raw value.
221
+ value(id: ThemeAttributeName): any {
222
+ if (this.active === undefined) { return; }
223
+ return this.active![id];
224
+ }
225
+
226
+ // ---------------------------------------------------------------------
227
+ // Color manipulation methods.
228
+
229
+ // Create a new color for each theme.
230
+ create<T = string>(id: string, create_theme_value: (theme_id: ThemeId, theme: ThemeOptions) => T): void {
231
+
232
+ // Already created.
233
+ if (this._css_vars[id]) {
234
+ throw new Error(`Color "${id}" already exists.`);
235
+ }
236
+
237
+ // Iterate.
238
+ let index = 0;
239
+ for (const theme_id of ThemeIdList) {
240
+ const theme = (this as any)[theme_id];
241
+ const value = create_theme_value(theme_id, theme);
242
+ theme[id] = value;
243
+
244
+ // Add attribute to document on first call.
245
+ if (index === 0) {
246
+ this._add_attr(id);
247
+ }
248
+
249
+ // Set property.
250
+ if (this.active_id === theme_id) {
251
+ document.documentElement.style.setProperty(`--${this._id}_${id}`, theme[id]);
252
+ }
253
+
254
+ // Incr index
255
+ ++index;
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Auto darken lighten a color from the theme
261
+ * Safe to call multiple times, caching is implemented.
262
+ *
263
+ * @warning The input color must be a hex / rgb(a) string.
264
+ * @param theme_attr The name of the original theme color.
265
+ * @param percent Percentage between 0. and 1.0.
266
+ */
267
+ auto_darken_lighten(
268
+ theme_attr: ThemeAttributeName,
269
+ percent: number = 0.5,
270
+ reversed: boolean = false,
271
+ ) {
272
+ let full_id = `${String(theme_attr)}_adl_${percent}`;
273
+ full_id = full_id.replaceAll(".", "_");
274
+ if (this._css_vars[full_id]) {
275
+ return this._css_vars[full_id] as string;
276
+ }
277
+ const process = reversed === true ? (x => x < 0.5) : (x => x > 0.5)
278
+ this.create(full_id, (theme_id, theme) => {
279
+ if (!theme[theme_attr]) {
280
+ throw new Error(`Theme attribute "${String(theme_attr)}" does not exist.`);
281
+ }
282
+ return new Color(theme[theme_attr]).auto_darken_lighten(percent, process).str()
283
+ });
284
+ return this._css_vars[full_id] as string;
285
+ }
286
+
287
+ // Opacity.
288
+ // Opacity must be a number `0.0` till `1.0`, and may also be an object with opacity pet theme `{dark: 0.2, light: 0.35}`.
289
+ opacity(theme_attr: ThemeAttributeName, opacity: number = 1.0): string {
290
+
291
+ // Create full id.
292
+ let full_id;
293
+ if (typeof opacity === "number") {
294
+ full_id = `${String(theme_attr)}_opac_${opacity}`;
295
+ } else {
296
+ full_id = `${String(theme_attr)}_opac_${Object.values(opacity).join("_")}`;
297
+ }
298
+ full_id = full_id.replaceAll(".", "_");
299
+
300
+ // Already created.
301
+ if (this._css_vars[full_id]) {
302
+ return this._css_vars[full_id] as string;
303
+ }
304
+
305
+ // Iterate.
306
+ let index = 0;
307
+ for (const theme_id of ThemeIdList) {
308
+ const theme = this[theme_id];
309
+
310
+ // Checks.
311
+ if (theme[theme_attr] == null) {
312
+ console.error(new Error(`Theme attribute "${String(theme_attr)}" does not exist.`));
313
+ return "";
314
+ }
315
+ if (theme[theme_attr]._is_gradient) {
316
+ console.error(new Error(`Unable to set the opacity on gradient color "${String(theme_attr)}".`));
317
+ return "";
318
+ }
319
+
320
+ // Create new color.
321
+ let theme_opac = opacity;
322
+ if (typeof theme_opac === "object") {
323
+ theme_opac = theme_opac[theme_attr];
324
+ if (theme_opac === undefined) {
325
+ console.error(new Error(`Unable to find the opacity on for theme id "${theme_attr}".`));
326
+ }
327
+ }
328
+ theme[full_id] = new Color(theme[theme_attr]).opacity(theme_opac).rgb();
329
+
330
+ // Add css var.
331
+ if (index === 0) {
332
+ this._add_attr(full_id);
333
+ }
334
+
335
+ // Set property.
336
+ if (this.active_id === theme_id) {
337
+ document.documentElement.style.setProperty(`--${this._id}_${full_id}`, theme[full_id]);
338
+ }
339
+
340
+ // Incr index
341
+ ++index;
342
+ }
343
+
344
+ return this._css_vars[full_id] as string;
345
+ }
346
+
347
+ // ---------------------------------------------------------------------
348
+ // Font size manipulation methods.
349
+
350
+ /**
351
+ * Create a new value by multiplying a numeric attribute.
352
+ * @warning argument `id` should be the name of a numeric theme attribute.
353
+ * @param theme_attr The name of a numeric attribute
354
+ * @param x The number by which to multiply the attribute, `attribute * x`.
355
+ */
356
+ multiply(theme_attr: ThemeAttributeName, x: number = 1.0): string {
357
+ let full_id = `${String(theme_attr)}_fsr_${x}`;
358
+ full_id = full_id.replaceAll(".", "_");
359
+ if (this._css_vars[full_id]) {
360
+ return this._css_vars[full_id] as string;
361
+ }
362
+ const process = (x => x < 0.5)
363
+ this.create<number>(full_id, (_, theme) => {
364
+ if (!theme[theme_attr]) {
365
+ throw new Error(`Theme attribute "${String(theme_attr)}" does not exist.`);
366
+ }
367
+ if (typeof theme[theme_attr] !== "number") {
368
+ throw new Error(`Theme attribute "${String(theme_attr)}" is not a number.`);
369
+ }
370
+ return theme[theme_attr] * x;
371
+ });
372
+ return this._css_vars[full_id] as string;
373
+ }
374
+
375
+ // ---------------------------------------------------------------------
376
+ // Animation methods.
377
+
378
+ /** Function to disable all transition attributes on all elements. */
379
+ disable_transitions(): this {
380
+ // const style = document.createElement('style');
381
+ // style.id = '__libris_thme_disable_transitions__';
382
+ // style.innerHTML = `
383
+ // * { transition: none !important; }
384
+ // *::after { transition: none !important; }
385
+ // *::before { transition: none !important; }
386
+ // `.dedent();
387
+ // document.head.appendChild(style);
388
+
389
+ document.body.classList.add("notransition");
390
+
391
+ // Force a reflow to apply the new styles immediately
392
+ // document.head.getBoundingClientRect();
393
+ void document.body.offsetHeight;
394
+
395
+ return this;
396
+ }
397
+
398
+ /** Function to re-enable all transition attributes on all elements. */
399
+ enable_transitions(delay = 0): this {
400
+ if (delay > 0) {
401
+ setTimeout(() => this.enable_transitions(0), delay);
402
+ return this;
403
+ }
404
+ document.body.classList.remove("notransition");
405
+ // const style = document.getElementById('__libris_thme_disable_transitions__');
406
+ // if (style) {
407
+ // style.remove();
408
+ // }
409
+ document.head.getBoundingClientRect();
410
+ return this;
411
+ }
412
+ }
413
+ export type ExtendTheme<ThemeOptions extends {}> = Theme<ThemeOptions> & ThemeOptions;
@@ -21,4 +21,5 @@ export const Themes = {
21
21
  }
22
22
  });
23
23
  }
24
- };
24
+ };
25
+ export { Themes as themes }; // also export as lowercase for compatibility.
@@ -141,7 +141,7 @@ export namespace User {
141
141
  * @type: boolean
142
142
  */
143
143
  export async function get(): Promise<UserObject> {
144
- return Utils.request({
144
+ return Utils.request_v1({
145
145
  method: "GET",
146
146
  url: "/volt/user/",
147
147
  data: {
@@ -167,7 +167,7 @@ export namespace User {
167
167
  email?: string,
168
168
  is_activated?: boolean,
169
169
  }): Promise<any> {
170
- return Utils.request({
170
+ return Utils.request_v1({
171
171
  method: "POST",
172
172
  url: "/volt/user/",
173
173
  data: user,
@@ -183,7 +183,7 @@ export namespace User {
183
183
  * @return: Returns a promise with a successful update response or a request error on a failed request.
184
184
  */
185
185
  export async function activate(code: string = ""): Promise<Response> {
186
- return Utils.request({
186
+ return Utils.request_v1({
187
187
  method: "POST",
188
188
  url: "/volt/auth/activate",
189
189
  data: {
@@ -205,7 +205,7 @@ export namespace User {
205
205
  password = "",
206
206
  verify_password = "",
207
207
  }: { current_password: string; password: string; verify_password: string }): Promise<Response> {
208
- return Utils.request({
208
+ return Utils.request_v1({
209
209
  method: "POST",
210
210
  url: "/volt/user/change_password",
211
211
  data: {
@@ -225,7 +225,7 @@ export namespace User {
225
225
  * @return: Returns a promise with a successful update response or a request error on a failed request.
226
226
  */
227
227
  export async function delete_account(): Promise<Response> {
228
- return Utils.request({
228
+ return Utils.request_v1({
229
229
  method: "DELETE",
230
230
  url: "/volt/user",
231
231
  });
@@ -240,7 +240,7 @@ export namespace User {
240
240
  * @return: Returns a promise with a successful update response with the newly generated API key as an attribute or a request error on a failed request.
241
241
  */
242
242
  export async function generate_api_key(): Promise<GenerateAPIKeyResponse> {
243
- return Utils.request({
243
+ return Utils.request_v1({
244
244
  method: "POST",
245
245
  url: "/volt/user/api_key",
246
246
  });
@@ -255,7 +255,7 @@ export namespace User {
255
255
  * @return: Returns a promise with a successful update response or a request error on a failed request.
256
256
  */
257
257
  export async function revoke_api_key(): Promise<Response> {
258
- return Utils.request({
258
+ return Utils.request_v1({
259
259
  method: "DELETE",
260
260
  url: "/volt/user/api_key",
261
261
  });
@@ -270,7 +270,7 @@ export namespace User {
270
270
  * @return: Returns a promise with the loaded user's data or a request error on a failed request.
271
271
  */
272
272
  export async function load(path: string, def: string = ""): Promise<any> {
273
- return Utils.request({
273
+ return Utils.request_v1({
274
274
  method: "GET",
275
275
  url: "/volt/user/data",
276
276
  data: {
@@ -289,7 +289,7 @@ export namespace User {
289
289
  * @return: Returns a promise with a successful update response or a request error on a failed request.
290
290
  */
291
291
  export async function save(path: string = "", data: Record<string, any> = {}): Promise<any> {
292
- return Utils.request({
292
+ return Utils.request_v1({
293
293
  method: "POST",
294
294
  url: "/volt/user/data",
295
295
  data: {
@@ -308,7 +308,7 @@ export namespace User {
308
308
  * @return: Returns a promise with the loaded user's data or a request error on a failed request.
309
309
  */
310
310
  export async function load_protected(path: string, def: string = ""): Promise<any> {
311
- return Utils.request({
311
+ return Utils.request_v1({
312
312
  method: "GET",
313
313
  url: "/volt/user/data/protected",
314
314
  data: {
@@ -318,4 +318,5 @@ export namespace User {
318
318
  });
319
319
  }
320
320
 
321
- };
321
+ };
322
+ export { User as user }; // also export as lowercase for compatibility.
@@ -3,6 +3,8 @@
3
3
  * Copyright: © 2022 - 2024 Daan van den Bergh.
4
4
  */
5
5
 
6
+ import { AnyElement } from "../ui/any_element";
7
+
6
8
  // Utils module.
7
9
  const Utils = {
8
10
  is_apple: navigator.vendor.includes('Apple') as boolean,
@@ -560,6 +562,126 @@ const Utils = {
560
562
  }
561
563
  },
562
564
 
565
+
566
+ /** New request method. */
567
+ async request<Data = any>(options: {
568
+ method?: string;
569
+ url?: string | null;
570
+ data?: any;
571
+ json?: boolean;
572
+ credentials?: RequestCredentials;
573
+ headers?: Record<string, string>;
574
+ }): Promise<{
575
+ error?: {
576
+ message: string;
577
+ type?: string;
578
+ invalid_fields?: { [name: string]: string };
579
+ };
580
+ status: number;
581
+ data?: Data;
582
+ }> {
583
+ const {
584
+ method = 'GET',
585
+ url = null,
586
+ data = null,
587
+ json = true,
588
+ credentials = "same-origin",
589
+ headers = {},
590
+ } = options;
591
+
592
+ // — prepare headers —
593
+ if (json && data != null && !headers['Content-Type']) {
594
+ headers['Content-Type'] = 'application/json';
595
+ }
596
+
597
+ // — build URL + body —
598
+ let finalUrl = url!;
599
+ let body: string | undefined;
600
+ if (data != null && typeof data === 'object') {
601
+ if (method.toUpperCase() === 'GET') {
602
+ finalUrl = `${url}?${new URLSearchParams(data).toString()}`;
603
+ } else {
604
+ body = JSON.stringify(data);
605
+ }
606
+ } else if (data != null) {
607
+ body = String(data);
608
+ }
609
+
610
+ const init: RequestInit = { method, credentials, headers };
611
+ if (body !== undefined) init.body = body;
612
+
613
+ try {
614
+ const response = await fetch(finalUrl, init);
615
+ const status = response.status;
616
+
617
+ // — parse payload once —
618
+ let payload: any;
619
+ const clone = response.clone(); // @dev.
620
+ if (json) {
621
+ try {
622
+ payload = await response.json();
623
+ } catch (e: any) {
624
+ // malformed JSON still counts as a “success” fetch
625
+ console.log("[debug] Unable to parse a json from response:", await clone.text(), "- Error: ", JSON.stringify(e, null, 4))
626
+ console.log("rsponse:", response);
627
+ return {
628
+ status,
629
+ error: { message: `Failed to parse JSON response: ${e.message}` },
630
+ };
631
+ }
632
+ } else {
633
+ try {
634
+ payload = await response.text();
635
+ } catch (e: any) {
636
+ return {
637
+ status,
638
+ error: { message: `Failed to parse text response: ${e.message}` },
639
+ };
640
+ }
641
+ }
642
+ console.log("Payload", json, payload)
643
+
644
+ // — handle HTTP errors (4xx/5xx) by resolving with an error object —
645
+ if (!response.ok) {
646
+ // if server wrapped its error in { error: { message, type?, invalid_fields? }, … }
647
+ if (
648
+ payload &&
649
+ typeof payload === 'object' &&
650
+ typeof payload.error === 'object' &&
651
+ typeof payload.error.message === 'string'
652
+ ) {
653
+ return {
654
+ status,
655
+ error: {
656
+ message: payload.error.message,
657
+ type: payload.error.type,
658
+ invalid_fields: payload.error.invalid_fields,
659
+ },
660
+ data: payload.data,
661
+ };
662
+ }
663
+
664
+ // otherwise fall back to a generic single‐message error
665
+ const msg =
666
+ typeof payload === 'string'
667
+ ? payload
668
+ : payload?.error?.toString() ?? JSON.stringify(payload);
669
+ return {
670
+ status,
671
+ error: { message: msg },
672
+ };
673
+ }
674
+
675
+ // — 2xx: success —
676
+ return { status, data: payload };
677
+ } catch (networkErr) {
678
+ // genuine network / system failure
679
+ throw networkErr;
680
+ }
681
+ },
682
+
683
+
684
+ // @deprecated.
563
685
  /* @docs:
564
686
  @nav: Frontend
565
687
  @chapter: Utils
@@ -580,7 +702,7 @@ const Utils = {
580
702
  @desc: A Promise that resolves with the response data.
581
703
  @type: Promise<any>
582
704
  */
583
- request(options: {
705
+ request_v1(options: {
584
706
  method?: string,
585
707
  url?: string | null,
586
708
  data?: any,
@@ -721,7 +843,7 @@ const Utils = {
721
843
  @desc: void
722
844
  @type: void
723
845
  */
724
- async on_load(func: () => HTMLElement | Promise<HTMLElement> | null): Promise<void> {
846
+ async on_load(func: () => HTMLElement | AnyElement | Promise<HTMLElement | AnyElement> | null | undefined): Promise<void> {
725
847
  // document.addEventListener("DOMContentLoaded", async () => {
726
848
  const splash = document.getElementById("__volt_splash_screen");
727
849
  if (splash != null) {
@@ -1258,3 +1380,4 @@ const Utils = {
1258
1380
 
1259
1381
  // Export.
1260
1382
  export { Utils };
1383
+ export { Utils as utils }; // also export as lowercase for compatibility.