@moni-labs/moni-ui 0.2.0 → 0.3.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 (323) hide show
  1. package/README.md +52 -194
  2. package/custom-elements.json +1636 -350
  3. package/dist/actions/index.d.ts +6 -0
  4. package/dist/actions/index.d.ts.map +1 -1
  5. package/dist/actions/index.js +6 -0
  6. package/dist/components/_base/field-styles.d.ts +51 -16
  7. package/dist/components/_base/field-styles.d.ts.map +1 -1
  8. package/dist/components/_base/field-styles.js +164 -36
  9. package/dist/components/_base/index.d.ts +25 -0
  10. package/dist/components/_base/index.d.ts.map +1 -1
  11. package/dist/components/_base/index.js +25 -0
  12. package/dist/components/_base/interaction-styles.d.ts +39 -12
  13. package/dist/components/_base/interaction-styles.d.ts.map +1 -1
  14. package/dist/components/_base/interaction-styles.js +85 -33
  15. package/dist/components/_base/moni-element.d.ts +43 -8
  16. package/dist/components/_base/moni-element.d.ts.map +1 -1
  17. package/dist/components/_base/moni-element.js +43 -8
  18. package/dist/components/_base/shared-styles.d.ts +41 -17
  19. package/dist/components/_base/shared-styles.d.ts.map +1 -1
  20. package/dist/components/_base/shared-styles.js +113 -21
  21. package/dist/components/index.d.ts +6 -0
  22. package/dist/components/index.d.ts.map +1 -1
  23. package/dist/components/index.js +6 -0
  24. package/dist/components/loading-shapes.d.ts +6 -0
  25. package/dist/components/loading-shapes.d.ts.map +1 -1
  26. package/dist/components/loading-shapes.js +6 -0
  27. package/dist/components/moni-app-bar.d.ts +128 -33
  28. package/dist/components/moni-app-bar.d.ts.map +1 -1
  29. package/dist/components/moni-app-bar.js +121 -26
  30. package/dist/components/moni-badge.d.ts +122 -14
  31. package/dist/components/moni-badge.d.ts.map +1 -1
  32. package/dist/components/moni-badge.js +122 -14
  33. package/dist/components/moni-bottom-sheet.d.ts +120 -15
  34. package/dist/components/moni-bottom-sheet.d.ts.map +1 -1
  35. package/dist/components/moni-bottom-sheet.js +116 -12
  36. package/dist/components/moni-button-group.d.ts +53 -27
  37. package/dist/components/moni-button-group.d.ts.map +1 -1
  38. package/dist/components/moni-button-group.js +49 -23
  39. package/dist/components/moni-button-segment.d.ts +28 -8
  40. package/dist/components/moni-button-segment.d.ts.map +1 -1
  41. package/dist/components/moni-button-segment.js +27 -7
  42. package/dist/components/moni-button.d.ts +51 -32
  43. package/dist/components/moni-button.d.ts.map +1 -1
  44. package/dist/components/moni-button.js +50 -31
  45. package/dist/components/moni-card.d.ts +91 -31
  46. package/dist/components/moni-card.d.ts.map +1 -1
  47. package/dist/components/moni-card.js +86 -26
  48. package/dist/components/moni-carousel.d.ts +67 -17
  49. package/dist/components/moni-carousel.d.ts.map +1 -1
  50. package/dist/components/moni-carousel.js +59 -16
  51. package/dist/components/moni-checkbox.d.ts +122 -17
  52. package/dist/components/moni-checkbox.d.ts.map +1 -1
  53. package/dist/components/moni-checkbox.js +118 -14
  54. package/dist/components/moni-chip.d.ts +56 -30
  55. package/dist/components/moni-chip.d.ts.map +1 -1
  56. package/dist/components/moni-chip.js +51 -25
  57. package/dist/components/moni-color-field.d.ts +44 -6
  58. package/dist/components/moni-color-field.d.ts.map +1 -1
  59. package/dist/components/moni-color-field.js +43 -5
  60. package/dist/components/moni-context-menu.d.ts +44 -22
  61. package/dist/components/moni-context-menu.d.ts.map +1 -1
  62. package/dist/components/moni-context-menu.js +43 -21
  63. package/dist/components/moni-dialog.d.ts +107 -15
  64. package/dist/components/moni-dialog.d.ts.map +1 -1
  65. package/dist/components/moni-dialog.js +105 -14
  66. package/dist/components/moni-divider.d.ts +50 -15
  67. package/dist/components/moni-divider.d.ts.map +1 -1
  68. package/dist/components/moni-divider.js +49 -14
  69. package/dist/components/moni-expansion.d.ts +44 -8
  70. package/dist/components/moni-expansion.d.ts.map +1 -1
  71. package/dist/components/moni-expansion.js +43 -7
  72. package/dist/components/moni-fab-menu.d.ts +39 -20
  73. package/dist/components/moni-fab-menu.d.ts.map +1 -1
  74. package/dist/components/moni-fab-menu.js +38 -19
  75. package/dist/components/moni-fab.d.ts +49 -23
  76. package/dist/components/moni-fab.d.ts.map +1 -1
  77. package/dist/components/moni-fab.js +46 -20
  78. package/dist/components/moni-file-field.d.ts +54 -14
  79. package/dist/components/moni-file-field.d.ts.map +1 -1
  80. package/dist/components/moni-file-field.js +53 -13
  81. package/dist/components/moni-icon.d.ts +78 -11
  82. package/dist/components/moni-icon.d.ts.map +1 -1
  83. package/dist/components/moni-icon.js +77 -10
  84. package/dist/components/moni-list-item.d.ts +61 -30
  85. package/dist/components/moni-list-item.d.ts.map +1 -1
  86. package/dist/components/moni-list-item.js +55 -24
  87. package/dist/components/moni-list.d.ts +37 -13
  88. package/dist/components/moni-list.d.ts.map +1 -1
  89. package/dist/components/moni-list.js +36 -12
  90. package/dist/components/moni-loading-indicator.d.ts +38 -11
  91. package/dist/components/moni-loading-indicator.d.ts.map +1 -1
  92. package/dist/components/moni-loading-indicator.js +37 -10
  93. package/dist/components/moni-menu-item.d.ts +31 -8
  94. package/dist/components/moni-menu-item.d.ts.map +1 -1
  95. package/dist/components/moni-menu-item.js +30 -7
  96. package/dist/components/moni-menu.d.ts +58 -33
  97. package/dist/components/moni-menu.d.ts.map +1 -1
  98. package/dist/components/moni-menu.js +51 -26
  99. package/dist/components/moni-morph-modal.d.ts +7 -1
  100. package/dist/components/moni-morph-modal.d.ts.map +1 -1
  101. package/dist/components/moni-morph-modal.js +46 -24
  102. package/dist/components/moni-nav-item.d.ts +50 -10
  103. package/dist/components/moni-nav-item.d.ts.map +1 -1
  104. package/dist/components/moni-nav-item.js +48 -8
  105. package/dist/components/moni-nav.d.ts +57 -22
  106. package/dist/components/moni-nav.d.ts.map +1 -1
  107. package/dist/components/moni-nav.js +53 -18
  108. package/dist/components/moni-progress.d.ts +108 -20
  109. package/dist/components/moni-progress.d.ts.map +1 -1
  110. package/dist/components/moni-progress.js +104 -16
  111. package/dist/components/moni-radio.d.ts +106 -14
  112. package/dist/components/moni-radio.d.ts.map +1 -1
  113. package/dist/components/moni-radio.js +104 -13
  114. package/dist/components/moni-ripple.d.ts +121 -10
  115. package/dist/components/moni-ripple.d.ts.map +1 -1
  116. package/dist/components/moni-ripple.js +120 -9
  117. package/dist/components/moni-segmented-button.d.ts +31 -11
  118. package/dist/components/moni-segmented-button.d.ts.map +1 -1
  119. package/dist/components/moni-segmented-button.js +30 -10
  120. package/dist/components/moni-select-option.d.ts +43 -9
  121. package/dist/components/moni-select-option.d.ts.map +1 -1
  122. package/dist/components/moni-select-option.js +41 -7
  123. package/dist/components/moni-select.d.ts +59 -2
  124. package/dist/components/moni-select.d.ts.map +1 -1
  125. package/dist/components/moni-select.js +58 -1
  126. package/dist/components/moni-shape.d.ts +1 -1
  127. package/dist/components/moni-side-sheet.d.ts +56 -19
  128. package/dist/components/moni-side-sheet.d.ts.map +1 -1
  129. package/dist/components/moni-side-sheet.js +53 -16
  130. package/dist/components/moni-slider.d.ts +56 -25
  131. package/dist/components/moni-slider.d.ts.map +1 -1
  132. package/dist/components/moni-slider.js +55 -24
  133. package/dist/components/moni-snackbar.d.ts +86 -17
  134. package/dist/components/moni-snackbar.d.ts.map +1 -1
  135. package/dist/components/moni-snackbar.js +85 -16
  136. package/dist/components/moni-split-button.d.ts +38 -9
  137. package/dist/components/moni-split-button.d.ts.map +1 -1
  138. package/dist/components/moni-split-button.js +37 -8
  139. package/dist/components/moni-step.d.ts +42 -9
  140. package/dist/components/moni-step.d.ts.map +1 -1
  141. package/dist/components/moni-step.js +41 -8
  142. package/dist/components/moni-stepper.d.ts +43 -6
  143. package/dist/components/moni-stepper.d.ts.map +1 -1
  144. package/dist/components/moni-stepper.js +42 -5
  145. package/dist/components/moni-switch.d.ts +103 -16
  146. package/dist/components/moni-switch.d.ts.map +1 -1
  147. package/dist/components/moni-switch.js +99 -13
  148. package/dist/components/moni-tab.d.ts +35 -8
  149. package/dist/components/moni-tab.d.ts.map +1 -1
  150. package/dist/components/moni-tab.js +34 -7
  151. package/dist/components/moni-tabs.d.ts +51 -13
  152. package/dist/components/moni-tabs.d.ts.map +1 -1
  153. package/dist/components/moni-tabs.js +48 -10
  154. package/dist/components/moni-text-field.d.ts +55 -10
  155. package/dist/components/moni-text-field.d.ts.map +1 -1
  156. package/dist/components/moni-text-field.js +54 -9
  157. package/dist/components/moni-textarea.d.ts +51 -21
  158. package/dist/components/moni-textarea.d.ts.map +1 -1
  159. package/dist/components/moni-textarea.js +48 -18
  160. package/dist/components/moni-time-picker.d.ts +41 -11
  161. package/dist/components/moni-time-picker.d.ts.map +1 -1
  162. package/dist/components/moni-time-picker.js +40 -10
  163. package/dist/components/moni-toolbar.d.ts +43 -15
  164. package/dist/components/moni-toolbar.d.ts.map +1 -1
  165. package/dist/components/moni-toolbar.js +42 -14
  166. package/dist/components/moni-tooltip.d.ts +55 -25
  167. package/dist/components/moni-tooltip.d.ts.map +1 -1
  168. package/dist/components/moni-tooltip.js +54 -24
  169. package/dist/components/moni-typography.d.ts +43 -18
  170. package/dist/components/moni-typography.d.ts.map +1 -1
  171. package/dist/components/moni-typography.js +42 -17
  172. package/dist/index.d.ts +47 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +59 -2
  175. package/dist/styles/tailwind.css +67 -0
  176. package/dist/styles/tokens.css +111 -99
  177. package/dist/utils/color.d.ts +181 -2
  178. package/dist/utils/color.d.ts.map +1 -1
  179. package/dist/utils/color.js +182 -4
  180. package/dist/utils/theme.svelte.d.ts +305 -2
  181. package/dist/utils/theme.svelte.d.ts.map +1 -1
  182. package/dist/utils/theme.svelte.js +331 -2
  183. package/dist/web-components.d.ts +28 -0
  184. package/dist/web-components.d.ts.map +1 -1
  185. package/dist/web-components.js +29 -2
  186. package/package.json +1 -1
  187. package/src/actions/index.ts +7 -0
  188. package/src/components/_base/field-styles.ts +165 -37
  189. package/src/components/_base/index.ts +27 -0
  190. package/src/components/_base/interaction-styles.ts +86 -33
  191. package/src/components/_base/moni-element.ts +44 -8
  192. package/src/components/_base/shared-styles.ts +114 -21
  193. package/src/components/index.ts +7 -0
  194. package/src/components/loading-shapes.ts +7 -0
  195. package/src/components/moni-app-bar.ts +127 -26
  196. package/src/components/moni-badge.ts +128 -14
  197. package/src/components/moni-bottom-sheet.ts +125 -13
  198. package/src/components/moni-button-group.ts +50 -23
  199. package/src/components/moni-button-segment.ts +28 -7
  200. package/src/components/moni-button.ts +51 -31
  201. package/src/components/moni-card.ts +90 -26
  202. package/src/components/moni-carousel.ts +67 -16
  203. package/src/components/moni-checkbox.ts +125 -14
  204. package/src/components/moni-chip.ts +52 -25
  205. package/src/components/moni-color-field.ts +44 -5
  206. package/src/components/moni-context-menu.ts +44 -21
  207. package/src/components/moni-dialog.ts +111 -14
  208. package/src/components/moni-divider.ts +50 -14
  209. package/src/components/moni-expansion.ts +44 -7
  210. package/src/components/moni-fab-menu.ts +39 -19
  211. package/src/components/moni-fab.ts +47 -20
  212. package/src/components/moni-file-field.ts +54 -13
  213. package/src/components/moni-icon.ts +80 -10
  214. package/src/components/moni-list-item.ts +56 -24
  215. package/src/components/moni-list.ts +37 -12
  216. package/src/components/moni-loading-indicator.ts +38 -10
  217. package/src/components/moni-menu-item.ts +31 -7
  218. package/src/components/moni-menu.ts +52 -26
  219. package/src/components/moni-morph-modal.ts +58 -24
  220. package/src/components/moni-nav-item.ts +49 -8
  221. package/src/components/moni-nav.ts +54 -18
  222. package/src/components/moni-progress.ts +109 -16
  223. package/src/components/moni-radio.ts +111 -13
  224. package/src/components/moni-ripple.ts +126 -9
  225. package/src/components/moni-segmented-button.ts +31 -10
  226. package/src/components/moni-select-option.ts +42 -7
  227. package/src/components/moni-select.ts +79 -1
  228. package/src/components/moni-side-sheet.ts +54 -16
  229. package/src/components/moni-slider.ts +56 -24
  230. package/src/components/moni-snackbar.ts +90 -16
  231. package/src/components/moni-split-button.ts +38 -8
  232. package/src/components/moni-step.ts +42 -8
  233. package/src/components/moni-stepper.ts +43 -5
  234. package/src/components/moni-switch.ts +106 -13
  235. package/src/components/moni-tab.ts +35 -7
  236. package/src/components/moni-tabs.ts +49 -10
  237. package/src/components/moni-text-field.ts +55 -9
  238. package/src/components/moni-textarea.ts +49 -18
  239. package/src/components/moni-time-picker.ts +41 -10
  240. package/src/components/moni-toolbar.ts +43 -14
  241. package/src/components/moni-tooltip.ts +55 -24
  242. package/src/components/moni-typography.ts +43 -17
  243. package/src/index.ts +67 -3
  244. package/src/styles/tailwind.css +67 -0
  245. package/src/styles/tokens.css +111 -99
  246. package/src/types/svelte-runes.d.ts +64 -2
  247. package/src/utils/color.ts +286 -5
  248. package/src/utils/theme.svelte.ts +411 -2
  249. package/src/web-components.ts +31 -2
  250. package/dist/assets/shapes/arch.svg +0 -1
  251. package/dist/assets/shapes/arrow.svg +0 -1
  252. package/dist/assets/shapes/boom.svg +0 -1
  253. package/dist/assets/shapes/burst.svg +0 -1
  254. package/dist/assets/shapes/circle.svg +0 -1
  255. package/dist/assets/shapes/clamshell.svg +0 -1
  256. package/dist/assets/shapes/diamond.svg +0 -1
  257. package/dist/assets/shapes/fan.svg +0 -1
  258. package/dist/assets/shapes/flower.svg +0 -1
  259. package/dist/assets/shapes/gem.svg +0 -1
  260. package/dist/assets/shapes/ghost-ish.svg +0 -1
  261. package/dist/assets/shapes/heart.svg +0 -1
  262. package/dist/assets/shapes/leaf-clover4.svg +0 -1
  263. package/dist/assets/shapes/leaf-clover8.svg +0 -1
  264. package/dist/assets/shapes/loading-indicator.svg +0 -1
  265. package/dist/assets/shapes/oval.svg +0 -1
  266. package/dist/assets/shapes/pentagon.svg +0 -1
  267. package/dist/assets/shapes/pill.svg +0 -1
  268. package/dist/assets/shapes/pixel-circle.svg +0 -1
  269. package/dist/assets/shapes/pixel-triangle.svg +0 -1
  270. package/dist/assets/shapes/puffy-diamond.svg +0 -1
  271. package/dist/assets/shapes/puffy.svg +0 -1
  272. package/dist/assets/shapes/semicircle.svg +0 -1
  273. package/dist/assets/shapes/sided-cookie12.svg +0 -1
  274. package/dist/assets/shapes/sided-cookie4.svg +0 -1
  275. package/dist/assets/shapes/sided-cookie6.svg +0 -1
  276. package/dist/assets/shapes/sided-cookie7.svg +0 -1
  277. package/dist/assets/shapes/sided-cookie9.svg +0 -1
  278. package/dist/assets/shapes/slanted.svg +0 -1
  279. package/dist/assets/shapes/soft-boom.svg +0 -1
  280. package/dist/assets/shapes/soft-burst.svg +0 -1
  281. package/dist/assets/shapes/square.svg +0 -1
  282. package/dist/assets/shapes/sunny.svg +0 -1
  283. package/dist/assets/shapes/triangle.svg +0 -1
  284. package/dist/assets/shapes/very-sunny.svg +0 -1
  285. package/dist/assets/shapes/wavy-circle.svg +0 -1
  286. package/dist/assets/shapes/wavy.svg +0 -1
  287. package/src/assets/shapes/arch.svg +0 -1
  288. package/src/assets/shapes/arrow.svg +0 -1
  289. package/src/assets/shapes/boom.svg +0 -1
  290. package/src/assets/shapes/burst.svg +0 -1
  291. package/src/assets/shapes/circle.svg +0 -1
  292. package/src/assets/shapes/clamshell.svg +0 -1
  293. package/src/assets/shapes/diamond.svg +0 -1
  294. package/src/assets/shapes/fan.svg +0 -1
  295. package/src/assets/shapes/flower.svg +0 -1
  296. package/src/assets/shapes/gem.svg +0 -1
  297. package/src/assets/shapes/ghost-ish.svg +0 -1
  298. package/src/assets/shapes/heart.svg +0 -1
  299. package/src/assets/shapes/leaf-clover4.svg +0 -1
  300. package/src/assets/shapes/leaf-clover8.svg +0 -1
  301. package/src/assets/shapes/loading-indicator.svg +0 -1
  302. package/src/assets/shapes/oval.svg +0 -1
  303. package/src/assets/shapes/pentagon.svg +0 -1
  304. package/src/assets/shapes/pill.svg +0 -1
  305. package/src/assets/shapes/pixel-circle.svg +0 -1
  306. package/src/assets/shapes/pixel-triangle.svg +0 -1
  307. package/src/assets/shapes/puffy-diamond.svg +0 -1
  308. package/src/assets/shapes/puffy.svg +0 -1
  309. package/src/assets/shapes/semicircle.svg +0 -1
  310. package/src/assets/shapes/sided-cookie12.svg +0 -1
  311. package/src/assets/shapes/sided-cookie4.svg +0 -1
  312. package/src/assets/shapes/sided-cookie6.svg +0 -1
  313. package/src/assets/shapes/sided-cookie7.svg +0 -1
  314. package/src/assets/shapes/sided-cookie9.svg +0 -1
  315. package/src/assets/shapes/slanted.svg +0 -1
  316. package/src/assets/shapes/soft-boom.svg +0 -1
  317. package/src/assets/shapes/soft-burst.svg +0 -1
  318. package/src/assets/shapes/square.svg +0 -1
  319. package/src/assets/shapes/sunny.svg +0 -1
  320. package/src/assets/shapes/triangle.svg +0 -1
  321. package/src/assets/shapes/very-sunny.svg +0 -1
  322. package/src/assets/shapes/wavy-circle.svg +0 -1
  323. package/src/assets/shapes/wavy.svg +0 -1
@@ -1,29 +1,153 @@
1
1
  /**
2
- * ThemeEngine — gestión reactiva del tema visual de Moni.
3
- * Soporta: modo claro/oscuro, color semilla, densidad, radio, fuente y grain.
2
+ * @file utils/theme.svelte.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
8
+ /**
9
+ * @module theme
10
+ *
11
+ * Reactive theme engine for the Moni design system.
12
+ *
13
+ * `ThemeEngine` is the single source of truth for all visual customization
14
+ * options exposed to users: color seed, light/dark mode, contrast, density,
15
+ * border radius, typography, and motion reduction.
16
+ *
17
+ * **Architecture:**
18
+ * - The engine is a **singleton** accessed via {@link getThemeEngine}. This
19
+ * ensures that all app-level components share the same reactive state.
20
+ * - Settings are persisted to `localStorage` under {@link STORAGE_KEY} so
21
+ * they survive page reloads.
22
+ * - The class uses Svelte 5 `$state` runes for reactivity. Consumers in
23
+ * Svelte components can read `engine.resolvedMode` or `engine.scheme`
24
+ * reactively without any additional subscription setup.
25
+ * - In SSR or non-browser environments, all DOM-side effects are skipped
26
+ * gracefully via `typeof window === 'undefined'` / `typeof document === 'undefined'` guards.
27
+ *
28
+ * **CSS custom properties set by {@link ThemeEngine.apply}:**
29
+ * - `--moni-spacing-density` — numeric multiplier (e.g. 0.75, 1.0, 1.25, 1.6)
30
+ * - `--moni-radius-base` — border-radius base value (e.g. `'0px'`, `'12px'`, `'20px'`)
31
+ * - `--moni-font-sans` — font-family stack for body text
32
+ * - `--moni-font-title` — font-family stack for headings
33
+ * - `--moni-grain-opacity` — CSS opacity for the texture overlay (0–1)
34
+ * - `moni-reduce-motion` — class toggled on `<html>` when reduce-motion is active
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * // In a Svelte component or framework-agnostic module:
39
+ * import { getThemeEngine } from '@moni-labs/moni-ui';
40
+ *
41
+ * const theme = getThemeEngine();
42
+ * theme.setSeedColor('#4f46e5');
43
+ * theme.setMode('dark');
44
+ * ```
4
45
  */
5
46
 
6
47
  import { generateScheme, applySchemeToDocument, getDefaultSeed, type ColorScheme, type ContrastLevel } from './color.js';
7
48
 
49
+ // ─────────────────────────────────────────────────────────────────────────────
50
+ // Public type aliases
51
+ // ─────────────────────────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Color scheme polarity / light-dark preference.
55
+ *
56
+ * - `'light'` — Always apply the light palette regardless of OS setting.
57
+ * - `'dark'` — Always apply the dark palette regardless of OS setting.
58
+ * - `'system'` — Follow `prefers-color-scheme` media query. Updates
59
+ * automatically when the user changes their OS preference.
60
+ */
8
61
  export type ThemeMode = 'light' | 'dark' | 'system';
62
+
63
+ /**
64
+ * Spacing density scale.
65
+ *
66
+ * Controls the `--moni-spacing-density` custom property, which scales padding,
67
+ * gap, and height values throughout the component library.
68
+ *
69
+ * | Value | Multiplier | Use case |
70
+ * |---------------|------------|----------------------------------------|
71
+ * | `'compact'` | 0.75 | Dense data tables, admin dashboards |
72
+ * | `'default'` | 1.0 | Standard consumer UIs |
73
+ * | `'comfortable'`| 1.25 | Touch-friendly interfaces |
74
+ * | `'spacious'` | 1.6 | Large-display / presentation screens |
75
+ */
9
76
  export type ThemeDensity = 'compact' | 'default' | 'comfortable' | 'spacious';
77
+
78
+ /**
79
+ * Global border-radius style.
80
+ *
81
+ * Sets the `--moni-radius-base` custom property used as the base radius for
82
+ * cards, dialogs, sheets, and other container elements.
83
+ *
84
+ * - `'sharp'` → `0px` — No rounding; geometric aesthetic.
85
+ * - `'default'` → `12px` — Moderate rounding per M3 spec (medium shape).
86
+ * - `'rounded'` → `20px` — Expressive full-curve shapes; default for Moni brand.
87
+ */
10
88
  export type ThemeRadius = 'sharp' | 'default' | 'rounded';
89
+
90
+ /**
91
+ * Available typeface families for body and title text.
92
+ *
93
+ * Each value maps to a specific font-family stack in {@link fontFamily}.
94
+ *
95
+ * - `'geist'` — Geist (Vercel), system-ui fallback. Default body font.
96
+ * - `'inter'` — Inter, system-ui fallback. Classic UI sans-serif.
97
+ * - `'roboto'` — Roboto, system-ui fallback. Material Design reference font.
98
+ * - `'instrument'` — Instrument Serif, Georgia fallback. Editorial serif for titles.
99
+ */
11
100
  export type ThemeFont = 'geist' | 'inter' | 'roboto' | 'instrument';
12
101
 
102
+ // ─────────────────────────────────────────────────────────────────────────────
103
+ // Settings interface
104
+ // ─────────────────────────────────────────────────────────────────────────────
105
+
106
+ /**
107
+ * Complete snapshot of all user-configurable theme preferences.
108
+ *
109
+ * This interface is serialized to JSON and stored in `localStorage`. Adding
110
+ * new optional fields is backward-compatible; the {@link parseSettings}
111
+ * function merges with {@link defaults} to fill any missing keys.
112
+ */
13
113
  export interface ThemeSettings {
114
+ /** Light/dark/system color scheme preference. */
14
115
  mode: ThemeMode;
116
+ /** Seed hex color used to generate the full color scheme. */
15
117
  seedColor: string;
118
+ /** WCAG contrast enhancement level for generated colors. */
16
119
  contrast: ContrastLevel;
120
+ /** Component spacing density multiplier. */
17
121
  density: ThemeDensity;
122
+ /** Global border-radius style for containers. */
18
123
  radius: ThemeRadius;
124
+ /** Typeface for body and UI text. */
19
125
  font: ThemeFont;
126
+ /** Typeface for display, headline, and title text. */
20
127
  titleFont: ThemeFont;
128
+ /** Opacity of the film-grain texture overlay (0–1). `0` disables the grain. */
21
129
  grainOpacity: number;
130
+ /** When `true`, disables non-essential CSS transitions and animations. */
22
131
  reduceMotion: boolean;
23
132
  }
24
133
 
134
+ // ─────────────────────────────────────────────────────────────────────────────
135
+ // Constants
136
+ // ─────────────────────────────────────────────────────────────────────────────
137
+
138
+ /**
139
+ * `localStorage` key under which theme settings are persisted.
140
+ *
141
+ * The `v1` suffix allows future breaking changes to use a new key (e.g.
142
+ * `moni-theme-settings-v2`) without conflicting with stale stored values.
143
+ */
25
144
  const STORAGE_KEY = 'moni-theme-settings-v1';
26
145
 
146
+ /**
147
+ * Factory default values for all {@link ThemeSettings} fields.
148
+ *
149
+ * Applied when no stored settings exist or when {@link ThemeEngine.reset} is called.
150
+ */
27
151
  const defaults: ThemeSettings = {
28
152
  mode: 'system',
29
153
  seedColor: getDefaultSeed(),
@@ -36,21 +160,55 @@ const defaults: ThemeSettings = {
36
160
  reduceMotion: false
37
161
  };
38
162
 
163
+ // ─────────────────────────────────────────────────────────────────────────────
164
+ // Private helpers
165
+ // ─────────────────────────────────────────────────────────────────────────────
166
+
167
+ /**
168
+ * Parses a raw JSON string from `localStorage` into a {@link ThemeSettings} object.
169
+ *
170
+ * Unknown or missing keys are filled in from {@link defaults}, making this
171
+ * function safe to call after schema additions (forward-compatible reads).
172
+ * Malformed JSON falls back to defaults silently rather than throwing.
173
+ *
174
+ * @param raw - The raw string from `localStorage.getItem(STORAGE_KEY)`,
175
+ * or `null` if the key was not present.
176
+ * @returns A fully populated `ThemeSettings` object.
177
+ */
39
178
  function parseSettings(raw: string | null): ThemeSettings {
40
179
  if (!raw) return { ...defaults };
41
180
  try {
42
181
  const parsed = JSON.parse(raw) as Partial<ThemeSettings>;
182
+ // Merge: stored values override defaults; missing keys fall back to defaults.
43
183
  return { ...defaults, ...parsed };
44
184
  } catch {
185
+ // JSON.parse failed (corrupted storage). Fall back to defaults.
45
186
  return { ...defaults };
46
187
  }
47
188
  }
48
189
 
190
+ /**
191
+ * Resolves the effective light/dark mode based on the OS media query.
192
+ *
193
+ * Safe to call in SSR — returns `'light'` when `window` is not available,
194
+ * which is the least disruptive default for server-rendered HTML.
195
+ *
196
+ * @returns `'dark'` if the user's OS prefers dark mode, otherwise `'light'`.
197
+ */
49
198
  function getSystemMode(): 'light' | 'dark' {
50
199
  if (typeof window === 'undefined') return 'light';
51
200
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
52
201
  }
53
202
 
203
+ /**
204
+ * Maps a {@link ThemeDensity} token to its numeric multiplier.
205
+ *
206
+ * The returned value is written to `--moni-spacing-density`. Components that
207
+ * support density scaling multiply their base spacing by this factor.
208
+ *
209
+ * @param density - The density label to resolve.
210
+ * @returns A numeric multiplier: `0.75` | `1.0` | `1.25` | `1.6`.
211
+ */
54
212
  function densityValue(density: ThemeDensity): number {
55
213
  switch (density) {
56
214
  case 'compact':
@@ -64,6 +222,15 @@ function densityValue(density: ThemeDensity): number {
64
222
  }
65
223
  }
66
224
 
225
+ /**
226
+ * Maps a {@link ThemeRadius} token to a CSS length value.
227
+ *
228
+ * The returned string is written to `--moni-radius-base` and is consumed by
229
+ * component styles that derive their border-radius from this token.
230
+ *
231
+ * @param radius - The radius label to resolve.
232
+ * @returns A CSS length string: `'0px'` | `'12px'` | `'20px'`.
233
+ */
67
234
  function radiusValue(radius: ThemeRadius): string {
68
235
  switch (radius) {
69
236
  case 'sharp':
@@ -75,6 +242,15 @@ function radiusValue(radius: ThemeRadius): string {
75
242
  }
76
243
  }
77
244
 
245
+ /**
246
+ * Maps a {@link ThemeFont} token to a CSS `font-family` stack string.
247
+ *
248
+ * The stacks follow the pattern `'Primary Font', system-ui fallback` to
249
+ * ensure graceful degradation when the primary font is not loaded.
250
+ *
251
+ * @param font - The font label to resolve.
252
+ * @returns A CSS `font-family` value string ready to pass to `setProperty`.
253
+ */
78
254
  function fontFamily(font: ThemeFont): string {
79
255
  switch (font) {
80
256
  case 'inter':
@@ -84,17 +260,101 @@ function fontFamily(font: ThemeFont): string {
84
260
  case 'instrument':
85
261
  return "'Instrument Serif', Georgia, serif";
86
262
  default:
263
+ // 'geist' is the Moni brand default.
87
264
  return "'Geist', system-ui, sans-serif";
88
265
  }
89
266
  }
90
267
 
268
+ // ─────────────────────────────────────────────────────────────────────────────
269
+ // ThemeEngine class
270
+ // ─────────────────────────────────────────────────────────────────────────────
271
+
272
+ /**
273
+ * Reactive singleton that orchestrates the full Moni visual theme.
274
+ *
275
+ * `ThemeEngine` is responsible for:
276
+ * 1. Loading persisted settings from `localStorage` on construction.
277
+ * 2. Listening to OS `prefers-color-scheme` changes when mode is `'system'`.
278
+ * 3. Generating the full 27-role `ColorScheme` from the current seed color.
279
+ * 4. Writing all CSS custom properties to the document root.
280
+ * 5. Persisting settings to `localStorage` on every user-initiated change.
281
+ *
282
+ * **Reactivity:** Public fields `settings`, `resolvedMode`, and `scheme` are
283
+ * Svelte 5 `$state` runes. Any Svelte template reading these fields will
284
+ * automatically re-render when they change.
285
+ *
286
+ * **Singleton pattern:** Do not instantiate this class directly. Always use
287
+ * {@link getThemeEngine}, which returns a module-level singleton and ensures
288
+ * exactly one engine exists per page lifecycle.
289
+ *
290
+ * **SSR compatibility:** The constructor is safe to call in a server context —
291
+ * all DOM/window access is guarded and skipped when unavailable.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * import { getThemeEngine } from '@moni-labs/moni-ui';
296
+ *
297
+ * const theme = getThemeEngine();
298
+ *
299
+ * // Change the seed color — triggers scheme regeneration and DOM update.
300
+ * theme.setSeedColor('#e91e63');
301
+ *
302
+ * // Read the current resolved scheme in a framework-agnostic way.
303
+ * console.log(theme.scheme.primary);
304
+ *
305
+ * // Reset to factory defaults.
306
+ * theme.reset();
307
+ * ```
308
+ */
91
309
  export class ThemeEngine {
310
+ /**
311
+ * The complete set of current user preferences.
312
+ *
313
+ * Mutate via the setter methods (e.g. `setMode`, `setSeedColor`) rather
314
+ * than directly, to ensure DOM updates and persistence are triggered.
315
+ */
92
316
  settings = $state<ThemeSettings>({ ...defaults });
317
+
318
+ /**
319
+ * The resolved light/dark mode after applying the `'system'` logic.
320
+ *
321
+ * Always either `'light'` or `'dark'` — never `'system'`. Use this value
322
+ * for icon toggling, conditional rendering, and `aria-*` attributes.
323
+ */
93
324
  resolvedMode = $state<'light' | 'dark'>('light');
325
+
326
+ /**
327
+ * The currently active 27-role color scheme, derived from `settings.seedColor`,
328
+ * `resolvedMode`, and `settings.contrast`.
329
+ *
330
+ * Reactive: re-assigned every time {@link apply} runs.
331
+ */
94
332
  scheme = $state<ColorScheme>(generateScheme(defaults.seedColor, 'light', defaults.contrast));
333
+
334
+ /**
335
+ * The OS `prefers-color-scheme` media query list.
336
+ * Used to listen for system-level dark mode changes when mode is `'system'`.
337
+ * `null` in SSR or when `window` is unavailable.
338
+ */
95
339
  private mediaQuery: MediaQueryList | null = null;
340
+
341
+ /**
342
+ * Guard flag to prevent attaching duplicate `'change'` listeners to
343
+ * {@link mediaQuery} if `bindSystem` is called more than once.
344
+ */
96
345
  private bound = false;
97
346
 
347
+ /**
348
+ * Initializes the engine.
349
+ *
350
+ * In browser environments:
351
+ * 1. Loads and merges stored settings from `localStorage`.
352
+ * 2. Captures the `prefers-color-scheme` media query.
353
+ * 3. Attaches a `'change'` listener to react to OS preference updates.
354
+ * 4. Runs the first {@link apply} pass to paint the document immediately.
355
+ *
356
+ * In SSR environments, the constructor is a no-op.
357
+ */
98
358
  constructor() {
99
359
  if (typeof window !== 'undefined') {
100
360
  this.settings = parseSettings(localStorage.getItem(STORAGE_KEY));
@@ -104,31 +364,68 @@ export class ThemeEngine {
104
364
  }
105
365
  }
106
366
 
367
+ /**
368
+ * Attaches a listener to the OS color-scheme media query.
369
+ *
370
+ * Calls {@link apply} whenever the OS switches between light and dark mode,
371
+ * but only when `settings.mode === 'system'` — the effective mode check
372
+ * inside `apply` handles the conditional logic.
373
+ *
374
+ * Idempotent: calling this method multiple times is safe; the `bound` flag
375
+ * ensures only one listener is ever attached.
376
+ */
107
377
  private bindSystem() {
108
378
  if (this.bound || !this.mediaQuery) return;
109
379
  this.bound = true;
110
380
  this.mediaQuery.addEventListener('change', () => this.apply());
111
381
  }
112
382
 
383
+ /**
384
+ * Resolves the effective polarity (`'light'` or `'dark'`) from `settings.mode`.
385
+ *
386
+ * When mode is `'system'`, defers to {@link getSystemMode} which reads the
387
+ * OS media query. Otherwise returns the explicit mode directly.
388
+ *
389
+ * @returns `'light'` or `'dark'`.
390
+ */
113
391
  private getEffectiveMode(): 'light' | 'dark' {
114
392
  if (this.settings.mode === 'system') return getSystemMode();
115
393
  return this.settings.mode;
116
394
  }
117
395
 
396
+ /**
397
+ * Regenerates the color scheme and applies all theme tokens to the document.
398
+ *
399
+ * This is the central "render" method of the engine. It:
400
+ * 1. Resolves the effective mode (`'light'` | `'dark'`).
401
+ * 2. Generates a fresh {@link ColorScheme} from the current seed and contrast.
402
+ * 3. Writes all 81 CSS custom properties (3 namespaces × 27 roles) to `<html>`.
403
+ * 4. Sets `--moni-spacing-density`, `--moni-radius-base`, `--moni-font-sans`,
404
+ * `--moni-font-title`, and `--moni-grain-opacity`.
405
+ * 5. Toggles the `moni-reduce-motion` class on `<html>`.
406
+ *
407
+ * **Side effects:** Mutates `document.documentElement.style` and `classList`.
408
+ * No-op in SSR (`typeof document === 'undefined'`).
409
+ */
118
410
  apply() {
119
411
  if (typeof document === 'undefined') return;
412
+
120
413
  const mode = this.getEffectiveMode();
121
414
  this.resolvedMode = mode;
122
415
  this.scheme = generateScheme(this.settings.seedColor, mode, this.settings.contrast);
123
416
  applySchemeToDocument(this.scheme, mode, document);
124
417
 
125
418
  const root = document.documentElement;
419
+
420
+ // Write non-color theme tokens.
126
421
  root.style.setProperty('--moni-spacing-density', densityValue(this.settings.density).toString());
127
422
  root.style.setProperty('--moni-radius-base', radiusValue(this.settings.radius));
128
423
  root.style.setProperty('--moni-font-sans', fontFamily(this.settings.font));
129
424
  root.style.setProperty('--moni-font-title', fontFamily(this.settings.titleFont));
130
425
  root.style.setProperty('--moni-grain-opacity', this.settings.grainOpacity.toString());
131
426
 
427
+ // Toggle motion reduction class. CSS `@media (prefers-reduced-motion)`
428
+ // handles native OS preference; this class covers user-initiated opt-in.
132
429
  if (this.settings.reduceMotion) {
133
430
  root.classList.add('moni-reduce-motion');
134
431
  } else {
@@ -136,6 +433,12 @@ export class ThemeEngine {
136
433
  }
137
434
  }
138
435
 
436
+ /**
437
+ * Persists the current {@link settings} to `localStorage` and re-applies the theme.
438
+ *
439
+ * Called internally by all setter methods after mutating `settings`.
440
+ * No-op when `localStorage` is unavailable (SSR, private browsing, quota exceeded).
441
+ */
139
442
  persist() {
140
443
  if (typeof localStorage !== 'undefined') {
141
444
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.settings));
@@ -143,64 +446,170 @@ export class ThemeEngine {
143
446
  this.apply();
144
447
  }
145
448
 
449
+ // ── Public setters ──────────────────────────────────────────────────────
450
+
451
+ /**
452
+ * Updates the color scheme polarity.
453
+ *
454
+ * @param mode - `'light'`, `'dark'`, or `'system'` (follows OS preference).
455
+ */
146
456
  setMode(mode: ThemeMode) {
147
457
  this.settings.mode = mode;
148
458
  this.persist();
149
459
  }
150
460
 
461
+ /**
462
+ * Updates the seed color used to generate the full color scheme.
463
+ *
464
+ * Automatically prepends `#` if the value doesn't already have one,
465
+ * ensuring the stored value is always a valid 7-character hex string.
466
+ *
467
+ * @param color - A hex color string, with or without the `#` prefix
468
+ * (e.g. `'#4f46e5'` or `'4f46e5'`).
469
+ */
151
470
  setSeedColor(color: string) {
152
471
  this.settings.seedColor = color.startsWith('#') ? color : `#${color}`;
153
472
  this.persist();
154
473
  }
155
474
 
475
+ /**
476
+ * Updates the WCAG contrast enhancement level for the generated palette.
477
+ *
478
+ * @param contrast - `'standard'` (AA), `'medium'` (enhanced), or `'high'` (AAA).
479
+ */
156
480
  setContrast(contrast: ContrastLevel) {
157
481
  this.settings.contrast = contrast;
158
482
  this.persist();
159
483
  }
160
484
 
485
+ /**
486
+ * Updates the spacing density multiplier.
487
+ *
488
+ * @param density - `'compact'`, `'default'`, `'comfortable'`, or `'spacious'`.
489
+ */
161
490
  setDensity(density: ThemeDensity) {
162
491
  this.settings.density = density;
163
492
  this.persist();
164
493
  }
165
494
 
495
+ /**
496
+ * Updates the global border-radius style.
497
+ *
498
+ * @param radius - `'sharp'` (0px), `'default'` (12px), or `'rounded'` (20px).
499
+ */
166
500
  setRadius(radius: ThemeRadius) {
167
501
  this.settings.radius = radius;
168
502
  this.persist();
169
503
  }
170
504
 
505
+ /**
506
+ * Updates the body/UI typeface.
507
+ *
508
+ * @param font - One of `'geist'` | `'inter'` | `'roboto'` | `'instrument'`.
509
+ */
171
510
  setFont(font: ThemeFont) {
172
511
  this.settings.font = font;
173
512
  this.persist();
174
513
  }
175
514
 
515
+ /**
516
+ * Updates the display/title typeface.
517
+ *
518
+ * @param font - One of `'geist'` | `'inter'` | `'roboto'` | `'instrument'`.
519
+ */
176
520
  setTitleFont(font: ThemeFont) {
177
521
  this.settings.titleFont = font;
178
522
  this.persist();
179
523
  }
180
524
 
525
+ /**
526
+ * Updates the grain texture opacity.
527
+ *
528
+ * The value is clamped to [0, 1] before storing. Setting to `0` effectively
529
+ * disables the grain overlay without removing the element from the DOM.
530
+ *
531
+ * @param opacity - A number in the range [0, 1].
532
+ */
181
533
  setGrainOpacity(opacity: number) {
182
534
  this.settings.grainOpacity = Math.max(0, Math.min(1, opacity));
183
535
  this.persist();
184
536
  }
185
537
 
538
+ /**
539
+ * Enables or disables user-initiated motion reduction.
540
+ *
541
+ * When `true`, the `moni-reduce-motion` class is added to `<html>`, which
542
+ * CSS components use to disable non-essential transitions and animations.
543
+ * This is separate from `prefers-reduced-motion` (OS-level) and allows
544
+ * users to opt in without changing their OS settings.
545
+ *
546
+ * @param reduce - `true` to disable motion, `false` to restore it.
547
+ */
186
548
  setReduceMotion(reduce: boolean) {
187
549
  this.settings.reduceMotion = reduce;
188
550
  this.persist();
189
551
  }
190
552
 
553
+ /**
554
+ * Resets all settings to factory defaults and re-applies the theme.
555
+ *
556
+ * The reset is also persisted to `localStorage` so subsequent page loads
557
+ * start from defaults rather than the old stored values.
558
+ */
191
559
  reset() {
192
560
  this.settings = { ...defaults };
193
561
  this.persist();
194
562
  }
195
563
  }
196
564
 
565
+ // ─────────────────────────────────────────────────────────────────────────────
566
+ // Module-level singleton
567
+ // ─────────────────────────────────────────────────────────────────────────────
568
+
569
+ /**
570
+ * Module-level singleton instance.
571
+ *
572
+ * `null` until the first call to {@link getThemeEngine}. Using `null` (rather
573
+ * than eagerly constructing) ensures the engine is only created in browser
574
+ * contexts where DOM and `localStorage` are actually available.
575
+ */
197
576
  let engine: ThemeEngine | null = null;
198
577
 
578
+ /**
579
+ * Returns the module-level {@link ThemeEngine} singleton, creating it on first call.
580
+ *
581
+ * This is the **recommended** entry point for all consumers. Calling this
582
+ * function multiple times always returns the same instance.
583
+ *
584
+ * @returns The shared `ThemeEngine` instance.
585
+ *
586
+ * @example
587
+ * ```ts
588
+ * import { getThemeEngine } from '@moni-labs/moni-ui';
589
+ *
590
+ * const theme = getThemeEngine();
591
+ * theme.setMode('dark');
592
+ * ```
593
+ */
199
594
  export function getThemeEngine(): ThemeEngine {
200
595
  if (!engine) engine = new ThemeEngine();
201
596
  return engine;
202
597
  }
203
598
 
599
+ /**
600
+ * Destroys the module-level singleton, forcing the next call to
601
+ * {@link getThemeEngine} to create a fresh instance.
602
+ *
603
+ * **Intended for test isolation only.** Do not call this in application code,
604
+ * as it will cause components sharing the singleton to lose their reference.
605
+ *
606
+ * @example
607
+ * ```ts
608
+ * afterEach(() => {
609
+ * resetThemeEngine(); // Start each test with a clean engine.
610
+ * });
611
+ * ```
612
+ */
204
613
  export function resetThemeEngine() {
205
614
  engine = null;
206
615
  }
@@ -1,5 +1,34 @@
1
- // Lightweight entry point for Moni UI Web Components only.
2
- // Auto-registers every <moni-*> custom element without pulling in Svelte.
1
+ /**
2
+ * @file web-components.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
8
+ /**
9
+ * @module web-components
10
+ *
11
+ * Lightweight entry point that registers and exports only the Moni UI Web
12
+ * Components, without importing any Svelte-specific utilities.
13
+ *
14
+ * **When to use this instead of the main `index.ts`:**
15
+ * - In non-Svelte projects (React, Vue, vanilla JS, HTML-only) where importing
16
+ * `theme.svelte.ts` would introduce an unnecessary Svelte 5 dependency.
17
+ * - When bundler tree-shaking is not sufficient to eliminate Svelte imports.
18
+ *
19
+ * This file has the same side-effect as the main entry: it calls
20
+ * `customElements.define()` for every `<moni-*>` element via the
21
+ * `./components/index.js` import.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * // In a React or Vue project:
26
+ * import '@moni-labs/moni-ui/web-components';
27
+ * // All <moni-*> elements are now available globally in the DOM.
28
+ * ```
29
+ */
30
+
31
+ // Side-effect: auto-registers every <moni-*> custom element.
3
32
  import './components/index.js';
4
33
 
5
34
  export * from './components/index.js';
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="304" height="304" fill="none" viewBox="0 0 304 304"><path fill="#d0bcff" d="M304 253.72c0 6.11 0 9.17-.31 11.74-2.38 20.05-18.18 35.85-38.23 38.23-2.57.31-5.63.31-11.74.31H50.281c-6.112 0-9.168 0-11.737-.31-20.049-2.38-35.856-18.18-38.239-38.23C0 262.89 0 259.83 0 253.72V152C0 68.05 68.053 0 152 0c83.95 0 152 68.05 152 152z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="316" height="278" fill="none" viewBox="0 0 316 278"><path fill="#d0bcff" d="M271.57 122.2c-14.018-21.58-28.035-43.19-42.053-64.77-9.094-14.01-18.35-28.21-30.645-39.34-12.296-11.15-28.224-19.03-44.556-18-14.34.92-27.632 8.63-38.125 18.7S97.546 41.26 89.528 53.54C67.842 86.72 46.13 119.9 24.444 153.1 14.139 168.86 3.565 185.31.713 204.09c-3.444 22.69 5.839 45.8 22.305 60.89 17.219 15.78 45.12 14.5 66.08 10.18 22.977-4.75 45.443-13.68 68.877-13.65 20.072 0 39.471 6.6 59.004 11.4 19.506 4.77 40.466 7.71 59.3.61 23.38-8.79 40.169-33.79 39.712-59.45-.431-23.41-13.534-44.32-26.152-63.8-6.081-9.35-12.161-18.72-18.242-28.07z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" fill="none" viewBox="0 0 320 320"><path fill="#d0bcff" d="M156.818 10.16c.753-6.02 1.13-9.03 1.702-9.57a2.145 2.145 0 0 1 2.96 0c.572.54.949 3.55 1.702 9.57l9.578 76.58c.304 2.43.456 3.64.892 4.15.633.72 1.668.95 2.541.54.601-.28 1.232-1.33 2.493-3.43l39.729-66.04c3.124-5.19 4.686-7.79 5.427-8.05 1.078-.37 2.26.16 2.704 1.22.305.72-.569 3.63-2.317 9.44l-22.23 73.87c-.706 2.35-1.058 3.52-.863 4.15a2.17 2.17 0 0 0 2.102 1.54c.663-.01 1.663-.71 3.663-2.11l63.01-44.08c4.956-3.47 7.433-5.2 8.214-5.14a2.177 2.177 0 0 1 1.98 2.21c-.014.79-1.988 3.09-5.935 7.68l-50.194 58.4c-1.593 1.85-2.389 2.78-2.468 3.44-.115.96.414 1.88 1.299 2.26.609.27 1.806.03 4.199-.43l75.397-14.5c5.929-1.14 8.894-1.71 9.58-1.33.998.55 1.398 1.79.915 2.83-.332.71-3.064 2-8.528 4.58l-69.478 32.83c-2.206 1.04-3.308 1.56-3.648 2.13-.493.83-.382 1.89.272 2.6.45.49 1.636.77 4.009 1.32l74.747 17.59c5.878 1.38 8.818 2.07 9.29 2.7.687.91.552 2.21-.309 2.96-.593.51-3.61.58-9.646.7l-76.75 1.57c-2.436.05-3.654.08-4.195.46a2.19 2.19 0 0 0-.803 2.49c.214.63 1.184 1.37 3.126 2.85l61.173 46.62c4.81 3.67 7.216 5.51 7.393 6.27a2.18 2.18 0 0 1-1.48 2.58c-.749.23-3.531-.95-9.096-3.3l-70.749-29.95c-2.246-.95-3.369-1.43-4.019-1.3a2.18 2.18 0 0 0-1.739 1.94c-.059.66.528 1.74 1.703 3.88l37.021 67.62c2.911 5.31 4.367 7.97 4.219 8.75a2.175 2.175 0 0 1-2.395 1.75c-.778-.1-2.843-2.31-6.973-6.74l-52.517-56.3c-1.667-1.78-2.501-2.68-3.146-2.82a2.15 2.15 0 0 0-2.374 1.06c-.323.58-.22 1.8-.015 4.24l6.467 76.91c.509 6.05.763 9.07.315 9.72a2.16 2.16 0 0 1-2.895.62c-.672-.41-1.663-3.28-3.645-9.01l-25.204-72.9c-.8-2.32-1.2-3.47-1.73-3.87a2.16 2.16 0 0 0-2.598 0c-.53.4-.93 1.55-1.73 3.87l-25.204 72.9c-1.982 5.73-2.973 8.6-3.645 9.01-.976.59-2.242.32-2.895-.62-.448-.65-.194-3.67.315-9.72l6.467-76.91c.205-2.44.308-3.66-.015-4.24a2.146 2.146 0 0 0-2.373-1.06c-.646.14-1.48 1.04-3.147 2.82l-52.517 56.3c-4.13 4.43-6.195 6.64-6.973 6.74a2.175 2.175 0 0 1-2.395-1.75c-.148-.78 1.308-3.44 4.219-8.75l37.021-67.62c1.175-2.14 1.762-3.22 1.703-3.88a2.18 2.18 0 0 0-1.739-1.94c-.65-.13-1.773.35-4.019 1.3l-70.75 29.95c-5.564 2.35-8.346 3.53-9.095 3.3a2.18 2.18 0 0 1-1.48-2.58c.177-.76 2.583-2.6 7.393-6.27l61.173-46.62c1.942-1.48 2.912-2.22 3.126-2.85a2.19 2.19 0 0 0-.803-2.49c-.541-.38-1.76-.41-4.195-.46l-76.75-1.57c-6.036-.12-9.054-.19-9.646-.7a2.19 2.19 0 0 1-.309-2.96c.472-.63 3.412-1.32 9.29-2.7l74.747-17.59c2.373-.55 3.559-.83 4.01-1.32.653-.71.764-1.77.271-2.6-.34-.57-1.442-1.09-3.648-2.13L15.63 117.94c-5.464-2.58-8.196-3.87-8.528-4.58a2.18 2.18 0 0 1 .915-2.83c.686-.38 3.65.19 9.58 1.33l75.397 14.5c2.393.46 3.59.7 4.199.43a2.18 2.18 0 0 0 1.299-2.26c-.078-.66-.875-1.59-2.468-3.44L45.83 62.69c-3.947-4.59-5.92-6.89-5.935-7.68a2.18 2.18 0 0 1 1.98-2.21c.78-.06 3.258 1.67 8.214 5.14l63.01 44.08c2 1.4 3 2.1 3.663 2.11a2.17 2.17 0 0 0 2.102-1.54c.195-.63-.157-1.8-.863-4.15l-22.23-73.87c-1.748-5.81-2.622-8.72-2.317-9.44a2.17 2.17 0 0 1 2.704-1.22c.741.26 2.303 2.86 5.427 8.05L141.314 88c1.261 2.1 1.892 3.15 2.493 3.43.873.41 1.908.18 2.541-.54.436-.51.588-1.72.892-4.15z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" fill="none" viewBox="0 0 320 320"><path fill="#d0bcff" d="M157.39 2.55c.74-1.32 1.1-1.97 1.55-2.25.65-.4 1.47-.4 2.12 0 .45.28.81.93 1.55 2.25l25.26 45.15c.45.81.68 1.22.99 1.46.44.36 1.01.51 1.57.42.39-.06.79-.29 1.58-.77l44.46-26.47c1.29-.77 1.94-1.16 2.46-1.17.77-.03 1.47.38 1.84 1.05.25.47.24 1.22.22 2.73l-.7 51.73c-.02.93-.02 1.39.12 1.76.2.53.62.95 1.15 1.15.37.14.83.14 1.76.12l51.73-.7c1.51-.02 2.26-.03 2.73.22.67.37 1.08 1.07 1.05 1.84-.01.52-.4 1.17-1.17 2.46l-26.47 44.46c-.48.79-.71 1.19-.77 1.58-.09.56.06 1.13.42 1.57.24.31.65.54 1.46.99l45.15 25.26c1.32.74 1.97 1.1 2.25 1.55.4.65.4 1.47 0 2.12-.28.45-.93.81-2.25 1.55l-45.15 25.26c-.81.45-1.22.68-1.46.99-.36.44-.51 1.01-.42 1.57.06.39.29.79.77 1.58l26.47 44.46c.77 1.29 1.16 1.94 1.17 2.46.03.77-.38 1.47-1.05 1.84-.47.25-1.22.24-2.73.22l-51.73-.7c-.93-.02-1.39-.02-1.76.12-.53.2-.95.62-1.15 1.15-.14.37-.14.83-.12 1.76l.7 51.73c.02 1.51.03 2.26-.22 2.73-.37.67-1.07 1.08-1.84 1.05-.52-.01-1.17-.4-2.46-1.17l-44.46-26.47c-.79-.48-1.19-.71-1.58-.77-.56-.09-1.13.06-1.57.42-.31.24-.54.65-.99 1.46l-25.26 45.15c-.74 1.32-1.1 1.97-1.55 2.25-.65.4-1.47.4-2.12 0-.45-.28-.81-.93-1.55-2.25l-25.26-45.15c-.45-.81-.68-1.22-.99-1.46-.44-.36-1.01-.51-1.57-.42-.39.06-.79.29-1.58.77l-44.46 26.47c-1.29.77-1.94 1.16-2.46 1.17-.77.03-1.47-.38-1.84-1.05-.25-.47-.24-1.22-.22-2.73l.7-51.73c.02-.93.02-1.39-.12-1.76-.2-.53-.62-.95-1.15-1.15-.37-.14-.83-.14-1.76-.12l-51.73.7c-1.51.02-2.26.03-2.73-.22a2.01 2.01 0 0 1-1.05-1.84c.01-.52.4-1.17 1.17-2.46l26.47-44.46c.48-.79.71-1.19.77-1.58.09-.56-.06-1.13-.42-1.57-.24-.31-.65-.54-1.46-.99L2.55 162.61c-1.32-.74-1.97-1.1-2.25-1.55-.4-.65-.4-1.47 0-2.12.28-.45.93-.81 2.25-1.55l45.15-25.26c.81-.45 1.22-.68 1.46-.99.36-.44.51-1.01.42-1.57-.06-.39-.29-.79-.77-1.58L22.34 83.53c-.77-1.29-1.16-1.94-1.17-2.46-.03-.77.38-1.47 1.05-1.84.47-.25 1.22-.24 2.73-.22l51.73.7c.93.02 1.39.02 1.76-.12.53-.2.95-.62 1.15-1.15.14-.37.14-.83.12-1.76l-.7-51.73c-.02-1.51-.03-2.26.22-2.73.37-.67 1.07-1.08 1.84-1.05.52.01 1.17.4 2.46 1.17l44.46 26.47c.79.48 1.19.71 1.58.77.56.09 1.13-.06 1.57-.42.31-.24.54-.65.99-1.46z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" fill="none" viewBox="0 0 320 320"><path fill="#d0bcff" d="M320 160c0 88.366-71.634 160-160 160S0 248.366 0 160 71.635 0 160 0c88.366 0 160 71.635 160 160"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="320" height="254" fill="none" viewBox="0 0 320 254"><path fill="#d0bcff" d="M306.405 84.081c6.709 13.51 10.063 20.265 11.757 27.322a67.1 67.1 0 0 1 0 31.194c-1.694 7.057-5.048 13.812-11.757 27.322l-20.438 41.16c-6.709 13.51-10.063 20.265-14.472 25.501-6.375 7.568-14.411 12.963-23.236 15.597C242.155 254 235.446 254 222.028 254H97.972c-13.418 0-20.127 0-26.231-1.822-8.825-2.635-16.861-8.029-23.236-15.598-4.409-5.235-7.763-11.991-14.472-25.501l-20.438-41.16c-6.709-13.51-10.063-20.265-11.757-27.322a67.1 67.1 0 0 1 0-31.194c1.694-7.057 5.048-13.812 11.757-27.322l20.438-41.16c6.709-13.51 10.063-20.266 14.472-25.501C54.88 9.851 62.916 4.457 71.741 1.822 77.845 0 84.554 0 97.972 0h124.056c13.418 0 20.127 0 26.231 1.822 8.825 2.635 16.861 8.029 23.236 15.598 4.409 5.235 7.763 11.99 14.472 25.501z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="268" height="320" fill="none" viewBox="0 0 268 320"><path fill="#d0bcff" d="M191.442 276.481c-16.836 22.033-25.254 33.049-34.976 38.067a49.02 49.02 0 0 1-44.932 0c-9.722-5.018-18.14-16.034-34.976-38.067l-55.912-73.173c-10.24-13.402-15.36-20.102-17.895-27.276a48.1 48.1 0 0 1 0-32.064c2.535-7.174 7.655-13.874 17.895-27.276l55.912-73.173c16.836-22.033 25.254-33.05 34.976-38.067a49.02 49.02 0 0 1 44.932 0c9.722 5.018 18.14 16.034 34.976 38.068l55.912 73.172c10.24 13.402 15.36 20.102 17.895 27.276a48.1 48.1 0 0 1 0 32.064c-2.535 7.174-7.655 13.874-17.895 27.276z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="280" height="280" fill="none" viewBox="0 0 280 280"><path fill="#d0bcff" d="M0 44.21c0-1.56 0-2.34.02-2.999C.717 18.757 18.757.717 41.211.021c.66-.021 1.44-.021 3-.021C52.53 0 56.69 0 60.208.11 179.96 3.825 276.17 100.037 279.89 219.791c.11 3.518.11 7.678.11 15.997 0 1.56 0 2.34-.02 3-.7 22.454-18.74 40.494-41.19 41.191-.66.02-1.44.02-3 .02H62.945c-19.018 0-28.528 0-36.071-2.987a42.53 42.53 0 0 1-23.887-23.887C0 245.583 0 236.073 0 217.055z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="320" height="320" fill="none" viewBox="0 0 320 320"><path fill="#d0bcff" fill-rule="evenodd" d="M273.13 46.863c-11.88-11.875-38.94-6.003-71.58 12.818C191.77 23.286 176.79 0 160 0c-16.8 0-31.78 23.284-41.55 59.678-32.65-18.82-59.7-24.69-71.58-12.817-11.87 11.876-6 38.935 12.82 71.585C23.29 128.222 0 143.204 0 160c0 16.793 23.28 31.773 59.68 41.549-18.83 32.651-24.7 59.712-12.83 71.588 11.88 11.876 38.94 6.001 71.59-12.827C128.22 296.711 143.2 320 160 320c16.79 0 31.77-23.291 41.55-59.693 32.66 18.829 59.72 24.705 71.6 12.829 11.87-11.876 6-38.936-12.83-71.587C296.72 191.773 320 176.793 320 160c0-16.796-23.29-31.778-59.7-41.554 18.83-32.65 24.7-59.708 12.83-71.583" clip-rule="evenodd"/></svg>