@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,69 +1,218 @@
1
1
  /**
2
- * Utilidades de color para generar esquemas compatibles con Material Design 3.
3
- * Basado en @material/material-color-utilities.
2
+ * @file utils/color.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
8
+ /**
9
+ * @module color
10
+ *
11
+ * Color utilities for generating and applying Material Design 3–compliant
12
+ * dynamic color schemes.
13
+ *
14
+ * This module wraps `@material/material-color-utilities` to expose a
15
+ * simplified, opinionated API that covers the full Moni theming pipeline:
16
+ *
17
+ * 1. Convert a user-supplied "seed" hex color to the HCT color space.
18
+ * 2. Generate a complete 27-role `ColorScheme` via `SchemeTonalSpot`.
19
+ * 3. Apply the scheme to the document root as CSS custom properties under
20
+ * three namespaces (`--md-sys-color-*`, `--moni-*`, and bare `--*`)
21
+ * so any component or stylesheet can consume the tokens.
22
+ *
23
+ * **Contrast levels** map to the MD3 contrast spec:
24
+ * - `standard` → 0.0 (WCAG AA baseline)
25
+ * - `medium` → 0.5 (enhanced readability)
26
+ * - `high` → 1.0 (WCAG AAA, maximum legibility)
27
+ *
28
+ * @see https://m3.material.io/styles/color/dynamic-color/overview
29
+ * @see https://github.com/material-foundation/material-color-utilities
4
30
  */
5
31
 
6
32
  import { SchemeTonalSpot, Hct, argbFromHex, hexFromArgb } from '@material/material-color-utilities';
7
33
 
34
+ // ─────────────────────────────────────────────────────────────────────────────
35
+ // Types
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+
38
+ /**
39
+ * WCAG contrast enhancement level for a generated color scheme.
40
+ *
41
+ * Maps to the `contrastLevel` argument of `SchemeTonalSpot`:
42
+ * - `'standard'` → 0.0 — WCAG AA minimum contrast. Best for everyday UIs.
43
+ * - `'medium'` → 0.5 — Raised contrast. Useful for users with mild low-vision.
44
+ * - `'high'` → 1.0 — WCAG AAA maximum contrast. Required for accessibility-first apps.
45
+ */
8
46
  export type ContrastLevel = 'standard' | 'medium' | 'high';
9
47
 
48
+ /**
49
+ * Hue–Saturation–Lightness color representation.
50
+ *
51
+ * All values use the CSS `hsl()` convention:
52
+ * - `h` — hue angle in **degrees**, range [0, 360).
53
+ * - `s` — saturation as a **percentage**, range [0, 100].
54
+ * - `l` — lightness as a **percentage**, range [0, 100].
55
+ */
10
56
  export interface HSL {
57
+ /** Hue angle in degrees [0, 360). */
11
58
  h: number;
59
+ /** Saturation percentage [0, 100]. */
12
60
  s: number;
61
+ /** Lightness percentage [0, 100]. */
13
62
  l: number;
14
63
  }
15
64
 
65
+ /**
66
+ * A complete Material Design 3 color scheme with 27 semantic color roles.
67
+ *
68
+ * Every role is expressed as a 7-character hex string (e.g. `'#6750a4'`).
69
+ * The naming convention follows the MD3 spec directly:
70
+ * - `primary` / `onPrimary` — main brand color and its contrast pair.
71
+ * - `primaryContainer` / `onPrimaryContainer` — lower-emphasis filled containers.
72
+ * - `secondary`, `tertiary`, `error` — supporting accent palettes.
73
+ * - `surface*` — background hierarchy (5 tones).
74
+ * - `inverse*` — used in snackbars and tooltips.
75
+ * - `shadow` — drop-shadow tint.
76
+ *
77
+ * @see https://m3.material.io/styles/color/roles
78
+ */
16
79
  export interface ColorScheme {
80
+ // ── Primary ────────────────────────────────────────────────────────────
81
+ /** High-emphasis brand color. Used for filled buttons, FABs, active indicators. */
17
82
  primary: string;
83
+ /** Text/icon color that guarantees contrast on top of `primary`. */
18
84
  onPrimary: string;
85
+ /** Lower-emphasis container using the primary palette (tone 90 light / tone 30 dark). */
19
86
  primaryContainer: string;
87
+ /** Text/icon color that guarantees contrast on top of `primaryContainer`. */
20
88
  onPrimaryContainer: string;
89
+
90
+ // ── Secondary ──────────────────────────────────────────────────────────
91
+ /** Complementary accent color, less prominent than primary. */
21
92
  secondary: string;
93
+ /** Text/icon color that guarantees contrast on top of `secondary`. */
22
94
  onSecondary: string;
95
+ /** Lower-emphasis container using the secondary palette. */
23
96
  secondaryContainer: string;
97
+ /** Text/icon color that guarantees contrast on top of `secondaryContainer`. */
24
98
  onSecondaryContainer: string;
99
+
100
+ // ── Tertiary ───────────────────────────────────────────────────────────
101
+ /** Optional third accent color for decorative elements. */
25
102
  tertiary: string;
103
+ /** Text/icon color that guarantees contrast on top of `tertiary`. */
26
104
  onTertiary: string;
105
+ /** Lower-emphasis container using the tertiary palette. */
27
106
  tertiaryContainer: string;
107
+ /** Text/icon color that guarantees contrast on top of `tertiaryContainer`. */
28
108
  onTertiaryContainer: string;
109
+
110
+ // ── Error ──────────────────────────────────────────────────────────────
111
+ /** Standard error/destructive color (red family by design). */
29
112
  error: string;
113
+ /** Text/icon color that guarantees contrast on top of `error`. */
30
114
  onError: string;
115
+ /** Lower-emphasis container for error states. */
31
116
  errorContainer: string;
117
+ /** Text/icon color that guarantees contrast on top of `errorContainer`. */
32
118
  onErrorContainer: string;
119
+
120
+ // ── Background & Surface ───────────────────────────────────────────────
121
+ /** Page-level background (typically equivalent to `surface` in M3). */
33
122
  background: string;
123
+ /** Default text/icon color on top of `background`. */
34
124
  onBackground: string;
125
+ /** Base surface color used for sheets, cards, and dialogs. */
35
126
  surface: string;
127
+ /** Default text/icon color on top of `surface`. */
36
128
  onSurface: string;
129
+ /** Subtle variant of surface used for chips, text field backgrounds, etc. */
37
130
  surfaceVariant: string;
131
+ /** Text/icon color that guarantees contrast on top of `surfaceVariant`. */
38
132
  onSurfaceVariant: string;
133
+
134
+ // ── Outline ────────────────────────────────────────────────────────────
135
+ /** Border color for fields, dividers, and outlined components. */
39
136
  outline: string;
137
+ /** Lower-emphasis border color; used for decorative separators. */
40
138
  outlineVariant: string;
139
+
140
+ // ── Surface Container Hierarchy (tone scale) ───────────────────────────
141
+ /** Lightest container tone (lowest elevation). */
41
142
  surfaceContainerLowest: string;
143
+ /** Second lightest container tone. */
42
144
  surfaceContainerLow: string;
145
+ /** Mid-range container tone (default cards, sheets). */
43
146
  surfaceContainer: string;
147
+ /** Second darkest container tone. */
44
148
  surfaceContainerHigh: string;
149
+ /** Darkest container tone (highest elevation equivalent). */
45
150
  surfaceContainerHighest: string;
151
+
152
+ // ── Inverse ────────────────────────────────────────────────────────────
153
+ /** Inverse of `surface`; used for snackbar and tooltip backgrounds. */
46
154
  inverseSurface: string;
155
+ /** Text/icon color that guarantees contrast on top of `inverseSurface`. */
47
156
  inverseOnSurface: string;
157
+ /** Used for action elements (links, buttons) inside inverse surfaces. */
48
158
  inversePrimary: string;
159
+
160
+ // ── Shadow ─────────────────────────────────────────────────────────────
161
+ /** Color tint used as the drop-shadow color for elevation. */
49
162
  shadow: string;
50
163
  }
51
164
 
165
+ // ─────────────────────────────────────────────────────────────────────────────
166
+ // Color conversion utilities
167
+ // ─────────────────────────────────────────────────────────────────────────────
168
+
169
+ /**
170
+ * Converts a 6-digit hex color string to the HSL color model.
171
+ *
172
+ * Normalizes the input (strips optional `#`), parses each 8-bit RGB channel
173
+ * into a [0, 1] float, then applies the standard RGB→HSL algorithm:
174
+ *
175
+ * - Lightness = (max + min) / 2
176
+ * - Saturation = delta / (2 − max − min) if L > 0.5
177
+ * = delta / (max + min) otherwise
178
+ * - Hue = derived from which channel is the maximum
179
+ *
180
+ * When the color is achromatic (r = g = b), hue and saturation are both 0.
181
+ *
182
+ * @param hex - A 6-digit hex color, with or without the `#` prefix.
183
+ * Examples: `'#4f46e5'`, `'4f46e5'`.
184
+ * @returns An {@link HSL} object where `h` ∈ [0, 360), `s` ∈ [0, 100], `l` ∈ [0, 100].
185
+ *
186
+ * @example
187
+ * hexToHsl('#ff0000') // { h: 0, s: 100, l: 50 }
188
+ * hexToHsl('#ffffff') // { h: 0, s: 0, l: 100 }
189
+ * hexToHsl('#4f46e5') // { h: 243, s: 73, l: 59 } (approx)
190
+ */
52
191
  export function hexToHsl(hex: string): HSL {
53
192
  const normalized = hex.replace('#', '');
193
+
194
+ // Parse each 8-bit channel and normalize to [0, 1].
54
195
  const r = parseInt(normalized.substring(0, 2), 16) / 255;
55
196
  const g = parseInt(normalized.substring(2, 4), 16) / 255;
56
197
  const b = parseInt(normalized.substring(4, 6), 16) / 255;
57
198
 
58
199
  const max = Math.max(r, g, b);
59
200
  const min = Math.min(r, g, b);
201
+
202
+ // Initialize hue and saturation; they stay 0 for achromatic colors.
60
203
  let h = 0;
61
204
  let s = 0;
205
+
206
+ // Lightness is always the midpoint between brightest and darkest channel.
62
207
  const l = (max + min) / 2;
63
208
 
64
209
  if (max !== min) {
65
210
  const d = max - min;
211
+
212
+ // Saturation formula differs above and below the 50% lightness threshold.
66
213
  s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
214
+
215
+ // Hue is determined by which channel dominates.
67
216
  switch (max) {
68
217
  case r:
69
218
  h = (g - b) / d + (g < b ? 6 : 0);
@@ -75,37 +224,109 @@ export function hexToHsl(hex: string): HSL {
75
224
  h = (r - g) / d + 4;
76
225
  break;
77
226
  }
227
+ // Normalize hue from a 0–6 sector index to degrees [0, 360).
78
228
  h /= 6;
79
229
  }
80
230
 
81
231
  return { h: h * 360, s: s * 100, l: l * 100 };
82
232
  }
83
233
 
234
+ /**
235
+ * Converts an HSL color to a 6-digit hex string.
236
+ *
237
+ * Uses the CSS Color Level 4 reference algorithm. Internally computes R, G,
238
+ * and B via a piecewise function `f(n)` that maps chroma sector offsets to
239
+ * individual channel values.
240
+ *
241
+ * @param hsl - An {@link HSL} object where `h` ∈ [0, 360), `s` ∈ [0, 100], `l` ∈ [0, 100].
242
+ * @returns A lowercase 7-character hex string including the `#` prefix (e.g. `'#4f46e5'`).
243
+ *
244
+ * @example
245
+ * hslToHex({ h: 0, s: 100, l: 50 }) // '#ff0000'
246
+ * hslToHex({ h: 0, s: 0, l: 100 }) // '#ffffff'
247
+ */
84
248
  export function hslToHex({ h, s, l }: HSL): string {
249
+ // Normalize percentages to [0, 1] for the algorithm.
85
250
  s /= 100;
86
251
  l /= 100;
252
+
253
+ /**
254
+ * Sector index helper. Maps the offset `n` (0, 4, 8) to a position within
255
+ * the 12-sector hue wheel (each sector = 30°).
256
+ */
87
257
  const k = (n: number) => (n + h / 30) % 12;
258
+
259
+ /** Chroma magnitude: 0 at lightness extremes, max at L=0.5. */
88
260
  const a = s * Math.min(l, 1 - l);
261
+
262
+ /**
263
+ * Per-channel computation. Returns a 2-character hex string for the
264
+ * channel corresponding to sector offset `n` (0=R, 8=G, 4=B).
265
+ */
89
266
  const f = (n: number) => {
90
267
  const color = l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
91
268
  return Math.round(color * 255)
92
269
  .toString(16)
93
270
  .padStart(2, '0');
94
271
  };
272
+
95
273
  return `#${f(0)}${f(8)}${f(4)}`;
96
274
  }
97
275
 
276
+ // ─────────────────────────────────────────────────────────────────────────────
277
+ // Scheme generation
278
+ // ─────────────────────────────────────────────────────────────────────────────
98
279
 
99
-
280
+ /**
281
+ * Generates a complete Material Design 3 color scheme from a seed hex color.
282
+ *
283
+ * Uses `SchemeTonalSpot` — the standard M3 dynamic color algorithm — which
284
+ * derives all 27 color roles from a single source hue while respecting the
285
+ * target lightness/contrast requirements for each role.
286
+ *
287
+ * **Algorithm pipeline:**
288
+ * 1. Parse `seedHex` → ARGB integer via `argbFromHex`.
289
+ * 2. Convert ARGB → HCT (Hue–Chroma–Tone) color space.
290
+ * 3. Construct a `SchemeTonalSpot` with the requested mode and contrast level.
291
+ * 4. Extract each scheme role via `hexFromArgb` and build the {@link ColorScheme}.
292
+ *
293
+ * @param seedHex - The source/brand color as a hex string. The `#` prefix
294
+ * is optional (e.g. `'#4f46e5'` or `'4f46e5'`).
295
+ * @param mode - Color scheme polarity. `'light'` produces light backgrounds
296
+ * with dark text; `'dark'` inverts the tone mapping.
297
+ * Defaults to `'light'`.
298
+ * @param contrast - WCAG contrast enhancement level. Defaults to `'standard'`.
299
+ *
300
+ * @returns A fully populated {@link ColorScheme} where every value is a
301
+ * lowercase 7-character hex string (e.g. `'#6750a4'`).
302
+ *
303
+ * @example
304
+ * // Generate a standard light scheme from an indigo seed.
305
+ * const scheme = generateScheme('#4f46e5');
306
+ * console.log(scheme.primary); // e.g. '#5046e4'
307
+ * console.log(scheme.primaryContainer); // e.g. '#e9e7ff'
308
+ *
309
+ * @example
310
+ * // High-contrast dark scheme.
311
+ * const darkHC = generateScheme('#4f46e5', 'dark', 'high');
312
+ */
100
313
  export function generateScheme(
101
314
  seedHex: string,
102
315
  mode: 'light' | 'dark' = 'light',
103
316
  contrast: ContrastLevel = 'standard'
104
317
  ): ColorScheme {
318
+ // Ensure the seed always has a leading '#' for argbFromHex.
105
319
  const seed = seedHex.startsWith('#') ? seedHex : `#${seedHex}`;
320
+
321
+ // Step 1: Convert hex → ARGB integer.
106
322
  const argb = argbFromHex(seed);
323
+
324
+ // Step 2: Convert ARGB → HCT. HCT is the perceptual color space used
325
+ // internally by the MD3 algorithm; it preserves human color perception
326
+ // better than RGB or HSL for palette generation.
107
327
  const hct = Hct.fromInt(argb);
108
328
 
329
+ // Step 3: Map the ContrastLevel union to a numeric value expected by the SDK.
109
330
  let contrastLevel = 0.0;
110
331
  if (contrast === 'medium') {
111
332
  contrastLevel = 0.5;
@@ -113,8 +334,11 @@ export function generateScheme(
113
334
  contrastLevel = 1.0;
114
335
  }
115
336
 
337
+ // Step 4: Build the tonal-spot scheme. isDark=true shifts every tone value
338
+ // to keep roles readable on dark backgrounds.
116
339
  const scheme = new SchemeTonalSpot(hct, mode === 'dark', contrastLevel);
117
340
 
341
+ // Step 5: Extract every color role from the scheme and convert back to hex.
118
342
  return {
119
343
  primary: hexFromArgb(scheme.primary),
120
344
  onPrimary: hexFromArgb(scheme.onPrimary),
@@ -152,19 +376,76 @@ export function generateScheme(
152
376
  };
153
377
  }
154
378
 
379
+ // ─────────────────────────────────────────────────────────────────────────────
380
+ // DOM integration
381
+ // ─────────────────────────────────────────────────────────────────────────────
382
+
383
+ /**
384
+ * Writes a {@link ColorScheme} to the document root as CSS custom properties.
385
+ *
386
+ * For each color role in the scheme, **three aliases** are set on
387
+ * `document.documentElement` so every context can consume the tokens:
388
+ *
389
+ * | Namespace prefix | Example | Consumer |
390
+ * |----------------------|----------------------------------|-----------------------|
391
+ * | `--md-sys-color-` | `--md-sys-color-primary` | MD3 spec / third-party|
392
+ * | `--moni-` | `--moni-primary` | Moni components |
393
+ * | `--` (bare) | `--primary` | BeerCSS / legacy |
394
+ *
395
+ * camelCase role names are converted to kebab-case automatically
396
+ * (e.g. `primaryContainer` → `primary-container`).
397
+ *
398
+ * Additionally sets `data-theme="light|dark"` on `<html>` so CSS can use
399
+ * `:root[data-theme='dark']` selectors for any additional overrides.
400
+ *
401
+ * **Side effects:** Mutates `doc.documentElement.style` and attributes.
402
+ * This function should only be called in browser environments.
403
+ *
404
+ * @param scheme - The color scheme to apply, as produced by {@link generateScheme}.
405
+ * @param mode - The resolved mode (`'light'` or `'dark'`); written to `data-theme`.
406
+ * @param doc - The `Document` to target. Pass `document` in normal usage;
407
+ * accepts a custom document for iframe or SSR scenarios.
408
+ *
409
+ * @example
410
+ * const scheme = generateScheme('#4f46e5', 'dark');
411
+ * applySchemeToDocument(scheme, 'dark', document);
412
+ * // <html data-theme="dark" style="--md-sys-color-primary: #...; --moni-primary: #...; --primary: #...">
413
+ */
155
414
  export function applySchemeToDocument(scheme: ColorScheme, mode: 'light' | 'dark', doc: Document) {
156
415
  const root = doc.documentElement;
416
+
417
+ // MD3 canonical namespace prefix.
157
418
  const prefix = '--md-sys-color-';
158
419
 
159
420
  for (const [key, value] of Object.entries(scheme)) {
421
+ // Convert camelCase → kebab-case (e.g. 'onPrimary' → 'on-primary').
160
422
  const kebab = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
161
- root.style.setProperty(`${prefix}${kebab}`, value);
162
- root.style.setProperty(`--${kebab}`, value);
423
+
424
+ // Set all three namespace aliases simultaneously.
425
+ root.style.setProperty(`${prefix}${kebab}`, value); // MD3 spec namespace
426
+ root.style.setProperty(`--moni-${kebab}`, value); // Moni namespace
427
+ root.style.setProperty(`--${kebab}`, value); // Bare/BeerCSS namespace
163
428
  }
164
429
 
430
+ // Mark the document with the resolved mode for CSS `[data-theme]` selectors.
165
431
  root.setAttribute('data-theme', mode);
166
432
  }
167
433
 
434
+ // ─────────────────────────────────────────────────────────────────────────────
435
+ // Defaults
436
+ // ─────────────────────────────────────────────────────────────────────────────
437
+
438
+ /**
439
+ * Returns the default seed color used by the Moni design system.
440
+ *
441
+ * The default seed is a deep indigo (`#4f46e5`) that maps to a material-spec
442
+ * primary hue of roughly 243°. It was chosen because it:
443
+ * - Generates accessible contrast ratios in both light and dark modes.
444
+ * - Feels brand-neutral enough to serve as a placeholder before users
445
+ * customize their color.
446
+ *
447
+ * @returns The default seed hex string `'#4f46e5'`.
448
+ */
168
449
  export function getDefaultSeed(): string {
169
450
  return '#4f46e5';
170
451
  }