@mhmo91/schmancy 0.10.19 → 0.10.20

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 (326) hide show
  1. package/custom-elements.json +0 -13
  2. package/dist/agent/{overlay.confirm-body-D3jQyXgA.js → overlay.confirm-body-mYm0zq4k.js} +1 -1
  3. package/dist/agent/{overlay.confirm-body-D3jQyXgA.js.map → overlay.confirm-body-mYm0zq4k.js.map} +1 -1
  4. package/dist/agent/schmancy.agent.js +808 -882
  5. package/dist/agent/schmancy.agent.js.map +1 -1
  6. package/dist/agent/schmancy.manifest.json +1 -9
  7. package/dist/area-C7MNn-3e.cjs +12 -0
  8. package/dist/area-C7MNn-3e.cjs.map +1 -0
  9. package/dist/{area-BIipuSyO.js → area-CRe41aIG.js} +91 -130
  10. package/dist/area-CRe41aIG.js.map +1 -0
  11. package/dist/area.cjs +1 -1
  12. package/dist/area.js +1 -1
  13. package/dist/{autocomplete-Mrb3koUN.js → autocomplete-CRDFL4Ul.js} +2 -2
  14. package/dist/{autocomplete-Mrb3koUN.js.map → autocomplete-CRDFL4Ul.js.map} +1 -1
  15. package/dist/{autocomplete-B8CE5vGw.cjs → autocomplete-CqUl7o0e.cjs} +1 -1
  16. package/dist/{autocomplete-B8CE5vGw.cjs.map → autocomplete-CqUl7o0e.cjs.map} +1 -1
  17. package/dist/autocomplete.cjs +1 -1
  18. package/dist/autocomplete.js +1 -1
  19. package/dist/avatar.cjs +1 -1
  20. package/dist/avatar.js +1 -1
  21. package/dist/badge.cjs +1 -1
  22. package/dist/badge.js +1 -1
  23. package/dist/{boat-OatK_MGh.cjs → boat-BHV5kOlN.cjs} +1 -1
  24. package/dist/{boat-OatK_MGh.cjs.map → boat-BHV5kOlN.cjs.map} +1 -1
  25. package/dist/{boat-CNWIQPA1.js → boat-XajM8A3M.js} +1 -1
  26. package/dist/{boat-CNWIQPA1.js.map → boat-XajM8A3M.js.map} +1 -1
  27. package/dist/boat.cjs +1 -1
  28. package/dist/boat.js +1 -1
  29. package/dist/breadcrumb.cjs +1 -1
  30. package/dist/breadcrumb.js +1 -1
  31. package/dist/{busy-CMKX4oQf.cjs → busy-BlBZ5ZOs.cjs} +1 -1
  32. package/dist/{busy-CMKX4oQf.cjs.map → busy-BlBZ5ZOs.cjs.map} +1 -1
  33. package/dist/{busy-Cetzws-m.js → busy-D8YsqVBf.js} +1 -1
  34. package/dist/{busy-Cetzws-m.js.map → busy-D8YsqVBf.js.map} +1 -1
  35. package/dist/busy.cjs +1 -1
  36. package/dist/busy.js +1 -1
  37. package/dist/button.cjs +15 -9
  38. package/dist/button.cjs.map +1 -1
  39. package/dist/button.js +15 -9
  40. package/dist/button.js.map +1 -1
  41. package/dist/{card-D2k3dRL0.js → card-C9TljY2Z.js} +1 -1
  42. package/dist/{card-D2k3dRL0.js.map → card-C9TljY2Z.js.map} +1 -1
  43. package/dist/{card-8VXoo2C_.cjs → card-yT_St83D.cjs} +1 -1
  44. package/dist/{card-8VXoo2C_.cjs.map → card-yT_St83D.cjs.map} +1 -1
  45. package/dist/card.cjs +1 -1
  46. package/dist/card.js +1 -1
  47. package/dist/{checkbox-8hNsBejz.js → checkbox-BDgh4rge.js} +1 -1
  48. package/dist/{checkbox-8hNsBejz.js.map → checkbox-BDgh4rge.js.map} +1 -1
  49. package/dist/{checkbox-Cq5wzeaY.cjs → checkbox-Dz2lkJs0.cjs} +1 -1
  50. package/dist/{checkbox-Cq5wzeaY.cjs.map → checkbox-Dz2lkJs0.cjs.map} +1 -1
  51. package/dist/checkbox.cjs +1 -1
  52. package/dist/checkbox.js +1 -1
  53. package/dist/{chips-Dx_WvOGk.cjs → chips-M7Dr2npv.cjs} +2 -4
  54. package/dist/chips-M7Dr2npv.cjs.map +1 -0
  55. package/dist/{chips-D1kJrbzo.js → chips-N7fu0hA4.js} +3 -5
  56. package/dist/chips-N7fu0hA4.js.map +1 -0
  57. package/dist/chips.cjs +1 -1
  58. package/dist/chips.js +2 -2
  59. package/dist/connectivity.cjs +1 -1
  60. package/dist/connectivity.js +1 -1
  61. package/dist/content-drawer.cjs +1 -1
  62. package/dist/content-drawer.js +1 -1
  63. package/dist/{date-range-H903Vt_r.cjs → date-range-D2vxD814.cjs} +1 -1
  64. package/dist/{date-range-H903Vt_r.cjs.map → date-range-D2vxD814.cjs.map} +1 -1
  65. package/dist/{date-range-Dv-DM6mB.js → date-range-DFWOMgI3.js} +2 -2
  66. package/dist/{date-range-Dv-DM6mB.js.map → date-range-DFWOMgI3.js.map} +1 -1
  67. package/dist/{date-range-inline-Bvs2ZvEY.cjs → date-range-inline-C5JuZ_Kw.cjs} +1 -1
  68. package/dist/{date-range-inline-Bvs2ZvEY.cjs.map → date-range-inline-C5JuZ_Kw.cjs.map} +1 -1
  69. package/dist/{date-range-inline-TWWnTZlw.js → date-range-inline-D3q1OoKk.js} +1 -1
  70. package/dist/{date-range-inline-TWWnTZlw.js.map → date-range-inline-D3q1OoKk.js.map} +1 -1
  71. package/dist/date-range-inline.cjs +1 -1
  72. package/dist/date-range-inline.js +1 -1
  73. package/dist/date-range.cjs +1 -1
  74. package/dist/date-range.js +1 -1
  75. package/dist/delay.cjs +1 -1
  76. package/dist/delay.js +1 -1
  77. package/dist/{details-Cpg8sH2F.js → details-BrUPmd92.js} +2 -2
  78. package/dist/details-BrUPmd92.js.map +1 -0
  79. package/dist/{details-CwSDur6j.cjs → details-DmDEInaL.cjs} +2 -2
  80. package/dist/details-DmDEInaL.cjs.map +1 -0
  81. package/dist/details.cjs +1 -1
  82. package/dist/details.js +1 -1
  83. package/dist/{divider-Be833gGZ.js → divider-BLijs8ba.js} +1 -1
  84. package/dist/{divider-Be833gGZ.js.map → divider-BLijs8ba.js.map} +1 -1
  85. package/dist/{divider-BNdVLE0H.cjs → divider-B_Ts_-qz.cjs} +1 -1
  86. package/dist/{divider-BNdVLE0H.cjs.map → divider-B_Ts_-qz.cjs.map} +1 -1
  87. package/dist/divider.cjs +1 -1
  88. package/dist/divider.js +1 -1
  89. package/dist/dropdown.cjs +1 -1
  90. package/dist/dropdown.js +1 -1
  91. package/dist/{expand-CtoffNNj.js → expand-C-xSpg7M.js} +2 -2
  92. package/dist/{expand-CtoffNNj.js.map → expand-C-xSpg7M.js.map} +1 -1
  93. package/dist/{expand-BP6RLzHw.cjs → expand-DV5sWUB6.cjs} +1 -1
  94. package/dist/{expand-BP6RLzHw.cjs.map → expand-DV5sWUB6.cjs.map} +1 -1
  95. package/dist/expand.cjs +1 -1
  96. package/dist/expand.js +1 -1
  97. package/dist/{float-CfbQM_2v.cjs → float-LyKef0LY.cjs} +1 -1
  98. package/dist/{float-CfbQM_2v.cjs.map → float-LyKef0LY.cjs.map} +1 -1
  99. package/dist/{float-KmbhaQHA.js → float-Y22yVBE2.js} +1 -1
  100. package/dist/{float-KmbhaQHA.js.map → float-Y22yVBE2.js.map} +1 -1
  101. package/dist/float.cjs +1 -1
  102. package/dist/float.js +1 -1
  103. package/dist/{form-CuBIrKOA.cjs → form-C_smXI2-.cjs} +1 -1
  104. package/dist/{form-CuBIrKOA.cjs.map → form-C_smXI2-.cjs.map} +1 -1
  105. package/dist/{form-8IcmP8uV.js → form-LFkEQkOX.js} +8 -8
  106. package/dist/{form-8IcmP8uV.js.map → form-LFkEQkOX.js.map} +1 -1
  107. package/dist/form.cjs +1 -1
  108. package/dist/form.js +6 -6
  109. package/dist/handover/agent-runtime-followups.md +1 -1
  110. package/dist/handover/agent-runtime-v1.md +3 -3
  111. package/dist/{icons-D7df1ysG.js → icons-B3pFrwKC.js} +1 -1
  112. package/dist/{icons-D7df1ysG.js.map → icons-B3pFrwKC.js.map} +1 -1
  113. package/dist/{icons-BJld4JHp.cjs → icons-CCNy4Egc.cjs} +1 -1
  114. package/dist/{icons-BJld4JHp.cjs.map → icons-CCNy4Egc.cjs.map} +1 -1
  115. package/dist/icons.cjs +1 -1
  116. package/dist/icons.js +1 -1
  117. package/dist/{iframe-DAbgW9tT.js → iframe-BbFlCEyP.js} +1 -1
  118. package/dist/{iframe-DAbgW9tT.js.map → iframe-BbFlCEyP.js.map} +1 -1
  119. package/dist/{iframe-GT6D8l5Z.cjs → iframe-CCcmLZ_K.cjs} +1 -1
  120. package/dist/{iframe-GT6D8l5Z.cjs.map → iframe-CCcmLZ_K.cjs.map} +1 -1
  121. package/dist/iframe.cjs +1 -1
  122. package/dist/iframe.js +1 -1
  123. package/dist/index.cjs +1 -1
  124. package/dist/index.js +27 -27
  125. package/dist/{input-DC6ap_uN.js → input-Dkneo4uA.js} +2 -2
  126. package/dist/{input-DC6ap_uN.js.map → input-Dkneo4uA.js.map} +1 -1
  127. package/dist/{input-chip-c5n547tg.js → input-chip-C1-TYu4v.js} +1 -1
  128. package/dist/{input-chip-c5n547tg.js.map → input-chip-C1-TYu4v.js.map} +1 -1
  129. package/dist/{input-chip-MsiMu-b5.cjs → input-chip-F5NEkkBU.cjs} +1 -1
  130. package/dist/{input-chip-MsiMu-b5.cjs.map → input-chip-F5NEkkBU.cjs.map} +1 -1
  131. package/dist/{input-BE9wEEw4.cjs → input-sBZ89wz1.cjs} +1 -1
  132. package/dist/{input-BE9wEEw4.cjs.map → input-sBZ89wz1.cjs.map} +1 -1
  133. package/dist/input.cjs +1 -1
  134. package/dist/input.js +1 -1
  135. package/dist/json.cjs +1 -1
  136. package/dist/json.js +2 -2
  137. package/dist/kbd.cjs +1 -1
  138. package/dist/kbd.js +1 -1
  139. package/dist/layout.cjs +1 -1
  140. package/dist/layout.js +1 -1
  141. package/dist/{lightbox-HqJBBjAT.cjs → lightbox-B4m5lxGs.cjs} +1 -1
  142. package/dist/{lightbox-HqJBBjAT.cjs.map → lightbox-B4m5lxGs.cjs.map} +1 -1
  143. package/dist/{lightbox-CNX9Eg3U.js → lightbox-D7hYFspE.js} +1 -1
  144. package/dist/{lightbox-CNX9Eg3U.js.map → lightbox-D7hYFspE.js.map} +1 -1
  145. package/dist/lightbox.cjs +1 -1
  146. package/dist/lightbox.js +1 -1
  147. package/dist/{list-bhyuQSyO.cjs → list-C2ycz-yr.cjs} +1 -1
  148. package/dist/{list-bhyuQSyO.cjs.map → list-C2ycz-yr.cjs.map} +1 -1
  149. package/dist/{list-C76Pb-c1.js → list-Ou72tSeq.js} +1 -1
  150. package/dist/{list-C76Pb-c1.js.map → list-Ou72tSeq.js.map} +1 -1
  151. package/dist/list.cjs +1 -1
  152. package/dist/list.js +1 -1
  153. package/dist/{menu-BqKQ-s0C.cjs → menu-ComSx-T0.cjs} +1 -1
  154. package/dist/{menu-BqKQ-s0C.cjs.map → menu-ComSx-T0.cjs.map} +1 -1
  155. package/dist/{menu-C5ksITpG.js → menu-YHbpRa7x.js} +2 -2
  156. package/dist/{menu-C5ksITpG.js.map → menu-YHbpRa7x.js.map} +1 -1
  157. package/dist/menu.cjs +1 -1
  158. package/dist/menu.js +1 -1
  159. package/dist/mixins-B9kY_60p.js +636 -0
  160. package/dist/{mixins-DCVXqL1Q.js.map → mixins-B9kY_60p.js.map} +1 -1
  161. package/dist/mixins-BwGJwK7X.cjs +254 -0
  162. package/dist/{mixins-Du9HMrIG.cjs.map → mixins-BwGJwK7X.cjs.map} +1 -1
  163. package/dist/mixins.cjs +1 -1
  164. package/dist/mixins.js +1 -1
  165. package/dist/nav-drawer.cjs +1 -1
  166. package/dist/nav-drawer.js +1 -1
  167. package/dist/navigation-bar.cjs +1 -1
  168. package/dist/navigation-bar.js +1 -1
  169. package/dist/navigation-rail.cjs +1 -1
  170. package/dist/navigation-rail.js +1 -1
  171. package/dist/{notification-DR3gvWt8.cjs → notification-DZhL0ZEg.cjs} +1 -1
  172. package/dist/{notification-DR3gvWt8.cjs.map → notification-DZhL0ZEg.cjs.map} +1 -1
  173. package/dist/{notification-eZxtr3NN.js → notification-O4Q5pyio.js} +2 -2
  174. package/dist/{notification-eZxtr3NN.js.map → notification-O4Q5pyio.js.map} +1 -1
  175. package/dist/notification.cjs +1 -1
  176. package/dist/notification.js +1 -1
  177. package/dist/{option-CBEHYG4U.js → option-BCks0a4i.js} +1 -1
  178. package/dist/{option-CBEHYG4U.js.map → option-BCks0a4i.js.map} +1 -1
  179. package/dist/{option-BDOKUqTy.cjs → option-C2VKw8Yt.cjs} +1 -1
  180. package/dist/{option-BDOKUqTy.cjs.map → option-C2VKw8Yt.cjs.map} +1 -1
  181. package/dist/option.cjs +1 -1
  182. package/dist/option.js +1 -1
  183. package/dist/{overlay-oxM9OLXP.js → overlay-C0YSnxoV.js} +8 -10
  184. package/dist/overlay-C0YSnxoV.js.map +1 -0
  185. package/dist/{overlay-DG6EeyKt.cjs → overlay-CG1gc1Jw.cjs} +2 -2
  186. package/dist/overlay-CG1gc1Jw.cjs.map +1 -0
  187. package/dist/overlay.cjs +1 -1
  188. package/dist/{overlay.confirm-body-78e1WrN9.cjs → overlay.confirm-body-B-Kmn7LF.cjs} +1 -1
  189. package/dist/{overlay.confirm-body-78e1WrN9.cjs.map → overlay.confirm-body-B-Kmn7LF.cjs.map} +1 -1
  190. package/dist/{overlay.confirm-body-D_P2e7l6.js → overlay.confirm-body-BmOnrKbF.js} +1 -1
  191. package/dist/{overlay.confirm-body-D_P2e7l6.js.map → overlay.confirm-body-BmOnrKbF.js.map} +1 -1
  192. package/dist/overlay.js +3 -3
  193. package/dist/{overlay.service-DQkGPUY7.cjs → overlay.service-BPKV2a8w.cjs} +1 -1
  194. package/dist/{overlay.service-DQkGPUY7.cjs.map → overlay.service-BPKV2a8w.cjs.map} +1 -1
  195. package/dist/{overlay.service-C8NwO4Bx.js → overlay.service-CRoq9Gu-.js} +2 -2
  196. package/dist/{overlay.service-C8NwO4Bx.js.map → overlay.service-CRoq9Gu-.js.map} +1 -1
  197. package/dist/page.cjs +1 -1
  198. package/dist/page.js +2 -2
  199. package/dist/{progress-CMSst_2U.cjs → progress-B9RWAFv5.cjs} +1 -1
  200. package/dist/{progress-CMSst_2U.cjs.map → progress-B9RWAFv5.cjs.map} +1 -1
  201. package/dist/{progress-C4kDZfb7.js → progress-CEEl7vdd.js} +1 -1
  202. package/dist/{progress-C4kDZfb7.js.map → progress-CEEl7vdd.js.map} +1 -1
  203. package/dist/progress.cjs +1 -1
  204. package/dist/progress.js +1 -1
  205. package/dist/radio-group-C2y6H5YY.cjs +19 -0
  206. package/dist/radio-group-C2y6H5YY.cjs.map +1 -0
  207. package/dist/radio-group-VERF_8rC.js +71 -0
  208. package/dist/radio-group-VERF_8rC.js.map +1 -0
  209. package/dist/radio-group.cjs +1 -1
  210. package/dist/radio-group.js +1 -1
  211. package/dist/range.cjs +1 -1
  212. package/dist/range.js +1 -1
  213. package/dist/{scroll-C1klVgSQ.js → scroll-Bj7FsS08.js} +1 -1
  214. package/dist/{scroll-C1klVgSQ.js.map → scroll-Bj7FsS08.js.map} +1 -1
  215. package/dist/{scroll-S-bXF2u6.cjs → scroll-Djz3pJfX.cjs} +1 -1
  216. package/dist/{scroll-S-bXF2u6.cjs.map → scroll-Djz3pJfX.cjs.map} +1 -1
  217. package/dist/{select-UU2pB67h.js → select-ClJj_2AP.js} +3 -3
  218. package/dist/select-ClJj_2AP.js.map +1 -0
  219. package/dist/select-CngphfDB.cjs +56 -0
  220. package/dist/select-CngphfDB.cjs.map +1 -0
  221. package/dist/select.cjs +1 -1
  222. package/dist/select.js +1 -1
  223. package/dist/skeleton.cjs +1 -1
  224. package/dist/skeleton.js +1 -1
  225. package/dist/skills/SKILL.md +12 -0
  226. package/dist/skills/schmancy/SKILL.md +12 -0
  227. package/dist/slider.cjs +1 -1
  228. package/dist/slider.js +1 -1
  229. package/dist/{splash-screen-ChMkAPLU.js → splash-screen-BQsBy3O1.js} +1 -1
  230. package/dist/{splash-screen-ChMkAPLU.js.map → splash-screen-BQsBy3O1.js.map} +1 -1
  231. package/dist/{splash-screen-BvaDkvJU.cjs → splash-screen-CntIFk2h.cjs} +1 -1
  232. package/dist/{splash-screen-BvaDkvJU.cjs.map → splash-screen-CntIFk2h.cjs.map} +1 -1
  233. package/dist/splash-screen.cjs +1 -1
  234. package/dist/splash-screen.js +1 -1
  235. package/dist/{src-DnunCC4X.js → src-BAXhEv8f.js} +32 -32
  236. package/dist/{src-DnunCC4X.js.map → src-BAXhEv8f.js.map} +1 -1
  237. package/dist/{src-BIlD63Cz.cjs → src-ChFa-FDD.cjs} +1 -1
  238. package/dist/{src-BIlD63Cz.cjs.map → src-ChFa-FDD.cjs.map} +1 -1
  239. package/dist/steps.cjs +1 -1
  240. package/dist/steps.js +1 -1
  241. package/dist/{surface-DCRy-EyT.js → surface-CHUJSY1o.js} +1 -1
  242. package/dist/{surface-DCRy-EyT.js.map → surface-CHUJSY1o.js.map} +1 -1
  243. package/dist/{surface-DWwQDX9r.cjs → surface-CXmQuXun.cjs} +1 -1
  244. package/dist/{surface-DWwQDX9r.cjs.map → surface-CXmQuXun.cjs.map} +1 -1
  245. package/dist/surface.cjs +1 -1
  246. package/dist/surface.js +1 -1
  247. package/dist/switch.cjs +1 -1
  248. package/dist/switch.js +1 -1
  249. package/dist/table.cjs +1 -1
  250. package/dist/table.js +1 -1
  251. package/dist/{tabs-lxQHWEb7.cjs → tabs-Bku0sC0p.cjs} +1 -1
  252. package/dist/{tabs-lxQHWEb7.cjs.map → tabs-Bku0sC0p.cjs.map} +1 -1
  253. package/dist/{tabs-CkDNLbiS.js → tabs-DPVX21WM.js} +1 -1
  254. package/dist/{tabs-CkDNLbiS.js.map → tabs-DPVX21WM.js.map} +1 -1
  255. package/dist/tabs.cjs +1 -1
  256. package/dist/tabs.js +1 -1
  257. package/dist/teleport.cjs +1 -1
  258. package/dist/teleport.js +1 -1
  259. package/dist/{textarea-CNa4dSvF.cjs → textarea-CqJNviYi.cjs} +1 -1
  260. package/dist/{textarea-CNa4dSvF.cjs.map → textarea-CqJNviYi.cjs.map} +1 -1
  261. package/dist/{textarea-DkfGmRSI.js → textarea-D6z1UZzs.js} +1 -1
  262. package/dist/{textarea-DkfGmRSI.js.map → textarea-D6z1UZzs.js.map} +1 -1
  263. package/dist/textarea.cjs +1 -1
  264. package/dist/textarea.js +1 -1
  265. package/dist/{theme-CMyXTDht.cjs → theme-BpKVBJCr.cjs} +1 -1
  266. package/dist/{theme-CMyXTDht.cjs.map → theme-BpKVBJCr.cjs.map} +1 -1
  267. package/dist/{theme-CNWRYdfn.js → theme-DbHfINBV.js} +1 -1
  268. package/dist/{theme-CNWRYdfn.js.map → theme-DbHfINBV.js.map} +1 -1
  269. package/dist/{theme-button-CixloLin.js → theme-button-BeU8Nbs2.js} +1 -1
  270. package/dist/{theme-button-CixloLin.js.map → theme-button-BeU8Nbs2.js.map} +1 -1
  271. package/dist/{theme-button-kMhsX5Oe.cjs → theme-button-Cof9I85G.cjs} +1 -1
  272. package/dist/{theme-button-kMhsX5Oe.cjs.map → theme-button-Cof9I85G.cjs.map} +1 -1
  273. package/dist/theme-button.cjs +1 -1
  274. package/dist/theme-button.js +1 -1
  275. package/dist/theme.cjs +1 -1
  276. package/dist/theme.js +2 -2
  277. package/dist/tree.cjs +1 -1
  278. package/dist/tree.js +1 -1
  279. package/dist/typography.cjs +1 -1
  280. package/dist/typography.js +1 -1
  281. package/dist/visually-hidden.cjs +1 -1
  282. package/dist/visually-hidden.js +1 -1
  283. package/dist/{window-qaGFMn_4.cjs → window-Cql1aIX2.cjs} +1 -1
  284. package/dist/{window-qaGFMn_4.cjs.map → window-Cql1aIX2.cjs.map} +1 -1
  285. package/dist/{window-BcvDNi9D.js → window-DmMNsos0.js} +1 -1
  286. package/dist/{window-BcvDNi9D.js.map → window-DmMNsos0.js.map} +1 -1
  287. package/dist/window.cjs +1 -1
  288. package/dist/window.js +1 -1
  289. package/package.json +1 -1
  290. package/skills/schmancy/SKILL.md +12 -0
  291. package/src/CLAUDE.md +20 -0
  292. package/src/area/area.component.ts +155 -342
  293. package/src/button/button.ts +8 -5
  294. package/src/button/icon-button.ts +8 -5
  295. package/src/chips/filter-chip.ts +1 -3
  296. package/src/details/details.ts +1 -1
  297. package/src/form/fields/radio-group/radio-button.ts +22 -44
  298. package/src/form/fields/radio-group/radio-group.ts +20 -75
  299. package/src/form/fields/select/select.ts +3 -2
  300. package/src/overlay/overlay.component.ts +29 -39
  301. package/src/overlay/overlay.positioning.ts +10 -2
  302. package/src/state/schmancy-state.html +897 -0
  303. package/src/state/schmancy-state.md +981 -0
  304. package/types/src/area/area.component.d.ts +0 -15
  305. package/types/src/button/icon-button.d.ts +1 -1
  306. package/types/src/form/fields/radio-group/radio-button.d.ts +2 -5
  307. package/types/src/form/fields/radio-group/radio-group.d.ts +2 -10
  308. package/types/src/overlay/overlay.positioning.d.ts +9 -1
  309. package/dist/area-BIipuSyO.js.map +0 -1
  310. package/dist/area-C-EMiNEE.cjs +0 -12
  311. package/dist/area-C-EMiNEE.cjs.map +0 -1
  312. package/dist/chips-D1kJrbzo.js.map +0 -1
  313. package/dist/chips-Dx_WvOGk.cjs.map +0 -1
  314. package/dist/details-Cpg8sH2F.js.map +0 -1
  315. package/dist/details-CwSDur6j.cjs.map +0 -1
  316. package/dist/mixins-DCVXqL1Q.js +0 -636
  317. package/dist/mixins-Du9HMrIG.cjs +0 -254
  318. package/dist/overlay-DG6EeyKt.cjs.map +0 -1
  319. package/dist/overlay-oxM9OLXP.js.map +0 -1
  320. package/dist/radio-group-DB9D2ZkA.js +0 -108
  321. package/dist/radio-group-DB9D2ZkA.js.map +0 -1
  322. package/dist/radio-group-dVUvYFq7.cjs +0 -40
  323. package/dist/radio-group-dVUvYFq7.cjs.map +0 -1
  324. package/dist/select-UU2pB67h.js.map +0 -1
  325. package/dist/select-fu_-rZyn.cjs +0 -56
  326. package/dist/select-fu_-rZyn.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay-oxM9OLXP.js","names":[],"sources":["../src/overlay/overlay.animations.ts","../src/overlay/overlay.gestures.ts","../src/overlay/overlay.layout.ts","../src/overlay/overlay.positioning.ts","../src/overlay/overlay.component.ts"],"sourcesContent":["import {\n\tDURATION_EXIT,\n\tgetEasing,\n\tSPRING_GENTLE,\n\tSPRING_SMOOTH,\n\tSPRING_SNAPPY,\n} from '../utils/animation'\nimport { reducedMotion$ } from '../directives/reduced-motion'\nimport type { Anchor, OverlayLayout } from './overlay.types'\n\n/**\n * WAAPI keyframes + options per layout + direction.\n *\n * One animation vocabulary — no per-element bespoke keyframes. Aligns\n * with the `animation` skill (spring physics presets). Every easing runs\n * through `getEasing()` so modern browsers (that support\n * `animation-timing-function: linear(0, 1)`) get the true `linear()`\n * spring expression while older browsers fall through to the cubic-bezier\n * fallback. Honors `prefers-reduced-motion` by collapsing transforms to\n * opacity-only.\n *\n * Anchor-origin bloom: the caller computes\n * `anchorOriginVars(anchor, surfaceRect)` and writes the resulting CSS\n * custom properties onto the surface element BEFORE triggering the\n * entrance animation. Keyframes reference those vars via\n * `transform-origin: var(--schmancy-overlay-origin-x, 50%) var(...)`, so\n * the surface scales OUT of the click point — not from its own centre.\n */\n\n/**\n * Shape matches both DOM `AnimationEffectTiming` and\n * `KeyframeAnimationOptions` so it passes structural checks in both\n * older and newer `lib.dom.d.ts` vintages.\n */\nexport interface AnimationSpec {\n\tkeyframes: Keyframe[]\n\toptions: {\n\t\tduration: number\n\t\teasing: string\n\t\tfill?: FillMode\n\t}\n}\n\n/**\n * Module-scope reduced-motion state, kept in sync with the house\n * `reducedMotion$` BehaviorSubject. The subscribe has no teardown —\n * module lifetime IS the subscription lifetime (house rxjs rule 4:\n * module singletons don't need explicit teardown).\n */\nlet reducedMotion = reducedMotion$.value\nreducedMotion$.subscribe((v) => {\n\treducedMotion = v\n})\n\nconst ORIGIN_X_VAR = '--schmancy-overlay-origin-x'\nconst ORIGIN_Y_VAR = '--schmancy-overlay-origin-y'\nconst ORIGIN_CSS = `var(${ORIGIN_X_VAR}, 50%) var(${ORIGIN_Y_VAR}, 50%)`\n\nfunction clampPercent(value: number): number {\n\tif (Number.isNaN(value) || !Number.isFinite(value)) return 50\n\treturn Math.max(0, Math.min(100, value))\n}\n\nfunction getAnchorCenter(anchor: Anchor): { x: number; y: number } {\n\t// Element | VirtualAnchor — anything exposing getBoundingClientRect()\n\tif (\n\t\ttypeof (anchor as { getBoundingClientRect?: unknown }).getBoundingClientRect === 'function'\n\t) {\n\t\tconst r = (anchor as { getBoundingClientRect(): DOMRect }).getBoundingClientRect()\n\t\treturn { x: r.left + r.width / 2, y: r.top + r.height / 2 }\n\t}\n\t// DOMRect — has left/top/width/height but no getBoundingClientRect()\n\tif (\n\t\ttypeof (anchor as DOMRect).width === 'number' &&\n\t\ttypeof (anchor as DOMRect).height === 'number' &&\n\t\ttypeof (anchor as DOMRect).left === 'number' &&\n\t\ttypeof (anchor as DOMRect).top === 'number'\n\t) {\n\t\tconst r = anchor as DOMRect\n\t\treturn { x: r.left + r.width / 2, y: r.top + r.height / 2 }\n\t}\n\t// MouseEvent / PointerEvent\n\tif (typeof (anchor as MouseEvent).clientX === 'number' && typeof (anchor as MouseEvent).clientY === 'number') {\n\t\tconst e = anchor as MouseEvent\n\t\treturn { x: e.clientX, y: e.clientY }\n\t}\n\t// TouchEvent\n\tif (\n\t\ttypeof (anchor as TouchEvent).touches !== 'undefined' &&\n\t\t(anchor as TouchEvent).touches.length > 0\n\t) {\n\t\tconst t = (anchor as TouchEvent).touches[0]\n\t\treturn { x: t.clientX, y: t.clientY }\n\t}\n\t// Plain { x, y } point\n\tconst pt = anchor as { x: number; y: number }\n\treturn { x: pt.x, y: pt.y }\n}\n\n/**\n * Compute CSS-var values for the anchor-relative transform origin.\n * Caller writes the returned record onto the surface element's style\n * before triggering the entrance animation. When no anchor is present,\n * returns sensible per-layout defaults (caller picks which to use):\n * - centered → 50% 50% (self-centre)\n * - sheet → 50% 100% (rises from bottom edge)\n * - anchored → computed from the anchor's position relative to the\n * surface rect\n */\nexport function anchorOriginVars(\n\tanchor: Anchor | undefined,\n\tsurfaceRect: DOMRect | { left: number; top: number; width: number; height: number },\n): Record<string, string> {\n\tif (!anchor) {\n\t\treturn {\n\t\t\t[ORIGIN_X_VAR]: '50%',\n\t\t\t[ORIGIN_Y_VAR]: '50%',\n\t\t}\n\t}\n\tconst { x, y } = getAnchorCenter(anchor)\n\tif (!surfaceRect.width || !surfaceRect.height) {\n\t\treturn {\n\t\t\t[ORIGIN_X_VAR]: '50%',\n\t\t\t[ORIGIN_Y_VAR]: '50%',\n\t\t}\n\t}\n\tconst originX = clampPercent(((x - surfaceRect.left) / surfaceRect.width) * 100)\n\tconst originY = clampPercent(((y - surfaceRect.top) / surfaceRect.height) * 100)\n\treturn {\n\t\t[ORIGIN_X_VAR]: `${originX}%`,\n\t\t[ORIGIN_Y_VAR]: `${originY}%`,\n\t}\n}\n\nexport function surfaceAnimation(layout: OverlayLayout, direction: 'in' | 'out'): AnimationSpec {\n\tif (reducedMotion) {\n\t\t// Opacity-only; explicit reset to { opacity: 1, transform: none } on `in`\n\t\t// so any leftover transform from a prior `out` doesn't persist.\n\t\treturn direction === 'in'\n\t\t\t? {\n\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t{ opacity: 0, transform: 'none' },\n\t\t\t\t\t\t{ opacity: 1, transform: 'none' },\n\t\t\t\t\t],\n\t\t\t\t\toptions: { duration: 1, easing: 'linear', fill: 'forwards' },\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t{ opacity: 1, transform: 'none' },\n\t\t\t\t\t\t{ opacity: 0, transform: 'none' },\n\t\t\t\t\t],\n\t\t\t\t\toptions: { duration: 1, easing: 'linear', fill: 'forwards' },\n\t\t\t\t}\n\t}\n\n\tswitch (layout) {\n\t\tcase 'centered':\n\t\t\t// Anchor-origin bloom: scale 0.6 → 1 from the var-driven origin.\n\t\t\t// More aggressive than dialog's 0.92 because the origin carries the\n\t\t\t// spatial work, so less translate is needed. Caller sets the origin\n\t\t\t// vars via anchorOriginVars() before triggering this animation.\n\t\t\treturn direction === 'in'\n\t\t\t\t? {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'scale(0.6)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'scale(1)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: SPRING_SNAPPY.duration,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_SNAPPY),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'scale(1)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'scale(0.95)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: DURATION_EXIT,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_SMOOTH),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\tcase 'sheet':\n\t\t\treturn direction === 'in'\n\t\t\t\t? {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'translateY(100%)' },\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'translateY(0)' },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: SPRING_GENTLE.duration,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_GENTLE),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'translateY(0)' },\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'translateY(100%)' },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: DURATION_EXIT,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_SMOOTH),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\tcase 'anchored':\n\t\t\t// Anchored surfaces get a scale-from-origin treatment too — the\n\t\t\t// positioning strategy (Popover API / CSS Anchor / Floating UI) owns\n\t\t\t// the final placement; the surface merely blooms from the anchor.\n\t\t\treturn direction === 'in'\n\t\t\t\t? {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'scale(0.85)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'scale(1)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: SPRING_SNAPPY.duration,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_SNAPPY),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkeyframes: [\n\t\t\t\t\t\t\t{ opacity: 1, transform: 'scale(1)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t\t{ opacity: 0, transform: 'scale(0.92)', transformOrigin: ORIGIN_CSS },\n\t\t\t\t\t\t],\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tduration: DURATION_EXIT,\n\t\t\t\t\t\t\teasing: getEasing(SPRING_SMOOTH),\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t}\n}\n\n/**\n * FLIP (First / Last / Invert / Play) animation from `before` rect to\n * `after` rect. Caller has already moved the element between the two\n * states; this produces the WAAPI spec that animates the delta back.\n *\n * Used by the ResizeObserver-driven layout re-resolve in the overlay\n * element — when content grows past threshold mid-session and the\n * layout switches from centered → sheet, this animates the transition\n * instead of a hard cut.\n *\n * Reduced-motion collapses to an instant 1ms no-op; caller should check\n * `reducedMotion` (not exported) — or just run this and tolerate the\n * 1ms animation.\n */\nexport function flipAnimation(\n\tbefore: DOMRect | { left: number; top: number; width: number; height: number },\n\tafter: DOMRect | { left: number; top: number; width: number; height: number },\n): AnimationSpec {\n\tif (reducedMotion) {\n\t\treturn {\n\t\t\tkeyframes: [{ transform: 'none' }, { transform: 'none' }],\n\t\t\toptions: { duration: 1, easing: 'linear', fill: 'forwards' },\n\t\t}\n\t}\n\tconst dx = before.left - after.left\n\tconst dy = before.top - after.top\n\tconst sx = after.width > 0 ? before.width / after.width : 1\n\tconst sy = after.height > 0 ? before.height / after.height : 1\n\treturn {\n\t\tkeyframes: [\n\t\t\t{\n\t\t\t\ttransform: `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`,\n\t\t\t\ttransformOrigin: 'top left',\n\t\t\t},\n\t\t\t{ transform: 'none', transformOrigin: 'top left' },\n\t\t],\n\t\toptions: {\n\t\t\tduration: SPRING_SMOOTH.duration,\n\t\t\teasing: getEasing(SPRING_SMOOTH),\n\t\t\tfill: 'forwards',\n\t\t},\n\t}\n}\n","import { filter, fromEvent, merge, Observable, Subject, take, takeUntil, tap } from 'rxjs'\n\n/**\n * Swipe-to-dismiss gesture for sheet-layout overlays.\n *\n * Pointer-event based — a single pipeline covers touch, mouse, pen, and\n * any future pointer source. Without a visible drag handle, the gesture\n * only starts within the top DRAG_START_TOP_PX band of the surface (a\n * standard pull-to-dismiss convention). Escape + backdrop click cover\n * the non-pointer dismiss paths via the component's modal-tier listeners.\n *\n * RxJS-native (rxjs skill principle 3: every async source is an Observable).\n * Thresholds are policy constants, not magic numbers.\n */\n\n/** Distance (px) past which the gesture dismisses. */\nexport const DISMISS_DISTANCE_PX = 80\n/** Distance as fraction of sheet height past which the gesture dismisses. */\nexport const DISMISS_DISTANCE_FRACTION = 0.25 // Vaul's value — feels right.\n/** Velocity (px/ms) past which the gesture dismisses even short of distance. */\nexport const DISMISS_VELOCITY_PX_PER_MS = 0.4 // Vaul's value.\n/** Drag only starts if pointerdown is within this top band (unless a drag handle is used). */\nexport const DRAG_START_TOP_PX = 40\n/** Snap-back animation duration when gesture doesn't pass threshold. */\nexport const SNAP_BACK_MS = 300\n\n/**\n * Logarithmic rubber-band damping for upward (negative) drag past the\n * top detent. Pulled from Vaul — `8 * (log(v + 1) - 2)` — diminishing\n * returns that feel physical, unlike the linear × 0.2 this replaces.\n *\n * Applied only to upward motion; downward drag tracks 1:1.\n */\nexport function logDamp(delta: number): number {\n\tif (delta >= 0) return delta\n\tconst abs = -delta\n\treturn -Math.max(0, 8 * (Math.log(abs + 1) - 2))\n}\n\nexport interface SwipeInputs {\n\t/** The surface element to track gestures on. */\n\tsurface: HTMLElement\n\t/** Optional drag handle. When provided, drag can start from anywhere on\n\t * the handle; without it, drag must start in the top DRAG_START_TOP_PX band. */\n\tdragHandle?: HTMLElement | null\n\t/** Completes the gesture stream (component disconnect / layout change). */\n\tuntil$: Observable<unknown>\n}\n\n/**\n * Emits exactly once when the user commits to dismissing the sheet\n * (distance OR velocity threshold passed). Works for touch, mouse, and\n * pen via the Pointer Events API. During an in-progress drag the\n * surface's `transform` is updated directly for 1:1 tracking. On\n * release-but-not-dismissed, the surface snaps back via a CSS transition.\n */\nexport function swipeToDismiss$(inputs: SwipeInputs): Observable<'dismiss'> {\n\tconst { surface, dragHandle, until$ } = inputs\n\n\treturn new Observable<'dismiss'>((subscriber) => {\n\t\tconst dragTarget = dragHandle ?? surface\n\t\tconst stopCurrent$ = new Subject<void>()\n\n\t\tlet dragging = false\n\t\tlet activePointerId: number | null = null\n\t\tlet startY = 0\n\t\tlet startTime = 0\n\t\tlet currentDelta = 0\n\n\t\tconst pointerDown$ = fromEvent<PointerEvent>(dragTarget, 'pointerdown').pipe(\n\t\t\t// Primary button / primary finger only. For touch, isPrimary also\n\t\t\t// covers the pinch-zoom guard (only one finger has isPrimary=true).\n\t\t\tfilter((e) => e.isPrimary && (e.pointerType !== 'mouse' || e.button === 0)),\n\t\t\t// Without a dedicated drag handle, require start in the top band.\n\t\t\tfilter((e) => {\n\t\t\t\tif (dragHandle) return true\n\t\t\t\tconst rect = surface.getBoundingClientRect()\n\t\t\t\treturn e.clientY - rect.top <= DRAG_START_TOP_PX\n\t\t\t}),\n\t\t\ttap((e) => {\n\t\t\t\tdragging = true\n\t\t\t\tactivePointerId = e.pointerId\n\t\t\t\tstartY = e.clientY\n\t\t\t\tstartTime = performance.now()\n\t\t\t\tcurrentDelta = 0\n\t\t\t\tsurface.style.transition = 'none'\n\t\t\t\tsurface.style.willChange = 'transform'\n\t\t\t\t// Capture so pointermove fires even if the pointer leaves the element\n\t\t\t\t// (covers the \"drag from handle, move past surface edge\" case).\n\t\t\t\ttry {\n\t\t\t\t\t;(dragTarget as Element).setPointerCapture?.(e.pointerId)\n\t\t\t\t} catch {\n\t\t\t\t\t// setPointerCapture can throw on detached elements; safe to ignore.\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\n\t\tconst pointerMove$ = fromEvent<PointerEvent>(dragTarget, 'pointermove').pipe(\n\t\t\tfilter(() => dragging),\n\t\t\tfilter((e) => e.pointerId === activePointerId),\n\t\t\ttap((e) => {\n\t\t\t\tconst deltaY = e.clientY - startY\n\t\t\t\tcurrentDelta = logDamp(deltaY)\n\t\t\t\tsurface.style.transform = `translateY(${currentDelta}px)`\n\t\t\t\t// preventDefault is a no-op on default Pointer Events but avoids\n\t\t\t\t// accidental text selection / page scroll during the drag.\n\t\t\t\tif (e.cancelable) e.preventDefault()\n\t\t\t}),\n\t\t)\n\n\t\tconst pointerEnd$ = merge(\n\t\t\tfromEvent<PointerEvent>(dragTarget, 'pointerup'),\n\t\t\tfromEvent<PointerEvent>(dragTarget, 'pointercancel'),\n\t\t\tfromEvent<PointerEvent>(dragTarget, 'lostpointercapture'),\n\t\t).pipe(\n\t\t\tfilter(() => dragging),\n\t\t\tfilter((e) => e.pointerId === activePointerId),\n\t\t\ttap(() => {\n\t\t\t\tdragging = false\n\t\t\t\tconst pointerId = activePointerId\n\t\t\t\tactivePointerId = null\n\t\t\t\ttry {\n\t\t\t\t\tif (pointerId !== null) (dragTarget as Element).releasePointerCapture?.(pointerId)\n\t\t\t\t} catch {\n\t\t\t\t\t// same reason as setPointerCapture — ignore.\n\t\t\t\t}\n\n\t\t\t\tconst elapsed = Math.max(1, performance.now() - startTime)\n\t\t\t\tconst velocity = currentDelta / elapsed\n\t\t\t\tconst surfaceHeight = surface.getBoundingClientRect().height\n\t\t\t\tconst distanceThreshold = Math.min(DISMISS_DISTANCE_PX, surfaceHeight * DISMISS_DISTANCE_FRACTION)\n\n\t\t\t\tconst shouldDismiss =\n\t\t\t\t\tcurrentDelta > distanceThreshold ||\n\t\t\t\t\t(currentDelta > 20 && velocity > DISMISS_VELOCITY_PX_PER_MS)\n\n\t\t\t\tsurface.style.willChange = ''\n\n\t\t\t\tif (shouldDismiss) {\n\t\t\t\t\t// Finish translate off-screen for visual continuity with the dismiss\n\t\t\t\t\t// animation; the caller's teardown will unmount.\n\t\t\t\t\tsurface.style.transition = `transform ${SNAP_BACK_MS}ms cubic-bezier(0.16, 1, 0.3, 1)`\n\t\t\t\t\tsurface.style.transform = 'translateY(100%)'\n\t\t\t\t\tsubscriber.next('dismiss')\n\t\t\t\t\tsubscriber.complete()\n\t\t\t\t} else {\n\t\t\t\t\t// Snap back to 0.\n\t\t\t\t\tsurface.style.transition = `transform ${SNAP_BACK_MS}ms cubic-bezier(0.16, 1, 0.3, 1)`\n\t\t\t\t\tsurface.style.transform = 'translateY(0)'\n\t\t\t\t}\n\t\t\t}),\n\t\t)\n\n\t\tmerge(pointerDown$, pointerMove$, pointerEnd$)\n\t\t\t.pipe(takeUntil(merge(stopCurrent$, until$)))\n\t\t\t.subscribe()\n\n\t\treturn () => {\n\t\t\tstopCurrent$.next()\n\t\t\tstopCurrent$.complete()\n\t\t\tsurface.style.transition = ''\n\t\t\tsurface.style.transform = ''\n\t\t\tsurface.style.willChange = ''\n\t\t}\n\t}).pipe(take(1))\n}\n\n","import type { Anchor, OverlayLayout, VirtualAnchor } from './overlay.types'\n\n/**\n * Layout dispatch engine — pure function of (anchor, content, viewport).\n * No DOM access, no side effects — testable with synthetic inputs.\n *\n * Thresholds are policy constants, not magic numbers. Changes are visible\n * as named-constant diffs, not hidden in inline literals (state skill:\n * \"thresholds ARE the policy\").\n */\n\n/** Below this viewport width, every overlay becomes a bottom sheet. */\nexport const NARROW_VIEWPORT_PX = 640\n\n/** Content taller than this fraction of viewport height → sheet. */\nexport const TALL_CONTENT_FRACTION = 0.8\n\n/** Content wider than this fraction of viewport width → sheet. */\nexport const WIDE_CONTENT_FRACTION = 0.9\n\n/** Floating UI / CSS anchor-positioning safety padding. */\nexport const ANCHOR_FIT_PADDING_PX = 16\n\nexport interface LayoutInputs {\n\tanchor?: Anchor\n\tcontent: { width: number; height: number }\n\tviewport: {\n\t\twidth: number\n\t\theight: number\n\t\t/** `matchMedia('(pointer: coarse)').matches` at call time. */\n\t\tisCoarsePointer: boolean\n\t}\n}\n\n/**\n * Priority order:\n * 1. viewport / content forces sheet\n * 2. anchor provided → anchored (the novel default)\n * 3. fallback → centered\n *\n * Floating UI's `flip` + `shift` + `size` middleware handles \"anchor\n * doesn't fit initially\" — it returns a fitting position rather than\n * rejecting. So step 2 does NOT branch on \"does the anchor fit?\";\n * Floating UI's output IS the answer. If content is genuinely too\n * large for any anchored position, step 1 already routed to sheet.\n */\nexport function resolveLayout(inputs: LayoutInputs): OverlayLayout {\n\tconst { anchor, content, viewport } = inputs\n\n\tconst isNarrow = viewport.width < NARROW_VIEWPORT_PX\n\tconst isCoarse = viewport.isCoarsePointer\n\tconst contentTall = content.height > viewport.height * TALL_CONTENT_FRACTION\n\tconst contentWide = content.width > viewport.width * WIDE_CONTENT_FRACTION\n\n\tif (isNarrow || isCoarse || contentTall || contentWide) {\n\t\treturn 'sheet'\n\t}\n\n\tif (anchor !== undefined) {\n\t\treturn 'anchored'\n\t}\n\n\treturn 'centered'\n}\n\n/**\n * Read the current viewport + pointer inputs. Separated so tests can\n * substitute synthetic inputs and the `resolveLayout` fn stays pure.\n */\nexport function readViewport(): LayoutInputs['viewport'] {\n\treturn {\n\t\twidth: window.innerWidth,\n\t\theight: window.innerHeight,\n\t\tisCoarsePointer: window.matchMedia('(pointer: coarse)').matches,\n\t}\n}\n\n/**\n * Resolved reference the positioning strategies consume.\n *\n * `el` is populated when the anchor is an HTMLElement — the Popover API\n * tier uses it directly via the `anchor=<id>` attribute, and Tier 1 / CSS\n * Anchor Positioning sets `element.style.anchorName` on it.\n *\n * `virtual` is populated for point/rect/TouchEvent anchors — Floating UI\n * accepts any object exposing `getBoundingClientRect()` as a virtual\n * reference. The Popover API path cannot use virtual references, so a\n * caller passing a point / DOMRect / event forces Tier 3 (or Tier 2 with\n * Floating UI, not CSS Anchor Positioning).\n */\nexport interface ResolvedAnchor {\n\tel?: HTMLElement\n\tvirtual?: VirtualAnchor\n}\n\n/**\n * Normalise an `Anchor` input into the shape the positioning strategies\n * accept. One function, one decision: element wins if present; otherwise\n * synthesize a zero-size virtual reference at the anchor's point.\n *\n * Called by the overlay element during `open()` before dispatching to\n * `pickPositioner(resolved)`.\n */\nexport function resolveAnchorRef(anchor: Anchor | undefined): ResolvedAnchor | undefined {\n\tif (!anchor) return undefined\n\n\t// HTMLElement — native element reference.\n\tif (typeof HTMLElement !== 'undefined' && anchor instanceof HTMLElement) {\n\t\treturn { el: anchor }\n\t}\n\n\t// Any other object with getBoundingClientRect — treat as virtual.\n\tif (typeof (anchor as { getBoundingClientRect?: unknown }).getBoundingClientRect === 'function') {\n\t\treturn {\n\t\t\tvirtual: {\n\t\t\t\tgetBoundingClientRect: () => (anchor as { getBoundingClientRect(): DOMRect }).getBoundingClientRect(),\n\t\t\t},\n\t\t}\n\t}\n\n\t// DOMRect — fixed rect; synthesize a virtual that returns it verbatim.\n\tif (\n\t\ttypeof (anchor as DOMRect).width === 'number' &&\n\t\ttypeof (anchor as DOMRect).height === 'number' &&\n\t\ttypeof (anchor as DOMRect).left === 'number' &&\n\t\ttypeof (anchor as DOMRect).top === 'number'\n\t) {\n\t\tconst rect = anchor as DOMRect\n\t\treturn {\n\t\t\tvirtual: {\n\t\t\t\tgetBoundingClientRect: () => rect,\n\t\t\t},\n\t\t}\n\t}\n\n\t// MouseEvent / PointerEvent — zero-size rect at click point.\n\tif (typeof (anchor as MouseEvent).clientX === 'number' && typeof (anchor as MouseEvent).clientY === 'number') {\n\t\tconst e = anchor as MouseEvent\n\t\tconst rect = makePointRect(e.clientX, e.clientY)\n\t\treturn { virtual: { getBoundingClientRect: () => rect } }\n\t}\n\n\t// TouchEvent — zero-size rect at first touch point.\n\tif (\n\t\ttypeof (anchor as TouchEvent).touches !== 'undefined' &&\n\t\t(anchor as TouchEvent).touches.length > 0\n\t) {\n\t\tconst t = (anchor as TouchEvent).touches[0]\n\t\tconst rect = makePointRect(t.clientX, t.clientY)\n\t\treturn { virtual: { getBoundingClientRect: () => rect } }\n\t}\n\n\t// { x, y } point — zero-size rect at coords.\n\tconst pt = anchor as { x: number; y: number }\n\tconst rect = makePointRect(pt.x, pt.y)\n\treturn { virtual: { getBoundingClientRect: () => rect } }\n}\n\n/**\n * Construct a DOMRect-compatible object for a zero-width / zero-height\n * point. Avoids `new DOMRect(...)` which isn't constructable across all\n * lib.dom.d.ts vintages.\n */\nfunction makePointRect(x: number, y: number): DOMRect {\n\treturn {\n\t\tx,\n\t\ty,\n\t\twidth: 0,\n\t\theight: 0,\n\t\tleft: x,\n\t\tright: x,\n\t\ttop: y,\n\t\tbottom: y,\n\t\ttoJSON() {\n\t\t\treturn { x, y, width: 0, height: 0, left: x, right: x, top: y, bottom: y }\n\t\t},\n\t}\n}\n","import {\n\tautoUpdate,\n\tcomputePosition,\n\tflip,\n\toffset,\n\tshift,\n\tsize,\n\ttype Placement,\n} from '@floating-ui/dom'\nimport { Observable } from 'rxjs'\nimport { ANCHOR_FIT_PADDING_PX, type ResolvedAnchor } from './overlay.layout'\nimport type { OverlayPlacement, OverlayTier } from './overlay.types'\n\n/**\n * Three-tier positioning ladder for anchored overlays. Public API of the\n * overlay doesn't change based on the tier — the strategy is picked\n * internally by feature-detection.\n *\n * Tier 1 — CSS Anchor Positioning (Popover + `anchor-name` / `position-anchor`)\n * Zero-JS position tracking. Chromium-only today.\n *\n * Tier 2 — Popover API + Floating UI\n * Native top-layer + light-dismiss + Esc from `popover=\"auto\"`, Floating\n * UI middleware for the position math. Safari 17+, Chrome 114+, Firefox 125+.\n *\n * Tier 3 — Floating UI only\n * Fallback for browsers without the Popover API. Caller provides manual\n * backdrop + click-outside + Esc wiring.\n */\n\n/**\n * Feature-detection snapshot captured at module load. Frozen so consumers\n * can safely destructure and compare.\n */\nexport const CAPS = Object.freeze({\n\tpopover:\n\t\ttypeof HTMLElement !== 'undefined' &&\n\t\t'popover' in HTMLElement.prototype &&\n\t\ttypeof (HTMLElement.prototype as unknown as { showPopover?: () => void }).showPopover === 'function',\n\tcssAnchor:\n\t\ttypeof CSS !== 'undefined' &&\n\t\ttypeof CSS.supports === 'function' &&\n\t\tCSS.supports('anchor-name: --x'),\n})\n\n/**\n * Pick the positioning tier for an anchor.\n *\n * CSS Anchor Positioning (Tier 1) requires a real element anchor — you\n * can't point `anchor-name` at a DOMRect or a coord. A point/rect anchor\n * forces Tier 2 (or Tier 3 if popover isn't supported).\n */\nexport function pickPositioner(anchor: ResolvedAnchor): OverlayTier {\n\tif (CAPS.popover && CAPS.cssAnchor && anchor.el) return 'css-anchor'\n\tif (CAPS.popover) return 'popover-fui'\n\treturn 'fui-only'\n}\n\n/* ======================================================================= *\n * Tier 1 — Popover API + CSS Anchor *\n * ======================================================================= */\n\n/**\n * Set up CSS Anchor Positioning. Assigns a unique `anchor-name` to the\n * anchor element and injects a stylesheet into the shadow root that\n * positions the surface relative to it. No JS running per frame.\n *\n * Returns a cleanup function that removes the injected styles and the\n * anchor-name from the anchor element.\n */\nexport function positionCSSAnchor(\n\tsurface: HTMLElement,\n\tanchor: ResolvedAnchor,\n\tshadowRoot: ShadowRoot,\n\topts: { id: string; placement?: OverlayPlacement } = { id: '' },\n): () => void {\n\tif (!anchor.el) {\n\t\tthrow new Error('positionCSSAnchor requires an element anchor')\n\t}\n\tconst anchorEl = anchor.el\n\tconst anchorName = `--ov-${opts.id || Math.random().toString(36).slice(2, 10)}`\n\tconst placement = opts.placement ?? 'bottom-start'\n\n\t// Save any prior anchor-name so we can restore it on cleanup.\n\tconst priorAnchorName = anchorEl.style.getPropertyValue('anchor-name')\n\tanchorEl.style.setProperty('anchor-name', anchorName)\n\n\tconst sheet = new CSSStyleSheet()\n\tsheet.replaceSync(`\n\t\t${surface.localName}[data-overlay-ref=\"${opts.id}\"] {\n\t\t\tposition-anchor: ${anchorName};\n\t\t\t${cssForPlacement(placement)}\n\t\t\tmargin: 8px;\n\t\t\tposition-try-fallbacks:\n\t\t\t\tflip-block,\n\t\t\t\tflip-inline,\n\t\t\t\tflip-block flip-inline;\n\t\t}\n\t`)\n\tsurface.dataset.overlayRef = opts.id\n\tconst existing = shadowRoot.adoptedStyleSheets\n\tshadowRoot.adoptedStyleSheets = [...existing, sheet]\n\n\treturn () => {\n\t\tif (priorAnchorName) {\n\t\t\tanchorEl.style.setProperty('anchor-name', priorAnchorName)\n\t\t} else {\n\t\t\tanchorEl.style.removeProperty('anchor-name')\n\t\t}\n\t\tshadowRoot.adoptedStyleSheets = shadowRoot.adoptedStyleSheets.filter((s) => s !== sheet)\n\t\tdelete surface.dataset.overlayRef\n\t}\n}\n\nfunction cssForPlacement(p: OverlayPlacement): string {\n\t// Minimal mapping for the Tier 1 stylesheet. The browser's\n\t// `position-try-fallbacks` flips when the preferred side doesn't fit,\n\t// so only the starting side needs to be encoded here.\n\tswitch (p) {\n\t\tcase 'top':\n\t\tcase 'top-start':\n\t\t\treturn 'bottom: anchor(top); left: anchor(start);'\n\t\tcase 'top-end':\n\t\t\treturn 'bottom: anchor(top); right: anchor(end);'\n\t\tcase 'bottom':\n\t\tcase 'bottom-start':\n\t\t\treturn 'top: anchor(bottom); left: anchor(start);'\n\t\tcase 'bottom-end':\n\t\t\treturn 'top: anchor(bottom); right: anchor(end);'\n\t\tcase 'left':\n\t\tcase 'left-start':\n\t\t\treturn 'right: anchor(left); top: anchor(start);'\n\t\tcase 'left-end':\n\t\t\treturn 'right: anchor(left); bottom: anchor(end);'\n\t\tcase 'right':\n\t\tcase 'right-start':\n\t\t\treturn 'left: anchor(right); top: anchor(start);'\n\t\tcase 'right-end':\n\t\t\treturn 'left: anchor(right); bottom: anchor(end);'\n\t}\n}\n\n/* ======================================================================= *\n * Tier 2 — Popover API (top-layer only) *\n * ======================================================================= */\n\n/**\n * Wire the Popover API lifecycle — the surface gets `popover=\"auto\"` and\n * `showPopover()` is called to promote it into the native top layer. No\n * position math here; the caller pairs this with `positionFloatingUI` for\n * the geometry, since Tier 2 is Popover-for-stacking + Floating UI-for-math.\n *\n * Returns a cleanup function that hides the popover and strips the attr.\n */\nexport function positionPopoverAPI(surface: HTMLElement): () => void {\n\tif (!CAPS.popover) {\n\t\tthrow new Error('positionPopoverAPI requires Popover API support')\n\t}\n\tsurface.setAttribute('popover', 'auto')\n\ttry {\n\t\t;(surface as unknown as { showPopover(): void }).showPopover()\n\t} catch {\n\t\t// showPopover can throw if already shown or detached; the component\n\t\t// is responsible for calling this on an already-mounted, not-yet-shown\n\t\t// surface. Silently swallowing a double-open is fine.\n\t}\n\treturn () => {\n\t\ttry {\n\t\t\t;(surface as unknown as { hidePopover?: () => void }).hidePopover?.()\n\t\t} catch {\n\t\t\t// already hidden / disconnected — fine.\n\t\t}\n\t\tsurface.removeAttribute('popover')\n\t}\n}\n\n/* ======================================================================= *\n * Tier 2 / 3 — Floating UI position math *\n * ======================================================================= */\n\nexport interface FloatingUIOptions {\n\t/** Preferred placement; Floating UI's `flip` middleware handles falls. */\n\tplacement?: OverlayPlacement\n\t/** Padding used by `shift` + `size` middleware. Defaults to\n\t * `ANCHOR_FIT_PADDING_PX` from overlay.layout. */\n\tpadding?: number\n\t/** Gap between anchor and surface. Default 8px. */\n\toffsetPx?: number\n\t/** Whether `autoUpdate` should track element resizes. Default true. */\n\ttrack?: boolean\n}\n\n/**\n * Floating UI-driven positioning. Returns a cold Observable — subscribe to\n * start positioning, unsubscribe to stop tracking (teardown cancels the\n * `autoUpdate` loop). The caller composes with `takeUntil(this.disconnecting)`:\n *\n * positionFloatingUI(surface, anchor, opts)\n * .pipe(takeUntil(this.disconnecting))\n * .subscribe()\n *\n * Middleware (stack, in order):\n * offset(opts.offsetPx)\n * → flip({ fallbackPlacements: [...] })\n * → shift({ padding: opts.padding })\n * → size({ apply: clamp maxWidth AND maxHeight from availableWidth/Height })\n *\n * `flip` is chosen over `autoPlacement` because element-anchored overlays\n * should respect the trigger's spatial context (menus shouldn't jump\n * sides). Dialog uses `autoPlacement` because it's point-anchored.\n */\nexport function positionFloatingUI(\n\tsurface: HTMLElement,\n\tanchor: ResolvedAnchor,\n\topts: FloatingUIOptions = {},\n): Observable<void> {\n\treturn new Observable<void>((subscriber) => {\n\t\tconst reference = anchor.el ?? anchor.virtual\n\t\tif (!reference) {\n\t\t\tsubscriber.error(new Error('positionFloatingUI requires an element or virtual anchor'))\n\t\t\treturn\n\t\t}\n\n\t\tconst placement: Placement = (opts.placement ?? 'bottom-start') as Placement\n\t\tconst padding = opts.padding ?? ANCHOR_FIT_PADDING_PX\n\t\tconst offsetPx = opts.offsetPx ?? 8\n\n\t\tconst update = async (): Promise<void> => {\n\t\t\ttry {\n\t\t\t\tconst { x, y } = await computePosition(reference, surface, {\n\t\t\t\t\tstrategy: 'fixed',\n\t\t\t\t\tplacement,\n\t\t\t\t\tmiddleware: [\n\t\t\t\t\t\toffset(offsetPx),\n\t\t\t\t\t\tflip({ padding, fallbackPlacements: defaultFallbacks(placement) }),\n\t\t\t\t\t\tshift({ padding }),\n\t\t\t\t\t\tsize({\n\t\t\t\t\t\t\tpadding,\n\t\t\t\t\t\t\tapply({ availableWidth, availableHeight, elements }) {\n\t\t\t\t\t\t\t\telements.floating.style.maxWidth = `${Math.max(0, availableWidth)}px`\n\t\t\t\t\t\t\t\telements.floating.style.maxHeight = `${Math.max(0, availableHeight)}px`\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t})\n\t\t\t\tObject.assign(surface.style, {\n\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\tleft: `${Math.round(x)}px`,\n\t\t\t\t\ttop: `${Math.round(y)}px`,\n\t\t\t\t\ttransform: 'none',\n\t\t\t\t})\n\t\t\t\tsubscriber.next()\n\t\t\t} catch (err) {\n\t\t\t\tsubscriber.error(err)\n\t\t\t}\n\t\t}\n\n\t\tconst cleanup = autoUpdate(reference, surface, update, {\n\t\t\tancestorScroll: true,\n\t\t\tancestorResize: true,\n\t\t\telementResize: opts.track !== false,\n\t\t})\n\n\t\treturn () => {\n\t\t\tcleanup()\n\t\t}\n\t})\n}\n\nfunction defaultFallbacks(preferred: Placement): Placement[] {\n\t// Flip to the opposite side first, then try the perpendicular ends.\n\t// Small, deterministic list — not exhaustive.\n\tswitch (preferred) {\n\t\tcase 'bottom-start':\n\t\t\treturn ['top-start', 'bottom-end', 'top-end']\n\t\tcase 'bottom-end':\n\t\t\treturn ['top-end', 'bottom-start', 'top-start']\n\t\tcase 'top-start':\n\t\t\treturn ['bottom-start', 'top-end', 'bottom-end']\n\t\tcase 'top-end':\n\t\t\treturn ['bottom-end', 'top-start', 'bottom-start']\n\t\tcase 'left-start':\n\t\t\treturn ['right-start', 'left-end', 'right-end']\n\t\tcase 'left-end':\n\t\t\treturn ['right-end', 'left-start', 'right-start']\n\t\tcase 'right-start':\n\t\t\treturn ['left-start', 'right-end', 'left-end']\n\t\tcase 'right-end':\n\t\t\treturn ['left-end', 'right-start', 'left-start']\n\t\tcase 'top':\n\t\t\treturn ['bottom', 'left', 'right']\n\t\tcase 'bottom':\n\t\t\treturn ['top', 'left', 'right']\n\t\tcase 'left':\n\t\t\treturn ['right', 'top', 'bottom']\n\t\tcase 'right':\n\t\t\treturn ['left', 'top', 'bottom']\n\t\tdefault:\n\t\t\treturn ['top-start', 'bottom-end']\n\t}\n}\n","import { SchmancyElement } from '@mixins/index'\nimport { css, html, render as litRender, type TemplateResult } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { when } from 'lit/directives/when.js'\nimport {\n\tdebounceTime,\n\tdistinctUntilChanged,\n\tfilter,\n\tfromEvent,\n\tmap,\n\tmerge,\n\tSubject,\n\ttake,\n\ttakeUntil,\n\ttap,\n} from 'rxjs'\nimport type { LazyComponent } from '../area/lazy'\nimport { fromResizeObserver } from '../directives/layout'\nimport {\n\tanchorOriginVars,\n\tflipAnimation,\n\tsurfaceAnimation,\n} from './overlay.animations'\nimport { swipeToDismiss$ } from './overlay.gestures'\nimport {\n\treadViewport,\n\tresolveAnchorRef,\n\tresolveLayout,\n\ttype ResolvedAnchor,\n} from './overlay.layout'\nimport {\n\tpickPositioner,\n\tpositionCSSAnchor,\n\tpositionFloatingUI,\n\tpositionPopoverAPI,\n} from './overlay.positioning'\nimport type {\n\tAnchor,\n\tCloseReason,\n\tContent,\n\tOverlayLayout,\n\tOverlayTier,\n\tShowOptions,\n} from './overlay.types'\n\nconst MOUNT_POINT_ID = 'overlay-mount'\nconst RE_RESOLVE_COOLDOWN_MS = 600\n\n/**\n * The single overlay element. Custom `<div>` shell (not a native\n * `<dialog>`) — one backdrop mechanism for all layouts, one focus-trap\n * path, one animation orchestrator. The shell is always rendered; the\n * backdrop only renders when modal. The surface is positioned per tier:\n *\n * - Modal layouts (centered / sheet) → backdrop + surface, focus-trapped,\n * library-managed z-index.\n * - Anchored 'css-anchor' tier → surface as `popover=\"auto\"` with\n * CSS Anchor Positioning; native top-layer + light-dismiss.\n * - Anchored 'popover-fui' tier → surface as `popover=\"auto\"` + Floating\n * UI position math; native top-layer + light-dismiss.\n * - Anchored 'fui-only' tier → surface positioned by Floating UI;\n * manual click-outside + manual Esc.\n *\n * Public lifecycle: the service calls `open()` to mount content and\n * animate in, `close(reason)` to animate out and dismiss. The element\n * exposes `closed$` (Observable emitting reason + result once) and\n * `tier` / `layout` / `modal` as properties for the stack entry.\n */\n@customElement('schmancy-overlay')\nexport class SchmancyOverlay extends SchmancyElement {\n\tstatic styles = [css`\n\t:host {\n\t\tposition: fixed;\n\t\tinset: 0;\n\t\tz-index: var(--schmancy-overlay-z, 10000);\n\t\tdisplay: none;\n\t\tpointer-events: none;\n\t}\n\t:host([active]) {\n\t\tdisplay: block;\n\t}\n\t.shell {\n\t\tposition: fixed;\n\t\tinset: 0;\n\t\tpointer-events: none;\n\t}\n\t.backdrop {\n\t\tposition: fixed;\n\t\tinset: 0;\n\t\tbackground: color-mix(in srgb, var(--schmancy-sys-color-surface-container, rgba(12, 12, 16, 0.28)) 60%, transparent);\n\t\tbackdrop-filter: blur(18px) saturate(150%);\n\t\t-webkit-backdrop-filter: blur(18px) saturate(150%);\n\t\tpointer-events: auto;\n\t}\n\t.surface {\n\t\tposition: fixed;\n\t\tpointer-events: auto;\n\t\tmax-width: calc(100vw - 2rem);\n\t\tmax-height: 90dvh;\n\t\toverflow: auto;\n\t\tborder-radius: var(--schmancy-sys-shape-corner-large, 16px);\n\t\tbackground: var(--schmancy-sys-color-surface, #ffffff);\n\t\tcolor: var(--schmancy-sys-color-on-surface, #1a1a1a);\n\t\tbox-shadow: 0 24px 64px -16px rgba(0, 0, 0, 0.35);\n\t}\n\t.surface[data-layout='centered'] {\n\t\ttop: 50%;\n\t\tleft: 50%;\n\t\ttransform: translate(-50%, -50%);\n\t}\n\t.surface[data-layout='sheet'] {\n\t\tleft: 0;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tmax-width: none;\n\t\twidth: 100%;\n\t\tborder-radius: var(--schmancy-sys-shape-corner-large, 16px) var(--schmancy-sys-shape-corner-large, 16px) 0 0;\n\t\tpadding-bottom: env(safe-area-inset-bottom);\n\t}\n\t.surface[data-layout='anchored'] {\n\t\tmax-width: min(480px, calc(100vw - 2rem));\n\t\tbox-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.28);\n\t}\n\t/* Popover top-layer surfaces escape normal z-index — zero out host\n\t * display to avoid two surfaces rendering during transitions. */\n\t.surface:popover-open {\n\t\tmargin: 0;\n\t\tborder: 0;\n\t}\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.surface {\n\t\t\tbox-shadow: var(--schmancy-sys-elevation-2, 0 2px 6px rgba(0, 0, 0, 0.2));\n\t\t}\n\t}\n`]\n\n\t@property({ type: String, reflect: true }) layout: OverlayLayout = 'centered'\n\t@property({ type: Boolean, reflect: true }) dismissable = true\n\t@property({ type: Boolean, reflect: true }) modal = true\n\t@property({ type: String, reflect: true }) tier: OverlayTier = 'modal'\n\n\t@state() private _active = false\n\n\t@query('.backdrop') private _backdrop?: HTMLDivElement\n\t@query('.surface') private _surface!: HTMLElement\n\n\t/** Close trigger for the service; emits the reason + detail payload. */\n\tprivate readonly _closed$ = new Subject<{ reason: CloseReason; result?: unknown }>()\n\n\tprivate _mounted = false\n\tprivate _closing = false\n\tprivate _resolvedAnchor?: ResolvedAnchor\n\tprivate _rawAnchor?: Anchor\n\tprivate _anchorOriginAnchor?: Anchor\n\tprivate _positionerTeardown?: () => void\n\tprivate _lastFocusedElement: HTMLElement | null = null\n\tprivate _inertedSiblings: HTMLElement[] = []\n\tprivate _lastReResolveAt = 0\n\n\t/** Service subscribes to this to know when the overlay dismissed. */\n\tget closed$(): import('rxjs').Observable<{ reason: CloseReason; result?: unknown }> {\n\t\treturn this._closed$.asObservable()\n\t}\n\n\t/**\n\t * Mount content and animate in. Called by the service after the\n\t * element is attached to the DOM. Resolves when the entrance\n\t * animation completes.\n\t */\n\tasync open(content: Content, options: ShowOptions): Promise<void> {\n\t\tif (this._mounted) throw new Error('schmancy-overlay: open() called twice on the same element')\n\t\tthis._mounted = true\n\n\t\tthis.dismissable = options.dismissable !== false\n\t\tthis._rawAnchor = options.anchor\n\t\tthis._anchorOriginAnchor = options.anchor\n\t\tthis._resolvedAnchor = resolveAnchorRef(options.anchor)\n\n\t\t// Ensure the shell is rendered so the mount point exists.\n\t\tthis._active = true\n\t\tthis.setAttribute('active', '')\n\t\tawait this.updateComplete\n\n\t\tconst mount = this.renderRoot.querySelector(`#${MOUNT_POINT_ID}`) as HTMLElement | null\n\t\tif (!mount) throw new Error('schmancy-overlay: mount point missing')\n\t\tawait mountContent(content, mount, options.props)\n\n\t\t// Measure content after mount for layout dispatch.\n\t\tconst viewport = readViewport()\n\t\tconst contentSize = {\n\t\t\twidth: mount.scrollWidth,\n\t\t\theight: mount.scrollHeight,\n\t\t}\n\t\tthis.layout = resolveLayout({\n\t\t\tanchor: options.anchor,\n\t\t\tcontent: contentSize,\n\t\t\tviewport,\n\t\t})\n\n\t\t// Modal defaults per layout, with the caller's `modal` as escape hatch.\n\t\tthis.modal =\n\t\t\toptions.modal ?? (this.layout === 'centered' || this.layout === 'sheet')\n\n\t\t// Pick the positioning tier. Modal layouts always use the 'modal'\n\t\t// tier (custom shell + manual backdrop); anchored uses the CAPS-driven\n\t\t// ladder. `modal: true` on an anchored layout stays modal.\n\t\tthis.tier = this.modal\n\t\t\t? 'modal'\n\t\t\t: this._resolvedAnchor\n\t\t\t\t? pickPositioner(this._resolvedAnchor)\n\t\t\t\t: 'modal'\n\n\t\tawait this.updateComplete\n\n\t\t// Apply tier-specific positioning. For 'modal' the CSS data-layout\n\t\t// attribute + :host styles already place the surface; nothing to do.\n\t\t// For anchored tiers we delegate to the positioning module.\n\t\tif (this.tier === 'css-anchor' && this._resolvedAnchor?.el && this.shadowRoot) {\n\t\t\tthis._positionerTeardown = positionCSSAnchor(this._surface, this._resolvedAnchor, this.shadowRoot, {\n\t\t\t\tid: `ov-${Math.random().toString(36).slice(2, 10)}`,\n\t\t\t\tplacement: options.preferredPlacement ?? 'bottom-start',\n\t\t\t})\n\t\t\t// Pair with Popover API to get native top-layer + light-dismiss.\n\t\t\tconst popoverCleanup = positionPopoverAPI(this._surface)\n\t\t\tconst prior = this._positionerTeardown\n\t\t\tthis._positionerTeardown = () => {\n\t\t\t\tpopoverCleanup()\n\t\t\t\tprior()\n\t\t\t}\n\t\t} else if (this.tier === 'popover-fui' && this._resolvedAnchor) {\n\t\t\tconst popoverCleanup = positionPopoverAPI(this._surface)\n\t\t\tconst floatSub = positionFloatingUI(this._surface, this._resolvedAnchor, {\n\t\t\t\tplacement: options.preferredPlacement ?? 'bottom-start',\n\t\t\t\toffsetPx: 8,\n\t\t\t\ttrack: options.track !== false,\n\t\t\t})\n\t\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t\t.subscribe()\n\t\t\tthis._positionerTeardown = () => {\n\t\t\t\tpopoverCleanup()\n\t\t\t\tfloatSub.unsubscribe()\n\t\t\t}\n\t\t} else if (this.tier === 'fui-only' && this._resolvedAnchor) {\n\t\t\tconst floatSub = positionFloatingUI(this._surface, this._resolvedAnchor, {\n\t\t\t\tplacement: options.preferredPlacement ?? 'bottom-start',\n\t\t\t\toffsetPx: 8,\n\t\t\t\ttrack: options.track !== false,\n\t\t\t})\n\t\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t\t.subscribe()\n\t\t\tthis._positionerTeardown = () => floatSub.unsubscribe()\n\t\t}\n\n\t\t// Set the anchor-origin CSS vars so the entrance animation blooms\n\t\t// from the click point. Must happen AFTER positioning so the\n\t\t// surface rect is final.\n\t\tthis.setAnchorOriginVars()\n\n\t\t// Wire close triggers (focus trap, Esc, backdrop click, etc).\n\t\tthis.wireFocusTrap()\n\t\tthis.wireCloseTriggers(options.signal)\n\n\t\t// Watch content for mid-session re-resolves (upward-only + cooldown).\n\t\tthis.wireResizeObserver(mount)\n\n\t\t// Play entrance animations.\n\t\tawait this.playEnterAnimations()\n\t}\n\n\t/** Play exit animations then dismiss. */\n\tasync close(reason: CloseReason, result?: unknown): Promise<void> {\n\t\tif (this._closing || !this._mounted) return\n\t\tthis._closing = true\n\t\ttry {\n\t\t\tawait this.playExitAnimations()\n\t\t} catch {\n\t\t\t// animation cancelled mid-flight — not an error.\n\t\t}\n\t\tthis.releaseFocusTrap()\n\t\tif (this._positionerTeardown) {\n\t\t\ttry {\n\t\t\t\tthis._positionerTeardown()\n\t\t\t} catch {\n\t\t\t\t// cleanup shouldn't throw; ignore anything that does.\n\t\t\t}\n\t\t\tthis._positionerTeardown = undefined\n\t\t}\n\t\tthis._active = false\n\t\tthis.removeAttribute('active')\n\t\tthis._closed$.next({ reason, result })\n\t\tthis._closed$.complete()\n\t}\n\n\t/* ---------------- render ------------------------------------------- */\n\n\tprotected render(): TemplateResult {\n\t\tif (!this._active) return html``\n\t\treturn html`\n\t\t\t<div class=\"shell\" part=\"shell\">\n\t\t\t\t${when(\n\t\t\t\t\tthis.modal,\n\t\t\t\t\t() => html`<div class=\"backdrop\" part=\"backdrop\" @click=${this.onBackdropClick}></div>`,\n\t\t\t\t)}\n\t\t\t\t<section\n\t\t\t\t\tclass=\"surface\"\n\t\t\t\t\tpart=\"surface\"\n\t\t\t\t\tdata-layout=${this.layout}\n\t\t\t\t\tdata-tier=${this.tier}\n\t\t\t\t\trole=${this.modal ? 'dialog' : 'region'}\n\t\t\t\t\taria-modal=${this.modal ? 'true' : 'false'}\n\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t>\n\t\t\t\t\t<div id=${MOUNT_POINT_ID}></div>\n\t\t\t\t</section>\n\t\t\t</div>\n\t\t`\n\t}\n\n\tprivate onBackdropClick = (): void => {\n\t\tif (this.dismissable) void this.close('backdrop')\n\t}\n\n\t/* ---------------- anchor-origin bloom ------------------------------ */\n\n\tprivate setAnchorOriginVars(): void {\n\t\tconst surface = this._surface\n\t\tif (!surface) return\n\t\tconst rect = surface.getBoundingClientRect()\n\t\tconst vars =\n\t\t\tthis.layout === 'centered' && !this._anchorOriginAnchor\n\t\t\t\t? { '--schmancy-overlay-origin-x': '50%', '--schmancy-overlay-origin-y': '50%' }\n\t\t\t\t: this.layout === 'sheet' && !this._anchorOriginAnchor\n\t\t\t\t\t? { '--schmancy-overlay-origin-x': '50%', '--schmancy-overlay-origin-y': '100%' }\n\t\t\t\t\t: anchorOriginVars(this._anchorOriginAnchor, rect)\n\t\tfor (const [k, v] of Object.entries(vars)) {\n\t\t\tsurface.style.setProperty(k, v)\n\t\t}\n\t}\n\n\t/* ---------------- focus trap --------------------------------------- */\n\n\tprivate wireFocusTrap(): void {\n\t\tif (!this.modal) return\n\t\tthis._lastFocusedElement = (document.activeElement as HTMLElement) ?? null\n\t\tconst parent = this.parentElement\n\t\tif (parent) {\n\t\t\tthis._inertedSiblings = []\n\t\t\tfor (const child of Array.from(parent.children)) {\n\t\t\t\tif (child !== this && child instanceof HTMLElement && !child.inert) {\n\t\t\t\t\tchild.inert = true\n\t\t\t\t\tthis._inertedSiblings.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Focus the surface or the first [autofocus] child.\n\t\tqueueMicrotask(() => {\n\t\t\tconst auto = this._surface?.querySelector<HTMLElement>('[autofocus]')\n\t\t\t;(auto ?? this._surface)?.focus()\n\t\t})\n\t}\n\n\tprivate releaseFocusTrap(): void {\n\t\tfor (const el of this._inertedSiblings) {\n\t\t\tel.inert = false\n\t\t}\n\t\tthis._inertedSiblings = []\n\t\ttry {\n\t\t\tthis._lastFocusedElement?.focus?.()\n\t\t} catch {\n\t\t\t// trigger may be detached now; no-op.\n\t\t}\n\t\tthis._lastFocusedElement = null\n\t}\n\n\t/* ---------------- close triggers ----------------------------------- */\n\n\tprivate wireCloseTriggers(signal?: AbortSignal): void {\n\t\tconst until = this.disconnecting\n\n\t\t// Structured close — content dispatches CustomEvent('close', { detail }).\n\t\tfromEvent<CustomEvent>(this, 'close')\n\t\t\t.pipe(\n\t\t\t\tfilter((e) => e instanceof CustomEvent),\n\t\t\t\ttap((e) => {\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t\tvoid this.close('structured', e.detail)\n\t\t\t\t}),\n\t\t\t\ttakeUntil(until),\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\t// Native <form method=\"dialog\"> submission bubbles up as a regular\n\t\t// submit event with `submitter.value` (returnValue proxy for our\n\t\t// custom shell). Capture it and resolve with the string value.\n\t\tfromEvent<SubmitEvent>(this, 'submit')\n\t\t\t.pipe(\n\t\t\t\tfilter((e) => {\n\t\t\t\t\tconst form = e.target as HTMLFormElement | null\n\t\t\t\t\treturn !!form && form.method === 'dialog'\n\t\t\t\t}),\n\t\t\t\ttap((e) => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\tconst submitter = (e as SubmitEvent & { submitter?: HTMLButtonElement | HTMLInputElement })\n\t\t\t\t\t\t.submitter\n\t\t\t\t\tconst value = submitter?.value ?? ''\n\t\t\t\t\tvoid this.close('native-submit', value)\n\t\t\t\t}),\n\t\t\t\ttakeUntil(until),\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\t// Modal tier: manual Esc (popover tiers use native toggle event).\n\t\tif (this.tier === 'modal') {\n\t\t\tfromEvent<KeyboardEvent>(document, 'keydown')\n\t\t\t\t.pipe(\n\t\t\t\t\tfilter((e) => e.key === 'Escape'),\n\t\t\t\t\ttap((e) => {\n\t\t\t\t\t\tif (!this.dismissable) {\n\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\tvoid this.close('escape')\n\t\t\t\t\t}),\n\t\t\t\t\ttakeUntil(until),\n\t\t\t\t)\n\t\t\t\t.subscribe()\n\t\t}\n\n\t\t// Popover tiers: native `toggle` event fires on open/close, with\n\t\t// `newState: 'closed'` when the browser light-dismisses the popover.\n\t\tif (this.tier === 'popover-fui' || this.tier === 'css-anchor') {\n\t\t\tfromEvent<ToggleEvent>(this._surface, 'toggle')\n\t\t\t\t.pipe(\n\t\t\t\t\tfilter((e) => e.newState === 'closed'),\n\t\t\t\t\ttake(1),\n\t\t\t\t\ttap(() => {\n\t\t\t\t\t\tif (!this._closing) void this.close('light-dismiss')\n\t\t\t\t\t}),\n\t\t\t\t\ttakeUntil(until),\n\t\t\t\t)\n\t\t\t\t.subscribe()\n\t\t}\n\n\t\t// Floating-UI-only tier: manual outside-click dismissal.\n\t\tif (this.tier === 'fui-only') {\n\t\t\tfromEvent<PointerEvent>(document, 'pointerdown', { capture: true })\n\t\t\t\t.pipe(\n\t\t\t\t\tfilter((e) => {\n\t\t\t\t\t\tif (!this.dismissable) return false\n\t\t\t\t\t\tconst target = e.composedPath()[0] as Node | undefined\n\t\t\t\t\t\tif (!target) return false\n\t\t\t\t\t\t// Clicks inside the surface shouldn't dismiss.\n\t\t\t\t\t\tif (this._surface?.contains(target as Node)) return false\n\t\t\t\t\t\t// Clicks on the anchor itself shouldn't dismiss (avoid re-toggle).\n\t\t\t\t\t\tif (this._resolvedAnchor?.el?.contains(target as Node)) return false\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}),\n\t\t\t\t\ttake(1),\n\t\t\t\t\ttap(() => void this.close('backdrop')),\n\t\t\t\t\ttakeUntil(until),\n\t\t\t\t)\n\t\t\t\t.subscribe()\n\t\t}\n\n\t\t// Swipe-to-dismiss for sheet layout only. No visual drag handle —\n\t\t// the gesture starts from the top 40px of the surface (see\n\t\t// DRAG_START_TOP_PX in overlay.gestures). Escape + backdrop click\n\t\t// cover the other dismiss paths via the modal-tier listeners above.\n\t\tif (this.layout === 'sheet' && this.dismissable) {\n\t\t\tswipeToDismiss$({\n\t\t\t\tsurface: this._surface,\n\t\t\t\tuntil$: merge(until, this._closed$),\n\t\t\t})\n\t\t\t\t.pipe(take(1))\n\t\t\t\t.subscribe(() => void this.close('swipe'))\n\t\t}\n\n\t\t// AbortSignal — standard cancellation input.\n\t\tif (signal) {\n\t\t\tif (signal.aborted) {\n\t\t\t\tqueueMicrotask(() => void this.close('abort'))\n\t\t\t} else {\n\t\t\t\tfromEvent(signal, 'abort')\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\ttake(1),\n\t\t\t\t\t\ttap(() => void this.close('abort')),\n\t\t\t\t\t\ttakeUntil(until),\n\t\t\t\t\t)\n\t\t\t\t\t.subscribe()\n\t\t\t}\n\t\t}\n\t}\n\n\t/* ---------------- ResizeObserver FLIP re-resolve ------------------- */\n\n\tprivate wireResizeObserver(mount: HTMLElement): void {\n\t\tfromResizeObserver(mount)\n\t\t\t.pipe(\n\t\t\t\tmap((entries) => {\n\t\t\t\t\tconst entry = entries[0]\n\t\t\t\t\tif (!entry) return null\n\t\t\t\t\tconst box = entry.contentRect\n\t\t\t\t\treturn { w: box.width, h: box.height }\n\t\t\t\t}),\n\t\t\t\tfilter((v): v is { w: number; h: number } => v !== null),\n\t\t\t\tdistinctUntilChanged((a, b) => a.w === b.w && a.h === b.h),\n\t\t\t\tdebounceTime(80),\n\t\t\t\ttakeUntil(merge(this.disconnecting, this._closed$)),\n\t\t\t)\n\t\t\t.subscribe((size) => this.maybeReResolve(size))\n\t}\n\n\tprivate async maybeReResolve(size: { w: number; h: number }): Promise<void> {\n\t\tif (this._closing) return\n\t\tconst viewport = readViewport()\n\t\tconst next = resolveLayout({\n\t\t\tanchor: this._rawAnchor,\n\t\t\tcontent: { width: size.w, height: size.h },\n\t\t\tviewport,\n\t\t})\n\t\tif (next === this.layout) return\n\t\t// Cooldown: prevent churn-driven bouncing.\n\t\tconst now = performance.now()\n\t\tif (now - this._lastReResolveAt < RE_RESOLVE_COOLDOWN_MS) return\n\t\t// Upward-only ratchet: centered → sheet on content-grow is OK,\n\t\t// sheet → centered on content-shrink is ignored.\n\t\tif (!isUpwardTransition(this.layout, next)) return\n\n\t\t// FLIP: capture `before` rect, apply new layout, capture `after`,\n\t\t// animate the inverse transform.\n\t\tconst surface = this._surface\n\t\tconst before = surface.getBoundingClientRect()\n\t\tthis.layout = next\n\t\tawait this.updateComplete\n\t\tconst after = surface.getBoundingClientRect()\n\t\tconst spec = flipAnimation(before, after)\n\t\ttry {\n\t\t\tawait surface.animate(spec.keyframes, spec.options).finished\n\t\t} catch {\n\t\t\t// cancelled — not an error.\n\t\t}\n\t\tthis._lastReResolveAt = performance.now()\n\t}\n\n\t/* ---------------- animations --------------------------------------- */\n\n\tprivate async playEnterAnimations(): Promise<void> {\n\t\tconst surface = this._surface\n\t\tif (!surface) return\n\t\tconst spec = surfaceAnimation(this.layout, 'in')\n\t\tconst tasks: Promise<unknown>[] = [\n\t\t\tsurface.animate(spec.keyframes, spec.options).finished.catch(() => undefined),\n\t\t]\n\t\tconst backdrop = this._backdrop\n\t\tif (this.modal && backdrop) {\n\t\t\ttasks.push(\n\t\t\t\tbackdrop\n\t\t\t\t\t.animate(\n\t\t\t\t\t\t[{ opacity: 0 }, { opacity: 1 }],\n\t\t\t\t\t\t{ duration: spec.options.duration, easing: 'ease-out', fill: 'forwards' },\n\t\t\t\t\t)\n\t\t\t\t\t.finished.catch(() => undefined),\n\t\t\t)\n\t\t}\n\t\tawait Promise.all(tasks)\n\t}\n\n\tprivate async playExitAnimations(): Promise<void> {\n\t\tconst surface = this._surface\n\t\tif (!surface) return\n\t\tconst spec = surfaceAnimation(this.layout, 'out')\n\t\tconst tasks: Promise<unknown>[] = [\n\t\t\tsurface.animate(spec.keyframes, spec.options).finished.catch(() => undefined),\n\t\t]\n\t\tconst backdrop = this._backdrop\n\t\tif (this.modal && backdrop) {\n\t\t\ttasks.push(\n\t\t\t\tbackdrop\n\t\t\t\t\t.animate(\n\t\t\t\t\t\t[{ opacity: 1 }, { opacity: 0 }],\n\t\t\t\t\t\t{ duration: spec.options.duration, easing: 'ease-in', fill: 'forwards' },\n\t\t\t\t\t)\n\t\t\t\t\t.finished.catch(() => undefined),\n\t\t\t)\n\t\t}\n\t\tawait Promise.all(tasks)\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-overlay': SchmancyOverlay\n\t}\n}\n\n/* ======================================================================= *\n * content mounting helpers *\n * ======================================================================= */\n\nasync function mountContent(\n\tcontent: Content,\n\thost: HTMLElement,\n\tprops?: Record<string, unknown>,\n): Promise<HTMLElement> {\n\t// TemplateResult — render via lit's `render`.\n\tif (isTemplateResult(content)) {\n\t\tlitRender(content, host)\n\t\treturn host\n\t}\n\n\t// Already-instantiated element — append directly.\n\tif (content instanceof HTMLElement) {\n\t\tif (props) Object.assign(content, props)\n\t\thost.appendChild(content)\n\t\treturn content\n\t}\n\n\t// LazyComponent — await the module, recurse with the default export.\n\tif (isLazy(content)) {\n\t\tconst mod = await content()\n\t\treturn mountContent(mod.default, host, props)\n\t}\n\n\t// Class constructor.\n\tif (typeof content === 'function') {\n\t\tconst Ctor = content as unknown as { new (): HTMLElement }\n\t\tconst el = new Ctor()\n\t\tif (props) Object.assign(el, props)\n\t\thost.appendChild(el)\n\t\treturn el\n\t}\n\n\t// Tag name.\n\tif (typeof content === 'string') {\n\t\tconst el = document.createElement(content)\n\t\tif (props) Object.assign(el, props)\n\t\thost.appendChild(el)\n\t\treturn el\n\t}\n\n\tthrow new Error('schmancy-overlay: unsupported content type')\n}\n\nfunction isTemplateResult(x: unknown): x is TemplateResult {\n\treturn typeof x === 'object' && x !== null && '_$litType$' in x\n}\n\nfunction isLazy(x: unknown): x is LazyComponent {\n\treturn typeof x === 'function' && ('preload' in (x as object) || '_promise' in (x as object))\n}\n\nfunction isUpwardTransition(from: OverlayLayout, to: OverlayLayout): boolean {\n\t// Upward ladder: centered < sheet. anchored → sheet is also upward\n\t// (overflow went past threshold). anchored → centered is NOT upward.\n\tif (from === 'centered' && to === 'sheet') return true\n\tif (from === 'anchored' && to === 'sheet') return true\n\treturn false\n}\n"],"mappings":"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"}
@@ -1,108 +0,0 @@
1
- import { c as e, i as t } from "./mixins-DCVXqL1Q.js";
2
- import { a as n } from "./active-host-BP0zy_Y9.js";
3
- import { Subject as r, fromEvent as i, takeUntil as a } from "rxjs";
4
- import { customElement as o, property as s } from "lit/decorators.js";
5
- import { html as c, unsafeCSS as l } from "lit";
6
- import { when as u } from "lit/directives/when.js";
7
- var d = class extends t(e) {
8
- constructor(...e) {
9
- super(...e), this.label = "", this.name = "", this.value = "", this.options = [], this.required = !1, this.selection$ = new r();
10
- }
11
- static {
12
- this.styles = [l(":host{display:inherit;position:inherit}")];
13
- }
14
- connectedCallback() {
15
- super.connectedCallback(), this.selection$.pipe(a(this.disconnecting)).subscribe((e) => {
16
- this.value = e, this.emitChange({ value: e }), this.updateChildRadioButtons();
17
- }), i(this, "radio-button-click").pipe(a(this.disconnecting)).subscribe((e) => {
18
- this.selection$.next(e.detail.value);
19
- });
20
- }
21
- disconnectedCallback() {
22
- super.disconnectedCallback(), this.selection$?.complete();
23
- }
24
- handleSelection(e) {
25
- this.selection$.next(e);
26
- }
27
- updateChildRadioButtons() {
28
- this.querySelectorAll("schmancy-radio-button").forEach((e) => {
29
- e.getAttribute("value") === this.value ? e.setAttribute("checked", "") : e.removeAttribute("checked");
30
- });
31
- }
32
- updated(e) {
33
- super.updated(e), e.has("value") && this.updateChildRadioButtons();
34
- }
35
- render() {
36
- let e = this.childElementCount > 0;
37
- return c`
38
- <div class="grid gap-4">
39
- ${u(this.label, () => c` <label class="text-base font-semibold text-surface-on">${this.label}</label> `)}
40
-
41
- ${e ? c`<slot></slot>` : this.options?.map((e) => c`
42
- <div class="flex items-center">
43
- <input
44
- .required=${this.required}
45
- id=${e.value}
46
- class="h-4 w-4 border-outline text-primary-default focus:ring-primary-default"
47
- type="radio"
48
- name=${this.name}
49
- .value=${e.value}
50
- .checked=${e.value === this.value}
51
- @change=${() => this.handleSelection(e.value)}
52
- />
53
- <label for=${e.value} class="ml-3 block text-sm font-medium leading-6 text-surface-on">
54
- ${e.label || e.value}
55
- </label>
56
- </div>
57
- `)}
58
- </div>
59
- `;
60
- }
61
- };
62
- n([s({ type: String })], d.prototype, "label", void 0), n([s({ type: String })], d.prototype, "name", void 0), n([s({ type: String })], d.prototype, "value", void 0), n([s({ type: Array })], d.prototype, "options", void 0), n([s({ type: Boolean })], d.prototype, "required", void 0), d = n([o("schmancy-radio-group")], d);
63
- var f = class extends t(e) {
64
- constructor(...e) {
65
- super(...e), this.value = "", this.checked = !1, this.disabled = !1, this.name = "";
66
- }
67
- connectedCallback() {
68
- super.connectedCallback(), i(this, "click").pipe(a(this.disconnecting)).subscribe(this.handleClick);
69
- }
70
- disconnectedCallback() {
71
- super.disconnectedCallback();
72
- }
73
- handleClick() {
74
- if (!this.disabled) if (this.closest("schmancy-radio-group")) {
75
- let e = new CustomEvent("radio-button-click", {
76
- detail: { value: this.value },
77
- bubbles: !0,
78
- composed: !0
79
- });
80
- this.dispatchEvent(e);
81
- } else this.checked = !0, this.emitChange({ value: this.value });
82
- }
83
- render() {
84
- return c`
85
- <label class="relative flex items-start cursor-pointer">
86
- <div class="flex items-center h-6">
87
- <input
88
- type="radio"
89
- class="h-4 w-4 text-primary-default focus:ring-primary-container border-outline"
90
- .value=${this.value}
91
- .checked=${this.checked}
92
- .disabled=${this.disabled}
93
- .name=${this.name}
94
- @change=${() => {}}
95
- />
96
- </div>
97
- <div class="ml-3">
98
- <slot name="label"></slot>
99
- </div>
100
- </label>
101
- `;
102
- }
103
- };
104
- n([s({ type: String })], f.prototype, "value", void 0), n([s({
105
- type: Boolean,
106
- reflect: !0
107
- })], f.prototype, "checked", void 0), n([s({ type: Boolean })], f.prototype, "disabled", void 0), n([s({ type: String })], f.prototype, "name", void 0), f = n([o("schmancy-radio-button")], f);
108
- export { d as n, f as t };
@@ -1 +0,0 @@
1
- {"version":3,"file":"radio-group-DB9D2ZkA.js","names":[],"sources":["../src/form/fields/radio-group/radio-group.scss?inline","../src/form/fields/radio-group/radio-group.ts","../src/form/fields/radio-group/radio-button.ts"],"sourcesContent":[":host {\n\tdisplay: inherit;\n\tposition: inherit;\n}\n","import { html, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { Subject, fromEvent, takeUntil } from 'rxjs'\nimport style from './radio-group.scss?inline'\nimport { SchmancyElement } from '@mixins/index'\nimport { when } from 'lit/directives/when.js'\nimport { FormFieldMixin } from '@mixins/formField.mixin'\n\nexport type SchmancyRadioGroupOption = {\n\tlabel: string\n\tvalue: string\n}\nexport type SchmancyRadioGroupChangeEvent = CustomEvent<{\n\tvalue: string\n}>\n@customElement('schmancy-radio-group')\nexport class RadioGroup extends FormFieldMixin(SchmancyElement) {\n\tstatic styles = [unsafeCSS(style)];\n\t@property({ type: String }) override label = ''\n\t@property({ type: String }) override name = ''\n\t@property({ type: String }) override value = ''\n\t@property({ type: Array }) options: SchmancyRadioGroupOption[] = []\n\t@property({ type: Boolean }) override required: boolean = false\n\tprivate selection$ = new Subject<string>()\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\tthis.selection$.pipe(takeUntil(this.disconnecting)).subscribe(value => {\n\t\t\tthis.value = value\n\t\t\tthis.emitChange({ value })\n\t\t\t// Update all child radio buttons\n\t\t\tthis.updateChildRadioButtons()\n\t\t})\n\n\t\t// Listen for radio button clicks from children\n\t\tfromEvent<CustomEvent>(this, 'radio-button-click')\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe((e: CustomEvent) => {\n\t\t\t\tthis.selection$.next(e.detail.value)\n\t\t\t})\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\t// Subscriptions are automatically cleaned up via takeUntil(this.disconnecting)\n\t\tthis.selection$?.complete()\n\t}\n\t\n\tprivate handleSelection(value: string) {\n\t\tthis.selection$.next(value)\n\t}\n\t\n\tprivate updateChildRadioButtons() {\n\t\t// Update child radio buttons checked state\n\t\tconst radioButtons = this.querySelectorAll('schmancy-radio-button')\n\t\tradioButtons.forEach(button => {\n\t\t\tconst buttonValue = button.getAttribute('value')\n\t\t\tif (buttonValue === this.value) {\n\t\t\t\tbutton.setAttribute('checked', '')\n\t\t\t} else {\n\t\t\t\tbutton.removeAttribute('checked')\n\t\t\t}\n\t\t})\n\t}\n\t\n\t// For backwards compatibility with direct option setting\n\tupdated(changedProperties: Map<string, unknown>) {\n\t\tsuper.updated(changedProperties)\n\t\tif (changedProperties.has('value')) {\n\t\t\tthis.updateChildRadioButtons()\n\t\t}\n\t}\n\n\trender() {\n\t\t// Check if we have any slotted radio buttons\n\t\tconst hasSlottedContent = this.childElementCount > 0\n\t\t\n\t\treturn html`\n\t\t\t<div class=\"grid gap-4\">\n\t\t\t\t${when(this.label, () => html` <label class=\"text-base font-semibold text-surface-on\">${this.label}</label> `)}\n\t\t\t\t\n\t\t\t\t${hasSlottedContent ? \n\t\t\t\t\thtml`<slot></slot>` :\n\t\t\t\t\tthis.options?.map(option => html`\n\t\t\t\t\t\t<div class=\"flex items-center\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t.required=${this.required}\n\t\t\t\t\t\t\t\tid=${option.value}\n\t\t\t\t\t\t\t\tclass=\"h-4 w-4 border-outline text-primary-default focus:ring-primary-default\"\n\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\tname=${this.name}\n\t\t\t\t\t\t\t\t.value=${option.value}\n\t\t\t\t\t\t\t\t.checked=${option.value === this.value}\n\t\t\t\t\t\t\t\t@change=${() => this.handleSelection(option.value)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<label for=${option.value} class=\"ml-3 block text-sm font-medium leading-6 text-surface-on\">\n\t\t\t\t\t\t\t\t${option.label || option.value}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`)\n\t\t\t\t}\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-radio-group': RadioGroup\n\t}\n}\n","import { SchmancyElement } from '@mixins/index'\nimport { html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { FormFieldMixin } from '@mixins/formField.mixin'\nimport { fromEvent, takeUntil } from 'rxjs'\n\n/**\n * Radio button component for use within radio groups.\n *\n * @prop {string} name - Name attribute for grouping radio buttons\n * @prop {string} value - Value of this radio button\n * @prop {boolean} checked - Whether the radio button is selected\n * @prop {boolean} disabled - Whether the radio button is disabled\n */\n@customElement('schmancy-radio-button')\nexport class RadioButton extends FormFieldMixin(SchmancyElement) {\n\t@property({ type: String }) override value = ''\n\t@property({ type: Boolean, reflect: true }) checked = false\n\t@property({ type: Boolean }) override disabled = false\n\t@property({ type: String }) override name = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Listen for click events\n\t\tfromEvent<MouseEvent>(this, 'click')\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe(this.handleClick)\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\t// Event listeners are automatically cleaned up via takeUntil(this.disconnecting)\n\t}\n\n\tprivate handleClick() {\n\t\tif (this.disabled) return\n\n\t\t// Find parent radio-group if exists\n\t\tconst radioGroup = this.closest('schmancy-radio-group')\n\t\tif (radioGroup) {\n\t\t\t// Let the radio-group handle the change\n\t\t\tconst event = new CustomEvent('radio-button-click', {\n\t\t\t\tdetail: { value: this.value },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t})\n\t\t\tthis.dispatchEvent(event)\n\t\t} else {\n\t\t\t// Standalone usage\n\t\t\tthis.checked = true\n\t\t\tthis.emitChange({ value: this.value })\n\t\t}\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<label class=\"relative flex items-start cursor-pointer\">\n\t\t\t\t<div class=\"flex items-center h-6\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tclass=\"h-4 w-4 text-primary-default focus:ring-primary-container border-outline\"\n\t\t\t\t\t\t.value=${this.value}\n\t\t\t\t\t\t.checked=${this.checked}\n\t\t\t\t\t\t.disabled=${this.disabled}\n\t\t\t\t\t\t.name=${this.name}\n\t\t\t\t\t\t@change=${() => {}}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"ml-3\">\n\t\t\t\t\t<slot name=\"label\"></slot>\n\t\t\t\t</div>\n\t\t\t</label>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-radio-button': RadioButton\n\t}\n}\n"],"mappings":"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"}
@@ -1,40 +0,0 @@
1
- require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-Du9HMrIG.cjs`),t=require(`./active-host-jH3iloCR.cjs`);let n=require(`rxjs`),r=require(`lit/decorators.js`),i=require(`lit`),a=require(`lit/directives/when.js`);var o=class extends e.i(e.c){constructor(...e){super(...e),this.label=``,this.name=``,this.value=``,this.options=[],this.required=!1,this.selection$=new n.Subject}static{this.styles=[(0,i.unsafeCSS)(`:host{display:inherit;position:inherit}`)]}connectedCallback(){super.connectedCallback(),this.selection$.pipe((0,n.takeUntil)(this.disconnecting)).subscribe(e=>{this.value=e,this.emitChange({value:e}),this.updateChildRadioButtons()}),(0,n.fromEvent)(this,`radio-button-click`).pipe((0,n.takeUntil)(this.disconnecting)).subscribe(e=>{this.selection$.next(e.detail.value)})}disconnectedCallback(){super.disconnectedCallback(),this.selection$?.complete()}handleSelection(e){this.selection$.next(e)}updateChildRadioButtons(){this.querySelectorAll(`schmancy-radio-button`).forEach(e=>{e.getAttribute(`value`)===this.value?e.setAttribute(`checked`,``):e.removeAttribute(`checked`)})}updated(e){super.updated(e),e.has(`value`)&&this.updateChildRadioButtons()}render(){let e=this.childElementCount>0;return i.html`
2
- <div class="grid gap-4">
3
- ${(0,a.when)(this.label,()=>i.html` <label class="text-base font-semibold text-surface-on">${this.label}</label> `)}
4
-
5
- ${e?i.html`<slot></slot>`:this.options?.map(e=>i.html`
6
- <div class="flex items-center">
7
- <input
8
- .required=${this.required}
9
- id=${e.value}
10
- class="h-4 w-4 border-outline text-primary-default focus:ring-primary-default"
11
- type="radio"
12
- name=${this.name}
13
- .value=${e.value}
14
- .checked=${e.value===this.value}
15
- @change=${()=>this.handleSelection(e.value)}
16
- />
17
- <label for=${e.value} class="ml-3 block text-sm font-medium leading-6 text-surface-on">
18
- ${e.label||e.value}
19
- </label>
20
- </div>
21
- `)}
22
- </div>
23
- `}};t.a([(0,r.property)({type:String})],o.prototype,`label`,void 0),t.a([(0,r.property)({type:String})],o.prototype,`name`,void 0),t.a([(0,r.property)({type:String})],o.prototype,`value`,void 0),t.a([(0,r.property)({type:Array})],o.prototype,`options`,void 0),t.a([(0,r.property)({type:Boolean})],o.prototype,`required`,void 0),o=t.a([(0,r.customElement)(`schmancy-radio-group`)],o);var s=class extends e.i(e.c){constructor(...e){super(...e),this.value=``,this.checked=!1,this.disabled=!1,this.name=``}connectedCallback(){super.connectedCallback(),(0,n.fromEvent)(this,`click`).pipe((0,n.takeUntil)(this.disconnecting)).subscribe(this.handleClick)}disconnectedCallback(){super.disconnectedCallback()}handleClick(){if(!this.disabled)if(this.closest(`schmancy-radio-group`)){let e=new CustomEvent(`radio-button-click`,{detail:{value:this.value},bubbles:!0,composed:!0});this.dispatchEvent(e)}else this.checked=!0,this.emitChange({value:this.value})}render(){return i.html`
24
- <label class="relative flex items-start cursor-pointer">
25
- <div class="flex items-center h-6">
26
- <input
27
- type="radio"
28
- class="h-4 w-4 text-primary-default focus:ring-primary-container border-outline"
29
- .value=${this.value}
30
- .checked=${this.checked}
31
- .disabled=${this.disabled}
32
- .name=${this.name}
33
- @change=${()=>{}}
34
- />
35
- </div>
36
- <div class="ml-3">
37
- <slot name="label"></slot>
38
- </div>
39
- </label>
40
- `}};t.a([(0,r.property)({type:String})],s.prototype,`value`,void 0),t.a([(0,r.property)({type:Boolean,reflect:!0})],s.prototype,`checked`,void 0),t.a([(0,r.property)({type:Boolean})],s.prototype,`disabled`,void 0),t.a([(0,r.property)({type:String})],s.prototype,`name`,void 0),s=t.a([(0,r.customElement)(`schmancy-radio-button`)],s),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
@@ -1 +0,0 @@
1
- {"version":3,"file":"radio-group-dVUvYFq7.cjs","names":[],"sources":["../src/form/fields/radio-group/radio-group.scss?inline","../src/form/fields/radio-group/radio-group.ts","../src/form/fields/radio-group/radio-button.ts"],"sourcesContent":[":host {\n\tdisplay: inherit;\n\tposition: inherit;\n}\n","import { html, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { Subject, fromEvent, takeUntil } from 'rxjs'\nimport style from './radio-group.scss?inline'\nimport { SchmancyElement } from '@mixins/index'\nimport { when } from 'lit/directives/when.js'\nimport { FormFieldMixin } from '@mixins/formField.mixin'\n\nexport type SchmancyRadioGroupOption = {\n\tlabel: string\n\tvalue: string\n}\nexport type SchmancyRadioGroupChangeEvent = CustomEvent<{\n\tvalue: string\n}>\n@customElement('schmancy-radio-group')\nexport class RadioGroup extends FormFieldMixin(SchmancyElement) {\n\tstatic styles = [unsafeCSS(style)];\n\t@property({ type: String }) override label = ''\n\t@property({ type: String }) override name = ''\n\t@property({ type: String }) override value = ''\n\t@property({ type: Array }) options: SchmancyRadioGroupOption[] = []\n\t@property({ type: Boolean }) override required: boolean = false\n\tprivate selection$ = new Subject<string>()\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\tthis.selection$.pipe(takeUntil(this.disconnecting)).subscribe(value => {\n\t\t\tthis.value = value\n\t\t\tthis.emitChange({ value })\n\t\t\t// Update all child radio buttons\n\t\t\tthis.updateChildRadioButtons()\n\t\t})\n\n\t\t// Listen for radio button clicks from children\n\t\tfromEvent<CustomEvent>(this, 'radio-button-click')\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe((e: CustomEvent) => {\n\t\t\t\tthis.selection$.next(e.detail.value)\n\t\t\t})\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\t// Subscriptions are automatically cleaned up via takeUntil(this.disconnecting)\n\t\tthis.selection$?.complete()\n\t}\n\t\n\tprivate handleSelection(value: string) {\n\t\tthis.selection$.next(value)\n\t}\n\t\n\tprivate updateChildRadioButtons() {\n\t\t// Update child radio buttons checked state\n\t\tconst radioButtons = this.querySelectorAll('schmancy-radio-button')\n\t\tradioButtons.forEach(button => {\n\t\t\tconst buttonValue = button.getAttribute('value')\n\t\t\tif (buttonValue === this.value) {\n\t\t\t\tbutton.setAttribute('checked', '')\n\t\t\t} else {\n\t\t\t\tbutton.removeAttribute('checked')\n\t\t\t}\n\t\t})\n\t}\n\t\n\t// For backwards compatibility with direct option setting\n\tupdated(changedProperties: Map<string, unknown>) {\n\t\tsuper.updated(changedProperties)\n\t\tif (changedProperties.has('value')) {\n\t\t\tthis.updateChildRadioButtons()\n\t\t}\n\t}\n\n\trender() {\n\t\t// Check if we have any slotted radio buttons\n\t\tconst hasSlottedContent = this.childElementCount > 0\n\t\t\n\t\treturn html`\n\t\t\t<div class=\"grid gap-4\">\n\t\t\t\t${when(this.label, () => html` <label class=\"text-base font-semibold text-surface-on\">${this.label}</label> `)}\n\t\t\t\t\n\t\t\t\t${hasSlottedContent ? \n\t\t\t\t\thtml`<slot></slot>` :\n\t\t\t\t\tthis.options?.map(option => html`\n\t\t\t\t\t\t<div class=\"flex items-center\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t.required=${this.required}\n\t\t\t\t\t\t\t\tid=${option.value}\n\t\t\t\t\t\t\t\tclass=\"h-4 w-4 border-outline text-primary-default focus:ring-primary-default\"\n\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\tname=${this.name}\n\t\t\t\t\t\t\t\t.value=${option.value}\n\t\t\t\t\t\t\t\t.checked=${option.value === this.value}\n\t\t\t\t\t\t\t\t@change=${() => this.handleSelection(option.value)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<label for=${option.value} class=\"ml-3 block text-sm font-medium leading-6 text-surface-on\">\n\t\t\t\t\t\t\t\t${option.label || option.value}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t`)\n\t\t\t\t}\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-radio-group': RadioGroup\n\t}\n}\n","import { SchmancyElement } from '@mixins/index'\nimport { html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { FormFieldMixin } from '@mixins/formField.mixin'\nimport { fromEvent, takeUntil } from 'rxjs'\n\n/**\n * Radio button component for use within radio groups.\n *\n * @prop {string} name - Name attribute for grouping radio buttons\n * @prop {string} value - Value of this radio button\n * @prop {boolean} checked - Whether the radio button is selected\n * @prop {boolean} disabled - Whether the radio button is disabled\n */\n@customElement('schmancy-radio-button')\nexport class RadioButton extends FormFieldMixin(SchmancyElement) {\n\t@property({ type: String }) override value = ''\n\t@property({ type: Boolean, reflect: true }) checked = false\n\t@property({ type: Boolean }) override disabled = false\n\t@property({ type: String }) override name = ''\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\t// Listen for click events\n\t\tfromEvent<MouseEvent>(this, 'click')\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe(this.handleClick)\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\t// Event listeners are automatically cleaned up via takeUntil(this.disconnecting)\n\t}\n\n\tprivate handleClick() {\n\t\tif (this.disabled) return\n\n\t\t// Find parent radio-group if exists\n\t\tconst radioGroup = this.closest('schmancy-radio-group')\n\t\tif (radioGroup) {\n\t\t\t// Let the radio-group handle the change\n\t\t\tconst event = new CustomEvent('radio-button-click', {\n\t\t\t\tdetail: { value: this.value },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t})\n\t\t\tthis.dispatchEvent(event)\n\t\t} else {\n\t\t\t// Standalone usage\n\t\t\tthis.checked = true\n\t\t\tthis.emitChange({ value: this.value })\n\t\t}\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<label class=\"relative flex items-start cursor-pointer\">\n\t\t\t\t<div class=\"flex items-center h-6\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tclass=\"h-4 w-4 text-primary-default focus:ring-primary-container border-outline\"\n\t\t\t\t\t\t.value=${this.value}\n\t\t\t\t\t\t.checked=${this.checked}\n\t\t\t\t\t\t.disabled=${this.disabled}\n\t\t\t\t\t\t.name=${this.name}\n\t\t\t\t\t\t@change=${() => {}}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"ml-3\">\n\t\t\t\t\t<slot name=\"label\"></slot>\n\t\t\t\t</div>\n\t\t\t</label>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-radio-button': RadioButton\n\t}\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"select-UU2pB67h.js","names":[],"sources":["../src/form/fields/select/select.ts"],"sourcesContent":["import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'\nimport { SchmancyFormField } from '@mixins/index'\nimport { color } from '@schmancy/directives'\nimport SchmancyInput from '@schmancy/input/input'\nimport SchmancyOption from '@schmancy/option/option'\nimport { SchmancyTheme } from '@schmancy/theme/theme.interface'\nimport { css, html, PropertyValues, TemplateResult } from 'lit'\nimport { customElement, property, query, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { BehaviorSubject, combineLatest, fromEvent, Subject, takeUntil } from 'rxjs'\nimport { tap, withLatestFrom } from 'rxjs/operators'\n\nexport type SchmancySelectChangeEvent = CustomEvent<{\n\tvalue: string | string[]\n}>\n\n/**\n * Select dropdown component with single and multi-select support.\n *\n * @prop {string} name - Name attribute for form submission\n * @prop {string} label - Label text displayed above the select\n * @prop {string} placeholder - Placeholder text when no value is selected\n * @prop {boolean} required - Whether the field is required\n * @prop {boolean} multi - Enable multi-select mode\n * @prop {string} value - Selected value (single select mode)\n * @prop {string[]} values - Selected values (multi-select mode)\n */\n@customElement('schmancy-select')\nexport class SchmancySelect extends SchmancyFormField() {\n\tstatic styles = [css`\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t}\n\n\t[role='listbox'] {\n\t\toverflow-y: auto;\n\t\toutline: none;\n\t}\n`]\n\n\t// FACE wiring (formAssociated, internals, attachInternals) comes from\n\t// SchmancyFormField. Same for: name, required, disabled, validationMessage,\n\t// validateOn, touched/dirty/pristine/submitted, markTouched/markSubmitted,\n\t// formResetCallback, formDisabledCallback, FIELD_CONNECT_EVENT dispatch.\n\n\t@property({ type: String }) placeholder = ''\n\n\t// Override `value` with the narrowed select-specific type and a custom\n\t// getter/setter pair backed by reactive subjects.\n\t@property({ type: String, reflect: true })\n\toverride get value(): string | string[] {\n\t\treturn this.multi\n\t\t\t? this._selectedValues$.value\n\t\t\t: this._selectedValue$.value\n\t}\n\toverride set value(val: string | string[]) {\n\t\tif (this.multi) {\n\t\t\tconst values = Array.isArray(val)\n\t\t\t\t? val\n\t\t\t\t: val ? String(val).split(',').map(v => v.trim()).filter(Boolean) : []\n\t\t\tthis._selectedValues$.next(values)\n\t\t} else {\n\t\t\tthis._selectedValue$.next(val == null ? '' : String(val))\n\t\t}\n\t}\n\n\t// Values property for multi-select mode\n\t@property({ type: Array })\n\tget values() {\n\t\treturn [...this._selectedValues$.value]\n\t}\n\tset values(vals: string[]) {\n\t\tthis._selectedValues$.next(Array.isArray(vals) ? [...vals] : [])\n\t}\n\n\t@property({ type: Boolean }) multi = false\n\t// `label` and `hint` come from the mixin.\n\t// M3 aligned sizes: 24dp (xxs) → 32dp (xs) → 40dp (sm) → 48dp (md) → 56dp (lg)\n\t@property({ type: String }) size: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' = 'md'\n\n\t// Internal states\n\t@state() private isOpen = false\n\t@state() private valueLabel = ''\n\t@state() private isValid = true\n\n\t// Store the initial/default value for reset behavior. Distinct from the\n\t// mixin's `_defaultValue` (which is `string` only); select needs the wider\n\t// shape so resetForm can restore arrays for multi-select.\n\t@state() private selectDefaultValue: string | string[] = ''\n\n\t@query('ul') private ul!: HTMLUListElement\n\t@query('sch-input') private inputRef!: SchmancyInput\n\t@queryAssignedElements({ flatten: true }) private options!: SchmancyOption[]\n\tprivate cleanupPositioner?: () => void\n\n\t// Reactive state management\n\tprivate _options$ = new BehaviorSubject<SchmancyOption[]>([])\n\tprivate _selectedValue$ = new BehaviorSubject<string>('')\n\tprivate _selectedValues$ = new BehaviorSubject<string[]>([])\n\tprivate _optionSelect$ = new Subject<SchmancyOption>()\n\n\t/**\n\t * Tracks whether the user has actively interacted (clicked/typed/keyed\n\t * inside the dropdown). Distinct from the mixin's `touched` (which fires on\n\t * blur). Used to gate dropdown-positioning side-effects on user-driven\n\t * actions versus programmatic state changes.\n\t */\n\t@state() _userInteracted = false\n\n\t// Reference to current focused option (for keyboard navigation)\n\t@state() private _focusedOptionId = ''\n\n\toverride connectedCallback() {\n\t\tsuper.connectedCallback()\n\t\tif (!this.id) {\n\t\t\tthis.id = `schmancy-select-${Math.random().toString(36).substring(2, 9)}`\n\t\t}\n\n\t\t// Store initial value for reset\n\t\tthis.selectDefaultValue = this.value\n\n\t\t// Add keyboard handling to host element\n\t\tfromEvent<KeyboardEvent>(this, 'keydown').pipe(takeUntil(this.disconnecting)).subscribe(this.handleKeyDown)\n\n\t\t// Setup reactive pipelines\n\t\tthis._setupReactivePipelines()\n\t}\n\n\toverride disconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\tthis.cleanupPositioner?.()\n\t\t// Form event listeners are automatically cleaned up via takeUntil(this.disconnecting)\n\t}\n\n\tfirstUpdated() {\n\t\tthis.syncSelection()\n\t\tthis.setupOptionsAccessibility()\n\n\t\t// Initially hide any validation errors until user interacts\n\t\tif (this.inputRef) {\n\t\t\tthis.inputRef.error = false\n\t\t}\n\t}\n\n\toverride updated(changedProps: PropertyValues) {\n\t\tsuper.updated(changedProps)\n\n\t\tif (changedProps.has('value')) {\n\t\t\t// Multi-select serializes to a comma-joined scalar on FormData; the\n\t\t\t// mixin's willUpdate already called setFormValue with the raw\n\t\t\t// value, override here for the joined-string shape.\n\t\t\tconst formValue = this.multi\n\t\t\t\t? this._selectedValues$.value.join(',')\n\t\t\t\t: this._selectedValue$.value\n\t\t\tthis.internals?.setFormValue(formValue)\n\n\t\t\t// `dirty` is a mixin getter (value !== _defaultValue); no manual flag.\n\t\t\t// Mixin's willUpdate already calls checkValidity when _shouldShowError().\n\t\t}\n\n\t\t// When open state changes, setup or cleanup the dropdown positioner\n\t\tif (changedProps.has('isOpen')) {\n\t\t\tif (this.isOpen) {\n\t\t\t\tthis.positionDropdown()\n\t\t\t} else {\n\t\t\t\tthis.cleanupPositioner?.()\n\t\t\t}\n\t\t}\n\t}\n\n\t// `shouldShowValidation` removed — replaced by mixin's `_shouldShowError()`.\n\n\tprivate syncSelection() {\n\t\tif (this.multi) {\n\t\t\t// Read directly from the BehaviorSubject to avoid string conversion issues\n\t\t\tconst selectedValues = this._selectedValues$.value\n\t\t\tthis.options?.forEach(o => (o.selected = selectedValues.includes(o.value))) // Update option selected state\n\t\t\tthis.valueLabel =\n\t\t\t\tselectedValues.length > 0\n\t\t\t\t\t? this.options\n\t\t\t\t\t\t\t?.filter(o => selectedValues.includes(o.value))\n\t\t\t\t\t\t\t.map(o => o.label || o.textContent || '')\n\t\t\t\t\t\t\t.join(', ') || this.placeholder\n\t\t\t\t\t: this.placeholder\n\t\t} else {\n\t\t\t// Single select - read from BehaviorSubject\n\t\t\tconst currentValue = this._selectedValue$.value\n\t\t\tthis.options?.forEach(o => {\n\t\t\t\t// Set selected property on each option based on matching value\n\t\t\t\to.selected = o.value === currentValue\n\t\t\t})\n\t\t\tconst selectedOption = this.options?.find(o => o.value === currentValue)\n\t\t\tthis.valueLabel = selectedOption ? (selectedOption.label || selectedOption.textContent || '') : this.placeholder\n\t\t}\n\t}\n\n\tprivate setupOptionsAccessibility() {\n\t\tthis.options?.forEach((option, index) => {\n\t\t\toption.setAttribute('role', 'option')\n\t\t\tif (!option.id) {\n\t\t\t\toption.id = `${this.id}-option-${index}`\n\t\t\t}\n\n\t\t\t// Set tabindex to -1 so they're focusable programmatically but not in the tab order\n\t\t\toption.tabIndex = -1\n\n\t\t\toption.setAttribute(\n\t\t\t\t'aria-selected',\n\t\t\t\tString(this.multi ? this._selectedValues$.value.includes(option.value) : option.value === this._selectedValue$.value),\n\t\t\t)\n\t\t})\n\t}\n\n\tprivate async positionDropdown() {\n\t\tconst reference = this.renderRoot.querySelector('.trigger') as HTMLElement\n\t\tif (!reference || !this.ul) return\n\n\t\tthis.cleanupPositioner = autoUpdate(reference, this.ul, async () => {\n\t\t\t// Get viewport dimensions\n\t\t\tconst viewportHeight = window.innerHeight\n\t\t\tconst triggerRect = reference.getBoundingClientRect()\n\n\t\t\t// Calculate available space below and above\n\t\t\tconst spaceBelow = viewportHeight - triggerRect.bottom\n\t\t\tconst spaceAbove = triggerRect.top\n\n\t\t\t// Calculate max height - use 75% of the largest available space, but at least 150px\n\t\t\tconst maxHeight = Math.max(Math.max(spaceBelow, spaceAbove) * 0.75, 150)\n\n\t\t\t// Determine if we should flip\n\t\t\tconst shouldFlip = spaceBelow < 200 && spaceAbove > spaceBelow\n\n\t\t\t// Apply max height\n\t\t\tthis.ul.style.maxHeight = `${maxHeight}px`\n\n\t\t\tconst { x, y } = await computePosition(reference, this.ul, {\n\t\t\t\tplacement: shouldFlip ? 'top-start' : 'bottom-start',\n\t\t\t\tmiddleware: [offset(5), flip(), shift({ padding: 5 })],\n\t\t\t})\n\n\t\t\tObject.assign(this.ul.style, {\n\t\t\t\tleft: `${x}px`,\n\t\t\t\ttop: `${y}px`,\n\t\t\t\tposition: 'absolute',\n\t\t\t\twidth: `${reference.offsetWidth}px`, // Match the width of the trigger\n\t\t\t})\n\t\t})\n\t}\n\n\tprivate handleKeyDown = (e: KeyboardEvent) => {\n\t\t// Don't handle keyboard events when disabled\n\t\tif (this.disabled) {\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.isOpen) {\n\t\t\tif (['Enter', ' ', 'ArrowDown'].includes(e.key)) {\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.openDropdown(false)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Find current focused option\n\t\tconst options = Array.from(this.options || [])\n\t\tconst current = options.findIndex(o => o.id === this._focusedOptionId) ?? -1\n\n\t\tswitch (e.key) {\n\t\t\tcase 'Escape':\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.closeDropdown()\n\t\t\t\tbreak\n\t\t\tcase 'ArrowDown':\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.focusOption(options, Math.min(current + 1, options.length - 1))\n\t\t\t\tbreak\n\t\t\tcase 'ArrowUp':\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.focusOption(options, Math.max(current - 1, 0))\n\t\t\t\tbreak\n\t\t\tcase 'Home':\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.focusOption(options, 0)\n\t\t\t\tbreak\n\t\t\tcase 'End':\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.focusOption(options, options.length - 1)\n\t\t\t\tbreak\n\t\t\tcase 'Enter':\n\t\t\tcase ' ':\n\t\t\t\te.preventDefault()\n\t\t\t\tif (this._focusedOptionId) {\n\t\t\t\t\tconst focusedOption = options.find(opt => opt.id === this._focusedOptionId)\n\t\t\t\t\tif (focusedOption) {\n\t\t\t\t\t\tthis.handleOptionSelect(focusedOption.value)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\tcase 'Tab':\n\t\t\t\tthis.closeDropdown()\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate focusOption(options: SchmancyOption[], index: number) {\n\t\tconst option = options[index]\n\t\tif (option) {\n\t\t\toption.focus()\n\t\t\tthis._focusedOptionId = option.id\n\n\t\t\t// Update aria-activedescendant on the combobox\n\t\t\tconst combobox = this.renderRoot.querySelector('.trigger')\n\t\t\tif (combobox) {\n\t\t\t\tcombobox.setAttribute('aria-activedescendant', option.id)\n\t\t\t}\n\n\t\t\t// Ensure option is visible in the scrollable area\n\t\t\tif (this.ul && option.offsetTop !== undefined) {\n\t\t\t\t// Get position info\n\t\t\t\tconst optionTop = option.offsetTop\n\t\t\t\tconst optionHeight = option.offsetHeight\n\t\t\t\tconst scrollTop = this.ul.scrollTop\n\t\t\t\tconst ulHeight = this.ul.clientHeight\n\n\t\t\t\t// Scroll into view if needed\n\t\t\t\tif (optionTop < scrollTop) {\n\t\t\t\t\tthis.ul.scrollTop = optionTop\n\t\t\t\t} else if (optionTop + optionHeight > scrollTop + ulHeight) {\n\t\t\t\t\tthis.ul.scrollTop = optionTop + optionHeight - ulHeight\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async openDropdown(report = false) {\n\t\t// Don't open if disabled\n\t\tif (this.disabled) {\n\t\t\treturn\n\t\t}\n\n\t\t// Don't mark as touched on opening - we'll do that on closing\n\t\t// so errors only show after interaction is complete\n\n\t\tthis.isOpen = true\n\t\tawait this.updateComplete\n\n\t\t// Focus first or selected option\n\t\tconst options = Array.from(this.options || [])\n\t\tconst selectedIndex = this.multi ? 0 : options.findIndex(o => o.value === this._selectedValue$.value)\n\n\t\tthis.focusOption(options, Math.max(selectedIndex, 0))\n\n\t\t// Don't automatically validate when opening\n\t\t// Only validate if explicitly requested (like from a form submission)\n\t\tif (report) this.reportValidity()\n\t}\n\n\tprivate closeDropdown() {\n\t\t// Only mark as touched if the user actually interacted with the component\n\t\t// and made a selection or explicitly closed it without selecting\n\t\tif (this._userInteracted) {\n\t\t\tthis.touched = true\n\t\t}\n\n\t\tthis.isOpen = false\n\t\tthis._focusedOptionId = ''\n\n\t\t// Update combobox to remove aria-activedescendant\n\t\tconst combobox = this.renderRoot.querySelector<HTMLElement>('.trigger')\n\t\tif (combobox) {\n\t\t\tcombobox.removeAttribute('aria-activedescendant')\n\t\t\tcombobox?.focus()\n\t\t}\n\n\t\t// Only check validity when closing if the user has actually interacted\n\t\t// with the component and validation should be shown\n\t\tif (this._userInteracted && this._shouldShowError()) {\n\t\t\tthis.checkValidity()\n\t\t}\n\t}\n\n\tprivate _setupReactivePipelines() {\n\t\t// Listen for option-select events from child options\n\t\tfromEvent<CustomEvent>(this, 'option-select')\n\t\t\t.pipe(\n\t\t\t\ttap((e) => {\n\t\t\t\t\te.stopPropagation() // Prevent event from bubbling further\n\t\t\t\t\tconst option = this.options.find(o => o.value === e.detail.value)\n\t\t\t\t\tif (option) {\n\t\t\t\t\t\tthis._optionSelect$.next(option)\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting)\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\t// Handle option selection through reactive pipeline\n\t\tthis._optionSelect$\n\t\t\t.pipe(\n\t\t\t\twithLatestFrom(this._selectedValue$, this._selectedValues$),\n\t\t\t\ttap(([option, _, currentValues]) => {\n\t\t\t\t\tthis._userInteracted = true\n\t\t\t\t\tthis.markTouched()\n\t\t\t\t\t// `dirty` is a mixin getter; setting `value` below triggers it\n\n\t\t\t\t\tif (this.multi) {\n\t\t\t\t\t\tconst index = currentValues.indexOf(option.value)\n\t\t\t\t\t\tconst newValues = index > -1\n\t\t\t\t\t\t\t? [...currentValues.slice(0, index), ...currentValues.slice(index + 1)]\n\t\t\t\t\t\t\t: [...currentValues, option.value]\n\t\t\t\t\t\tthis._selectedValues$.next(newValues)\n\n\t\t\t\t\t\t// Update form value\n\t\t\t\t\t\tthis.internals?.setFormValue(newValues.join(','))\n\n\t\t\t\t\t\t// Update display label\n\t\t\t\t\t\tthis.valueLabel = newValues.length > 0\n\t\t\t\t\t\t\t? this.options\n\t\t\t\t\t\t\t\t\t.filter(o => newValues.includes(o.value))\n\t\t\t\t\t\t\t\t\t.map(o => o.label || o.textContent || '')\n\t\t\t\t\t\t\t\t\t.join(', ')\n\t\t\t\t\t\t\t: this.placeholder\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Single select\n\t\t\t\t\t\tthis._selectedValue$.next(option.value)\n\n\t\t\t\t\t\t// Update form value\n\t\t\t\t\t\tthis.internals?.setFormValue(option.value)\n\n\t\t\t\t\t\tthis.valueLabel = option.label || option.textContent || this.placeholder\n\t\t\t\t\t\tthis.closeDropdown()\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update the option's accessibility state\n\t\t\t\t\tthis.setupOptionsAccessibility()\n\n\t\t\t\t\t// Dispatch change event\n\t\t\t\t\tthis._fireChangeEvent()\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting)\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\t// Options management pipeline - bind pointerdown events exactly like autocomplete\n\t\tthis._options$\n\t\t\t.pipe(\n\t\t\t\ttap((options) => {\n\t\t\t\t\toptions.forEach((option, index) => {\n\t\t\t\t\t\toption.setAttribute('role', 'option')\n\t\t\t\t\t\toption.tabIndex = -1\n\t\t\t\t\t\tif (!option.id) {\n\t\t\t\t\t\t\toption.id = `${this.id}-option-${index}`\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Use data-event-bound to prevent duplicate bindings\n\t\t\t\t\t\tif (!option.hasAttribute('data-event-bound')) {\n\t\t\t\t\t\t\t// Use click event instead of pointerdown for better mobile UX\n\t\t\t\t\t\t\t// This allows users to scroll through options without immediately selecting\n\t\t\t\t\t\t\tfromEvent(option, 'click').pipe(\n\t\t\t\t\t\t\t\ttap(e => {\n\t\t\t\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\ttakeUntil(this.disconnecting)\n\t\t\t\t\t\t\t).subscribe(() => this._optionSelect$.next(option))\n\t\t\t\t\t\t\toption.setAttribute('data-event-bound', 'true')\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting)\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\t// Selection sync pipeline - sync selected states with value changes\n\t\tcombineLatest([this._selectedValue$, this._selectedValues$, this._options$])\n\t\t\t.pipe(\n\t\t\t\ttap(([singleValue, multiValues, options]) => {\n\t\t\t\t\tif (options.length === 0) return\n\n\t\t\t\t\tif (this.multi) {\n\t\t\t\t\t\toptions.forEach(option => {\n\t\t\t\t\t\t\toption.selected = multiValues.includes(option.value)\n\t\t\t\t\t\t})\n\t\t\t\t\t} else {\n\t\t\t\t\t\toptions.forEach(option => {\n\t\t\t\t\t\t\toption.selected = option.value === singleValue\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting)\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\tprivate handleOptionSelect(value: string) {\n\t\t// This method is now called from keyboard navigation only\n\t\tconst option = this.options.find(o => o.value === value)\n\t\tif (option) {\n\t\t\tthis._optionSelect$.next(option)\n\t\t}\n\t}\n\n\tprivate _fireChangeEvent() {\n\t\t// Get the current value based on multi/single mode\n\t\tconst value = this.multi ? this._selectedValues$.value : this._selectedValue$.value\n\n\t\t// Dispatch only one change event with the value in detail\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent<SchmancySelectChangeEvent['detail']>('change', {\n\t\t\t\tdetail: { value },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\n\t\t// Then check validity (only show error if validation should be shown)\n\t\tthis.checkValidity()\n\t}\n\n\tpublic checkValidity(): boolean {\n\t\t// Disabled fields are always valid\n\t\tif (this.disabled) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Determine if the select is empty based on whether it's multi-select or single-select\n\t\tconst isEmpty = this.multi\n\t\t\t? this._selectedValues$.value.length === 0\n\t\t\t: !this._selectedValue$.value\n\n\t\t// Check if the value is valid (not empty when required)\n\t\tconst isValid = !(this.required && isEmpty)\n\n\t\t// Set the validity state\n\t\tthis.isValid = isValid\n\n\t\tif (!this.isValid) {\n\t\t\tthis.validationMessage = 'Please select an option.'\n\t\t\tthis.internals?.setValidity({ valueMissing: true }, 'Please select an option.', this.inputRef)\n\t\t} else {\n\t\t\t// Clear validation message\n\t\t\tthis.validationMessage = ''\n\t\t\tthis.internals?.setValidity({})\n\t\t}\n\n\t\t// Update the input component to reflect our validation state\n\t\tif (this.inputRef && this.hasUpdated) {\n\t\t\tconst showError = !this.isValid && this._shouldShowError()\n\t\t\tthis.inputRef.error = showError\n\t\t\tthis.inputRef.hint = showError ? this.validationMessage : this.hint\n\t\t}\n\n\t\treturn this.isValid\n\t}\n\n\tpublic reportValidity(): boolean {\n\t\t// Force validation display regardless of validation strategy\n\t\tconst valid = this.checkValidity()\n\n\t\t// Force the input to show validation errors\n\t\tif (this.inputRef) {\n\t\t\t// Set the input's error state\n\t\t\tthis.inputRef.error = !valid\n\t\t\tthis.inputRef.hint = !valid ? this.validationMessage : this.hint\n\n\t\t\t// If invalid and not already open, automatically open the dropdown to show options\n\t\t\tif (!valid && !this.isOpen) {\n\t\t\t\t// Open the dropdown but don't mark as user interaction yet\n\t\t\t\t// This helps users immediately see available options when validation fails\n\t\t\t\tthis.openDropdown(false)\n\t\t\t}\n\n\t\t\t// Only call reportValidity on the input if invalid to show the native popup\n\t\t\tif (!valid) {\n\t\t\t\tthis.inputRef.reportValidity()\n\t\t\t}\n\t\t}\n\n\t\treturn valid\n\t}\n\n\t// `markTouched`, `markSubmitted`, `touched`, `dirty`, `pristine`, `submitted`,\n\t// `error` (storage) — all from the mixin. Select's `error` semantics\n\t// (errors-while-open suppression) live in render() via _shouldShowError() +\n\t// !isOpen, not as a separate getter.\n\n\t/**\n\t * Multi-value-aware `toFormEntries`. Single-select emits one `[name,value]`;\n\t * multi-select emits N entries with the same name (canonical FormData shape\n\t * for repeated fields).\n\t */\n\toverride toFormEntries(): Array<[string, FormDataEntryValue]> {\n\t\tif (!this.name || this.disabled) return []\n\t\tconst v = this.value\n\t\tif (v === undefined || v === null || v === '') return []\n\t\tif (Array.isArray(v))\n\t\t\treturn v.map(item => [this.name, String(item)] as [string, FormDataEntryValue])\n\t\treturn [[this.name, String(v)]]\n\t}\n\n\toverride setCustomValidity(message: string) {\n\t\tthis.validationMessage = message\n\t\tif (message) {\n\t\t\tthis.isValid = false\n\t\t\tthis.internals?.setValidity({ customError: true }, message, this.inputRef)\n\t\t} else {\n\t\t\tthis.isValid = true\n\t\t\tthis.internals?.setValidity({})\n\t\t}\n\n\t\t// Update input if needed\n\t\tif (this.inputRef && this._shouldShowError()) {\n\t\t\tthis.inputRef.error = !this.isValid\n\t\t\tthis.inputRef.hint = !this.isValid ? this.validationMessage : this.hint\n\t\t}\n\t}\n\n\t/**\n\t * Reset to the snapshot captured at connect time. Mixin's `resetForm`\n\t * handles touched/submitted/error/validationMessage; the override layers on\n\t * select-specific cleanup (value subjects, label, validity).\n\t */\n\toverride resetForm(): void {\n\t\t// Restore value (multi-aware) before super so the mixin's _defaultValue\n\t\t// reset doesn't clobber the array-shape we need.\n\t\tthis.value = this.selectDefaultValue\n\t\tthis.valueLabel = this.placeholder\n\t\tthis.isValid = true\n\t\tthis._userInteracted = false\n\t\tthis.internals?.setValidity({})\n\t\tsuper.resetForm()\n\t\tif (this.inputRef) {\n\t\t\tthis.inputRef.error = false\n\t\t\tthis.inputRef.hint = this.hint\n\t\t}\n\t}\n\n\t/** Back-compat alias for callers that used the previous public API. */\n\tpublic reset(): void {\n\t\tthis.resetForm()\n\t}\n\n\trender(): TemplateResult {\n\t\t// Determine if we should show errors based on the validation strategy and interaction\n\t\t// Never show errors on initial render or if the dropdown is open\n\t\tconst showErrors = !this.isValid && this._shouldShowError() && !this.isOpen\n\n\t\t// Add caret icon based on open state\n\t\tconst caretIcon = this.isOpen\n\t\t\t? html`<span class=\"absolute right-3 top-1/2 transform -translate-y-1/2\">▲</span>`\n\t\t\t: html`<span class=\"absolute right-3 top-1/2 transform -translate-y-1/2\">▼</span>`\n\n\t\treturn html`\n\t\t\t<div class=\"relative ${this.disabled ? 'opacity-60 cursor-not-allowed' : ''}\">\n\t\t\t\t<sch-input\n\t\t\t\t\t.name=${this.name ?? ''}\n\t\t\t\t\ttabIndex=${this.disabled ? '-1' : '0'}\n\t\t\t\t\tclass=\"trigger\"\n\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t\t\taria-expanded=${this.isOpen}\n\t\t\t\t\taria-controls=\"options\"\n\t\t\t\t\taria-autocomplete=\"none\"\n\t\t\t\t\taria-required=${this.required}\n\t\t\t\t\taria-activedescendant=${ifDefined(this._focusedOptionId || undefined)}\n\t\t\t\t\taria-disabled=${this.disabled}\n\t\t\t\t\t.label=${this.label}\n\t\t\t\t\t.placeholder=${this.placeholder}\n\t\t\t\t\t.value=${this.valueLabel}\n\t\t\t\t\t.required=${this.required}\n\t\t\t\t\t.disabled=${this.disabled}\n\t\t\t\t\t.hint=${showErrors ? this.validationMessage : this.hint}\n\t\t\t\t\t.error=${showErrors}\n\t\t\t\t\t.validateOn=${this.validateOn}\n\t\t\t\t\t.size=${this.size}\n\t\t\t\t\t.readonly=${true}\n\t\t\t\t\tclickable\n\t\t\t\t\t@click=${(e: MouseEvent) => {\n\t\t\t\t\t\t// Don't process clicks if disabled\n\t\t\t\t\t\tif (this.disabled) {\n\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// On first click, don't count this as user interaction yet\n\t\t\t\t\t\tif (!this.isOpen) {\n\t\t\t\t\t\t\t// Open without triggering validation - we'll validate when they close\n\t\t\t\t\t\t\tthis.openDropdown(false)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Mark as interacted when they close the dropdown\n\t\t\t\t\t\t\tthis._userInteracted = true\n\t\t\t\t\t\t\tthis.closeDropdown()\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t${caretIcon}\n\t\t\t\t</sch-input>\n\n\t\t\t\t<!-- Overlay for capturing clicks outside when dropdown is open -->\n\t\t\t\t${this.isOpen\n\t\t\t\t\t? html` <div class=\"fixed inset-0 z-10\" @click=${this.closeDropdown} tabindex=\"-1\" aria-hidden=\"true\"></div> `\n\t\t\t\t\t: ''}\n\n\t\t\t\t<ul\n\t\t\t\t\tid=\"options\"\n\t\t\t\t\trole=\"listbox\"\n\t\t\t\t\taria-multiselectable=${this.multi}\n\t\t\t\t\tclass=${classMap({\n\t\t\t\t\t\t'absolute min-w-full w-full z-20 mt-1 rounded-md shadow-lg': true,\n\t\t\t\t\t\thidden: !this.isOpen,\n\t\t\t\t\t})}\n\t\t\t\t\t${color({\n\t\t\t\t\t\tbgColor: SchmancyTheme.sys.color.surface.low,\n\t\t\t\t\t\tcolor: SchmancyTheme.sys.color.surface.on,\n\t\t\t\t\t})}\n\t\t\t\t>\n\t\t\t\t\t<slot\n\t\t\t\t\t\t@slotchange=${() => {\n\t\t\t\t\t\t\tthis._options$.next(this.options)\n\t\t\t\t\t\t\t// Sync selection state when options re-render\n\t\t\t\t\t\t\tthis.syncSelection()\n\t\t\t\t\t\t}}\n\t\t\t\t\t></slot>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t`\n\t}\n}\n\n// Don't export 'select' here as it conflicts with the store's select decorator\n// export const select = SchmancySelect\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-select': SchmancySelect\n\t}\n}\n"],"mappings":"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"}
@@ -1,56 +0,0 @@
1
- require(`./chunk-CncqDLb2.cjs`);const e=require(`./mixins-Du9HMrIG.cjs`),t=require(`./active-host-jH3iloCR.cjs`),n=require(`./directives.cjs`),r=require(`./theme.interface-D4NeufQA.cjs`);let i=require(`rxjs`),a=require(`rxjs/operators`),o=require(`lit/directives/class-map.js`),s=require(`lit/decorators.js`),c=require(`lit`),l=require(`lit/directives/if-defined.js`),u=require(`@floating-ui/dom`);var d=class extends e.o(){constructor(...e){super(...e),this.placeholder=``,this.multi=!1,this.size=`md`,this.isOpen=!1,this.valueLabel=``,this.isValid=!0,this.selectDefaultValue=``,this._options$=new i.BehaviorSubject([]),this._selectedValue$=new i.BehaviorSubject(``),this._selectedValues$=new i.BehaviorSubject([]),this._optionSelect$=new i.Subject,this._userInteracted=!1,this._focusedOptionId=``,this.handleKeyDown=e=>{if(this.disabled)return;if(!this.isOpen)return void([`Enter`,` `,`ArrowDown`].includes(e.key)&&(e.preventDefault(),this.openDropdown(!1)));let t=Array.from(this.options||[]),n=t.findIndex(e=>e.id===this._focusedOptionId)??-1;switch(e.key){case`Escape`:e.preventDefault(),this.closeDropdown();break;case`ArrowDown`:e.preventDefault(),this.focusOption(t,Math.min(n+1,t.length-1));break;case`ArrowUp`:e.preventDefault(),this.focusOption(t,Math.max(n-1,0));break;case`Home`:e.preventDefault(),this.focusOption(t,0);break;case`End`:e.preventDefault(),this.focusOption(t,t.length-1);break;case`Enter`:case` `:if(e.preventDefault(),this._focusedOptionId){let e=t.find(e=>e.id===this._focusedOptionId);e&&this.handleOptionSelect(e.value)}break;case`Tab`:this.closeDropdown()}}}static{this.styles=[c.css`
2
- :host {
3
- display: block;
4
- position: relative;
5
- }
6
-
7
- [role='listbox'] {
8
- overflow-y: auto;
9
- outline: none;
10
- }
11
- `]}get value(){return this.multi?this._selectedValues$.value:this._selectedValue$.value}set value(e){if(this.multi){let t=Array.isArray(e)?e:e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[];this._selectedValues$.next(t)}else this._selectedValue$.next(e==null?``:String(e))}get values(){return[...this._selectedValues$.value]}set values(e){this._selectedValues$.next(Array.isArray(e)?[...e]:[])}connectedCallback(){super.connectedCallback(),this.id||=`schmancy-select-${Math.random().toString(36).substring(2,9)}`,this.selectDefaultValue=this.value,(0,i.fromEvent)(this,`keydown`).pipe((0,i.takeUntil)(this.disconnecting)).subscribe(this.handleKeyDown),this._setupReactivePipelines()}disconnectedCallback(){super.disconnectedCallback(),this.cleanupPositioner?.()}firstUpdated(){this.syncSelection(),this.setupOptionsAccessibility(),this.inputRef&&(this.inputRef.error=!1)}updated(e){if(super.updated(e),e.has(`value`)){let e=this.multi?this._selectedValues$.value.join(`,`):this._selectedValue$.value;this.internals?.setFormValue(e)}e.has(`isOpen`)&&(this.isOpen?this.positionDropdown():this.cleanupPositioner?.())}syncSelection(){if(this.multi){let e=this._selectedValues$.value;this.options?.forEach(t=>t.selected=e.includes(t.value)),this.valueLabel=e.length>0&&this.options?.filter(t=>e.includes(t.value)).map(e=>e.label||e.textContent||``).join(`, `)||this.placeholder}else{let e=this._selectedValue$.value;this.options?.forEach(t=>{t.selected=t.value===e});let t=this.options?.find(t=>t.value===e);this.valueLabel=t?t.label||t.textContent||``:this.placeholder}}setupOptionsAccessibility(){this.options?.forEach((e,t)=>{e.setAttribute(`role`,`option`),e.id||=`${this.id}-option-${t}`,e.tabIndex=-1,e.setAttribute(`aria-selected`,String(this.multi?this._selectedValues$.value.includes(e.value):e.value===this._selectedValue$.value))})}async positionDropdown(){let e=this.renderRoot.querySelector(`.trigger`);e&&this.ul&&(this.cleanupPositioner=(0,u.autoUpdate)(e,this.ul,async()=>{let t=window.innerHeight,n=e.getBoundingClientRect(),r=t-n.bottom,i=n.top,a=Math.max(.75*Math.max(r,i),150),o=r<200&&i>r;this.ul.style.maxHeight=`${a}px`;let{x:s,y:c}=await(0,u.computePosition)(e,this.ul,{placement:o?`top-start`:`bottom-start`,middleware:[(0,u.offset)(5),(0,u.flip)(),(0,u.shift)({padding:5})]});Object.assign(this.ul.style,{left:`${s}px`,top:`${c}px`,position:`absolute`,width:`${e.offsetWidth}px`})}))}focusOption(e,t){let n=e[t];if(n){n.focus(),this._focusedOptionId=n.id;let e=this.renderRoot.querySelector(`.trigger`);if(e&&e.setAttribute(`aria-activedescendant`,n.id),this.ul&&n.offsetTop!==void 0){let e=n.offsetTop,t=n.offsetHeight,r=this.ul.scrollTop,i=this.ul.clientHeight;e<r?this.ul.scrollTop=e:e+t>r+i&&(this.ul.scrollTop=e+t-i)}}}async openDropdown(e=!1){if(this.disabled)return;this.isOpen=!0,await this.updateComplete;let t=Array.from(this.options||[]),n=this.multi?0:t.findIndex(e=>e.value===this._selectedValue$.value);this.focusOption(t,Math.max(n,0)),e&&this.reportValidity()}closeDropdown(){this._userInteracted&&(this.touched=!0),this.isOpen=!1,this._focusedOptionId=``;let e=this.renderRoot.querySelector(`.trigger`);e&&(e.removeAttribute(`aria-activedescendant`),e?.focus()),this._userInteracted&&this._shouldShowError()&&this.checkValidity()}_setupReactivePipelines(){(0,i.fromEvent)(this,`option-select`).pipe((0,a.tap)(e=>{e.stopPropagation();let t=this.options.find(t=>t.value===e.detail.value);t&&this._optionSelect$.next(t)}),(0,i.takeUntil)(this.disconnecting)).subscribe(),this._optionSelect$.pipe((0,a.withLatestFrom)(this._selectedValue$,this._selectedValues$),(0,a.tap)(([e,t,n])=>{if(this._userInteracted=!0,this.markTouched(),this.multi){let t=n.indexOf(e.value),r=t>-1?[...n.slice(0,t),...n.slice(t+1)]:[...n,e.value];this._selectedValues$.next(r),this.internals?.setFormValue(r.join(`,`)),this.valueLabel=r.length>0?this.options.filter(e=>r.includes(e.value)).map(e=>e.label||e.textContent||``).join(`, `):this.placeholder}else this._selectedValue$.next(e.value),this.internals?.setFormValue(e.value),this.valueLabel=e.label||e.textContent||this.placeholder,this.closeDropdown();this.setupOptionsAccessibility(),this._fireChangeEvent()}),(0,i.takeUntil)(this.disconnecting)).subscribe(),this._options$.pipe((0,a.tap)(e=>{e.forEach((e,t)=>{e.setAttribute(`role`,`option`),e.tabIndex=-1,e.id||=`${this.id}-option-${t}`,e.hasAttribute(`data-event-bound`)||((0,i.fromEvent)(e,`click`).pipe((0,a.tap)(e=>{e.stopPropagation()}),(0,i.takeUntil)(this.disconnecting)).subscribe(()=>this._optionSelect$.next(e)),e.setAttribute(`data-event-bound`,`true`))})}),(0,i.takeUntil)(this.disconnecting)).subscribe(),(0,i.combineLatest)([this._selectedValue$,this._selectedValues$,this._options$]).pipe((0,a.tap)(([e,t,n])=>{n.length!==0&&(this.multi?n.forEach(e=>{e.selected=t.includes(e.value)}):n.forEach(t=>{t.selected=t.value===e}))}),(0,i.takeUntil)(this.disconnecting)).subscribe()}handleOptionSelect(e){let t=this.options.find(t=>t.value===e);t&&this._optionSelect$.next(t)}_fireChangeEvent(){let e=this.multi?this._selectedValues$.value:this._selectedValue$.value;this.dispatchEvent(new CustomEvent(`change`,{detail:{value:e},bubbles:!0,composed:!0})),this.checkValidity()}checkValidity(){if(this.disabled)return!0;let e=this.multi?this._selectedValues$.value.length===0:!this._selectedValue$.value,t=!(this.required&&e);if(this.isValid=t,this.isValid?(this.validationMessage=``,this.internals?.setValidity({})):(this.validationMessage=`Please select an option.`,this.internals?.setValidity({valueMissing:!0},`Please select an option.`,this.inputRef)),this.inputRef&&this.hasUpdated){let e=!this.isValid&&this._shouldShowError();this.inputRef.error=e,this.inputRef.hint=e?this.validationMessage:this.hint}return this.isValid}reportValidity(){let e=this.checkValidity();return this.inputRef&&(this.inputRef.error=!e,this.inputRef.hint=e?this.hint:this.validationMessage,e||this.isOpen||this.openDropdown(!1),e||this.inputRef.reportValidity()),e}toFormEntries(){if(!this.name||this.disabled)return[];let e=this.value;return e==null||e===``?[]:Array.isArray(e)?e.map(e=>[this.name,String(e)]):[[this.name,String(e)]]}setCustomValidity(e){this.validationMessage=e,e?(this.isValid=!1,this.internals?.setValidity({customError:!0},e,this.inputRef)):(this.isValid=!0,this.internals?.setValidity({})),this.inputRef&&this._shouldShowError()&&(this.inputRef.error=!this.isValid,this.inputRef.hint=this.isValid?this.hint:this.validationMessage)}resetForm(){this.value=this.selectDefaultValue,this.valueLabel=this.placeholder,this.isValid=!0,this._userInteracted=!1,this.internals?.setValidity({}),super.resetForm(),this.inputRef&&(this.inputRef.error=!1,this.inputRef.hint=this.hint)}reset(){this.resetForm()}render(){let e=!this.isValid&&this._shouldShowError()&&!this.isOpen,t=this.isOpen?c.html`<span class="absolute right-3 top-1/2 transform -translate-y-1/2">▲</span>`:c.html`<span class="absolute right-3 top-1/2 transform -translate-y-1/2">▼</span>`;return c.html`
12
- <div class="relative ${this.disabled?`opacity-60 cursor-not-allowed`:``}">
13
- <sch-input
14
- .name=${this.name??``}
15
- tabIndex=${this.disabled?`-1`:`0`}
16
- class="trigger"
17
- role="combobox"
18
- aria-haspopup="listbox"
19
- aria-expanded=${this.isOpen}
20
- aria-controls="options"
21
- aria-autocomplete="none"
22
- aria-required=${this.required}
23
- aria-activedescendant=${(0,l.ifDefined)(this._focusedOptionId||void 0)}
24
- aria-disabled=${this.disabled}
25
- .label=${this.label}
26
- .placeholder=${this.placeholder}
27
- .value=${this.valueLabel}
28
- .required=${this.required}
29
- .disabled=${this.disabled}
30
- .hint=${e?this.validationMessage:this.hint}
31
- .error=${e}
32
- .validateOn=${this.validateOn}
33
- .size=${this.size}
34
- .readonly=${!0}
35
- clickable
36
- @click=${e=>{if(this.disabled)return e.preventDefault(),void e.stopPropagation();this.isOpen?(this._userInteracted=!0,this.closeDropdown()):this.openDropdown(!1)}}
37
- >
38
- ${t}
39
- </sch-input>
40
-
41
- <!-- Overlay for capturing clicks outside when dropdown is open -->
42
- ${this.isOpen?c.html` <div class="fixed inset-0 z-10" @click=${this.closeDropdown} tabindex="-1" aria-hidden="true"></div> `:``}
43
-
44
- <ul
45
- id="options"
46
- role="listbox"
47
- aria-multiselectable=${this.multi}
48
- class=${(0,o.classMap)({"absolute min-w-full w-full z-20 mt-1 rounded-md shadow-lg":!0,hidden:!this.isOpen})}
49
- ${n.color({bgColor:r.t.sys.color.surface.low,color:r.t.sys.color.surface.on})}
50
- >
51
- <slot
52
- @slotchange=${()=>{this._options$.next(this.options),this.syncSelection()}}
53
- ></slot>
54
- </ul>
55
- </div>
56
- `}};t.a([(0,s.property)({type:String})],d.prototype,`placeholder`,void 0),t.a([(0,s.property)({type:String,reflect:!0})],d.prototype,`value`,null),t.a([(0,s.property)({type:Array})],d.prototype,`values`,null),t.a([(0,s.property)({type:Boolean})],d.prototype,`multi`,void 0),t.a([(0,s.property)({type:String})],d.prototype,`size`,void 0),t.a([(0,s.state)()],d.prototype,`isOpen`,void 0),t.a([(0,s.state)()],d.prototype,`valueLabel`,void 0),t.a([(0,s.state)()],d.prototype,`isValid`,void 0),t.a([(0,s.state)()],d.prototype,`selectDefaultValue`,void 0),t.a([(0,s.query)(`ul`)],d.prototype,`ul`,void 0),t.a([(0,s.query)(`sch-input`)],d.prototype,`inputRef`,void 0),t.a([(0,s.queryAssignedElements)({flatten:!0})],d.prototype,`options`,void 0),t.a([(0,s.state)()],d.prototype,`_userInteracted`,void 0),t.a([(0,s.state)()],d.prototype,`_focusedOptionId`,void 0),d=t.a([(0,s.customElement)(`schmancy-select`)],d),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return d}});