@mhmo91/schmancy 0.10.34 → 0.10.36

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 (414) hide show
  1. package/custom-elements.json +1144 -1101
  2. package/dist/SchmancyElement-BBzRWB1w.cjs +2 -0
  3. package/dist/SchmancyElement-BBzRWB1w.cjs.map +1 -0
  4. package/dist/SchmancyElement-C3CpdNsi.js +284 -0
  5. package/dist/SchmancyElement-C3CpdNsi.js.map +1 -0
  6. package/dist/agent/schmancy.agent.js +3414 -3263
  7. package/dist/agent/schmancy.agent.js.map +1 -1
  8. package/dist/agent/schmancy.manifest.json +335 -276
  9. package/dist/{area-DviXdbDx.js → area-BA96mwFY.js} +2 -2
  10. package/dist/{area-DviXdbDx.js.map → area-BA96mwFY.js.map} +1 -1
  11. package/dist/{area-CTSTgjlx.cjs → area-DtyQDdOF.cjs} +1 -1
  12. package/dist/{area-CTSTgjlx.cjs.map → area-DtyQDdOF.cjs.map} +1 -1
  13. package/dist/area.cjs +1 -1
  14. package/dist/area.js +1 -1
  15. package/dist/{audio-Q9oB_cQR.cjs → audio-B_jT9Xr7.cjs} +1 -1
  16. package/dist/{audio-Q9oB_cQR.cjs.map → audio-B_jT9Xr7.cjs.map} +1 -1
  17. package/dist/{audio-DFYoaw0M.js → audio-D52h1jAT.js} +1 -1
  18. package/dist/{audio-DFYoaw0M.js.map → audio-D52h1jAT.js.map} +1 -1
  19. package/dist/audio.cjs +1 -1
  20. package/dist/audio.js +2 -2
  21. package/dist/{autocomplete-DmLXJr7C.cjs → autocomplete-Bts5Jwwr.cjs} +1 -1
  22. package/dist/{autocomplete-DmLXJr7C.cjs.map → autocomplete-Bts5Jwwr.cjs.map} +1 -1
  23. package/dist/{autocomplete-BDvuma6D.js → autocomplete-CI4QJXAN.js} +3 -3
  24. package/dist/{autocomplete-BDvuma6D.js.map → autocomplete-CI4QJXAN.js.map} +1 -1
  25. package/dist/autocomplete.cjs +1 -1
  26. package/dist/autocomplete.js +1 -1
  27. package/dist/avatar.cjs +1 -1
  28. package/dist/avatar.js +3 -3
  29. package/dist/badge.cjs +1 -1
  30. package/dist/badge.js +1 -1
  31. package/dist/boat-I4B1UNMc.cjs +34 -0
  32. package/dist/boat-I4B1UNMc.cjs.map +1 -0
  33. package/dist/boat-_N1x5U_3.js +191 -0
  34. package/dist/boat-_N1x5U_3.js.map +1 -0
  35. package/dist/boat.cjs +1 -1
  36. package/dist/boat.js +1 -1
  37. package/dist/breadcrumb.cjs +1 -1
  38. package/dist/breadcrumb.js +2 -2
  39. package/dist/{busy-CgzZbGfx.cjs → busy-BIUonyPk.cjs} +1 -1
  40. package/dist/{busy-CgzZbGfx.cjs.map → busy-BIUonyPk.cjs.map} +1 -1
  41. package/dist/{busy-DgQ4ux5N.js → busy-CCB3qKnh.js} +2 -2
  42. package/dist/{busy-DgQ4ux5N.js.map → busy-CCB3qKnh.js.map} +1 -1
  43. package/dist/busy.cjs +1 -1
  44. package/dist/busy.js +1 -1
  45. package/dist/{button-qbN1muQ0.js → button-C89bPnHt.js} +2 -2
  46. package/dist/{button-qbN1muQ0.js.map → button-C89bPnHt.js.map} +1 -1
  47. package/dist/{button-DFvR1iXX.cjs → button-CkwQH-g3.cjs} +1 -1
  48. package/dist/{button-DFvR1iXX.cjs.map → button-CkwQH-g3.cjs.map} +1 -1
  49. package/dist/button.cjs +4 -4
  50. package/dist/button.cjs.map +1 -1
  51. package/dist/button.js +16 -22
  52. package/dist/button.js.map +1 -1
  53. package/dist/{card-D_GlwZ5q.cjs → card-BO93_oxQ.cjs} +1 -1
  54. package/dist/{card-D_GlwZ5q.cjs.map → card-BO93_oxQ.cjs.map} +1 -1
  55. package/dist/{card-DAbr-7Vy.js → card-CFsCgJKZ.js} +2 -2
  56. package/dist/{card-DAbr-7Vy.js.map → card-CFsCgJKZ.js.map} +1 -1
  57. package/dist/card.cjs +1 -1
  58. package/dist/card.js +1 -1
  59. package/dist/{checkbox-BNORaxMF.js → checkbox-Bh7q0djq.js} +2 -2
  60. package/dist/{checkbox-BNORaxMF.js.map → checkbox-Bh7q0djq.js.map} +1 -1
  61. package/dist/{checkbox-BUY_uc_r.cjs → checkbox-CFUBUFtW.cjs} +1 -1
  62. package/dist/{checkbox-BUY_uc_r.cjs.map → checkbox-CFUBUFtW.cjs.map} +1 -1
  63. package/dist/checkbox.cjs +1 -1
  64. package/dist/checkbox.js +1 -1
  65. package/dist/{chips-Dg6Lk6BT.js → chips-6YaoRmeG.js} +145 -122
  66. package/dist/chips-6YaoRmeG.js.map +1 -0
  67. package/dist/{chips-CXZ4dJCK.cjs → chips-BfzpsyV1.cjs} +44 -33
  68. package/dist/chips-BfzpsyV1.cjs.map +1 -0
  69. package/dist/chips.cjs +1 -1
  70. package/dist/chips.js +2 -2
  71. package/dist/connectivity.cjs +1 -1
  72. package/dist/connectivity.js +3 -3
  73. package/dist/content-drawer.cjs +1 -1
  74. package/dist/content-drawer.js +1 -1
  75. package/dist/{date-range-BU6WX7d5.js → date-range-CEo_Kjqw.js} +129 -137
  76. package/dist/date-range-CEo_Kjqw.js.map +1 -0
  77. package/dist/{date-range-C-_be3_E.cjs → date-range-N-A249O9.cjs} +25 -19
  78. package/dist/date-range-N-A249O9.cjs.map +1 -0
  79. package/dist/{date-range-inline-7o7xtVIu.js → date-range-inline-BwialV9j.js} +2 -2
  80. package/dist/{date-range-inline-7o7xtVIu.js.map → date-range-inline-BwialV9j.js.map} +1 -1
  81. package/dist/{date-range-inline-DJtUmHKF.cjs → date-range-inline-DFopysWF.cjs} +1 -1
  82. package/dist/{date-range-inline-DJtUmHKF.cjs.map → date-range-inline-DFopysWF.cjs.map} +1 -1
  83. package/dist/date-range-inline.cjs +1 -1
  84. package/dist/date-range-inline.js +1 -1
  85. package/dist/date-range.cjs +1 -1
  86. package/dist/date-range.js +1 -1
  87. package/dist/delay.cjs +1 -1
  88. package/dist/delay.js +2 -2
  89. package/dist/{details-Bs0MyyvF.cjs → details-BLRPV8sY.cjs} +1 -1
  90. package/dist/{details-Bs0MyyvF.cjs.map → details-BLRPV8sY.cjs.map} +1 -1
  91. package/dist/{details-EfbDPVEo.js → details-GtpfI2hA.js} +2 -2
  92. package/dist/{details-EfbDPVEo.js.map → details-GtpfI2hA.js.map} +1 -1
  93. package/dist/details.cjs +1 -1
  94. package/dist/details.js +1 -1
  95. package/dist/{directives-zi1Mm2er.js → directives-C2dXgpCY.js} +13 -6
  96. package/dist/directives-C2dXgpCY.js.map +1 -0
  97. package/dist/{directives-fLwDj6b0.cjs → directives-CvYGSW_a.cjs} +2 -2
  98. package/dist/directives-CvYGSW_a.cjs.map +1 -0
  99. package/dist/directives.cjs +1 -1
  100. package/dist/directives.js +2 -2
  101. package/dist/{divider-CEPfrIwe.js → divider-D0pGX2VB.js} +2 -2
  102. package/dist/{divider-CEPfrIwe.js.map → divider-D0pGX2VB.js.map} +1 -1
  103. package/dist/{divider-CdIsWZrM.cjs → divider-rNsWCvMi.cjs} +1 -1
  104. package/dist/{divider-CdIsWZrM.cjs.map → divider-rNsWCvMi.cjs.map} +1 -1
  105. package/dist/divider.cjs +1 -1
  106. package/dist/divider.js +1 -1
  107. package/dist/dropdown.cjs +1 -1
  108. package/dist/dropdown.js +2 -2
  109. package/dist/{expand-g1vqqUp1.js → expand-FcKAzJta.js} +3 -3
  110. package/dist/{expand-g1vqqUp1.js.map → expand-FcKAzJta.js.map} +1 -1
  111. package/dist/{expand--at1k3qo.cjs → expand-tffQHGbZ.cjs} +1 -1
  112. package/dist/{expand--at1k3qo.cjs.map → expand-tffQHGbZ.cjs.map} +1 -1
  113. package/dist/expand.cjs +1 -1
  114. package/dist/expand.js +1 -1
  115. package/dist/fab.cjs +77 -0
  116. package/dist/fab.cjs.map +1 -0
  117. package/dist/fab.js +151 -0
  118. package/dist/fab.js.map +1 -0
  119. package/dist/{float-P9HukAm-.cjs → float-CDjgxWyy.cjs} +1 -1
  120. package/dist/{float-P9HukAm-.cjs.map → float-CDjgxWyy.cjs.map} +1 -1
  121. package/dist/{float-DxVzgI9o.js → float-CQ1WEp3M.js} +2 -2
  122. package/dist/{float-DxVzgI9o.js.map → float-CQ1WEp3M.js.map} +1 -1
  123. package/dist/float.cjs +1 -1
  124. package/dist/float.js +1 -1
  125. package/dist/{form-CqLaozHp.js → form-H24puioV.js} +3 -3
  126. package/dist/{form-CqLaozHp.js.map → form-H24puioV.js.map} +1 -1
  127. package/dist/{form-ByYhXe1p.cjs → form-VYhbbir3.cjs} +1 -1
  128. package/dist/{form-ByYhXe1p.cjs.map → form-VYhbbir3.cjs.map} +1 -1
  129. package/dist/form.cjs +6 -6
  130. package/dist/form.cjs.map +1 -1
  131. package/dist/form.js +25 -23
  132. package/dist/form.js.map +1 -1
  133. package/dist/handover/agent-runtime-followups.md +1 -1
  134. package/dist/handover/agent-runtime-v1.md +3 -3
  135. package/dist/{icons-DYtiRU5V.cjs → icons-B_a1HStW.cjs} +1 -1
  136. package/dist/{icons-DYtiRU5V.cjs.map → icons-B_a1HStW.cjs.map} +1 -1
  137. package/dist/{icons-CkphcMp6.js → icons-DBxfN91B.js} +2 -2
  138. package/dist/{icons-CkphcMp6.js.map → icons-DBxfN91B.js.map} +1 -1
  139. package/dist/icons.cjs +1 -1
  140. package/dist/icons.js +1 -1
  141. package/dist/{iframe-CjqJksl8.js → iframe-BDVElN8z.js} +2 -2
  142. package/dist/{iframe-CjqJksl8.js.map → iframe-BDVElN8z.js.map} +1 -1
  143. package/dist/{iframe-C3trkP8q.cjs → iframe-CG-z9qev.cjs} +1 -1
  144. package/dist/{iframe-C3trkP8q.cjs.map → iframe-CG-z9qev.cjs.map} +1 -1
  145. package/dist/iframe.cjs +1 -1
  146. package/dist/iframe.js +1 -1
  147. package/dist/index.cjs +1 -1
  148. package/dist/index.js +57 -56
  149. package/dist/{input-DuavpwNL.cjs → input-B14Nn6xD.cjs} +1 -1
  150. package/dist/{input-DuavpwNL.cjs.map → input-B14Nn6xD.cjs.map} +1 -1
  151. package/dist/{input-CG51zDVh.js → input-Bt_o4sYo.js} +2 -2
  152. package/dist/{input-CG51zDVh.js.map → input-Bt_o4sYo.js.map} +1 -1
  153. package/dist/{input-chip-C6Lq1927.js → input-chip-DEqO0DXc.js} +2 -2
  154. package/dist/input-chip-DEqO0DXc.js.map +1 -0
  155. package/dist/{input-chip-57tgNXKT.cjs → input-chip-ugYu9Fn9.cjs} +1 -1
  156. package/dist/input-chip-ugYu9Fn9.cjs.map +1 -0
  157. package/dist/input.cjs +1 -1
  158. package/dist/input.js +1 -1
  159. package/dist/json.cjs +1 -1
  160. package/dist/json.js +3 -3
  161. package/dist/kbd.cjs +1 -1
  162. package/dist/kbd.js +2 -2
  163. package/dist/{layout-D4IOwx7p.js → layout-BJ_43VrH.js} +1 -1
  164. package/dist/{layout-D4IOwx7p.js.map → layout-BJ_43VrH.js.map} +1 -1
  165. package/dist/{layout-6ipbiWTl.cjs → layout-DF9ZaQ-b.cjs} +1 -1
  166. package/dist/{layout-6ipbiWTl.cjs.map → layout-DF9ZaQ-b.cjs.map} +1 -1
  167. package/dist/layout.cjs +1 -1
  168. package/dist/layout.js +2 -2
  169. package/dist/{lightbox-H8pVWGMX.cjs → lightbox-B47Zoqv-.cjs} +1 -1
  170. package/dist/{lightbox-H8pVWGMX.cjs.map → lightbox-B47Zoqv-.cjs.map} +1 -1
  171. package/dist/{lightbox-CsyO2XSr.js → lightbox-ZmuoBBFT.js} +2 -2
  172. package/dist/{lightbox-CsyO2XSr.js.map → lightbox-ZmuoBBFT.js.map} +1 -1
  173. package/dist/lightbox.cjs +1 -1
  174. package/dist/lightbox.js +1 -1
  175. package/dist/{list-BAwH0pQW.js → list-C47xzld_.js} +2 -2
  176. package/dist/{list-BAwH0pQW.js.map → list-C47xzld_.js.map} +1 -1
  177. package/dist/{list-Bs9m8kw7.cjs → list-CaSWrlG2.cjs} +1 -1
  178. package/dist/{list-Bs9m8kw7.cjs.map → list-CaSWrlG2.cjs.map} +1 -1
  179. package/dist/list.cjs +1 -1
  180. package/dist/list.js +1 -1
  181. package/dist/{menu-tQVARVaC.js → menu-8RObM6Ie.js} +3 -3
  182. package/dist/{menu-tQVARVaC.js.map → menu-8RObM6Ie.js.map} +1 -1
  183. package/dist/{menu-BMcGzj1h.cjs → menu-Jpsy85SX.cjs} +1 -1
  184. package/dist/{menu-BMcGzj1h.cjs.map → menu-Jpsy85SX.cjs.map} +1 -1
  185. package/dist/menu.cjs +1 -1
  186. package/dist/menu.js +1 -1
  187. package/dist/{mixins-CGXSzZc7.cjs → mixins-DPdzC9ZH.cjs} +1 -1
  188. package/dist/{mixins-CGXSzZc7.cjs.map → mixins-DPdzC9ZH.cjs.map} +1 -1
  189. package/dist/{mixins-Bp0wIHg2.js → mixins-DTzfFVyv.js} +1 -1
  190. package/dist/{mixins-Bp0wIHg2.js.map → mixins-DTzfFVyv.js.map} +1 -1
  191. package/dist/mixins.cjs +1 -1
  192. package/dist/mixins.js +2 -2
  193. package/dist/nav-drawer.cjs +1 -1
  194. package/dist/nav-drawer.js +1 -1
  195. package/dist/navigation-bar.cjs +1 -1
  196. package/dist/navigation-bar.js +1 -1
  197. package/dist/navigation-rail.cjs +1 -1
  198. package/dist/navigation-rail.js +2 -2
  199. package/dist/{notification-D1tX2nx5.js → notification-Ccktcj9H.js} +4 -4
  200. package/dist/{notification-D1tX2nx5.js.map → notification-Ccktcj9H.js.map} +1 -1
  201. package/dist/{notification-Bz00zdpV.cjs → notification-DSkB-sn0.cjs} +1 -1
  202. package/dist/{notification-Bz00zdpV.cjs.map → notification-DSkB-sn0.cjs.map} +1 -1
  203. package/dist/notification.cjs +1 -1
  204. package/dist/notification.js +1 -1
  205. package/dist/{option-BnybLEDO.cjs → option-0aNiVB3Q.cjs} +1 -1
  206. package/dist/{option-BnybLEDO.cjs.map → option-0aNiVB3Q.cjs.map} +1 -1
  207. package/dist/{option-BpGV8Apj.js → option-CkMxwBqU.js} +2 -2
  208. package/dist/{option-BpGV8Apj.js.map → option-CkMxwBqU.js.map} +1 -1
  209. package/dist/option.cjs +1 -1
  210. package/dist/option.js +1 -1
  211. package/dist/{overlay-UQR2Dy3u.cjs → overlay-BS-ta-zq.cjs} +5 -5
  212. package/dist/overlay-BS-ta-zq.cjs.map +1 -0
  213. package/dist/{overlay-BpNhd74N.js → overlay-H3Wt_dgQ.js} +108 -108
  214. package/dist/overlay-H3Wt_dgQ.js.map +1 -0
  215. package/dist/overlay.cjs +1 -1
  216. package/dist/{overlay.confirm-body-CVDtVk5X.cjs → overlay.confirm-body-CR9xaqOE.cjs} +1 -1
  217. package/dist/{overlay.confirm-body-CVDtVk5X.cjs.map → overlay.confirm-body-CR9xaqOE.cjs.map} +1 -1
  218. package/dist/{overlay.confirm-body-BHcXu5Wk.js → overlay.confirm-body-Dxn_wNm3.js} +6 -6
  219. package/dist/{overlay.confirm-body-BHcXu5Wk.js.map → overlay.confirm-body-Dxn_wNm3.js.map} +1 -1
  220. package/dist/overlay.js +3 -3
  221. package/dist/{overlay.service-DTE6NwIM.js → overlay.service-C46kOtUi.js} +2 -2
  222. package/dist/{overlay.service-DTE6NwIM.js.map → overlay.service-C46kOtUi.js.map} +1 -1
  223. package/dist/{overlay.service-C8RsQzgM.cjs → overlay.service-DEj3rfRr.cjs} +1 -1
  224. package/dist/{overlay.service-C8RsQzgM.cjs.map → overlay.service-DEj3rfRr.cjs.map} +1 -1
  225. package/dist/{progress-CAKsxp29.js → progress-BK7gSq8j.js} +2 -2
  226. package/dist/{progress-CAKsxp29.js.map → progress-BK7gSq8j.js.map} +1 -1
  227. package/dist/{progress-gbIALDRs.cjs → progress-zs18GR6C.cjs} +1 -1
  228. package/dist/{progress-gbIALDRs.cjs.map → progress-zs18GR6C.cjs.map} +1 -1
  229. package/dist/progress.cjs +1 -1
  230. package/dist/progress.js +1 -1
  231. package/dist/{radio-group-otyvZvUk.js → radio-group-1HCpzRUB.js} +2 -2
  232. package/dist/{radio-group-otyvZvUk.js.map → radio-group-1HCpzRUB.js.map} +1 -1
  233. package/dist/{radio-group-CfJ5DtI4.cjs → radio-group-DbYlyPc-.cjs} +1 -1
  234. package/dist/{radio-group-CfJ5DtI4.cjs.map → radio-group-DbYlyPc-.cjs.map} +1 -1
  235. package/dist/radio-group.cjs +1 -1
  236. package/dist/radio-group.js +1 -1
  237. package/dist/range.cjs +1 -1
  238. package/dist/range.js +2 -2
  239. package/dist/{select-81jniVTs.cjs → select-B-SSmUDe.cjs} +1 -1
  240. package/dist/{select-81jniVTs.cjs.map → select-B-SSmUDe.cjs.map} +1 -1
  241. package/dist/{select-9vXx1fhr.js → select-CEyhNtZ2.js} +3 -3
  242. package/dist/{select-9vXx1fhr.js.map → select-CEyhNtZ2.js.map} +1 -1
  243. package/dist/select.cjs +1 -1
  244. package/dist/select.js +1 -1
  245. package/dist/skeleton.cjs +1 -1
  246. package/dist/skeleton.js +2 -2
  247. package/dist/skills/INDEX.md +1 -1
  248. package/dist/skills/SKILL.md +6 -7
  249. package/dist/skills/boat.md +21 -15
  250. package/dist/skills/fab.md +75 -0
  251. package/dist/skills/schmancy/INDEX.md +1 -1
  252. package/dist/skills/schmancy/SKILL.md +6 -7
  253. package/dist/skills/schmancy/boat.md +21 -15
  254. package/dist/skills/schmancy/fab.md +75 -0
  255. package/dist/skills/schmancy/theme.md +1 -1
  256. package/dist/skills/theme.md +1 -1
  257. package/dist/slider.cjs +1 -1
  258. package/dist/slider.js +2 -2
  259. package/dist/{sound.service-D3ZSq1Kj.js → sound.service-DO4SmUUT.js} +1 -1
  260. package/dist/{sound.service-D3ZSq1Kj.js.map → sound.service-DO4SmUUT.js.map} +1 -1
  261. package/dist/{sound.service-CmIw63aM.cjs → sound.service-G_8GV_6L.cjs} +1 -1
  262. package/dist/{sound.service-CmIw63aM.cjs.map → sound.service-G_8GV_6L.cjs.map} +1 -1
  263. package/dist/{splash-screen-BOjrmGLk.js → splash-screen-B1mM4_xz.js} +2 -2
  264. package/dist/{splash-screen-BOjrmGLk.js.map → splash-screen-B1mM4_xz.js.map} +1 -1
  265. package/dist/{splash-screen-C5KAWXvA.cjs → splash-screen-cbz4bxjB.cjs} +1 -1
  266. package/dist/{splash-screen-C5KAWXvA.cjs.map → splash-screen-cbz4bxjB.cjs.map} +1 -1
  267. package/dist/splash-screen.cjs +1 -1
  268. package/dist/splash-screen.js +1 -1
  269. package/dist/{src-Bm1vop0l.cjs → src-czeiuT1m.cjs} +1 -1
  270. package/dist/{src-Bm1vop0l.cjs.map → src-czeiuT1m.cjs.map} +1 -1
  271. package/dist/{src-DoOhMBtI.js → src-tncsWsTY.js} +36 -35
  272. package/dist/{src-DoOhMBtI.js.map → src-tncsWsTY.js.map} +1 -1
  273. package/dist/{state-Cex3rmx2.cjs → state-Cx0aoL5e.cjs} +1 -1
  274. package/dist/{state-Cex3rmx2.cjs.map → state-Cx0aoL5e.cjs.map} +1 -1
  275. package/dist/{state-CWBRTSvE.js → state-DJDp3N7J.js} +1 -1
  276. package/dist/{state-CWBRTSvE.js.map → state-DJDp3N7J.js.map} +1 -1
  277. package/dist/state.cjs +1 -1
  278. package/dist/state.js +2 -2
  279. package/dist/steps.cjs +1 -1
  280. package/dist/steps.js +2 -2
  281. package/dist/{surface-PfiejLuw.cjs → surface-C3cxTcJD.cjs} +1 -1
  282. package/dist/{surface-PfiejLuw.cjs.map → surface-C3cxTcJD.cjs.map} +1 -1
  283. package/dist/{surface-9S5scTsD.js → surface-CYBl8_a3.js} +2 -2
  284. package/dist/{surface-9S5scTsD.js.map → surface-CYBl8_a3.js.map} +1 -1
  285. package/dist/surface.cjs +1 -1
  286. package/dist/surface.js +1 -1
  287. package/dist/switch.cjs +1 -1
  288. package/dist/switch.js +2 -2
  289. package/dist/table.cjs +1 -1
  290. package/dist/table.js +2 -2
  291. package/dist/{tabs-BBOjAmgG.js → tabs-DHy93Q3N.js} +2 -2
  292. package/dist/{tabs-BBOjAmgG.js.map → tabs-DHy93Q3N.js.map} +1 -1
  293. package/dist/{tabs-uYvb1P06.cjs → tabs-ORQ_Zd43.cjs} +1 -1
  294. package/dist/{tabs-uYvb1P06.cjs.map → tabs-ORQ_Zd43.cjs.map} +1 -1
  295. package/dist/tabs.cjs +1 -1
  296. package/dist/tabs.js +1 -1
  297. package/dist/teleport.cjs +1 -1
  298. package/dist/teleport.js +1 -1
  299. package/dist/{textarea-YPHX4g7Y.cjs → textarea-CEUaDURR.cjs} +1 -1
  300. package/dist/{textarea-YPHX4g7Y.cjs.map → textarea-CEUaDURR.cjs.map} +1 -1
  301. package/dist/{textarea-QzSj8Dkl.js → textarea-DHIMt-ly.js} +2 -2
  302. package/dist/{textarea-QzSj8Dkl.js.map → textarea-DHIMt-ly.js.map} +1 -1
  303. package/dist/textarea.cjs +1 -1
  304. package/dist/textarea.js +1 -1
  305. package/dist/theme-CJpjkqHr.cjs +181 -0
  306. package/dist/{theme-iKUaS9JB.cjs.map → theme-CJpjkqHr.cjs.map} +1 -1
  307. package/dist/{theme-C2Mp-VGt.js → theme-CgI9PRco.js} +6 -5
  308. package/dist/{theme-C2Mp-VGt.js.map → theme-CgI9PRco.js.map} +1 -1
  309. package/dist/{theme-button-CJmhxfMe.cjs → theme-button--FuBkuVr.cjs} +1 -1
  310. package/dist/{theme-button-CJmhxfMe.cjs.map → theme-button--FuBkuVr.cjs.map} +1 -1
  311. package/dist/{theme-button-DGWAXhzd.js → theme-button-D-FXb3oO.js} +2 -2
  312. package/dist/{theme-button-DGWAXhzd.js.map → theme-button-D-FXb3oO.js.map} +1 -1
  313. package/dist/theme-button.cjs +1 -1
  314. package/dist/theme-button.js +1 -1
  315. package/dist/theme.cjs +1 -1
  316. package/dist/theme.js +3 -3
  317. package/dist/{theme.service-hc4N-1Oz.js → theme.service-BfTK1Wtl.js} +1 -1
  318. package/dist/{theme.service-hc4N-1Oz.js.map → theme.service-BfTK1Wtl.js.map} +1 -1
  319. package/dist/{theme.service-p61RsJBF.cjs → theme.service-Dg7LO0Qz.cjs} +1 -1
  320. package/dist/{theme.service-p61RsJBF.cjs.map → theme.service-Dg7LO0Qz.cjs.map} +1 -1
  321. package/dist/tree.cjs +1 -1
  322. package/dist/tree.js +2 -2
  323. package/dist/{typography-DwV0sqht.js → typography-BEGLfHwz.js} +2 -2
  324. package/dist/{typography-DwV0sqht.js.map → typography-BEGLfHwz.js.map} +1 -1
  325. package/dist/{typography-Bdt8RlX2.cjs → typography-CxA3sx9B.cjs} +1 -1
  326. package/dist/{typography-Bdt8RlX2.cjs.map → typography-CxA3sx9B.cjs.map} +1 -1
  327. package/dist/typography.cjs +1 -1
  328. package/dist/typography.js +1 -1
  329. package/dist/visually-hidden.cjs +1 -1
  330. package/dist/visually-hidden.js +2 -2
  331. package/dist/{window-n4jN60B_.js → window-B_n4P9az.js} +3 -3
  332. package/dist/{window-n4jN60B_.js.map → window-B_n4P9az.js.map} +1 -1
  333. package/dist/{window-D2WfvNng.cjs → window-Vl1u1-EG.cjs} +1 -1
  334. package/dist/{window-D2WfvNng.cjs.map → window-Vl1u1-EG.cjs.map} +1 -1
  335. package/dist/window.cjs +1 -1
  336. package/dist/window.js +1 -1
  337. package/package.json +1 -1
  338. package/skills/schmancy/INDEX.md +1 -1
  339. package/skills/schmancy/SKILL.md +6 -7
  340. package/skills/schmancy/boat.md +21 -15
  341. package/skills/schmancy/fab.md +75 -0
  342. package/skills/schmancy/theme.md +1 -1
  343. package/src/CLAUDE.md +22 -16
  344. package/src/boat/boat.test.ts +130 -0
  345. package/src/boat/boat.ts +192 -186
  346. package/src/button/icon-button.ts +18 -30
  347. package/src/chips/assist-chip.ts +2 -263
  348. package/src/chips/chips.ts +2 -259
  349. package/src/chips/filter-chip.ts +2 -255
  350. package/src/chips/index.ts +2 -5
  351. package/src/chips/input-chip.ts +2 -413
  352. package/src/chips/suggestion-chip.ts +2 -266
  353. package/src/directives/fill.ts +28 -5
  354. package/src/fab/fab.test.ts +101 -0
  355. package/src/fab/fab.ts +226 -0
  356. package/src/fab/index.ts +1 -0
  357. package/src/form/fields/chips/assist-chip.ts +263 -0
  358. package/src/form/fields/chips/chips.ts +234 -0
  359. package/src/form/fields/chips/filter-chip.ts +255 -0
  360. package/src/form/fields/chips/index.ts +5 -0
  361. package/src/form/fields/chips/input-chip.ts +413 -0
  362. package/src/form/fields/chips/suggestion-chip.ts +266 -0
  363. package/src/form/fields/date-range/date-range.test.ts +44 -0
  364. package/src/form/fields/date-range/date-range.ts +103 -97
  365. package/src/form/fields/index.ts +1 -0
  366. package/src/index.ts +2 -1
  367. package/src/overlay/overlay.animations.ts +2 -3
  368. package/src/overlay/overlay.component.ts +8 -4
  369. package/src/overlay/overlay.types.ts +14 -2
  370. package/src/theme/theme.component.ts +1 -0
  371. package/src/theme/theme.style.css +3 -0
  372. package/types/src/boat/boat.d.ts +40 -25
  373. package/types/src/boat/boat.test.d.ts +2 -0
  374. package/types/src/button/icon-button.d.ts +3 -2
  375. package/types/src/chips/assist-chip.d.ts +1 -47
  376. package/types/src/chips/chips.d.ts +1 -43
  377. package/types/src/chips/filter-chip.d.ts +1 -67
  378. package/types/src/chips/index.d.ts +1 -5
  379. package/types/src/chips/input-chip.d.ts +1 -82
  380. package/types/src/chips/suggestion-chip.d.ts +1 -52
  381. package/types/src/fab/fab.d.ts +80 -0
  382. package/types/src/fab/fab.test.d.ts +2 -0
  383. package/types/src/fab/index.d.ts +1 -0
  384. package/types/src/form/fields/chips/assist-chip.d.ts +47 -0
  385. package/types/src/form/fields/chips/chips.d.ts +35 -0
  386. package/types/src/form/fields/chips/filter-chip.d.ts +67 -0
  387. package/types/src/form/fields/chips/index.d.ts +5 -0
  388. package/types/src/form/fields/chips/input-chip.d.ts +82 -0
  389. package/types/src/form/fields/chips/suggestion-chip.d.ts +52 -0
  390. package/types/src/form/fields/date-range/date-range.d.ts +5 -10
  391. package/types/src/form/fields/index.d.ts +1 -0
  392. package/types/src/index.d.ts +2 -1
  393. package/types/src/overlay/overlay.component.d.ts +1 -0
  394. package/types/src/overlay/overlay.types.d.ts +12 -2
  395. package/types/src/theme/theme.component.d.ts +1 -0
  396. package/dist/SchmancyElement-CA0Wqt8m.js +0 -284
  397. package/dist/SchmancyElement-CA0Wqt8m.js.map +0 -1
  398. package/dist/SchmancyElement-CYIif26I.cjs +0 -2
  399. package/dist/SchmancyElement-CYIif26I.cjs.map +0 -1
  400. package/dist/boat-BgpWcLnV.cjs +0 -38
  401. package/dist/boat-BgpWcLnV.cjs.map +0 -1
  402. package/dist/boat-Y5UMiJCV.js +0 -216
  403. package/dist/boat-Y5UMiJCV.js.map +0 -1
  404. package/dist/chips-CXZ4dJCK.cjs.map +0 -1
  405. package/dist/chips-Dg6Lk6BT.js.map +0 -1
  406. package/dist/date-range-BU6WX7d5.js.map +0 -1
  407. package/dist/date-range-C-_be3_E.cjs.map +0 -1
  408. package/dist/directives-fLwDj6b0.cjs.map +0 -1
  409. package/dist/directives-zi1Mm2er.js.map +0 -1
  410. package/dist/input-chip-57tgNXKT.cjs.map +0 -1
  411. package/dist/input-chip-C6Lq1927.js.map +0 -1
  412. package/dist/overlay-BpNhd74N.js.map +0 -1
  413. package/dist/overlay-UQR2Dy3u.cjs.map +0 -1
  414. package/dist/theme-iKUaS9JB.cjs +0 -181
@@ -0,0 +1,266 @@
1
+ import { SchmancyElement } from '@mixins/index'
2
+ import { css, html, LitElement } from 'lit'
3
+ import { customElement, property, state } from 'lit/decorators.js'
4
+ import { classMap } from 'lit/directives/class-map.js'
5
+ import { BehaviorSubject, combineLatest } from 'rxjs'
6
+ import { takeUntil } from 'rxjs/operators'
7
+
8
+ /**
9
+ * Suggestion chip component - provides contextual recommendations to users
10
+ *
11
+ * IMPORTANT: Suggestion chips do NOT have a selected state. They are designed to
12
+ * provide suggestions and recommendations that trigger actions when clicked.
13
+ * Unlike filter chips, they cannot be toggled on/off.
14
+ *
15
+ * Pure Schmancy implementation with Tailwind CSS and RxJS state management
16
+ */
17
+ @customElement('schmancy-suggestion-chip')
18
+ export class SchmancySuggestionChip extends SchmancyElement {
19
+ static styles = [css`
20
+ :host {
21
+ display: inline-block;
22
+ outline: none;
23
+ width: fit-content;
24
+ min-width: fit-content;
25
+ }
26
+
27
+ :host([disabled]) {
28
+ pointer-events: none;
29
+ }
30
+
31
+ .ripple {
32
+ position: absolute;
33
+ border-radius: 50%;
34
+ transform: scale(0);
35
+ animation: ripple 600ms linear;
36
+ background-color: rgba(0, 0, 0, 0.08);
37
+ pointer-events: none;
38
+ }
39
+
40
+ @keyframes ripple {
41
+ to {
42
+ transform: scale(4);
43
+ opacity: 0;
44
+ }
45
+ }
46
+
47
+ /* State layer for M3 hover/focus/pressed states */
48
+ .state-layer {
49
+ position: absolute;
50
+ inset: 0;
51
+ border-radius: inherit;
52
+ pointer-events: none;
53
+ background-color: currentColor;
54
+ opacity: 0;
55
+ transition: opacity 200ms ease;
56
+ }
57
+
58
+ :host(:not([disabled])) button:hover .state-layer {
59
+ opacity: 0.08;
60
+ }
61
+
62
+ :host(:not([disabled])) button:focus-visible .state-layer {
63
+ opacity: 0.1;
64
+ }
65
+
66
+ :host(:not([disabled])) button:active .state-layer {
67
+ opacity: 0.1;
68
+ }
69
+ `];
70
+ /** Value identifier for the chip */
71
+ @property({ reflect: true }) value = ''
72
+
73
+ /** Optional icon name (Material Symbols) */
74
+ @property({ reflect: true }) icon = ''
75
+
76
+ /** Optional href for navigation */
77
+ @property({ reflect: true }) href = ''
78
+
79
+ /** Target for navigation (e.g., '_blank') */
80
+ @property({ reflect: true }) target = ''
81
+
82
+ /** Disable the chip */
83
+ @property({ type: Boolean, reflect: true }) disabled = false
84
+
85
+ /** Elevated style variant - flat by default per M3 spec */
86
+ @property({ type: Boolean, reflect: true }) elevated = false
87
+
88
+ // RxJS state streams
89
+ private hover$ = new BehaviorSubject<boolean>(false)
90
+ private pressed$ = new BehaviorSubject<boolean>(false)
91
+ private focused$ = new BehaviorSubject<boolean>(false)
92
+
93
+ // UI state - only ripples needed for rendering
94
+ @state() private ripples: Array<{ x: number; y: number; id: number }> = []
95
+
96
+ protected static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }
97
+
98
+ private nextRippleId = 0
99
+
100
+ connectedCallback() {
101
+ super.connectedCallback()
102
+
103
+ // Stream management for future extensions
104
+ // Currently, states are handled directly in event handlers
105
+ // This pipeline can be extended for more complex state interactions
106
+ combineLatest([
107
+ this.hover$,
108
+ this.pressed$,
109
+ this.focused$
110
+ ]).pipe(
111
+ // States are managed through event handlers directly
112
+ // This pipeline is kept for potential future state combinations
113
+ takeUntil(this.disconnecting)
114
+ ).subscribe()
115
+ }
116
+
117
+ private handleClick = (e: MouseEvent) => {
118
+ if (this.disabled) return
119
+
120
+ // Add ripple effect
121
+ const button = this.shadowRoot?.querySelector('button')
122
+ if (button) {
123
+ const rect = button.getBoundingClientRect()
124
+ const x = e.clientX - rect.left
125
+ const y = e.clientY - rect.top
126
+ const id = this.nextRippleId++
127
+
128
+ this.ripples = [...this.ripples, { x, y, id }]
129
+
130
+ // Remove ripple after animation
131
+ setTimeout(() => {
132
+ this.ripples = this.ripples.filter(r => r.id !== id)
133
+ }, 600)
134
+ }
135
+
136
+ // Navigate if href is provided
137
+ if (this.href) {
138
+ if (this.target === '_blank') {
139
+ window.open(this.href, '_blank')
140
+ } else {
141
+ window.location.href = this.href
142
+ }
143
+ }
144
+
145
+ // Dispatch action event
146
+ this.dispatchEvent(new CustomEvent('action', {
147
+ detail: { value: this.value },
148
+ bubbles: true,
149
+ composed: true
150
+ }))
151
+ }
152
+
153
+ private handleKeyDown = (e: KeyboardEvent) => {
154
+ if (this.disabled) return
155
+
156
+ if (e.key === 'Enter' || e.key === ' ') {
157
+ e.preventDefault()
158
+ this.pressed$.next(true)
159
+
160
+ // Simulate click
161
+ const clickEvent = new MouseEvent('click', {
162
+ bubbles: true,
163
+ cancelable: true,
164
+ clientX: 0,
165
+ clientY: 0
166
+ })
167
+ this.handleClick(clickEvent)
168
+
169
+ setTimeout(() => this.pressed$.next(false), 100)
170
+ }
171
+ }
172
+
173
+ private handleFocus = () => {
174
+ this.focused$.next(true)
175
+ }
176
+
177
+ private handleBlur = () => {
178
+ this.focused$.next(false)
179
+ }
180
+
181
+ protected render(): unknown {
182
+ const hasIcon = !!this.icon;
183
+
184
+ const classes = {
185
+ 'relative': true,
186
+ 'inline-flex': true,
187
+ 'items-center': true,
188
+ 'gap-2': true,
189
+ 'h-8': true, // M3: 32px height
190
+ 'min-h-[32px]': true,
191
+ 'rounded-full': true,
192
+ 'cursor-pointer': !this.disabled,
193
+ 'transition-all': true,
194
+ 'duration-200': true,
195
+ 'select-none': true,
196
+ 'overflow-hidden': true,
197
+
198
+ // M3 Padding: 8px with icon, 16px without (leading), 16px trailing
199
+ 'pl-2': hasIcon, // 8px with icon
200
+ 'pl-4': !hasIcon, // 16px without icon
201
+ 'pr-4': true, // 16px trailing
202
+
203
+ // M3 Colors for suggestion chips
204
+ 'bg-surface-containerLow': true,
205
+ 'text-surface-onVariant': true,
206
+
207
+ // Suggestion chips are flat by default (no elevation per M3)
208
+
209
+ // Focus state
210
+ 'focus-visible:outline': !this.disabled,
211
+ 'focus-visible:outline-2': !this.disabled,
212
+ 'focus-visible:outline-primary': !this.disabled,
213
+ 'focus-visible:outline-offset-2': !this.disabled,
214
+
215
+ // Disabled
216
+ 'opacity-38': this.disabled, // M3 disabled opacity
217
+ 'cursor-not-allowed': this.disabled
218
+ }
219
+
220
+ return html`
221
+ <button
222
+ type="button"
223
+ class=${classMap(classes)}
224
+ ?disabled=${this.disabled}
225
+ @click=${this.handleClick}
226
+ @keydown=${this.handleKeyDown}
227
+ @mouseenter=${() => this.hover$.next(true)}
228
+ @mouseleave=${() => this.hover$.next(false)}
229
+ @mousedown=${() => this.pressed$.next(true)}
230
+ @mouseup=${() => this.pressed$.next(false)}
231
+ @focus=${this.handleFocus}
232
+ @blur=${this.handleBlur}
233
+ tabindex=${this.disabled ? '-1' : '0'}
234
+ role="button"
235
+ aria-disabled=${this.disabled}
236
+ aria-label=${this.value}
237
+ >
238
+ ${this.icon ? html`
239
+ <schmancy-icon class="text-[18px] shrink-0">${this.icon}</schmancy-icon>
240
+ ` : ''}
241
+ <span class="text-sm font-medium leading-5">
242
+ <slot></slot>
243
+ </span>
244
+
245
+ <!-- Ripple effects -->
246
+ ${this.ripples.map(ripple => html`
247
+ <span
248
+ class="ripple"
249
+ style="left: ${ripple.x}px; top: ${ripple.y}px;"
250
+ ></span>
251
+ `)}
252
+
253
+ <!-- State layer for M3 hover/focus/pressed states -->
254
+ <div class="state-layer"></div>
255
+ </button>
256
+ `
257
+ }
258
+ }
259
+
260
+ declare global {
261
+ interface HTMLElementTagNameMap {
262
+ 'schmancy-suggestion-chip': SchmancySuggestionChip
263
+ }
264
+ }
265
+
266
+ export type SuggestionChipActionEvent = { value: string }
@@ -68,6 +68,50 @@ describe('schmancy-date-range', () => {
68
68
  expect(form.checkValidity()).toBe(true)
69
69
  })
70
70
 
71
+ it('paints both validity surfaces when required, empty, and submitted', async () => {
72
+ host.innerHTML = `<form><schmancy-date-range name="w" required></schmancy-date-range></form>`
73
+ const form = host.querySelector('form') as HTMLFormElement
74
+ const dr = host.querySelector('schmancy-date-range') as HTMLElement & {
75
+ dateFrom: { label: string; value: string }
76
+ dateTo: { label: string; value: string }
77
+ markSubmitted(): void
78
+ checkValidity(): boolean
79
+ }
80
+ await nextUpdate()
81
+ await nextUpdate()
82
+ dr.dateFrom = { label: 'From', value: '' }
83
+ dr.dateTo = { label: 'To', value: '' }
84
+ await nextUpdate()
85
+
86
+ // Platform surface: the form blocks submit.
87
+ expect(form.checkValidity()).toBe(false)
88
+
89
+ // Rendered surface is gated until submit (validateOn default 'dirty').
90
+ dr.markSubmitted()
91
+ dr.checkValidity()
92
+ await nextUpdate()
93
+ await nextUpdate()
94
+
95
+ const root = (dr as unknown as { shadowRoot: ShadowRoot }).shadowRoot
96
+ const alert = root.querySelector('[role="alert"]')
97
+ expect(alert, 'a role=alert message must render').not.toBeNull()
98
+ expect(alert?.textContent?.trim()).toBe('Please select a date range.')
99
+ // Control itself carries a visible invalid treatment.
100
+ expect(
101
+ root.querySelector('section.outline-error-default'),
102
+ 'the control must carry an invalid treatment',
103
+ ).not.toBeNull()
104
+
105
+ // Filling the range clears both surfaces.
106
+ dr.dateFrom = { label: 'From', value: '2026-01-01' }
107
+ dr.dateTo = { label: 'To', value: '2026-01-31' }
108
+ await nextUpdate()
109
+ await nextUpdate()
110
+ expect(form.checkValidity()).toBe(true)
111
+ expect(root.querySelector('[role="alert"]')).toBeNull()
112
+ expect(root.querySelector('section.outline-error-default')).toBeNull()
113
+ })
114
+
71
115
  it('has no axe-core a11y violations', async () => {
72
116
  host.innerHTML = `<schmancy-date-range name="window"></schmancy-date-range>`
73
117
  await nextUpdate()
@@ -1,8 +1,8 @@
1
1
  import dayjs from 'dayjs'
2
2
  import quarterOfYear from 'dayjs/plugin/quarterOfYear'
3
- import { html, PropertyValues } from 'lit'
3
+ import { html, nothing, PropertyValues } from 'lit'
4
4
  import { customElement, property, state } from 'lit/decorators.js'
5
- import { fromEvent, Subscription, takeUntil, timer } from 'rxjs'
5
+ import { concat, exhaustMap, finalize, fromEvent, map, merge, of, Subject, switchMap, takeUntil, tap, timer } from 'rxjs'
6
6
  import { SchmancyFormField } from '@mixins/index'
7
7
  import { show } from '../../../overlay/overlay.service'
8
8
  import { detectDateRangeType, formatDateRange } from './date-range-helpers'
@@ -55,6 +55,12 @@ export class SchmancyDateRange extends SchmancyFormField() {
55
55
  /** When true, collapses to just an icon button on mobile screens */
56
56
  @property({ type: Boolean }) collapse = false
57
57
 
58
+ // Session inputs — driven by handlers, consumed by the single pipeline
59
+ // in connectedCallback (rxjs ONE_PIPELINE_ONE_SUBSCRIBE / SESSIONS).
60
+ private readonly open$ = new Subject<MouseEvent | undefined>()
61
+ private readonly close$ = new Subject<void>()
62
+ private readonly announce$ = new Subject<string>()
63
+
58
64
  // Internal states
59
65
  @state() private isOpen = false
60
66
  @state() private selectedDateRange: string = ''
@@ -95,17 +101,71 @@ export class SchmancyDateRange extends SchmancyFormField() {
95
101
  this.updateSelectedDateRange()
96
102
  }
97
103
 
98
- // Set up global event handlers using RxJS
99
- this.setupEventHandlers()
100
- }
101
-
102
- private setupEventHandlers() {
103
- // Handle keyboard navigation
104
- fromEvent<KeyboardEvent>(document, 'keydown')
104
+ // One pipeline, one subscribe (rxjs ONE_PIPELINE_ONE_SUBSCRIBE): the
105
+ // dropdown open/close session, screen-reader announcements, and
106
+ // document keyboard navigation merge into a single chain torn down by
107
+ // takeUntil(this.disconnecting).
108
+ merge(
109
+ // Dropdown is a session (rxjs SESSIONS_USE_HIGHER_ORDER_OBSERVABLES):
110
+ // open$ opens the overlay; show() completes when an inner handler
111
+ // dispatches `close`, close$ dismisses it externally; finalize
112
+ // resets isOpen on either teardown path.
113
+ this.open$.pipe(
114
+ tap(() => {
115
+ this.dispatchEvent(new CustomEvent('beforeopen', { bubbles: true, composed: true }))
116
+ this.isOpen = true
117
+ }),
118
+ exhaustMap(anchor =>
119
+ show(
120
+ html`
121
+ <schmancy-date-range-dialog
122
+ .type="${this.type}"
123
+ .dateFrom="${this.dateFrom}"
124
+ .dateTo="${this.dateTo}"
125
+ .minDate="${this.minDate}"
126
+ .maxDate="${this.maxDate}"
127
+ .activePreset="${this.activePreset}"
128
+ .presetCategories="${this.presetCategories}"
129
+ @preset-select="${(ev: CustomEvent) => {
130
+ this.activePreset = ev.detail.preset.label
131
+ this.setDateRange(ev.detail.preset.range.dateFrom, ev.detail.preset.range.dateTo)
132
+ dispatchClose(ev.currentTarget)
133
+ }}"
134
+ @date-change="${() => this.updateSelectedDateRange()}"
135
+ @apply-dates="${(ev: CustomEvent) => {
136
+ const { dateFrom, dateTo, swapIfNeeded } = ev.detail
137
+ if (swapIfNeeded) {
138
+ this.setDateRange(dateTo, dateFrom)
139
+ } else {
140
+ this.setDateRange(dateFrom, dateTo)
141
+ }
142
+ dispatchClose(ev.currentTarget)
143
+ }}"
144
+ @announce="${(ev: CustomEvent) => this.announce$.next(ev.detail.message)}"
145
+ ></schmancy-date-range-dialog>
146
+ `,
147
+ { anchor },
148
+ ).pipe(
149
+ takeUntil(this.close$),
150
+ finalize(() => {
151
+ this.isOpen = false
152
+ }),
153
+ ),
154
+ ),
155
+ ),
156
+ // Announcements (rxjs LIFT_EVERY_ASYNC_SOURCE): one Subject, one
157
+ // switchMap-cleared timer — not a fresh timer().subscribe() per call.
158
+ this.announce$.pipe(
159
+ switchMap(message => concat(of(message), timer(100).pipe(map(() => '')))),
160
+ tap(message => {
161
+ this.announceMessage = message
162
+ }),
163
+ ),
164
+ // Document keyboard navigation.
165
+ fromEvent<KeyboardEvent>(document, 'keydown').pipe(tap(event => this.handleKeyboardNavigation(event))),
166
+ )
105
167
  .pipe(takeUntil(this.disconnecting))
106
- .subscribe(event => {
107
- this.handleKeyboardNavigation(event)
108
- })
168
+ .subscribe()
109
169
  }
110
170
 
111
171
  updated(changedProps: PropertyValues) {
@@ -182,23 +242,23 @@ export class SchmancyDateRange extends SchmancyFormField() {
182
242
  }
183
243
 
184
244
  /** `dirty` tracks the underlying date strings, not the wide-union value. */
185
- private _dateFromDefault: string = ''
186
- private _dateToDefault: string = ''
245
+ private dateFromDefault: string = ''
246
+ private dateToDefault: string = ''
187
247
  override firstUpdated(changed: PropertyValues): void {
188
248
  super.firstUpdated(changed)
189
- this._dateFromDefault = this.dateFrom?.value ?? ''
190
- this._dateToDefault = this.dateTo?.value ?? ''
249
+ this.dateFromDefault = this.dateFrom?.value ?? ''
250
+ this.dateToDefault = this.dateTo?.value ?? ''
191
251
  }
192
252
  override get dirty(): boolean {
193
253
  return (
194
- (this.dateFrom?.value ?? '') !== this._dateFromDefault ||
195
- (this.dateTo?.value ?? '') !== this._dateToDefault
254
+ (this.dateFrom?.value ?? '') !== this.dateFromDefault ||
255
+ (this.dateTo?.value ?? '') !== this.dateToDefault
196
256
  )
197
257
  }
198
258
 
199
259
  override resetForm(): void {
200
- this.dateFrom = { ...this.dateFrom, value: this._dateFromDefault }
201
- this.dateTo = { ...this.dateTo, value: this._dateToDefault }
260
+ this.dateFrom = { ...this.dateFrom, value: this.dateFromDefault }
261
+ this.dateTo = { ...this.dateTo, value: this.dateToDefault }
202
262
  super.resetForm()
203
263
  }
204
264
 
@@ -282,7 +342,7 @@ export class SchmancyDateRange extends SchmancyFormField() {
282
342
  this.updateSelectedDateRange()
283
343
 
284
344
  // Announce change to screen readers
285
- this.announceToScreenReader(`Date range updated: ${this.selectedDateRange}`)
345
+ this.announce$.next(`Date range updated: ${this.selectedDateRange}`)
286
346
 
287
347
  this.dispatchEvent(
288
348
  new CustomEvent<{ dateFrom: string; dateTo: string }>('change', {
@@ -296,72 +356,15 @@ export class SchmancyDateRange extends SchmancyFormField() {
296
356
  private toggleDropdown(e: MouseEvent) {
297
357
  e.stopPropagation()
298
358
  if (this.disabled || this.step !== undefined) return
299
-
359
+ // Drive the session pipeline (connectedCallback) — no imperative
360
+ // open/close, no manual subscription field.
300
361
  if (this.isOpen) {
301
- this.closeDropdown()
362
+ this.close$.next()
302
363
  } else {
303
- this.openDropdown(e)
364
+ this.open$.next(e)
304
365
  }
305
366
  }
306
367
 
307
- private _overlaySubscription: Subscription | null = null
308
-
309
- private openDropdown(e?: MouseEvent) {
310
- if (this.disabled || this.step !== undefined) return
311
-
312
- this.dispatchEvent(new CustomEvent('beforeopen', { bubbles: true, composed: true }))
313
- this.isOpen = true
314
-
315
- // Inline-template overlay. Inner handlers dispatch a 'close' event
316
- // from the dialog itself (via the module-scoped `dispatchClose`),
317
- // which `show()` translates into observable completion + an emission.
318
- // Layout (centered vs sheet) is chosen by the overlay system based on
319
- // viewport / anchor presence.
320
- const dialogContent = html`
321
- <schmancy-date-range-dialog
322
- .type="${this.type}"
323
- .dateFrom="${this.dateFrom}"
324
- .dateTo="${this.dateTo}"
325
- .minDate="${this.minDate}"
326
- .maxDate="${this.maxDate}"
327
- .activePreset="${this.activePreset}"
328
- .presetCategories="${this.presetCategories}"
329
- @preset-select="${(ev: CustomEvent) => {
330
- this.activePreset = ev.detail.preset.label
331
- this.setDateRange(ev.detail.preset.range.dateFrom, ev.detail.preset.range.dateTo)
332
- dispatchClose(ev.currentTarget)
333
- }}"
334
- @date-change="${() => this.updateSelectedDateRange()}"
335
- @apply-dates="${(ev: CustomEvent) => {
336
- const { dateFrom, dateTo, swapIfNeeded } = ev.detail
337
- if (swapIfNeeded) {
338
- this.setDateRange(dateTo, dateFrom)
339
- } else {
340
- this.setDateRange(dateFrom, dateTo)
341
- }
342
- dispatchClose(ev.currentTarget)
343
- }}"
344
- @announce="${(ev: CustomEvent) => this.announceToScreenReader(ev.detail.message)}"
345
- ></schmancy-date-range-dialog>
346
- `
347
-
348
- this._overlaySubscription?.unsubscribe()
349
- this._overlaySubscription = show(dialogContent, { anchor: e })
350
- .pipe(takeUntil(this.disconnecting))
351
- .subscribe({
352
- complete: () => {
353
- this.isOpen = false
354
- this._overlaySubscription = null
355
- },
356
- })
357
- }
358
-
359
- private closeDropdown() {
360
- this._overlaySubscription?.unsubscribe()
361
- this._overlaySubscription = null
362
- this.isOpen = false
363
- }
364
-
365
368
  /**
366
369
  * Shifts the date range based on the step property
367
370
  */
@@ -522,20 +525,15 @@ export class SchmancyDateRange extends SchmancyFormField() {
522
525
  return toDate.isBefore(maxDate)
523
526
  }
524
527
 
525
- /**
526
- * Announce messages to screen readers
527
- */
528
- private announceToScreenReader(message: string) {
529
- this.announceMessage = message
530
- // Clear the message after announcement
531
- timer(100)
532
- .pipe(takeUntil(this.disconnecting))
533
- .subscribe(() => {
534
- this.announceMessage = ''
535
- })
536
- }
537
528
 
538
529
  render() {
530
+ // Step 6 — validity is two surfaces: when checkValidity() has flipped
531
+ // `error` (gated by `_shouldShowError`), the control must visibly carry
532
+ // the invalid treatment AND render the message. Platform validity is
533
+ // set in checkValidity(); this paints the user-facing half.
534
+ const showError = this.error && !!this.validationMessage
535
+ const errorRing = showError ? ' rounded outline outline-2 outline-error-default' : ''
536
+
539
537
  return html`
540
538
  <div class="relative ${this.disabled ? 'opacity-60 pointer-events-none' : ''}">
541
539
  <!-- Screen reader announcements -->
@@ -545,18 +543,22 @@ export class SchmancyDateRange extends SchmancyFormField() {
545
543
 
546
544
  <!-- Collapsed: icon-only on mobile when collapse=true -->
547
545
  <schmancy-icon-button
548
- class="${this.collapse ? 'lg:hidden' : 'hidden'}"
546
+ class="${this.collapse ? 'lg:hidden' : 'hidden'}${errorRing}"
549
547
  variant="outlined"
550
548
  type="button"
549
+ aria-invalid=${showError ? 'true' : 'false'}
551
550
  aria-label="Select date range. Current: ${this.selectedDateRange || 'No date selected'}"
552
551
  @click=${(e: MouseEvent) => this.toggleDropdown(e)}
553
552
  ?disabled=${this.disabled}
554
553
  >
555
- date_range
554
+ date_range
556
555
  </schmancy-icon-button>
557
556
 
558
557
  <!-- Full UI: always visible when collapse=false, or lg+ when collapse=true -->
559
- <section @click=${(event: Event) => event.stopPropagation()} class="${this.collapse ? 'hidden lg:flex' : 'flex'}">
558
+ <section
559
+ @click=${(event: Event) => event.stopPropagation()}
560
+ aria-invalid=${showError ? 'true' : 'false'}
561
+ class="${this.collapse ? 'hidden lg:flex' : 'flex'}${errorRing}">
560
562
  <schmancy-icon-button
561
563
  type="button"
562
564
  aria-label="Previous ${this.activePreset ? this.activePreset.toLowerCase() : 'date range'}"
@@ -590,6 +592,10 @@ export class SchmancyDateRange extends SchmancyFormField() {
590
592
  arrow_right
591
593
  </schmancy-icon-button>
592
594
  </section>
595
+
596
+ ${showError
597
+ ? html`<div role="alert" class="text-error-default text-sm mt-1">${this.validationMessage}</div>`
598
+ : nothing}
593
599
  </div>
594
600
  `
595
601
  }
@@ -1,5 +1,6 @@
1
1
  export * from './autocomplete'
2
2
  export * from './checkbox'
3
+ export * from './chips'
3
4
  export * from './date-range'
4
5
  export * from './input'
5
6
  export * from './radio-group'
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@ export * from './busy';
7
7
  export * from './button';
8
8
  export * from './card';
9
9
  export * from './form/fields/checkbox';
10
- export * from './chips';
10
+ export * from './form/fields/chips';
11
11
  export * from './connectivity';
12
12
  export * from './content-drawer';
13
13
  export * from './form/fields/date-range';
@@ -19,6 +19,7 @@ export * from './discovery';
19
19
  export * from './divider';
20
20
  export * from './dropdown';
21
21
  export * from './expand';
22
+ export * from './fab';
22
23
  export * from './float';
23
24
  export * from './window';
24
25
  export * from './form';
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  DURATION_EXIT,
3
3
  getEasing,
4
- SPRING_GENTLE,
5
4
  SPRING_SMOOTH,
6
5
  SPRING_SNAPPY,
7
6
  } from '../utils/animation'
@@ -162,8 +161,8 @@ export function surfaceAnimation(layout: OverlayLayout, direction: 'in' | 'out')
162
161
  { opacity: 1, transform: 'translateY(0)' },
163
162
  ],
164
163
  options: {
165
- duration: SPRING_GENTLE.duration,
166
- easing: getEasing(SPRING_GENTLE),
164
+ duration: SPRING_SNAPPY.duration,
165
+ easing: getEasing(SPRING_SNAPPY),
167
166
  fill: 'forwards',
168
167
  },
169
168
  }
@@ -119,6 +119,7 @@ export class SchmancyOverlay extends SchmancyElement {
119
119
  @property({ type: String, reflect: true }) tier: OverlayTier = 'modal'
120
120
 
121
121
  @state() private _active = false
122
+ @state() private _full = false
122
123
 
123
124
  @query('.backdrop') private _backdrop?: HTMLDivElement
124
125
  @query('.surface') private _surface!: HTMLElement
@@ -152,6 +153,7 @@ export class SchmancyOverlay extends SchmancyElement {
152
153
  this._mounted = true
153
154
 
154
155
  this.dismissable = options.dismissable !== false
156
+ this._full = options.full ?? false
155
157
  this._rawAnchor = options.anchor
156
158
  this._anchorOriginAnchor = options.anchor
157
159
  this._resolvedAnchor = resolveAnchorRef(options.anchor)
@@ -278,13 +280,15 @@ export class SchmancyOverlay extends SchmancyElement {
278
280
  protected render(): TemplateResult {
279
281
  if (!this._active) return html``
280
282
  const baseClasses =
281
- 'surface fixed pointer-events-auto overflow-auto ' +
283
+ 'surface fixed pointer-events-auto ' +
282
284
  'bg-surface-container/85 text-surface-on backdrop-blur-md ' +
283
285
  'border border-surface-on/8'
284
286
  const layoutClasses =
285
287
  this.layout === 'sheet'
286
- ? 'left-0 right-0 bottom-0 w-full max-h-[90dvh] rounded-t-[28px] shadow-overlay'
287
- : 'max-w-[min(480px,calc(100vw-2rem))] max-h-[90dvh] rounded-3xl shadow-overlay-anchored'
288
+ ? this._full
289
+ ? 'left-0 right-0 bottom-0 w-full h-[90dvh] rounded-t-[28px] shadow-overlay flex flex-col overflow-hidden'
290
+ : 'left-0 right-0 bottom-0 w-full max-h-[90dvh] rounded-t-[28px] shadow-overlay overflow-auto'
291
+ : 'max-w-[min(480px,calc(100vw-2rem))] max-h-[90dvh] rounded-3xl shadow-overlay-anchored overflow-auto'
288
292
  return html`
289
293
  <div class="shell fixed inset-0 pointer-events-none" part="shell">
290
294
  ${when(
@@ -300,7 +304,7 @@ export class SchmancyOverlay extends SchmancyElement {
300
304
  aria-modal=${this.modal ? 'true' : 'false'}
301
305
  tabindex="-1"
302
306
  >
303
- <div id=${MOUNT_POINT_ID}></div>
307
+ <div id=${MOUNT_POINT_ID} class=${this.layout === 'sheet' && this._full ? 'flex-1 min-h-0 overflow-hidden' : ''}></div>
304
308
  </section>
305
309
  </div>
306
310
  `