@mhmo91/schmancy 0.10.35 → 0.10.37

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 (430) hide show
  1. package/custom-elements.json +1165 -1109
  2. package/dist/SchmancyElement-BHfQg3Tj.cjs +2 -0
  3. package/dist/SchmancyElement-BHfQg3Tj.cjs.map +1 -0
  4. package/dist/SchmancyElement-CDT2q1lA.js +284 -0
  5. package/dist/SchmancyElement-CDT2q1lA.js.map +1 -0
  6. package/dist/agent/schmancy.agent.js +3488 -3290
  7. package/dist/agent/schmancy.agent.js.map +1 -1
  8. package/dist/agent/schmancy.manifest.json +335 -275
  9. package/dist/{area-DviXdbDx.js → area-KtULlxuA.js} +2 -2
  10. package/dist/{area-DviXdbDx.js.map → area-KtULlxuA.js.map} +1 -1
  11. package/dist/{area-CTSTgjlx.cjs → area-fdKhYB6T.cjs} +1 -1
  12. package/dist/{area-CTSTgjlx.cjs.map → area-fdKhYB6T.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-CUMAv9D_.cjs} +1 -1
  16. package/dist/{audio-Q9oB_cQR.cjs.map → audio-CUMAv9D_.cjs.map} +1 -1
  17. package/dist/{audio-DFYoaw0M.js → audio-zIJVTo_V.js} +1 -1
  18. package/dist/{audio-DFYoaw0M.js.map → audio-zIJVTo_V.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-DEZk6wBD.cjs} +1 -1
  22. package/dist/{autocomplete-DmLXJr7C.cjs.map → autocomplete-DEZk6wBD.cjs.map} +1 -1
  23. package/dist/{autocomplete-BDvuma6D.js → autocomplete-DIScyo8Q.js} +3 -3
  24. package/dist/{autocomplete-BDvuma6D.js.map → autocomplete-DIScyo8Q.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-lr7MPZ7H.js → boat-BHPqSqJd.js} +67 -83
  32. package/dist/boat-BHPqSqJd.js.map +1 -0
  33. package/dist/boat-OBZ77exO.cjs +34 -0
  34. package/dist/boat-OBZ77exO.cjs.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-BJNsKSCM.cjs} +1 -1
  40. package/dist/{busy-CgzZbGfx.cjs.map → busy-BJNsKSCM.cjs.map} +1 -1
  41. package/dist/{busy-DgQ4ux5N.js → busy-Dut78y4L.js} +2 -2
  42. package/dist/{busy-DgQ4ux5N.js.map → busy-Dut78y4L.js.map} +1 -1
  43. package/dist/busy.cjs +1 -1
  44. package/dist/busy.js +1 -1
  45. package/dist/{button-DFvR1iXX.cjs → button-DzlHLjWO.cjs} +1 -1
  46. package/dist/{button-DFvR1iXX.cjs.map → button-DzlHLjWO.cjs.map} +1 -1
  47. package/dist/{button-qbN1muQ0.js → button-kcpPQavY.js} +2 -2
  48. package/dist/{button-qbN1muQ0.js.map → button-kcpPQavY.js.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-BLxPLqdQ.cjs} +1 -1
  54. package/dist/{card-D_GlwZ5q.cjs.map → card-BLxPLqdQ.cjs.map} +1 -1
  55. package/dist/{card-DAbr-7Vy.js → card-DxSKxCid.js} +2 -2
  56. package/dist/{card-DAbr-7Vy.js.map → card-DxSKxCid.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-B1wiM3Dv.js} +2 -2
  60. package/dist/{checkbox-BNORaxMF.js.map → checkbox-B1wiM3Dv.js.map} +1 -1
  61. package/dist/{checkbox-BUY_uc_r.cjs → checkbox-BCLkhp5G.cjs} +1 -1
  62. package/dist/{checkbox-BUY_uc_r.cjs.map → checkbox-BCLkhp5G.cjs.map} +1 -1
  63. package/dist/checkbox.cjs +1 -1
  64. package/dist/checkbox.js +1 -1
  65. package/dist/{chips-CXZ4dJCK.cjs → chips-C9dS1WKn.cjs} +44 -33
  66. package/dist/chips-C9dS1WKn.cjs.map +1 -0
  67. package/dist/{chips-Dg6Lk6BT.js → chips-vWmwqQed.js} +145 -122
  68. package/dist/chips-vWmwqQed.js.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-C-_be3_E.cjs → date-range-BV6HuvLw.cjs} +25 -19
  76. package/dist/date-range-BV6HuvLw.cjs.map +1 -0
  77. package/dist/{date-range-BU6WX7d5.js → date-range-D3ge1b4c.js} +129 -137
  78. package/dist/date-range-D3ge1b4c.js.map +1 -0
  79. package/dist/{date-range-inline-DJtUmHKF.cjs → date-range-inline-DpYgdLRv.cjs} +1 -1
  80. package/dist/{date-range-inline-DJtUmHKF.cjs.map → date-range-inline-DpYgdLRv.cjs.map} +1 -1
  81. package/dist/{date-range-inline-7o7xtVIu.js → date-range-inline-DuWQaWps.js} +2 -2
  82. package/dist/{date-range-inline-7o7xtVIu.js.map → date-range-inline-DuWQaWps.js.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-EfbDPVEo.js → details-C-GZaq3j.js} +2 -2
  90. package/dist/{details-EfbDPVEo.js.map → details-C-GZaq3j.js.map} +1 -1
  91. package/dist/{details-Bs0MyyvF.cjs → details-Dp5rLIWk.cjs} +1 -1
  92. package/dist/{details-Bs0MyyvF.cjs.map → details-Dp5rLIWk.cjs.map} +1 -1
  93. package/dist/details.cjs +1 -1
  94. package/dist/details.js +1 -1
  95. package/dist/{directives-fLwDj6b0.cjs → directives-D_l1E5H6.cjs} +3 -3
  96. package/dist/directives-D_l1E5H6.cjs.map +1 -0
  97. package/dist/{directives-zi1Mm2er.js → directives-DyS51FUh.js} +37 -21
  98. package/dist/directives-DyS51FUh.js.map +1 -0
  99. package/dist/directives.cjs +1 -1
  100. package/dist/directives.js +2 -2
  101. package/dist/{divider-CdIsWZrM.cjs → divider-CBnAmHMZ.cjs} +1 -1
  102. package/dist/{divider-CdIsWZrM.cjs.map → divider-CBnAmHMZ.cjs.map} +1 -1
  103. package/dist/{divider-CEPfrIwe.js → divider-nQffE0AD.js} +2 -2
  104. package/dist/{divider-CEPfrIwe.js.map → divider-nQffE0AD.js.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-DvTb-UPR.js} +3 -3
  110. package/dist/{expand-g1vqqUp1.js.map → expand-DvTb-UPR.js.map} +1 -1
  111. package/dist/{expand--at1k3qo.cjs → expand-mlP_3XWz.cjs} +1 -1
  112. package/dist/{expand--at1k3qo.cjs.map → expand-mlP_3XWz.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-DxVzgI9o.js → float-C-Ko0Le3.js} +2 -2
  120. package/dist/{float-DxVzgI9o.js.map → float-C-Ko0Le3.js.map} +1 -1
  121. package/dist/{float-P9HukAm-.cjs → float-C17xgMT1.cjs} +1 -1
  122. package/dist/{float-P9HukAm-.cjs.map → float-C17xgMT1.cjs.map} +1 -1
  123. package/dist/float.cjs +1 -1
  124. package/dist/float.js +1 -1
  125. package/dist/{form-ByYhXe1p.cjs → form-CwPHcQYB.cjs} +1 -1
  126. package/dist/{form-ByYhXe1p.cjs.map → form-CwPHcQYB.cjs.map} +1 -1
  127. package/dist/{form-CqLaozHp.js → form-DA0hUu2h.js} +3 -3
  128. package/dist/{form-CqLaozHp.js.map → form-DA0hUu2h.js.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-CkphcMp6.js → icons-C6UfxmHZ.js} +2 -2
  136. package/dist/{icons-CkphcMp6.js.map → icons-C6UfxmHZ.js.map} +1 -1
  137. package/dist/{icons-DYtiRU5V.cjs → icons-CW3-oMSb.cjs} +1 -1
  138. package/dist/{icons-DYtiRU5V.cjs.map → icons-CW3-oMSb.cjs.map} +1 -1
  139. package/dist/icons.cjs +1 -1
  140. package/dist/icons.js +1 -1
  141. package/dist/{iframe-CjqJksl8.js → iframe-BTjZfYyh.js} +2 -2
  142. package/dist/{iframe-CjqJksl8.js.map → iframe-BTjZfYyh.js.map} +1 -1
  143. package/dist/{iframe-C3trkP8q.cjs → iframe-wuYT2xFz.cjs} +1 -1
  144. package/dist/{iframe-C3trkP8q.cjs.map → iframe-wuYT2xFz.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-CG51zDVh.js → input-B_4g2ulO.js} +2 -2
  150. package/dist/{input-CG51zDVh.js.map → input-B_4g2ulO.js.map} +1 -1
  151. package/dist/{input-DuavpwNL.cjs → input-BrDiIT60.cjs} +1 -1
  152. package/dist/{input-DuavpwNL.cjs.map → input-BrDiIT60.cjs.map} +1 -1
  153. package/dist/{input-chip-57tgNXKT.cjs → input-chip-B-XWh4aE.cjs} +1 -1
  154. package/dist/input-chip-B-XWh4aE.cjs.map +1 -0
  155. package/dist/{input-chip-C6Lq1927.js → input-chip-BlWhOruv.js} +2 -2
  156. package/dist/input-chip-BlWhOruv.js.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-6ipbiWTl.cjs → layout-BhyIcEVu.cjs} +1 -1
  164. package/dist/{layout-6ipbiWTl.cjs.map → layout-BhyIcEVu.cjs.map} +1 -1
  165. package/dist/{layout-D4IOwx7p.js → layout-Dxit9enO.js} +1 -1
  166. package/dist/{layout-D4IOwx7p.js.map → layout-Dxit9enO.js.map} +1 -1
  167. package/dist/layout.cjs +1 -1
  168. package/dist/layout.js +2 -2
  169. package/dist/{lightbox-H8pVWGMX.cjs → lightbox-CVBogswK.cjs} +1 -1
  170. package/dist/{lightbox-H8pVWGMX.cjs.map → lightbox-CVBogswK.cjs.map} +1 -1
  171. package/dist/{lightbox-CsyO2XSr.js → lightbox-D85XAAuC.js} +2 -2
  172. package/dist/{lightbox-CsyO2XSr.js.map → lightbox-D85XAAuC.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-DOF_yVn5.js} +2 -2
  176. package/dist/{list-BAwH0pQW.js.map → list-DOF_yVn5.js.map} +1 -1
  177. package/dist/{list-Bs9m8kw7.cjs → list-nVjLskgx.cjs} +1 -1
  178. package/dist/{list-Bs9m8kw7.cjs.map → list-nVjLskgx.cjs.map} +1 -1
  179. package/dist/list.cjs +1 -1
  180. package/dist/list.js +1 -1
  181. package/dist/{menu-BMcGzj1h.cjs → menu-DqmNjLgY.cjs} +1 -1
  182. package/dist/{menu-BMcGzj1h.cjs.map → menu-DqmNjLgY.cjs.map} +1 -1
  183. package/dist/{menu-tQVARVaC.js → menu-QrAK5Uu9.js} +3 -3
  184. package/dist/{menu-tQVARVaC.js.map → menu-QrAK5Uu9.js.map} +1 -1
  185. package/dist/menu.cjs +1 -1
  186. package/dist/menu.js +1 -1
  187. package/dist/{mixins-Bp0wIHg2.js → mixins-De1zjyhy.js} +1 -1
  188. package/dist/{mixins-Bp0wIHg2.js.map → mixins-De1zjyhy.js.map} +1 -1
  189. package/dist/{mixins-CGXSzZc7.cjs → mixins-DxHpyMHA.cjs} +1 -1
  190. package/dist/{mixins-CGXSzZc7.cjs.map → mixins-DxHpyMHA.cjs.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-BtAK7NK8.js} +4 -4
  200. package/dist/{notification-D1tX2nx5.js.map → notification-BtAK7NK8.js.map} +1 -1
  201. package/dist/{notification-Bz00zdpV.cjs → notification-DYzbUb5C.cjs} +1 -1
  202. package/dist/{notification-Bz00zdpV.cjs.map → notification-DYzbUb5C.cjs.map} +1 -1
  203. package/dist/notification.cjs +1 -1
  204. package/dist/notification.js +1 -1
  205. package/dist/{option-BpGV8Apj.js → option-DHwA0miA.js} +2 -2
  206. package/dist/{option-BpGV8Apj.js.map → option-DHwA0miA.js.map} +1 -1
  207. package/dist/{option-BnybLEDO.cjs → option-DnSPa8ro.cjs} +1 -1
  208. package/dist/{option-BnybLEDO.cjs.map → option-DnSPa8ro.cjs.map} +1 -1
  209. package/dist/option.cjs +1 -1
  210. package/dist/option.js +1 -1
  211. package/dist/{overlay-UQR2Dy3u.cjs → overlay-BVkqZmoS.cjs} +5 -5
  212. package/dist/overlay-BVkqZmoS.cjs.map +1 -0
  213. package/dist/{overlay-BpNhd74N.js → overlay-Del1sBEB.js} +108 -108
  214. package/dist/overlay-Del1sBEB.js.map +1 -0
  215. package/dist/overlay.cjs +1 -1
  216. package/dist/{overlay.confirm-body-CVDtVk5X.cjs → overlay.confirm-body-BV9umTAl.cjs} +1 -1
  217. package/dist/{overlay.confirm-body-CVDtVk5X.cjs.map → overlay.confirm-body-BV9umTAl.cjs.map} +1 -1
  218. package/dist/{overlay.confirm-body-BHcXu5Wk.js → overlay.confirm-body-DSONXUzl.js} +6 -6
  219. package/dist/{overlay.confirm-body-BHcXu5Wk.js.map → overlay.confirm-body-DSONXUzl.js.map} +1 -1
  220. package/dist/overlay.js +3 -3
  221. package/dist/{overlay.service-DTE6NwIM.js → overlay.service-BTp5Oq7f.js} +2 -2
  222. package/dist/{overlay.service-DTE6NwIM.js.map → overlay.service-BTp5Oq7f.js.map} +1 -1
  223. package/dist/{overlay.service-C8RsQzgM.cjs → overlay.service-XLlrsSdA.cjs} +1 -1
  224. package/dist/{overlay.service-C8RsQzgM.cjs.map → overlay.service-XLlrsSdA.cjs.map} +1 -1
  225. package/dist/{progress-gbIALDRs.cjs → progress-DUbTL9g9.cjs} +1 -1
  226. package/dist/{progress-gbIALDRs.cjs.map → progress-DUbTL9g9.cjs.map} +1 -1
  227. package/dist/{progress-CAKsxp29.js → progress-DYA83CFU.js} +2 -2
  228. package/dist/{progress-CAKsxp29.js.map → progress-DYA83CFU.js.map} +1 -1
  229. package/dist/progress.cjs +1 -1
  230. package/dist/progress.js +1 -1
  231. package/dist/{radio-group-CfJ5DtI4.cjs → radio-group-B-ORNtvR.cjs} +1 -1
  232. package/dist/{radio-group-CfJ5DtI4.cjs.map → radio-group-B-ORNtvR.cjs.map} +1 -1
  233. package/dist/{radio-group-otyvZvUk.js → radio-group-DxX0iJBo.js} +2 -2
  234. package/dist/{radio-group-otyvZvUk.js.map → radio-group-DxX0iJBo.js.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-B9uj_u-s.cjs} +1 -1
  240. package/dist/{select-81jniVTs.cjs.map → select-B9uj_u-s.cjs.map} +1 -1
  241. package/dist/{select-9vXx1fhr.js → select-C7gkA-ab.js} +3 -3
  242. package/dist/{select-9vXx1fhr.js.map → select-C7gkA-ab.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 +20 -18
  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 +20 -18
  253. package/dist/skills/schmancy/boat.md +21 -15
  254. package/dist/skills/schmancy/fab.md +75 -0
  255. package/dist/skills/schmancy/steps.md +68 -34
  256. package/dist/skills/schmancy/theme.md +1 -1
  257. package/dist/skills/steps.md +68 -34
  258. package/dist/skills/theme.md +1 -1
  259. package/dist/slider.cjs +1 -1
  260. package/dist/slider.js +2 -2
  261. package/dist/{sound.service-CmIw63aM.cjs → sound.service-C7FDY_yD.cjs} +1 -1
  262. package/dist/{sound.service-CmIw63aM.cjs.map → sound.service-C7FDY_yD.cjs.map} +1 -1
  263. package/dist/{sound.service-D3ZSq1Kj.js → sound.service-O0232os6.js} +1 -1
  264. package/dist/{sound.service-D3ZSq1Kj.js.map → sound.service-O0232os6.js.map} +1 -1
  265. package/dist/{splash-screen-C5KAWXvA.cjs → splash-screen-DIS4odDr.cjs} +1 -1
  266. package/dist/{splash-screen-C5KAWXvA.cjs.map → splash-screen-DIS4odDr.cjs.map} +1 -1
  267. package/dist/{splash-screen-BOjrmGLk.js → splash-screen-jfE47xl0.js} +2 -2
  268. package/dist/{splash-screen-BOjrmGLk.js.map → splash-screen-jfE47xl0.js.map} +1 -1
  269. package/dist/splash-screen.cjs +1 -1
  270. package/dist/splash-screen.js +1 -1
  271. package/dist/{src-C5g3p1J5.js → src-BP3h-9d9.js} +36 -35
  272. package/dist/{src-C5g3p1J5.js.map → src-BP3h-9d9.js.map} +1 -1
  273. package/dist/{src-qzUpLbje.cjs → src-Um_pzb-U.cjs} +1 -1
  274. package/dist/{src-qzUpLbje.cjs.map → src-Um_pzb-U.cjs.map} +1 -1
  275. package/dist/{state-Cex3rmx2.cjs → state-Bj0M9a6T.cjs} +1 -1
  276. package/dist/{state-Cex3rmx2.cjs.map → state-Bj0M9a6T.cjs.map} +1 -1
  277. package/dist/{state-CWBRTSvE.js → state-DscWQpoM.js} +1 -1
  278. package/dist/{state-CWBRTSvE.js.map → state-DscWQpoM.js.map} +1 -1
  279. package/dist/state.cjs +1 -1
  280. package/dist/state.js +2 -2
  281. package/dist/steps.cjs +35 -19
  282. package/dist/steps.cjs.map +1 -1
  283. package/dist/steps.js +96 -73
  284. package/dist/steps.js.map +1 -1
  285. package/dist/{surface-9S5scTsD.js → surface-B4Wn4SOO.js} +2 -2
  286. package/dist/{surface-9S5scTsD.js.map → surface-B4Wn4SOO.js.map} +1 -1
  287. package/dist/{surface-PfiejLuw.cjs → surface-DRq6cVW6.cjs} +1 -1
  288. package/dist/{surface-PfiejLuw.cjs.map → surface-DRq6cVW6.cjs.map} +1 -1
  289. package/dist/surface.cjs +1 -1
  290. package/dist/surface.js +1 -1
  291. package/dist/switch.cjs +1 -1
  292. package/dist/switch.js +2 -2
  293. package/dist/table.cjs +1 -1
  294. package/dist/table.js +2 -2
  295. package/dist/{tabs-uYvb1P06.cjs → tabs-Ca_fbHPW.cjs} +1 -1
  296. package/dist/{tabs-uYvb1P06.cjs.map → tabs-Ca_fbHPW.cjs.map} +1 -1
  297. package/dist/{tabs-BBOjAmgG.js → tabs-CnQPo-XS.js} +2 -2
  298. package/dist/{tabs-BBOjAmgG.js.map → tabs-CnQPo-XS.js.map} +1 -1
  299. package/dist/tabs.cjs +1 -1
  300. package/dist/tabs.js +1 -1
  301. package/dist/teleport.cjs +1 -1
  302. package/dist/teleport.js +1 -1
  303. package/dist/{textarea-QzSj8Dkl.js → textarea-BvqENhTW.js} +2 -2
  304. package/dist/{textarea-QzSj8Dkl.js.map → textarea-BvqENhTW.js.map} +1 -1
  305. package/dist/{textarea-YPHX4g7Y.cjs → textarea-qr7oL8oU.cjs} +1 -1
  306. package/dist/{textarea-YPHX4g7Y.cjs.map → textarea-qr7oL8oU.cjs.map} +1 -1
  307. package/dist/textarea.cjs +1 -1
  308. package/dist/textarea.js +1 -1
  309. package/dist/theme-BSwJ2YZo.cjs +181 -0
  310. package/dist/{theme-iKUaS9JB.cjs.map → theme-BSwJ2YZo.cjs.map} +1 -1
  311. package/dist/{theme-C2Mp-VGt.js → theme-BV0EzHQ1.js} +6 -5
  312. package/dist/{theme-C2Mp-VGt.js.map → theme-BV0EzHQ1.js.map} +1 -1
  313. package/dist/{theme-button-CJmhxfMe.cjs → theme-button-C6fpUzPM.cjs} +1 -1
  314. package/dist/{theme-button-CJmhxfMe.cjs.map → theme-button-C6fpUzPM.cjs.map} +1 -1
  315. package/dist/{theme-button-DGWAXhzd.js → theme-button-O_xNCgI7.js} +2 -2
  316. package/dist/{theme-button-DGWAXhzd.js.map → theme-button-O_xNCgI7.js.map} +1 -1
  317. package/dist/theme-button.cjs +1 -1
  318. package/dist/theme-button.js +1 -1
  319. package/dist/theme.cjs +1 -1
  320. package/dist/theme.js +3 -3
  321. package/dist/{theme.service-hc4N-1Oz.js → theme.service-DwLhhOmP.js} +1 -1
  322. package/dist/{theme.service-hc4N-1Oz.js.map → theme.service-DwLhhOmP.js.map} +1 -1
  323. package/dist/{theme.service-p61RsJBF.cjs → theme.service-kn9MC025.cjs} +1 -1
  324. package/dist/{theme.service-p61RsJBF.cjs.map → theme.service-kn9MC025.cjs.map} +1 -1
  325. package/dist/tree.cjs +1 -1
  326. package/dist/tree.js +2 -2
  327. package/dist/{typography-DwV0sqht.js → typography-Dtdooaic.js} +2 -2
  328. package/dist/{typography-DwV0sqht.js.map → typography-Dtdooaic.js.map} +1 -1
  329. package/dist/{typography-Bdt8RlX2.cjs → typography-opFYuUYS.cjs} +1 -1
  330. package/dist/{typography-Bdt8RlX2.cjs.map → typography-opFYuUYS.cjs.map} +1 -1
  331. package/dist/typography.cjs +1 -1
  332. package/dist/typography.js +1 -1
  333. package/dist/visually-hidden.cjs +1 -1
  334. package/dist/visually-hidden.js +2 -2
  335. package/dist/{window-D2WfvNng.cjs → window-BSAemI9J.cjs} +1 -1
  336. package/dist/{window-D2WfvNng.cjs.map → window-BSAemI9J.cjs.map} +1 -1
  337. package/dist/{window-n4jN60B_.js → window-ConcHirJ.js} +3 -3
  338. package/dist/{window-n4jN60B_.js.map → window-ConcHirJ.js.map} +1 -1
  339. package/dist/window.cjs +1 -1
  340. package/dist/window.js +1 -1
  341. package/package.json +1 -1
  342. package/skills/schmancy/INDEX.md +1 -1
  343. package/skills/schmancy/SKILL.md +20 -18
  344. package/skills/schmancy/boat.md +21 -15
  345. package/skills/schmancy/fab.md +75 -0
  346. package/skills/schmancy/steps.md +68 -34
  347. package/skills/schmancy/theme.md +1 -1
  348. package/src/CLAUDE.md +22 -16
  349. package/src/boat/boat.test.ts +130 -0
  350. package/src/boat/boat.ts +144 -121
  351. package/src/button/icon-button.ts +18 -30
  352. package/src/chips/assist-chip.ts +2 -263
  353. package/src/chips/chips.ts +2 -259
  354. package/src/chips/filter-chip.ts +2 -255
  355. package/src/chips/index.ts +2 -5
  356. package/src/chips/input-chip.ts +2 -413
  357. package/src/chips/suggestion-chip.ts +2 -266
  358. package/src/directives/fill.ts +28 -5
  359. package/src/directives/reveal.ts +192 -118
  360. package/src/fab/fab.test.ts +101 -0
  361. package/src/fab/fab.ts +226 -0
  362. package/src/fab/index.ts +1 -0
  363. package/src/form/fields/chips/assist-chip.ts +263 -0
  364. package/src/form/fields/chips/chips.ts +234 -0
  365. package/src/form/fields/chips/filter-chip.ts +255 -0
  366. package/src/form/fields/chips/index.ts +5 -0
  367. package/src/form/fields/chips/input-chip.ts +413 -0
  368. package/src/form/fields/chips/suggestion-chip.ts +266 -0
  369. package/src/form/fields/date-range/date-range.test.ts +44 -0
  370. package/src/form/fields/date-range/date-range.ts +103 -97
  371. package/src/form/fields/index.ts +1 -0
  372. package/src/index.ts +2 -1
  373. package/src/overlay/overlay.animations.ts +2 -3
  374. package/src/overlay/overlay.component.ts +8 -4
  375. package/src/overlay/overlay.types.ts +14 -2
  376. package/src/steps/index.ts +1 -1
  377. package/src/steps/schmancy-step.ts +91 -65
  378. package/src/steps/{schmancy-steps-container.ts → schmancy-steps.ts} +18 -38
  379. package/src/steps/steps.context.ts +5 -4
  380. package/src/steps/steps.test.ts +120 -0
  381. package/src/theme/theme.component.ts +1 -0
  382. package/src/theme/theme.style.css +3 -0
  383. package/types/src/boat/boat.d.ts +27 -9
  384. package/types/src/boat/boat.test.d.ts +2 -0
  385. package/types/src/button/icon-button.d.ts +3 -2
  386. package/types/src/chips/assist-chip.d.ts +1 -47
  387. package/types/src/chips/chips.d.ts +1 -43
  388. package/types/src/chips/filter-chip.d.ts +1 -67
  389. package/types/src/chips/index.d.ts +1 -5
  390. package/types/src/chips/input-chip.d.ts +1 -82
  391. package/types/src/chips/suggestion-chip.d.ts +1 -52
  392. package/types/src/directives/reveal.d.ts +15 -5
  393. package/types/src/fab/fab.d.ts +80 -0
  394. package/types/src/fab/fab.test.d.ts +2 -0
  395. package/types/src/fab/index.d.ts +1 -0
  396. package/types/src/form/fields/chips/assist-chip.d.ts +47 -0
  397. package/types/src/form/fields/chips/chips.d.ts +35 -0
  398. package/types/src/form/fields/chips/filter-chip.d.ts +67 -0
  399. package/types/src/form/fields/chips/index.d.ts +5 -0
  400. package/types/src/form/fields/chips/input-chip.d.ts +82 -0
  401. package/types/src/form/fields/chips/suggestion-chip.d.ts +52 -0
  402. package/types/src/form/fields/date-range/date-range.d.ts +5 -10
  403. package/types/src/form/fields/index.d.ts +1 -0
  404. package/types/src/index.d.ts +2 -1
  405. package/types/src/overlay/overlay.component.d.ts +1 -0
  406. package/types/src/overlay/overlay.types.d.ts +12 -2
  407. package/types/src/steps/index.d.ts +1 -1
  408. package/types/src/steps/schmancy-step.d.ts +8 -23
  409. package/types/src/steps/{schmancy-steps-container.d.ts → schmancy-steps.d.ts} +8 -9
  410. package/types/src/steps/steps.context.d.ts +2 -1
  411. package/types/src/steps/steps.test.d.ts +2 -0
  412. package/types/src/theme/theme.component.d.ts +1 -0
  413. package/dist/SchmancyElement-CA0Wqt8m.js +0 -284
  414. package/dist/SchmancyElement-CA0Wqt8m.js.map +0 -1
  415. package/dist/SchmancyElement-CYIif26I.cjs +0 -2
  416. package/dist/SchmancyElement-CYIif26I.cjs.map +0 -1
  417. package/dist/boat-Vqjgo10B.cjs +0 -33
  418. package/dist/boat-Vqjgo10B.cjs.map +0 -1
  419. package/dist/boat-lr7MPZ7H.js.map +0 -1
  420. package/dist/chips-CXZ4dJCK.cjs.map +0 -1
  421. package/dist/chips-Dg6Lk6BT.js.map +0 -1
  422. package/dist/date-range-BU6WX7d5.js.map +0 -1
  423. package/dist/date-range-C-_be3_E.cjs.map +0 -1
  424. package/dist/directives-fLwDj6b0.cjs.map +0 -1
  425. package/dist/directives-zi1Mm2er.js.map +0 -1
  426. package/dist/input-chip-57tgNXKT.cjs.map +0 -1
  427. package/dist/input-chip-C6Lq1927.js.map +0 -1
  428. package/dist/overlay-BpNhd74N.js.map +0 -1
  429. package/dist/overlay-UQR2Dy3u.cjs.map +0 -1
  430. package/dist/theme-iKUaS9JB.cjs +0 -181
@@ -1,7 +1,7 @@
1
1
  import { AsyncDirective, directive } from 'lit/async-directive.js'
2
2
  import { ElementPart, PartType } from 'lit/directive.js'
3
3
  import { EMPTY, Subject, animationFrameScheduler, combineLatest, fromEvent, merge, timer } from 'rxjs'
4
- import { auditTime, filter, startWith, switchMap, takeUntil, tap } from 'rxjs/operators'
4
+ import { auditTime, distinctUntilChanged, filter, map, startWith, switchMap, takeUntil, tap } from 'rxjs/operators'
5
5
  import { theme } from '../theme/theme.service'
6
6
  import { fromResizeObserver } from './layout'
7
7
 
@@ -50,6 +50,15 @@ class Fill extends AsyncDirective {
50
50
  : EMPTY,
51
51
  fromEvent(window, 'orientationchange'),
52
52
  fromEvent(document, 'focusout', { passive: true }).pipe(switchMap(() => timer(100))),
53
+ // Observe `el` itself: this is the post-layout settle trigger
54
+ // (its initial callback fires once `rect.top/left` resolve) and
55
+ // the only DOM trigger for a top-level fill element whose
56
+ // `el.parentElement` is null. It is loop-safe ONLY because of
57
+ // the `distinctUntilChanged` gate below: write → RO fires →
58
+ // recompute → identical value → gate suppresses → no write →
59
+ // RO quiet (converges in ≤2 frames). The ~20s overlay hang was
60
+ // the *missing gate*, not the observation — without it every
61
+ // write re-fired the observer forever.
53
62
  fromResizeObserver(el),
54
63
  el.parentElement ? fromResizeObserver(el.parentElement) : EMPTY,
55
64
  ).pipe(auditTime(0, animationFrameScheduler), startWith(null)),
@@ -61,14 +70,28 @@ class Fill extends AsyncDirective {
61
70
  const vv = window.visualViewport
62
71
  return vv ? Math.abs(vv.scale - 1) <= 0.01 : true
63
72
  }),
64
- tap(([, bottomOffset, isFullscreen]) => {
73
+ map(([, bottomOffset, isFullscreen]) => {
65
74
  const vv = window.visualViewport
66
75
  const rect = el.getBoundingClientRect()
76
+ return {
77
+ height: `${Math.max(0, (vv?.height ?? window.innerHeight) - rect.top)}px`,
78
+ width: `${Math.max(0, (vv?.width ?? window.innerWidth) - rect.left)}px`,
79
+ paddingBottom: `${isFullscreen ? 0 : bottomOffset}px`,
80
+ }
81
+ }),
82
+ // Idempotent gate: once geometry is stable the computed values
83
+ // stop changing, so no DOM write happens and no resize is
84
+ // emitted — the parent observer (and any ancestor's, e.g. the
85
+ // overlay's) goes quiet instead of ping-ponging.
86
+ distinctUntilChanged(
87
+ (a, b) => a.height === b.height && a.width === b.width && a.paddingBottom === b.paddingBottom,
88
+ ),
89
+ tap(({ height, width, paddingBottom }) => {
67
90
  const s = el.style
68
91
  s.boxSizing = 'border-box'
69
- s.height = `${Math.max(0, (vv?.height ?? window.innerHeight) - rect.top)}px`
70
- s.width = `${Math.max(0, (vv?.width ?? window.innerWidth) - rect.left)}px`
71
- s.paddingBottom = `${isFullscreen ? 0 : bottomOffset}px`
92
+ s.height = height
93
+ s.width = width
94
+ s.paddingBottom = paddingBottom
72
95
  s.minHeight = '0'
73
96
  s.minWidth = '0'
74
97
  s.overflow = 'hidden'
@@ -4,6 +4,9 @@
4
4
  * Uses Blackbird spring physics for natural, organic motion.
5
5
  * Element stays in DOM to prevent layout shift.
6
6
  *
7
+ * When fully revealed, no directive-imposed max-height or overflow:hidden
8
+ * is left on the element — it lays out at its natural full height.
9
+ *
7
10
  * Usage:
8
11
  * ```ts
9
12
  * // Basic - uses 'smooth' preset
@@ -12,7 +15,7 @@
12
15
  * // With preset - 'snappy' for quick interactions
13
16
  * html`<div ${reveal(this.isVisible, { preset: 'snappy' })}>Content</div>`
14
17
  *
15
- * // With custom max height
18
+ * // Opt-in scroll cap (explicit maxHeight — keeps overflow:auto, does NOT clip)
16
19
  * html`<div ${reveal(this.items.length > 1, { maxHeight: '200px' })}>Content</div>`
17
20
  *
18
21
  * // Bouncy for playful UI
@@ -28,131 +31,202 @@
28
31
  * @see packages/schmancy/src/utils/animation.ts for Blackbird system
29
32
  */
30
33
 
31
- import { noChange } from 'lit'
32
- import { AsyncDirective, directive } from 'lit/async-directive.js'
33
- import type { ElementPart, PartInfo } from 'lit/directive.js'
34
- import { PartType } from 'lit/directive.js'
34
+ import { noChange } from 'lit';
35
+ import { AsyncDirective, directive } from 'lit/async-directive.js';
36
+ import { type ElementPart, type PartInfo, PartType } from 'lit/directive.js';
37
+ import { fromEvent, Subject } from 'rxjs';
38
+ import { filter, take, takeUntil } from 'rxjs/operators';
35
39
  import {
36
- SPRING_SMOOTH,
37
- SPRING_SNAPPY,
38
- SPRING_BOUNCY,
39
- SPRING_GENTLE,
40
- getEasing,
41
- type AnimationPreset,
42
- } from '../utils/animation'
43
- import { reducedMotion$ } from './reduced-motion'
40
+ type AnimationPreset,
41
+ getEasing,
42
+ SPRING_BOUNCY,
43
+ SPRING_GENTLE,
44
+ SPRING_SMOOTH,
45
+ SPRING_SNAPPY,
46
+ } from '../utils/animation';
47
+ import { reducedMotion$ } from './reduced-motion';
44
48
 
45
- export type RevealPreset = 'smooth' | 'snappy' | 'bouncy' | 'gentle'
49
+ export type RevealPreset = 'smooth' | 'snappy' | 'bouncy' | 'gentle';
46
50
 
47
51
  export interface RevealOptions {
48
- /** Animation preset (default: 'smooth') */
49
- preset?: RevealPreset
50
- /** Max height when revealed (default: '10rem') */
51
- maxHeight?: string
52
- /** Custom duration override in ms (uses preset duration if not specified) */
53
- duration?: number
54
- /** Custom easing override (uses preset easing if not specified) */
55
- easing?: string
52
+ /** Animation preset (default: 'smooth') */
53
+ preset?: RevealPreset;
54
+ /**
55
+ * Explicit scroll cap (opt-in). When set the element is constrained to
56
+ * this height with overflow:auto content scrolls rather than clips.
57
+ * When omitted (the default) the element is fully unconstrained after
58
+ * opening: no max-height, no overflow:hidden left on it.
59
+ */
60
+ maxHeight?: string;
61
+ /** Custom duration override in ms (uses preset duration if not specified) */
62
+ duration?: number;
63
+ /** Custom easing override (uses preset easing if not specified) */
64
+ easing?: string;
56
65
  }
57
66
 
58
67
  const PRESETS: Record<RevealPreset, AnimationPreset> = {
59
- smooth: SPRING_SMOOTH,
60
- snappy: SPRING_SNAPPY,
61
- bouncy: SPRING_BOUNCY,
62
- gentle: SPRING_GENTLE,
63
- }
68
+ smooth: SPRING_SMOOTH,
69
+ snappy: SPRING_SNAPPY,
70
+ bouncy: SPRING_BOUNCY,
71
+ gentle: SPRING_GENTLE,
72
+ };
64
73
 
65
74
  class RevealDirective extends AsyncDirective {
66
- private initialized = false
67
- private element: HTMLElement | null = null
68
-
69
- constructor(partInfo: PartInfo) {
70
- super(partInfo)
71
- if (partInfo.type !== PartType.ELEMENT) {
72
- throw new Error('reveal() can only be used on elements')
73
- }
74
- }
75
-
76
- render(_show?: boolean, _options?: RevealOptions) {
77
- return noChange
78
- }
79
-
80
- override update(part: ElementPart, [show = false, options = {}]: [boolean | undefined, RevealOptions?]) {
81
- const element = part.element as HTMLElement
82
- this.element = element
83
-
84
- const { preset = 'smooth', maxHeight = '10rem', duration, easing } = options
85
-
86
- // Get the preset configuration
87
- const presetConfig = PRESETS[preset]
88
-
89
- // Determine actual duration and easing
90
- const actualDuration = duration ?? presetConfig.duration
91
- const actualEasing = easing ?? getEasing(presetConfig)
92
-
93
- const reducedMotion = reducedMotion$.value
94
-
95
- // Set up transitions on first run or when preset changes
96
- if (!this.initialized) {
97
- this.setupElement(element, actualDuration, actualEasing, reducedMotion)
98
- this.initialized = true
99
- }
100
-
101
- // Apply show/hide styles with spring physics
102
- if (show) {
103
- element.style.maxHeight = maxHeight
104
- element.style.opacity = '1'
105
- element.style.transform = 'translateY(0) scale(1)'
106
- element.style.pointerEvents = ''
107
- element.style.paddingTop = ''
108
- element.style.paddingBottom = ''
109
- element.style.marginTop = ''
110
- element.style.marginBottom = ''
111
- element.removeAttribute('aria-hidden')
112
- element.removeAttribute('inert')
113
- } else {
114
- element.style.maxHeight = '0'
115
- element.style.opacity = '0'
116
- element.style.transform = 'translateY(-8px) scale(0.98)'
117
- element.style.pointerEvents = 'none'
118
- element.style.paddingTop = '0'
119
- element.style.paddingBottom = '0'
120
- element.style.marginTop = '0'
121
- element.style.marginBottom = '0'
122
- element.setAttribute('aria-hidden', 'true')
123
- element.setAttribute('inert', '')
124
- }
125
-
126
- return noChange
127
- }
128
-
129
- private setupElement(element: HTMLElement, duration: number, easing: string, reducedMotion: boolean): void {
130
- element.style.overflow = 'hidden'
131
-
132
- if (reducedMotion) {
133
- // Instant transitions for reduced motion
134
- element.style.transition = 'none'
135
- } else {
136
- // Spring physics transitions — include padding/margin so hidden elements take zero space
137
- element.style.transition = [
138
- `max-height ${duration}ms ${easing}`,
139
- `opacity ${duration}ms ${easing}`,
140
- `transform ${duration}ms ${easing}`,
141
- `padding ${duration}ms ${easing}`,
142
- `margin ${duration}ms ${easing}`,
143
- ].join(', ')
144
- }
145
- }
146
-
147
- override disconnected(): void {
148
- if (this.element) {
149
- this.element.style.willChange = ''
150
- }
151
- }
152
-
153
- override reconnected(): void {
154
- // State preserved in inline styles — no action needed
155
- }
75
+ private initialized = false;
76
+ /** Fires on disconnect to tear down the transitionend subscription. */
77
+ private teardown$ = new Subject<void>();
78
+ /** True if this is the very first update call — used to detect always-true initial mount. */
79
+ private firstUpdate = true;
80
+
81
+ constructor(partInfo: PartInfo) {
82
+ super(partInfo);
83
+ if (partInfo.type !== PartType.ELEMENT) {
84
+ throw new Error('reveal() can only be used on elements');
85
+ }
86
+ }
87
+
88
+ render(_show?: boolean, _options?: RevealOptions) {
89
+ return noChange;
90
+ }
91
+
92
+ override update(
93
+ part: ElementPart,
94
+ [show = false, options = {}]: [boolean | undefined, RevealOptions?],
95
+ ) {
96
+ const element = part.element as HTMLElement;
97
+
98
+ const { preset = 'smooth', maxHeight, duration, easing } = options;
99
+ const explicitCap = maxHeight !== undefined;
100
+
101
+ const presetConfig = PRESETS[preset];
102
+ const actualDuration = duration ?? presetConfig.duration;
103
+ const actualEasing = easing ?? getEasing(presetConfig);
104
+ const reducedMotion = reducedMotion$.value;
105
+
106
+ const isFirstUpdate = this.firstUpdate;
107
+ this.firstUpdate = false;
108
+
109
+ if (!this.initialized) {
110
+ this.initialized = true;
111
+
112
+ if (reducedMotion) {
113
+ element.style.transition = 'none';
114
+ } else {
115
+ element.style.transition = [
116
+ `max-height ${actualDuration}ms ${actualEasing}`,
117
+ `opacity ${actualDuration}ms ${actualEasing}`,
118
+ `transform ${actualDuration}ms ${actualEasing}`,
119
+ `padding ${actualDuration}ms ${actualEasing}`,
120
+ `margin ${actualDuration}ms ${actualEasing}`,
121
+ ].join(', ');
122
+ }
123
+ }
124
+
125
+ if (show) {
126
+ if (isFirstUpdate) {
127
+ // Always-true initial mount: do not impose max-height animation.
128
+ // Apply opacity/transform entrance only (visible immediately for
129
+ // reduced-motion; fades in via the transition for normal motion).
130
+ if (explicitCap) {
131
+ element.style.maxHeight = maxHeight;
132
+ element.style.overflow = 'auto';
133
+ } else {
134
+ element.style.maxHeight = '';
135
+ element.style.overflow = '';
136
+ }
137
+ element.style.opacity = '1';
138
+ element.style.transform = 'translateY(0) scale(1)';
139
+ } else {
140
+ // Toggle case: false→true. Animate from 0 to natural height,
141
+ // then release the clamp so content is fully unconstrained.
142
+ if (reducedMotion) {
143
+ if (explicitCap) {
144
+ element.style.maxHeight = maxHeight;
145
+ element.style.overflow = 'auto';
146
+ } else {
147
+ element.style.maxHeight = '';
148
+ element.style.overflow = '';
149
+ }
150
+ element.style.opacity = '1';
151
+ element.style.transform = 'translateY(0) scale(1)';
152
+ } else {
153
+ // Force a concrete start value so CSS can animate from it.
154
+ element.style.overflow = 'hidden';
155
+ element.style.maxHeight = '0';
156
+ void element.offsetHeight; // force reflow
157
+
158
+ const targetHeight = explicitCap ? maxHeight : `${element.scrollHeight}px`;
159
+ element.style.maxHeight = targetHeight;
160
+ element.style.opacity = '1';
161
+ element.style.transform = 'translateY(0) scale(1)';
162
+
163
+ if (!explicitCap) {
164
+ // Once the open animation settles, release the clamp entirely.
165
+ fromEvent<TransitionEvent>(element, 'transitionend')
166
+ .pipe(
167
+ filter((e) => e.propertyName === 'max-height' && e.target === element),
168
+ take(1),
169
+ takeUntil(this.teardown$),
170
+ )
171
+ .subscribe(() => {
172
+ element.style.maxHeight = '';
173
+ element.style.overflow = '';
174
+ });
175
+ } else {
176
+ fromEvent<TransitionEvent>(element, 'transitionend')
177
+ .pipe(
178
+ filter((e) => e.propertyName === 'max-height' && e.target === element),
179
+ take(1),
180
+ takeUntil(this.teardown$),
181
+ )
182
+ .subscribe(() => {
183
+ element.style.overflow = 'auto';
184
+ });
185
+ }
186
+ }
187
+ }
188
+
189
+ element.style.pointerEvents = '';
190
+ element.style.paddingTop = '';
191
+ element.style.paddingBottom = '';
192
+ element.style.marginTop = '';
193
+ element.style.marginBottom = '';
194
+ element.removeAttribute('aria-hidden');
195
+ element.removeAttribute('inert');
196
+ } else {
197
+ // Collapse: animate to height 0. Re-measure from natural height if
198
+ // the clamp was previously released (max-height is '' or 'none').
199
+ if (element.style.maxHeight === '' || element.style.maxHeight === 'none') {
200
+ element.style.overflow = 'hidden';
201
+ element.style.maxHeight = `${element.scrollHeight}px`;
202
+ void element.offsetHeight; // force reflow so CSS sees the start value
203
+ } else {
204
+ element.style.overflow = 'hidden';
205
+ }
206
+
207
+ element.style.maxHeight = '0';
208
+ element.style.opacity = '0';
209
+ element.style.transform = 'translateY(-8px) scale(0.98)';
210
+ element.style.pointerEvents = 'none';
211
+ element.style.paddingTop = '0';
212
+ element.style.paddingBottom = '0';
213
+ element.style.marginTop = '0';
214
+ element.style.marginBottom = '0';
215
+ element.setAttribute('aria-hidden', 'true');
216
+ element.setAttribute('inert', '');
217
+ }
218
+
219
+ return noChange;
220
+ }
221
+
222
+ override disconnected(): void {
223
+ this.teardown$.next();
224
+ }
225
+
226
+ override reconnected(): void {
227
+ // Re-subscribe is handled on the next update() call via the new subscription
228
+ // created in the show branch. Nothing to wire up here explicitly.
229
+ }
156
230
  }
157
231
 
158
- export const reveal = directive(RevealDirective)
232
+ export const reveal = directive(RevealDirective);
@@ -0,0 +1,101 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
2
+ import './fab'
3
+ import '../icons/icon'
4
+ import { expectNoA11yViolations } from '../test-utils/a11y'
5
+ import type { SchmancyFab } from './fab'
6
+
7
+ const nextUpdate = () => new Promise(r => requestAnimationFrame(() => r(null)))
8
+
9
+ const base = (fab: SchmancyFab) =>
10
+ fab.shadowRoot!.querySelector('[part="base"]') as HTMLButtonElement
11
+
12
+ describe('schmancy-fab — M3 contract', () => {
13
+ let host: HTMLDivElement
14
+
15
+ beforeEach(() => {
16
+ host = document.createElement('div')
17
+ document.body.appendChild(host)
18
+ })
19
+
20
+ afterEach(() => {
21
+ host.remove()
22
+ })
23
+
24
+ it('renders a non-disablable native button (M3: a FAB is never disabled)', async () => {
25
+ host.innerHTML = `<schmancy-fab aria-label="Compose"><schmancy-icon>edit</schmancy-icon></schmancy-fab>`
26
+ const fab = host.querySelector('schmancy-fab') as SchmancyFab
27
+ await nextUpdate()
28
+ const btn = base(fab)
29
+ expect(btn.tagName).toBe('BUTTON')
30
+ expect(btn.getAttribute('type')).toBe('button')
31
+ expect('disabled' in fab).toBe(false)
32
+ })
33
+
34
+ it('defaults to surface / medium: surface-containerHigh container, primary on-colour, 16dp shape', async () => {
35
+ host.innerHTML = `<schmancy-fab aria-label="Compose"><schmancy-icon>edit</schmancy-icon></schmancy-fab>`
36
+ const fab = host.querySelector('schmancy-fab') as SchmancyFab
37
+ await nextUpdate()
38
+ expect(fab.variant).toBe('surface')
39
+ expect(fab.size).toBe('medium')
40
+ expect(fab.extended).toBe(false)
41
+ const cls = base(fab).classList
42
+ expect(cls.contains('bg-surface-containerHigh')).toBe(true)
43
+ expect(cls.contains('text-primary-default')).toBe(true)
44
+ expect(cls.contains('size-14')).toBe(true)
45
+ expect(getComputedStyle(fab).borderTopLeftRadius).toBe('16px')
46
+ })
47
+
48
+ it.each([
49
+ ['primary', 'bg-primary-container', 'text-primary-onContainer'],
50
+ ['secondary', 'bg-secondary-container', 'text-secondary-onContainer'],
51
+ ['tertiary', 'bg-tertiary-container', 'text-tertiary-onContainer'],
52
+ ] as const)('maps the %s variant to its M3 container + on-container colour pair', async (variant, bg, fg) => {
53
+ host.innerHTML = `<schmancy-fab variant="${variant}" aria-label="x"><schmancy-icon>add</schmancy-icon></schmancy-fab>`
54
+ const fab = host.querySelector('schmancy-fab') as SchmancyFab
55
+ await nextUpdate()
56
+ const cls = base(fab).classList
57
+ expect(cls.contains(bg)).toBe(true)
58
+ expect(cls.contains(fg)).toBe(true)
59
+ })
60
+
61
+ it('applies the M3 size geometry: small 12dp/40, large 28dp/36 icon', async () => {
62
+ host.innerHTML = `<schmancy-fab size="small" aria-label="x"><schmancy-icon>add</schmancy-icon></schmancy-fab>`
63
+ let fab = host.querySelector('schmancy-fab') as SchmancyFab
64
+ await nextUpdate()
65
+ expect(base(fab).classList.contains('size-10')).toBe(true)
66
+ expect(getComputedStyle(fab).borderTopLeftRadius).toBe('12px')
67
+
68
+ host.innerHTML = `<schmancy-fab size="large" aria-label="x"><schmancy-icon>add</schmancy-icon></schmancy-fab>`
69
+ fab = host.querySelector('schmancy-fab') as SchmancyFab
70
+ await nextUpdate()
71
+ expect(base(fab).classList.contains('size-24')).toBe(true)
72
+ expect(getComputedStyle(fab).borderTopLeftRadius).toBe('28px')
73
+ })
74
+
75
+ it('derives the extended form from a non-empty label and renders the label', async () => {
76
+ host.innerHTML = `<schmancy-fab label="Compose" variant="primary"><schmancy-icon>edit</schmancy-icon></schmancy-fab>`
77
+ const fab = host.querySelector('schmancy-fab') as SchmancyFab
78
+ await nextUpdate()
79
+ expect(fab.extended).toBe(true)
80
+ expect(fab.hasAttribute('extended')).toBe(true)
81
+ const btn = base(fab)
82
+ expect(btn.classList.contains('size-14')).toBe(false)
83
+ expect(btn.classList.contains('ps-4')).toBe(true)
84
+ expect(btn.classList.contains('pe-5')).toBe(true)
85
+ expect(btn.textContent).toContain('Compose')
86
+ })
87
+
88
+ it('reflects lowered and hides the icon slot from AT when a name is present', async () => {
89
+ host.innerHTML = `<schmancy-fab lowered label="New"><schmancy-icon>edit</schmancy-icon></schmancy-fab>`
90
+ const fab = host.querySelector('schmancy-fab') as SchmancyFab
91
+ await nextUpdate()
92
+ expect(fab.hasAttribute('lowered')).toBe(true)
93
+ expect(fab.shadowRoot!.querySelector('slot')!.getAttribute('aria-hidden')).toBe('true')
94
+ })
95
+
96
+ it('has no a11y violations as an icon-only FAB with an accessible name', async () => {
97
+ host.innerHTML = `<schmancy-fab aria-label="Compose message"><schmancy-icon>edit</schmancy-icon></schmancy-fab>`
98
+ await nextUpdate()
99
+ await expectNoA11yViolations(host)
100
+ })
101
+ })