@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
package/src/boat/boat.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  import { SchmancyElement } from '@mixins/index'
2
- import { css, html, nothing, type PropertyValues } from 'lit'
2
+ import { html, type PropertyValues } from 'lit'
3
3
  import { customElement, property, queryAssignedElements, state } from 'lit/decorators.js'
4
4
  import { classMap } from 'lit/directives/class-map.js'
5
5
  import { createRef, ref } from 'lit/directives/ref.js'
6
6
  import { styleMap } from 'lit/directives/style-map.js'
7
- import { when } from 'lit/directives/when.js'
8
- import { filter, finalize, fromEvent, map, merge, type Subscription, switchMap, takeUntil, tap } from 'rxjs'
9
- import { SPRING_SMOOTH } from '../utils/animation.js'
7
+ import { exhaustMap, filter, finalize, fromEvent, merge, type Subscription, takeUntil, tap } from 'rxjs'
10
8
  import { reducedMotion$ } from '../directives/reduced-motion'
11
9
  import { show } from '../overlay/overlay.service'
12
10
  import { theme } from '../theme/theme.service.js'
11
+ import { SPRING_SMOOTH } from '../utils/animation.js'
13
12
 
14
13
  const DRAG_THRESHOLD = 5
15
14
  const POSITION_STORAGE_KEY_PREFIX = 'schmancy-boat-'
@@ -21,42 +20,51 @@ interface Position {
21
20
  }
22
21
 
23
22
  /**
24
- * Material-3 extended FAB that delegates its expanded panel to the `show()`
25
- * overlay service. Collapsed: a draggable, corner-anchored pill (icon + label,
26
- * circular when no label). Activated: the default-slot content blooms from the
27
- * FAB as an overlay (backdrop / Esc / back-button / sheet-on-narrow handled by
28
- * the overlay primitive).
23
+ * Corner-anchored launcher that delegates its expanded panel to the `show()`
24
+ * overlay service.
25
+ *
26
+ * Three slots, three non-overlapping intents no element-type sniffing,
27
+ * ever:
28
+ *
29
+ * - `trigger` — pure consumer content. A native click anywhere on it
30
+ * opens the panel; interactive children (buttons, FABs, inputs) work
31
+ * with zero special-casing because the boat never calls
32
+ * `preventDefault` / `stopPropagation` / `setPointerCapture` here.
33
+ * - `drag-handle` — opt-in. Pointer-drag is wired ONLY to this slot's
34
+ * boat-owned wrapper. Slot it to make the boat draggable; omit it and
35
+ * the boat is static at its corner. (A no-move tap on the handle also
36
+ * opens, so the grip doubles as a launcher.)
37
+ * - _(default)_ — the panel body; parked hidden while collapsed,
38
+ * relocated into the `show()` overlay on open.
39
+ *
40
+ * The boat owns drag, corner-snapping, position persistence and the glass
41
+ * surface — never the collapsed shape.
29
42
  */
30
43
  @customElement('schmancy-boat')
31
44
  export default class SchmancyBoat extends SchmancyElement {
32
- static styles = [css`
33
- :host {
34
- display: contents;
35
- }
36
- :host([hidden]) {
37
- display: none !important;
38
- }
39
- `]
40
45
 
46
+
47
+ /** Identity for localStorage drag-position persistence. */
41
48
  @property({ type: String }) id: string = 'default'
42
- @property({ type: String }) icon?: string
43
- @property({ type: String }) label?: string
44
- /** When true, uses a lower elevation shadow on the FAB. */
45
- @property({ type: Boolean, reflect: true }) lowered: boolean = false
46
- /** Corner the FAB is anchored to. */
49
+ /** Corner the launcher is anchored to. */
47
50
  @property({ type: String }) corner: Corner = 'bottom-right'
48
51
  /** Open state. Bind `?open=${…}` to drive the overlay; reflected to the attribute. */
49
52
  @property({ type: Boolean, reflect: true }) open: boolean = false
50
53
 
51
54
  @state() private isDragging = false
52
- @state() private _currentCorner: Corner = 'bottom-right'
55
+ @state() private currentCorner: Corner = 'bottom-right'
56
+ @state() private hasHandle = false
53
57
 
54
- @queryAssignedElements() private _slotted!: Element[]
58
+ /** Default-slot nodes — the overlay body. */
59
+ @queryAssignedElements() private slotted!: Element[]
60
+ /** Slotted drag-handle nodes — presence toggles draggability. */
61
+ @queryAssignedElements({ slot: 'drag-handle' }) private handleNodes!: Element[]
55
62
 
56
- private _position: Position = { x: 16, y: 16 }
57
- private _containerRef = createRef<HTMLElement>()
58
- private _headerRef = createRef<HTMLElement>()
59
- private _currentAnimation?: Animation
63
+ private position: Position = { x: 16, y: 16 }
64
+ private containerRef = createRef<HTMLElement>()
65
+ private triggerRef = createRef<HTMLElement>()
66
+ private handleRef = createRef<HTMLElement>()
67
+ private currentAnimation?: Animation
60
68
 
61
69
  #ready = false
62
70
  #sub?: Subscription
@@ -66,76 +74,76 @@ export default class SchmancyBoat extends SchmancyElement {
66
74
  // POSITION MANAGEMENT
67
75
  // ============================================
68
76
 
69
- private _applyContainerPosition() {
70
- const container = this._containerRef.value
77
+ private applyContainerPosition() {
78
+ const container = this.containerRef.value
71
79
  if (!container) return
72
80
  container.style.removeProperty('left')
73
81
  container.style.removeProperty('right')
74
82
  container.style.removeProperty('top')
75
83
  container.style.removeProperty('bottom')
76
- const { x, y } = this._position
77
- if (this._currentCorner.includes('right')) {
84
+ const { x, y } = this.position
85
+ if (this.currentCorner.includes('right')) {
78
86
  container.style.right = `${x}px`
79
87
  } else {
80
88
  container.style.left = `${x}px`
81
89
  }
82
- if (this._currentCorner.includes('bottom')) {
90
+ if (this.currentCorner.includes('bottom')) {
83
91
  container.style.bottom = `${y + theme.bottomOffset}px`
84
92
  } else {
85
93
  container.style.top = `${y}px`
86
94
  }
87
95
  }
88
96
 
89
- private _loadPosition() {
97
+ private loadPosition() {
90
98
  try {
91
99
  const saved = localStorage.getItem(POSITION_STORAGE_KEY_PREFIX + this.id)
92
100
  if (saved) {
93
101
  const parsed = JSON.parse(saved) as { x: number; y: number; anchor: Corner }
94
- this._position = { x: parsed.x, y: parsed.y }
95
- this._currentCorner = parsed.anchor
102
+ this.position = { x: parsed.x, y: parsed.y }
103
+ this.currentCorner = parsed.anchor
96
104
  }
97
105
  } catch {
98
106
  // ignore localStorage errors
99
107
  }
100
108
  }
101
109
 
102
- private _savePosition() {
110
+ private savePosition() {
103
111
  try {
104
112
  localStorage.setItem(
105
113
  POSITION_STORAGE_KEY_PREFIX + this.id,
106
- JSON.stringify({ ...this._position, anchor: this._currentCorner }),
114
+ JSON.stringify({ ...this.position, anchor: this.currentCorner }),
107
115
  )
108
116
  } catch {
109
117
  // ignore localStorage errors
110
118
  }
111
119
  }
112
120
 
113
- private _validateBounds() {
114
- const container = this._containerRef.value
121
+ private validateBounds() {
122
+ const container = this.containerRef.value
115
123
  if (!container) return
116
124
  const rect = container.getBoundingClientRect()
117
125
  if (rect.width === 0) return
118
126
  const vw = window.innerWidth
119
127
  const vh = window.innerHeight
120
- const isRight = this._currentCorner.includes('right')
121
- const isBottom = this._currentCorner.includes('bottom')
122
- const actualLeft = isRight ? vw - this._position.x - rect.width : this._position.x
123
- const actualTop = isBottom ? vh - this._position.y - rect.height : this._position.y
128
+ const isRight = this.currentCorner.includes('right')
129
+ const isBottom = this.currentCorner.includes('bottom')
130
+ const actualLeft = isRight ? vw - this.position.x - rect.width : this.position.x
131
+ const actualTop = isBottom ? vh - this.position.y - rect.height : this.position.y
124
132
  const newLeft = Math.max(0, Math.min(actualLeft, vw - rect.width))
125
133
  const newTop = Math.max(0, Math.min(actualTop, vh - rect.height))
126
- this._position = {
134
+ this.position = {
127
135
  x: isRight ? vw - newLeft - rect.width : newLeft,
128
136
  y: isBottom ? vh - newTop - rect.height : newTop,
129
137
  }
130
- this._applyContainerPosition()
138
+ this.applyContainerPosition()
131
139
  }
132
140
 
133
141
  // ============================================
134
142
  // CORNER SNAPPING (FLIP)
135
143
  // ============================================
136
144
 
137
- private _reorientToNearestCorner(): void {
138
- const container = this._containerRef.value
145
+ private reorientToNearestCorner(): void {
146
+ const container = this.containerRef.value
139
147
  if (!container) return
140
148
 
141
149
  const rect = container.getBoundingClientRect()
@@ -143,12 +151,12 @@ export default class SchmancyBoat extends SchmancyElement {
143
151
  const fabCenterY = rect.top + rect.height / 2
144
152
  const side = fabCenterX > window.innerWidth / 2 ? 'right' : 'left'
145
153
  const vert = fabCenterY > window.innerHeight / 2 ? 'bottom' : 'top'
146
- this._currentCorner = `${vert}-${side}` as Corner
147
- this._position = { x: 16, y: 16 }
148
- this._applyContainerPosition()
154
+ this.currentCorner = `${vert}-${side}` as Corner
155
+ this.position = { x: 16, y: 16 }
156
+ this.applyContainerPosition()
149
157
 
150
158
  if (reducedMotion$.value) {
151
- this._savePosition()
159
+ this.savePosition()
152
160
  return
153
161
  }
154
162
 
@@ -157,7 +165,7 @@ export default class SchmancyBoat extends SchmancyElement {
157
165
  const dy = rect.top - newRect.top
158
166
  container.style.transform = `translate(${dx}px, ${dy}px)`
159
167
 
160
- this._currentAnimation?.cancel()
168
+ this.currentAnimation?.cancel()
161
169
  const anim = container.animate(
162
170
  [{ transform: container.style.transform }, { transform: 'translate(0,0)' }],
163
171
  {
@@ -166,103 +174,25 @@ export default class SchmancyBoat extends SchmancyElement {
166
174
  fill: 'forwards',
167
175
  },
168
176
  )
169
- this._currentAnimation = anim
177
+ this.currentAnimation = anim
170
178
  anim.finished.then(() => {
171
179
  if (container.isConnected) container.style.transform = ''
172
180
  return
173
181
  })
174
182
 
175
- this._savePosition()
176
- }
177
-
178
- // ============================================
179
- // DRAG PIPELINE
180
- // ============================================
181
-
182
- private _setupDrag() {
183
- const header = this._headerRef.value
184
- const container = this._containerRef.value
185
- if (!header || !container) return
186
-
187
- let didDrag = false
188
-
189
- fromEvent<PointerEvent>(header, 'pointerdown')
190
- .pipe(
191
- filter(e => e.button === 0),
192
- tap(e => {
193
- e.preventDefault()
194
- e.stopPropagation()
195
- header.setPointerCapture(e.pointerId)
196
- }),
197
- map(e => {
198
- const rect = container.getBoundingClientRect()
199
- didDrag = false
200
- return {
201
- pointerId: e.pointerId,
202
- startX: e.clientX,
203
- startY: e.clientY,
204
- offsetX: e.clientX - rect.left,
205
- offsetY: e.clientY - rect.top,
206
- rect,
207
- }
208
- }),
209
- switchMap(({ pointerId, startX, startY, offsetX, offsetY, rect }) => {
210
- const sameId = (e: PointerEvent) => e.pointerId === pointerId
211
- const move$ = fromEvent<PointerEvent>(window, 'pointermove').pipe(filter(sameId))
212
- const end$ = merge(
213
- fromEvent<PointerEvent>(window, 'pointerup'),
214
- fromEvent<PointerEvent>(window, 'pointercancel'),
215
- ).pipe(filter(sameId))
216
-
217
- return move$.pipe(
218
- tap(({ clientX, clientY }) => {
219
- const dx = clientX - startX
220
- const dy = clientY - startY
221
- if (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD && !didDrag) {
222
- didDrag = true
223
- this.isDragging = true
224
- }
225
- if (!didDrag) return
226
-
227
- const vw = window.innerWidth
228
- const vh = window.innerHeight
229
- const left = Math.max(0, Math.min(clientX - offsetX, vw - rect.width))
230
- const top = Math.max(0, Math.min(clientY - offsetY, vh - rect.height))
231
- this._position = {
232
- x: this._currentCorner.includes('right') ? vw - left - rect.width : left,
233
- y: this._currentCorner.includes('bottom') ? vh - top - rect.height : top,
234
- }
235
- this._applyContainerPosition()
236
- }),
237
- takeUntil(end$),
238
- finalize(() => {
239
- if (didDrag) {
240
- this._reorientToNearestCorner()
241
- this.isDragging = false
242
- didDrag = false
243
- } else {
244
- this.isDragging = false
245
- didDrag = false
246
- this.toggle()
247
- }
248
- }),
249
- )
250
- }),
251
- takeUntil(this.disconnecting),
252
- )
253
- .subscribe()
183
+ this.savePosition()
254
184
  }
255
185
 
256
186
  // ============================================
257
187
  // OVERLAY DELEGATION
258
188
  // ============================================
259
189
 
260
- private _openOverlay() {
190
+ private openOverlay() {
261
191
  if (this.#sub) return
262
- const anchor = this._containerRef.value
192
+ const anchor = this.containerRef.value
263
193
  const wrapper = document.createElement('div')
264
194
  wrapper.className = 'flex flex-col'
265
- this.#captured = [...this._slotted]
195
+ this.#captured = [...this.slotted]
266
196
  this.#captured.forEach(node => wrapper.appendChild(node))
267
197
 
268
198
  this.#sub = show(wrapper, {
@@ -271,7 +201,7 @@ export default class SchmancyBoat extends SchmancyElement {
271
201
  historyStrategy: 'silent',
272
202
  })
273
203
  .pipe(
274
- finalize(() => this._restoreSlotted()),
204
+ finalize(() => this.restoreSlotted()),
275
205
  takeUntil(this.disconnecting),
276
206
  )
277
207
  .subscribe()
@@ -279,7 +209,7 @@ export default class SchmancyBoat extends SchmancyElement {
279
209
  this.dispatchScopedEvent('toggle', 'open')
280
210
  }
281
211
 
282
- private _restoreSlotted() {
212
+ private restoreSlotted() {
283
213
  this.#captured.forEach(node => this.appendChild(node))
284
214
  this.#captured = []
285
215
  this.#sub = undefined
@@ -294,35 +224,115 @@ export default class SchmancyBoat extends SchmancyElement {
294
224
  connectedCallback() {
295
225
  super.connectedCallback()
296
226
 
297
- fromEvent(window, 'resize')
227
+ // One concern: keep the container in place when the environment
228
+ // shifts. Viewport resize re-validates bounds; a theme bottom-offset
229
+ // change (e.g. a snackbar pushing the safe area) re-applies position.
230
+ merge(
231
+ fromEvent(window, 'resize').pipe(tap(() => this.validateBounds())),
232
+ theme.bottomOffset$.pipe(tap(() => this.applyContainerPosition())),
233
+ )
298
234
  .pipe(takeUntil(this.disconnecting))
299
- .subscribe(() => this._validateBounds())
300
-
301
- theme.bottomOffset$.pipe(
302
- tap(() => this._applyContainerPosition()),
303
- takeUntil(this.disconnecting),
304
- ).subscribe()
235
+ .subscribe()
305
236
  }
306
237
 
307
238
  firstUpdated() {
308
- this._currentCorner = this.corner
309
- this._loadPosition()
310
- if (!this._containerRef.value) return
311
- this._applyContainerPosition()
312
- this._setupDrag()
239
+ this.currentCorner = this.corner
240
+ this.hasHandle = this.handleNodes.length > 0
241
+ this.loadPosition()
242
+ const container = this.containerRef.value
243
+ const trigger = this.triggerRef.value
244
+ const handle = this.handleRef.value
245
+ if (!container || !trigger || !handle) return
246
+ this.applyContainerPosition()
247
+
248
+ // Three intents, three sources, one pipeline, one subscribe.
249
+ //
250
+ // open$ — a plain click/Enter/Space on the trigger region. No
251
+ // preventDefault/stopPropagation: a slotted button's own
252
+ // click still fires; it merely also bubbles to "open".
253
+ // drag$ — pointerdown on the boat-owned drag-handle wrapper. A
254
+ // dedicated region, so every pointerdown there is a drag
255
+ // intent — no element-type sniffing. A session ends on
256
+ // pointerup/cancel; settle = move past threshold ? snap to
257
+ // the nearest corner : treat as a tap and open.
258
+ merge(
259
+ fromEvent<MouseEvent>(trigger, 'click').pipe(tap(() => this.toggle())),
260
+ fromEvent<KeyboardEvent>(trigger, 'keydown').pipe(
261
+ filter(e => e.key === 'Enter' || e.key === ' '),
262
+ tap(e => {
263
+ e.preventDefault()
264
+ this.toggle()
265
+ }),
266
+ ),
267
+ fromEvent<PointerEvent>(handle, 'pointerdown').pipe(
268
+ filter(e => e.button === 0),
269
+ tap(e => {
270
+ e.preventDefault()
271
+ // Capture can throw InvalidStateError if the pointer is
272
+ // already released (fast tap) — drag still works without it.
273
+ try {
274
+ handle.setPointerCapture(e.pointerId)
275
+ } catch {
276
+ // no active pointer to capture; ignore
277
+ }
278
+ }),
279
+ exhaustMap(down => {
280
+ const rect = container.getBoundingClientRect()
281
+ const offsetX = down.clientX - rect.left
282
+ const offsetY = down.clientY - rect.top
283
+ let moved = false
284
+ const sameId = (e: PointerEvent) => e.pointerId === down.pointerId
285
+ const end$ = merge(
286
+ fromEvent<PointerEvent>(window, 'pointerup'),
287
+ fromEvent<PointerEvent>(window, 'pointercancel'),
288
+ ).pipe(filter(sameId))
289
+
290
+ return fromEvent<PointerEvent>(window, 'pointermove').pipe(
291
+ filter(sameId),
292
+ tap(e => {
293
+ const dx = e.clientX - down.clientX
294
+ const dy = e.clientY - down.clientY
295
+ if (!moved && Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD) {
296
+ moved = true
297
+ this.isDragging = true
298
+ }
299
+ if (!moved) return
300
+ const vw = window.innerWidth
301
+ const vh = window.innerHeight
302
+ const left = Math.max(0, Math.min(e.clientX - offsetX, vw - rect.width))
303
+ const top = Math.max(0, Math.min(e.clientY - offsetY, vh - rect.height))
304
+ this.position = {
305
+ x: this.currentCorner.includes('right') ? vw - left - rect.width : left,
306
+ y: this.currentCorner.includes('bottom') ? vh - top - rect.height : top,
307
+ }
308
+ this.applyContainerPosition()
309
+ }),
310
+ takeUntil(end$),
311
+ finalize(() => {
312
+ if (moved) this.reorientToNearestCorner()
313
+ else this.toggle()
314
+ this.isDragging = false
315
+ }),
316
+ )
317
+ }),
318
+ ),
319
+ )
320
+ .pipe(takeUntil(this.disconnecting))
321
+ .subscribe()
322
+
313
323
  this.#ready = true
314
- if (this.open) this._openOverlay()
324
+ if (this.open) this.openOverlay()
315
325
  }
316
326
 
317
327
  protected willUpdate(changed: PropertyValues<this>) {
318
328
  if (!this.#ready || !changed.has('open')) return
319
- if (this.open && !this.#sub) this._openOverlay()
329
+ if (this.open && !this.#sub) this.openOverlay()
320
330
  else if (!this.open && this.#sub) this.#sub.unsubscribe()
321
331
  }
322
332
 
323
333
  disconnectedCallback() {
324
334
  super.disconnectedCallback()
325
- this._currentAnimation?.cancel()
335
+ this.currentAnimation?.cancel()
326
336
  this.#sub?.unsubscribe()
327
337
  }
328
338
 
@@ -339,11 +349,13 @@ export default class SchmancyBoat extends SchmancyElement {
339
349
  // RENDER
340
350
  // ============================================
341
351
 
352
+ private onHandleSlotChange = () => {
353
+ this.hasHandle = this.handleNodes.length > 0
354
+ }
355
+
342
356
  protected render(): unknown {
343
357
  const containerClasses = classMap({
344
358
  'inline-flex': true,
345
- 'rounded-full': true,
346
- 'overflow-hidden': true,
347
359
  'transition-opacity': true,
348
360
  'duration-200': true,
349
361
  'opacity-85': this.isDragging,
@@ -355,53 +367,47 @@ export default class SchmancyBoat extends SchmancyElement {
355
367
  'pointer-events': 'auto',
356
368
  })
357
369
 
358
- const fabClasses = classMap({
359
- 'h-14': true,
360
- 'rounded-full': true,
370
+ // Boat-owned drag region — wraps ONLY the drag-handle slot, so every
371
+ // pointerdown inside it is unambiguously a drag intent. Hidden (and
372
+ // out of layout) when the consumer slots no handle: the boat is then
373
+ // simply not draggable.
374
+ const handleClasses = classMap({
361
375
  flex: true,
362
376
  'items-center': true,
363
- 'gap-3': true,
364
- 'select-none': true,
365
377
  'touch-none': true,
378
+ 'select-none': true,
379
+ hidden: !this.hasHandle,
366
380
  'cursor-grabbing': this.isDragging,
367
- 'cursor-pointer': !this.isDragging,
368
- 'px-5': !!this.label,
369
- 'w-14': !this.label,
370
- 'justify-center': !this.label,
381
+ 'cursor-grab': !this.isDragging,
371
382
  })
372
383
 
373
384
  return html`
374
385
  <schmancy-surface
375
- ${ref(this._containerRef)}
386
+ ${ref(this.containerRef)}
376
387
  type="glass"
377
- .elevation=${this.lowered ? 1 : 3}
378
- class=${containerClasses}
388
+ rounded="all"
389
+ .elevation=${3}
390
+ class="${containerClasses} overflow-hidden rounded-2xl"
379
391
  style=${containerStyles}
380
392
  aria-expanded=${this.open}
381
393
  >
382
394
  <div
383
- ${ref(this._headerRef)}
384
- class=${fabClasses}
395
+ ${ref(this.handleRef)}
396
+ class=${handleClasses}
397
+ aria-label="Drag to move"
398
+ >
399
+ <slot name="drag-handle" @slotchange=${this.onHandleSlotChange}></slot>
400
+ </div>
401
+
402
+ <div
403
+ ${ref(this.triggerRef)}
404
+ class="flex items-center cursor-pointer"
385
405
  role="button"
386
406
  tabindex="0"
387
- aria-label=${this.label ?? 'Open panel'}
388
- title="Drag to move · click to open"
407
+ aria-label="Open panel"
408
+ title="Click to open"
389
409
  >
390
- <slot name="header">
391
- ${when(
392
- !!this.icon,
393
- () => html`<schmancy-icon>${this.icon}</schmancy-icon>`,
394
- () => nothing,
395
- )}
396
- </slot>
397
- ${when(
398
- !!this.label,
399
- () => html`<schmancy-typography type="label" token="lg" class="whitespace-nowrap">
400
- ${this.label}
401
- </schmancy-typography>`,
402
- () => nothing,
403
- )}
404
- <slot name="summary"></slot>
410
+ <slot name="trigger"></slot>
405
411
  </div>
406
412
 
407
413
  <!-- Default-slot content parks here (hidden) while collapsed;
@@ -116,44 +116,32 @@ export class SchmnacyIconButton extends SchmancyElement {
116
116
  @property({ type: String })
117
117
  public icon?: string
118
118
 
119
- // Reactively captured icon name from slot content (translation-proof)
119
+ // Reactively captured icon name from slot content (translation-proof).
120
+ // Mirrors <schmancy-icon>: a MutationObserver on the light DOM keeps this
121
+ // in sync no matter how the consumer passes the name — a plain text node,
122
+ // a dynamic ${...} binding (Lit mutates the text node's data in place, so
123
+ // no slotchange ever fires), or a nested <schmancy-icon> element.
124
+ // `textContent` flattens through all three.
120
125
  @state()
121
126
  private _capturedIcon?: string
122
127
 
128
+ private _observer?: MutationObserver
129
+
123
130
  connectedCallback(): void {
124
131
  super.connectedCallback()
125
- // Pre-capture icon from children to avoid double render flash
126
- this._captureIconFromChildren()
132
+ this._captureIcon()
133
+ this._observer = new MutationObserver(() => this._captureIcon())
134
+ this._observer.observe(this, { childList: true, characterData: true, subtree: true })
127
135
  }
128
136
 
129
- // Capture icon from direct children (for initial render)
130
- private _captureIconFromChildren(): void {
131
- if (this.icon || this.text) return
132
- for (const node of this.childNodes) {
133
- if (node.nodeType === Node.TEXT_NODE) {
134
- const text = node.textContent?.trim()
135
- if (text) {
136
- this._capturedIcon = text
137
- return
138
- }
139
- }
140
- }
137
+ disconnectedCallback(): void {
138
+ super.disconnectedCallback()
139
+ this._observer?.disconnect()
141
140
  }
142
141
 
143
- // Handle slot content changes reactively (for dynamic updates)
144
- private _handleSlotChange(e: Event): void {
142
+ private _captureIcon(): void {
145
143
  if (this.icon || this.text) return
146
- const slot = e.target as HTMLSlotElement
147
- const nodes = slot.assignedNodes({ flatten: true })
148
- for (const node of nodes) {
149
- if (node.nodeType === Node.TEXT_NODE) {
150
- const text = node.textContent?.trim()
151
- if (text) {
152
- this._capturedIcon = text
153
- return
154
- }
155
- }
156
- }
144
+ this._capturedIcon = this.textContent?.trim() || undefined
157
145
  }
158
146
 
159
147
  // Manage aria-label manually so that we can always use our internal property.
@@ -254,7 +242,7 @@ export class SchmnacyIconButton extends SchmancyElement {
254
242
  ${this.text
255
243
  ? html`<slot></slot>`
256
244
  : html`
257
- <slot style="display:none" @slotchange=${this._handleSlotChange}></slot>
245
+ <slot style="display:none"></slot>
258
246
  <schmancy-icon class=${iconSizeClass}>${this.icon || this._capturedIcon}</schmancy-icon>
259
247
  `
260
248
  }
@@ -277,7 +265,7 @@ export class SchmnacyIconButton extends SchmancyElement {
277
265
  ${this.text
278
266
  ? html`<slot></slot>`
279
267
  : html`
280
- <slot style="display:none" @slotchange=${this._handleSlotChange}></slot>
268
+ <slot style="display:none"></slot>
281
269
  <schmancy-icon class=${iconSizeClass}>${this.icon || this._capturedIcon}</schmancy-icon>
282
270
  `
283
271
  }