@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,65 @@
1
+ /**
2
+ * @file components/moni-nav.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { html, css } from 'lit';
2
9
  import { customElement, property } from 'lit/decorators.js';
3
10
  import { MoniElement, sharedStyles } from './_base/index.js';
4
11
 
5
12
  /**
6
- * Visual-only navigation. Renders a `<nav>` styled with BeerCSS helpers.
13
+ * Material Design 3 Navigation container component.
14
+ *
15
+ * `<moni-nav>` is the container that wraps `<moni-nav-item>` elements and
16
+ * controls the M3 navigation pattern: navigation bar, navigation rail, or
17
+ * navigation drawer.
18
+ *
19
+ * **M3 spec references:**
20
+ * - Navigation bar: `m3-docs/components/navigation-bar/specs.md`
21
+ * - Navigation rail: `m3-docs/components/navigation-rail/specs.md`
22
+ * - Navigation drawer: `m3-docs/components/navigation-drawer/specs.md`
23
+ *
24
+ * **Navigation patterns:**
25
+ * - **Navigation bar** (`placement="bottom"`) — Horizontal bar of icon+label
26
+ * items at the bottom of the screen. Best for 3–5 top-level destinations.
27
+ * - **Navigation rail** (`variant="rail"`) — Vertical rail of icon+label items
28
+ * on the side of the screen. Best for medium/expanded breakpoints.
29
+ * - **Standard drawer** (`variant="drawer"`) — Always-visible vertical panel
30
+ * with full text labels. No scrim. Best for large screens.
31
+ * - **Modal drawer** (`variant="drawer" modal`) — Overlay drawer with scrim.
32
+ * Opened/closed via the `open` property. Traps keyboard focus while open.
33
+ * Closes on `Escape` key press.
34
+ *
35
+ * **Keyboard handling:**
36
+ * When `modal=true`, the component adds a global `keydown` listener in
37
+ * `connectedCallback` that closes the drawer on `Escape`. The listener is
38
+ * removed in `disconnectedCallback`.
39
+ *
40
+ * @example
41
+ * ```html
42
+ * <!-- Bottom navigation bar -->
43
+ * <moni-nav placement="bottom">
44
+ * <moni-nav-item icon="home" label="Home" active></moni-nav-item>
45
+ * <moni-nav-item icon="search" label="Search"></moni-nav-item>
46
+ * <moni-nav-item icon="person" label="Profile"></moni-nav-item>
47
+ * </moni-nav>
7
48
  *
8
- * M3 navigation patterns (`m3-docs/components/navigation-*`):
9
- * - Navigation bar: placement="bottom"
10
- * - Navigation rail: placement="left|right" variant="rail"
11
- * - Navigation drawer: placement="left|right" variant="drawer"
12
- * * Standard drawer: always visible, no scrim (default)
13
- * * Modal drawer: `modal` toggles open/closed, renders a scrim and
14
- * traps focus while open. See `m3-docs/components/navigation-drawer/specs.md`.
49
+ * <!-- Modal navigation drawer -->
50
+ * <moni-nav variant="drawer" modal open placement="left">
51
+ * <h3 slot="header">My App</h3>
52
+ * <moni-nav-item icon="home" label="Home" active></moni-nav-item>
53
+ * <moni-nav-item icon="settings" label="Settings"></moni-nav-item>
54
+ * </moni-nav>
55
+ * ```
15
56
  *
16
- * Attributes:
17
- * - placement: top (default) | bottom | left | right
18
- * - variant: rail | drawer
19
- * - modal: present → drawer is modal (requires variant="drawer")
20
- * - open: present → modal drawer is open (default true)
21
- * - layout: vertical | horizontal | auto (default)
57
+ * @slot default - `<moni-nav-item>` children.
58
+ * @slot header - Content above the nav items (drawer variant only).
59
+ * @slot footer - Content below the nav items (drawer variant only).
22
60
  *
23
- * Slots:
24
- * - default: <moni-nav-item> children
25
- * - header: content above nav items (drawer only)
26
- * - footer: content below nav items (drawer only)
61
+ * @csspart nav - The inner `<nav>` element.
62
+ * @csspart scrim - The backdrop scrim (modal drawer only).
27
63
  */
28
64
  @customElement('moni-nav')
29
65
  export class MoniNav extends MoniElement {
@@ -1,40 +1,133 @@
1
+ /**
2
+ * @file components/moni-progress.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { html, css, svg, nothing } from 'lit';
2
9
  import { customElement, property, state } from 'lit/decorators.js';
3
10
  import { MoniElement, sharedStyles } from './_base/index.js';
4
11
 
5
12
  /**
6
- * Progress indicator that faithfully ports BeerCSS's progress styles.
13
+ * Material Design 3 Progress Indicator component.
14
+ *
15
+ * Progress indicators express an unspecified wait time or display the length
16
+ * of a process. They inform users about the status of ongoing processes such
17
+ * as loading an app, submitting a form, or saving updates.
18
+ *
19
+ * **M3 spec reference:** `m3-docs/components/progress-indicators/specs.md`
20
+ *
21
+ * **Variants:**
22
+ * - `linear` (default) — A horizontal bar that fills left-to-right.
23
+ * - `circular` — A circular SVG stroke indicator.
24
+ * - `wavy` — An animated wave bar (Moni extension; not in M3 spec).
25
+ * - `circular-wavy` — Circular + wave combo (Moni extension).
7
26
  *
8
- * BeerCSS uses the native <progress> element with `::after`, `::before` and
9
- * `mask-image` pseudo-elements. Those don't work inside Shadow DOM because:
10
- * - `<progress>` native pseudo-elements (::webkit-progress-value, ::after)
11
- * are blocked by the UA shadow root in Chrome/Firefox within a custom shadow.
12
- * - `mask-image` on those pseudo-elements doesn't apply at all in shadows.
27
+ * **Shadow DOM compatibility note:**
28
+ * BeerCSS's progress uses native `<progress>` pseudo-elements (`::before`,
29
+ * `::after`, `::webkit-progress-value`) and `mask-image`, which are blocked
30
+ * by the UA shadow root in Chrome/Firefox. This component uses a plain `<div>`
31
+ * wrapper that replicates the visual rules exactly, and an `<svg>` element
32
+ * for the circular variant using SVG stroke-dashoffset animation for superior
33
+ * cross-browser support compared to `conic-gradient`.
13
34
  *
14
- * Solution: use a plain <div> wrapper that replicates BeerCSS's visual rules
15
- * exactly, and an SVG for the circular variant (matching BeerCSS's conic-gradient
16
- * approach but with SVG stroke for better cross-browser support).
35
+ * **Percentage computation:**
36
+ * `_pct` is computed in `willUpdate()` as `(value / max) * 100`, clamped to
37
+ * `[0, 100]`. When `indeterminate` is set, `_pct` is fixed at `50` to drive
38
+ * the infinite loop animation.
17
39
  *
18
- * Attributes:
19
- * - value: 0..max (omit for indeterminate)
20
- * - max: upper bound (default 100)
21
- * - variant: linear (default) | circular | wavy | circular-wavy
22
- * - size: small | medium (default) | large
23
- * - indeterminate: present infinite animation
40
+ * @example
41
+ * ```html
42
+ * <!-- Determinate linear progress -->
43
+ * <moni-progress value="65" max="100"></moni-progress>
44
+ *
45
+ * <!-- Indeterminate circular progress (loading spinner) -->
46
+ * <moni-progress variant="circular" indeterminate></moni-progress>
47
+ * ```
48
+ *
49
+ * @csspart bar - The outer container div.
50
+ * @csspart fill - The inner fill element (linear variant).
51
+ * @csspart svg - The SVG element (circular variant).
24
52
  */
25
53
  @customElement('moni-progress')
26
54
  export class MoniProgress extends MoniElement {
55
+ /**
56
+ * Current progress value.
57
+ *
58
+ * Must be in the range `[0, max]`. Values outside this range are clamped
59
+ * during percentage computation in `willUpdate()`. Ignored when
60
+ * `indeterminate` is set.
61
+ *
62
+ * @default 0
63
+ */
27
64
  @property({ type: Number, reflect: true }) value = 0;
65
+
66
+ /**
67
+ * Maximum value of the progress range.
68
+ *
69
+ * Defaults to `100` so `value` can be set as a percentage directly.
70
+ * For non-percentage ranges (e.g. steps), set `max` to the total step count
71
+ * and `value` to the current step.
72
+ *
73
+ * @default 100
74
+ */
28
75
  @property({ type: Number, reflect: true }) max = 100;
76
+
77
+ /**
78
+ * Visual variant of the progress indicator.
79
+ *
80
+ * - `'linear'` (default) — Horizontal fill bar.
81
+ * - `'circular'` — SVG circle with stroke-dashoffset animation.
82
+ * - `'wavy'` — Animated wave bar.
83
+ * - `'circular-wavy'` — Combination of circular and wave.
84
+ *
85
+ * @default 'linear'
86
+ */
29
87
  @property({ reflect: true })
30
88
  variant: 'linear' | 'circular' | 'wavy' | 'circular-wavy' = 'linear';
89
+
90
+ /**
91
+ * Visual size of the progress indicator.
92
+ *
93
+ * - `'small'` — Compact; suitable for inline or tight layouts.
94
+ * - `'medium'` — Standard M3 size (default).
95
+ * - `'large'` — Prominent; for full-page loading states.
96
+ *
97
+ * @default 'medium'
98
+ */
31
99
  @property({ reflect: true })
32
100
  size: 'small' | 'medium' | 'large' = 'medium';
101
+
102
+ /**
103
+ * When `true`, the indicator animates in an infinite loop regardless of `value`.
104
+ *
105
+ * Use for operations where the completion percentage is unknown
106
+ * (e.g. network requests, file processing). When `indeterminate` is set,
107
+ * `_pct` is fixed at `50` to drive a continuous sweep animation.
108
+ *
109
+ * @default false
110
+ */
33
111
  @property({ type: Boolean, reflect: true }) indeterminate = false;
34
112
 
35
- /** Computed fill percentage (0-100) used in styles/SVG */
113
+ /**
114
+ * Computed fill percentage in the range `[0, 100]`.
115
+ *
116
+ * Updated in `willUpdate()` whenever `value`, `max`, or `indeterminate` changes.
117
+ * Used directly in CSS custom property bindings and SVG stroke attributes.
118
+ *
119
+ * @internal
120
+ */
36
121
  @state() private _pct = 0;
37
122
 
123
+ /**
124
+ * Computes the fill percentage before each render.
125
+ *
126
+ * Recalculates `_pct` whenever `value`, `max`, or `indeterminate` changes.
127
+ * The `Math.max(1, max)` guard prevents division-by-zero when `max` is 0.
128
+ *
129
+ * @param changed - Map of property names to their previous values.
130
+ */
38
131
  override willUpdate(changed: Map<string, unknown>) {
39
132
  if (changed.has('value') || changed.has('max') || changed.has('indeterminate')) {
40
133
  this._pct = this.indeterminate
@@ -1,3 +1,10 @@
1
+ /**
2
+ * @file components/moni-radio.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { html, css } from 'lit';
2
9
  import { customElement, property, query } from 'lit/decorators.js';
3
10
  import { ifDefined } from 'lit/directives/if-defined.js';
@@ -5,34 +12,112 @@ import { live } from 'lit/directives/live.js';
5
12
  import { MoniElement, sharedStyles } from './_base/index.js';
6
13
 
7
14
  /**
8
- * Radio that faithfully ports BeerCSS's `.radio` styles.
15
+ * Material Design 3 Radio Button component.
16
+ *
17
+ * Radio buttons allow users to select exactly one item from a set of mutually
18
+ * exclusive options. They share the same visual architecture as
19
+ * `<moni-checkbox>` but use `type="radio"` and implement group deselection.
20
+ *
21
+ * **M3 spec reference:** `m3-docs/components/radio/specs.md`
22
+ *
23
+ * **Visual architecture (BeerCSS pattern):**
24
+ * Identical to the checkbox pattern: the native `<input type="radio">` occupies
25
+ * real layout space at `--_size` × `--_size` but is hidden via `opacity: 0`.
26
+ * A sibling `<span>` renders:
27
+ * - `::before` — the radio icon (`radio_button_unchecked` / `radio_button_checked`).
28
+ * - `::after` — the hover/focus ripple ring.
29
+ *
30
+ * **Group deselection:**
31
+ * When a radio is checked, `_onChange` queries the component's `getRootNode()`
32
+ * for all `moni-radio` elements sharing the same `name` attribute and sets
33
+ * their `checked` property to `false`. This mirrors native browser behavior
34
+ * for radio groups across shadow DOM boundaries where `name` grouping does
35
+ * not work natively.
9
36
  *
10
- * BeerCSS architecture:
11
- * - `.radio` is inline-flex, aligns items center
12
- * - `input` has width/height = --_size, opacity: 0 (real layout space, not absolute)
13
- * - `span::before` shows "radio_button_unchecked" / "radio_button_checked" via Material Symbols font
14
- * - `span::after` is the ripple hover effect
37
+ * @fires change - Bubbles and is composed. Fired when this radio is selected.
38
+ * Read `element.checked` for the new state.
15
39
  *
16
- * Attributes:
17
- * - label: text label
18
- * - checked: present
19
- * - disabled: present
20
- * - size: small | medium (default) | large | extra
21
- * - name: forwarded to input.name (group radios by name)
22
- * - value: forwarded to input.value
40
+ * @example
41
+ * ```html
42
+ * <moni-radio name="color" value="red" label="Red"></moni-radio>
43
+ * <moni-radio name="color" value="green" label="Green"></moni-radio>
44
+ * <moni-radio name="color" value="blue" label="Blue" checked></moni-radio>
45
+ * ```
46
+ *
47
+ * @csspart radio - The outer `<label>` element.
23
48
  */
24
49
  @customElement('moni-radio')
25
50
  export class MoniRadio extends MoniElement {
51
+ /**
52
+ * Text label displayed to the right of the radio icon.
53
+ *
54
+ * When non-empty, renders as a text node. When empty, the default slot
55
+ * is rendered, allowing slotted HTML content as the label.
56
+ *
57
+ * @default ''
58
+ */
26
59
  @property({ reflect: true }) label = '';
60
+
61
+ /**
62
+ * Whether this radio button is currently selected.
63
+ *
64
+ * Reflected as an attribute so CSS selectors can target it. Synced to
65
+ * the native input via `updated()`.
66
+ *
67
+ * @default false
68
+ */
27
69
  @property({ type: Boolean, reflect: true }) checked = false;
70
+
71
+ /**
72
+ * When `true`, the radio is non-interactive and renders at 50% opacity.
73
+ *
74
+ * @default false
75
+ */
28
76
  @property({ type: Boolean, reflect: true }) disabled = false;
77
+
78
+ /**
79
+ * Visual size of the radio icon and its invisible hit area.
80
+ *
81
+ * | Value | `--_size` |
82
+ * |------------|-----------|
83
+ * | `'small'` | 1rem |
84
+ * | `'medium'` | 1.5rem |
85
+ * | `'large'` | 2rem |
86
+ * | `'extra'` | 2.5rem |
87
+ *
88
+ * @default 'medium'
89
+ */
29
90
  @property({ reflect: true })
30
91
  size: 'small' | 'medium' | 'large' | 'extra' = 'medium';
92
+
93
+ /**
94
+ * Radio group name. Radios with the same `name` in the same root node
95
+ * are treated as a mutual-exclusion group by `_onChange`.
96
+ *
97
+ * Note: Native `<input type="radio">` groups only work within the same
98
+ * document root. Since `moni-radio` uses shadow DOM, the deselection
99
+ * of siblings is handled imperatively in `_onChange`.
100
+ *
101
+ * @default ''
102
+ */
31
103
  @property({ reflect: true }) name = '';
104
+
105
+ /**
106
+ * Forwarded to the native `<input value>` attribute.
107
+ * The value submitted in a form when this radio is selected.
108
+ *
109
+ * @default ''
110
+ */
32
111
  @property({ reflect: true }) value = '';
33
112
 
113
+ /** Direct reference to the native input element for programmatic access. */
34
114
  @query('input') private _input!: HTMLInputElement;
35
115
 
116
+ /**
117
+ * Syncs `checked` and `disabled` to the native input after each render cycle.
118
+ *
119
+ * @param changed - Map of changed property names to their previous values.
120
+ */
36
121
  override updated(changed: Map<string, unknown>) {
37
122
  if (this._input) {
38
123
  if (changed.has('checked')) this._input.checked = this.checked;
@@ -152,6 +237,19 @@ export class MoniRadio extends MoniElement {
152
237
  `
153
238
  ];
154
239
 
240
+ /**
241
+ * Handles the native input `change` event.
242
+ *
243
+ * On selection, deselects all sibling `moni-radio` elements with the same
244
+ * `name` in the same root node (document or shadow root). This is necessary
245
+ * because native radio group exclusion only works within the same document
246
+ * root and does not cross shadow DOM boundaries.
247
+ *
248
+ * After deselection, dispatches a composed `'change'` event so it is
249
+ * audible to parent elements in the light DOM.
250
+ *
251
+ * @param e - The native `change` event from the hidden `<input>`.
252
+ */
155
253
  private _onChange(e: Event) {
156
254
  this.checked = (e.target as HTMLInputElement).checked;
157
255
  if (this.checked && this.name) {
@@ -1,33 +1,135 @@
1
+ /**
2
+ * @file components/moni-ripple.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { html, css } from 'lit';
2
9
  import { customElement, property } from 'lit/decorators.js';
3
10
  import { MoniElement, sharedStyles } from './_base/index.js';
4
11
 
5
12
  /**
6
- * Visual-only ripple decoration.
13
+ * Visual-only ripple decoration component.
14
+ *
15
+ * Provides a pointer-origin ripple animation — the expanding circle starts
16
+ * at the exact pointer-down coordinates rather than the element's center.
17
+ * This is the full-fidelity M3 ripple; for a simpler CSS-only center-ripple,
18
+ * use the `interactionStyles` `.interactive::after` pseudo-element instead.
19
+ *
20
+ * **Usage:**
21
+ * Drop `<moni-ripple>` as a **child** of any interactive element. The component
22
+ * automatically attaches a `pointerdown` listener to its `parentElement` and
23
+ * calculates the ripple origin in percentage coordinates relative to the parent.
24
+ *
25
+ * The parent element must NOT have `position: static` (the ripple applies
26
+ * `position: relative` automatically in `connectedCallback`).
27
+ *
28
+ * **Timing model:**
29
+ * On `pointerdown`:
30
+ * 1. `active = false` is set (cancels any in-progress ripple).
31
+ * 2. A `requestAnimationFrame` tick ensures the browser has processed the reset.
32
+ * 3. `active = true` triggers the CSS scale animation.
33
+ * 4. A `setTimeout` of `duration` ms (based on `speed`) resets `active = false`.
7
34
  *
8
- * To trigger a ripple at a specific point, set the `x` and `y` attributes
9
- * and toggle the `active` attribute. The visual scale-in animation will
10
- * run for `duration` ms and then the element becomes hidden.
35
+ * The duration matches the CSS transition duration so the opacity fade-out
36
+ * completes before `active` is cleared.
11
37
  *
12
- * Attributes:
13
- * - x, y: origin in px (0..100, %)
14
- * - active: present visible
15
- * - speed: fast | normal (default) | slow
16
- * - color: primary (default) | secondary | surface
38
+ * **Cleanup:**
39
+ * `disconnectedCallback` removes the `pointerdown` listener and clears any
40
+ * pending timeout. Always call `super.disconnectedCallback()` if subclassing.
41
+ *
42
+ * @example
43
+ * ```html
44
+ * <!-- Ripple on a custom element -->
45
+ * <div class="my-button" style="position: relative; overflow: hidden;">
46
+ * Click me
47
+ * <moni-ripple color="primary"></moni-ripple>
48
+ * </div>
49
+ * ```
50
+ *
51
+ * @csspart ripple - The inner `<span>` that performs the scale animation.
17
52
  */
18
53
  @customElement('moni-ripple')
19
54
  export class MoniRipple extends MoniElement {
55
+ /**
56
+ * Horizontal origin of the ripple as a percentage of the parent's width.
57
+ *
58
+ * Set automatically by `_onPointerDown` based on the pointer coordinates.
59
+ * Can be set manually to trigger a ripple at a specific location.
60
+ *
61
+ * @default 50
62
+ */
20
63
  @property({ type: Number, reflect: true }) x = 50;
64
+
65
+ /**
66
+ * Vertical origin of the ripple as a percentage of the parent's height.
67
+ *
68
+ * Set automatically by `_onPointerDown` based on the pointer coordinates.
69
+ *
70
+ * @default 50
71
+ */
21
72
  @property({ type: Number, reflect: true }) y = 50;
73
+
74
+ /**
75
+ * When `true`, the ripple is visible and animating.
76
+ *
77
+ * Toggled automatically by `_onPointerDown`. Can be set manually for
78
+ * programmatically-triggered ripple effects.
79
+ *
80
+ * @default false
81
+ */
22
82
  @property({ type: Boolean, reflect: true }) active = false;
83
+
84
+ /**
85
+ * Animation speed of the ripple expand-and-fade sequence.
86
+ *
87
+ * Maps to the `--_dur` CSS custom property:
88
+ * - `'fast'` — 300ms
89
+ * - `'normal'` — 600ms (default)
90
+ * - `'slow'` — 1200ms
91
+ *
92
+ * @default 'normal'
93
+ */
23
94
  @property({ reflect: true })
24
95
  speed: 'fast' | 'normal' | 'slow' = 'normal';
96
+
97
+ /**
98
+ * Color token for the ripple overlay.
99
+ *
100
+ * Sets the `color` CSS property on `:host`, which the `.ripple` span
101
+ * inherits via `background-color: currentColor`.
102
+ *
103
+ * - `'primary'` — `--primary` (default)
104
+ * - `'secondary'` — `--secondary`
105
+ * - `'surface'` — `--surface-variant` (subtle, for surface containers)
106
+ *
107
+ * @default 'primary'
108
+ */
25
109
  @property({ reflect: true })
26
110
  color: 'primary' | 'secondary' | 'surface' = 'primary';
27
111
 
112
+ /**
113
+ * Reference to the parent element that the ripple is anchored to.
114
+ * Populated in `connectedCallback`, cleared in `disconnectedCallback`.
115
+ */
28
116
  private _target: HTMLElement | null = null;
117
+
118
+ /**
119
+ * ID of the pending `setTimeout` that clears `active` after the animation.
120
+ * Stored so it can be cancelled if a second pointer event fires before the
121
+ * first ripple finishes (rapid double-tap prevention).
122
+ */
29
123
  private _timeoutId: any = null;
30
124
 
125
+ /**
126
+ * Attaches the ripple to its parent element.
127
+ *
128
+ * - Stores a reference to `parentElement` for pointer event listening.
129
+ * - Ensures the parent has `position: relative` so the ripple's `position: absolute`
130
+ * stays within bounds.
131
+ * - Registers the `_onPointerDown` event listener.
132
+ */
31
133
  override connectedCallback() {
32
134
  super.connectedCallback();
33
135
  this._target = this.parentElement;
@@ -40,6 +142,12 @@ export class MoniRipple extends MoniElement {
40
142
  }
41
143
  }
42
144
 
145
+ /**
146
+ * Detaches the ripple from its parent element.
147
+ *
148
+ * Removes the `pointerdown` listener and clears any pending timeout to
149
+ * prevent the `active` flag from being set after the element is removed.
150
+ */
43
151
  override disconnectedCallback() {
44
152
  if (this._target) {
45
153
  this._target.removeEventListener('pointerdown', this._onPointerDown);
@@ -50,6 +158,15 @@ export class MoniRipple extends MoniElement {
50
158
  super.disconnectedCallback();
51
159
  }
52
160
 
161
+ /**
162
+ * Handles pointer-down events on the parent element.
163
+ *
164
+ * Computes the ripple origin as a percentage of the parent's bounding rect,
165
+ * cancels any in-progress ripple, then triggers a new one after one
166
+ * animation frame to guarantee the CSS transition fires from the new position.
167
+ *
168
+ * @param e - The `PointerEvent` from the parent's `pointerdown` listener.
169
+ */
53
170
  private _onPointerDown = (e: PointerEvent) => {
54
171
  if (!this._target) return;
55
172
  const rect = this._target.getBoundingClientRect();
@@ -1,26 +1,47 @@
1
+ /**
2
+ * @file components/moni-segmented-button.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { html, css } from 'lit';
2
9
  import { customElement, property, queryAssignedElements } from 'lit/decorators.js';
3
10
  import { MoniElement, sharedStyles } from './_base/index.js';
4
11
  import { MoniButtonSegment } from './moni-button-segment.js';
5
12
 
6
13
  /**
14
+ * Material Design 3 Segmented Button component (Legacy).
15
+ *
7
16
  * A form-associated group of selectable segmented buttons.
8
17
  *
9
- * @deprecated since v0.3.0 `moni-segmented-button` is **no longer
10
- * recommended** by Material Design 3 Expressive. Use
11
- * `moni-button-group[variant="connected"]` instead, which has the same
12
- * functionality with an updated visual design. See
13
- * `m3-docs/components/segmented-buttons/overview.md` § M3 Expressive update.
18
+ * **Deprecation Notice:** The M3 spec (`m3-docs/components/segmented-buttons/overview.md`)
19
+ * has updated the segmented button pattern. The bespoke segments have been
20
+ * replaced with standard `<moni-button>` elements grouped inside a
21
+ * `<moni-button-group variant="connected">`.
14
22
  *
15
23
  * This component continues to work for backward compatibility but will be
16
24
  * removed in v1.0. A deprecation warning is logged to the console when the
17
25
  * element is connected to the DOM.
18
26
  *
19
- * Attributes:
20
- * - name: Name of the control in forms
21
- * - multi: Whether multiple options can be selected
22
- * - hide-check: Hides checkmarks on all child segments
23
- * - gap: Custom gap space (e.g. "8px" or "1rem")
27
+ * @deprecated Use `<moni-button-group variant="connected">` instead.
28
+ *
29
+ * @example
30
+ * ```html
31
+ * <!-- Legacy usage (not recommended) -->
32
+ * <moni-segmented-button name="view" multi>
33
+ * <moni-button-segment value="day">Day</moni-button-segment>
34
+ * <moni-button-segment value="week">Week</moni-button-segment>
35
+ * </moni-segmented-button>
36
+ *
37
+ * <!-- Modern M3 equivalent -->
38
+ * <moni-button-group variant="connected">
39
+ * <moni-button>Day</moni-button>
40
+ * <moni-button>Week</moni-button>
41
+ * </moni-button-group>
42
+ * ```
43
+ *
44
+ * @slot default - `<moni-button-segment>` elements.
24
45
  */
25
46
  @customElement('moni-segmented-button')
26
47
  export class MoniSegmentedButton extends MoniElement {