@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,36 +1,79 @@
1
+ /**
2
+ * @file components/_base/field-styles.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
1
8
  import { css } from 'lit';
2
9
 
3
10
  /**
4
- * Shared visual rules for every field-like input shell.
11
+ * Shared visual rules for all field-like input components.
12
+ *
13
+ * This stylesheet provides the complete CSS foundation for the Moni input
14
+ * field pattern, ported and extended from the BeerCSS field system. It is
15
+ * consumed by: `moni-text-field`, `moni-textarea`, `moni-select`,
16
+ * `moni-color-field`, and `moni-file-field`.
17
+ *
18
+ * **Required DOM structure:**
19
+ * Each consumer must render this exact DOM hierarchy inside its shadow root for
20
+ * all selectors (especially the floating label) to function correctly:
21
+ *
22
+ * ```html
23
+ * <div class="field [label] [fill|border] [small|large|extra] [prefix|suffix|icon] [invalid] [round*]">
24
+ * <i class="leading-icon">...</i> <!-- optional leading icon -->
25
+ * <input | select | textarea> <!-- native form control -->
26
+ * <label>Label text</label> <!-- MUST be immediately after the control -->
27
+ * <i class="trailing-icon">...</i> <!-- optional trailing icon -->
28
+ * <span class="suffix-text">...</span> <!-- optional suffix text -->
29
+ * <slot name="trailing"></slot> <!-- optional trailing slot -->
30
+ * <output>Helper or error text</output> <!-- helper / validation message -->
31
+ * </div>
32
+ * ```
33
+ *
34
+ * **Critical ordering rule:**
35
+ * The `<label>` element MUST be the immediate next sibling of the
36
+ * `<input|select|textarea>`. The CSS adjacent sibling combinator (`+ label`)
37
+ * and the `:focus + label` selector depend on this ordering to animate the
38
+ * floating label lift. Breaking the order will prevent the label from animating.
5
39
  *
6
- * Direct port of `beercss-CDN/elements/fields.css`. Each consumer (text-field,
7
- * textarea, select, color-field, file-field) is expected to render a DOM tree
8
- * of the form:
40
+ * **Modifier classes:**
41
+ * - `.label` — Activates the floating label behavior.
42
+ * - `.fill` — Uses `surface-container-highest` as the input background (filled style).
43
+ * - `.border` — Applies an `outline-variant` border (outlined style).
44
+ * - `.small` / `.large` / `.extra` — Adjusts height and padding.
45
+ * - `.prefix` / `.suffix` — Shifts input padding to make room for icons.
46
+ * - `.invalid` — Applies error color to borders, label, and helper text.
47
+ * - `.round` / `.round-*` — Applies pill-shaped border radius to the field.
48
+ * - `.square` — Removes all border-radius (overrides everything via `!important`).
9
49
  *
10
- * <div class="field label fill|small|large|extra|prefix|icon|suffix|invalid">
11
- * [leading <i class="leading-icon">] optional
12
- * <input|select|textarea> ← input area
13
- * <label> ← immediate next sibling (for label lift)
14
- * [trailing <i class="trailing-icon">] optional
15
- * [suffix text] ← optional
16
- * <slot name="trailing"> ← optional slot
17
- * <output> ← helper text or error
18
- * </div>
50
+ * **Internal CSS custom properties:**
51
+ * | Property | Default | Description |
52
+ * |------------|---------|------------------------------------------|
53
+ * | `--_input` | `3rem` | Height of the input area. |
54
+ * | `--_start` | `1.2rem`| Block-start padding for label alignment. |
55
+ * | `--_middle`| computed| Vertical center of the input (for icons).|
19
56
  *
20
- * The selector order is rigid: input must be followed by label so the
21
- * `+ label` and `:focus + label` selectors in BeerCSS can lift the floating
22
- * label. If a component reorders the DOM, the label may not animate properly.
57
+ * @see {@link sharedStyles} — Token bridge consumed by this stylesheet.
58
+ * @see {@link interactionStyles} — State layer (not used directly in fields).
23
59
  */
24
60
  export const fieldStyles = css`
25
61
  :host {
26
62
  display: block;
63
+ /* Fields are full-width by default; the parent layout controls sizing. */
27
64
  inline-size: 100%;
28
65
  }
29
66
 
67
+ /* ─── Base field container ───────────────────────────────────────────────── */
30
68
  .field {
69
+ /* Internal height token — overridden by size modifiers (.small, .large, .extra). */
31
70
  --_input: 3rem;
71
+ /* Vertical start offset used for textarea padding and label positioning. */
32
72
  --_start: 1.2rem;
73
+ /* Computed vertical center — used to position absolutely-placed icons. */
33
74
  --_middle: calc(var(--_input, 0) / 2);
75
+
76
+ /* Default field shape: bottom border only (BeerCSS / MD3 "filled" style). */
34
77
  border-radius: 0.25rem 0.25rem 0 0;
35
78
  min-block-size: var(--_input);
36
79
  display: flex;
@@ -39,17 +82,22 @@ export const fieldStyles = css`
39
82
  inline-size: 100%;
40
83
  }
41
84
 
42
- /* Square overrides anything (border, round variants) via !important. */
85
+ /* ─── Shape overrides ────────────────────────────────────────────────────── */
86
+
87
+ /* Square: removes all border-radius regardless of other modifiers.
88
+ Uses !important to win specificity over .border and [class*='round']. */
43
89
  .field.square,
44
90
  .field.square.border,
45
91
  .field.square[class*='round'] {
46
92
  border-radius: 0 !important;
47
93
  }
48
-
49
94
  .field.square > :is(input, textarea, select) {
50
95
  border-radius: 0 !important;
51
96
  }
52
97
 
98
+ /* ─── Fill variant ───────────────────────────────────────────────────────── */
99
+ /* Unsets background/color on the container; the background is applied
100
+ directly to the <input> so that the floating label overlaps it correctly. */
53
101
  .field.fill {
54
102
  --_background: var(--surface-container-highest);
55
103
  background-color: unset !important;
@@ -57,9 +105,11 @@ export const fieldStyles = css`
57
105
  }
58
106
  .field.fill > :is(input, select, textarea) {
59
107
  background-color: var(--_background);
108
+ /* z-index: 0 ensures the background renders above the ::before layer. */
60
109
  z-index: 0;
61
110
  }
62
111
 
112
+ /* ─── Size variants ──────────────────────────────────────────────────────── */
63
113
  .field.small {
64
114
  --_input: 2.5rem;
65
115
  --_start: 1rem;
@@ -73,10 +123,14 @@ export const fieldStyles = css`
73
123
  --_start: 1.6rem;
74
124
  }
75
125
 
126
+ /* ─── Border (outlined) variant ─────────────────────────────────────────── */
127
+ /* Adds full border-radius and outline-variant stroke on all four sides. */
76
128
  .field.border {
77
129
  border-radius: 0.25rem;
78
130
  }
79
131
 
132
+ /* ─── Round / pill variants ──────────────────────────────────────────────── */
133
+ /* Applied when class matches the 'round' substring (e.g. .round, .round-sm). */
80
134
  .field[class*='round'].small {
81
135
  border-radius: 1.25rem;
82
136
  }
@@ -90,10 +144,8 @@ export const fieldStyles = css`
90
144
  border-radius: 2rem;
91
145
  }
92
146
 
93
- /* Generic icon baseline (BeerCSS: .field > :is(i, img, svg, progress.circle, a)).
94
- The explicit .leading-icon / .trailing-icon classes below win over
95
- the position-suffix selectors and guarantee correct placement even when
96
- the icon is wrapped in a custom element (e.g. <moni-icon>). */
147
+ /* ─── Icon positioning ───────────────────────────────────────────────────── */
148
+ /* Generic rule: absolutely positions any icon/image/svg inside the field. */
97
149
  .field > :is(i, img, svg) {
98
150
  position: absolute;
99
151
  inset: calc((var(--_input, 0) / 2) - 0.75rem) auto auto auto;
@@ -104,31 +156,37 @@ export const fieldStyles = css`
104
156
  margin: auto 0;
105
157
  pointer-events: none;
106
158
  }
159
+ /* Leading icon: explicit class wins over :first-child heuristic. */
107
160
  .field > :is(i, img, svg):first-child,
108
161
  .field > .leading-icon {
109
162
  inset: calc(var(--_middle, 0) - 0.75rem) auto auto 1rem;
110
163
  }
111
164
 
112
- /* Trailing icon: BeerCSS uses :last-child:not(:first-child) which fails
113
- when an output follows. The class selectors below always win and
114
- guarantee correct positioning on the right edge. */
165
+ /* Trailing icon: BeerCSS uses :last-child:not(:first-child) which fails when
166
+ an <output> follows the icon. The explicit class always wins and places
167
+ the icon on the right edge regardless of sibling count. */
115
168
  .field > :is(i, img, svg):last-child:not(:first-child),
116
169
  .field > .trailing-icon {
117
170
  inset: calc(var(--_middle, 0) - 0.75rem) 1rem auto auto;
171
+ /* Prevent the inline-start override from the generic rule above. */
118
172
  inset-inline-start: auto !important;
119
173
  }
120
174
 
175
+ /* Error state: trailing icons inherit the error color. */
121
176
  .field.invalid > i {
122
177
  color: var(--error);
123
178
  }
124
179
 
125
- /* Input / textarea / select — native form elements get a full reset. */
180
+ /* ─── Native form element reset ──────────────────────────────────────────── */
181
+ /* 'all: unset' strips browser-default styles (appearance, border, font, etc.)
182
+ so the field's visual design is fully controlled by Moni's CSS. */
126
183
  .field > :is(input, textarea, select) {
127
184
  all: unset;
128
185
  position: relative;
129
186
  display: block;
130
187
  box-sizing: border-box;
131
188
  border-radius: inherit;
189
+ /* Default border is transparent; visible only in .border and focus states. */
132
190
  border: 0.0625rem solid transparent;
133
191
  padding: 0 0.9375rem;
134
192
  font-family: inherit;
@@ -137,30 +195,42 @@ export const fieldStyles = css`
137
195
  outline: none;
138
196
  z-index: 1;
139
197
  background: none;
140
- resize: none;
198
+ resize: none; /* Textareas use field-sizing:content instead of manual resize. */
141
199
  text-align: start;
142
200
  cursor: text;
143
201
  color: var(--on-surface);
144
202
  }
145
203
 
204
+ /* Ensure date/time input values align to start (browser quirk on some platforms). */
146
205
  input::-webkit-date-and-time-value {
147
206
  text-align: start;
148
207
  }
208
+
209
+ /* Autofill: preserve text color when the browser applies its autofill highlight.
210
+ -webkit-background-clip + -webkit-text-fill-color override the yellow tint. */
149
211
  :is(input, select, textarea):is(:-webkit-autofill, :autofill) {
150
212
  -webkit-background-clip: text;
151
213
  -webkit-text-fill-color: var(--on-surface);
152
214
  }
153
215
 
216
+ /* On focus, increase border width by 1px — shift padding inward by 1px
217
+ to prevent layout shift from the border width change. */
154
218
  .field > :is(input, textarea, select):focus {
155
219
  border: 0.125rem solid transparent;
156
220
  padding-inline: 0.875rem;
157
221
  }
158
222
 
223
+ /* Textareas without explicit rows grow automatically using field-sizing:content.
224
+ A max-height of 12rem (~8 lines) prevents uncontrolled page growth. */
159
225
  .field > textarea:not([rows]) {
160
226
  field-sizing: content;
161
227
  max-block-size: 12rem;
162
228
  }
163
229
 
230
+ /* ─── Transparent native picker controls ─────────────────────────────────── */
231
+ /* File and color inputs, and date/time picker indicators are hidden so the
232
+ component can render its own UI. The native controls are still active for
233
+ accessibility (click propagates through the transparent overlay). */
164
234
  input[type='file'],
165
235
  input[type='color'],
166
236
  :not(.field) > input:is([type^='date'], [type^='time'], [type='month'], [type='week']),
@@ -177,12 +247,15 @@ export const fieldStyles = css`
177
247
  z-index: 2 !important;
178
248
  }
179
249
 
250
+ /* On fine-pointer (mouse) devices, push the calendar picker indicator behind
251
+ the field content so it doesn't interfere with other clickable elements. */
180
252
  @media (pointer: fine) {
181
253
  .field > input::-webkit-calendar-picker-indicator {
182
254
  z-index: -1 !important;
183
255
  }
184
256
  }
185
257
 
258
+ /* Remove browser-native search field decorations. */
186
259
  input::-webkit-search-decoration,
187
260
  input::-webkit-search-cancel-button,
188
261
  input::-webkit-search-results-button,
@@ -192,10 +265,12 @@ export const fieldStyles = css`
192
265
  display: none;
193
266
  }
194
267
 
268
+ /* Remove the browser spinner on number inputs — use explicit stepper UI instead. */
195
269
  input[type='number'] {
196
270
  appearance: textfield;
197
271
  }
198
272
 
273
+ /* ─── Border variant: field-level border colors ──────────────────────────── */
199
274
  .field.border > :is(input, textarea, select) {
200
275
  border-color: var(--outline);
201
276
  }
@@ -203,6 +278,7 @@ export const fieldStyles = css`
203
278
  border-color: var(--primary);
204
279
  }
205
280
 
281
+ /* Round variants add extra inline padding to clear the curved edges. */
206
282
  .field[class*='round'] > :is(input, textarea, select) {
207
283
  padding-inline: 1.4376rem;
208
284
  }
@@ -210,13 +286,14 @@ export const fieldStyles = css`
210
286
  padding-inline: 1.375rem;
211
287
  }
212
288
 
289
+ /* ─── Icon padding accommodation ─────────────────────────────────────────── */
290
+ /* .prefix / .suffix shift the input's inline padding to make room for icons. */
213
291
  .field.prefix > :is(input, textarea, select) {
214
292
  padding-inline-start: 2.9375rem;
215
293
  }
216
294
  .field.prefix > :is(input, textarea, select):focus {
217
295
  padding-inline-start: 2.875rem;
218
296
  }
219
-
220
297
  .field.suffix > :is(input, textarea, select) {
221
298
  padding-inline-end: 2.9375rem;
222
299
  }
@@ -224,6 +301,8 @@ export const fieldStyles = css`
224
301
  padding-inline-end: 2.875rem;
225
302
  }
226
303
 
304
+ /* ─── Underline (non-border, non-round) bottom border ─────────────────────── */
305
+ /* Default M3 filled field style: only the bottom border is visible. */
227
306
  .field:not(.border, [class*='round']) > :is(input, textarea, select) {
228
307
  border-block-end-color: var(--outline);
229
308
  }
@@ -231,6 +310,7 @@ export const fieldStyles = css`
231
310
  border-block-end-color: var(--primary);
232
311
  }
233
312
 
313
+ /* Round non-bordered fields get a subtle elevation shadow instead of a border. */
234
314
  .field[class*='round']:not(.border, .fill) > :is(input, textarea, select),
235
315
  .field[class*='round']:not(.border) > :is(input, textarea, select):focus {
236
316
  box-shadow: var(--elevate1);
@@ -239,6 +319,7 @@ export const fieldStyles = css`
239
319
  box-shadow: var(--elevate2);
240
320
  }
241
321
 
322
+ /* ─── Invalid / error state borders ─────────────────────────────────────── */
242
323
  .field.invalid:not(.border, [class*='round']) > :is(input, textarea, select),
243
324
  .field.invalid:not(.border, [class*='round']) > :is(input, textarea, select):focus {
244
325
  border-block-end-color: var(--error);
@@ -248,6 +329,9 @@ export const fieldStyles = css`
248
329
  border-color: var(--error);
249
330
  }
250
331
 
332
+ /* ─── Disabled state ─────────────────────────────────────────────────────── */
333
+ /* Reduces opacity on the entire field container when the native control is
334
+ disabled, rather than applying separate rules to each child. */
251
335
  .field:has(> :disabled) {
252
336
  opacity: 0.5;
253
337
  cursor: not-allowed;
@@ -256,6 +340,8 @@ export const fieldStyles = css`
256
340
  cursor: not-allowed;
257
341
  }
258
342
 
343
+ /* ─── Select element ─────────────────────────────────────────────────────── */
344
+ /* Remove browser-native select appearance; the component renders its own dropdown. */
259
345
  .field > select {
260
346
  user-select: none;
261
347
  appearance: none;
@@ -263,17 +349,23 @@ export const fieldStyles = css`
263
349
  background-image: none;
264
350
  }
265
351
 
352
+ /* ─── Block-start padding for label accommodation ────────────────────────── */
353
+ /* Inputs with a floating label need top padding to create space for the
354
+ label when it lifts above the input. Selects always lift their label. */
266
355
  .field > :is(input, select) {
267
356
  padding-block-start: 1rem;
268
357
  }
358
+ /* No-label and border+fill fields: remove the top padding offset. */
269
359
  .field:not(.label) > :is(input, select),
270
360
  .field.border:not(.fill) > :is(input, select) {
271
361
  padding-block-start: 0;
272
362
  }
363
+ /* Textareas use the --_start token to align with the label baseline. */
273
364
  .field > textarea {
274
365
  padding-block-start: var(--_start) !important;
275
366
  }
276
367
  .field > textarea:focus {
368
+ /* 0.01rem compensates for the border width increase on focus. */
277
369
  padding-block-start: calc(var(--_start, 0) - 0.01rem) !important;
278
370
  }
279
371
  .field:not(.label) > textarea,
@@ -285,29 +377,42 @@ export const fieldStyles = css`
285
377
  padding-block-start: calc(var(--_start, 0) - 0.51rem) !important;
286
378
  }
287
379
 
288
- /* Floating label */
380
+ /* ─── Floating label ─────────────────────────────────────────────────────── */
381
+ /* The label starts at full font-size (1rem) vertically centered in the field.
382
+ On focus or when value is present, it scales down to 0.75rem and lifts
383
+ to the top of the field container. */
289
384
  .field.label > label {
290
385
  --_start: 1rem;
291
386
  position: absolute;
292
387
  inset: -0.5rem 0.9375rem 0 var(--_start);
293
388
  display: flex;
389
+ /* Full height + 1rem (for label overhang) centers the label vertically. */
294
390
  block-size: calc(var(--_input, 0) + 1rem);
295
391
  line-height: calc(var(--_input, 0) + 1rem);
296
392
  font-size: 1rem;
297
393
  transition: all 0.2s;
298
394
  gap: 0.25rem;
299
395
  white-space: nowrap;
396
+ /* The label is purely decorative from a layout perspective; it must never
397
+ intercept pointer events meant for the underlying input. */
300
398
  pointer-events: none;
301
399
  color: var(--on-surface-variant);
302
400
  }
303
401
 
402
+ /* Round fields: label aligns with the increased inline padding. */
304
403
  .field.label[class*='round'] > label {
305
404
  inset: -0.5rem 1.9375rem 0 var(--_start);
306
405
  }
307
406
 
308
- /* Label lift selectors. Note the inclusion of .active + label so that
309
- readonly inputs (color-field, file-field) still trigger the float when
310
- the consumer sets class=active on the input. */
407
+ /* ─── Label lift selector group ──────────────────────────────────────────── */
408
+ /* The label lifts (scales down + moves up) in four conditions:
409
+ 1. label.active — the component sets this class directly (readonly inputs).
410
+ 2. :focus + label — when the native control is focused.
411
+ 3. [placeholder]:not(:placeholder-shown) + label — when a value is present.
412
+ 4. select + label — selects always show their label lifted.
413
+ 5. input.active + label — for programmatically activated inputs. */
414
+
415
+ /* Border + prefix + no-fill variant needs a reduced --_start offset. */
311
416
  .field.label.border.prefix:not(.fill)
312
417
  > :is(
313
418
  label.active,
@@ -319,6 +424,7 @@ export const fieldStyles = css`
319
424
  --_start: 1rem;
320
425
  }
321
426
 
427
+ /* Round field label and round border prefix field label override. */
322
428
  .field.label[class*='round'] > label,
323
429
  .field.label.border.prefix[class*='round']:not(.fill)
324
430
  > :is(
@@ -331,10 +437,12 @@ export const fieldStyles = css`
331
437
  --_start: 1.5rem;
332
438
  }
333
439
 
440
+ /* Prefix fields: shift the label's inline-start to clear the leading icon. */
334
441
  .field.label.prefix > label {
335
442
  --_start: 3rem;
336
443
  }
337
444
 
445
+ /* Lifted label: shrinks to 0.75rem and collapses to the top of the field. */
338
446
  .field.label
339
447
  > :is(
340
448
  label.active,
@@ -348,6 +456,7 @@ export const fieldStyles = css`
348
456
  font-size: 0.75rem;
349
457
  }
350
458
 
459
+ /* Border variant: label collapses to 1rem height with a notch cut effect. */
351
460
  .field.label.border:not(.fill)
352
461
  > :is(
353
462
  label.active,
@@ -360,6 +469,9 @@ export const fieldStyles = css`
360
469
  line-height: 1rem;
361
470
  }
362
471
 
472
+ /* ─── Border notch (label gap in the top border) ─────────────────────────── */
473
+ /* The ::after pseudo creates the horizontal line to the right of the lifted
474
+ label, visually cutting a notch into the top border of .field.border. */
363
475
  .field.label.border:not(.fill) > label::after {
364
476
  content: '';
365
477
  display: block;
@@ -371,9 +483,14 @@ export const fieldStyles = css`
371
483
  }
372
484
  .field.label.border:not(.fill) > :focus + label::after,
373
485
  .field.label.border:not(.fill) > input.active + label::after {
486
+ /* On focus, the notch line becomes primary-colored. */
374
487
  border-block-start: 0.125rem solid var(--primary);
375
488
  }
376
489
 
490
+ /* ─── Border notch clipping (clip-path) ──────────────────────────────────── */
491
+ /* When the label is lifted, a clip-path cuts a gap in the top border of the
492
+ input element itself, creating the appearance of the label floating within
493
+ the border's top edge. The clip-path dimensions account for label width. */
377
494
  .field.label.border:not(.fill)
378
495
  > :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
379
496
  .field.label.border:not(.fill) > select,
@@ -391,6 +508,7 @@ export const fieldStyles = css`
391
508
  );
392
509
  }
393
510
 
511
+ /* Prefix variant: clip starts further right to clear the leading icon text. */
394
512
  .field.label.border.prefix:not(.fill)
395
513
  > :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
396
514
  .field.label.border.prefix:not(.fill) > select,
@@ -408,6 +526,7 @@ export const fieldStyles = css`
408
526
  );
409
527
  }
410
528
 
529
+ /* Round and square border fields use a wider notch to clear the curved border. */
411
530
  .field.label.border[class*='round']:not(.fill)
412
531
  > :is(input, textarea):is(:focus, [placeholder]:not(:placeholder-shown), .active),
413
532
  .field.label.border[class*='round']:not(.fill) > select,
@@ -435,18 +554,22 @@ export const fieldStyles = css`
435
554
  clip-path: polygon(-2% -2%, 1.25rem -2%, 1.25rem 0.5rem, calc(100% - 2rem) 0.5rem, calc(100% - 2rem) -2%, 102% -2%, 102% 102%, -2% 102%);
436
555
  }
437
556
 
557
+ /* ─── Label color changes ─────────────────────────────────────────────────── */
558
+ /* On focus: label turns primary-colored to draw attention. */
438
559
  .field.label > :focus + label,
439
560
  .field.label > input.active + label {
440
561
  color: var(--primary);
441
562
  }
442
563
 
564
+ /* On error: label and notch line turn error-colored. */
443
565
  .field.label.invalid > label,
444
566
  .field.label.invalid > label::after {
445
567
  color: var(--error) !important;
446
568
  border-color: var(--error) !important;
447
569
  }
448
570
 
449
- /* Helper / error output */
571
+ /* ─── Helper / error output ──────────────────────────────────────────────── */
572
+ /* The <output> element below the field shows helper text or validation errors. */
450
573
  .field > output {
451
574
  display: inline-block;
452
575
  font-size: 0.75rem;
@@ -456,20 +579,23 @@ export const fieldStyles = css`
456
579
  align-self: start;
457
580
  color: var(--on-surface-variant);
458
581
  }
582
+ /* Error output overrides the neutral helper color. */
459
583
  .field > output.invalid {
460
584
  color: var(--error) !important;
461
585
  }
586
+ /* Round fields: increase horizontal padding to align with the curved edge. */
462
587
  .field[class*='round'] > output {
463
588
  padding: 0.25rem 1.5rem;
464
589
  }
590
+ /* Show only one output at a time: helper OR error, never both. */
465
591
  .field.invalid > output:not(.invalid),
466
592
  .field:not(.invalid) > output.invalid {
467
593
  display: none;
468
594
  }
469
595
 
470
- /* Footer wrapper for textarea (and other multi-line fields) that pairs
471
- a helper text on the left with a character counter on the right.
472
- Per M3 spec, supporting text and character counter share the footer. */
596
+ /* ─── Footer wrapper (textarea & multi-line fields) ───────────────────────── */
597
+ /* Lays out helper text (left) and character counter (right) on the same row,
598
+ matching the M3 spec for supporting-text + character-counter pairs. */
473
599
  .field > .footer {
474
600
  display: flex;
475
601
  align-items: center;
@@ -490,13 +616,16 @@ export const fieldStyles = css`
490
616
  .field > .footer > output.invalid {
491
617
  color: var(--error) !important;
492
618
  }
619
+ /* Character counter — right-aligned, same typographic style as the helper. */
493
620
  .field > .footer > .counter {
494
621
  padding: 0.25rem 1rem;
495
622
  color: var(--on-surface-variant);
496
623
  }
624
+ /* Spacer pushes counter to the right when there is no helper text. */
497
625
  .field > .footer > .spacer {
498
626
  flex: 1;
499
627
  }
628
+ /* Same exclusive show logic as direct <output> elements. */
500
629
  .field.invalid > .footer > output:not(.invalid),
501
630
  .field:not(.invalid) > .footer > output.invalid {
502
631
  display: none;
@@ -504,4 +633,3 @@ export const fieldStyles = css`
504
633
  `;
505
634
 
506
635
  export default fieldStyles;
507
-
@@ -1,3 +1,30 @@
1
+ /**
2
+ * @file components/_base/index.ts
3
+ * @package @moni-labs/moni-ui
4
+ * @license MIT
5
+ * @contributors Moni Labs & Contributors
6
+ */
7
+
8
+ /**
9
+ * @module _base
10
+ *
11
+ * Re-exports the foundational building blocks shared by all Moni Web Components.
12
+ *
13
+ * **Exports:**
14
+ * - {@link MoniElement} — Abstract LitElement base class every component extends.
15
+ * - {@link sharedStyles} — Baseline CSS: box-sizing, token bridge, utility classes.
16
+ * - {@link fieldStyles} — CSS for field-like input components (text-field, select, etc.).
17
+ *
18
+ * `interactionStyles` is intentionally **not** re-exported from this barrel —
19
+ * it should be imported directly by components that need state layers to avoid
20
+ * adding its CSS to components that don't use `.interactive`.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { MoniElement, sharedStyles, fieldStyles } from './_base/index.js';
25
+ * ```
26
+ */
27
+
1
28
  export { MoniElement } from './moni-element.js';
2
29
  export { sharedStyles } from './shared-styles.js';
3
30
  export { fieldStyles } from './field-styles.js';