@mhmo91/schmancy 0.10.14 → 0.10.16

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 (544) hide show
  1. package/custom-elements.json +2554 -3086
  2. package/dist/active-host-BP0zy_Y9.js +63 -0
  3. package/dist/{active-host-CvNYoprt.js.map → active-host-BP0zy_Y9.js.map} +1 -1
  4. package/dist/active-host-jH3iloCR.cjs +1 -0
  5. package/dist/{active-host-CcIa2tmW.cjs.map → active-host-jH3iloCR.cjs.map} +1 -1
  6. package/dist/agent/schmancy.agent.js +2579 -2385
  7. package/dist/agent/schmancy.agent.js.map +1 -1
  8. package/dist/agent/schmancy.manifest.json +971 -1189
  9. package/dist/{animation-CO_Csq84.cjs.map → animation-CCOIW4wJ.cjs.map} +1 -1
  10. package/dist/{animation-BK-8BwY8.js.map → animation-DCznELuT.js.map} +1 -1
  11. package/dist/{area-C_kgZZhN.js → area-ChxsDTu_.js} +2 -2
  12. package/dist/{area-C_kgZZhN.js.map → area-ChxsDTu_.js.map} +1 -1
  13. package/dist/{area-DFPtKzWy.cjs → area-Qt6yUnuA.cjs} +3 -3
  14. package/dist/{area-DFPtKzWy.cjs.map → area-Qt6yUnuA.cjs.map} +1 -1
  15. package/dist/area.cjs +1 -1
  16. package/dist/area.js +2 -2
  17. package/dist/{audio-CluX8Qpq.cjs → audio-D-TZzpXF.cjs} +1 -1
  18. package/dist/{audio-CluX8Qpq.cjs.map → audio-D-TZzpXF.cjs.map} +1 -1
  19. package/dist/{audio-DcXphulJ.js → audio-DS43uoRA.js} +1 -1
  20. package/dist/{audio-DcXphulJ.js.map → audio-DS43uoRA.js.map} +1 -1
  21. package/dist/audio.cjs +1 -1
  22. package/dist/audio.js +2 -2
  23. package/dist/{autocomplete-DWSuwSRS.js → autocomplete-CXvUjMD-.js} +46 -71
  24. package/dist/autocomplete-CXvUjMD-.js.map +1 -0
  25. package/dist/autocomplete-Ck2zbdF9.cjs +115 -0
  26. package/dist/autocomplete-Ck2zbdF9.cjs.map +1 -0
  27. package/dist/autocomplete.cjs +1 -1
  28. package/dist/autocomplete.js +1 -1
  29. package/dist/avatar.cjs +2 -2
  30. package/dist/avatar.cjs.map +1 -1
  31. package/dist/avatar.js +3 -3
  32. package/dist/badge.cjs +1 -1
  33. package/dist/badge.js +1 -1
  34. package/dist/{boat-CZma2ojF.js → boat-Bj0wVcZi.js} +5 -5
  35. package/dist/{boat-CZma2ojF.js.map → boat-Bj0wVcZi.js.map} +1 -1
  36. package/dist/{boat-Dy6cc3hB.cjs → boat-DpFkILFF.cjs} +2 -2
  37. package/dist/{boat-Dy6cc3hB.cjs.map → boat-DpFkILFF.cjs.map} +1 -1
  38. package/dist/boat.cjs +1 -1
  39. package/dist/boat.js +1 -1
  40. package/dist/breadcrumb.cjs +3 -3
  41. package/dist/breadcrumb.cjs.map +1 -1
  42. package/dist/breadcrumb.js +2 -2
  43. package/dist/{busy-DCsqryvq.cjs → busy-CtcnclA3.cjs} +3 -3
  44. package/dist/{busy-DCsqryvq.cjs.map → busy-CtcnclA3.cjs.map} +1 -1
  45. package/dist/{busy-DeV2ByMw.js → busy-CyZSBnZP.js} +2 -2
  46. package/dist/{busy-DeV2ByMw.js.map → busy-CyZSBnZP.js.map} +1 -1
  47. package/dist/busy.cjs +1 -1
  48. package/dist/busy.js +1 -1
  49. package/dist/button.cjs +4 -4
  50. package/dist/button.cjs.map +1 -1
  51. package/dist/button.js +19 -4
  52. package/dist/button.js.map +1 -1
  53. package/dist/{card--GgSX4X5.cjs → card-Cl6jp1yX.cjs} +5 -5
  54. package/dist/{card--GgSX4X5.cjs.map → card-Cl6jp1yX.cjs.map} +1 -1
  55. package/dist/{card-BTTsHzJJ.js → card-nYZCKmOO.js} +3 -3
  56. package/dist/{card-BTTsHzJJ.js.map → card-nYZCKmOO.js.map} +1 -1
  57. package/dist/card.cjs +1 -1
  58. package/dist/card.js +1 -1
  59. package/dist/{checkbox-NNReP9s_.cjs → checkbox-BeNo0ZGt.cjs} +4 -4
  60. package/dist/{checkbox-Cj5j-ppk.js.map → checkbox-BeNo0ZGt.cjs.map} +1 -1
  61. package/dist/{checkbox-Cj5j-ppk.js → checkbox-DiUrZiyc.js} +17 -30
  62. package/dist/checkbox-DiUrZiyc.js.map +1 -0
  63. package/dist/checkbox.cjs +1 -1
  64. package/dist/checkbox.js +1 -1
  65. package/dist/{chips-CP-CbfoZ.js → chips-CfPFXv7Z.js} +5 -5
  66. package/dist/{chips-CP-CbfoZ.js.map → chips-CfPFXv7Z.js.map} +1 -1
  67. package/dist/{chips-iporOXxK.cjs → chips-DK6m-VCM.cjs} +5 -5
  68. package/dist/{chips-iporOXxK.cjs.map → chips-DK6m-VCM.cjs.map} +1 -1
  69. package/dist/chips.cjs +1 -1
  70. package/dist/chips.js +2 -2
  71. package/dist/connectivity.cjs +2 -2
  72. package/dist/connectivity.cjs.map +1 -1
  73. package/dist/connectivity.js +3 -3
  74. package/dist/content-drawer.cjs +1 -1
  75. package/dist/content-drawer.js +1 -1
  76. package/dist/{context-DJTJnSK4.js.map → context-6oXCZmZN.js.map} +1 -1
  77. package/dist/{context-BpCETidA.cjs.map → context-CRZeiCqq.cjs.map} +1 -1
  78. package/dist/{cursor-glow-Bulq-38P.cjs → cursor-glow-C8LgCxpI.cjs} +1 -1
  79. package/dist/{cursor-glow-Bulq-38P.cjs.map → cursor-glow-C8LgCxpI.cjs.map} +1 -1
  80. package/dist/{cursor-glow-Ah7VXSj7.js → cursor-glow-Cs2XLDB9.js} +1 -1
  81. package/dist/{cursor-glow-Ah7VXSj7.js.map → cursor-glow-Cs2XLDB9.js.map} +1 -1
  82. package/dist/date-range-DA6anfcF.cjs +131 -0
  83. package/dist/date-range-DA6anfcF.cjs.map +1 -0
  84. package/dist/{date-range-CgNujP8r.js → date-range-DjlF2u7o.js} +124 -89
  85. package/dist/date-range-DjlF2u7o.js.map +1 -0
  86. package/dist/date-range-inline-BfYK795W.cjs +43 -0
  87. package/dist/{date-range-inline-D4IjOOO0.cjs.map → date-range-inline-BfYK795W.cjs.map} +1 -1
  88. package/dist/{date-range-inline-C2PXX_GY.js → date-range-inline-n7y_H6PJ.js} +2 -2
  89. package/dist/{date-range-inline-C2PXX_GY.js.map → date-range-inline-n7y_H6PJ.js.map} +1 -1
  90. package/dist/date-range-inline.cjs +1 -1
  91. package/dist/date-range-inline.js +1 -1
  92. package/dist/date-range.cjs +1 -1
  93. package/dist/date-range.js +1 -1
  94. package/dist/delay.cjs +2 -2
  95. package/dist/delay.cjs.map +1 -1
  96. package/dist/delay.js +3 -3
  97. package/dist/{details-DT2b3xOn.cjs → details-BdAVsLl-.cjs} +2 -2
  98. package/dist/{details-DT2b3xOn.cjs.map → details-BdAVsLl-.cjs.map} +1 -1
  99. package/dist/{details-VjaNwtfd.js → details-CS_ToAOj.js} +6 -6
  100. package/dist/{details-VjaNwtfd.js.map → details-CS_ToAOj.js.map} +1 -1
  101. package/dist/details.cjs +1 -1
  102. package/dist/details.js +1 -1
  103. package/dist/directives.cjs +1 -1
  104. package/dist/directives.js +5 -5
  105. package/dist/{divider-BMO8pzEO.js → divider-COLK0RbT.js} +2 -2
  106. package/dist/{divider-BMO8pzEO.js.map → divider-COLK0RbT.js.map} +1 -1
  107. package/dist/{divider-BW33TZ-X.cjs → divider-CvWAnvdO.cjs} +2 -2
  108. package/dist/{divider-BW33TZ-X.cjs.map → divider-CvWAnvdO.cjs.map} +1 -1
  109. package/dist/divider.cjs +1 -1
  110. package/dist/divider.js +1 -1
  111. package/dist/dropdown.cjs +3 -3
  112. package/dist/dropdown.cjs.map +1 -1
  113. package/dist/dropdown.js +2 -2
  114. package/dist/{expand-DbELKKOt.js → expand-D9LzmpoV.js} +5 -5
  115. package/dist/{expand-DbELKKOt.js.map → expand-D9LzmpoV.js.map} +1 -1
  116. package/dist/{expand-_f5EUKWB.cjs → expand-r2sATPUJ.cjs} +3 -3
  117. package/dist/{expand-_f5EUKWB.cjs.map → expand-r2sATPUJ.cjs.map} +1 -1
  118. package/dist/expand.cjs +1 -1
  119. package/dist/expand.js +1 -1
  120. package/dist/float-2nHYuBx-.cjs +1 -0
  121. package/dist/{float-CKmd-0-t.cjs.map → float-2nHYuBx-.cjs.map} +1 -1
  122. package/dist/{float-B6RBb2dN.js → float-BWy39CXr.js} +2 -2
  123. package/dist/{float-B6RBb2dN.js.map → float-BWy39CXr.js.map} +1 -1
  124. package/dist/float.cjs +1 -1
  125. package/dist/float.js +1 -1
  126. package/dist/form-DhjedCWm.js +258 -0
  127. package/dist/form-DhjedCWm.js.map +1 -0
  128. package/dist/form-g5c70rac.cjs +42 -0
  129. package/dist/form-g5c70rac.cjs.map +1 -0
  130. package/dist/form.cjs +1 -1
  131. package/dist/form.js +2 -2
  132. package/dist/handover/agent-runtime-followups.md +1 -1
  133. package/dist/handover/agent-runtime-v1.md +3 -3
  134. package/dist/{hashContent-Bobsobip.cjs.map → hashContent-Ck6laKlk.cjs.map} +1 -1
  135. package/dist/{hashContent-BU6jl5ih.js.map → hashContent-dJrI-9sc.js.map} +1 -1
  136. package/dist/{icons-r-S17M8U.cjs → icons-1HIENBco.cjs} +2 -2
  137. package/dist/{icons-r-S17M8U.cjs.map → icons-1HIENBco.cjs.map} +1 -1
  138. package/dist/{icons-CoDo95Cu.js → icons-3y0kr1aB.js} +3 -3
  139. package/dist/{icons-CoDo95Cu.js.map → icons-3y0kr1aB.js.map} +1 -1
  140. package/dist/icons.cjs +1 -1
  141. package/dist/icons.js +1 -1
  142. package/dist/{iframe-P9c_qg1-.cjs → iframe-CjqYuZG5.cjs} +2 -2
  143. package/dist/{iframe-P9c_qg1-.cjs.map → iframe-CjqYuZG5.cjs.map} +1 -1
  144. package/dist/{iframe-k4oI-TIj.js → iframe-Z5gTK-gd.js} +2 -2
  145. package/dist/{iframe-k4oI-TIj.js.map → iframe-Z5gTK-gd.js.map} +1 -1
  146. package/dist/iframe.cjs +1 -1
  147. package/dist/iframe.js +1 -1
  148. package/dist/index.cjs +1 -1
  149. package/dist/index.js +60 -60
  150. package/dist/{input-D95GjINh.js → input-B-fw6f_r.js} +103 -104
  151. package/dist/input-B-fw6f_r.js.map +1 -0
  152. package/dist/input-BtcIhu0Q.cjs +52 -0
  153. package/dist/input-BtcIhu0Q.cjs.map +1 -0
  154. package/dist/{input-chip-DpC_XEKN.js → input-chip-CtQ0pH5b.js} +2 -2
  155. package/dist/{input-chip-DpC_XEKN.js.map → input-chip-CtQ0pH5b.js.map} +1 -1
  156. package/dist/{input-chip-D0ZXqTt5.cjs → input-chip-DZktYohr.cjs} +2 -2
  157. package/dist/{input-chip-D0ZXqTt5.cjs.map → input-chip-DZktYohr.cjs.map} +1 -1
  158. package/dist/input.cjs +1 -1
  159. package/dist/input.js +1 -1
  160. package/dist/json.cjs +2 -2
  161. package/dist/json.cjs.map +1 -1
  162. package/dist/json.js +3 -3
  163. package/dist/kbd.cjs +2 -2
  164. package/dist/kbd.cjs.map +1 -1
  165. package/dist/kbd.js +2 -2
  166. package/dist/{layout-CXPNsUIo.js → layout-BH28sKGc.js} +1 -1
  167. package/dist/{layout-CXPNsUIo.js.map → layout-BH28sKGc.js.map} +1 -1
  168. package/dist/{layout-Zhe7wSZ_.cjs → layout-Delq-QvR.cjs} +1 -1
  169. package/dist/{layout-Zhe7wSZ_.cjs.map → layout-Delq-QvR.cjs.map} +1 -1
  170. package/dist/layout.cjs +1 -1
  171. package/dist/layout.js +1 -1
  172. package/dist/{lazy-Dq9mRRjT.cjs.map → lazy-CayEFyC3.cjs.map} +1 -1
  173. package/dist/{lazy-B0ia54tT.js.map → lazy-D-bO2r4m.js.map} +1 -1
  174. package/dist/{lightbox-C-yHeoK0.cjs → lightbox-BHTZOn8K.cjs} +3 -3
  175. package/dist/{lightbox-C-yHeoK0.cjs.map → lightbox-BHTZOn8K.cjs.map} +1 -1
  176. package/dist/{lightbox-CovQtmyn.js → lightbox-BL3LWp-P.js} +9 -9
  177. package/dist/{lightbox-CovQtmyn.js.map → lightbox-BL3LWp-P.js.map} +1 -1
  178. package/dist/lightbox.cjs +1 -1
  179. package/dist/lightbox.js +1 -1
  180. package/dist/{list-CAijuky4.cjs → list-CHYa5VGY.cjs} +3 -3
  181. package/dist/{list-CAijuky4.cjs.map → list-CHYa5VGY.cjs.map} +1 -1
  182. package/dist/{list-C1pR9vhu.js → list-DLJL1JQj.js} +2 -2
  183. package/dist/{list-C1pR9vhu.js.map → list-DLJL1JQj.js.map} +1 -1
  184. package/dist/list.cjs +1 -1
  185. package/dist/list.js +1 -1
  186. package/dist/{magnetic-BJgB1dVi.cjs → magnetic-Bgh7aHHI.cjs} +1 -1
  187. package/dist/{magnetic-BJgB1dVi.cjs.map → magnetic-Bgh7aHHI.cjs.map} +1 -1
  188. package/dist/{magnetic-YwCNvtbB.js → magnetic-DxvoEz8_.js} +2 -2
  189. package/dist/{magnetic-YwCNvtbB.js.map → magnetic-DxvoEz8_.js.map} +1 -1
  190. package/dist/{menu-B59vZv9n.js → menu-BNq93w6X.js} +3 -3
  191. package/dist/{menu-B59vZv9n.js.map → menu-BNq93w6X.js.map} +1 -1
  192. package/dist/{menu-BaHO3Cip.cjs → menu-DAikvkeV.cjs} +3 -3
  193. package/dist/{menu-BaHO3Cip.cjs.map → menu-DAikvkeV.cjs.map} +1 -1
  194. package/dist/menu.cjs +1 -1
  195. package/dist/menu.js +1 -1
  196. package/dist/mixins-BOOu6q2n.cjs +298 -0
  197. package/dist/mixins-BOOu6q2n.cjs.map +1 -0
  198. package/dist/mixins-BWb9_e1s.js +680 -0
  199. package/dist/mixins-BWb9_e1s.js.map +1 -0
  200. package/dist/mixins.cjs +1 -1
  201. package/dist/mixins.js +2 -2
  202. package/dist/nav-drawer.cjs +1 -1
  203. package/dist/nav-drawer.js +1 -1
  204. package/dist/navigation-bar.cjs +1 -1
  205. package/dist/navigation-bar.js +1 -1
  206. package/dist/navigation-rail.cjs +3 -3
  207. package/dist/navigation-rail.cjs.map +1 -1
  208. package/dist/navigation-rail.js +2 -2
  209. package/dist/{notification-BeLoVa47.js → notification-CUmb9c3Y.js} +4 -4
  210. package/dist/{notification-BeLoVa47.js.map → notification-CUmb9c3Y.js.map} +1 -1
  211. package/dist/notification-Dy2azMyt.cjs +23 -0
  212. package/dist/{notification-BC9nG8Sr.cjs.map → notification-Dy2azMyt.cjs.map} +1 -1
  213. package/dist/notification.cjs +1 -1
  214. package/dist/notification.js +1 -1
  215. package/dist/{option-BWF4GBp-.cjs → option-CDgIKifG.cjs} +2 -2
  216. package/dist/{option-BWF4GBp-.cjs.map → option-CDgIKifG.cjs.map} +1 -1
  217. package/dist/{option-UvlSAcC4.js → option-DFvQ551b.js} +2 -2
  218. package/dist/{option-UvlSAcC4.js.map → option-DFvQ551b.js.map} +1 -1
  219. package/dist/option.cjs +1 -1
  220. package/dist/option.js +1 -1
  221. package/dist/{overlay-stack-DCDS17uj.js.map → overlay-stack-BR4iYivO.js.map} +1 -1
  222. package/dist/{overlay-stack-DPIe_aYv.cjs.map → overlay-stack-Dk0xETTy.cjs.map} +1 -1
  223. package/dist/overlay.cjs +2 -2
  224. package/dist/overlay.cjs.map +1 -1
  225. package/dist/{overlay.confirm-body-URtE1gI3.cjs → overlay.confirm-body-BkhNvr0c.cjs} +2 -2
  226. package/dist/{overlay.confirm-body-URtE1gI3.cjs.map → overlay.confirm-body-BkhNvr0c.cjs.map} +1 -1
  227. package/dist/{overlay.confirm-body-9W0B5QGv.js → overlay.confirm-body-uFp-0Zfh.js} +2 -2
  228. package/dist/{overlay.confirm-body-9W0B5QGv.js.map → overlay.confirm-body-uFp-0Zfh.js.map} +1 -1
  229. package/dist/overlay.js +8 -8
  230. package/dist/{overlay.service-DnZTcKyJ.cjs → overlay.service-1YWfUD2S.cjs} +1 -1
  231. package/dist/{overlay.service-DnZTcKyJ.cjs.map → overlay.service-1YWfUD2S.cjs.map} +1 -1
  232. package/dist/{overlay.service-CVqs2Gu1.js → overlay.service-BcF12kGb.js} +2 -2
  233. package/dist/{overlay.service-CVqs2Gu1.js.map → overlay.service-BcF12kGb.js.map} +1 -1
  234. package/dist/page.cjs +2 -2
  235. package/dist/page.cjs.map +1 -1
  236. package/dist/page.js +5 -5
  237. package/dist/{progress-CwzwY8Oe.cjs → progress-C02sWkmE.cjs} +2 -2
  238. package/dist/{progress-CwzwY8Oe.cjs.map → progress-C02sWkmE.cjs.map} +1 -1
  239. package/dist/{progress-C29Uw-WJ.js → progress-bLbGRuQ1.js} +2 -2
  240. package/dist/{progress-C29Uw-WJ.js.map → progress-bLbGRuQ1.js.map} +1 -1
  241. package/dist/progress.cjs +1 -1
  242. package/dist/progress.js +1 -1
  243. package/dist/radio-group-BA-jRct5.cjs +40 -0
  244. package/dist/radio-group-BA-jRct5.cjs.map +1 -0
  245. package/dist/{radio-group-CW8airhZ.js → radio-group-DA4eIGCj.js} +4 -4
  246. package/dist/radio-group-DA4eIGCj.js.map +1 -0
  247. package/dist/radio-group.cjs +1 -1
  248. package/dist/radio-group.js +1 -1
  249. package/dist/range.cjs +6 -4
  250. package/dist/range.cjs.map +1 -1
  251. package/dist/range.js +19 -15
  252. package/dist/range.js.map +1 -1
  253. package/dist/{reduced-motion-D-L12p7G.js.map → reduced-motion-D7LqTUMn.js.map} +1 -1
  254. package/dist/{reduced-motion-Ds-HjMzn.cjs.map → reduced-motion-Dzfp_w5x.cjs.map} +1 -1
  255. package/dist/{rxjs-utils-CVeJQ9KG.js.map → rxjs-utils-D9U4MW0Q.js.map} +1 -1
  256. package/dist/{rxjs-utils-DCUHg_Ml.cjs.map → rxjs-utils-kWPShgKu.cjs.map} +1 -1
  257. package/dist/rxjs-utils.cjs +1 -1
  258. package/dist/rxjs-utils.js +1 -1
  259. package/dist/{scroll-BotoGcMU.js → scroll-CG5up5oy.js} +2 -2
  260. package/dist/{scroll-BotoGcMU.js.map → scroll-CG5up5oy.js.map} +1 -1
  261. package/dist/{scroll-CmhmUebp.cjs → scroll-D8vBF_gY.cjs} +2 -2
  262. package/dist/{scroll-CmhmUebp.cjs.map → scroll-D8vBF_gY.cjs.map} +1 -1
  263. package/dist/{search-BLCRsxIC.cjs.map → search-DPKoC-dT.cjs.map} +1 -1
  264. package/dist/{search-BTz7-Rev.js.map → search-MvIBA93K.js.map} +1 -1
  265. package/dist/{select-Dbn-CImU.js → select-BrK1BJoU.js} +52 -73
  266. package/dist/select-BrK1BJoU.js.map +1 -0
  267. package/dist/select-Dh2j7Qc-.cjs +56 -0
  268. package/dist/select-Dh2j7Qc-.cjs.map +1 -0
  269. package/dist/select.cjs +1 -1
  270. package/dist/select.js +1 -1
  271. package/dist/skeleton.cjs +2 -2
  272. package/dist/skeleton.cjs.map +1 -1
  273. package/dist/skeleton.js +2 -2
  274. package/dist/skills/autocomplete.md +16 -3
  275. package/dist/skills/button.md +19 -0
  276. package/dist/skills/checkbox.md +19 -0
  277. package/dist/skills/date-range.md +19 -0
  278. package/dist/skills/form-ux-rules.md +55 -0
  279. package/dist/skills/form.md +121 -25
  280. package/dist/skills/input.md +19 -4
  281. package/dist/skills/range.md +15 -1
  282. package/dist/skills/schmancy/autocomplete.md +16 -3
  283. package/dist/skills/schmancy/button.md +19 -0
  284. package/dist/skills/schmancy/checkbox.md +19 -0
  285. package/dist/skills/schmancy/date-range.md +19 -0
  286. package/dist/skills/schmancy/form-ux-rules.md +55 -0
  287. package/dist/skills/schmancy/form.md +121 -25
  288. package/dist/skills/schmancy/input.md +19 -4
  289. package/dist/skills/schmancy/range.md +15 -1
  290. package/dist/skills/schmancy/select.md +13 -1
  291. package/dist/skills/schmancy/state.md +5 -0
  292. package/dist/skills/schmancy/switch.md +21 -2
  293. package/dist/skills/schmancy/textarea.md +13 -0
  294. package/dist/skills/select.md +13 -1
  295. package/dist/skills/state.md +5 -0
  296. package/dist/skills/switch.md +21 -2
  297. package/dist/skills/textarea.md +13 -0
  298. package/dist/slider.cjs +3 -3
  299. package/dist/slider.cjs.map +1 -1
  300. package/dist/slider.js +2 -2
  301. package/dist/{sound.service-kKfsN0m-.js → sound.service-BIN2W7Rv.js} +1 -1
  302. package/dist/{sound.service-kKfsN0m-.js.map → sound.service-BIN2W7Rv.js.map} +1 -1
  303. package/dist/{sound.service-BGs6m0Cm.cjs → sound.service-DyY78ukR.cjs} +1 -1
  304. package/dist/{sound.service-BGs6m0Cm.cjs.map → sound.service-DyY78ukR.cjs.map} +1 -1
  305. package/dist/{splash-screen-DtkjCJYo.js → splash-screen-BcjjJSlK.js} +2 -2
  306. package/dist/{splash-screen-DtkjCJYo.js.map → splash-screen-BcjjJSlK.js.map} +1 -1
  307. package/dist/{splash-screen-DlQUv-kV.cjs → splash-screen-Kr1sPtME.cjs} +2 -2
  308. package/dist/{splash-screen-DlQUv-kV.cjs.map → splash-screen-Kr1sPtME.cjs.map} +1 -1
  309. package/dist/splash-screen.cjs +1 -1
  310. package/dist/splash-screen.js +1 -1
  311. package/dist/{src-DEUjlTsX.cjs → src-B2-CU8fu.cjs} +11 -11
  312. package/dist/{src-DEUjlTsX.cjs.map → src-B2-CU8fu.cjs.map} +1 -1
  313. package/dist/{src-D6e0adHi.js → src-DvywUq7l.js} +38 -38
  314. package/dist/{src-D6e0adHi.js.map → src-DvywUq7l.js.map} +1 -1
  315. package/dist/state-avic94Ft.cjs +1 -0
  316. package/dist/{state-DNdCPITt.cjs.map → state-avic94Ft.cjs.map} +1 -1
  317. package/dist/{state-BusMG6sM.js → state-nm8yzMPp.js} +1 -2
  318. package/dist/{state-BusMG6sM.js.map → state-nm8yzMPp.js.map} +1 -1
  319. package/dist/state.cjs +1 -1
  320. package/dist/state.js +2 -2
  321. package/dist/steps.cjs +3 -3
  322. package/dist/steps.cjs.map +1 -1
  323. package/dist/steps.js +2 -2
  324. package/dist/{surface-A82O1kgu.js → surface-BtMMHKol.js} +2 -2
  325. package/dist/{surface-A82O1kgu.js.map → surface-BtMMHKol.js.map} +1 -1
  326. package/dist/surface-CgXeKdGL.cjs +7 -0
  327. package/dist/{surface-BpppoNXN.cjs.map → surface-CgXeKdGL.cjs.map} +1 -1
  328. package/dist/surface.cjs +1 -1
  329. package/dist/surface.js +1 -1
  330. package/dist/switch.cjs +3 -3
  331. package/dist/switch.cjs.map +1 -1
  332. package/dist/switch.js +27 -43
  333. package/dist/switch.js.map +1 -1
  334. package/dist/table.cjs +3 -3
  335. package/dist/table.cjs.map +1 -1
  336. package/dist/table.js +2 -2
  337. package/dist/{tabs-cVHHd1dY.js → tabs-CikPr7by.js} +2 -2
  338. package/dist/{tabs-cVHHd1dY.js.map → tabs-CikPr7by.js.map} +1 -1
  339. package/dist/{tabs-TO3UiBsm.cjs → tabs-CitVls3_.cjs} +2 -2
  340. package/dist/{tabs-TO3UiBsm.cjs.map → tabs-CitVls3_.cjs.map} +1 -1
  341. package/dist/tabs.cjs +1 -1
  342. package/dist/tabs.js +1 -1
  343. package/dist/teleport.cjs +1 -1
  344. package/dist/teleport.js +1 -1
  345. package/dist/textarea-CqV1wvmB.cjs +43 -0
  346. package/dist/textarea-CqV1wvmB.cjs.map +1 -0
  347. package/dist/textarea-DVkwQSis.js +186 -0
  348. package/dist/textarea-DVkwQSis.js.map +1 -0
  349. package/dist/textarea.cjs +1 -1
  350. package/dist/textarea.js +1 -1
  351. package/dist/{theme-CT408FqH.js → theme-BIWS4TOW.js} +9 -9
  352. package/dist/{theme-CT408FqH.js.map → theme-BIWS4TOW.js.map} +1 -1
  353. package/dist/theme-DMgjiKda.cjs +181 -0
  354. package/dist/{theme-CpuF3D3q.cjs.map → theme-DMgjiKda.cjs.map} +1 -1
  355. package/dist/{theme-button-pTb5-Wxx.js → theme-button-DC_shZ_7.js} +2 -2
  356. package/dist/{theme-button-pTb5-Wxx.js.map → theme-button-DC_shZ_7.js.map} +1 -1
  357. package/dist/theme-button-ENKa3TPT.cjs +8 -0
  358. package/dist/{theme-button-B6Xf-EiH.cjs.map → theme-button-ENKa3TPT.cjs.map} +1 -1
  359. package/dist/theme-button.cjs +1 -1
  360. package/dist/theme-button.js +1 -1
  361. package/dist/theme.cjs +1 -1
  362. package/dist/{theme.interface-B9TjbSBF.js.map → theme.interface-C8OHheXg.js.map} +1 -1
  363. package/dist/{theme.interface-BujperTo.cjs.map → theme.interface-CYo4UpWK.cjs.map} +1 -1
  364. package/dist/theme.js +4 -4
  365. package/dist/{theme.service-DIUo1mBP.js → theme.service-BOWIT_5k.js} +1 -1
  366. package/dist/{theme.service-DIUo1mBP.js.map → theme.service-BOWIT_5k.js.map} +1 -1
  367. package/dist/{theme.service-Cfk88qHK.cjs → theme.service-DkdH1t60.cjs} +1 -1
  368. package/dist/{theme.service-Cfk88qHK.cjs.map → theme.service-DkdH1t60.cjs.map} +1 -1
  369. package/dist/tree.cjs +2 -2
  370. package/dist/tree.cjs.map +1 -1
  371. package/dist/tree.js +2 -2
  372. package/dist/typography.cjs +2 -2
  373. package/dist/typography.cjs.map +1 -1
  374. package/dist/typography.js +2 -2
  375. package/dist/{utils-kND2Z9Xg.js → utils-Cj_nRRyx.js} +2 -2
  376. package/dist/{utils-kND2Z9Xg.js.map → utils-Cj_nRRyx.js.map} +1 -1
  377. package/dist/{utils-Dt5PpmaQ.cjs → utils-D2QUu4-g.cjs} +1 -1
  378. package/dist/{utils-Dt5PpmaQ.cjs.map → utils-D2QUu4-g.cjs.map} +1 -1
  379. package/dist/utils.cjs +1 -1
  380. package/dist/utils.js +4 -4
  381. package/dist/visually-hidden.cjs +2 -2
  382. package/dist/visually-hidden.cjs.map +1 -1
  383. package/dist/visually-hidden.js +2 -2
  384. package/dist/{window-CuBcOxbc.js → window-BTecgE_U.js} +7 -7
  385. package/dist/{window-CuBcOxbc.js.map → window-BTecgE_U.js.map} +1 -1
  386. package/dist/{window-CSKvv4Ts.cjs → window-DGydMS0g.cjs} +2 -2
  387. package/dist/{window-CSKvv4Ts.cjs.map → window-DGydMS0g.cjs.map} +1 -1
  388. package/dist/window.cjs +1 -1
  389. package/dist/window.js +1 -1
  390. package/package.json +1 -1
  391. package/skills/schmancy/autocomplete.md +16 -3
  392. package/skills/schmancy/button.md +19 -0
  393. package/skills/schmancy/checkbox.md +19 -0
  394. package/skills/schmancy/date-range.md +19 -0
  395. package/skills/schmancy/form-ux-rules.md +55 -0
  396. package/skills/schmancy/form.md +121 -25
  397. package/skills/schmancy/input.md +19 -4
  398. package/skills/schmancy/range.md +15 -1
  399. package/skills/schmancy/select.md +13 -1
  400. package/skills/schmancy/state.md +5 -0
  401. package/skills/schmancy/switch.md +21 -2
  402. package/skills/schmancy/textarea.md +13 -0
  403. package/src/button/button.test.ts +122 -0
  404. package/src/button/button.ts +36 -0
  405. package/src/{autocomplete → form/fields/autocomplete}/autocomplete.ts +48 -75
  406. package/src/{checkbox → form/fields/checkbox}/checkbox.test.ts +1 -1
  407. package/src/form/fields/checkbox/checkbox.ts +126 -0
  408. package/src/form/fields/date-range/date-range.test.ts +102 -0
  409. package/src/{date-range → form/fields/date-range}/date-range.ts +90 -7
  410. package/src/form/fields/input/input.test.ts +201 -0
  411. package/src/{input → form/fields/input}/input.ts +153 -238
  412. package/src/{radio-group → form/fields/radio-group}/radio-button.ts +1 -1
  413. package/src/{radio-group → form/fields/radio-group}/radio-group.ts +1 -1
  414. package/src/form/fields/range/range.test.ts +90 -0
  415. package/src/{range → form/fields/range}/range.ts +34 -13
  416. package/src/{select → form/fields/select}/select.ts +77 -108
  417. package/src/{switch → form/fields/switch}/switch.test.ts +1 -1
  418. package/src/{switch → form/fields/switch}/switch.ts +71 -51
  419. package/src/form/fields/textarea/textarea.test.ts +54 -0
  420. package/src/{textarea → form/fields/textarea}/textarea.ts +33 -72
  421. package/src/form/form-state.ts +31 -0
  422. package/src/form/form-summary.test.ts +105 -0
  423. package/src/form/form-summary.ts +171 -0
  424. package/src/form/form.test.ts +218 -35
  425. package/src/form/form.ts +330 -99
  426. package/src/form/index.ts +2 -0
  427. package/src/index.ts +9 -9
  428. package/types/mixins/formField.mixin.d.ts +90 -0
  429. package/types/src/button/button.d.ts +9 -0
  430. package/types/src/button/button.test.d.ts +3 -0
  431. package/types/src/{autocomplete → form/fields/autocomplete}/autocomplete.d.ts +6 -15
  432. package/types/src/form/fields/checkbox/checkbox.d.ts +47 -0
  433. package/types/src/{date-range → form/fields/date-range}/date-range.d.ts +22 -4
  434. package/types/src/form/fields/date-range/date-range.test.d.ts +1 -0
  435. package/types/src/{input → form/fields/input}/input.d.ts +20 -45
  436. package/types/src/form/fields/input/input.test.d.ts +1 -0
  437. package/types/src/{radio-group → form/fields/radio-group}/radio-button.d.ts +1 -1
  438. package/types/src/{radio-group → form/fields/radio-group}/radio-group.d.ts +1 -1
  439. package/types/src/form/fields/range/range.d.ts +28 -0
  440. package/types/src/form/fields/range/range.test.d.ts +1 -0
  441. package/types/src/{select → form/fields/select}/select.d.ts +23 -24
  442. package/types/src/form/fields/switch/switch.d.ts +57 -0
  443. package/types/src/{textarea → form/fields/textarea}/textarea.d.ts +6 -39
  444. package/types/src/form/fields/textarea/textarea.test.d.ts +1 -0
  445. package/types/src/form/form-state.d.ts +22 -0
  446. package/types/src/form/form-summary.d.ts +42 -0
  447. package/types/src/form/form-summary.test.d.ts +4 -0
  448. package/types/src/form/form.d.ts +79 -34
  449. package/types/src/form/form.test.d.ts +2 -2
  450. package/types/src/form/index.d.ts +2 -0
  451. package/types/src/index.d.ts +9 -9
  452. package/dist/active-host-CcIa2tmW.cjs +0 -1
  453. package/dist/active-host-CvNYoprt.js +0 -57
  454. package/dist/autocomplete-DWSuwSRS.js.map +0 -1
  455. package/dist/autocomplete-iCJOia-q.cjs +0 -115
  456. package/dist/autocomplete-iCJOia-q.cjs.map +0 -1
  457. package/dist/checkbox-NNReP9s_.cjs.map +0 -1
  458. package/dist/date-range-CaOxwZDq.cjs +0 -131
  459. package/dist/date-range-CaOxwZDq.cjs.map +0 -1
  460. package/dist/date-range-CgNujP8r.js.map +0 -1
  461. package/dist/date-range-inline-D4IjOOO0.cjs +0 -43
  462. package/dist/decorate-23nYs4Le.js +0 -7
  463. package/dist/decorate-DpFmy0nm.cjs +0 -1
  464. package/dist/float-CKmd-0-t.cjs +0 -1
  465. package/dist/form-CFvwnfuJ.js +0 -68
  466. package/dist/form-CFvwnfuJ.js.map +0 -1
  467. package/dist/form-Ceijw1aA.cjs +0 -1
  468. package/dist/form-Ceijw1aA.cjs.map +0 -1
  469. package/dist/input-D95GjINh.js.map +0 -1
  470. package/dist/input-D9s4jDAb.cjs +0 -51
  471. package/dist/input-D9s4jDAb.cjs.map +0 -1
  472. package/dist/mixins-BV0w2yIE.js +0 -627
  473. package/dist/mixins-BV0w2yIE.js.map +0 -1
  474. package/dist/mixins-DvAYa-F7.cjs +0 -298
  475. package/dist/mixins-DvAYa-F7.cjs.map +0 -1
  476. package/dist/notification-BC9nG8Sr.cjs +0 -23
  477. package/dist/radio-group-ByMD6Lsj.cjs +0 -40
  478. package/dist/radio-group-ByMD6Lsj.cjs.map +0 -1
  479. package/dist/radio-group-CW8airhZ.js.map +0 -1
  480. package/dist/select-BdBThja4.cjs +0 -56
  481. package/dist/select-BdBThja4.cjs.map +0 -1
  482. package/dist/select-Dbn-CImU.js.map +0 -1
  483. package/dist/state-DNdCPITt.cjs +0 -1
  484. package/dist/surface-BpppoNXN.cjs +0 -7
  485. package/dist/textarea-B9dy-yec.js +0 -211
  486. package/dist/textarea-B9dy-yec.js.map +0 -1
  487. package/dist/textarea-DFY0Flgv.cjs +0 -39
  488. package/dist/textarea-DFY0Flgv.cjs.map +0 -1
  489. package/dist/theme-CpuF3D3q.cjs +0 -181
  490. package/dist/theme-button-B6Xf-EiH.cjs +0 -8
  491. package/src/checkbox/checkbox.ts +0 -162
  492. package/types/src/checkbox/checkbox.d.ts +0 -71
  493. package/types/src/range/range.d.ts +0 -25
  494. package/types/src/switch/switch.d.ts +0 -53
  495. /package/dist/{animation-CO_Csq84.cjs → animation-CCOIW4wJ.cjs} +0 -0
  496. /package/dist/{animation-BK-8BwY8.js → animation-DCznELuT.js} +0 -0
  497. /package/dist/{context-DJTJnSK4.js → context-6oXCZmZN.js} +0 -0
  498. /package/dist/{context-BpCETidA.cjs → context-CRZeiCqq.cjs} +0 -0
  499. /package/dist/{hashContent-Bobsobip.cjs → hashContent-Ck6laKlk.cjs} +0 -0
  500. /package/dist/{hashContent-BU6jl5ih.js → hashContent-dJrI-9sc.js} +0 -0
  501. /package/dist/{lazy-Dq9mRRjT.cjs → lazy-CayEFyC3.cjs} +0 -0
  502. /package/dist/{lazy-B0ia54tT.js → lazy-D-bO2r4m.js} +0 -0
  503. /package/dist/{overlay-stack-DCDS17uj.js → overlay-stack-BR4iYivO.js} +0 -0
  504. /package/dist/{overlay-stack-DPIe_aYv.cjs → overlay-stack-Dk0xETTy.cjs} +0 -0
  505. /package/dist/{reduced-motion-D-L12p7G.js → reduced-motion-D7LqTUMn.js} +0 -0
  506. /package/dist/{reduced-motion-Ds-HjMzn.cjs → reduced-motion-Dzfp_w5x.cjs} +0 -0
  507. /package/dist/{rxjs-utils-CVeJQ9KG.js → rxjs-utils-D9U4MW0Q.js} +0 -0
  508. /package/dist/{rxjs-utils-DCUHg_Ml.cjs → rxjs-utils-kWPShgKu.cjs} +0 -0
  509. /package/dist/{search-BLCRsxIC.cjs → search-DPKoC-dT.cjs} +0 -0
  510. /package/dist/{search-BTz7-Rev.js → search-MvIBA93K.js} +0 -0
  511. /package/dist/{theme.interface-B9TjbSBF.js → theme.interface-C8OHheXg.js} +0 -0
  512. /package/dist/{theme.interface-BujperTo.cjs → theme.interface-CYo4UpWK.cjs} +0 -0
  513. /package/src/{autocomplete → form/fields/autocomplete}/autocomplete.scss +0 -0
  514. /package/src/{autocomplete → form/fields/autocomplete}/index.ts +0 -0
  515. /package/src/{checkbox → form/fields/checkbox}/index.ts +0 -0
  516. /package/src/{date-range → form/fields/date-range}/date-range-dialog.ts +0 -0
  517. /package/src/{date-range → form/fields/date-range}/date-range-helpers.ts +0 -0
  518. /package/src/{date-range → form/fields/date-range}/date-range-presets.ts +0 -0
  519. /package/src/{date-range → form/fields/date-range}/date-utils.ts +0 -0
  520. /package/src/{date-range → form/fields/date-range}/index.ts +0 -0
  521. /package/src/{input → form/fields/input}/index.ts +0 -0
  522. /package/src/{input → form/fields/input}/input.scss +0 -0
  523. /package/src/{radio-group → form/fields/radio-group}/index.ts +0 -0
  524. /package/src/{radio-group → form/fields/radio-group}/radio-group.scss +0 -0
  525. /package/src/{range → form/fields/range}/index.ts +0 -0
  526. /package/src/{select → form/fields/select}/index.ts +0 -0
  527. /package/src/{switch → form/fields/switch}/index.ts +0 -0
  528. /package/src/{textarea → form/fields/textarea}/index.ts +0 -0
  529. /package/src/{textarea → form/fields/textarea}/textarea.scss +0 -0
  530. /package/types/src/{autocomplete → form/fields/autocomplete}/index.d.ts +0 -0
  531. /package/types/src/{checkbox → form/fields/checkbox}/checkbox.test.d.ts +0 -0
  532. /package/types/src/{checkbox → form/fields/checkbox}/index.d.ts +0 -0
  533. /package/types/src/{date-range → form/fields/date-range}/date-range-dialog.d.ts +0 -0
  534. /package/types/src/{date-range → form/fields/date-range}/date-range-helpers.d.ts +0 -0
  535. /package/types/src/{date-range → form/fields/date-range}/date-range-presets.d.ts +0 -0
  536. /package/types/src/{date-range → form/fields/date-range}/date-utils.d.ts +0 -0
  537. /package/types/src/{date-range → form/fields/date-range}/index.d.ts +0 -0
  538. /package/types/src/{input → form/fields/input}/index.d.ts +0 -0
  539. /package/types/src/{radio-group → form/fields/radio-group}/index.d.ts +0 -0
  540. /package/types/src/{range → form/fields/range}/index.d.ts +0 -0
  541. /package/types/src/{select → form/fields/select}/index.d.ts +0 -0
  542. /package/types/src/{switch → form/fields/switch}/index.d.ts +0 -0
  543. /package/types/src/{switch → form/fields/switch}/switch.test.d.ts +0 -0
  544. /package/types/src/{textarea → form/fields/textarea}/index.d.ts +0 -0
@@ -1,18 +1,17 @@
1
- import { SchmancyElement } from '@mixins/index'
2
- import { css, html } from 'lit'
1
+ import { css, html, type PropertyValues } from 'lit'
3
2
  import { customElement, property } from 'lit/decorators.js'
4
3
  import { when } from 'lit/directives/when.js'
4
+ import { SchmancyFormField } from '@mixins/index'
5
5
 
6
6
  export type SchmancyRangeChangeEvent = CustomEvent<{ value: number }>
7
7
 
8
8
  /**
9
9
  * @element schmancy-range
10
10
  * Range input (numeric slider).
11
- * @fires change - Fires on value change with { value: number }
11
+ * @fires change - Fires on value change with `{ value: number }`.
12
12
  */
13
13
  @customElement('schmancy-range')
14
- export class SchmancyRange extends SchmancyElement {
15
- static styles = [css`
14
+ export class SchmancyRange extends SchmancyFormField(css`
16
15
  input[type='range'] {
17
16
  -webkit-appearance: none;
18
17
  appearance: none;
@@ -54,18 +53,37 @@ export class SchmancyRange extends SchmancyElement {
54
53
  background: var(--color-primary, #6750a4);
55
54
  cursor: pointer;
56
55
  }
57
- `];
58
- @property({ type: Number }) min = 0
59
- @property({ type: Number }) max = 1
60
- @property({ type: Number }) step = 0.01
61
- @property({ type: Number }) value = 0
62
- @property({ type: String }) label?: string
63
- @property({ type: Boolean }) disabled = false
56
+ `) {
57
+ // `formAssociated`, `internals`, `name`, `disabled`, `required`, `id`,
58
+ // `label`, `error`, `validationMessage`, `validateOn`, touched/dirty/submitted,
59
+ // `markTouched/markSubmitted`, `formResetCallback`, FIELD_CONNECT_EVENT
60
+ // dispatch all from the mixin.
61
+
62
+ @property({ type: Number }) min: number = 0
63
+ @property({ type: Number }) max: number = 1
64
+ @property({ type: Number }) step: number = 0.01
65
+
66
+ /** Numeric value — narrowed override of the mixin's wide value union. */
67
+ @property({ type: Number, reflect: true })
68
+ override value: number = 0
64
69
 
65
70
  private get progress(): string {
66
71
  return `${((this.value - this.min) / (this.max - this.min)) * 100}%`
67
72
  }
68
73
 
74
+ override willUpdate(changed: PropertyValues): void {
75
+ super.willUpdate(changed)
76
+ if (changed.has('value') || changed.has('name')) {
77
+ this.internals?.setFormValue(String(this.value))
78
+ }
79
+ }
80
+
81
+ /** FormData contributes the value as a string (native range input convention). */
82
+ override toFormEntries(): Array<[string, FormDataEntryValue]> {
83
+ if (!this.name || this.disabled) return []
84
+ return [[this.name, String(this.value)]]
85
+ }
86
+
69
87
  render() {
70
88
  return html`
71
89
  <div class="flex flex-col gap-1 w-full">
@@ -85,10 +103,13 @@ export class SchmancyRange extends SchmancyElement {
85
103
  .step=${String(this.step)}
86
104
  .value=${String(this.value)}
87
105
  ?disabled=${this.disabled}
106
+ aria-label=${this.label || 'Range'}
107
+ aria-valuetext=${String(this.value)}
88
108
  style="--range-progress: ${this.progress}"
89
109
  @input=${(e: Event) => {
90
110
  this.value = Number((e.target as HTMLInputElement).value)
91
- this.dispatchEvent(new CustomEvent('change', { detail: { value: this.value }, bubbles: true, composed: true }))
111
+ this.markTouched()
112
+ this.emitChange({ value: this.value })
92
113
  }}
93
114
  />
94
115
  </div>
@@ -1,5 +1,5 @@
1
1
  import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'
2
- import { SchmancyElement } from '@mixins/index'
2
+ import { SchmancyFormField } from '@mixins/index'
3
3
  import { color } from '@schmancy/directives'
4
4
  import SchmancyInput from '@schmancy/input/input'
5
5
  import SchmancyOption from '@schmancy/option/option'
@@ -27,7 +27,7 @@ export type SchmancySelectChangeEvent = CustomEvent<{
27
27
  * @prop {string[]} values - Selected values (multi-select mode)
28
28
  */
29
29
  @customElement('schmancy-select')
30
- export class SchmancySelect extends SchmancyElement {
30
+ export class SchmancySelect extends SchmancyFormField() {
31
31
  static styles = [css`
32
32
  :host {
33
33
  display: block;
@@ -40,22 +40,22 @@ export class SchmancySelect extends SchmancyElement {
40
40
  }
41
41
  `]
42
42
 
43
- // Form association setup
44
- static formAssociated = true
45
- private internals?: ElementInternals
43
+ // FACE wiring (formAssociated, internals, attachInternals) comes from
44
+ // SchmancyFormField. Same for: name, required, disabled, validationMessage,
45
+ // validateOn, touched/dirty/pristine/submitted, markTouched/markSubmitted,
46
+ // formResetCallback, formDisabledCallback, FIELD_CONNECT_EVENT dispatch.
46
47
 
47
- // API
48
- @property({ type: String }) name: string | undefined
49
- @property({ type: Boolean, reflect: true }) required = false
50
- @property({ type: Boolean, reflect: true }) disabled = false
51
48
  @property({ type: String }) placeholder = ''
49
+
50
+ // Override `value` with the narrowed select-specific type and a custom
51
+ // getter/setter pair backed by reactive subjects.
52
52
  @property({ type: String, reflect: true })
53
- get value() {
53
+ override get value(): string | string[] {
54
54
  return this.multi
55
- ? this._selectedValues$.value // Return array for multi-select
56
- : this._selectedValue$.value // Return string for single-select
55
+ ? this._selectedValues$.value
56
+ : this._selectedValue$.value
57
57
  }
58
- set value(val: string | string[]) {
58
+ override set value(val: string | string[]) {
59
59
  if (this.multi) {
60
60
  const values = Array.isArray(val)
61
61
  ? val
@@ -76,9 +76,7 @@ export class SchmancySelect extends SchmancyElement {
76
76
  }
77
77
 
78
78
  @property({ type: Boolean }) multi = false
79
- @property({ type: String }) label = ''
80
- @property({ type: String }) hint = ''
81
- @property({ type: String }) validateOn: 'always' | 'touched' | 'dirty' | 'submitted' = 'touched'
79
+ // `label` and `hint` come from the mixin.
82
80
  // M3 aligned sizes: 24dp (xxs) → 32dp (xs) → 40dp (sm) → 48dp (md) → 56dp (lg)
83
81
  @property({ type: String }) size: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' = 'md'
84
82
 
@@ -86,10 +84,11 @@ export class SchmancySelect extends SchmancyElement {
86
84
  @state() private isOpen = false
87
85
  @state() private valueLabel = ''
88
86
  @state() private isValid = true
89
- @property({ type: String }) validationMessage = ''
90
87
 
91
- // Store the initial/default value for reset behavior
92
- @state() private defaultValue: string | string[] = ''
88
+ // Store the initial/default value for reset behavior. Distinct from the
89
+ // mixin's `_defaultValue` (which is `string` only); select needs the wider
90
+ // shape so resetForm can restore arrays for multi-select.
91
+ @state() private selectDefaultValue: string | string[] = ''
93
92
 
94
93
  @query('ul') private ul!: HTMLUListElement
95
94
  @query('sch-input') private inputRef!: SchmancyInput
@@ -101,67 +100,35 @@ export class SchmancySelect extends SchmancyElement {
101
100
  private _selectedValue$ = new BehaviorSubject<string>('')
102
101
  private _selectedValues$ = new BehaviorSubject<string[]>([])
103
102
  private _optionSelect$ = new Subject<SchmancyOption>()
103
+
104
+ /**
105
+ * Tracks whether the user has actively interacted (clicked/typed/keyed
106
+ * inside the dropdown). Distinct from the mixin's `touched` (which fires on
107
+ * blur). Used to gate dropdown-positioning side-effects on user-driven
108
+ * actions versus programmatic state changes.
109
+ */
104
110
  @state() _userInteracted = false
105
- @state() private _touched = false
106
- @state() private _dirty = false
107
- @state() private _submitted = false
108
111
 
109
112
  // Reference to current focused option (for keyboard navigation)
110
113
  @state() private _focusedOptionId = ''
111
114
 
112
- // Form event handlers
113
- private formSubmitHandler = () => {
114
- this._submitted = true
115
- this.checkValidity()
116
- }
117
-
118
- private formResetHandler = () => {
119
- this.reset()
120
- }
121
-
122
- constructor() {
123
- super()
124
- // Initialize ElementInternals for form association
125
- try {
126
- this.internals = this.attachInternals()
127
- } catch (e) {
128
- console.warn('FormAssociated elements not supported in this browser', e)
129
- }
130
- }
131
-
132
- get form() {
133
- return this.internals?.form
134
- }
135
-
136
- connectedCallback() {
115
+ override connectedCallback() {
137
116
  super.connectedCallback()
138
117
  if (!this.id) {
139
118
  this.id = `schmancy-select-${Math.random().toString(36).substring(2, 9)}`
140
119
  }
141
120
 
142
121
  // Store initial value for reset
143
- this.defaultValue = this.value
122
+ this.selectDefaultValue = this.value
144
123
 
145
124
  // Add keyboard handling to host element
146
125
  fromEvent<KeyboardEvent>(this, 'keydown').pipe(takeUntil(this.disconnecting)).subscribe(this.handleKeyDown)
147
126
 
148
127
  // Setup reactive pipelines
149
128
  this._setupReactivePipelines()
150
-
151
- // Listen for form submission events to mark field as submitted
152
- if (this.internals?.form) {
153
- fromEvent(this.internals.form, 'submit')
154
- .pipe(takeUntil(this.disconnecting))
155
- .subscribe(this.formSubmitHandler)
156
-
157
- // Listen for form reset
158
- fromEvent(this.internals.form, 'reset')
159
- .pipe(takeUntil(this.disconnecting))
160
- .subscribe(this.formResetHandler)
161
- }
162
129
  }
163
130
 
164
- disconnectedCallback() {
131
+ override disconnectedCallback() {
165
132
  super.disconnectedCallback()
166
133
  this.cleanupPositioner?.()
167
134
  // Form event listeners are automatically cleaned up via takeUntil(this.disconnecting)
@@ -177,25 +144,20 @@ export class SchmancySelect extends SchmancyElement {
177
144
  }
178
145
  }
179
146
 
180
- updated(changedProps: PropertyValues) {
147
+ override updated(changedProps: PropertyValues) {
181
148
  super.updated(changedProps)
182
149
 
183
150
  if (changedProps.has('value')) {
184
- // Update form value when component value changes
151
+ // Multi-select serializes to a comma-joined scalar on FormData; the
152
+ // mixin's willUpdate already called setFormValue with the raw
153
+ // value, override here for the joined-string shape.
185
154
  const formValue = this.multi
186
155
  ? this._selectedValues$.value.join(',')
187
156
  : this._selectedValue$.value
188
157
  this.internals?.setFormValue(formValue)
189
158
 
190
- // Mark as dirty if value changes from initial value
191
- if (this.hasUpdated) {
192
- this._dirty = true
193
- }
194
-
195
- // Check validity based on validation strategy
196
- if (this.hasUpdated) {
197
- this.checkValidity()
198
- }
159
+ // `dirty` is a mixin getter (value !== _defaultValue); no manual flag.
160
+ // Mixin's willUpdate already calls checkValidity when _shouldShowError().
199
161
  }
200
162
 
201
163
  // When open state changes, setup or cleanup the dropdown positioner
@@ -208,26 +170,7 @@ export class SchmancySelect extends SchmancyElement {
208
170
  }
209
171
  }
210
172
 
211
- /**
212
- * Determines if validation errors should be shown based on current state
213
- * and validation strategy
214
- */
215
- private shouldShowValidation(forceValidation = false): boolean {
216
- if (forceValidation) return true
217
-
218
- switch (this.validateOn) {
219
- case 'always':
220
- return true
221
- case 'touched':
222
- return this._touched
223
- case 'dirty':
224
- return this._dirty
225
- case 'submitted':
226
- return this._submitted
227
- default:
228
- return this._touched
229
- }
230
- }
173
+ // `shouldShowValidation` removed — replaced by mixin's `_shouldShowError()`.
231
174
 
232
175
  private syncSelection() {
233
176
  if (this.multi) {
@@ -418,7 +361,7 @@ export class SchmancySelect extends SchmancyElement {
418
361
  // Only mark as touched if the user actually interacted with the component
419
362
  // and made a selection or explicitly closed it without selecting
420
363
  if (this._userInteracted) {
421
- this._touched = true
364
+ this.touched = true
422
365
  }
423
366
 
424
367
  this.isOpen = false
@@ -433,7 +376,7 @@ export class SchmancySelect extends SchmancyElement {
433
376
 
434
377
  // Only check validity when closing if the user has actually interacted
435
378
  // with the component and validation should be shown
436
- if (this._userInteracted && this.shouldShowValidation()) {
379
+ if (this._userInteracted && this._shouldShowError()) {
437
380
  this.checkValidity()
438
381
  }
439
382
  }
@@ -459,8 +402,8 @@ export class SchmancySelect extends SchmancyElement {
459
402
  withLatestFrom(this._selectedValue$, this._selectedValues$),
460
403
  tap(([option, _, currentValues]) => {
461
404
  this._userInteracted = true
462
- this._touched = true
463
- this._dirty = true
405
+ this.markTouched()
406
+ // `dirty` is a mixin getter; setting `value` below triggers it
464
407
 
465
408
  if (this.multi) {
466
409
  const index = currentValues.indexOf(option.value)
@@ -602,7 +545,7 @@ export class SchmancySelect extends SchmancyElement {
602
545
 
603
546
  // Update the input component to reflect our validation state
604
547
  if (this.inputRef && this.hasUpdated) {
605
- const showError = !this.isValid && this.shouldShowValidation()
548
+ const showError = !this.isValid && this._shouldShowError()
606
549
  this.inputRef.error = showError
607
550
  this.inputRef.hint = showError ? this.validationMessage : this.hint
608
551
  }
@@ -636,7 +579,26 @@ export class SchmancySelect extends SchmancyElement {
636
579
  return valid
637
580
  }
638
581
 
639
- public setCustomValidity(message: string) {
582
+ // `markTouched`, `markSubmitted`, `touched`, `dirty`, `pristine`, `submitted`,
583
+ // `error` (storage) — all from the mixin. Select's `error` semantics
584
+ // (errors-while-open suppression) live in render() via _shouldShowError() +
585
+ // !isOpen, not as a separate getter.
586
+
587
+ /**
588
+ * Multi-value-aware `toFormEntries`. Single-select emits one `[name,value]`;
589
+ * multi-select emits N entries with the same name (canonical FormData shape
590
+ * for repeated fields).
591
+ */
592
+ override toFormEntries(): Array<[string, FormDataEntryValue]> {
593
+ if (!this.name || this.disabled) return []
594
+ const v = this.value
595
+ if (v === undefined || v === null || v === '') return []
596
+ if (Array.isArray(v))
597
+ return v.map(item => [this.name, String(item)] as [string, FormDataEntryValue])
598
+ return [[this.name, String(v)]]
599
+ }
600
+
601
+ override setCustomValidity(message: string) {
640
602
  this.validationMessage = message
641
603
  if (message) {
642
604
  this.isValid = false
@@ -647,34 +609,41 @@ export class SchmancySelect extends SchmancyElement {
647
609
  }
648
610
 
649
611
  // Update input if needed
650
- if (this.inputRef && this.shouldShowValidation()) {
612
+ if (this.inputRef && this._shouldShowError()) {
651
613
  this.inputRef.error = !this.isValid
652
614
  this.inputRef.hint = !this.isValid ? this.validationMessage : this.hint
653
615
  }
654
616
  }
655
617
 
656
- public reset() {
657
- // Reset to initial value
658
- this.value = this.defaultValue
618
+ /**
619
+ * Reset to the snapshot captured at connect time. Mixin's `resetForm`
620
+ * handles touched/submitted/error/validationMessage; the override layers on
621
+ * select-specific cleanup (value subjects, label, validity).
622
+ */
623
+ override resetForm(): void {
624
+ // Restore value (multi-aware) before super so the mixin's _defaultValue
625
+ // reset doesn't clobber the array-shape we need.
626
+ this.value = this.selectDefaultValue
659
627
  this.valueLabel = this.placeholder
660
628
  this.isValid = true
661
- this.validationMessage = ''
662
- this._touched = false
663
- this._dirty = false
664
- this._submitted = false
665
629
  this._userInteracted = false
666
630
  this.internals?.setValidity({})
667
-
631
+ super.resetForm()
668
632
  if (this.inputRef) {
669
633
  this.inputRef.error = false
670
634
  this.inputRef.hint = this.hint
671
635
  }
672
636
  }
673
637
 
638
+ /** Back-compat alias for callers that used the previous public API. */
639
+ public reset(): void {
640
+ this.resetForm()
641
+ }
642
+
674
643
  render(): TemplateResult {
675
644
  // Determine if we should show errors based on the validation strategy and interaction
676
645
  // Never show errors on initial render or if the dropdown is open
677
- const showErrors = !this.isValid && this.shouldShowValidation() && !this.isOpen
646
+ const showErrors = !this.isValid && this._shouldShowError() && !this.isOpen
678
647
 
679
648
  // Add caret icon based on open state
680
649
  const caretIcon = this.isOpen
@@ -1,5 +1,5 @@
1
1
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
2
- import { expectNoA11yViolations } from '../test-utils/a11y'
2
+ import { expectNoA11yViolations } from '../../../test-utils/a11y'
3
3
  import './switch'
4
4
 
5
5
  const nextUpdate = () => new Promise(r => requestAnimationFrame(() => r(null)))
@@ -1,6 +1,6 @@
1
- import { SchmancyElement } from '@mixins/index'
2
- import { css, html, LitElement, nothing } from 'lit'
1
+ import { css, html, LitElement, nothing, type PropertyValues } from 'lit'
3
2
  import { customElement, property } from 'lit/decorators.js'
3
+ import { SchmancyFormField } from '@mixins/index'
4
4
 
5
5
  export type SchmancySwitchChangeEvent = CustomEvent<{ value: boolean }>
6
6
 
@@ -12,16 +12,11 @@ export type SchmancySwitchChangeEvent = CustomEvent<{ value: boolean }>
12
12
  *
13
13
  * @element schmancy-switch
14
14
  * @fires change - `CustomEvent<{ value: boolean }>` when the state changes.
15
- * @attr checked - Initial checked state (also reflected via `value`).
16
- * @attr disabled - Disables interaction.
17
- * @attr required - Requires the switch to be on for form validity.
18
- * @attr name - Form field name for submission.
19
15
  * @csspart track - The background track.
20
16
  * @csspart thumb - The moving thumb.
21
17
  */
22
18
  @customElement('schmancy-switch')
23
- export class SchmancySwitch extends SchmancyElement {
24
- static styles = [css`
19
+ export class SchmancySwitch extends SchmancyFormField(css`
25
20
  :host {
26
21
  display: inline-block;
27
22
  }
@@ -74,77 +69,102 @@ export class SchmancySwitch extends SchmancyElement {
74
69
  @media (prefers-reduced-motion: reduce) {
75
70
  .track, .thumb { transition: none; }
76
71
  }
77
- `];
78
- static formAssociated = true
79
- private internals: ElementInternals | undefined
80
-
81
- @property({ type: Boolean, reflect: true }) checked = false
82
- @property({ type: Boolean, reflect: true }) disabled = false
83
- @property({ type: Boolean, reflect: true }) required = false
84
- @property({ type: String }) name = ''
85
- @property({ type: String }) value = 'on'
86
- @property({ type: String }) label = ''
72
+ `) {
73
+ // `formAssociated`, `internals`, `name`, `disabled`, `required`, `id`,
74
+ // `label`, `error`, `validationMessage`, `validateOn`, touched/dirty/submitted,
75
+ // `markTouched/markSubmitted`, `formResetCallback`, `formDisabledCallback`,
76
+ // FIELD_CONNECT_EVENT dispatch all from the mixin.
87
77
 
78
+ // Inner <button> is the focusable surface; route host focus to it.
88
79
  protected static shadowRootOptions = {
89
80
  ...LitElement.shadowRootOptions,
90
81
  delegatesFocus: true,
91
82
  }
92
83
 
93
- constructor() {
94
- super()
95
- try {
96
- this.internals = this.attachInternals()
97
- } catch {
98
- this.internals = undefined
99
- }
84
+ /**
85
+ * The string written to FormData when the switch is on. Native
86
+ * `<input type=checkbox value="...">` semantics. Defaults to `'on'` to
87
+ * match HTML checkbox conventions.
88
+ */
89
+ @property({ type: String, reflect: true })
90
+ override value: string = 'on'
91
+
92
+ /** Boolean on/off state. Native `<input type=checkbox>.checked` semantics. */
93
+ @property({ type: Boolean, reflect: true })
94
+ checked: boolean = false
95
+
96
+ /** Snapshot of `checked` at first render — drives the `dirty` override. */
97
+ private _checkedDefault: boolean = false
98
+
99
+ override firstUpdated(changed: PropertyValues): void {
100
+ super.firstUpdated(changed)
101
+ this._checkedDefault = this.checked
100
102
  }
101
103
 
102
- get form(): HTMLFormElement | null {
103
- return this.internals?.form ?? null
104
+ /**
105
+ * Override the mixin's value-vs-default `dirty` getter — for switch the
106
+ * meaningful state is `checked`, not the FormData string.
107
+ */
108
+ override get dirty(): boolean {
109
+ return this.checked !== this._checkedDefault
104
110
  }
105
111
 
106
- protected updated(changed: Map<string, unknown>) {
107
- super.updated?.(changed)
112
+ override willUpdate(changed: PropertyValues): void {
113
+ super.willUpdate(changed)
108
114
  if (changed.has('checked') || changed.has('value') || changed.has('name')) {
115
+ // Switch contributes `value` to FormData when on, nothing when off
116
+ // (native checkbox semantics; overrides the mixin's scalar default).
109
117
  this.internals?.setFormValue(this.checked ? this.value : null)
110
118
  if (this.checked) this.internals?.states.add('checked')
111
119
  else this.internals?.states.delete('checked')
120
+ // Mixin's value-changed branch won't fire `checkValidity` here
121
+ // (validateOn: 'dirty' gate stays closed until checked diverges).
122
+ // Sync platform validity explicitly so `form.checkValidity()` is
123
+ // correct from first render.
124
+ this.checkValidity()
112
125
  }
113
- if (changed.has('required') || changed.has('checked')) {
114
- if (this.required && !this.checked) {
115
- this.internals?.setValidity({ valueMissing: true }, 'This switch is required.')
116
- } else {
117
- this.internals?.setValidity({})
118
- }
126
+ if (changed.has('required') || changed.has('disabled')) {
127
+ this.checkValidity()
119
128
  }
120
129
  }
121
130
 
122
- formResetCallback() {
123
- this.checked = this.hasAttribute('checked')
124
- }
131
+ /** Override — switch validity is `checked === true` when required. */
132
+ override checkValidity(): boolean {
133
+ if (this.disabled) {
134
+ this.internals?.setValidity({})
135
+ return true
136
+ }
137
+ const isValid = !this.required || this.checked
138
+ const message = isValid ? '' : 'This switch is required.'
139
+
140
+ this.internals?.setValidity(
141
+ isValid ? {} : { valueMissing: true },
142
+ isValid ? undefined : message,
143
+ )
125
144
 
126
- formDisabledCallback(disabled: boolean) {
127
- this.disabled = disabled
145
+ if (this._shouldShowError()) {
146
+ this.error = !isValid
147
+ this.validationMessage = message
148
+ }
149
+ return isValid
128
150
  }
129
151
 
130
- public checkValidity(): boolean {
131
- return this.internals?.checkValidity() ?? true
152
+ /** Override emit only when the switch is on. */
153
+ override toFormEntries(): Array<[string, FormDataEntryValue]> {
154
+ if (!this.name || this.disabled || !this.checked) return []
155
+ return [[this.name, this.value]]
132
156
  }
133
157
 
134
- public reportValidity(): boolean {
135
- return this.internals?.reportValidity() ?? true
158
+ override resetForm(): void {
159
+ this.checked = this._checkedDefault
160
+ super.resetForm()
136
161
  }
137
162
 
138
163
  private _toggle = () => {
139
164
  if (this.disabled) return
140
165
  this.checked = !this.checked
141
- this.dispatchEvent(
142
- new CustomEvent('change', {
143
- detail: { value: this.checked },
144
- bubbles: true,
145
- composed: true,
146
- }),
147
- )
166
+ this.markTouched()
167
+ this.emitChange({ value: this.checked })
148
168
  }
149
169
 
150
170
  private _onKeydown = (e: KeyboardEvent) => {
@@ -0,0 +1,54 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
2
+ import './textarea'
3
+ import { expectNoA11yViolations } from '../../../test-utils/a11y'
4
+
5
+ const nextUpdate = () => new Promise(r => requestAnimationFrame(() => r(null)))
6
+
7
+ describe('schmancy-textarea', () => {
8
+ let host: HTMLDivElement
9
+
10
+ beforeEach(() => {
11
+ host = document.createElement('div')
12
+ document.body.appendChild(host)
13
+ })
14
+
15
+ afterEach(() => {
16
+ host.remove()
17
+ })
18
+
19
+ it('contributes value to FormData under its name', async () => {
20
+ host.innerHTML = `
21
+ <form>
22
+ <schmancy-textarea name="notes" value="hello"></schmancy-textarea>
23
+ </form>
24
+ `
25
+ const form = host.querySelector('form') as HTMLFormElement
26
+ await nextUpdate()
27
+ await nextUpdate()
28
+ expect(new FormData(form).get('notes')).toBe('hello')
29
+ })
30
+
31
+ it('reports invalid when required and empty', async () => {
32
+ host.innerHTML = `<form><schmancy-textarea name="n" required></schmancy-textarea></form>`
33
+ const form = host.querySelector('form') as HTMLFormElement
34
+ await nextUpdate()
35
+ await nextUpdate()
36
+ expect(form.checkValidity()).toBe(false)
37
+ })
38
+
39
+ it('default validateOn is "dirty"', async () => {
40
+ host.innerHTML = `<schmancy-textarea label="Notes" required></schmancy-textarea>`
41
+ const ta = host.querySelector('schmancy-textarea') as HTMLElement & { validateOn: string; error: boolean }
42
+ await nextUpdate()
43
+ await nextUpdate()
44
+ expect(ta.validateOn).toBe('dirty')
45
+ expect(ta.error).toBe(false)
46
+ })
47
+
48
+ it('has no axe-core a11y violations (idle, with label)', async () => {
49
+ host.innerHTML = `<schmancy-textarea label="Description"></schmancy-textarea>`
50
+ await nextUpdate()
51
+ await nextUpdate()
52
+ await expectNoA11yViolations(host)
53
+ })
54
+ })