@mhmo91/schmancy 0.10.15 → 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 (541) 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/switch.md +21 -2
  292. package/dist/skills/schmancy/textarea.md +13 -0
  293. package/dist/skills/select.md +13 -1
  294. package/dist/skills/switch.md +21 -2
  295. package/dist/skills/textarea.md +13 -0
  296. package/dist/slider.cjs +3 -3
  297. package/dist/slider.cjs.map +1 -1
  298. package/dist/slider.js +2 -2
  299. package/dist/{sound.service-kKfsN0m-.js → sound.service-BIN2W7Rv.js} +1 -1
  300. package/dist/{sound.service-kKfsN0m-.js.map → sound.service-BIN2W7Rv.js.map} +1 -1
  301. package/dist/{sound.service-BGs6m0Cm.cjs → sound.service-DyY78ukR.cjs} +1 -1
  302. package/dist/{sound.service-BGs6m0Cm.cjs.map → sound.service-DyY78ukR.cjs.map} +1 -1
  303. package/dist/{splash-screen-DtkjCJYo.js → splash-screen-BcjjJSlK.js} +2 -2
  304. package/dist/{splash-screen-DtkjCJYo.js.map → splash-screen-BcjjJSlK.js.map} +1 -1
  305. package/dist/{splash-screen-DlQUv-kV.cjs → splash-screen-Kr1sPtME.cjs} +2 -2
  306. package/dist/{splash-screen-DlQUv-kV.cjs.map → splash-screen-Kr1sPtME.cjs.map} +1 -1
  307. package/dist/splash-screen.cjs +1 -1
  308. package/dist/splash-screen.js +1 -1
  309. package/dist/{src-DEUjlTsX.cjs → src-B2-CU8fu.cjs} +11 -11
  310. package/dist/{src-DEUjlTsX.cjs.map → src-B2-CU8fu.cjs.map} +1 -1
  311. package/dist/{src-D6e0adHi.js → src-DvywUq7l.js} +38 -38
  312. package/dist/{src-D6e0adHi.js.map → src-DvywUq7l.js.map} +1 -1
  313. package/dist/state-avic94Ft.cjs +1 -0
  314. package/dist/{state-DNdCPITt.cjs.map → state-avic94Ft.cjs.map} +1 -1
  315. package/dist/{state-BusMG6sM.js → state-nm8yzMPp.js} +1 -2
  316. package/dist/{state-BusMG6sM.js.map → state-nm8yzMPp.js.map} +1 -1
  317. package/dist/state.cjs +1 -1
  318. package/dist/state.js +2 -2
  319. package/dist/steps.cjs +3 -3
  320. package/dist/steps.cjs.map +1 -1
  321. package/dist/steps.js +2 -2
  322. package/dist/{surface-A82O1kgu.js → surface-BtMMHKol.js} +2 -2
  323. package/dist/{surface-A82O1kgu.js.map → surface-BtMMHKol.js.map} +1 -1
  324. package/dist/surface-CgXeKdGL.cjs +7 -0
  325. package/dist/{surface-BpppoNXN.cjs.map → surface-CgXeKdGL.cjs.map} +1 -1
  326. package/dist/surface.cjs +1 -1
  327. package/dist/surface.js +1 -1
  328. package/dist/switch.cjs +3 -3
  329. package/dist/switch.cjs.map +1 -1
  330. package/dist/switch.js +27 -43
  331. package/dist/switch.js.map +1 -1
  332. package/dist/table.cjs +3 -3
  333. package/dist/table.cjs.map +1 -1
  334. package/dist/table.js +2 -2
  335. package/dist/{tabs-cVHHd1dY.js → tabs-CikPr7by.js} +2 -2
  336. package/dist/{tabs-cVHHd1dY.js.map → tabs-CikPr7by.js.map} +1 -1
  337. package/dist/{tabs-TO3UiBsm.cjs → tabs-CitVls3_.cjs} +2 -2
  338. package/dist/{tabs-TO3UiBsm.cjs.map → tabs-CitVls3_.cjs.map} +1 -1
  339. package/dist/tabs.cjs +1 -1
  340. package/dist/tabs.js +1 -1
  341. package/dist/teleport.cjs +1 -1
  342. package/dist/teleport.js +1 -1
  343. package/dist/textarea-CqV1wvmB.cjs +43 -0
  344. package/dist/textarea-CqV1wvmB.cjs.map +1 -0
  345. package/dist/textarea-DVkwQSis.js +186 -0
  346. package/dist/textarea-DVkwQSis.js.map +1 -0
  347. package/dist/textarea.cjs +1 -1
  348. package/dist/textarea.js +1 -1
  349. package/dist/{theme-CT408FqH.js → theme-BIWS4TOW.js} +9 -9
  350. package/dist/{theme-CT408FqH.js.map → theme-BIWS4TOW.js.map} +1 -1
  351. package/dist/theme-DMgjiKda.cjs +181 -0
  352. package/dist/{theme-CpuF3D3q.cjs.map → theme-DMgjiKda.cjs.map} +1 -1
  353. package/dist/{theme-button-pTb5-Wxx.js → theme-button-DC_shZ_7.js} +2 -2
  354. package/dist/{theme-button-pTb5-Wxx.js.map → theme-button-DC_shZ_7.js.map} +1 -1
  355. package/dist/theme-button-ENKa3TPT.cjs +8 -0
  356. package/dist/{theme-button-B6Xf-EiH.cjs.map → theme-button-ENKa3TPT.cjs.map} +1 -1
  357. package/dist/theme-button.cjs +1 -1
  358. package/dist/theme-button.js +1 -1
  359. package/dist/theme.cjs +1 -1
  360. package/dist/{theme.interface-B9TjbSBF.js.map → theme.interface-C8OHheXg.js.map} +1 -1
  361. package/dist/{theme.interface-BujperTo.cjs.map → theme.interface-CYo4UpWK.cjs.map} +1 -1
  362. package/dist/theme.js +4 -4
  363. package/dist/{theme.service-DIUo1mBP.js → theme.service-BOWIT_5k.js} +1 -1
  364. package/dist/{theme.service-DIUo1mBP.js.map → theme.service-BOWIT_5k.js.map} +1 -1
  365. package/dist/{theme.service-Cfk88qHK.cjs → theme.service-DkdH1t60.cjs} +1 -1
  366. package/dist/{theme.service-Cfk88qHK.cjs.map → theme.service-DkdH1t60.cjs.map} +1 -1
  367. package/dist/tree.cjs +2 -2
  368. package/dist/tree.cjs.map +1 -1
  369. package/dist/tree.js +2 -2
  370. package/dist/typography.cjs +2 -2
  371. package/dist/typography.cjs.map +1 -1
  372. package/dist/typography.js +2 -2
  373. package/dist/{utils-kND2Z9Xg.js → utils-Cj_nRRyx.js} +2 -2
  374. package/dist/{utils-kND2Z9Xg.js.map → utils-Cj_nRRyx.js.map} +1 -1
  375. package/dist/{utils-Dt5PpmaQ.cjs → utils-D2QUu4-g.cjs} +1 -1
  376. package/dist/{utils-Dt5PpmaQ.cjs.map → utils-D2QUu4-g.cjs.map} +1 -1
  377. package/dist/utils.cjs +1 -1
  378. package/dist/utils.js +4 -4
  379. package/dist/visually-hidden.cjs +2 -2
  380. package/dist/visually-hidden.cjs.map +1 -1
  381. package/dist/visually-hidden.js +2 -2
  382. package/dist/{window-CuBcOxbc.js → window-BTecgE_U.js} +7 -7
  383. package/dist/{window-CuBcOxbc.js.map → window-BTecgE_U.js.map} +1 -1
  384. package/dist/{window-CSKvv4Ts.cjs → window-DGydMS0g.cjs} +2 -2
  385. package/dist/{window-CSKvv4Ts.cjs.map → window-DGydMS0g.cjs.map} +1 -1
  386. package/dist/window.cjs +1 -1
  387. package/dist/window.js +1 -1
  388. package/package.json +1 -1
  389. package/skills/schmancy/autocomplete.md +16 -3
  390. package/skills/schmancy/button.md +19 -0
  391. package/skills/schmancy/checkbox.md +19 -0
  392. package/skills/schmancy/date-range.md +19 -0
  393. package/skills/schmancy/form-ux-rules.md +55 -0
  394. package/skills/schmancy/form.md +121 -25
  395. package/skills/schmancy/input.md +19 -4
  396. package/skills/schmancy/range.md +15 -1
  397. package/skills/schmancy/select.md +13 -1
  398. package/skills/schmancy/switch.md +21 -2
  399. package/skills/schmancy/textarea.md +13 -0
  400. package/src/button/button.test.ts +122 -0
  401. package/src/button/button.ts +36 -0
  402. package/src/{autocomplete → form/fields/autocomplete}/autocomplete.ts +48 -75
  403. package/src/{checkbox → form/fields/checkbox}/checkbox.test.ts +1 -1
  404. package/src/form/fields/checkbox/checkbox.ts +126 -0
  405. package/src/form/fields/date-range/date-range.test.ts +102 -0
  406. package/src/{date-range → form/fields/date-range}/date-range.ts +90 -7
  407. package/src/form/fields/input/input.test.ts +201 -0
  408. package/src/{input → form/fields/input}/input.ts +153 -238
  409. package/src/{radio-group → form/fields/radio-group}/radio-button.ts +1 -1
  410. package/src/{radio-group → form/fields/radio-group}/radio-group.ts +1 -1
  411. package/src/form/fields/range/range.test.ts +90 -0
  412. package/src/{range → form/fields/range}/range.ts +34 -13
  413. package/src/{select → form/fields/select}/select.ts +77 -108
  414. package/src/{switch → form/fields/switch}/switch.test.ts +1 -1
  415. package/src/{switch → form/fields/switch}/switch.ts +71 -51
  416. package/src/form/fields/textarea/textarea.test.ts +54 -0
  417. package/src/{textarea → form/fields/textarea}/textarea.ts +33 -72
  418. package/src/form/form-state.ts +31 -0
  419. package/src/form/form-summary.test.ts +105 -0
  420. package/src/form/form-summary.ts +171 -0
  421. package/src/form/form.test.ts +218 -35
  422. package/src/form/form.ts +330 -99
  423. package/src/form/index.ts +2 -0
  424. package/src/index.ts +9 -9
  425. package/types/mixins/formField.mixin.d.ts +90 -0
  426. package/types/src/button/button.d.ts +9 -0
  427. package/types/src/button/button.test.d.ts +3 -0
  428. package/types/src/{autocomplete → form/fields/autocomplete}/autocomplete.d.ts +6 -15
  429. package/types/src/form/fields/checkbox/checkbox.d.ts +47 -0
  430. package/types/src/{date-range → form/fields/date-range}/date-range.d.ts +22 -4
  431. package/types/src/form/fields/date-range/date-range.test.d.ts +1 -0
  432. package/types/src/{input → form/fields/input}/input.d.ts +20 -45
  433. package/types/src/form/fields/input/input.test.d.ts +1 -0
  434. package/types/src/{radio-group → form/fields/radio-group}/radio-button.d.ts +1 -1
  435. package/types/src/{radio-group → form/fields/radio-group}/radio-group.d.ts +1 -1
  436. package/types/src/form/fields/range/range.d.ts +28 -0
  437. package/types/src/form/fields/range/range.test.d.ts +1 -0
  438. package/types/src/{select → form/fields/select}/select.d.ts +23 -24
  439. package/types/src/form/fields/switch/switch.d.ts +57 -0
  440. package/types/src/{textarea → form/fields/textarea}/textarea.d.ts +6 -39
  441. package/types/src/form/fields/textarea/textarea.test.d.ts +1 -0
  442. package/types/src/form/form-state.d.ts +22 -0
  443. package/types/src/form/form-summary.d.ts +42 -0
  444. package/types/src/form/form-summary.test.d.ts +4 -0
  445. package/types/src/form/form.d.ts +79 -34
  446. package/types/src/form/form.test.d.ts +2 -2
  447. package/types/src/form/index.d.ts +2 -0
  448. package/types/src/index.d.ts +9 -9
  449. package/dist/active-host-CcIa2tmW.cjs +0 -1
  450. package/dist/active-host-CvNYoprt.js +0 -57
  451. package/dist/autocomplete-DWSuwSRS.js.map +0 -1
  452. package/dist/autocomplete-iCJOia-q.cjs +0 -115
  453. package/dist/autocomplete-iCJOia-q.cjs.map +0 -1
  454. package/dist/checkbox-NNReP9s_.cjs.map +0 -1
  455. package/dist/date-range-CaOxwZDq.cjs +0 -131
  456. package/dist/date-range-CaOxwZDq.cjs.map +0 -1
  457. package/dist/date-range-CgNujP8r.js.map +0 -1
  458. package/dist/date-range-inline-D4IjOOO0.cjs +0 -43
  459. package/dist/decorate-23nYs4Le.js +0 -7
  460. package/dist/decorate-DpFmy0nm.cjs +0 -1
  461. package/dist/float-CKmd-0-t.cjs +0 -1
  462. package/dist/form-CFvwnfuJ.js +0 -68
  463. package/dist/form-CFvwnfuJ.js.map +0 -1
  464. package/dist/form-Ceijw1aA.cjs +0 -1
  465. package/dist/form-Ceijw1aA.cjs.map +0 -1
  466. package/dist/input-D95GjINh.js.map +0 -1
  467. package/dist/input-D9s4jDAb.cjs +0 -51
  468. package/dist/input-D9s4jDAb.cjs.map +0 -1
  469. package/dist/mixins-BV0w2yIE.js +0 -627
  470. package/dist/mixins-BV0w2yIE.js.map +0 -1
  471. package/dist/mixins-DvAYa-F7.cjs +0 -298
  472. package/dist/mixins-DvAYa-F7.cjs.map +0 -1
  473. package/dist/notification-BC9nG8Sr.cjs +0 -23
  474. package/dist/radio-group-ByMD6Lsj.cjs +0 -40
  475. package/dist/radio-group-ByMD6Lsj.cjs.map +0 -1
  476. package/dist/radio-group-CW8airhZ.js.map +0 -1
  477. package/dist/select-BdBThja4.cjs +0 -56
  478. package/dist/select-BdBThja4.cjs.map +0 -1
  479. package/dist/select-Dbn-CImU.js.map +0 -1
  480. package/dist/state-DNdCPITt.cjs +0 -1
  481. package/dist/surface-BpppoNXN.cjs +0 -7
  482. package/dist/textarea-B9dy-yec.js +0 -211
  483. package/dist/textarea-B9dy-yec.js.map +0 -1
  484. package/dist/textarea-DFY0Flgv.cjs +0 -39
  485. package/dist/textarea-DFY0Flgv.cjs.map +0 -1
  486. package/dist/theme-CpuF3D3q.cjs +0 -181
  487. package/dist/theme-button-B6Xf-EiH.cjs +0 -8
  488. package/src/checkbox/checkbox.ts +0 -162
  489. package/types/src/checkbox/checkbox.d.ts +0 -71
  490. package/types/src/range/range.d.ts +0 -25
  491. package/types/src/switch/switch.d.ts +0 -53
  492. /package/dist/{animation-CO_Csq84.cjs → animation-CCOIW4wJ.cjs} +0 -0
  493. /package/dist/{animation-BK-8BwY8.js → animation-DCznELuT.js} +0 -0
  494. /package/dist/{context-DJTJnSK4.js → context-6oXCZmZN.js} +0 -0
  495. /package/dist/{context-BpCETidA.cjs → context-CRZeiCqq.cjs} +0 -0
  496. /package/dist/{hashContent-Bobsobip.cjs → hashContent-Ck6laKlk.cjs} +0 -0
  497. /package/dist/{hashContent-BU6jl5ih.js → hashContent-dJrI-9sc.js} +0 -0
  498. /package/dist/{lazy-Dq9mRRjT.cjs → lazy-CayEFyC3.cjs} +0 -0
  499. /package/dist/{lazy-B0ia54tT.js → lazy-D-bO2r4m.js} +0 -0
  500. /package/dist/{overlay-stack-DCDS17uj.js → overlay-stack-BR4iYivO.js} +0 -0
  501. /package/dist/{overlay-stack-DPIe_aYv.cjs → overlay-stack-Dk0xETTy.cjs} +0 -0
  502. /package/dist/{reduced-motion-D-L12p7G.js → reduced-motion-D7LqTUMn.js} +0 -0
  503. /package/dist/{reduced-motion-Ds-HjMzn.cjs → reduced-motion-Dzfp_w5x.cjs} +0 -0
  504. /package/dist/{rxjs-utils-CVeJQ9KG.js → rxjs-utils-D9U4MW0Q.js} +0 -0
  505. /package/dist/{rxjs-utils-DCUHg_Ml.cjs → rxjs-utils-kWPShgKu.cjs} +0 -0
  506. /package/dist/{search-BLCRsxIC.cjs → search-DPKoC-dT.cjs} +0 -0
  507. /package/dist/{search-BTz7-Rev.js → search-MvIBA93K.js} +0 -0
  508. /package/dist/{theme.interface-B9TjbSBF.js → theme.interface-C8OHheXg.js} +0 -0
  509. /package/dist/{theme.interface-BujperTo.cjs → theme.interface-CYo4UpWK.cjs} +0 -0
  510. /package/src/{autocomplete → form/fields/autocomplete}/autocomplete.scss +0 -0
  511. /package/src/{autocomplete → form/fields/autocomplete}/index.ts +0 -0
  512. /package/src/{checkbox → form/fields/checkbox}/index.ts +0 -0
  513. /package/src/{date-range → form/fields/date-range}/date-range-dialog.ts +0 -0
  514. /package/src/{date-range → form/fields/date-range}/date-range-helpers.ts +0 -0
  515. /package/src/{date-range → form/fields/date-range}/date-range-presets.ts +0 -0
  516. /package/src/{date-range → form/fields/date-range}/date-utils.ts +0 -0
  517. /package/src/{date-range → form/fields/date-range}/index.ts +0 -0
  518. /package/src/{input → form/fields/input}/index.ts +0 -0
  519. /package/src/{input → form/fields/input}/input.scss +0 -0
  520. /package/src/{radio-group → form/fields/radio-group}/index.ts +0 -0
  521. /package/src/{radio-group → form/fields/radio-group}/radio-group.scss +0 -0
  522. /package/src/{range → form/fields/range}/index.ts +0 -0
  523. /package/src/{select → form/fields/select}/index.ts +0 -0
  524. /package/src/{switch → form/fields/switch}/index.ts +0 -0
  525. /package/src/{textarea → form/fields/textarea}/index.ts +0 -0
  526. /package/src/{textarea → form/fields/textarea}/textarea.scss +0 -0
  527. /package/types/src/{autocomplete → form/fields/autocomplete}/index.d.ts +0 -0
  528. /package/types/src/{checkbox → form/fields/checkbox}/checkbox.test.d.ts +0 -0
  529. /package/types/src/{checkbox → form/fields/checkbox}/index.d.ts +0 -0
  530. /package/types/src/{date-range → form/fields/date-range}/date-range-dialog.d.ts +0 -0
  531. /package/types/src/{date-range → form/fields/date-range}/date-range-helpers.d.ts +0 -0
  532. /package/types/src/{date-range → form/fields/date-range}/date-range-presets.d.ts +0 -0
  533. /package/types/src/{date-range → form/fields/date-range}/date-utils.d.ts +0 -0
  534. /package/types/src/{date-range → form/fields/date-range}/index.d.ts +0 -0
  535. /package/types/src/{input → form/fields/input}/index.d.ts +0 -0
  536. /package/types/src/{radio-group → form/fields/radio-group}/index.d.ts +0 -0
  537. /package/types/src/{range → form/fields/range}/index.d.ts +0 -0
  538. /package/types/src/{select → form/fields/select}/index.d.ts +0 -0
  539. /package/types/src/{switch → form/fields/switch}/index.d.ts +0 -0
  540. /package/types/src/{switch → form/fields/switch}/switch.test.d.ts +0 -0
  541. /package/types/src/{textarea → form/fields/textarea}/index.d.ts +0 -0
@@ -3,9 +3,9 @@ import { customElement, property, query } from 'lit/decorators.js'
3
3
  import { ifDefined } from 'lit/directives/if-defined.js'
4
4
  import { createRef, ref } from 'lit/directives/ref.js'
5
5
  import { when } from 'lit/directives/when.js'
6
- import { distinctUntilChanged, filter, fromEvent, map } from 'rxjs'
6
+ import { distinctUntilChanged, filter, fromEvent, map, takeUntil, timer } from 'rxjs'
7
7
  import style from './textarea.scss?inline'
8
- import { SchmancyElement } from '@mixins/index'
8
+ import { SchmancyFormField } from '@mixins/index'
9
9
 
10
10
  /**
11
11
  * Textarea component with auto-resize and form integration.
@@ -20,38 +20,21 @@ import { SchmancyElement } from '@mixins/index'
20
20
  * @prop {number} maxlength - Maximum character length
21
21
  */
22
22
  @customElement('schmancy-textarea')
23
- export default class SchmancyTextarea extends SchmancyElement {
24
- static styles = [unsafeCSS(style)];
23
+ export default class SchmancyTextarea extends SchmancyFormField(unsafeCSS(style)) {
25
24
 
26
25
  protected static shadowRootOptions = {
27
26
  ...LitElement.shadowRootOptions,
28
27
  delegatesFocus: true,
29
28
  }
30
- static formAssociated = true
31
- // private internals
32
- internals: ElementInternals | undefined
29
+
30
+ // `formAssociated`, `internals`, `name`, `label`, `required`, `disabled`,
31
+ // `error`, `validationMessage`, `hint`, `id`, `validateOn`, `touched`,
32
+ // `dirty`, `submitted`, `markTouched`, `markSubmitted`, `setCustomValidity`,
33
+ // `formResetCallback`, `formDisabledCallback` — all from the mixin.
33
34
  textareaRef = createRef<HTMLTextAreaElement>()
34
35
 
35
36
  private readonly _a11yId = `schmancy-textarea-${Math.random().toString(36).slice(2, 10)}`
36
37
 
37
- /**
38
- * The label of the control.
39
- * @attr
40
- * @type {string} label
41
- * @default ''
42
- * @public
43
- */
44
- @property() label = ''
45
-
46
- /**
47
- * The name of the control.
48
- * @attr name
49
- * @type {string} name
50
- * @default 'name_' + Date.now()
51
- * @public
52
- */
53
- @property() name = 'name_' + Date.now()
54
-
55
38
  /**
56
39
  * The placeholder of the control.
57
40
  * @attr placeholder
@@ -62,13 +45,11 @@ export default class SchmancyTextarea extends SchmancyElement {
62
45
  @property() placeholder = ''
63
46
 
64
47
  /**
65
- * The value of the control.
48
+ * The value of the control. Narrowed from the mixin's wide union to the
49
+ * textarea-specific `string` type.
66
50
  * @attr {string} value - The value of the control.
67
- * @type {string}
68
- * @default ''
69
- * @public
70
51
  */
71
- @property({ type: String, reflect: true }) public value = ''
52
+ @property({ type: String, reflect: true }) override value: string = ''
72
53
 
73
54
  /**
74
55
  * The minlength attribute of the control.
@@ -148,19 +129,14 @@ export default class SchmancyTextarea extends SchmancyElement {
148
129
  */
149
130
  @property({ type: String }) dirname: string | undefined
150
131
 
151
- @property({ type: Boolean, reflect: true }) required = false
152
- @property({ type: Boolean, reflect: true }) disabled = false
153
- @property({ type: Boolean, reflect: true }) readonly = false
132
+ // `required`, `disabled`, `readonly`, `error`, `validationMessage`, `hint`
133
+ // come from the mixin. Textarea-specific extras only:
154
134
  @property({ type: Boolean, reflect: true }) spellcheck = false
155
135
 
156
136
  @property({ type: String, reflect: true }) align: 'left' | 'center' | 'right' = 'left'
157
137
 
158
138
  /**
159
139
  * The autofocus attribute of the control.
160
- * @attr
161
- * @type {boolean}
162
- * @default false
163
- * @public
164
140
  */
165
141
  @property({ type: Boolean })
166
142
  public override autofocus!: boolean
@@ -170,54 +146,33 @@ export default class SchmancyTextarea extends SchmancyElement {
170
146
 
171
147
  @query('textarea') textareaElement!: HTMLTextAreaElement
172
148
 
173
- @property() hint: string | undefined
174
-
175
- @property({ type: Boolean, reflect: true }) public error = false
176
-
177
- constructor() {
178
- super()
179
- try {
180
- this.internals = this.attachInternals()
181
- } catch {
182
- this.internals = undefined
183
- }
184
- }
185
-
186
- protected willUpdate(changed: PropertyValues): void {
187
- super.willUpdate?.(changed)
188
- if (changed.has('value') || changed.has('name')) {
189
- this.internals?.setFormValue(this.value ?? '')
190
- }
149
+ // Mixin's willUpdate already calls internals.setFormValue() on value-change
150
+ // and runs the required-empty / customError validity machinery. Native
151
+ // `valueMissing` flag is set here for richer ValidityState introspection.
152
+ override willUpdate(changed: PropertyValues): void {
153
+ super.willUpdate(changed)
191
154
  if (changed.has('required') || changed.has('value')) {
192
155
  if (this.required && !this.value) {
193
156
  this.internals?.setValidity({ valueMissing: true }, 'Please fill out this field.')
194
- } else {
195
- this.internals?.setValidity({})
196
157
  }
197
158
  }
198
159
  }
199
160
 
200
- formResetCallback(): void {
201
- this.value = this.getAttribute('value') ?? ''
202
- this.error = false
203
- }
204
-
205
- formDisabledCallback(disabled: boolean): void {
206
- this.disabled = disabled
207
- }
208
-
209
161
  firstUpdated() {
210
162
  if (this.autofocus) {
211
163
  this.focus()
212
164
  }
213
165
  if (this.autoHeight) {
214
- // Initial adjustment for pre-filled content
215
- setTimeout(() => this.adjustHeight(), 0)
166
+ // Initial adjustment for pre-filled content (cancel-on-disconnect).
167
+ timer(0)
168
+ .pipe(takeUntil(this.disconnecting))
169
+ .subscribe(() => this.adjustHeight())
216
170
  }
217
171
  fromEvent(this.textareaElement, 'input')
218
172
  .pipe(
219
173
  map(event => (event.target as HTMLTextAreaElement).value),
220
174
  distinctUntilChanged(),
175
+ takeUntil(this.disconnecting),
221
176
  )
222
177
  .subscribe(value => {
223
178
  this.value = value
@@ -236,6 +191,7 @@ export default class SchmancyTextarea extends SchmancyElement {
236
191
  .pipe(
237
192
  map(event => (event.target as HTMLTextAreaElement).value),
238
193
  distinctUntilChanged(),
194
+ takeUntil(this.disconnecting),
239
195
  )
240
196
  .subscribe(value => {
241
197
  this.value = value
@@ -256,6 +212,7 @@ export default class SchmancyTextarea extends SchmancyElement {
256
212
  filter(event => event.key === 'Enter'),
257
213
  map(event => (event.target as HTMLTextAreaElement).value),
258
214
  distinctUntilChanged(),
215
+ takeUntil(this.disconnecting),
259
216
  )
260
217
  .subscribe(value => {
261
218
  this.value = value
@@ -434,15 +391,19 @@ export default class SchmancyTextarea extends SchmancyElement {
434
391
  dirname=${ifDefined(this.dirname)}
435
392
  aria-invalid=${this.error ? 'true' : 'false'}
436
393
  aria-required=${this.required ? 'true' : 'false'}
437
- aria-describedby=${this.hint ? hintId : nothing}
394
+ aria-describedby=${this.hint || (this.error && this.validationMessage) ? hintId : nothing}
438
395
  aria-label=${!this.label && this.placeholder ? this.placeholder : nothing}
439
396
  ></textarea>
440
397
 
441
398
  ${when(
442
- this.hint,
399
+ this.hint || (this.error && this.validationMessage),
443
400
  () => html`
444
- <div id=${hintId} class="mt-1 text-sm ${this.error ? 'text-error-default' : 'text-surface-onVariant'}">
445
- ${this.hint}
401
+ <div
402
+ id=${hintId}
403
+ class="mt-1 text-sm ${this.error ? 'text-error-default' : 'text-surface-onVariant'}"
404
+ role=${ifDefined(this.error ? 'alert' : undefined)}
405
+ >
406
+ ${this.error && this.validationMessage ? this.validationMessage : this.hint}
446
407
  </div>
447
408
  `,
448
409
  )}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Form-level submit state — consumed by `<schmancy-form>` and any descendant
3
+ * (e.g. `<schmancy-button type="submit">` to drive its loading/aria-busy).
4
+ *
5
+ * `<schmancy-form>` wraps its render output in `<schmancy-context
6
+ * .provides=${[formSubmitState]}>` so each instance gets an isolated copy
7
+ * via the schmancy state library's resolveContextual mechanism. Reads of
8
+ * `formSubmitState.value` and writes via `formSubmitState.set(...)` inside
9
+ * the form's subtree resolve to the per-form copy automatically — no
10
+ * `@lit/context` plumbing in user code.
11
+ */
12
+
13
+ import { state } from '../state'
14
+
15
+ export type FormError = {
16
+ message: string
17
+ code?: string
18
+ }
19
+
20
+ export type FormSubmitState = {
21
+ status: 'idle' | 'submitting' | 'success' | 'error'
22
+ error: FormError | null
23
+ /** Increments on every submit attempt — RHF parity. */
24
+ submitCount: number
25
+ }
26
+
27
+ export const formSubmitState = state<FormSubmitState>('schmancy/form-submit').memory({
28
+ status: 'idle',
29
+ error: null,
30
+ submitCount: 0,
31
+ })
@@ -0,0 +1,105 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
2
+ import './form'
3
+ import './form-summary'
4
+ import './fields/input/input'
5
+ import '../button/button'
6
+ import { expectNoA11yViolations } from '../test-utils/a11y'
7
+ import type SchmancyForm from './form'
8
+
9
+ const nextUpdate = () => new Promise(r => requestAnimationFrame(() => r(null)))
10
+
11
+ describe('schmancy-form-summary', () => {
12
+ let host: HTMLDivElement
13
+
14
+ beforeEach(() => {
15
+ host = document.createElement('div')
16
+ document.body.appendChild(host)
17
+ })
18
+
19
+ afterEach(() => {
20
+ host.remove()
21
+ })
22
+
23
+ it('renders nothing when form is idle', async () => {
24
+ host.innerHTML = `
25
+ <schmancy-form>
26
+ <schmancy-form-summary></schmancy-form-summary>
27
+ <schmancy-input name="email" required></schmancy-input>
28
+ </schmancy-form>
29
+ `
30
+ await nextUpdate()
31
+ await nextUpdate()
32
+ const summary = host.querySelector('schmancy-form-summary') as HTMLElement
33
+ expect(summary.shadowRoot?.querySelector('[role="alert"]')).toBeNull()
34
+ })
35
+
36
+ it('renders banner with heading + form message after setFormError', async () => {
37
+ host.innerHTML = `
38
+ <schmancy-form>
39
+ <schmancy-form-summary></schmancy-form-summary>
40
+ <schmancy-input name="email" required></schmancy-input>
41
+ </schmancy-form>
42
+ `
43
+ const sf = host.querySelector('schmancy-form') as SchmancyForm
44
+ await nextUpdate()
45
+ await nextUpdate()
46
+ sf.setFormError('Network error — please try again.')
47
+ await nextUpdate()
48
+ await nextUpdate()
49
+ await nextUpdate()
50
+ const summary = host.querySelector('schmancy-form-summary') as HTMLElement
51
+ const banner = summary.shadowRoot?.querySelector('[role="alert"]') as HTMLElement
52
+ expect(banner).toBeTruthy()
53
+ expect(banner.textContent).toContain('Network error')
54
+ })
55
+
56
+ it('lists invalid field links after a failed submit', async () => {
57
+ host.innerHTML = `
58
+ <schmancy-form>
59
+ <schmancy-form-summary></schmancy-form-summary>
60
+ <schmancy-input name="email" label="Email" required></schmancy-input>
61
+ <schmancy-input name="city" label="City" required></schmancy-input>
62
+ <schmancy-button type="submit">Send</schmancy-button>
63
+ </schmancy-form>
64
+ `
65
+ const btn = host.querySelector('schmancy-button[type=submit]') as HTMLElement
66
+ await nextUpdate()
67
+ await nextUpdate()
68
+ btn.click()
69
+ // Wait long enough for: form submit chain → markSubmitted → field
70
+ // updates → live region populated → MutationObserver fired → form-summary
71
+ // re-render.
72
+ await new Promise(r => setTimeout(r, 200))
73
+ const summary = host.querySelector('schmancy-form-summary') as HTMLElement & {
74
+ updateComplete: Promise<boolean>
75
+ }
76
+ await summary.updateComplete
77
+
78
+ // Diagnostic: confirm fields actually report :state(invalid).
79
+ const fields = host.querySelectorAll('schmancy-input')
80
+ const invalidCount = Array.from(fields).filter(f => f.matches(':state(invalid)')).length
81
+ expect(invalidCount).toBe(2) // sanity — fields are flagged
82
+
83
+ const links = summary.shadowRoot?.querySelectorAll('a') ?? []
84
+ expect(links.length).toBe(2)
85
+ expect((links[0] as HTMLAnchorElement).textContent).toContain('Email')
86
+ })
87
+
88
+ it('has no axe-core a11y violations in error state', async () => {
89
+ host.innerHTML = `
90
+ <schmancy-form>
91
+ <schmancy-form-summary></schmancy-form-summary>
92
+ <schmancy-input name="email" label="Email" required></schmancy-input>
93
+ <schmancy-button type="submit">Send</schmancy-button>
94
+ </schmancy-form>
95
+ `
96
+ const sf = host.querySelector('schmancy-form') as SchmancyForm
97
+ await nextUpdate()
98
+ await nextUpdate()
99
+ sf.setFormError('Server is down')
100
+ await nextUpdate()
101
+ await nextUpdate()
102
+ await nextUpdate()
103
+ await expectNoA11yViolations(host)
104
+ })
105
+ })
@@ -0,0 +1,171 @@
1
+ /**
2
+ * `<schmancy-form-summary>` — top-of-form error summary with anchor links to
3
+ * each invalid field. Linear / GOV.UK / GitHub pattern.
4
+ *
5
+ * Drop one inside any `<schmancy-form>`; on submit-failure or when
6
+ * `<schmancy-form>.setFormError(...)` is called, the summary renders a
7
+ * `role="alert"` banner with the form-level error message and a list of
8
+ * links pointing at each invalid field's `id`.
9
+ *
10
+ * Hidden when the form is idle, submitting, or successful — only `error`
11
+ * populates it.
12
+ *
13
+ * @element schmancy-form-summary
14
+ */
15
+
16
+ import { html, nothing } from 'lit'
17
+ import { customElement, property, state } from 'lit/decorators.js'
18
+ import { SchmancyElement } from '../../mixins'
19
+ import type SchmancyForm from './form'
20
+
21
+ @customElement('schmancy-form-summary')
22
+ export class SchmancyFormSummary extends SchmancyElement {
23
+ /**
24
+ * Optional heading text. Defaults to a count-based summary
25
+ * ("1 problem with this form" / "3 problems with this form").
26
+ */
27
+ @property({ type: String }) heading?: string
28
+
29
+ /**
30
+ * Render bumper — incremented to force a re-render when the form's state
31
+ * changes (the actual content is computed from the DOM in render()).
32
+ */
33
+ @state() private _bump: number = 0
34
+
35
+ private _form: SchmancyForm | null = null
36
+ private _formObserver?: MutationObserver
37
+
38
+ override connectedCallback(): void {
39
+ super.connectedCallback()
40
+ this._form = this.closest('schmancy-form') as SchmancyForm | null
41
+ if (!this._form) {
42
+ console.error('[schmancy-form-summary] must be a descendant of <schmancy-form>')
43
+ return
44
+ }
45
+ const bump = () => { this._bump++ }
46
+ this._formObserver = new MutationObserver(bump)
47
+ // Form host attribute changes (aria-busy, :state class reflections,
48
+ // descendant attribute changes for fields' aria-invalid). subtree:true
49
+ // catches attribute mutations on every descendant including light-DOM
50
+ // fields and the form's own host.
51
+ this._formObserver.observe(this._form, {
52
+ attributes: true,
53
+ subtree: true,
54
+ })
55
+ // Defer live-region observation until the form has rendered its
56
+ // shadow tree.
57
+ const attachLiveRegionObserver = async (): Promise<void> => {
58
+ await this._form?.updateComplete
59
+ const liveRegion = this._form?.shadowRoot?.querySelector('[role="status"]')
60
+ if (liveRegion) {
61
+ this._formObserver?.observe(liveRegion, {
62
+ childList: true,
63
+ characterData: true,
64
+ subtree: true,
65
+ })
66
+ }
67
+ // Force a render so the initial state is reflected.
68
+ this._bump++
69
+ }
70
+ void attachLiveRegionObserver()
71
+ }
72
+
73
+ override disconnectedCallback(): void {
74
+ this._formObserver?.disconnect()
75
+ this._formObserver = undefined
76
+ super.disconnectedCallback()
77
+ }
78
+
79
+ private _readFormStatus(): 'idle' | 'submitting' | 'success' | 'error' {
80
+ if (!this._form) return 'idle'
81
+ if (this._form.matches(':state(error)')) return 'error'
82
+ if (this._form.matches(':state(submitting)')) return 'submitting'
83
+ if (this._form.matches(':state(success)')) return 'success'
84
+ return 'idle'
85
+ }
86
+
87
+ private _readFormMessage(): string {
88
+ const liveRegion = this._form?.shadowRoot?.querySelector('[role="status"]')
89
+ return liveRegion?.textContent?.trim() ?? ''
90
+ }
91
+
92
+ private _readInvalidFields(): Array<{ id: string; label: string; message: string }> {
93
+ if (!this._form) return []
94
+ const result: Array<{ id: string; label: string; message: string }> = []
95
+ for (const el of Array.from(this._form.querySelectorAll('*'))) {
96
+ if (!(el instanceof HTMLElement)) continue
97
+ let isInvalid = false
98
+ try {
99
+ isInvalid = el.matches(':state(invalid)')
100
+ } catch {
101
+ continue
102
+ }
103
+ if (!isInvalid) continue
104
+ const f = el as HTMLElement & {
105
+ label?: string
106
+ name?: string
107
+ validationMessage?: string
108
+ }
109
+ result.push({
110
+ id: f.id,
111
+ label: f.label || f.name || '(field)',
112
+ message: f.validationMessage || 'Invalid value',
113
+ })
114
+ }
115
+ return result
116
+ }
117
+
118
+ render() {
119
+ // Read everything fresh from the DOM each render — no @state cache, no
120
+ // re-render loops. The MutationObserver bumps `_bump` to trigger this
121
+ // render; `_bump` itself is never read here.
122
+ void this._bump
123
+
124
+ const status = this._readFormStatus()
125
+ if (status !== 'error') return nothing
126
+
127
+ const formMessage = this._readFormMessage()
128
+ const invalid = this._readInvalidFields()
129
+ const count = invalid.length
130
+ const heading =
131
+ this.heading ??
132
+ (count === 0
133
+ ? 'There is a problem with this form'
134
+ : `There ${count === 1 ? 'is' : 'are'} ${count} problem${count === 1 ? '' : 's'} with this form`)
135
+
136
+ return html`
137
+ <div role="alert" aria-labelledby="schmancy-form-summary-heading">
138
+ <h2 id="schmancy-form-summary-heading">${heading}</h2>
139
+ ${formMessage ? html`<p>${formMessage}</p>` : nothing}
140
+ ${count > 0
141
+ ? html`
142
+ <ul>
143
+ ${invalid.map(
144
+ f => html`
145
+ <li>
146
+ <a
147
+ href="#${f.id}"
148
+ @click=${(e: MouseEvent) => this._jumpToField(e, f.id)}
149
+ >${f.label}: ${f.message}</a>
150
+ </li>
151
+ `,
152
+ )}
153
+ </ul>
154
+ `
155
+ : nothing}
156
+ </div>
157
+ `
158
+ }
159
+
160
+ private _jumpToField(e: MouseEvent, fieldId: string): void {
161
+ e.preventDefault()
162
+ const target = this._form?.querySelector(`#${CSS.escape(fieldId)}`) as HTMLElement | null
163
+ target?.focus()
164
+ }
165
+ }
166
+
167
+ declare global {
168
+ interface HTMLElementTagNameMap {
169
+ 'schmancy-form-summary': SchmancyFormSummary
170
+ }
171
+ }