@vielzeug/buildit 2.0.0

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 (792) hide show
  1. package/README.md +124 -0
  2. package/dist/accordion-item.cjs +32 -0
  3. package/dist/accordion-item.cjs.map +1 -0
  4. package/dist/accordion-item.js +72 -0
  5. package/dist/accordion-item.js.map +1 -0
  6. package/dist/accordion.cjs +2 -0
  7. package/dist/accordion.cjs.map +1 -0
  8. package/dist/accordion.js +37 -0
  9. package/dist/accordion.js.map +1 -0
  10. package/dist/alert.cjs +31 -0
  11. package/dist/alert.cjs.map +1 -0
  12. package/dist/alert.js +85 -0
  13. package/dist/alert.js.map +1 -0
  14. package/dist/avatar.cjs +37 -0
  15. package/dist/avatar.cjs.map +1 -0
  16. package/dist/avatar.js +123 -0
  17. package/dist/avatar.js.map +1 -0
  18. package/dist/badge.cjs +7 -0
  19. package/dist/badge.cjs.map +1 -0
  20. package/dist/badge.js +60 -0
  21. package/dist/badge.js.map +1 -0
  22. package/dist/box.cjs +2 -0
  23. package/dist/box.cjs.map +1 -0
  24. package/dist/box.js +22 -0
  25. package/dist/box.js.map +1 -0
  26. package/dist/breadcrumb.cjs +21 -0
  27. package/dist/breadcrumb.cjs.map +1 -0
  28. package/dist/breadcrumb.js +58 -0
  29. package/dist/breadcrumb.js.map +1 -0
  30. package/dist/buildit.cjs +1892 -0
  31. package/dist/buildit.cjs.map +1 -0
  32. package/dist/buildit.js +1892 -0
  33. package/dist/buildit.js.map +1 -0
  34. package/dist/button-group.cjs +6 -0
  35. package/dist/button-group.cjs.map +1 -0
  36. package/dist/button-group.js +31 -0
  37. package/dist/button-group.js.map +1 -0
  38. package/dist/button.cjs +30 -0
  39. package/dist/button.cjs.map +1 -0
  40. package/dist/button.js +115 -0
  41. package/dist/button.js.map +1 -0
  42. package/dist/card.cjs +23 -0
  43. package/dist/card.cjs.map +1 -0
  44. package/dist/card.js +99 -0
  45. package/dist/card.js.map +1 -0
  46. package/dist/checkbox-group.cjs +20 -0
  47. package/dist/checkbox-group.cjs.map +1 -0
  48. package/dist/checkbox-group.js +88 -0
  49. package/dist/checkbox-group.js.map +1 -0
  50. package/dist/checkbox.cjs +37 -0
  51. package/dist/checkbox.cjs.map +1 -0
  52. package/dist/checkbox.js +115 -0
  53. package/dist/checkbox.js.map +1 -0
  54. package/dist/chip.cjs +56 -0
  55. package/dist/chip.cjs.map +1 -0
  56. package/dist/chip.js +140 -0
  57. package/dist/chip.js.map +1 -0
  58. package/dist/combobox.cjs +93 -0
  59. package/dist/combobox.cjs.map +1 -0
  60. package/dist/combobox.js +401 -0
  61. package/dist/combobox.js.map +1 -0
  62. package/dist/content/avatar/avatar-group.css?inline.cjs +2 -0
  63. package/dist/content/avatar/avatar-group.css?inline.cjs.map +1 -0
  64. package/dist/content/avatar/avatar-group.css?inline.js +6 -0
  65. package/dist/content/avatar/avatar-group.css?inline.js.map +1 -0
  66. package/dist/content/avatar/avatar.css?inline.cjs +2 -0
  67. package/dist/content/avatar/avatar.css?inline.cjs.map +1 -0
  68. package/dist/content/avatar/avatar.css?inline.js +6 -0
  69. package/dist/content/avatar/avatar.css?inline.js.map +1 -0
  70. package/dist/content/avatar/avatar.d.ts +78 -0
  71. package/dist/content/avatar/avatar.d.ts.map +1 -0
  72. package/dist/content/breadcrumb/breadcrumb-item.css?inline.cjs +2 -0
  73. package/dist/content/breadcrumb/breadcrumb-item.css?inline.cjs.map +1 -0
  74. package/dist/content/breadcrumb/breadcrumb-item.css?inline.js +6 -0
  75. package/dist/content/breadcrumb/breadcrumb-item.css?inline.js.map +1 -0
  76. package/dist/content/breadcrumb/breadcrumb.css?inline.cjs +2 -0
  77. package/dist/content/breadcrumb/breadcrumb.css?inline.cjs.map +1 -0
  78. package/dist/content/breadcrumb/breadcrumb.css?inline.js +6 -0
  79. package/dist/content/breadcrumb/breadcrumb.css?inline.js.map +1 -0
  80. package/dist/content/breadcrumb/breadcrumb.d.ts +36 -0
  81. package/dist/content/breadcrumb/breadcrumb.d.ts.map +1 -0
  82. package/dist/content/card/card.css?inline.cjs +2 -0
  83. package/dist/content/card/card.css?inline.cjs.map +1 -0
  84. package/dist/content/card/card.css?inline.js +6 -0
  85. package/dist/content/card/card.css?inline.js.map +1 -0
  86. package/dist/content/card/card.d.ts +66 -0
  87. package/dist/content/card/card.d.ts.map +1 -0
  88. package/dist/content/index.cjs +1 -0
  89. package/dist/content/index.d.ts +15 -0
  90. package/dist/content/index.d.ts.map +1 -0
  91. package/dist/content/index.js +7 -0
  92. package/dist/content/pagination/pagination.css?inline.cjs +2 -0
  93. package/dist/content/pagination/pagination.css?inline.cjs.map +1 -0
  94. package/dist/content/pagination/pagination.css?inline.js +6 -0
  95. package/dist/content/pagination/pagination.css?inline.js.map +1 -0
  96. package/dist/content/pagination/pagination.d.ts +56 -0
  97. package/dist/content/pagination/pagination.d.ts.map +1 -0
  98. package/dist/content/separator/separator.css?inline.cjs +2 -0
  99. package/dist/content/separator/separator.css?inline.cjs.map +1 -0
  100. package/dist/content/separator/separator.css?inline.js +6 -0
  101. package/dist/content/separator/separator.css?inline.js.map +1 -0
  102. package/dist/content/separator/separator.d.ts +35 -0
  103. package/dist/content/separator/separator.d.ts.map +1 -0
  104. package/dist/content/table/table.css?inline.cjs +2 -0
  105. package/dist/content/table/table.css?inline.cjs.map +1 -0
  106. package/dist/content/table/table.css?inline.js +6 -0
  107. package/dist/content/table/table.css?inline.js.map +1 -0
  108. package/dist/content/table/table.d.ts +69 -0
  109. package/dist/content/table/table.d.ts.map +1 -0
  110. package/dist/content/text/text.css?inline.cjs +2 -0
  111. package/dist/content/text/text.css?inline.cjs.map +1 -0
  112. package/dist/content/text/text.css?inline.js +6 -0
  113. package/dist/content/text/text.css?inline.js.map +1 -0
  114. package/dist/content/text/text.d.ts +55 -0
  115. package/dist/content/text/text.d.ts.map +1 -0
  116. package/dist/craftit/dist/core/internal.cjs +2 -0
  117. package/dist/craftit/dist/core/internal.cjs.map +1 -0
  118. package/dist/craftit/dist/core/internal.js +25 -0
  119. package/dist/craftit/dist/core/internal.js.map +1 -0
  120. package/dist/craftit/dist/core/runtime-bindings.cjs +2 -0
  121. package/dist/craftit/dist/core/runtime-bindings.cjs.map +1 -0
  122. package/dist/craftit/dist/core/runtime-bindings.js +38 -0
  123. package/dist/craftit/dist/core/runtime-bindings.js.map +1 -0
  124. package/dist/craftit/dist/core/runtime-lifecycle.cjs +2 -0
  125. package/dist/craftit/dist/core/runtime-lifecycle.cjs.map +1 -0
  126. package/dist/craftit/dist/core/runtime-lifecycle.js +68 -0
  127. package/dist/craftit/dist/core/runtime-lifecycle.js.map +1 -0
  128. package/dist/craftit/dist/core/runtime.cjs +1 -0
  129. package/dist/craftit/dist/core/runtime.js +2 -0
  130. package/dist/craftit/dist/core/utilities.cjs +2 -0
  131. package/dist/craftit/dist/core/utilities.cjs.map +1 -0
  132. package/dist/craftit/dist/core/utilities.js +12 -0
  133. package/dist/craftit/dist/core/utilities.js.map +1 -0
  134. package/dist/craftit/dist/directives/attr.cjs +2 -0
  135. package/dist/craftit/dist/directives/attr.cjs.map +1 -0
  136. package/dist/craftit/dist/directives/attr.js +13 -0
  137. package/dist/craftit/dist/directives/attr.js.map +1 -0
  138. package/dist/craftit/dist/directives/bind.cjs +1 -0
  139. package/dist/craftit/dist/directives/bind.js +3 -0
  140. package/dist/craftit/dist/directives/choose.cjs +1 -0
  141. package/dist/craftit/dist/directives/choose.js +1 -0
  142. package/dist/craftit/dist/directives/classes.cjs +2 -0
  143. package/dist/craftit/dist/directives/classes.cjs.map +1 -0
  144. package/dist/craftit/dist/directives/classes.js +12 -0
  145. package/dist/craftit/dist/directives/classes.js.map +1 -0
  146. package/dist/craftit/dist/directives/each.cjs +2 -0
  147. package/dist/craftit/dist/directives/each.cjs.map +1 -0
  148. package/dist/craftit/dist/directives/each.js +96 -0
  149. package/dist/craftit/dist/directives/each.js.map +1 -0
  150. package/dist/craftit/dist/directives/index.cjs +1 -0
  151. package/dist/craftit/dist/directives/index.js +12 -0
  152. package/dist/craftit/dist/directives/match.cjs +1 -0
  153. package/dist/craftit/dist/directives/match.js +1 -0
  154. package/dist/craftit/dist/directives/memo.cjs +1 -0
  155. package/dist/craftit/dist/directives/memo.js +1 -0
  156. package/dist/craftit/dist/directives/raw.cjs +1 -0
  157. package/dist/craftit/dist/directives/raw.js +2 -0
  158. package/dist/craftit/dist/directives/spread.cjs +2 -0
  159. package/dist/craftit/dist/directives/spread.cjs.map +1 -0
  160. package/dist/craftit/dist/directives/spread.js +30 -0
  161. package/dist/craftit/dist/directives/spread.js.map +1 -0
  162. package/dist/craftit/dist/directives/style.cjs +1 -0
  163. package/dist/craftit/dist/directives/style.js +1 -0
  164. package/dist/craftit/dist/directives/until.cjs +1 -0
  165. package/dist/craftit/dist/directives/until.js +1 -0
  166. package/dist/craftit/dist/directives/when.cjs +2 -0
  167. package/dist/craftit/dist/directives/when.cjs.map +1 -0
  168. package/dist/craftit/dist/directives/when.js +14 -0
  169. package/dist/craftit/dist/directives/when.js.map +1 -0
  170. package/dist/craftit/dist/labs/a11y.cjs +2 -0
  171. package/dist/craftit/dist/labs/a11y.cjs.map +1 -0
  172. package/dist/craftit/dist/labs/a11y.js +38 -0
  173. package/dist/craftit/dist/labs/a11y.js.map +1 -0
  174. package/dist/craftit/dist/labs/list.cjs +2 -0
  175. package/dist/craftit/dist/labs/list.cjs.map +1 -0
  176. package/dist/craftit/dist/labs/list.js +87 -0
  177. package/dist/craftit/dist/labs/list.js.map +1 -0
  178. package/dist/craftit/dist/labs/observers.cjs +2 -0
  179. package/dist/craftit/dist/labs/observers.cjs.map +1 -0
  180. package/dist/craftit/dist/labs/observers.js +28 -0
  181. package/dist/craftit/dist/labs/observers.js.map +1 -0
  182. package/dist/craftit/dist/labs/overlay.cjs +2 -0
  183. package/dist/craftit/dist/labs/overlay.cjs.map +1 -0
  184. package/dist/craftit/dist/labs/overlay.js +49 -0
  185. package/dist/craftit/dist/labs/overlay.js.map +1 -0
  186. package/dist/craftit/dist/labs/selectable.cjs +2 -0
  187. package/dist/craftit/dist/labs/selectable.cjs.map +1 -0
  188. package/dist/craftit/dist/labs/selectable.js +29 -0
  189. package/dist/craftit/dist/labs/selectable.js.map +1 -0
  190. package/dist/craftit/dist/labs/selection.cjs +2 -0
  191. package/dist/craftit/dist/labs/selection.cjs.map +1 -0
  192. package/dist/craftit/dist/labs/selection.js +42 -0
  193. package/dist/craftit/dist/labs/selection.js.map +1 -0
  194. package/dist/craftit/dist/labs.cjs +1 -0
  195. package/dist/craftit/dist/labs.js +6 -0
  196. package/dist/custom-elements.json +2321 -0
  197. package/dist/dialog.cjs +33 -0
  198. package/dist/dialog.cjs.map +1 -0
  199. package/dist/dialog.js +94 -0
  200. package/dist/dialog.js.map +1 -0
  201. package/dist/disclosure/accordion/accordion.css?inline.cjs +2 -0
  202. package/dist/disclosure/accordion/accordion.css?inline.cjs.map +1 -0
  203. package/dist/disclosure/accordion/accordion.css?inline.js +6 -0
  204. package/dist/disclosure/accordion/accordion.css?inline.js.map +1 -0
  205. package/dist/disclosure/accordion/accordion.d.ts +47 -0
  206. package/dist/disclosure/accordion/accordion.d.ts.map +1 -0
  207. package/dist/disclosure/accordion-item/accordion-item.css?inline.cjs +2 -0
  208. package/dist/disclosure/accordion-item/accordion-item.css?inline.cjs.map +1 -0
  209. package/dist/disclosure/accordion-item/accordion-item.css?inline.js +6 -0
  210. package/dist/disclosure/accordion-item/accordion-item.css?inline.js.map +1 -0
  211. package/dist/disclosure/accordion-item/accordion-item.d.ts +62 -0
  212. package/dist/disclosure/accordion-item/accordion-item.d.ts.map +1 -0
  213. package/dist/disclosure/index.cjs +1 -0
  214. package/dist/disclosure/index.d.ts +11 -0
  215. package/dist/disclosure/index.d.ts.map +1 -0
  216. package/dist/disclosure/index.js +5 -0
  217. package/dist/disclosure/tab-item/tab-item.css?inline.cjs +2 -0
  218. package/dist/disclosure/tab-item/tab-item.css?inline.cjs.map +1 -0
  219. package/dist/disclosure/tab-item/tab-item.css?inline.js +6 -0
  220. package/dist/disclosure/tab-item/tab-item.css?inline.js.map +1 -0
  221. package/dist/disclosure/tab-item/tab-item.d.ts +39 -0
  222. package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -0
  223. package/dist/disclosure/tab-panel/tab-panel.css?inline.cjs +2 -0
  224. package/dist/disclosure/tab-panel/tab-panel.css?inline.cjs.map +1 -0
  225. package/dist/disclosure/tab-panel/tab-panel.css?inline.js +6 -0
  226. package/dist/disclosure/tab-panel/tab-panel.css?inline.js.map +1 -0
  227. package/dist/disclosure/tab-panel/tab-panel.d.ts +30 -0
  228. package/dist/disclosure/tab-panel/tab-panel.d.ts.map +1 -0
  229. package/dist/disclosure/tabs/tabs.css?inline.cjs +2 -0
  230. package/dist/disclosure/tabs/tabs.css?inline.cjs.map +1 -0
  231. package/dist/disclosure/tabs/tabs.css?inline.js +6 -0
  232. package/dist/disclosure/tabs/tabs.css?inline.js.map +1 -0
  233. package/dist/disclosure/tabs/tabs.d.ts +64 -0
  234. package/dist/disclosure/tabs/tabs.d.ts.map +1 -0
  235. package/dist/drawer.cjs +31 -0
  236. package/dist/drawer.cjs.map +1 -0
  237. package/dist/drawer.js +98 -0
  238. package/dist/drawer.js.map +1 -0
  239. package/dist/feedback/alert/alert.css?inline.cjs +2 -0
  240. package/dist/feedback/alert/alert.css?inline.cjs.map +1 -0
  241. package/dist/feedback/alert/alert.css?inline.js +6 -0
  242. package/dist/feedback/alert/alert.css?inline.js.map +1 -0
  243. package/dist/feedback/alert/alert.d.ts +63 -0
  244. package/dist/feedback/alert/alert.d.ts.map +1 -0
  245. package/dist/feedback/badge/badge.css?inline.cjs +2 -0
  246. package/dist/feedback/badge/badge.css?inline.cjs.map +1 -0
  247. package/dist/feedback/badge/badge.css?inline.js +6 -0
  248. package/dist/feedback/badge/badge.css?inline.js.map +1 -0
  249. package/dist/feedback/badge/badge.d.ts +67 -0
  250. package/dist/feedback/badge/badge.d.ts.map +1 -0
  251. package/dist/feedback/chip/chip.css?inline.cjs +2 -0
  252. package/dist/feedback/chip/chip.css?inline.cjs.map +1 -0
  253. package/dist/feedback/chip/chip.css?inline.js +6 -0
  254. package/dist/feedback/chip/chip.css?inline.js.map +1 -0
  255. package/dist/feedback/chip/chip.d.ts +124 -0
  256. package/dist/feedback/chip/chip.d.ts.map +1 -0
  257. package/dist/feedback/index.cjs +1 -0
  258. package/dist/feedback/index.d.ts +13 -0
  259. package/dist/feedback/index.d.ts.map +1 -0
  260. package/dist/feedback/index.js +6 -0
  261. package/dist/feedback/progress/progress.css?inline.cjs +2 -0
  262. package/dist/feedback/progress/progress.css?inline.cjs.map +1 -0
  263. package/dist/feedback/progress/progress.css?inline.js +6 -0
  264. package/dist/feedback/progress/progress.css?inline.js.map +1 -0
  265. package/dist/feedback/progress/progress.d.ts +64 -0
  266. package/dist/feedback/progress/progress.d.ts.map +1 -0
  267. package/dist/feedback/skeleton/skeleton.css?inline.cjs +2 -0
  268. package/dist/feedback/skeleton/skeleton.css?inline.cjs.map +1 -0
  269. package/dist/feedback/skeleton/skeleton.css?inline.js +6 -0
  270. package/dist/feedback/skeleton/skeleton.css?inline.js.map +1 -0
  271. package/dist/feedback/skeleton/skeleton.d.ts +61 -0
  272. package/dist/feedback/skeleton/skeleton.d.ts.map +1 -0
  273. package/dist/feedback/toast/index.d.ts +2 -0
  274. package/dist/feedback/toast/index.d.ts.map +1 -0
  275. package/dist/feedback/toast/toast.css?inline.cjs +2 -0
  276. package/dist/feedback/toast/toast.css?inline.cjs.map +1 -0
  277. package/dist/feedback/toast/toast.css?inline.js +6 -0
  278. package/dist/feedback/toast/toast.css?inline.js.map +1 -0
  279. package/dist/feedback/toast/toast.d.ts +95 -0
  280. package/dist/feedback/toast/toast.d.ts.map +1 -0
  281. package/dist/file-input.cjs +66 -0
  282. package/dist/file-input.cjs.map +1 -0
  283. package/dist/file-input.js +210 -0
  284. package/dist/file-input.js.map +1 -0
  285. package/dist/form.cjs +11 -0
  286. package/dist/form.cjs.map +1 -0
  287. package/dist/form.js +49 -0
  288. package/dist/form.js.map +1 -0
  289. package/dist/grid-item.cjs +2 -0
  290. package/dist/grid-item.cjs.map +1 -0
  291. package/dist/grid-item.js +28 -0
  292. package/dist/grid-item.js.map +1 -0
  293. package/dist/grid.cjs +2 -0
  294. package/dist/grid.cjs.map +1 -0
  295. package/dist/grid.js +90 -0
  296. package/dist/grid.js.map +1 -0
  297. package/dist/icons.cjs +176 -0
  298. package/dist/icons.cjs.map +1 -0
  299. package/dist/icons.d.ts +15 -0
  300. package/dist/icons.d.ts.map +1 -0
  301. package/dist/icons.js +181 -0
  302. package/dist/icons.js.map +1 -0
  303. package/dist/index.cjs +1 -0
  304. package/dist/index.d.ts +9 -0
  305. package/dist/index.d.ts.map +1 -0
  306. package/dist/index.js +53 -0
  307. package/dist/input.cjs +48 -0
  308. package/dist/input.cjs.map +1 -0
  309. package/dist/input.js +182 -0
  310. package/dist/input.js.map +1 -0
  311. package/dist/inputs/button/button.css?inline.cjs +2 -0
  312. package/dist/inputs/button/button.css?inline.cjs.map +1 -0
  313. package/dist/inputs/button/button.css?inline.js +6 -0
  314. package/dist/inputs/button/button.css?inline.js.map +1 -0
  315. package/dist/inputs/button/button.d.ts +73 -0
  316. package/dist/inputs/button/button.d.ts.map +1 -0
  317. package/dist/inputs/button-group/button-group.css?inline.cjs +2 -0
  318. package/dist/inputs/button-group/button-group.css?inline.cjs.map +1 -0
  319. package/dist/inputs/button-group/button-group.css?inline.js +6 -0
  320. package/dist/inputs/button-group/button-group.css?inline.js.map +1 -0
  321. package/dist/inputs/button-group/button-group.d.ts +52 -0
  322. package/dist/inputs/button-group/button-group.d.ts.map +1 -0
  323. package/dist/inputs/checkbox/checkbox.css?inline.cjs +2 -0
  324. package/dist/inputs/checkbox/checkbox.css?inline.cjs.map +1 -0
  325. package/dist/inputs/checkbox/checkbox.css?inline.js +6 -0
  326. package/dist/inputs/checkbox/checkbox.css?inline.js.map +1 -0
  327. package/dist/inputs/checkbox/checkbox.d.ts +43 -0
  328. package/dist/inputs/checkbox/checkbox.d.ts.map +1 -0
  329. package/dist/inputs/checkbox-group/checkbox-group.css?inline.cjs +2 -0
  330. package/dist/inputs/checkbox-group/checkbox-group.css?inline.cjs.map +1 -0
  331. package/dist/inputs/checkbox-group/checkbox-group.css?inline.js +6 -0
  332. package/dist/inputs/checkbox-group/checkbox-group.css?inline.js.map +1 -0
  333. package/dist/inputs/checkbox-group/checkbox-group.d.ts +56 -0
  334. package/dist/inputs/checkbox-group/checkbox-group.d.ts.map +1 -0
  335. package/dist/inputs/combobox/combobox-options.cjs +2 -0
  336. package/dist/inputs/combobox/combobox-options.cjs.map +1 -0
  337. package/dist/inputs/combobox/combobox-options.d.ts +7 -0
  338. package/dist/inputs/combobox/combobox-options.d.ts.map +1 -0
  339. package/dist/inputs/combobox/combobox-options.js +36 -0
  340. package/dist/inputs/combobox/combobox-options.js.map +1 -0
  341. package/dist/inputs/combobox/combobox-virtualizer.cjs +2 -0
  342. package/dist/inputs/combobox/combobox-virtualizer.cjs.map +1 -0
  343. package/dist/inputs/combobox/combobox-virtualizer.d.ts +20 -0
  344. package/dist/inputs/combobox/combobox-virtualizer.d.ts.map +1 -0
  345. package/dist/inputs/combobox/combobox-virtualizer.js +71 -0
  346. package/dist/inputs/combobox/combobox-virtualizer.js.map +1 -0
  347. package/dist/inputs/combobox/combobox.css?inline.cjs +2 -0
  348. package/dist/inputs/combobox/combobox.css?inline.cjs.map +1 -0
  349. package/dist/inputs/combobox/combobox.css?inline.js +6 -0
  350. package/dist/inputs/combobox/combobox.css?inline.js.map +1 -0
  351. package/dist/inputs/combobox/combobox.d.ts +28 -0
  352. package/dist/inputs/combobox/combobox.d.ts.map +1 -0
  353. package/dist/inputs/combobox/combobox.types.d.ts +36 -0
  354. package/dist/inputs/combobox/combobox.types.d.ts.map +1 -0
  355. package/dist/inputs/file-input/file-input.css?inline.cjs +2 -0
  356. package/dist/inputs/file-input/file-input.css?inline.cjs.map +1 -0
  357. package/dist/inputs/file-input/file-input.css?inline.js +6 -0
  358. package/dist/inputs/file-input/file-input.css?inline.js.map +1 -0
  359. package/dist/inputs/file-input/file-input.d.ts +94 -0
  360. package/dist/inputs/file-input/file-input.d.ts.map +1 -0
  361. package/dist/inputs/form/form.css?inline.cjs +2 -0
  362. package/dist/inputs/form/form.css?inline.cjs.map +1 -0
  363. package/dist/inputs/form/form.css?inline.js +6 -0
  364. package/dist/inputs/form/form.css?inline.js.map +1 -0
  365. package/dist/inputs/form/form.d.ts +61 -0
  366. package/dist/inputs/form/form.d.ts.map +1 -0
  367. package/dist/inputs/index.cjs +1 -0
  368. package/dist/inputs/index.d.ts +38 -0
  369. package/dist/inputs/index.d.ts.map +1 -0
  370. package/dist/inputs/index.js +18 -0
  371. package/dist/inputs/input/input.css?inline.cjs +2 -0
  372. package/dist/inputs/input/input.css?inline.cjs.map +1 -0
  373. package/dist/inputs/input/input.css?inline.js +6 -0
  374. package/dist/inputs/input/input.css?inline.js.map +1 -0
  375. package/dist/inputs/input/input.d.ts +82 -0
  376. package/dist/inputs/input/input.d.ts.map +1 -0
  377. package/dist/inputs/number-input/number-input.css?inline.cjs +2 -0
  378. package/dist/inputs/number-input/number-input.css?inline.cjs.map +1 -0
  379. package/dist/inputs/number-input/number-input.css?inline.js +6 -0
  380. package/dist/inputs/number-input/number-input.css?inline.js.map +1 -0
  381. package/dist/inputs/number-input/number-input.d.ts +76 -0
  382. package/dist/inputs/number-input/number-input.d.ts.map +1 -0
  383. package/dist/inputs/otp-input/otp-input.css?inline.cjs +2 -0
  384. package/dist/inputs/otp-input/otp-input.css?inline.cjs.map +1 -0
  385. package/dist/inputs/otp-input/otp-input.css?inline.js +6 -0
  386. package/dist/inputs/otp-input/otp-input.css?inline.js.map +1 -0
  387. package/dist/inputs/otp-input/otp-input.d.ts +71 -0
  388. package/dist/inputs/otp-input/otp-input.d.ts.map +1 -0
  389. package/dist/inputs/radio/radio.css?inline.cjs +2 -0
  390. package/dist/inputs/radio/radio.css?inline.cjs.map +1 -0
  391. package/dist/inputs/radio/radio.css?inline.js +6 -0
  392. package/dist/inputs/radio/radio.css?inline.js.map +1 -0
  393. package/dist/inputs/radio/radio.d.ts +41 -0
  394. package/dist/inputs/radio/radio.d.ts.map +1 -0
  395. package/dist/inputs/radio-group/radio-group.css?inline.cjs +2 -0
  396. package/dist/inputs/radio-group/radio-group.css?inline.cjs.map +1 -0
  397. package/dist/inputs/radio-group/radio-group.css?inline.js +6 -0
  398. package/dist/inputs/radio-group/radio-group.css?inline.js.map +1 -0
  399. package/dist/inputs/radio-group/radio-group.d.ts +61 -0
  400. package/dist/inputs/radio-group/radio-group.d.ts.map +1 -0
  401. package/dist/inputs/rating/rating.css?inline.cjs +2 -0
  402. package/dist/inputs/rating/rating.css?inline.cjs.map +1 -0
  403. package/dist/inputs/rating/rating.css?inline.js +6 -0
  404. package/dist/inputs/rating/rating.css?inline.js.map +1 -0
  405. package/dist/inputs/rating/rating.d.ts +48 -0
  406. package/dist/inputs/rating/rating.d.ts.map +1 -0
  407. package/dist/inputs/select/select.css?inline.cjs +2 -0
  408. package/dist/inputs/select/select.css?inline.cjs.map +1 -0
  409. package/dist/inputs/select/select.css?inline.js +6 -0
  410. package/dist/inputs/select/select.css?inline.js.map +1 -0
  411. package/dist/inputs/select/select.d.ts +79 -0
  412. package/dist/inputs/select/select.d.ts.map +1 -0
  413. package/dist/inputs/shared/base-props.d.ts +39 -0
  414. package/dist/inputs/shared/base-props.d.ts.map +1 -0
  415. package/dist/inputs/shared/composables/index.cjs +1 -0
  416. package/dist/inputs/shared/composables/index.d.ts +3 -0
  417. package/dist/inputs/shared/composables/index.d.ts.map +1 -0
  418. package/dist/inputs/shared/composables/index.js +2 -0
  419. package/dist/inputs/shared/composables/use-text-field.cjs +2 -0
  420. package/dist/inputs/shared/composables/use-text-field.cjs.map +1 -0
  421. package/dist/inputs/shared/composables/use-text-field.d.ts +33 -0
  422. package/dist/inputs/shared/composables/use-text-field.d.ts.map +1 -0
  423. package/dist/inputs/shared/composables/use-text-field.js +41 -0
  424. package/dist/inputs/shared/composables/use-text-field.js.map +1 -0
  425. package/dist/inputs/shared/composables/use-toggle-field.cjs +2 -0
  426. package/dist/inputs/shared/composables/use-toggle-field.cjs.map +1 -0
  427. package/dist/inputs/shared/composables/use-toggle-field.d.ts +18 -0
  428. package/dist/inputs/shared/composables/use-toggle-field.d.ts.map +1 -0
  429. package/dist/inputs/shared/composables/use-toggle-field.js +26 -0
  430. package/dist/inputs/shared/composables/use-toggle-field.js.map +1 -0
  431. package/dist/inputs/shared/design-presets.cjs +2 -0
  432. package/dist/inputs/shared/design-presets.cjs.map +1 -0
  433. package/dist/inputs/shared/design-presets.d.ts +97 -0
  434. package/dist/inputs/shared/design-presets.d.ts.map +1 -0
  435. package/dist/inputs/shared/design-presets.js +92 -0
  436. package/dist/inputs/shared/design-presets.js.map +1 -0
  437. package/dist/inputs/shared/dom-sync/dropdown.cjs +2 -0
  438. package/dist/inputs/shared/dom-sync/dropdown.cjs.map +1 -0
  439. package/dist/inputs/shared/dom-sync/dropdown.d.ts +7 -0
  440. package/dist/inputs/shared/dom-sync/dropdown.d.ts.map +1 -0
  441. package/dist/inputs/shared/dom-sync/dropdown.js +30 -0
  442. package/dist/inputs/shared/dom-sync/dropdown.js.map +1 -0
  443. package/dist/inputs/shared/dom-sync/field-sync.cjs +2 -0
  444. package/dist/inputs/shared/dom-sync/field-sync.cjs.map +1 -0
  445. package/dist/inputs/shared/dom-sync/field-sync.d.ts +36 -0
  446. package/dist/inputs/shared/dom-sync/field-sync.d.ts.map +1 -0
  447. package/dist/inputs/shared/dom-sync/field-sync.js +37 -0
  448. package/dist/inputs/shared/dom-sync/field-sync.js.map +1 -0
  449. package/dist/inputs/shared/dom-sync/form-context.cjs +2 -0
  450. package/dist/inputs/shared/dom-sync/form-context.cjs.map +1 -0
  451. package/dist/inputs/shared/dom-sync/form-context.d.ts +18 -0
  452. package/dist/inputs/shared/dom-sync/form-context.d.ts.map +1 -0
  453. package/dist/inputs/shared/dom-sync/form-context.js +20 -0
  454. package/dist/inputs/shared/dom-sync/form-context.js.map +1 -0
  455. package/dist/inputs/shared/dom-sync/index.cjs +1 -0
  456. package/dist/inputs/shared/dom-sync/index.d.ts +5 -0
  457. package/dist/inputs/shared/dom-sync/index.d.ts.map +1 -0
  458. package/dist/inputs/shared/dom-sync/index.js +4 -0
  459. package/dist/inputs/shared/dom-sync/label-sync.cjs +2 -0
  460. package/dist/inputs/shared/dom-sync/label-sync.cjs.map +1 -0
  461. package/dist/inputs/shared/dom-sync/label-sync.d.ts +16 -0
  462. package/dist/inputs/shared/dom-sync/label-sync.d.ts.map +1 -0
  463. package/dist/inputs/shared/dom-sync/label-sync.js +12 -0
  464. package/dist/inputs/shared/dom-sync/label-sync.js.map +1 -0
  465. package/dist/inputs/shared/form-context.cjs +2 -0
  466. package/dist/inputs/shared/form-context.cjs.map +1 -0
  467. package/dist/inputs/shared/form-context.d.ts +19 -0
  468. package/dist/inputs/shared/form-context.d.ts.map +1 -0
  469. package/dist/inputs/shared/form-context.js +7 -0
  470. package/dist/inputs/shared/form-context.js.map +1 -0
  471. package/dist/inputs/shared/utils/assistive-text.cjs +2 -0
  472. package/dist/inputs/shared/utils/assistive-text.cjs.map +1 -0
  473. package/dist/inputs/shared/utils/assistive-text.d.ts +24 -0
  474. package/dist/inputs/shared/utils/assistive-text.d.ts.map +1 -0
  475. package/dist/inputs/shared/utils/assistive-text.js +37 -0
  476. package/dist/inputs/shared/utils/assistive-text.js.map +1 -0
  477. package/dist/inputs/shared/utils/choice-change.cjs +2 -0
  478. package/dist/inputs/shared/utils/choice-change.cjs.map +1 -0
  479. package/dist/inputs/shared/utils/choice-change.d.ts +8 -0
  480. package/dist/inputs/shared/utils/choice-change.d.ts.map +1 -0
  481. package/dist/inputs/shared/utils/choice-change.js +13 -0
  482. package/dist/inputs/shared/utils/choice-change.js.map +1 -0
  483. package/dist/inputs/shared/utils/controlled-csv.cjs +2 -0
  484. package/dist/inputs/shared/utils/controlled-csv.cjs.map +1 -0
  485. package/dist/inputs/shared/utils/controlled-csv.d.ts +8 -0
  486. package/dist/inputs/shared/utils/controlled-csv.d.ts.map +1 -0
  487. package/dist/inputs/shared/utils/controlled-csv.js +15 -0
  488. package/dist/inputs/shared/utils/controlled-csv.js.map +1 -0
  489. package/dist/inputs/shared/utils/field-values.cjs +2 -0
  490. package/dist/inputs/shared/utils/field-values.cjs.map +1 -0
  491. package/dist/inputs/shared/utils/field-values.d.ts +5 -0
  492. package/dist/inputs/shared/utils/field-values.d.ts.map +1 -0
  493. package/dist/inputs/shared/utils/field-values.js +13 -0
  494. package/dist/inputs/shared/utils/field-values.js.map +1 -0
  495. package/dist/inputs/shared/utils/index.d.ts +5 -0
  496. package/dist/inputs/shared/utils/index.d.ts.map +1 -0
  497. package/dist/inputs/shared/validation/index.cjs +2 -0
  498. package/dist/inputs/shared/validation/index.cjs.map +1 -0
  499. package/dist/inputs/shared/validation/index.d.ts +14 -0
  500. package/dist/inputs/shared/validation/index.d.ts.map +1 -0
  501. package/dist/inputs/shared/validation/index.js +13 -0
  502. package/dist/inputs/shared/validation/index.js.map +1 -0
  503. package/dist/inputs/slider/slider.css?inline.cjs +2 -0
  504. package/dist/inputs/slider/slider.css?inline.cjs.map +1 -0
  505. package/dist/inputs/slider/slider.css?inline.js +6 -0
  506. package/dist/inputs/slider/slider.css?inline.js.map +1 -0
  507. package/dist/inputs/slider/slider.d.ts +82 -0
  508. package/dist/inputs/slider/slider.d.ts.map +1 -0
  509. package/dist/inputs/switch/switch.css?inline.cjs +2 -0
  510. package/dist/inputs/switch/switch.css?inline.cjs.map +1 -0
  511. package/dist/inputs/switch/switch.css?inline.js +6 -0
  512. package/dist/inputs/switch/switch.css?inline.js.map +1 -0
  513. package/dist/inputs/switch/switch.d.ts +40 -0
  514. package/dist/inputs/switch/switch.d.ts.map +1 -0
  515. package/dist/inputs/textarea/textarea.css?inline.cjs +2 -0
  516. package/dist/inputs/textarea/textarea.css?inline.cjs.map +1 -0
  517. package/dist/inputs/textarea/textarea.css?inline.js +6 -0
  518. package/dist/inputs/textarea/textarea.css?inline.js.map +1 -0
  519. package/dist/inputs/textarea/textarea.d.ts +57 -0
  520. package/dist/inputs/textarea/textarea.d.ts.map +1 -0
  521. package/dist/layout/box/box.css?inline.cjs +2 -0
  522. package/dist/layout/box/box.css?inline.cjs.map +1 -0
  523. package/dist/layout/box/box.css?inline.js +6 -0
  524. package/dist/layout/box/box.css?inline.js.map +1 -0
  525. package/dist/layout/box/box.d.ts +52 -0
  526. package/dist/layout/box/box.d.ts.map +1 -0
  527. package/dist/layout/grid/grid.css?inline.cjs +2 -0
  528. package/dist/layout/grid/grid.css?inline.cjs.map +1 -0
  529. package/dist/layout/grid/grid.css?inline.js +6 -0
  530. package/dist/layout/grid/grid.css?inline.js.map +1 -0
  531. package/dist/layout/grid/grid.d.ts +105 -0
  532. package/dist/layout/grid/grid.d.ts.map +1 -0
  533. package/dist/layout/grid-item/grid-item.css?inline.cjs +2 -0
  534. package/dist/layout/grid-item/grid-item.css?inline.cjs.map +1 -0
  535. package/dist/layout/grid-item/grid-item.css?inline.js +6 -0
  536. package/dist/layout/grid-item/grid-item.css?inline.js.map +1 -0
  537. package/dist/layout/grid-item/grid-item.d.ts +47 -0
  538. package/dist/layout/grid-item/grid-item.d.ts.map +1 -0
  539. package/dist/layout/index.cjs +1 -0
  540. package/dist/layout/index.d.ts +9 -0
  541. package/dist/layout/index.d.ts.map +1 -0
  542. package/dist/layout/index.js +4 -0
  543. package/dist/layout/sidebar/sidebar-group.css?inline.cjs +2 -0
  544. package/dist/layout/sidebar/sidebar-group.css?inline.cjs.map +1 -0
  545. package/dist/layout/sidebar/sidebar-group.css?inline.js +6 -0
  546. package/dist/layout/sidebar/sidebar-group.css?inline.js.map +1 -0
  547. package/dist/layout/sidebar/sidebar-item.css?inline.cjs +2 -0
  548. package/dist/layout/sidebar/sidebar-item.css?inline.cjs.map +1 -0
  549. package/dist/layout/sidebar/sidebar-item.css?inline.js +6 -0
  550. package/dist/layout/sidebar/sidebar-item.css?inline.js.map +1 -0
  551. package/dist/layout/sidebar/sidebar.css?inline.cjs +2 -0
  552. package/dist/layout/sidebar/sidebar.css?inline.cjs.map +1 -0
  553. package/dist/layout/sidebar/sidebar.css?inline.js +6 -0
  554. package/dist/layout/sidebar/sidebar.css?inline.js.map +1 -0
  555. package/dist/layout/sidebar/sidebar.d.ts +190 -0
  556. package/dist/layout/sidebar/sidebar.d.ts.map +1 -0
  557. package/dist/menu.cjs +133 -0
  558. package/dist/menu.cjs.map +1 -0
  559. package/dist/menu.js +296 -0
  560. package/dist/menu.js.map +1 -0
  561. package/dist/number-input.cjs +55 -0
  562. package/dist/number-input.cjs.map +1 -0
  563. package/dist/number-input.js +158 -0
  564. package/dist/number-input.js.map +1 -0
  565. package/dist/otp-input.cjs +22 -0
  566. package/dist/otp-input.cjs.map +1 -0
  567. package/dist/otp-input.js +120 -0
  568. package/dist/otp-input.js.map +1 -0
  569. package/dist/overlay/dialog/dialog.css?inline.cjs +2 -0
  570. package/dist/overlay/dialog/dialog.css?inline.cjs.map +1 -0
  571. package/dist/overlay/dialog/dialog.css?inline.js +6 -0
  572. package/dist/overlay/dialog/dialog.css?inline.js.map +1 -0
  573. package/dist/overlay/dialog/dialog.d.ts +98 -0
  574. package/dist/overlay/dialog/dialog.d.ts.map +1 -0
  575. package/dist/overlay/drawer/drawer.css?inline.cjs +2 -0
  576. package/dist/overlay/drawer/drawer.css?inline.cjs.map +1 -0
  577. package/dist/overlay/drawer/drawer.css?inline.js +6 -0
  578. package/dist/overlay/drawer/drawer.css?inline.js.map +1 -0
  579. package/dist/overlay/drawer/drawer.d.ts +98 -0
  580. package/dist/overlay/drawer/drawer.d.ts.map +1 -0
  581. package/dist/overlay/index.cjs +1 -0
  582. package/dist/overlay/index.d.ts +11 -0
  583. package/dist/overlay/index.d.ts.map +1 -0
  584. package/dist/overlay/index.js +5 -0
  585. package/dist/overlay/menu/menu.css?inline.cjs +2 -0
  586. package/dist/overlay/menu/menu.css?inline.cjs.map +1 -0
  587. package/dist/overlay/menu/menu.css?inline.js +6 -0
  588. package/dist/overlay/menu/menu.css?inline.js.map +1 -0
  589. package/dist/overlay/menu/menu.d.ts +45 -0
  590. package/dist/overlay/menu/menu.d.ts.map +1 -0
  591. package/dist/overlay/popover/popover.css?inline.cjs +2 -0
  592. package/dist/overlay/popover/popover.css?inline.cjs.map +1 -0
  593. package/dist/overlay/popover/popover.css?inline.js +6 -0
  594. package/dist/overlay/popover/popover.css?inline.js.map +1 -0
  595. package/dist/overlay/popover/popover.d.ts +56 -0
  596. package/dist/overlay/popover/popover.d.ts.map +1 -0
  597. package/dist/overlay/tooltip/tooltip.css?inline.cjs +2 -0
  598. package/dist/overlay/tooltip/tooltip.css?inline.cjs.map +1 -0
  599. package/dist/overlay/tooltip/tooltip.css?inline.js +6 -0
  600. package/dist/overlay/tooltip/tooltip.css?inline.js.map +1 -0
  601. package/dist/overlay/tooltip/tooltip.d.ts +55 -0
  602. package/dist/overlay/tooltip/tooltip.d.ts.map +1 -0
  603. package/dist/pagination.cjs +102 -0
  604. package/dist/pagination.cjs.map +1 -0
  605. package/dist/pagination.js +168 -0
  606. package/dist/pagination.js.map +1 -0
  607. package/dist/popover.cjs +16 -0
  608. package/dist/popover.cjs.map +1 -0
  609. package/dist/popover.js +110 -0
  610. package/dist/popover.js.map +1 -0
  611. package/dist/progress.cjs +51 -0
  612. package/dist/progress.cjs.map +1 -0
  613. package/dist/progress.js +90 -0
  614. package/dist/progress.js.map +1 -0
  615. package/dist/radio-group.cjs +20 -0
  616. package/dist/radio-group.cjs.map +1 -0
  617. package/dist/radio-group.js +104 -0
  618. package/dist/radio-group.js.map +1 -0
  619. package/dist/radio.cjs +16 -0
  620. package/dist/radio.cjs.map +1 -0
  621. package/dist/radio.js +135 -0
  622. package/dist/radio.js.map +1 -0
  623. package/dist/rating.cjs +37 -0
  624. package/dist/rating.cjs.map +1 -0
  625. package/dist/rating.js +123 -0
  626. package/dist/rating.js.map +1 -0
  627. package/dist/select.cjs +77 -0
  628. package/dist/select.cjs.map +1 -0
  629. package/dist/select.js +317 -0
  630. package/dist/select.js.map +1 -0
  631. package/dist/separator.cjs +26 -0
  632. package/dist/separator.cjs.map +1 -0
  633. package/dist/separator.js +46 -0
  634. package/dist/separator.js.map +1 -0
  635. package/dist/sidebar.cjs +69 -0
  636. package/dist/sidebar.cjs.map +1 -0
  637. package/dist/sidebar.js +202 -0
  638. package/dist/sidebar.js.map +1 -0
  639. package/dist/skeleton.cjs +10 -0
  640. package/dist/skeleton.cjs.map +1 -0
  641. package/dist/skeleton.js +56 -0
  642. package/dist/skeleton.js.map +1 -0
  643. package/dist/slider.cjs +24 -0
  644. package/dist/slider.cjs.map +1 -0
  645. package/dist/slider.js +209 -0
  646. package/dist/slider.js.map +1 -0
  647. package/dist/stateit/dist/computed.cjs +2 -0
  648. package/dist/stateit/dist/computed.cjs.map +1 -0
  649. package/dist/stateit/dist/computed.js +65 -0
  650. package/dist/stateit/dist/computed.js.map +1 -0
  651. package/dist/stateit/dist/effect.cjs +2 -0
  652. package/dist/stateit/dist/effect.cjs.map +1 -0
  653. package/dist/stateit/dist/effect.js +53 -0
  654. package/dist/stateit/dist/effect.js.map +1 -0
  655. package/dist/stateit/dist/index.cjs +1 -0
  656. package/dist/stateit/dist/index.js +5 -0
  657. package/dist/stateit/dist/runtime.cjs +2 -0
  658. package/dist/stateit/dist/runtime.cjs.map +1 -0
  659. package/dist/stateit/dist/runtime.js +43 -0
  660. package/dist/stateit/dist/runtime.js.map +1 -0
  661. package/dist/stateit/dist/signal.cjs +2 -0
  662. package/dist/stateit/dist/signal.cjs.map +1 -0
  663. package/dist/stateit/dist/signal.js +27 -0
  664. package/dist/stateit/dist/signal.js.map +1 -0
  665. package/dist/stateit/dist/store.cjs +2 -0
  666. package/dist/stateit/dist/store.cjs.map +1 -0
  667. package/dist/stateit/dist/store.js +17 -0
  668. package/dist/stateit/dist/store.js.map +1 -0
  669. package/dist/stateit/dist/types.cjs +2 -0
  670. package/dist/stateit/dist/types.cjs.map +1 -0
  671. package/dist/stateit/dist/types.js +6 -0
  672. package/dist/stateit/dist/types.js.map +1 -0
  673. package/dist/styles/animation.css +87 -0
  674. package/dist/styles/index.cjs +2 -0
  675. package/dist/styles/index.cjs.map +1 -0
  676. package/dist/styles/index.d.ts +48 -0
  677. package/dist/styles/index.d.ts.map +1 -0
  678. package/dist/styles/index.js +26 -0
  679. package/dist/styles/index.js.map +1 -0
  680. package/dist/styles/layer.css +18 -0
  681. package/dist/styles/mixins/accessibility.css.cjs +15 -0
  682. package/dist/styles/mixins/accessibility.css.cjs.map +1 -0
  683. package/dist/styles/mixins/accessibility.css.d.ts +46 -0
  684. package/dist/styles/mixins/accessibility.css.d.ts.map +1 -0
  685. package/dist/styles/mixins/accessibility.css.js +20 -0
  686. package/dist/styles/mixins/accessibility.css.js.map +1 -0
  687. package/dist/styles/mixins/animation.css.cjs +71 -0
  688. package/dist/styles/mixins/animation.css.cjs.map +1 -0
  689. package/dist/styles/mixins/animation.css.d.ts +22 -0
  690. package/dist/styles/mixins/animation.css.d.ts.map +1 -0
  691. package/dist/styles/mixins/animation.css.js +90 -0
  692. package/dist/styles/mixins/animation.css.js.map +1 -0
  693. package/dist/styles/mixins/shape.css.cjs +72 -0
  694. package/dist/styles/mixins/shape.css.cjs.map +1 -0
  695. package/dist/styles/mixins/shape.css.d.ts +97 -0
  696. package/dist/styles/mixins/shape.css.d.ts.map +1 -0
  697. package/dist/styles/mixins/shape.css.js +104 -0
  698. package/dist/styles/mixins/shape.css.js.map +1 -0
  699. package/dist/styles/mixins/states.css.cjs +18 -0
  700. package/dist/styles/mixins/states.css.cjs.map +1 -0
  701. package/dist/styles/mixins/states.css.d.ts +61 -0
  702. package/dist/styles/mixins/states.css.d.ts.map +1 -0
  703. package/dist/styles/mixins/states.css.js +26 -0
  704. package/dist/styles/mixins/states.css.js.map +1 -0
  705. package/dist/styles/mixins/theme.css.cjs +146 -0
  706. package/dist/styles/mixins/theme.css.cjs.map +1 -0
  707. package/dist/styles/mixins/theme.css.d.ts +93 -0
  708. package/dist/styles/mixins/theme.css.d.ts.map +1 -0
  709. package/dist/styles/mixins/theme.css.js +151 -0
  710. package/dist/styles/mixins/theme.css.js.map +1 -0
  711. package/dist/styles/mixins/variants.css.cjs +84 -0
  712. package/dist/styles/mixins/variants.css.cjs.map +1 -0
  713. package/dist/styles/mixins/variants.css.d.ts +22 -0
  714. package/dist/styles/mixins/variants.css.d.ts.map +1 -0
  715. package/dist/styles/mixins/variants.css.js +89 -0
  716. package/dist/styles/mixins/variants.css.js.map +1 -0
  717. package/dist/styles/preflight.css +237 -0
  718. package/dist/styles/styles.css +5 -0
  719. package/dist/styles/theme.css +457 -0
  720. package/dist/switch.cjs +16 -0
  721. package/dist/switch.cjs.map +1 -0
  722. package/dist/switch.js +82 -0
  723. package/dist/switch.js.map +1 -0
  724. package/dist/tab-item.cjs +17 -0
  725. package/dist/tab-item.cjs.map +1 -0
  726. package/dist/tab-item.js +57 -0
  727. package/dist/tab-item.js.map +1 -0
  728. package/dist/tab-panel.cjs +14 -0
  729. package/dist/tab-panel.cjs.map +1 -0
  730. package/dist/tab-panel.js +51 -0
  731. package/dist/tab-panel.js.map +1 -0
  732. package/dist/table.cjs +2 -0
  733. package/dist/table.cjs.map +1 -0
  734. package/dist/table.js +101 -0
  735. package/dist/table.js.map +1 -0
  736. package/dist/tabs.cjs +17 -0
  737. package/dist/tabs.cjs.map +1 -0
  738. package/dist/tabs.js +98 -0
  739. package/dist/tabs.js.map +1 -0
  740. package/dist/text.cjs +2 -0
  741. package/dist/text.cjs.map +1 -0
  742. package/dist/text.js +30 -0
  743. package/dist/text.js.map +1 -0
  744. package/dist/textarea.cjs +16 -0
  745. package/dist/textarea.cjs.map +1 -0
  746. package/dist/textarea.js +122 -0
  747. package/dist/textarea.js.map +1 -0
  748. package/dist/toast.cjs +63 -0
  749. package/dist/toast.cjs.map +1 -0
  750. package/dist/toast.js +221 -0
  751. package/dist/toast.js.map +1 -0
  752. package/dist/tooltip.cjs +15 -0
  753. package/dist/tooltip.cjs.map +1 -0
  754. package/dist/tooltip.js +111 -0
  755. package/dist/tooltip.js.map +1 -0
  756. package/dist/types/index.d.ts +7 -0
  757. package/dist/types/index.d.ts.map +1 -0
  758. package/dist/types/shared.d.ts +120 -0
  759. package/dist/types/shared.d.ts.map +1 -0
  760. package/dist/utils/animation.cjs +2 -0
  761. package/dist/utils/animation.cjs.map +1 -0
  762. package/dist/utils/animation.d.ts +2 -0
  763. package/dist/utils/animation.d.ts.map +1 -0
  764. package/dist/utils/animation.js +29 -0
  765. package/dist/utils/animation.js.map +1 -0
  766. package/dist/utils/background-lock.cjs +2 -0
  767. package/dist/utils/background-lock.cjs.map +1 -0
  768. package/dist/utils/background-lock.d.ts +20 -0
  769. package/dist/utils/background-lock.d.ts.map +1 -0
  770. package/dist/utils/background-lock.js +21 -0
  771. package/dist/utils/background-lock.js.map +1 -0
  772. package/dist/utils/index.cjs +1 -0
  773. package/dist/utils/index.d.ts +4 -0
  774. package/dist/utils/index.d.ts.map +1 -0
  775. package/dist/utils/index.js +3 -0
  776. package/dist/utils/use-overlay.cjs +2 -0
  777. package/dist/utils/use-overlay.cjs.map +1 -0
  778. package/dist/utils/use-overlay.d.ts +26 -0
  779. package/dist/utils/use-overlay.d.ts.map +1 -0
  780. package/dist/utils/use-overlay.js +34 -0
  781. package/dist/utils/use-overlay.js.map +1 -0
  782. package/dist/virtualit/dist/dom/dom.cjs +2 -0
  783. package/dist/virtualit/dist/dom/dom.cjs.map +1 -0
  784. package/dist/virtualit/dist/dom/dom.js +47 -0
  785. package/dist/virtualit/dist/dom/dom.js.map +1 -0
  786. package/dist/virtualit/dist/dom.cjs +1 -0
  787. package/dist/virtualit/dist/dom.js +2 -0
  788. package/dist/virtualit/dist/virtualit.cjs +2 -0
  789. package/dist/virtualit/dist/virtualit.cjs.map +1 -0
  790. package/dist/virtualit/dist/virtualit.js +129 -0
  791. package/dist/virtualit/dist/virtualit.js.map +1 -0
  792. package/package.json +282 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildit.js","names":["e","t","n","r","i","a","o","#e","s","e","t","i","e","r","t","#n","#e","#i","#s","#a","n","#o","#t","#r","a","o","s","c","r","e","i","t","a","n","e","t","#e","#t","r","i","a","o","s","c","r","i","n","e","#e","#t","t","a","o","n","r","i","i","a","o","s","t","c","l","u","e","p","m","n","r","i","a","o","s","c","l","u","d","f","e","r","n","t","i","a","o","e","o","a","s","e","c","r","i","n","l","u","t","d","t","e","n","t","e","n","t","i","e","r","t","e","t","e","r","e","t","e","e","n","t","t","e","t","e"],"sources":["../src/styles/mixins/accessibility.css.ts","../src/styles/mixins/shape.css.ts","../src/styles/mixins/states.css.ts","../src/styles/mixins/theme.css.ts","../src/styles/mixins/animation.css.ts","../src/styles/mixins/variants.css.ts","../src/styles/index.ts","../src/content/avatar/avatar.css?inline","../src/content/avatar/avatar-group.css?inline","../src/content/avatar/avatar.ts","../src/content/breadcrumb/breadcrumb-item.css?inline","../src/content/breadcrumb/breadcrumb.css?inline","../src/content/breadcrumb/breadcrumb.ts","../src/content/card/card.css?inline","../src/content/card/card.ts","../../stateit/dist/runtime.js","../../stateit/dist/types.js","../../stateit/dist/computed.js","../../stateit/dist/effect.js","../../stateit/dist/signal.js","../../stateit/dist/store.js","../../craftit/dist/core/internal.js","../../craftit/dist/core/runtime-lifecycle.js","../../craftit/dist/core/utilities.js","../../craftit/dist/core/runtime-bindings.js","../../craftit/dist/directives/spread.js","../../craftit/dist/directives/attr.js","../../craftit/dist/directives/classes.js","../../craftit/dist/directives/each.js","../../craftit/dist/directives/when.js","../src/inputs/button-group/button-group.css?inline","../src/inputs/button-group/button-group.ts","../src/inputs/button/button.css?inline","../src/inputs/button/button.ts","../src/content/pagination/pagination.css?inline","../src/content/pagination/pagination.ts","../src/content/separator/separator.css?inline","../src/content/separator/separator.ts","../src/content/table/table.css?inline","../src/content/table/table.ts","../src/content/text/text.css?inline","../src/content/text/text.ts","../src/disclosure/accordion/accordion.css?inline","../src/disclosure/accordion/accordion.ts","../src/disclosure/tabs/tabs.css?inline","../src/disclosure/tabs/tabs.ts","../src/disclosure/accordion-item/accordion-item.css?inline","../src/disclosure/accordion-item/accordion-item.ts","../src/disclosure/tab-item/tab-item.css?inline","../src/disclosure/tab-item/tab-item.ts","../src/disclosure/tab-panel/tab-panel.css?inline","../src/disclosure/tab-panel/tab-panel.ts","../src/icons.ts","../src/utils/animation.ts","../src/feedback/alert/alert.css?inline","../src/feedback/alert/alert.ts","../src/feedback/badge/badge.css?inline","../src/feedback/badge/badge.ts","../src/feedback/chip/chip.css?inline","../src/feedback/chip/chip.ts","../src/feedback/progress/progress.css?inline","../src/feedback/progress/progress.ts","../../craftit/dist/labs/observers.js","../../craftit/dist/labs/list.js","../../craftit/dist/labs/overlay.js","../../craftit/dist/labs/selection.js","../../craftit/dist/labs/a11y.js","../../craftit/dist/labs/selectable.js","../src/feedback/skeleton/skeleton.css?inline","../src/feedback/skeleton/skeleton.ts","../src/feedback/toast/toast.css?inline","../src/feedback/toast/toast.ts","../src/inputs/shared/dom-sync/dropdown.ts","../src/inputs/shared/utils/assistive-text.ts","../src/inputs/shared/utils/choice-change.ts","../src/inputs/shared/utils/field-values.ts","../src/inputs/shared/utils/controlled-csv.ts","../src/inputs/shared/dom-sync/field-sync.ts","../src/inputs/shared/form-context.ts","../src/inputs/shared/dom-sync/form-context.ts","../src/inputs/shared/dom-sync/label-sync.ts","../src/inputs/checkbox-group/checkbox-group.css?inline","../src/inputs/checkbox-group/checkbox-group.ts","../src/inputs/shared/validation/index.ts","../src/inputs/shared/composables/use-text-field.ts","../src/inputs/shared/composables/use-toggle-field.ts","../src/inputs/shared/design-presets.ts","../src/inputs/checkbox/checkbox.css?inline","../src/inputs/checkbox/checkbox.ts","../src/inputs/combobox/combobox-options.ts","../../virtualit/dist/virtualit.js","../../virtualit/dist/dom/dom.js","../src/inputs/combobox/combobox-virtualizer.ts","../src/inputs/combobox/combobox.css?inline","../src/inputs/combobox/combobox.ts","../src/inputs/file-input/file-input.css?inline","../src/inputs/file-input/file-input.ts","../src/inputs/form/form.css?inline","../src/inputs/form/form.ts","../src/inputs/input/input.css?inline","../src/inputs/input/input.ts","../src/inputs/number-input/number-input.css?inline","../src/inputs/number-input/number-input.ts","../src/inputs/otp-input/otp-input.css?inline","../src/inputs/otp-input/otp-input.ts","../src/inputs/radio-group/radio-group.css?inline","../src/inputs/radio-group/radio-group.ts","../src/inputs/radio/radio.css?inline","../src/inputs/radio/radio.ts","../src/inputs/rating/rating.css?inline","../src/inputs/rating/rating.ts","../src/inputs/select/select.css?inline","../src/inputs/select/select.ts","../src/inputs/slider/slider.css?inline","../src/inputs/slider/slider.ts","../src/inputs/switch/switch.css?inline","../src/inputs/switch/switch.ts","../src/inputs/textarea/textarea.css?inline","../src/inputs/textarea/textarea.ts","../src/layout/box/box.css?inline","../src/layout/box/box.ts","../src/layout/grid-item/grid-item.css?inline","../src/layout/grid-item/grid-item.ts","../src/layout/grid/grid.css?inline","../src/layout/grid/grid.ts","../src/layout/sidebar/sidebar.css?inline","../src/layout/sidebar/sidebar-group.css?inline","../src/layout/sidebar/sidebar-item.css?inline","../src/layout/sidebar/sidebar.ts","../src/utils/background-lock.ts","../src/utils/use-overlay.ts","../src/overlay/dialog/dialog.css?inline","../src/overlay/dialog/dialog.ts","../src/overlay/drawer/drawer.css?inline","../src/overlay/drawer/drawer.ts","../src/overlay/menu/menu.css?inline","../src/overlay/menu/menu.ts","../src/overlay/popover/popover.css?inline","../src/overlay/popover/popover.ts","../src/overlay/tooltip/tooltip.css?inline","../src/overlay/tooltip/tooltip.ts"],"sourcesContent":["import { css } from '@vielzeug/craftit';\n\n/**\n * Coarse Pointer Mixin\n *\n * Defines `--_touch-target: var(--size-11)` on `:host` under `@media (pointer: coarse)`\n * to expose the WCAG minimum tap-target token across the shadow DOM.\n * Interactive elements inside the component should reference it:\n *\n * ```css\n * .close { min-height: var(--_touch-target); min-width: var(--_touch-target); }\n * ```\n *\n * @example\n * ```ts\n * import { coarsePointerMixin } from '../../styles';\n *\n * return {\n * styles: [coarsePointerMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const coarsePointerMixin = css`\n @media (pointer: coarse) {\n :host {\n --_touch-target: var(--size-11);\n }\n }\n`;\n\n/**\n * Reduced Motion Mixin\n *\n * Defines `--_motion-transition: none` and `--_motion-animation: none` on\n * `:host` under `@media (prefers-reduced-motion: reduce)`.\n * Component CSS opts in via CSS variable fallbacks:\n *\n * ```css\n * .panel { transition: var(--_motion-transition, opacity 300ms ease); }\n * .loader { animation: var(--_motion-animation, spin 0.6s linear infinite); }\n * ```\n *\n * @example\n * ```ts\n * import { reducedMotionMixin } from '../../styles';\n *\n * return {\n * styles: [reducedMotionMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const reducedMotionMixin = css`\n @media (prefers-reduced-motion: reduce) {\n :host {\n --_motion-transition: none;\n --_motion-animation: none;\n }\n }\n`;\n","import { css } from '@vielzeug/craftit';\n\n// ── Padding ───────────────────────────────────────────────────────────────────\n\n/**\n * Padding Variant Mixin\n *\n * Provides padding size variants (none, sm, md, lg, xl) via CSS custom properties.\n * Sets the --_padding variable based on padding attribute.\n *\n * @example\n * ```ts\n * import { paddingMixin } from '../../styles';\n *\n * return {\n * styles: [paddingMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const paddingMixin = css`\n /* ========================================\n Padding Variants\n ======================================== */\n\n :host([padding='none']) {\n --_padding: var(--size-0);\n }\n\n :host([padding='sm']) {\n --_padding: var(--size-3);\n }\n\n :host([padding='md']) {\n --_padding: var(--size-4);\n }\n\n :host([padding='lg']) {\n --_padding: var(--size-6);\n }\n\n :host([padding='xl']) {\n --_padding: var(--size-8);\n }\n`;\n\n// ── Rounded ───────────────────────────────────────────────────────────────────\n\n/**\n * Rounded Variant Mixin\n *\n * Shared border-radius variant styles for components.\n * Maps rounded attribute values to theme border radius tokens.\n *\n * @example\n * ```ts\n * import { roundedVariantMixin } from '../../styles';\n *\n * return {\n * styles: [roundedVariantMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const roundedVariantMixin = css`\n :host([rounded='none']) {\n --_radius: var(--rounded-none);\n }\n :host([rounded='sm']) {\n --_radius: var(--rounded-sm);\n }\n :host([rounded='md']) {\n --_radius: var(--rounded-md);\n }\n :host([rounded='lg']) {\n --_radius: var(--rounded-lg);\n }\n :host([rounded='xl']) {\n --_radius: var(--rounded-xl);\n }\n :host([rounded='2xl']) {\n --_radius: var(--rounded-2xl);\n }\n :host([rounded='3xl']) {\n --_radius: var(--rounded-3xl);\n }\n :host([rounded='full']),\n :host([rounded='']) {\n --_radius: var(--rounded-full);\n }\n`;\n\n// ── Size Variants ─────────────────────────────────────────────────────────────\n\n/**\n * Size Variant Mixin\n *\n * Provides consistent size variants (sm, md, lg) across components.\n * Reduces code duplication for size-based styling.\n *\n * @param config - Optional configuration for size-specific values\n * @returns CSSResult with size variant styles\n *\n * @example\n * ```ts\n * import { sizeVariantMixin } from '../../styles';\n *\n * return {\n * styles: [sizeVariantMixin(), componentStyles],\n * template: html`...`\n * };\n * ```\n *\n * @example\n * ```ts\n * // Custom size configuration\n * return {\n * styles: [sizeVariantMixin({\n * sm: { size: 'var(--size-3)', fontSize: 'var(--text-2xs)' },\n * lg: { size: 'var(--size-8)', fontSize: 'var(--text-lg)' },\n * }), componentStyles],\n * template: html`...`\n * };\n * ```\n */\ntype SizeConfig = {\n /** Arbitrary CSS custom properties (must start with --) */\n [key: `--${string}`]: string | undefined;\n /** Font size — maps to --_font-size */\n fontSize?: string;\n /** Gap between elements — maps to --_gap */\n gap?: string;\n /** Element height — maps to --_height */\n height?: string;\n /** Icon size — maps to --_icon-size */\n iconSize?: string;\n /** Line height — maps to --_line-height */\n lineHeight?: string;\n /** Internal padding — maps to --_padding */\n padding?: string;\n /** Element size (width/height) — maps to --_size */\n size?: string;\n /** Thumb size (e.g. toggle/switch thumb) — maps to --_thumb-size */\n thumbSize?: string;\n /** Element width — maps to --_width */\n width?: string;\n};\n\nexport const sizeVariantMixin = (config?: {\n /** Large size configuration */\n lg?: SizeConfig;\n /** Medium size configuration (default) */\n md?: SizeConfig;\n /** Small size configuration */\n sm?: SizeConfig;\n}) => {\n const defaults = {\n lg: {\n fontSize: 'var(--text-base)',\n gap: 'var(--size-2-5)',\n size: 'var(--size-6)',\n },\n md: {\n fontSize: 'var(--text-sm)',\n gap: 'var(--size-2)',\n size: 'var(--size-5)',\n },\n sm: {\n fontSize: 'var(--text-xs)',\n gap: 'var(--size-1-5)',\n size: 'var(--size-4)',\n },\n };\n\n const sm = { ...defaults.sm, ...config?.sm };\n const md = { ...defaults.md, ...config?.md };\n const lg = { ...defaults.lg, ...config?.lg };\n\n // Helper to convert camelCase to kebab-case\n const camelToKebab = (str: string): string => {\n return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n };\n\n // Helper to generate CSS for a size\n const generateSizeCSS = (sizeConfig: typeof sm) => {\n return Object.entries(sizeConfig)\n .map(([key, value]) => {\n if (value === undefined) return '';\n\n // If it already starts with --, pass it through as-is (custom property)\n if (key.startsWith('--')) {\n return `${key}: ${value};`;\n }\n\n // Convert camelCase to --_kebab-case custom property\n // Examples: gap → --_gap, fontSize → --_font-size, lineHeight → --_line-height\n const customProperty = `--_${camelToKebab(key)}`;\n\n return `${customProperty}: ${value};`;\n })\n .filter(Boolean)\n .join('\\n ');\n };\n\n return css`\n /* ========================================\n Size Variants (Shared Mixin)\n ======================================== */\n\n /* Small */\n :host([size='sm']) {\n ${generateSizeCSS(sm)}\n }\n\n /* Medium (default, can be used for explicit md attribute) */\n :host([size='md']) {\n ${generateSizeCSS(md)}\n }\n\n /* Large */\n :host([size='lg']) {\n ${generateSizeCSS(lg)}\n }\n `;\n};\n","import { css } from '@vielzeug/craftit';\n\n/**\n * Disabled State Mixin\n *\n * Provides consistent disabled styling across interactive components.\n * Reduces opacity, changes cursor, and prevents pointer events.\n *\n * @param selector - Optional CSS selector to apply styles to (default: component root)\n * @returns CSSResult with disabled state styles\n *\n * @example\n * ```ts\n * import { disabledStateMixin } from '../../styles';\n *\n * return {\n * styles: [disabledStateMixin(), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const disabledStateMixin = (selector = '') => {\n const sel = selector ? ` ${selector}` : '';\n\n return css`\n :host([disabled])${sel} {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n `;\n};\n\n/**\n * Loading State Mixin\n *\n * Provides consistent loading styling across interactive components.\n * Similar to disabled but for loading states.\n *\n * @param selector - Optional CSS selector to apply styles to (default: component root)\n * @returns CSSResult with loading state styles\n *\n * @example\n * ```ts\n * import { loadingStateMixin } from '../../styles';\n *\n * return {\n * styles: [loadingStateMixin(), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const loadingStateMixin = (selector = '') => {\n const sel = selector ? ` ${selector}` : '';\n\n return css`\n :host([loading])${sel} {\n opacity: 0.5;\n cursor: wait;\n pointer-events: none;\n }\n `;\n};\n\n/**\n * Combined Disabled & Loading State Mixin\n *\n * Convenience mixin that combines both disabled and loading states.\n * Most interactive components need both.\n *\n * @param selector - Optional CSS selector to apply styles to\n * @returns CSSResult with both disabled and loading state styles\n *\n * @example\n * ```ts\n * import { disabledLoadingMixin } from '../../styles';\n *\n * return {\n * styles: [disabledLoadingMixin('button'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const disabledLoadingMixin = (selector = '') => {\n const sel = selector ? ` ${selector}` : '';\n\n return css`\n :host([disabled])${sel}, :host([loading])${sel} {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n :host([loading])${sel} {\n cursor: wait;\n }\n `;\n};\n","import { css } from '@vielzeug/craftit';\n\n// ── Color Theme ───────────────────────────────────────────────────────────────\n\n/**\n * Color Theme Mixin\n *\n * Provides theme color CSS custom properties for components.\n * Sets up --_theme-* variables that map to semantic color tokens.\n *\n * @example\n * ```ts\n * import { colorThemeMixin } from '../../styles';\n *\n * return {\n * styles: [colorThemeMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const colorThemeMixin = css`\n /* ========================================\n Color Themes (Default: Neutral)\n ======================================== */\n\n :host {\n /* Default to neutral when no color is specified */\n --_theme-base: var(--color-neutral);\n --_theme-content: var(--color-neutral-content);\n --_theme-contrast: var(--color-neutral-contrast);\n --_theme-focus: var(--color-neutral-focus);\n --_theme-backdrop: var(--color-neutral-backdrop);\n --_theme-border: var(--color-neutral-border);\n --_theme-shadow: var(--color-neutral-focus-shadow);\n --_theme-halo: var(--halo-shadow-neutral);\n }\n\n :host([color='primary']) {\n --_theme-base: var(--color-primary);\n --_theme-content: var(--color-primary-content);\n --_theme-contrast: var(--color-primary-contrast);\n --_theme-focus: var(--color-primary-focus);\n --_theme-backdrop: var(--color-primary-backdrop);\n --_theme-border: var(--color-primary-border);\n --_theme-shadow: var(--color-primary-focus-shadow);\n --_theme-halo: var(--halo-shadow-primary);\n }\n\n :host([color='secondary']) {\n --_theme-base: var(--color-secondary);\n --_theme-content: var(--color-secondary-content);\n --_theme-contrast: var(--color-secondary-contrast);\n --_theme-focus: var(--color-secondary-focus);\n --_theme-backdrop: var(--color-secondary-backdrop);\n --_theme-border: var(--color-secondary-border);\n --_theme-shadow: var(--color-secondary-focus-shadow);\n --_theme-halo: var(--halo-shadow-secondary);\n }\n\n :host([color='info']) {\n --_theme-base: var(--color-info);\n --_theme-content: var(--color-info-content);\n --_theme-contrast: var(--color-info-contrast);\n --_theme-focus: var(--color-info-focus);\n --_theme-backdrop: var(--color-info-backdrop);\n --_theme-border: var(--color-info-border);\n --_theme-shadow: var(--color-info-focus-shadow);\n --_theme-halo: var(--halo-shadow-info);\n }\n\n :host([color='success']) {\n --_theme-base: var(--color-success);\n --_theme-content: var(--color-success-content);\n --_theme-contrast: var(--color-success-contrast);\n --_theme-focus: var(--color-success-focus);\n --_theme-backdrop: var(--color-success-backdrop);\n --_theme-border: var(--color-success-border);\n --_theme-shadow: var(--color-success-focus-shadow);\n --_theme-halo: var(--halo-shadow-success);\n }\n\n :host([color='warning']) {\n --_theme-base: var(--color-warning);\n --_theme-content: var(--color-warning-content);\n --_theme-contrast: var(--color-warning-contrast);\n --_theme-focus: var(--color-warning-focus);\n --_theme-backdrop: var(--color-warning-backdrop);\n --_theme-border: var(--color-warning-border);\n --_theme-shadow: var(--color-warning-focus-shadow);\n --_theme-halo: var(--halo-shadow-warning);\n }\n\n :host([color='error']) {\n --_theme-base: var(--color-error);\n --_theme-content: var(--color-error-content);\n --_theme-contrast: var(--color-error-contrast);\n --_theme-focus: var(--color-error-focus);\n --_theme-backdrop: var(--color-error-backdrop);\n --_theme-border: var(--color-error-border);\n --_theme-shadow: var(--color-error-focus-shadow);\n --_theme-halo: var(--halo-shadow-error);\n }\n`;\n\n// ── Elevation ─────────────────────────────────────────────────────────────────\n\n/**\n * Elevation Mixin\n *\n * Provides elevation shadow levels (0-5) via CSS custom properties.\n * Sets the --_shadow variable based on elevation attribute.\n *\n * @example\n * ```ts\n * import { elevationMixin } from '../../styles';\n *\n * return {\n * styles: [elevationMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const elevationMixin = css`\n /* ========================================\n Elevation Levels (0-5)\n ======================================== */\n\n :host([elevation='0']) {\n --_shadow: none;\n }\n\n :host([elevation='1']) {\n --_shadow: var(--shadow-sm);\n }\n\n :host([elevation='2']) {\n --_shadow: var(--shadow-md);\n }\n\n :host([elevation='3']) {\n --_shadow: var(--shadow-lg);\n }\n\n :host([elevation='4']) {\n --_shadow: var(--shadow-xl);\n }\n\n :host([elevation='5']) {\n --_shadow: var(--shadow-2xl);\n }\n`;\n\n// ── Forced Colors ─────────────────────────────────────────────────────────────\n\n/**\n * Forced Colors Mixin\n *\n * Ensures components are visually distinct in Windows High Contrast / forced-colors mode.\n * The browser already overrides `color`, `background-color`, and `border-color` to system\n * color keywords, but components that rely solely on `background` for visual identity\n * (no border) or that use `box-shadow` for focus rings need explicit fallbacks.\n *\n * Usage: apply to any component that has a background but no natural border.\n *\n * @example\n * ```ts\n * import { forcedColorsMixin } from '../../styles';\n *\n * return {\n * styles: [forcedColorsMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const forcedColorsMixin = css`\n @media (forced-colors: active) {\n :host {\n border: 1px solid ButtonText;\n }\n }\n`;\n\n/**\n * Forced Colors Focus Ring Mixin\n *\n * Replaces box-shadow focus rings (which are removed in forced-colors mode)\n * with a proper system-color outline.\n *\n * @param selector - CSS selector for the focusable element inside the host\n *\n * @example\n * ```ts\n * import { forcedColorsFocusMixin } from '../../styles';\n *\n * return {\n * styles: [forcedColorsFocusMixin('button'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const forcedColorsFocusMixin = (selector: string) => css`\n @media (forced-colors: active) {\n ${selector}:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: 2px;\n box-shadow: none;\n }\n }\n`;\n\n/**\n * Forced Colors Form Control Mixin\n *\n * For custom form controls (checkbox, radio, switch, slider) that paint their\n * own visual state. Maps checked/active state to system colors so they remain\n * distinguishable in forced-colors mode.\n *\n * @example\n * ```ts\n * import { forcedColorsFormControlMixin } from '../../styles';\n *\n * return {\n * styles: [forcedColorsFormControlMixin, componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const forcedColorsFormControlMixin = css`\n @media (forced-colors: active) {\n :host {\n forced-color-adjust: none;\n color: ButtonText;\n background: ButtonFace;\n border: 1px solid ButtonText;\n }\n\n :host([checked]) {\n background: Highlight;\n color: HighlightText;\n border-color: Highlight;\n }\n\n :host([disabled]) {\n color: GrayText;\n border-color: GrayText;\n }\n }\n`;\n","import { css } from '@vielzeug/craftit';\n\n/**\n * Register the --rainbow-angle CSS custom property so browsers can\n * interpolate it inside conic-gradient().\n * Called automatically by rainbowEffectMixin on first use.\n */\nlet rainbowRegistered = false;\n\nexport function registerRainbowProperty() {\n if (rainbowRegistered) return;\n\n if (typeof CSS !== 'undefined' && CSS.registerProperty) {\n try {\n CSS.registerProperty({\n inherits: false,\n initialValue: '0deg',\n name: '--rainbow-angle',\n syntax: '<angle>',\n });\n } catch {\n // Already registered — safe to ignore\n }\n }\n\n rainbowRegistered = true;\n}\n\n/**\n * Rainbow Border Effect Mixin\n *\n * Animated rainbow border with glow effect.\n * Perfect for highlighting call-to-action elements or special features.\n *\n * @param selector - CSS selector for the element (e.g., 'button', '.box')\n * @returns CSSResult with rainbow border animation\n *\n * @example\n * ```ts\n * import { rainbowEffectMixin } from '../../styles/effects/rainbow.css';\n *\n * return {\n * styles: [rainbowEffectMixin('button'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const rainbowEffectMixin = (selector: string) => {\n registerRainbowProperty();\n\n return css`\n /* ========================================\n Rainbow Border Effect\n ======================================== */\n\n :host([rainbow]) ${selector} {\n position: relative;\n border: var(--border-2) solid transparent !important;\n overflow: visible;\n }\n\n /* Rainbow border and glow layers */\n :host([rainbow]) ${selector}::before, :host([rainbow]) ${selector}::after {\n content: '';\n position: absolute;\n inset: calc(-1 * var(--border-2));\n border: inherit;\n border-radius: inherit;\n\n /* Reserve no-clip space for glow */\n box-shadow: 0 0 calc(3 * var(--blur-xl)) rgba(0 0 0 / 0.001);\n\n /* Rainbow gradient — Okabe-Ito colorblind-safe palette */\n background: conic-gradient(\n from var(--rainbow-angle),\n #56b4e9,\n /* Sky Blue */ #0072b2,\n /* Deep Blue */ #009e73,\n /* Bluish Green */ #f0e442,\n /* Yellow */ #e69f00,\n /* Orange */ #d55e00,\n /* Vermillion */ #cc79a7,\n /* Reddish Purple */ #56b4e9 /* Back to Sky Blue */\n )\n border-box;\n\n /* Make everything inside padding-box transparent\n by subtracting padding-box from no-clip box */\n -webkit-mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n mask:\n conic-gradient(red 0 0) no-clip subtract,\n conic-gradient(red 0 0) padding-box;\n\n pointer-events: none;\n animation: rainbow-rotate 4s linear infinite;\n }\n\n /* Turn one pseudo layer into glow halo */\n :host([rainbow]) ${selector}::after {\n filter: blur(var(--blur-xl));\n }\n\n /* ========================================\n Animation\n ======================================== */\n\n @keyframes rainbow-rotate {\n to {\n --rainbow-angle: 1turn;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host([rainbow]) ${selector}::before, :host([rainbow]) ${selector}::after {\n animation: none;\n }\n }\n `;\n};\n","import { css } from '@vielzeug/craftit';\n\n/**\n * Frost Variant Mixin\n *\n * Shared frost variant styles for components.\n * Provides consistent frosted glass effect with backdrop blur,\n * theme-aware colors, halo shadows, and elevation support.\n *\n * @param selector - CSS selector for the element (e.g., 'button', '.card', '.field')\n * @returns CSSResult with complete frost variant implementation\n *\n * @example\n * ```ts\n * import { frostVariantMixin } from '../../styles/mixins/frost.css';\n *\n * return {\n * styles: [frostVariantMixin('button'), componentStyles],\n * template: html`...`\n * };\n * ```\n */\nexport const frostVariantMixin = (selector: string) => css`\n :host([variant='frost']) ${selector} {\n backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n -webkit-backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n }\n\n :host([variant='frost']:not([color])) ${selector} {\n background: color-mix(in srgb, var(--color-canvas) 55%, transparent);\n border-color: color-mix(in srgb, var(--color-contrast-400) 45%, transparent);\n color: var(--color-contrast);\n text-shadow: var(--text-shadow-xs);\n border: var(--border) solid var(--_border-color);\n }\n\n /* Frost neutral without elevation: use halo shadow */\n :host([variant='frost']:not([color]):not([elevation])) ${selector} {\n box-shadow: var(--halo-shadow-neutral);\n }\n\n /* Frost neutral with elevation: combine halo with elevation shadow */\n :host([variant='frost']:not([color])[elevation]) ${selector} {\n box-shadow: var(--halo-shadow-neutral), var(--_shadow);\n }\n\n :host([variant='frost'][color]) ${selector} {\n background: color-mix(in srgb, var(--_theme-base), transparent);\n border-color: color-mix(in srgb, var(--_theme-border) 45%, transparent);\n color: var(--_theme-content);\n border: var(--border) solid color-mix(in srgb, var(--_theme-border) 45%, transparent);\n backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n -webkit-backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n text-shadow: var(--text-shadow-xs);\n filter: brightness(1.05);\n }\n\n /* Frost color without elevation: use halo shadow */\n :host([variant='frost'][color]:not([elevation])) ${selector} {\n box-shadow: var(--_theme-halo);\n }\n\n /* Frost color with elevation: combine halo with elevation shadow */\n :host([variant='frost'][color][elevation]) ${selector} {\n box-shadow: var(--_theme-halo), var(--_shadow);\n }\n\n :host([variant='frost']:not([color])) ${selector}:hover {\n backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n -webkit-backdrop-filter: blur(var(--blur-2xl)) saturate(220%) brightness(1.15);\n }\n\n :host([variant='frost'][color]) ${selector}:hover {\n backdrop-filter: blur(var(--blur-3xl)) saturate(240%) brightness(1.2);\n -webkit-backdrop-filter: blur(var(--blur-3xl)) saturate(240%) brightness(1.2);\n }\n\n /* ========================================\n Halo Shadows per Theme Color\n ======================================== */\n\n :host([variant='frost'][color='primary']) ${selector} {\n box-shadow: var(--halo-shadow-primary);\n }\n\n :host([variant='frost'][color='secondary']) ${selector} {\n box-shadow: var(--halo-shadow-secondary);\n }\n\n :host([variant='frost'][color='info']) ${selector} {\n box-shadow: var(--halo-shadow-info);\n }\n\n :host([variant='frost'][color='success']) ${selector} {\n box-shadow: var(--halo-shadow-success);\n }\n\n :host([variant='frost'][color='warning']) ${selector} {\n box-shadow: var(--halo-shadow-warning);\n }\n\n :host([variant='frost'][color='error']) ${selector} {\n box-shadow: var(--halo-shadow-error);\n }\n`;\n","/**\n * Shared Mixins & Effects\n *\n * Reusable CSS mixins for common component patterns.\n */\n\nimport { coarsePointerMixin, reducedMotionMixin } from './mixins/accessibility.css';\nimport { paddingMixin, roundedVariantMixin } from './mixins/shape.css';\nimport { disabledStateMixin } from './mixins/states.css';\nimport { colorThemeMixin, elevationMixin, forcedColorsFormControlMixin } from './mixins/theme.css';\n\n// Accessibility Mixins\nexport { coarsePointerMixin, reducedMotionMixin } from './mixins/accessibility.css';\n// Effects\nexport { rainbowEffectMixin, registerRainbowProperty } from './mixins/animation.css';\n// Shape Mixins (padding, rounded, size)\nexport { paddingMixin, roundedVariantMixin, sizeVariantMixin } from './mixins/shape.css';\n// State Mixins\nexport { disabledLoadingMixin, disabledStateMixin, loadingStateMixin } from './mixins/states.css';\n// Theme Mixins (color, elevation, forced-colors)\nexport {\n colorThemeMixin,\n elevationMixin,\n forcedColorsFocusMixin,\n forcedColorsFormControlMixin,\n forcedColorsMixin,\n} from './mixins/theme.css';\n// Frost Mixin\nexport { frostVariantMixin } from './mixins/variants.css';\n\n// ── Preset Arrays ─────────────────────────────────────────────────────────────\n\n/**\n * Base mixins for text-field-style form inputs (input, select, combobox).\n * Covers theming, coarse pointer, reduced motion, and border radius.\n * Still add `sizeVariantMixin({...})`, `disabledLoadingMixin()`, and\n * `forcedColorsFocusMixin(selector)` separately.\n *\n * @example\n * ```ts\n * styles: [...formFieldMixins, sizeVariantMixin({...}), disabledLoadingMixin(), forcedColorsFocusMixin('input'), componentStyles]\n * ```\n */\nexport const formFieldMixins = [colorThemeMixin, coarsePointerMixin, reducedMotionMixin, roundedVariantMixin] as const;\n\n/**\n * Base mixins for elevated surface components (box, card).\n * Covers theming, elevation shadows, padding, and border radius.\n *\n * @example\n * ```ts\n * styles: [...surfaceMixins, frostVariantMixin('.box'), componentStyles]\n * ```\n */\nexport const surfaceMixins = [colorThemeMixin, elevationMixin, paddingMixin, roundedVariantMixin] as const;\n\n/**\n * Base mixins for custom form controls (checkbox, radio, switch).\n * Covers theming, forced-colors visibility, and disabled state.\n * Still add `coarsePointerMixin` (for touch targets) and `sizeVariantMixin({...})` separately.\n *\n * @example\n * ```ts\n * // checkbox / radio (with touch target):\n * styles: [...formControlMixins, coarsePointerMixin, sizeVariantMixin({...}), componentStyles]\n * // switch (no touch target override needed):\n * styles: [...formControlMixins, sizeVariantMixin({...}), componentStyles]\n * ```\n */\nexport const formControlMixins = [colorThemeMixin, forcedColorsFormControlMixin, disabledStateMixin()] as const;\n","@layer buildit.base {\n :host {\n --_bg: var(--avatar-bg, var(--_theme-backdrop, var(--color-contrast-200)));\n --_color: var(--avatar-color, var(--_theme-base, var(--color-contrast-700)));\n --_radius: var(--avatar-radius, var(--rounded-full));\n --_font-weight: var(--avatar-font-weight, var(--font-semibold));\n --_border: var(--avatar-border, none);\n --_border-color: var(--avatar-border-color, var(--color-canvas));\n --_size: var(--avatar-size, var(--size-10));\n --_font-size: var(--avatar-font-size, var(--text-sm));\n\n position: relative;\n display: inline-flex;\n flex-shrink: 0;\n }\n\n .avatar {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--_size);\n height: var(--_size);\n overflow: hidden;\n font-size: var(--_font-size);\n font-weight: var(--_font-weight);\n line-height: 1;\n color: var(--_color);\n text-transform: uppercase;\n user-select: none;\n background: var(--_bg);\n border: var(--_border);\n border-color: var(--_border-color);\n border-radius: var(--_radius);\n }\n\n img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n img[hidden] {\n display: none;\n }\n\n .initials {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n }\n\n .icon-fallback {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n color: var(--_color);\n opacity: 0.6;\n }\n\n .status {\n position: absolute;\n inset-inline-end: 0;\n bottom: 0;\n width: 0.75em;\n height: 0.75em;\n border: 2px solid var(--_border-color, var(--color-canvas));\n border-radius: var(--rounded-full);\n }\n\n .status[data-status='online'] {\n background: var(--color-success);\n }\n\n .status[data-status='offline'] {\n background: var(--color-contrast-400);\n }\n\n .status[data-status='busy'] {\n background: var(--color-error);\n }\n\n .status[data-status='away'] {\n background: var(--color-warning);\n }\n}\n\n/* forcedColorsMixin targets :host; avatar needs the border on .avatar (different geometry),\n so forced-color rules are kept inline and unlayered to match mixin convention. */\n@media (forced-colors: active) {\n .avatar {\n forced-color-adjust: none;\n border: 1px solid ButtonText;\n }\n\n .status {\n background: Highlight;\n border: 2px solid ButtonText;\n }\n}\n","@layer buildit.base {\n :host {\n display: inline-flex;\n flex-direction: row;\n }\n\n /* Overlap avatars, latest first */\n ::slotted(bit-avatar) {\n --avatar-border: var(--border-2) solid var(--color-canvas);\n\n margin-inline-start: calc(var(--avatar-group-overlap, -0.75rem));\n }\n\n ::slotted(bit-avatar:first-child) {\n margin-inline-start: 0;\n }\n\n ::slotted(bit-avatar[data-avatar-group-hidden]) {\n display: none;\n }\n\n .overflow-badge {\n --_size: var(--avatar-size, var(--size-10));\n\n box-sizing: border-box;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--_size);\n height: var(--_size);\n margin-inline-start: calc(var(--avatar-group-overlap, -0.75rem));\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-700);\n user-select: none;\n background: var(--color-contrast-200);\n border: var(--border-2) solid var(--color-canvas);\n border-radius: var(--rounded-full);\n }\n}\n","import { computed, defineComponent, html, onMount, onSlotChange, signal, watch } from '@vielzeug/craftit';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport { colorThemeMixin, roundedVariantMixin, sizeVariantMixin } from '../../styles';\n// ============================================\n// Styles\n// ============================================\nimport componentStyles from './avatar.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';\n\nconst STATUS_LABELS: Record<AvatarStatus, string> = {\n away: 'Away',\n busy: 'Busy',\n offline: 'Offline',\n online: 'Online',\n};\n\n/** Avatar component properties */\nexport type BitAvatarProps = {\n /** Alt text for the image; also used to derive initials when no `initials` prop is given */\n alt?: string;\n /** Theme color (used for initials background) */\n color?: ThemeColor;\n /** Explicit initials to display when no image is available (e.g. \"JD\") */\n initials?: string;\n /** Border radius */\n rounded?: RoundedSize | '';\n /** Component size */\n size?: ComponentSize;\n /** Image source URL */\n src?: string;\n /** Online presence indicator */\n status?: AvatarStatus;\n};\n\n// ============================================\n// Component\n// ============================================\n\n/**\n * Displays a user avatar: image → initials → generic fallback icon, in that priority order.\n *\n * @element bit-avatar\n *\n * @attr {string} src - Image source URL\n * @attr {string} alt - Image alt text (also used to derive initials)\n * @attr {string} initials - Explicit initials (up to 2 chars)\n * @attr {string} color - Theme color for initials background\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius\n * @attr {string} status - 'online' | 'offline' | 'busy' | 'away'\n *\n * @cssprop --avatar-size - Diameter of the avatar\n * @cssprop --avatar-bg - Background color\n * @cssprop --avatar-color - Text/icon color\n * @cssprop --avatar-radius - Border radius\n * @cssprop --avatar-border - Border shorthand\n * @cssprop --avatar-border-color - Border color (also controls status dot border)\n *\n * @example\n * ```html\n * <bit-avatar src=\"/jane.jpg\" alt=\"Jane Doe\"></bit-avatar>\n * <bit-avatar initials=\"JD\" color=\"primary\"></bit-avatar>\n * <bit-avatar alt=\"John Smith\" status=\"online\"></bit-avatar>\n * ```\n */\nexport const AVATAR_TAG = defineComponent<BitAvatarProps>({\n props: {\n alt: { default: undefined },\n color: { default: undefined },\n initials: { default: undefined },\n rounded: { default: undefined },\n size: { default: undefined },\n src: { default: undefined },\n status: { default: undefined },\n },\n setup({ props }) {\n const imgFailed = signal(false);\n\n // Reset stale error state whenever src changes\n watch(props.src, () => {\n imgFailed.value = false;\n });\n\n // Attach load/error listeners reactively when the img element mounts\n const attachImgListeners = (el: HTMLImageElement | null) => {\n if (!el) return;\n\n el.addEventListener('error', () => {\n imgFailed.value = true;\n });\n el.addEventListener('load', () => {\n imgFailed.value = false;\n });\n };\n const derivedInitials = computed(() => {\n if (props.initials.value) return props.initials.value.slice(0, 2);\n\n const alt = props.alt.value;\n\n if (!alt) return '';\n\n const parts = alt.trim().split(/\\s+/);\n\n if (parts.length >= 2) return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n\n return parts[0].slice(0, 2).toUpperCase();\n });\n const showImage = computed(() => !!props.src.value && !imgFailed.value);\n const showInitials = computed(() => !showImage.value && !!derivedInitials.value);\n const showFallback = computed(() => !showImage.value && !showInitials.value);\n // Combines name and status into a single accessible label so AT announces them together\n const avatarLabel = computed(() => {\n const name = (props.alt.value as string | undefined) || null;\n const statusKey = props.status.value as AvatarStatus | undefined;\n const status = statusKey ? STATUS_LABELS[statusKey] : null;\n\n if (!name && !status) return null;\n\n if (!name) return `Status: ${status}`;\n\n if (!status) return name;\n\n return `${name}, ${status}`;\n });\n\n return html`\n <span\n class=\"avatar\"\n part=\"avatar\"\n :aria-label=\"${() => avatarLabel.value}\"\n :role=\"${() => (avatarLabel.value ? 'img' : null)}\">\n ${() =>\n props.src.value\n ? html`<img\n ref=${attachImgListeners}\n part=\"img\"\n :src=\"${() => props.src.value}\"\n :alt=\"${() => props.alt.value || ''}\"\n ?hidden=\"${() => !showImage.value}\"\n aria-hidden=\"true\" />`\n : ''}\n ${() =>\n showInitials.value\n ? html`<span class=\"initials\" part=\"initials\" aria-hidden=\"true\">${() => derivedInitials.value}</span>`\n : ''}\n ${() =>\n showFallback.value\n ? html`<span class=\"icon-fallback\" part=\"fallback\" aria-hidden=\"true\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n width=\"55%\"\n height=\"55%\">\n <path d=\"M12 12a5 5 0 1 0 0-10 5 5 0 0 0 0 10Zm0 2c-5.33 0-8 2.67-8 4v1h16v-1c0-1.33-2.67-4-8-4Z\" />\n </svg>\n </span>`\n : ''}\n </span>\n ${() =>\n props.status.value\n ? html`<span\n class=\"status\"\n part=\"status\"\n :data-status=\"${() => props.status.value}\"\n aria-hidden=\"true\"></span>`\n : ''}\n `;\n },\n styles: [\n colorThemeMixin,\n roundedVariantMixin,\n sizeVariantMixin({\n lg: { fontSize: 'var(--avatar-font-size, var(--text-base))', size: 'var(--avatar-size, var(--size-14))' },\n md: { fontSize: 'var(--avatar-font-size, var(--text-sm))', size: 'var(--avatar-size, var(--size-10))' },\n sm: { fontSize: 'var(--avatar-font-size, var(--text-xs))', size: 'var(--avatar-size, var(--size-7))' },\n }),\n componentStyles,\n ],\n tag: 'bit-avatar',\n});\n\n// ============================================\n// AvatarGroup\n// ============================================\n\nimport groupStyles from './avatar-group.css?inline';\n\n/** AvatarGroup component properties */\nexport type BitAvatarGroupProps = {\n /** Maximum number of avatars to show before showing a +N badge */\n max?: number;\n /** Total count shown in the overflow badge (defaults to the actual hidden count) */\n total?: number;\n};\n\n/**\n * Groups multiple `bit-avatar` elements in a stacked, overlapping row.\n *\n * @element bit-avatar-group\n *\n * @attr {number} max - Max visible avatars before overflow badge (default: 5)\n * @attr {number} total - Override the total count displayed in the badge\n *\n * @slot - `bit-avatar` elements\n *\n * @cssprop --avatar-group-overlap - Negative margin creating the overlap (default: -0.75rem)\n *\n * @example\n * ```html\n * <bit-avatar-group max=\"3\">\n * <bit-avatar src=\"/a.jpg\" alt=\"Alice\"></bit-avatar>\n * <bit-avatar src=\"/b.jpg\" alt=\"Bob\"></bit-avatar>\n * <bit-avatar src=\"/c.jpg\" alt=\"Carol\"></bit-avatar>\n * <bit-avatar src=\"/d.jpg\" alt=\"Dave\"></bit-avatar>\n * </bit-avatar-group>\n * ```\n */\nexport const AVATAR_GROUP_TAG = defineComponent<BitAvatarGroupProps>({\n props: {\n max: { default: 5 },\n total: { default: undefined },\n },\n setup({ host, props }) {\n const overflowCount = signal(0);\n\n onMount(() => {\n const updateVisibility = () => {\n const avatars = [...host.querySelectorAll('bit-avatar')];\n const max = Number(props.max.value) || 5;\n const hidden = Math.max(0, avatars.length - max);\n\n overflowCount.value = props.total.value != null ? Number(props.total.value) - max : hidden;\n avatars.forEach((a, i) => {\n if (i >= max) a.setAttribute('data-avatar-group-hidden', '');\n else a.removeAttribute('data-avatar-group-hidden');\n });\n };\n\n onSlotChange('default', updateVisibility);\n });\n\n return html`\n <slot></slot>\n ${() =>\n overflowCount.value > 0\n ? html`<span class=\"overflow-badge\" part=\"overflow\" aria-label=\"${() => `+${overflowCount.value} more`}\">\n +${() => overflowCount.value}\n </span>`\n : ''}\n `;\n },\n styles: [groupStyles],\n tag: 'bit-avatar-group',\n});\n","@layer buildit.base {\n :host {\n display: inline-flex;\n align-items: center;\n }\n\n .item {\n display: inline-flex;\n align-items: center;\n }\n\n .separator {\n display: none;\n padding-inline: var(--size-2);\n font-size: var(--text-sm);\n font-weight: var(--font-normal);\n color: var(--color-contrast-400);\n }\n\n :host([data-show-separator]) .separator {\n display: inline-block;\n }\n\n .link {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-contrast-600);\n text-decoration: none;\n outline-offset: 2px;\n border-radius: var(--rounded-sm);\n transition: color var(--transition-fast);\n }\n\n .link:hover {\n color: var(--color-contrast-900);\n text-decoration: underline;\n }\n\n .link:focus-visible {\n outline: var(--border-2) solid currentcolor;\n outline-offset: var(--border-2);\n }\n\n :host([active]) .link {\n font-weight: var(--font-semibold);\n color: var(--color-contrast-900);\n text-decoration: none;\n pointer-events: none;\n }\n\n /* Icon slot */\n .icon {\n display: contents;\n }\n\n .label {\n min-width: 0;\n max-width: var(--breadcrumb-item-max-width, 20ch);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n","@layer buildit.base {\n :host {\n display: block;\n }\n\n nav {\n display: block;\n }\n\n ol {\n display: flex;\n flex-wrap: wrap;\n gap: 0;\n align-items: center;\n padding: 0;\n margin: 0;\n list-style: none;\n }\n}\n","import { defineComponent, effect, html, onMount, onSlotChange } from '@vielzeug/craftit';\n\n// ============================================\n// Types\n// ============================================\n\nexport type BitBreadcrumbProps = {\n label?: string;\n separator?: string;\n};\n\nexport type BitBreadcrumbItemProps = {\n active?: boolean;\n href?: string;\n separator?: string;\n};\n\n// ============================================\n// Breadcrumb Item Component\n// ============================================\n\nimport itemStyles from './breadcrumb-item.css?inline';\n\n/**\n * `bit-breadcrumb-item` — A single crumb within a `<bit-breadcrumb>` list.\n *\n * @example\n * ```html\n * <bit-breadcrumb-item href=\"/\">Home</bit-breadcrumb-item>\n * <bit-breadcrumb-item active>Current Page</bit-breadcrumb-item>\n * ```\n */\nexport const BREADCRUMB_ITEM_TAG = defineComponent<BitBreadcrumbItemProps>({\n props: {\n active: { default: false },\n href: { default: '' },\n separator: { default: '/' },\n },\n setup({ props }) {\n return html`\n <li class=\"item\" role=\"listitem\">\n <span class=\"separator\" part=\"separator\" aria-hidden=\"true\">${() => props.separator.value || '/'}</span>\n <a\n class=\"link\"\n href=\"${() => props.href.value || undefined}\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\"\n tabindex=\"${() => (props.active.value ? '-1' : null)}\"\n part=\"link\">\n <span class=\"icon\"><slot name=\"icon\"></slot></span>\n <span class=\"label\"><slot></slot></span>\n </a>\n </li>\n `;\n },\n styles: [itemStyles],\n tag: 'bit-breadcrumb-item',\n});\n\n// ============================================\n// Breadcrumb Component\n// ============================================\n\nimport componentStyles from './breadcrumb.css?inline';\n\n/**\n * `bit-breadcrumb` — Accessible navigation breadcrumb.\n *\n * Wrap `<bit-breadcrumb-item>` elements as children.\n * The last/current item should have `active` attribute.\n *\n * @example\n * ```html\n * <bit-breadcrumb label=\"Page breadcrumb\">\n * <bit-breadcrumb-item href=\"/\">Home</bit-breadcrumb-item>\n * <bit-breadcrumb-item href=\"/blog\">Blog</bit-breadcrumb-item>\n * <bit-breadcrumb-item active>My Post</bit-breadcrumb-item>\n * </bit-breadcrumb>\n * ```\n */\nexport const BREADCRUMB_TAG = defineComponent<BitBreadcrumbProps>({\n props: {\n label: { default: 'Breadcrumb' },\n separator: { default: '' },\n },\n setup({ host, props }) {\n const getItems = (): HTMLElement[] => Array.from(host.getElementsByTagName('bit-breadcrumb-item')) as HTMLElement[];\n const syncSeparatorVar = () => {\n const sep = props.separator.value;\n\n if (sep) {\n host.style.setProperty('--breadcrumb-separator', `'${sep}'`);\n } else {\n host.style.removeProperty('--breadcrumb-separator');\n }\n };\n const syncItems = () => {\n const sep = props.separator.value || '/';\n const items = getItems();\n\n for (let i = 0; i < items.length; i += 1) {\n items[i].setAttribute('separator', sep);\n\n if (i === 0) {\n items[i].removeAttribute('data-show-separator');\n } else {\n items[i].setAttribute('data-show-separator', '');\n }\n }\n };\n\n onMount(() => {\n onSlotChange('default', syncItems);\n // Ensure initial slotted items are normalized once on mount.\n syncItems();\n });\n effect(syncSeparatorVar);\n effect(syncItems);\n\n return html`\n <nav aria-label=\"${() => props.label.value}\" part=\"nav\">\n <ol role=\"list\" part=\"list\">\n <slot></slot>\n </ol>\n </nav>\n `;\n },\n styles: [componentStyles],\n tag: 'bit-breadcrumb',\n});\n","@layer buildit.base {\n :host {\n --_bg: var(--card-bg, var(--color-canvas));\n --_color: var(--card-color, var(--color-contrast-900));\n --_border: var(--card-border, var(--border));\n --_border-color: var(--card-border-color, var(--color-contrast-300));\n --_radius: var(--card-radius, var(--rounded-lg));\n --_padding: var(--card-padding, var(--size-4));\n --_shadow: var(--card-shadow, var(--shadow-sm));\n --_hover-shadow: var(--card-hover-shadow, var(--shadow-md));\n\n position: relative;\n display: block;\n }\n\n .card {\n position: relative;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n color: var(--_color);\n background: var(--_bg);\n border-radius: var(--_radius);\n transition: var(\n --_motion-transition,\n backdrop-filter var(--transition-slow),\n box-shadow var(--transition-normal),\n transform var(--transition-normal),\n background var(--transition-normal),\n border-color var(--transition-normal),\n opacity var(--transition-normal)\n );\n }\n\n /* ── Card Structure ───────────────────────── */\n\n .card-media {\n flex-shrink: 0;\n overflow: hidden;\n }\n\n .card-media img {\n display: block;\n width: 100%;\n height: auto;\n object-fit: cover;\n }\n\n .card-body {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n\n .card-header,\n .card-content,\n .card-footer {\n padding: var(--_padding);\n }\n\n .card-header {\n padding-bottom: calc(var(--_padding) / 2);\n }\n\n .card-footer {\n padding-top: calc(var(--_padding) / 2);\n }\n\n .card-content {\n flex: 1;\n }\n\n .card-actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--size-2);\n align-items: center;\n padding: var(--_padding);\n padding-top: calc(var(--_padding) / 2);\n }\n\n [hidden] {\n display: none;\n }\n}\n\n@layer buildit.variants {\n /* Default (no variant) */\n :host(:not([variant], [color])) .card {\n border: var(--_border) solid var(--_border-color);\n box-shadow: var(--_shadow);\n }\n\n :host(:not([variant])[color]) .card {\n background: var(--_theme-backdrop);\n border: var(--_border) solid var(--_theme-border);\n }\n\n :host(:not([variant])[color]:hover) .card {\n background: color-mix(in srgb, var(--_theme-base) 16%, var(--color-contrast-50));\n border-color: var(--_theme-focus);\n }\n\n /* Solid */\n :host([variant='solid']) .card {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n border: var(--_border) solid var(--_theme-base);\n box-shadow: var(--_shadow);\n }\n\n /* Flat */\n :host([variant='flat']) .card {\n background: var(--_theme-backdrop);\n border: var(--_border) solid color-mix(in srgb, var(--_theme-border) 50%, transparent);\n }\n\n /* Glass */\n :host([variant='glass']) .card {\n text-shadow: var(--text-shadow-xs);\n border: var(--_border) solid var(--_border-color);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']:hover) .card {\n box-shadow: var(--shadow-xl), var(--inset-shadow-sm);\n backdrop-filter: blur(var(--blur-xl)) saturate(200%) brightness(1.1);\n }\n\n :host([variant='glass'][interactive]:hover) .card {\n box-shadow: var(--shadow-2xl), var(--inset-shadow-sm);\n }\n}\n\n@layer buildit.overrides {\n /* ── Loading bar ──────────────────────────── */\n\n /* Bar lives inside .card which already has overflow:hidden,\n so translateX can sweep freely without any overflow. */\n .loading-bar {\n position: absolute;\n inset-inline-start: 0;\n top: 0;\n display: none;\n width: 65%;\n height: 3px;\n background: linear-gradient(90deg, transparent 0%, var(--_theme-base, var(--color-primary)) 50%, transparent 100%);\n }\n\n :host([loading]) .loading-bar {\n display: block;\n animation: var(--_motion-animation, loading-bar 1.4s ease-in-out infinite);\n }\n\n /* In RTL the loading bar sweeps right-to-left */\n :host(:dir(rtl)[loading]) .loading-bar {\n animation-direction: reverse;\n }\n\n /* ── Disabled ─────────────────────────────── */\n\n :host([disabled]) {\n pointer-events: none;\n opacity: 0.6;\n }\n\n :host([disabled][interactive]) .card {\n cursor: not-allowed;\n }\n\n /* ── Interactive hover/active ─────────────── */\n\n :host([interactive]:not([disabled]):hover) .card {\n box-shadow: var(--_hover-shadow);\n transform: translateY(calc(-1 * var(--size-1))) scale(1.01);\n will-change: box-shadow, transform;\n }\n\n :host([interactive]) .card {\n cursor: pointer;\n }\n\n :host([interactive]:not([disabled]):active) .card {\n box-shadow: var(--_shadow);\n transform: translateY(0) scale(0.99);\n transition: var(--_motion-transition, box-shadow var(--transition-fast), transform var(--transition-fast));\n }\n\n :host([interactive]:focus-visible) .card {\n outline: var(--border-2) solid var(--_theme-focus, var(--color-primary));\n outline-offset: var(--border-2);\n }\n\n /* ── Horizontal orientation ───────────────── */\n\n :host([orientation='horizontal']) .card {\n flex-direction: row;\n }\n\n :host([orientation='horizontal']) .card-media {\n width: 30%;\n min-width: 192px;\n max-width: 320px;\n }\n\n :host([orientation='horizontal']) .card-media img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n :host([orientation='horizontal']) .card-body {\n flex: 1;\n }\n}\n\n@keyframes loading-bar {\n 0% {\n transform: translateX(-100%);\n }\n\n 100% {\n transform: translateX(200%);\n }\n}\n","import { defineComponent, handle, html, onMount, onSlotChange, ref, signal, watch } from '@vielzeug/craftit';\n\nimport type { ElevationLevel, PaddingSize, ThemeColor } from '../../types';\n\nimport { frostVariantMixin, reducedMotionMixin, surfaceMixins } from '../../styles';\n\nconst INTERACTIVE_DESCENDANT_SELECTOR =\n 'button, a[href], input, select, textarea, summary, [role=\"button\"], [role=\"link\"], [contenteditable=\"\"], [contenteditable=\"true\"]';\n\nfunction slotHasMeaningfulContent(slot: HTMLSlotElement | null | undefined): boolean {\n if (!slot) return false;\n\n return slot.assignedNodes({ flatten: true }).some((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) return true;\n\n if (node.nodeType === Node.TEXT_NODE) return !!node.textContent?.trim();\n\n return false;\n });\n}\n\nfunction isNestedInteractiveTarget(host: HTMLElement, event: Event): boolean {\n for (const node of event.composedPath()) {\n if (!(node instanceof HTMLElement)) continue;\n\n if (node === host) return false;\n\n if (node.matches(INTERACTIVE_DESCENDANT_SELECTOR) || !!node.closest(INTERACTIVE_DESCENDANT_SELECTOR)) {\n return true;\n }\n }\n\n return false;\n}\n\nimport componentStyles from './card.css?inline';\n\n/** Card component properties */\n\nexport type BitCardEvents = {\n activate: { originalEvent: MouseEvent | KeyboardEvent; trigger: 'pointer' | 'keyboard' };\n};\n\nexport type BitCardProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Shadow elevation level (0-5) */\n elevation?: `${ElevationLevel}`;\n /** Make the card interactive (role=button, keyboard nav, emits activate) */\n interactive?: boolean;\n /** Show a loading progress bar */\n loading?: boolean;\n /** Card orientation */\n orientation?: 'horizontal';\n /** Internal padding size */\n padding?: PaddingSize;\n /** Visual style variant */\n variant?: 'solid' | 'flat' | 'glass' | 'frost';\n};\n\n/**\n * A versatile card container with semantic slots for media, header, body, footer, and actions.\n *\n * @element bit-card\n *\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'glass' | 'frost'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} padding - Internal padding: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n * @attr {string} orientation - Card layout: 'horizontal'\n * @attr {boolean} interactive - Enable pointer/keyboard activation\n * @attr {boolean} disabled - Disable card interaction\n * @attr {boolean} loading - Show loading progress bar\n *\n * @fires activate - Emitted when an interactive card is activated\n *\n * @slot media - Media content displayed at top/left\n * @slot header - Card header (title, subtitle)\n * @slot - Main card content\n * @slot footer - Card footer content\n * @slot actions - Action buttons or links\n *\n * @cssprop --card-bg - Background color\n * @cssprop --card-color - Text color\n * @cssprop --card-border - Border width\n * @cssprop --card-border-color - Border color\n * @cssprop --card-radius - Border radius\n * @cssprop --card-padding - Internal padding\n * @cssprop --card-shadow - Box shadow\n * @cssprop --card-hover-shadow - Shadow on hover\n *\n * @example\n * ```html\n * <bit-card elevation=\"2\"><h3 slot=\"header\">Title</h3><p>Content</p></bit-card>\n * <bit-card interactive color=\"primary\"><h3 slot=\"header\">Click me</h3></bit-card>\n * <bit-card variant=\"frost\" color=\"secondary\">Frosted card</bit-card>\n * ```\n */\nexport const CARD_TAG = defineComponent<BitCardProps, BitCardEvents>({\n props: {\n color: { default: undefined },\n disabled: { default: false, type: Boolean },\n elevation: { default: undefined },\n interactive: { default: false, type: Boolean },\n loading: { default: false, type: Boolean },\n orientation: { default: undefined },\n padding: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const mediaSlot = ref<HTMLSlotElement>();\n const headerSlot = ref<HTMLSlotElement>();\n const contentSlot = ref<HTMLSlotElement>();\n const footerSlot = ref<HTMLSlotElement>();\n const actionsSlot = ref<HTMLSlotElement>();\n const hasMedia = signal(false);\n const hasHeader = signal(false);\n const hasContent = signal(false);\n const hasFooter = signal(false);\n const hasActions = signal(false);\n\n function updateSlotState() {\n hasMedia.value = slotHasMeaningfulContent(mediaSlot.value);\n hasHeader.value = slotHasMeaningfulContent(headerSlot.value);\n hasContent.value = slotHasMeaningfulContent(contentSlot.value);\n hasFooter.value = slotHasMeaningfulContent(footerSlot.value);\n hasActions.value = slotHasMeaningfulContent(actionsSlot.value);\n }\n onMount(() => {\n onSlotChange('media', updateSlotState);\n onSlotChange('header', updateSlotState);\n onSlotChange('default', updateSlotState);\n onSlotChange('footer', updateSlotState);\n onSlotChange('actions', updateSlotState);\n });\n watch(\n [props.interactive, props.disabled, props.loading, props.variant, props.color, props.padding, props.orientation],\n () => {\n if (props.interactive.value) {\n host.setAttribute('role', 'button');\n host.setAttribute('tabindex', props.disabled.value ? '-1' : '0');\n host.setAttribute('aria-disabled', String(props.disabled.value));\n } else {\n host.removeAttribute('role');\n host.removeAttribute('tabindex');\n host.removeAttribute('aria-disabled');\n }\n\n host.setAttribute('aria-busy', props.loading.value ? 'true' : 'false');\n },\n { immediate: true },\n );\n\n const handleClick = (e: MouseEvent) => {\n if (!props.interactive.value || props.disabled.value) return;\n\n if (isNestedInteractiveTarget(host, e)) return;\n\n emit('activate', { originalEvent: e, trigger: 'pointer' });\n };\n const handleKeydown = (e: KeyboardEvent) => {\n if (!props.interactive.value || props.disabled.value) return;\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n emit('activate', { originalEvent: e, trigger: 'keyboard' });\n }\n };\n\n handle(host, 'click', handleClick);\n handle(host, 'keydown', handleKeydown);\n\n return html`\n <div class=\"card\" part=\"card\">\n <div class=\"loading-bar\" part=\"loading-bar\"></div>\n <div class=\"card-media\" part=\"media\" ?hidden=\"${() => !hasMedia.value}\">\n <slot ref=${mediaSlot} name=\"media\"></slot>\n </div>\n <div class=\"card-body\" part=\"body\">\n <div class=\"card-header\" part=\"header\" ?hidden=\"${() => !hasHeader.value}\">\n <slot ref=${headerSlot} name=\"header\"></slot>\n </div>\n <div class=\"card-content\" part=\"content\" ?hidden=\"${() => !hasContent.value}\">\n <slot ref=${contentSlot}></slot>\n </div>\n <div class=\"card-footer\" part=\"footer\" ?hidden=\"${() => !hasFooter.value}\">\n <slot ref=${footerSlot} name=\"footer\"></slot>\n </div>\n <div class=\"card-actions\" part=\"actions\" ?hidden=\"${() => !hasActions.value}\">\n <slot ref=${actionsSlot} name=\"actions\"></slot>\n </div>\n </div>\n </div>\n `;\n },\n styles: [...surfaceMixins, frostVariantMixin('.card'), reducedMotionMixin, componentStyles],\n tag: 'bit-card',\n});\n","//#region src/runtime.ts\nvar e = Symbol(\"stateit.uninitialized\"), t = {\n\tcleanups: null,\n\tdeps: null,\n\teffect: null\n}, n = {\n\tdepth: 0,\n\tpending: /* @__PURE__ */ new Set()\n}, r = 100, i = (e) => {\n\te.maxEffectIterations !== void 0 && (r = e.maxEffectIterations);\n}, a = () => {\n\tn.depth = 0, t.deps = null, t.effect = null, t.cleanups = null, n.pending.clear();\n}, o = class {\n\t#e = /* @__PURE__ */ new Set();\n\t_track() {\n\t\tif (t.deps !== null && t.effect !== null) {\n\t\t\tlet e = t.effect;\n\t\t\tthis.#e.add(e), t.deps.add(() => this.#e.delete(e));\n\t\t}\n\t}\n\t_notify() {\n\t\tif (this.#e.size === 0) return;\n\t\tif (n.depth > 0) {\n\t\t\tfor (let e of this.#e) n.pending.add(e);\n\t\t\treturn;\n\t\t}\n\t\tlet e = [];\n\t\tfor (let t of [...this.#e]) try {\n\t\t\tt();\n\t\t} catch (t) {\n\t\t\te.push(t);\n\t\t}\n\t\tif (e.length) throw e.length === 1 ? e[0] : AggregateError(e, \"[stateit] multiple subscriber errors\");\n\t}\n}, s = (e, n, r, i) => {\n\tlet a = t.effect, o = t.deps, s = t.cleanups;\n\tt.effect = e, t.deps = n, t.cleanups = r;\n\ttry {\n\t\treturn i();\n\t} finally {\n\t\tt.effect = a, t.deps = o, t.cleanups = s;\n\t}\n};\n//#endregion\nexport { o as ReactiveNode, e as _UNINITIALIZED, r as _maxEffectIterations, a as _resetContextForTesting, s as _withCtx, i as configureStateit, n as queue, t as scope };\n\n//# sourceMappingURL=runtime.js.map","//#region src/types.ts\nvar e = Symbol(\"stateit.signal\"), t = Symbol(\"stateit.store\");\n//#endregion\nexport { e as _SIGNAL_BRAND, t as _STORE_BRAND };\n\n//# sourceMappingURL=types.js.map","import { ReactiveNode as e, _UNINITIALIZED as t, _withCtx as n } from \"./runtime.js\";\nimport { _SIGNAL_BRAND as r } from \"./types.js\";\n//#region src/computed.ts\nvar i = class extends e {\n\t[r] = !0;\n\t#e;\n\t#t = t;\n\t#n = !0;\n\t#r = !1;\n\t#i;\n\t#a = /* @__PURE__ */ new Set();\n\t#o = () => {\n\t\tthis.#n || (this.#n = !0, this._notify());\n\t};\n\tconstructor(e, t) {\n\t\tsuper(), this.#e = e, this.#i = t?.equals ?? Object.is, t?.lazy || this.#s();\n\t}\n\t#s() {\n\t\tfor (let e of this.#a) e();\n\t\tthis.#a.clear();\n\t\tlet e = n(this.#o, this.#a, null, this.#e);\n\t\tthis.#n = !1, (this.#t === t || !this.#i(this.#t, e)) && (this.#t = e);\n\t}\n\tget value() {\n\t\treturn this.#r ? this.#t : (this.#n && this.#s(), this._track(), this.#t);\n\t}\n\tpeek() {\n\t\tif (this.#t === t) {\n\t\t\tif (this.#r) return;\n\t\t\tthis.#s();\n\t\t}\n\t\treturn this.#t;\n\t}\n\tget stale() {\n\t\treturn this.#n || this.#r;\n\t}\n\tdispose() {\n\t\tif (!this.#r) {\n\t\t\tthis.#r = !0;\n\t\t\tfor (let e of this.#a) e();\n\t\t\tthis.#a.clear();\n\t\t}\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.dispose();\n\t}\n}, a = (e, t) => new i(e, t), o = class extends i {\n\t#e;\n\tconstructor(e, t, n) {\n\t\tsuper(e, n), this.#e = t;\n\t}\n\tget value() {\n\t\treturn super.value;\n\t}\n\tset value(e) {\n\t\tthis.#e(e);\n\t}\n\tupdate(e) {\n\t\tthis.#e(e(this.peek()));\n\t}\n}, s = (e, t, n) => new o(e, t, n), c = (e, t, n) => a(() => t(...e.map((e) => e.value)), n);\n//#endregion\nexport { i as ComputedNode, o as WritableNode, a as computed, c as derived, s as writable };\n\n//# sourceMappingURL=computed.js.map","import { _maxEffectIterations as e, _withCtx as t, scope as n } from \"./runtime.js\";\n//#region src/effect.ts\nvar r = (n, r) => {\n\tlet i, a = /* @__PURE__ */ new Set(), o = !1, s = !1, c = !1, l = r?.maxIterations ?? e, u = () => {\n\t\ti?.(), i = void 0;\n\t\tfor (let e of a) e();\n\t\ta.clear();\n\t}, d = () => {\n\t\ts = !1, u();\n\t\tlet e = [], o, l = !1;\n\t\ttry {\n\t\t\tt(f, a, e, () => {\n\t\t\t\tlet t = n();\n\t\t\t\ttypeof t == \"function\" && e.push(t);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tif (r?.onError) l = !0, o = e;\n\t\t\telse throw e;\n\t\t}\n\t\treturn i = e.length > 0 ? () => {\n\t\t\tfor (let t of e) t();\n\t\t} : void 0, l && (u(), r.onError(o), c = !0), l;\n\t}, f = () => {\n\t\tif (c || o) {\n\t\t\to && (s = !0);\n\t\t\treturn;\n\t\t}\n\t\to = !0;\n\t\ttry {\n\t\t\tlet e = 0;\n\t\t\tdo {\n\t\t\t\tif (++e > l) throw Error(`[stateit] effect: possible infinite reactive loop (> ${l} iterations)`);\n\t\t\t\tif (d()) break;\n\t\t\t} while (s);\n\t\t} finally {\n\t\t\to = !1;\n\t\t}\n\t};\n\tf();\n\tlet p = () => {\n\t\tc || (c = !0, u());\n\t};\n\treturn Object.assign(p, {\n\t\tdispose: p,\n\t\t[Symbol.dispose]: p\n\t});\n}, i = (e) => t(null, null, null, e), a = (e) => {\n\tn.cleanups?.push(e);\n};\n//#endregion\nexport { r as effect, a as onCleanup, i as untrack };\n\n//# sourceMappingURL=effect.js.map","import { ReactiveNode as e } from \"./runtime.js\";\nimport { _SIGNAL_BRAND as t } from \"./types.js\";\n//#region src/signal.ts\nvar n = class extends e {\n\t[t] = !0;\n\t#e;\n\t#t;\n\tconstructor(e, t) {\n\t\tsuper(), this.#e = e, this.#t = t?.equals ?? Object.is;\n\t}\n\tget value() {\n\t\treturn this._track(), this.#e;\n\t}\n\tset value(e) {\n\t\tthis.#t(this.#e, e) || (this.#e = e, this._notify());\n\t}\n\tupdate(e) {\n\t\tthis.value = e(this.#e);\n\t}\n\tpeek() {\n\t\treturn this.#e;\n\t}\n}, r = (e, t) => new n(e, t), i = /* @__PURE__ */ new WeakMap(), a = (e) => {\n\tlet n = i.get(e);\n\tif (n) return n;\n\tlet r = {\n\t\tget [t]() {\n\t\t\treturn !0;\n\t\t},\n\t\tpeek: () => e.peek(),\n\t\tget value() {\n\t\t\treturn e.value;\n\t\t}\n\t};\n\treturn i.set(e, r), r;\n}, o = (e) => typeof e == \"object\" && !!e && t in e, s = (e) => o(e) ? e.value : e, c = (e) => o(e) ? e.peek() : e;\n//#endregion\nexport { n as SignalImpl, o as isSignal, c as peekValue, a as readonly, r as signal, s as toValue };\n\n//# sourceMappingURL=signal.js.map","import { _STORE_BRAND as e } from \"./types.js\";\nimport { computed as t } from \"./computed.js\";\nimport { SignalImpl as n } from \"./signal.js\";\n//#region src/store.ts\nvar r = (e, t) => {\n\tif (e === t) return !0;\n\tif (e == null || t == null) return e === t;\n\tif (typeof e != \"object\" || typeof t != \"object\") return !1;\n\tlet n = Object.keys(e), r = Object.keys(t);\n\tif (n.length !== r.length) return !1;\n\tfor (let r of n) if (!Object.is(e[r], t[r])) return !1;\n\treturn !0;\n}, i = class extends n {\n\t[e] = !0;\n\t#e;\n\t#t = !1;\n\tconstructor(e, t) {\n\t\tsuper(e, { equals: t?.equals ?? r }), this.#e = { ...e };\n\t}\n\tget frozen() {\n\t\treturn this.#t;\n\t}\n\tget value() {\n\t\treturn super.value;\n\t}\n\tset value(e) {\n\t\tthis.#t || (super.value = e);\n\t}\n\tpatch(e) {\n\t\tthis.value = {\n\t\t\t...this.peek(),\n\t\t\t...e\n\t\t};\n\t}\n\tupdate(e) {\n\t\tthis.value = e({ ...this.peek() });\n\t}\n\treset() {\n\t\tthis.value = { ...this.#e };\n\t}\n\tselect(e, n) {\n\t\treturn t(() => e(this.value), n);\n\t}\n\tfreeze() {\n\t\tthis.#t = !0;\n\t}\n}, a = (e, t) => new i(e, t), o = (t) => typeof t == \"object\" && !!t && e in t;\n//#endregion\nexport { o as isStore, r as shallowEqual, a as store };\n\n//# sourceMappingURL=store.js.map","import\"@vielzeug/stateit\";function e(){return{value:null}}function t(){return[]}function n(e,t=[]){return{__bindings:t,__html:e,toString(){return e}}}function r(e){return typeof e==`string`?{bindings:[],html:e}:{bindings:e.__bindings,html:e.__html}}var i=Symbol(`craftit.eachSignal`);export{i as EACH_SIGNAL,r as extractResult,n as htmlResult,e as ref,t as refs};\n//# sourceMappingURL=internal.js.map","import\"./utilities.js\";import{effect as e,onCleanup as t,untrack as n,watch as r}from\"@vielzeug/stateit\";var i=[],a=()=>{let e=i[i.length-1];if(!e)throw Error(`[craftit:E1] lifecycle outside setup`);return e},o=e=>{a().onMount.push(e)},s=e=>{i.length>0?a().cleanups.push(e):t(e)},c=e=>{a().errorHandlers.push(e)},l=e=>{i.length>0&&s(e)},u=(t,n)=>{let r=e(t,n);return l(r),r};function d(t,i,a){if(Array.isArray(t)){let r=a,o=!1,s=!1,c=e(()=>{for(let e of t)e.value;if(o)n(i),r?.once&&c();else if(o=!0,r?.immediate&&(n(i),r.once)){s=!0;return}});return l(c),s&&c(),c}let o=r(t,i,a);return l(o),o}function f(e,t,n,r){e&&(e.addEventListener(t,n,r),s(()=>e.removeEventListener(t,n,r)))}var p={bubbles:!0,cancelable:!0,composed:!0},m={basic(e,t,n={}){return e.dispatchEvent(new Event(t,{...p,...n}))},custom(e,t,n={}){return e.dispatchEvent(new CustomEvent(t,{...p,...n}))},event(e,t){return e.dispatchEvent(t)},focus(e,t,n={}){return e.dispatchEvent(new FocusEvent(t,{...p,...n}))},keyboard(e,t,n={}){return e.dispatchEvent(new KeyboardEvent(t,{...p,...n}))},mouse(e,t,n={}){return e.dispatchEvent(new MouseEvent(t,{...p,...n}))},touch(e,t,n={}){return typeof TouchEvent<`u`?e.dispatchEvent(new TouchEvent(t,{...p,...n})):e.dispatchEvent(new CustomEvent(t,{...p,...n}))}};function h(e,t){let n=t===void 0?a().el:e,r=t===void 0?e:t,i=(e,t)=>{let r=`aria-${e}`,i=typeof t==`function`?t():t;i==null||i===!1?n.removeAttribute(r):n.setAttribute(r,String(i))},o=Object.entries(r).map(([e,t])=>u(()=>i(e,t)));if(t!==void 0)return()=>{for(let e of o)e()}}export{h as aria,l as autoCleanup,a as currentRuntime,u as effect,m as fire,f as handle,s as onCleanup,c as onError,o as onMount,i as runtimeStack,d as watch};\n//# sourceMappingURL=runtime-lifecycle.js.map","import{currentRuntime as e,fire as t}from\"./runtime-lifecycle.js\";var n=0,r=()=>{n=0},i=e=>{for(let t of e)t()},a=(e,t,n)=>{n==null||n===!1?e.removeAttribute(t):n===!0?e.setAttribute(t,``):e.setAttribute(t,String(n))},o=(e,t,n,r)=>{let i=n;return e.addEventListener(t,i,r),()=>e.removeEventListener(t,i,r)},s=e=>`${e?`${e}-`:`cft-`}${++n}`,c=(e,t)=>{let n=`${e}-${t&&t.trim()?t:s(e)}`;return{errorId:`error-${n}`,fieldId:n,helperId:`helper-${n}`,labelId:`label-${n}`}},l=(e,t)=>n=>{e()&&t(n)},u=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),d={\"'\":`&#39;`,'\"':`&quot;`,\"&\":`&amp;`,\"<\":`&lt;`,\">\":`&gt;`},f=e=>String(e).replace(/[&<>\"']/g,e=>d[e]),p=()=>{let n=e().el;return((e,...r)=>{t.custom(n,String(e),r.length>0?{detail:r[0]}:void 0)})},m=function(){return this.content},h=(e,...t)=>{let n=``;for(let r=0;r<e.length;r++)if(n+=e[r],r<t.length){let e=t[r];n+=e&&typeof e==`object`&&`content`in e?e.content:e??``}return{content:n.trim(),toString:m}},g=new Map,_=e=>{if(e instanceof CSSStyleSheet)return e;let t=typeof e==`string`?e:e.content,n=g.get(t);if(n)return n;let r=new CSSStyleSheet;try{r.replaceSync(t),g.set(t,r)}catch(e){console.error(`[craftit:E2] style replace failed`,e)}return r};export{r as _resetIdCounter,p as createEmitFn,c as createFormIds,s as createId,h as css,f as escapeHtml,l as guard,o as listen,_ as loadStylesheet,i as runAll,a as setAttr,u as toKebab};\n//# sourceMappingURL=utilities.js.map","import{listen as e}from\"./utilities.js\";import{computed as t,isSignal as n}from\"@vielzeug/stateit\";var r=e=>{if(n(e))return e;if(typeof e==`function`)return t(e)},i=e=>{if(!n(e))return!1;let t=Object.getPrototypeOf(e);for(;t;){let e=Object.getOwnPropertyDescriptor(t,`value`);if(e)return typeof e.set==`function`;t=Object.getPrototypeOf(t)}return!1},a=(e,t)=>{if(!Object.is(e.value,t))try{e.value=t}catch{}},o=(t,n,r,i)=>{if(r){if(n===`value`){(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&i(e(t,t instanceof HTMLSelectElement?`change`:`input`,()=>{a(r,t.value)}));return}n===`checked`&&t instanceof HTMLInputElement&&i(e(t,`change`,()=>{a(r,t.checked)}))}};export{o as bindPropertyModel,i as hasWritableValueSetter,r as toReactiveBindingSource};\n//# sourceMappingURL=runtime-bindings.js.map","import\"../core/internal.js\";import{listen as e,setAttr as t}from\"../core/utilities.js\";import{bindPropertyModel as n,hasWritableValueSetter as r,toReactiveBindingSource as i}from\"../core/runtime-bindings.js\";import{effect as a}from\"@vielzeug/stateit\";var o=(e,t,n)=>e?(n(a(()=>{t(e.value)})),!0):!1,s=(t,n,r,i)=>n.startsWith(`@`)?(typeof r==`function`&&i(e(t,n.slice(1),r)),!0):!1,c=(e,t,a,s)=>{if(!t.startsWith(`.`))return!1;let c=t.slice(1),l=r(a)?a:void 0;return o(i(a),t=>e[c]=t,s)||(e[c]=a),n(e,c,l,s),!0},l=(e,t,n,r)=>{if(!t.startsWith(`?`))return!1;let a=t.slice(1);return o(i(n),t=>e.toggleAttribute(a,!!t),r)||e.toggleAttribute(a,!!n),!0},u=(e,n,r,a)=>{o(i(r),r=>t(e,n,r),a)||t(e,n,r)},d=(e,t,n,r)=>{n!==void 0&&(s(e,t,n,r)||c(e,t,n,r)||l(e,t,n,r)||u(e,t,n,r))};function f(e){return{mount(t,{registerCleanup:n}){for(let[r,i]of Object.entries(e))d(t,r,i,n)}}}export{f as spread};\n//# sourceMappingURL=spread.js.map","import\"../core/internal.js\";import{spread as e}from\"./spread.js\";import\"@vielzeug/stateit\";function t(t){let n={};for(let[e,r]of Object.entries(t))n[`.${e}`]=r;return e(n)}export{t as attr};\n//# sourceMappingURL=attr.js.map","import{computed as e,isSignal as t}from\"@vielzeug/stateit\";function n(n){let r=Object.entries(n),i=r.some(([,e])=>t(e)||typeof e==`function`),a=()=>r.filter(([,e])=>t(e)?e.value:typeof e==`function`?!!e():!!e).map(([e])=>e).join(` `);return i?e(a):a()}export{n as classes};\n//# sourceMappingURL=classes.js.map","import{EACH_SIGNAL as e,extractResult as t,htmlResult as n}from\"../core/internal.js\";import{computed as r,isSignal as i}from\"@vielzeug/stateit\";var a=RegExp(`u=\"(\\\\d+)\"`,`g`),o=n(``),s=[];function c(e,t){let n=new Map,r=[];for(let i of e.__bindings){let e=i.uid,a=n.get(e)??String(t.n++);n.has(e)||n.set(e,a),r.push({...i,uid:a})}return{bindings:r,html:e.__html.replace(a,(e,t)=>`u=\"${n.get(t)??t}\"`).replace(/<!--(\\d+)-->/g,(e,t)=>`<!--${n.get(t)??t}-->`)}}function l(e,t,n){let r=``,i=[],a=[],o=[],l={n:0};for(let u=0;u<e.length;u++){a.push(n(e[u],u));let d=t(e[u],u),f=typeof d==`string`?{bindings:s,html:d}:c(d,l);r+=f.html,i.push(...f.bindings),o.push(f)}return{bindings:i,html:r,keys:a,rendered:o}}function u(e,t){let n=``,r=[],i={n:0};for(let a=0;a<e.length;a++){let o=t(e[a],a),l=typeof o==`string`?{bindings:s,html:o}:c(o,i);n+=l.html,r.push(...l.bindings)}return{bindings:r,html:n}}function d(a,s,c,d){let f=typeof c==`function`,p=f?c:void 0,m=(f?d:d??c)??{},h=m.select;if(Array.isArray(a)){let e=h?a.filter(h):a;if(!e.length){if(p){let e=t(p());return n(e.html,e.bindings)}return o}let{bindings:r,html:i}=u(e,s);return n(i,r)}let g=m.key;if(!g)throw Error(`[craftit:each] Reactive each() requires options.key for stable reconciliation.`);let _=i(a)?()=>a.value:a;return{[e]:r(()=>{let e=_(),n=h?e.filter(h):e;if(!n.length){let e=p?.();return e?{...t(e),items:[],keys:[]}:{bindings:[],html:``,items:[],keys:[]}}let{bindings:r,html:i,keys:a,rendered:o}=l(n,s,g);return{bindings:r,html:i,items:o,keys:a}})}}export{d as each};\n//# sourceMappingURL=each.js.map","import{isSignal as e}from\"@vielzeug/stateit\";function t(t,n,r){if(e(t)||typeof t==`function`){let i=e(t)?()=>t.value:t;return{render:()=>i()?n():r?.()??``}}return t?n():r?.()??``}export{t as when};\n//# sourceMappingURL=when.js.map","@layer buildit.base {\n /* ========================================\n Base Styles\n ======================================== */\n\n :host {\n display: inline-flex;\n\n --group-gap: var(--size-2);\n --group-radius: var(--rounded-lg);\n }\n\n .button-group {\n display: flex;\n flex-direction: row;\n gap: var(--group-gap);\n }\n}\n\n@layer buildit.variants {\n /* ========================================\n Orientation\n ======================================== */\n\n :host([orientation='vertical']) .button-group {\n flex-direction: column;\n }\n}\n\n@layer buildit.overrides {\n /* ========================================\n Full Width\n ======================================== */\n\n :host([fullwidth]) {\n display: flex;\n width: 100%;\n }\n\n :host([fullwidth]) .button-group {\n width: 100%;\n }\n\n :host([fullwidth]) ::slotted(bit-button) {\n flex: 1;\n }\n\n /* ========================================\n Attached Mode\n ======================================== */\n\n :host([attached]) .button-group {\n gap: 0;\n }\n\n /* Ensure attached buttons have proper z-index on hover/focus */\n :host([attached]) ::slotted(bit-button:hover),\n :host([attached]) ::slotted(bit-button:focus-within) {\n position: relative;\n z-index: 1;\n }\n\n /* Horizontal attached - remove inner borders and round corners */\n :host([attached]:not([orientation='vertical'])) ::slotted(bit-button) {\n --button-radius: 0;\n }\n\n :host([attached]:not([orientation='vertical'])) ::slotted(bit-button:not(:first-child)) {\n --button-border-start: 0;\n }\n\n :host([attached]:not([orientation='vertical'])) ::slotted(bit-button:first-child) {\n --button-radius: var(--group-radius) 0 0 var(--group-radius);\n }\n\n :host([attached]:not([orientation='vertical'])) ::slotted(bit-button:last-child) {\n --button-radius: 0 var(--group-radius) var(--group-radius) 0;\n }\n\n /* Vertical attached - remove inner borders and round corners */\n :host([attached][orientation='vertical']) ::slotted(bit-button) {\n --button-radius: 0;\n }\n\n :host([attached][orientation='vertical']) ::slotted(bit-button:not(:first-child)) {\n --button-border-top: 0;\n }\n\n :host([attached][orientation='vertical']) ::slotted(bit-button:first-child) {\n --button-radius: var(--group-radius) var(--group-radius) 0 0;\n }\n\n :host([attached][orientation='vertical']) ::slotted(bit-button:last-child) {\n --button-radius: 0 0 var(--group-radius) var(--group-radius);\n }\n}\n","import { createContext, defineComponent, html, provide, type ReadonlySignal } from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\n/** Context provided by bit-button-group to its bit-button children. */\nexport type ButtonGroupContext = {\n color: ReadonlySignal<ThemeColor | undefined>;\n size: ReadonlySignal<ComponentSize | undefined>;\n variant: ReadonlySignal<Exclude<VisualVariant, 'glass'> | undefined>;\n};\n/** Injection key for the button-group context. */\nexport const BUTTON_GROUP_CTX = createContext<ButtonGroupContext>('ButtonGroupContext');\n\nimport styles from './button-group.css?inline';\n\n/** Button group component properties */\nexport type BitButtonGroupProps = {\n /** Attach buttons together (no gap, rounded only on edges) */\n attached?: boolean;\n /** Button color for all children (propagated) */\n color?: ThemeColor;\n /** Make all buttons full width */\n fullwidth?: boolean;\n /** Accessible group label */\n label?: string;\n /** Group orientation */\n orientation?: 'horizontal' | 'vertical';\n /** Button size for all children (propagated) */\n size?: ComponentSize;\n /** Button variant for all children (propagated) */\n variant?: Exclude<VisualVariant, 'glass'>;\n};\n\n// -------------------- Component Definition --------------------\n/**\n * A container for grouping buttons with coordinated styling and layout.\n *\n * @element bit-button-group\n *\n * @attr {string} size - Button size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'frost'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} orientation - Group orientation: 'horizontal' | 'vertical'\n * @attr {boolean} attached - Attach buttons together (no gap, rounded only on edges)\n * @attr {boolean} fullwidth - Make all buttons full width\n * @attr {string} label - Accessible group label\n *\n * @slot - Button elements (bit-button)\n *\n * @cssprop --group-gap - Gap between buttons\n * @cssprop --group-radius - Border radius for edge buttons\n *\n * @example\n * ```html\n * <bit-button-group><bit-button>First</bit-button><bit-button>Second</bit-button></bit-button-group>\n * ```\n */\nexport const BUTTON_GROUP_TAG = defineComponent<BitButtonGroupProps>({\n props: {\n attached: { default: false },\n color: { default: undefined },\n fullwidth: { default: false },\n label: { default: undefined },\n orientation: { default: undefined },\n size: { default: undefined },\n variant: { default: undefined },\n },\n setup({ props }) {\n provide(BUTTON_GROUP_CTX, {\n color: props.color,\n size: props.size,\n variant: props.variant,\n });\n\n return html`\n <div class=\"button-group\" part=\"group\" role=\"group\" :aria-label=\"${() => props.label.value ?? null}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [styles],\n tag: 'bit-button-group',\n});\n","@layer buildit.base {\n :host {\n --_bg: var(--button-bg, var(--color-contrast-50));\n --_color: var(--button-color, var(--color-contrast-900));\n --_border: var(--button-border, var(--border));\n --_border-color: var(--button-border-color, var(--color-contrast-200));\n --_radius: var(--button-radius, var(--rounded-lg));\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([disabled]) {\n cursor: not-allowed;\n }\n\n /* Link mode: mixin covers <button> but not <a> */\n :host([disabled]) a,\n :host([loading]) a {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n :host([loading]) a {\n cursor: wait;\n }\n\n button,\n a {\n position: relative;\n box-sizing: border-box;\n display: flex;\n gap: var(--_gap, var(--size-2));\n align-items: center;\n justify-content: center;\n width: 100%;\n min-width: 0;\n height: var(--_height, var(--size-10));\n min-height: var(--_touch-target);\n padding: var(--_padding, var(--size-2) var(--size-4));\n font-size: var(--_font-size, var(--text-sm));\n font-weight: var(--font-medium);\n line-height: var(--_line-height, var(--leading-normal));\n color: var(--_color);\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n background: var(--_bg);\n border: var(--_border) solid var(--_border-color);\n border-block-start-width: var(--button-border-top, var(--_border));\n border-block-end-width: var(--button-border-bottom, var(--_border));\n border-inline-start-width: var(--button-border-start, var(--_border));\n border-inline-end-width: var(--button-border-end, var(--_border));\n border-radius: var(--_radius);\n transition: var(\n --_motion-transition,\n background var(--transition-normal),\n border-color var(--transition-normal),\n box-shadow var(--transition-normal),\n color var(--transition-normal),\n opacity var(--transition-normal),\n transform var(--transition-fast)\n );\n }\n\n a {\n text-decoration: none;\n }\n\n button:focus-visible,\n a:focus-visible {\n outline: none;\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n vertical-align: middle;\n white-space: nowrap;\n }\n\n ::slotted([slot='prefix']),\n ::slotted([slot='suffix']) {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n }\n\n ::slotted(svg) {\n flex-shrink: 0;\n width: var(--_icon-size, var(--leading-6));\n height: var(--_icon-size, var(--leading-6));\n }\n}\n\n@layer buildit.overrides {\n :host([fullwidth]) {\n display: flex;\n width: 100%;\n }\n}\n\n@layer buildit.variants {\n :host([icon-only]) :is(button, a) {\n aspect-ratio: 1;\n padding: 0;\n }\n\n /* Solid (Default) - Full theme color background */\n :host(:not([variant])) :is(button, a),\n :host([variant='solid']) :is(button, a) {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n border-color: var(--_theme-base);\n }\n\n :host(:not([variant])) :is(button, a):hover,\n :host([variant='solid']) :is(button, a):hover {\n background: var(--_theme-focus);\n }\n\n :host(:not([variant])) :is(button, a):active,\n :host([variant='solid']) :is(button, a):active {\n background: var(--_theme-content);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n /* Flat - Subtle background with theme color text */\n :host([variant='flat']) :is(button, a) {\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-backdrop) 8%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-focus) 20%, transparent);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) :is(button, a):hover {\n color: var(--_theme-contrast);\n background: var(--_theme-focus);\n box-shadow: var(--inset-shadow-xs);\n }\n\n :host([variant='flat']) :is(button, a):active {\n color: var(--_theme-contrast);\n background: var(--_theme-content);\n box-shadow: var(--inset-shadow-sm);\n }\n\n /* Bordered - Outlined with filled background */\n :host([variant='bordered']) :is(button, a) {\n color: var(--_theme-base);\n background: var(--_theme-backdrop);\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-xs);\n }\n\n :host([variant='bordered']) :is(button, a):hover {\n color: var(--_theme-contrast);\n background: var(--_theme-focus);\n border-color: var(--_theme-focus);\n box-shadow: var(--inset-shadow-xs);\n }\n\n :host([variant='bordered']) :is(button, a):active {\n color: var(--_theme-contrast);\n background: var(--_theme-content);\n box-shadow: var(--inset-shadow-sm);\n }\n\n /* Outline - Transparent with colored border */\n :host([variant='outline']) :is(button, a) {\n color: var(--_theme-base);\n background: transparent;\n border-color: var(--_theme-base);\n }\n\n :host([variant='outline']) :is(button, a):hover {\n background: var(--_theme-backdrop);\n border-color: var(--_theme-focus);\n }\n\n :host([variant='outline']) :is(button, a):active {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n /* Ghost - Transparent until interaction */\n :host([variant='ghost']) :is(button, a) {\n color: var(--_theme-base);\n background: transparent;\n border-color: transparent;\n border-width: 0;\n }\n\n :host([variant='ghost']) :is(button, a):hover {\n background: var(--_theme-backdrop);\n }\n\n :host([variant='ghost']) :is(button, a):active {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n /* Text - Minimal styling, color on hover */\n :host([variant='text']) :is(button, a) {\n color: var(--_theme-base);\n background: transparent;\n border-color: transparent;\n border-width: 0;\n }\n\n :host([variant='text']) :is(button, a):hover {\n color: var(--_theme-focus);\n }\n\n :host([variant='text']) :is(button, a):active {\n color: var(--_theme-content);\n }\n\n /* Additional button-specific frost active states */\n :host([variant='frost']:not([color])) :is(button, a):active {\n background: color-mix(in srgb, var(--color-canvas) 70%, transparent);\n border-color: color-mix(in srgb, var(--theme-focus) 40%, transparent);\n }\n\n :host([variant='frost'][color]) :is(button, a):active {\n background: color-mix(in srgb, var(--_theme-backdrop) 50%, var(--_theme-base) 50%);\n border-color: color-mix(in srgb, var(--_theme-focus) 65%, transparent);\n }\n}\n\n/* ========================================\n Other Variants & States\n ======================================== */\n\n@layer buildit.overrides {\n /* Icon-only always uses perfect circle */\n :host([rounded][icon-only]) :is(button, a) {\n border-radius: 50%;\n }\n\n :host([loading]) .content {\n visibility: hidden;\n }\n}\n\n/* ========================================\n Loading Spinner (unlayered for easy override)\n ======================================== */\n\n.loader {\n position: absolute;\n width: 1em;\n height: 1em;\n border: var(--border-2) solid currentcolor;\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: var(--_motion-animation, spin 0.6s linear infinite);\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Focus ring & hover halo — unlayered so it wins over all @layer variant rules */\nbutton:focus-visible,\na:focus-visible,\nbutton:hover,\na:hover {\n outline: none;\n box-shadow: var(--_theme-shadow);\n}\n\n/* Text variant: no halo on hover or focus */\n:host([variant='text']) button:hover,\n:host([variant='text']) a:hover {\n box-shadow: none;\n}\n","import { computed, defineComponent, defineField, fire, html, inject, syncContextProps } from '@vielzeug/craftit';\nimport { when } from '@vielzeug/craftit/directives';\n\nimport type { ButtonType, DisablableProps, RoundedSize, SizableProps, ThemableProps, VisualVariant } from '../../types';\n\nimport {\n disabledLoadingMixin,\n forcedColorsMixin,\n formFieldMixins,\n frostVariantMixin,\n rainbowEffectMixin,\n sizeVariantMixin,\n} from '../../styles';\nimport { BUTTON_GROUP_CTX } from '../button-group/button-group';\nimport componentStyles from './button.css?inline';\n\n/** Button component properties */\nexport type BitButtonProps = ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Full width button (100% of container) */\n fullwidth?: boolean;\n /** When set, renders an `<a>` instead of `<button>` */\n href?: string;\n /** Icon-only mode (square aspect ratio, no padding) */\n iconOnly?: boolean;\n /** Accessible label for the inner button — required for icon-only buttons */\n label?: string;\n /** Show loading state with spinner */\n loading?: boolean;\n /** Enable animated rainbow border effect */\n rainbow?: boolean;\n /** Link rel attribute (requires href) */\n rel?: string;\n /** Border radius size */\n rounded?: RoundedSize;\n /** Link target (requires href) */\n target?: '_blank' | '_self' | '_parent' | '_top';\n /** HTML button type attribute */\n type?: ButtonType;\n /** Visual style variant */\n variant?: Exclude<VisualVariant, 'glass'>;\n };\n\n/**\n * A customizable button component with multiple variants, sizes, and states.\n * Supports icons, loading states, and special effects like frost and rainbow.\n *\n * @element bit-button\n *\n * @attr {string} type - HTML button type: 'button' | 'submit' | 'reset'\n * @attr {boolean} disabled - Disable button interaction\n * @attr {boolean} loading - Show loading state with spinner\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'frost'\n * @attr {string} size - Button size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} rainbow - Enable animated rainbow border effect\n * @attr {boolean} icon-only - Icon-only mode (square aspect ratio, no padding)\n * @attr {boolean} fullwidth - Full width button (100% of container)\n *\n * @fires click - Emitted when button is clicked (unless disabled/loading)\n *\n * @slot - Button content (text, icons, etc.)\n * @slot prefix - Content before the button text (e.g., icons)\n * @slot suffix - Content after the button text (e.g., icons, badges)\n *\n * @part button - The button element\n * @part loader - The loading spinner element\n * @part content - The button content wrapper\n *\n * @cssprop --button-bg - Background color\n * @cssprop --button-color - Text color\n * @cssprop --button-hover-bg - Hover background\n * @cssprop --button-active-bg - Active/pressed background\n * @cssprop --button-border - Border width\n * @cssprop --button-border-color - Border color\n * @cssprop --button-radius - Border radius\n * @cssprop --button-padding - Inner padding\n * @cssprop --button-gap - Gap between icon and text\n * @cssprop --button-font-size - Font size\n *\n * @example\n * ```html\n * <bit-button variant=\"solid\" color=\"primary\">Click me</bit-button>\n * <bit-button loading color=\"success\">Processing...</bit-button>\n * <bit-button variant=\"frost\" rainbow>Special Button</bit-button>\n * ```\n */\nexport const BUTTON_TAG = defineComponent<BitButtonProps>({\n formAssociated: true,\n props: {\n color: { default: undefined },\n disabled: { default: false },\n fullwidth: { default: false },\n href: { default: undefined },\n iconOnly: { default: false },\n label: { default: undefined },\n loading: { default: false },\n rainbow: { default: false },\n rel: { default: undefined },\n rounded: { default: undefined },\n size: { default: undefined },\n target: { default: undefined },\n type: { default: 'button' },\n variant: { default: 'solid' },\n },\n setup({ host, props }) {\n // Reactively inherit size/variant/color from a parent bit-button-group when present.\n syncContextProps(inject(BUTTON_GROUP_CTX, undefined), props, ['color', 'size', 'variant']);\n\n const isDisabled = computed(() => props.disabled.value || props.loading.value || false);\n const isLink = computed(() => !!props.href.value);\n // Form association: relay submit/reset clicks to the associated form.\n // The inner <button> always has type=\"button\" so shadow DOM never drives native form actions.\n const formField = defineField({\n disabled: isDisabled,\n toFormValue: () => null,\n value: computed(() => ''),\n });\n // Prevent navigation on disabled links; native <button disabled> handles the button case.\n const handleLinkClick = (e: MouseEvent) => {\n if (isDisabled.value) {\n e.preventDefault();\n e.stopPropagation();\n\n return;\n }\n\n // Relay to host as a proper MouseEvent. stopPropagation prevents double-dispatch in\n // browsers where shadow DOM already retargets the event to the host.\n e.stopPropagation();\n fire.mouse(host, e.type, e);\n };\n const handleButtonClick = (e: MouseEvent) => {\n if (isDisabled.value) return;\n\n // Relay to host, handle form submission, and stop inner bubble in one place.\n e.stopPropagation();\n\n const form = formField.internals.form;\n\n if (form) {\n if (props.type.value === 'submit') form.requestSubmit();\n else if (props.type.value === 'reset') form.reset();\n }\n\n fire.mouse(host, e.type, e);\n };\n\n return html`\n ${when(\n isLink,\n () =>\n html`<a\n part=\"button\"\n :href=\"${() => props.href.value ?? null}\"\n :target=\"${() => props.target.value ?? null}\"\n :rel=\"${() => props.rel.value ?? null}\"\n :aria-label=\"${() => props.label.value ?? null}\"\n :aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n :aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"\n role=\"button\"\n @click=\"${handleLinkClick}\">\n <span class=\"loader\" part=\"loader\" aria-label=\"Loading\" ?hidden=${() => !props.loading.value}></span>\n <slot name=\"prefix\"></slot>\n <span class=\"content\" part=\"content\"><slot></slot></span>\n <slot name=\"suffix\"></slot>\n </a>`,\n () =>\n html`<button\n part=\"button\"\n type=\"button\"\n ?disabled=${isDisabled}\n :aria-label=\"${() => props.label.value ?? null}\"\n :aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n :aria-busy=\"${() => (props.loading.value ? 'true' : null)}\"\n @click=\"${handleButtonClick}\">\n <span class=\"loader\" part=\"loader\" aria-label=\"Loading\" ?hidden=${() => !props.loading.value}></span>\n <slot name=\"prefix\"></slot>\n <span class=\"content\" part=\"content\"><slot></slot></span>\n <slot name=\"suffix\"></slot>\n </button>`,\n )}\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n ...formFieldMixins,\n forcedColorsMixin,\n sizeVariantMixin({\n lg: {\n fontSize: 'var(--text-base)',\n gap: 'var(--size-2-5)',\n height: 'var(--size-12)',\n iconSize: 'var(--size-6)',\n lineHeight: 'var(--leading-relaxed)',\n padding: 'var(--size-2-5) var(--size-5)',\n },\n sm: {\n fontSize: 'var(--text-sm)',\n gap: 'var(--size-1-5)',\n height: 'var(--size-8)',\n iconSize: 'var(--size-4)',\n lineHeight: 'var(--leading-tight)',\n padding: 'var(--size-1-5) var(--size-3)',\n },\n }),\n frostVariantMixin('button'),\n rainbowEffectMixin('button'),\n disabledLoadingMixin('button'),\n componentStyles,\n ],\n tag: 'bit-button',\n});\n","@layer buildit.base {\n :host {\n display: flex;\n gap: var(--size-1);\n align-items: center;\n }\n\n .pagination {\n display: flex;\n gap: var(--pagination-gap, var(--size-1));\n align-items: center;\n padding: 0;\n margin: 0;\n list-style: none;\n }\n\n li {\n display: contents;\n }\n\n button {\n all: unset;\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--pagination-item-size, var(--size-9));\n height: var(--pagination-item-size, var(--size-9));\n min-height: var(--_touch-target);\n padding: 0 var(--size-2);\n font-size: var(--_font-size, var(--text-sm));\n font-weight: var(--font-medium);\n color: var(--color-contrast-700);\n cursor: pointer;\n user-select: none;\n border: var(--border) solid transparent;\n border-radius: var(--pagination-radius, var(--rounded-lg));\n transition:\n background var(--transition-fast),\n color var(--transition-fast),\n border-color var(--transition-fast);\n }\n\n /* Default (ghost-like) behavior unless variant is specified */\n :host(:not([variant])) button,\n :host([variant='ghost']) button {\n color: var(--_theme-base);\n background: transparent;\n border-color: transparent;\n border-width: 0;\n }\n\n :host(:not([variant])) button:hover:not(:disabled, [aria-current='page']),\n :host([variant='ghost']) button:hover:not(:disabled, [aria-current='page']) {\n background: var(--_theme-backdrop);\n }\n\n :host([variant='solid']) button {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n border-color: var(--_theme-base);\n }\n\n :host([variant='solid']) button:hover:not(:disabled, [aria-current='page']) {\n background: var(--_theme-focus);\n }\n\n :host([variant='flat']) button {\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-backdrop) 8%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-focus) 20%, transparent);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) button:hover:not(:disabled, [aria-current='page']) {\n color: var(--_theme-contrast);\n background: var(--_theme-focus);\n }\n\n :host([variant='bordered']) button {\n color: var(--_theme-base);\n background: var(--_theme-backdrop);\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-xs);\n }\n\n :host([variant='bordered']) button:hover:not(:disabled, [aria-current='page']) {\n color: var(--_theme-contrast);\n background: var(--_theme-focus);\n border-color: var(--_theme-focus);\n }\n\n :host([variant='outline']) button {\n color: var(--_theme-base);\n background: transparent;\n border-color: var(--_theme-base);\n }\n\n :host([variant='outline']) button:hover:not(:disabled, [aria-current='page']) {\n background: var(--_theme-backdrop);\n border-color: var(--_theme-focus);\n }\n\n :host([variant='text']) button {\n color: var(--_theme-base);\n background: transparent;\n border-color: transparent;\n border-width: 0;\n }\n\n :host([variant='text']) button:hover:not(:disabled, [aria-current='page']) {\n color: var(--_theme-focus);\n background: transparent;\n }\n\n :host([variant='frost']) button {\n color: var(--_theme-content);\n background: color-mix(in srgb, var(--_theme-backdrop) 45%, transparent);\n border-color: color-mix(in srgb, var(--_theme-border) 45%, transparent);\n backdrop-filter: blur(var(--blur-xl)) saturate(200%);\n }\n\n :host([variant='frost']) button:hover:not(:disabled, [aria-current='page']) {\n background: color-mix(in srgb, var(--_theme-backdrop) 65%, transparent);\n border-color: color-mix(in srgb, var(--_theme-focus) 55%, transparent);\n }\n\n :host([variant='glass']) button {\n color: var(--_theme-content);\n background: color-mix(in srgb, var(--color-canvas) 70%, transparent);\n border-color: color-mix(in srgb, var(--_theme-border) 40%, transparent);\n backdrop-filter: blur(var(--blur-md)) saturate(140%);\n }\n\n :host([variant='glass']) button:hover:not(:disabled, [aria-current='page']) {\n background: color-mix(in srgb, var(--color-canvas) 55%, transparent);\n border-color: color-mix(in srgb, var(--_theme-focus) 45%, transparent);\n }\n\n button:hover:not(:disabled, [aria-current='page']) {\n background: var(--color-contrast-100);\n }\n\n button:focus-visible {\n outline: var(--border-2) solid var(--_theme-base, var(--color-contrast-500));\n outline-offset: var(--border-2);\n }\n\n button[aria-current='page'] {\n color: var(--_theme-contrast, var(--color-canvas));\n cursor: default;\n background: var(--_theme-base, var(--color-contrast-800));\n border-color: var(--_theme-base, var(--color-contrast-800));\n }\n\n button:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n\n .ellipsis {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--pagination-item-size, var(--size-9));\n height: var(--pagination-item-size, var(--size-9));\n font-size: var(--_font-size, var(--text-sm));\n color: var(--color-contrast-400);\n cursor: default;\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --pagination-item-size: var(--size-7);\n --pagination-gap: var(--size-0_5);\n --_font-size: var(--text-xs);\n }\n\n :host([size='lg']) {\n --pagination-item-size: var(--size-11);\n --_font-size: var(--text-base);\n }\n}\n","import { computed, defineComponent, html } from '@vielzeug/craftit';\nimport { each } from '@vielzeug/craftit/directives';\n\nimport '../../inputs/button/button';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { coarsePointerMixin, colorThemeMixin, sizeVariantMixin } from '../../styles';\nimport styles from './pagination.css?inline';\n\nexport type BitPaginationEvents = {\n change: { page: number };\n};\n\n/** Pagination props */\nexport type BitPaginationProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Accessible label for the nav landmark */\n label?: string;\n /** Current page (1-indexed) */\n page?: number;\n /** Show first/last page navigation buttons */\n 'show-first-last'?: boolean;\n /** Show prev/next navigation buttons */\n 'show-prev-next'?: boolean;\n /** Number of sibling pages shown around the current page */\n siblings?: number;\n /** Size */\n size?: ComponentSize;\n /** Total number of pages */\n 'total-pages'?: number;\n /** Visual variant for nav buttons */\n variant?: VisualVariant;\n};\n\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblings: number,\n): Array<number | 'ellipsis-start' | 'ellipsis-end'> {\n const BOUNDARY = 1; // always show first and last page\n const total = totalPages;\n const pages: Array<number | 'ellipsis-start' | 'ellipsis-end'> = [];\n\n // If total is small enough, show all pages\n if (total <= 2 * BOUNDARY + 2 * siblings + 3) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblings, BOUNDARY + 1);\n const rightSibling = Math.min(currentPage + siblings, total - BOUNDARY);\n\n pages.push(1);\n\n if (leftSibling > BOUNDARY + 2) pages.push('ellipsis-start');\n else if (leftSibling === BOUNDARY + 2) pages.push(BOUNDARY + 1);\n\n for (let i = leftSibling; i <= rightSibling; i++) pages.push(i);\n\n if (rightSibling < total - BOUNDARY - 1) pages.push('ellipsis-end');\n else if (rightSibling === total - BOUNDARY - 1) pages.push(total - BOUNDARY);\n\n pages.push(total);\n\n return pages;\n}\n\n/**\n * Page-based navigation control.\n *\n * @element bit-pagination\n *\n * @attr {number} page - Current page (1-indexed, default: 1)\n * @attr {number} total-pages - Total number of pages (required)\n * @attr {number} siblings - Sibling pages around current (default: 1)\n * @attr {boolean} show-first-last - Show first/last page buttons (default: false)\n * @attr {boolean} show-prev-next - Show prev/next buttons (default: false)\n * @attr {string} color - Theme color\n * @attr {string} variant - Visual variant for nav buttons: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'frost' | 'glass' (default: 'ghost')\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} label - Accessible nav label (default: 'Pagination')\n *\n * @fires change - Emitted when the page changes, with { page: number }\n *\n * @cssprop --pagination-item-size - Width/height of each item\n * @cssprop --pagination-gap - Gap between items\n * @cssprop --pagination-radius - Border radius of items\n *\n * @example\n * ```html\n * <bit-pagination page=\"3\" total-pages=\"10\" color=\"primary\"></bit-pagination>\n * ```\n */\nexport const PAGINATION_TAG = defineComponent<BitPaginationProps, BitPaginationEvents>({\n props: {\n color: { default: undefined },\n label: { default: 'Pagination' },\n page: { default: 1 },\n 'show-first-last': { default: false, type: Boolean },\n 'show-prev-next': { default: false, type: Boolean },\n siblings: { default: 1 },\n size: { default: undefined },\n 'total-pages': { default: 1 },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n function goTo(page: number) {\n const total = Number(props['total-pages'].value) || 1;\n const next = Math.min(Math.max(1, page), total);\n\n if (next === Number(props.page.value)) return;\n\n host.setAttribute('page', String(next));\n emit('change', { page: next });\n }\n\n function handlePageClick(event: Event) {\n const btn = (event.target as HTMLElement)?.closest('[part=\"page-btn\"]') as HTMLButtonElement | null;\n\n if (!btn) return;\n\n const ariaLabel = btn.getAttribute('aria-label');\n\n if (!ariaLabel) return;\n\n const pageMatch = ariaLabel.match(/\\d+/);\n\n if (!pageMatch) return;\n\n const page = Number(pageMatch[0]);\n\n goTo(page);\n }\n\n const pageItems = computed(() =>\n buildPageRange(\n Number(props.page.value) || 1,\n Number(props['total-pages'].value) || 1,\n // eslint-disable-next-line no-constant-binary-expression\n Number(props.siblings.value) ?? 1,\n ),\n );\n const isFirst = computed(() => (Number(props.page.value) || 1) <= 1);\n const isLast = computed(() => (Number(props.page.value) || 1) >= (Number(props['total-pages'].value) || 1));\n\n return html`\n <nav :aria-label=\"${() => props.label.value}\" part=\"nav\" @click=${handlePageClick}>\n <ol class=\"pagination\" part=\"list\">\n ${() =>\n props['show-first-last'].value\n ? html`<li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"first-btn\"\n aria-label=\"First page\"\n ?disabled=${() => isFirst.value}\n @click=${() => goTo(1)}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"11 17 6 12 11 7\" />\n <polyline points=\"18 17 13 12 18 7\" />\n </svg>\n </button>\n </li>`\n : ''}\n ${() =>\n props['show-prev-next'].value\n ? html`<li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"prev-btn\"\n aria-label=\"Previous page\"\n ?disabled=${() => isFirst.value}\n @click=${() => goTo((Number(props.page.value) || 1) - 1)}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n </li>`\n : ''}\n <li style=\"display: contents;\">\n ${each(\n pageItems,\n (item) => {\n if (item === 'ellipsis-start' || item === 'ellipsis-end') {\n return html`<span class=\"ellipsis\" aria-hidden=\"true\">&hellip;</span>`;\n }\n\n const pg = item as number;\n const isCurrent = pg === (Number(props.page.value) || 1);\n\n return isCurrent\n ? html`<button type=\"button\" part=\"page-btn\" aria-label=\"Page ${pg}\" aria-current=\"page\">\n ${pg}\n </button>`\n : html`<button type=\"button\" part=\"page-btn\" aria-label=\"Page ${pg}\">${pg}</button>`;\n },\n undefined,\n { key: (item) => `${item}` },\n )}\n </li>\n ${() =>\n props['show-prev-next'].value\n ? html`<li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"next-btn\"\n aria-label=\"Next page\"\n ?disabled=${() => isLast.value}\n @click=${() => goTo((Number(props.page.value) || 1) + 1)}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </button>\n </li>`\n : ''}\n ${() =>\n props['show-first-last'].value\n ? html`<li>\n <button\n type=\"button\"\n class=\"nav-btn\"\n part=\"last-btn\"\n aria-label=\"Last page\"\n ?disabled=${() => isLast.value}\n @click=${() => goTo(Number(props['total-pages'].value) || 1)}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"13 17 18 12 13 7\" />\n <polyline points=\"6 17 11 12 6 7\" />\n </svg>\n </button>\n </li>`\n : ''}\n </ol>\n </nav>\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, styles],\n tag: 'bit-pagination',\n});\n","@layer buildit.base {\n :host {\n --_color: var(--separator-color, var(--color-contrast-300));\n --_size: var(--separator-size, var(--border));\n --_spacing: var(--separator-spacing, 0);\n\n display: block;\n }\n\n .separator {\n all: unset;\n box-sizing: border-box;\n display: block;\n margin: var(--_spacing) 0;\n }\n\n :host([orientation='horizontal']),\n :host(:not([orientation='vertical'])) {\n width: 100%;\n }\n\n :host([orientation='horizontal']) .separator,\n :host(:not([orientation='vertical'])) .separator {\n width: 100%;\n border-top: var(--_size) solid var(--_color);\n }\n\n :host([orientation='vertical']) {\n display: inline-block;\n align-self: stretch;\n }\n\n :host([orientation='vertical']) .separator {\n height: 100%;\n border-inline-start: var(--_size) solid var(--_color);\n }\n\n :host([color]) {\n --_color: var(--_theme-base);\n }\n\n /* Labelled separator */\n .separator-wrapper {\n display: flex;\n gap: var(--size-3);\n align-items: center;\n }\n\n .separator-wrapper .separator {\n flex: 1;\n }\n\n .separator-label {\n font-size: var(--text-xs);\n font-weight: var(--font-medium);\n color: var(--_color);\n white-space: nowrap;\n }\n}\n","import { defineComponent, html, typed } from '@vielzeug/craftit';\n\nimport type { ThemeColor } from '../../types';\n\nimport { colorThemeMixin } from '../../styles';\nimport componentStyles from './separator.css?inline';\n\n/** Separator component properties */\nexport type BitSeparatorProps = {\n /** Theme color tint */\n color?: ThemeColor;\n /** Decorative only (default true) — set to false for semantic separators */\n decorative?: boolean;\n /** Optional label text centered on the separator */\n label?: string;\n /** Orientation of the separator */\n orientation?: 'horizontal' | 'vertical';\n};\n\n/**\n * A simple visual divider between sections of content.\n *\n * @element bit-separator\n *\n * @attr {string} orientation - 'horizontal' (default) | 'vertical'\n * @attr {boolean} decorative - When true (default), aria-hidden is applied\n * @attr {string} label - Optional centered label text\n * @attr {string} color - Theme color\n *\n * @cssprop --separator-color - Line color\n * @cssprop --separator-size - Line thickness\n * @cssprop --separator-spacing - Vertical margin\n *\n * @example\n * ```html\n * <bit-separator></bit-separator>\n * <bit-separator label=\"or\"></bit-separator>\n * <bit-separator orientation=\"vertical\"></bit-separator>\n * ```\n */\nexport const SEPARATOR_TAG = defineComponent<BitSeparatorProps>({\n props: {\n color: typed<BitSeparatorProps['color']>(undefined),\n decorative: typed<boolean>(true),\n label: typed<string | undefined>(undefined),\n orientation: typed<BitSeparatorProps['orientation']>('horizontal'),\n },\n setup({ props }) {\n return html`\n ${() =>\n props.label.value\n ? html`\n <div class=\"separator-wrapper\" part=\"wrapper\">\n <hr\n class=\"separator\"\n part=\"separator\"\n :role=\"${() => (props.decorative.value ? 'none' : 'separator')}\"\n :aria-hidden=\"${() => (props.decorative.value ? 'true' : null)}\"\n :aria-orientation=\"${() => props.orientation.value}\" />\n <span class=\"separator-label\" part=\"label\">${() => props.label.value}</span>\n <hr\n class=\"separator\"\n part=\"separator\"\n :role=\"${() => (props.decorative.value ? 'none' : 'separator')}\"\n :aria-hidden=\"${() => (props.decorative.value ? 'true' : null)}\" />\n </div>\n `\n : html`\n <hr\n class=\"separator\"\n part=\"separator\"\n :role=\"${() => (props.decorative.value ? 'none' : 'separator')}\"\n :aria-hidden=\"${() => (props.decorative.value ? 'true' : null)}\"\n :aria-orientation=\"${() => props.orientation.value}\" />\n `}\n `;\n },\n styles: [colorThemeMixin, componentStyles],\n tag: 'bit-separator',\n});\n","@layer buildit.base {\n :host {\n /* ── Public API tokens ──────────────────────────────────────────────── */\n --_radius: var(--table-radius, var(--rounded-lg));\n --_shadow: var(--table-shadow, none);\n --_border: var(--table-border, 1px solid var(--color-contrast-200));\n\n /* ── Tokens consumed by native th/td in the shadow table ────────────── */\n --_cell-padding: var(--table-cell-padding, var(--size-4) var(--size-5));\n --_cell-font-size: var(--table-cell-font-size, var(--text-sm));\n --_cell-color: var(--table-cell-color, var(--color-contrast-800));\n --_th-bg: var(--table-header-bg, color-mix(in srgb, var(--color-contrast-100) 85%, transparent));\n --_th-color: var(--table-header-color, var(--_theme-content));\n --_th-font-weight: var(--font-semibold);\n --_th-font-size: var(--text-xs);\n --_row-hover-bg: var(--table-row-hover-bg, var(--color-contrast-100));\n --_stripe-bg: transparent;\n\n display: block;\n width: 100%;\n border-radius: var(--_radius);\n box-shadow: var(--_shadow);\n }\n\n /* ── Scroll container ────────────────────────────────────────────────── */\n\n .scroll-container {\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n\n /* ── Native table ─────────────────────────────────────────────────────── */\n\n table {\n width: 100%;\n table-layout: auto;\n border-spacing: 0;\n border-collapse: collapse;\n background: var(--table-bg, var(--color-canvas));\n }\n\n /* ── Caption ─────────────────────────────────────────────────────────── */\n\n caption {\n padding: var(--size-3) var(--size-5);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-align: start;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n caption-side: top;\n background: var(--_th-bg);\n }\n\n /* ── Native cells (live in shadow DOM — all styling goes here) ────────── */\n\n th,\n td {\n padding: var(--_cell-padding);\n font-size: var(--_cell-font-size);\n font-weight: normal;\n vertical-align: middle;\n color: var(--_cell-color);\n text-align: start;\n background: transparent;\n border-bottom: var(--_border);\n transition: background var(--duration-150) var(--ease-in-out);\n }\n\n /* Last row in each section — remove separator */\n tbody tr:last-child th,\n tbody tr:last-child td,\n tfoot tr:last-child th,\n tfoot tr:last-child td {\n border-bottom: none;\n }\n\n /* ── Header / footer rows ─────────────────────────────────────────────── */\n\n thead th,\n thead td,\n tfoot th,\n tfoot td {\n font-size: var(--_th-font-size);\n font-weight: var(--_th-font-weight);\n color: var(--_th-color);\n background: var(--_th-bg) !important;\n border-bottom: var(--border-2) solid var(--color-contrast-200);\n backdrop-filter: blur(var(--blur-md)) saturate(140%);\n }\n\n thead th {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n /* ── Row hover (body only) ────────────────────────────────────────────── */\n\n tbody tr:hover th,\n tbody tr:hover td {\n background: var(--_row-hover-bg);\n }\n\n /* ── Striped rows ─────────────────────────────────────────────────────── */\n\n tbody tr:nth-child(even) th,\n tbody tr:nth-child(even) td {\n background: var(--_stripe-bg);\n }\n\n tbody tr:nth-child(even):hover th,\n tbody tr:nth-child(even):hover td {\n background: var(--_row-hover-bg);\n }\n}\n\n/* ── Loading state ───────────────────────────────────────────────────────── */\n\n@layer buildit.states {\n :host([loading]) {\n cursor: wait;\n }\n\n :host([loading]) table {\n pointer-events: none;\n opacity: 0.5;\n transition: opacity var(--duration-200) var(--ease-in-out);\n }\n}\n\n/* ── Variants ────────────────────────────────────────────────────────────── */\n\n@layer buildit.variants {\n /* Striped: flip --_stripe-bg token on */\n :host([striped]) {\n --_stripe-bg: var(--table-stripe-bg, var(--color-contrast-50));\n }\n\n /* Bordered: border and radius on the host itself; overflow:hidden on the\n scroll-container would block position:sticky so we avoid it there. */\n :host([bordered]) {\n overflow: hidden;\n border: var(--_border);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-xs);\n }\n\n /* Clip painted table sections (caption/thead/tbody/tfoot) to the same radius\n without interfering with scrolling or sticky headers. */\n :host([bordered]) .scroll-container {\n border-radius: inherit;\n clip-path: inset(0 round var(--_radius));\n }\n\n /* Color theme: remap header tokens from the theme mixin's --_theme-* vars */\n :host([color]) {\n --_th-color: var(--_theme-base);\n }\n\n /* Sticky: clamp height and let the single scroll container handle both axes.\n position:sticky on thead th works correctly when the scrolling ancestor\n is the same element in both x and y — two nested overflow containers break it. */\n :host([sticky]) .scroll-container {\n max-height: var(--table-sticky-max-height, 24rem);\n overflow-y: auto;\n }\n\n /* Pin thead cells to the top of the scroll container */\n :host([sticky]) thead th,\n :host([sticky]) thead td {\n position: sticky;\n top: 0;\n z-index: 10;\n background: var(\n --table-sticky-header-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 94%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 94%, transparent)\n )\n );\n backdrop-filter: blur(var(--table-sticky-blur, var(--blur-md))) saturate(140%);\n will-change: backdrop-filter;\n }\n}\n\n/* ── Size utilities ──────────────────────────────────────────────────────── */\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --_cell-padding: var(--size-2) var(--size-3);\n --_cell-font-size: var(--text-xs);\n }\n\n :host([size='lg']) {\n --_cell-padding: var(--size-5) var(--size-8);\n --_cell-font-size: var(--text-base);\n }\n}\n","import { aria, defineComponent, effect, html, onMount } from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport componentStyles from './table.css?inline';\n\n/* ── Types ───────────────────────────────────────────────────────────────── */\n\n/** Table component properties */\nexport type BitTableProps = {\n /** Show borders between rows and around the table */\n bordered?: boolean;\n /** Visible caption text — also used as accessible label for the table group */\n caption?: string;\n /** Theme color applied to the header row background */\n color?: ThemeColor;\n /** Show a loading / busy state */\n loading?: boolean;\n /** Component size: 'sm' | 'md' | 'lg' */\n size?: ComponentSize;\n /** Stick the header row to the top while the body scrolls */\n sticky?: boolean;\n /** Alternating row stripe background */\n striped?: boolean;\n};\n\n/* ── Sub-components (no shadow DOM) ─────────────────────────────────────── */\n\n// bit-tr, bit-th, bit-td are lightweight markers in the light DOM.\n// bit-table reads them and builds a fully-native shadow <table> so that\n// browser features that only work on real table elements (colspan/rowspan,\n// position:sticky on <th>, table layout algorithm) all work correctly.\n\nif (!customElements.get('bit-tr')) customElements.define('bit-tr', class extends HTMLElement {});\n\nif (!customElements.get('bit-th')) customElements.define('bit-th', class extends HTMLElement {});\n\nif (!customElements.get('bit-td')) customElements.define('bit-td', class extends HTMLElement {});\n\nexport const TR_TAG = 'bit-tr';\nexport const TH_TAG = 'bit-th';\nexport const TD_TAG = 'bit-td';\n\n/* ── Table proxy helpers ─────────────────────────────────────────────────── */\n\n// Attributes on bit-th / bit-td that should be forwarded to the native cell.\nconst CELL_ATTRS = ['colspan', 'rowspan', 'scope', 'headers', 'abbr', 'axis', 'align', 'valign', 'width'];\n\n/**\n * Build (or rebuild) the entire native shadow table from the current light-DOM\n * bit-tr / bit-th / bit-td structure. Returns a cleanup function that\n * disconnects all MutationObservers created during the build.\n */\nfunction buildTable(\n host: HTMLElement,\n thead: HTMLTableSectionElement,\n tbody: HTMLTableSectionElement,\n tfoot: HTMLTableSectionElement,\n): () => void {\n const observers: MutationObserver[] = [];\n\n // Clear all sections first\n thead.textContent = '';\n tbody.textContent = '';\n tfoot.textContent = '';\n\n /**\n * Mirror one bit-td / bit-th → native td / th, keeping text content and\n * relevant attributes in sync via a MutationObserver.\n */\n function mirrorCell(source: Element, into: HTMLTableSectionElement | HTMLTableRowElement): HTMLTableCellElement {\n const isHeader = source.localName === 'bit-th';\n const cell = document.createElement(isHeader ? 'th' : 'td');\n\n // Forward allowed attributes\n for (const attr of CELL_ATTRS) {\n const val = source.getAttribute(attr);\n\n if (val !== null) cell.setAttribute(attr, val);\n }\n\n cell.textContent = source.textContent ?? '';\n\n // Keep text + attrs in sync\n const obs = new MutationObserver(() => {\n cell.textContent = source.textContent ?? '';\n for (const attr of CELL_ATTRS) {\n const val = source.getAttribute(attr);\n\n if (val !== null) cell.setAttribute(attr, val);\n else cell.removeAttribute(attr);\n }\n });\n\n obs.observe(source, { attributes: true, characterData: true, childList: true, subtree: true });\n observers.push(obs);\n\n into.appendChild(cell);\n\n return cell;\n }\n\n /**\n * Mirror one bit-tr → native tr with all its cells.\n */\n function mirrorRow(source: Element, section: HTMLTableSectionElement): void {\n const tr = document.createElement('tr');\n\n for (const child of source.children) {\n if (child.localName === 'bit-th' || child.localName === 'bit-td') {\n mirrorCell(child, tr);\n }\n }\n section.appendChild(tr);\n }\n\n // Walk all direct children of bit-table\n for (const child of host.children) {\n if (child.localName !== 'bit-tr') continue;\n\n if (child.hasAttribute('head')) {\n mirrorRow(child, thead);\n } else if (child.hasAttribute('foot')) {\n mirrorRow(child, tfoot);\n } else {\n mirrorRow(child, tbody);\n }\n }\n\n return () => {\n for (const obs of observers) obs.disconnect();\n };\n}\n\n/**\n * Accessible data table. Compose with `<bit-tr>`, `<bit-th>`, and `<bit-td>`.\n * Add `head` to header rows and `foot` to footer rows.\n *\n * @element bit-table\n *\n * @attr {string} caption - Visible caption and accessible label\n * @attr {string} color - Header theme: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {boolean} bordered - Outer border and radius\n * @attr {boolean} loading - Busy / loading state\n * @attr {string} size - Size variant: 'sm' | 'md' | 'lg'\n * @attr {boolean} sticky - Stick header cells during vertical scroll\n * @attr {boolean} striped - Alternating row backgrounds\n *\n * @part scroll - Horizontally-scrollable container\n * @part table - The native `<table>` element\n * @part head - The native `<thead>` element\n * @part body - The native `<tbody>` element\n * @part foot - The native `<tfoot>` element\n *\n * @cssprop --table-bg - Table background\n * @cssprop --table-border - Full border shorthand for row separators (e.g. `2px solid red`)\n * @cssprop --table-header-bg - Header row background\n * @cssprop --table-header-color - Header cell text color\n * @cssprop --table-cell-padding - Cell padding (e.g. `0.75rem 1rem`)\n * @cssprop --table-cell-font-size - Cell font size\n * @cssprop --table-cell-color - Body cell text color\n * @cssprop --table-stripe-bg - Stripe row background\n * @cssprop --table-row-hover-bg - Row hover background\n * @cssprop --table-radius - Outer corner radius\n * @cssprop --table-shadow - Outer box shadow\n * @cssprop --table-sticky-max-height - Max height when `sticky` is active (default `24rem`)\n *\n * @example\n * ```html\n * <bit-table caption=\"Members\" striped bordered color=\"primary\">\n * <bit-tr head>\n * <bit-th scope=\"col\">Name</bit-th>\n * <bit-th scope=\"col\">Role</bit-th>\n * </bit-tr>\n * <bit-tr><bit-td>Alice</bit-td><bit-td>Admin</bit-td></bit-tr>\n * <bit-tr><bit-td>Bob</bit-td><bit-td>Editor</bit-td></bit-tr>\n * <bit-tr foot><bit-td colspan=\"2\">2 members</bit-td></bit-tr>\n * </bit-table>\n * ```\n */\nexport const TABLE_TAG = defineComponent<BitTableProps>({\n props: {\n bordered: { default: false, type: Boolean },\n caption: { default: undefined },\n color: { default: undefined },\n loading: { default: false, type: Boolean },\n size: { default: undefined },\n sticky: { default: false, type: Boolean },\n striped: { default: false, type: Boolean },\n },\n setup({ host, props }) {\n aria({\n busy: () => props.loading.value,\n label: () => props.caption.value ?? null,\n });\n // Build the fully-native shadow table via DOM APIs (not innerHTML) to avoid\n // HTML-parser foster-parenting which would eject <slot> elements from table\n // contexts. All three issues — color themes, sticky headers, colspan —\n // require real <thead>/<tbody>/<tfoot>/<tr>/<th>/<td> in the shadow tree.\n onMount(() => {\n const scrollContainer = host.shadowRoot!.querySelector('.scroll-container')!;\n\n const table = document.createElement('table');\n const captionEl = document.createElement('caption');\n const thead = document.createElement('thead');\n const tbody = document.createElement('tbody');\n const tfoot = document.createElement('tfoot');\n\n // Keep part assignment imperative so template typing stays strict.\n scrollContainer.setAttribute('part', 'scroll');\n\n table.setAttribute('part', 'table');\n thead.setAttribute('part', 'head');\n tbody.setAttribute('part', 'body');\n tfoot.setAttribute('part', 'foot');\n table.append(captionEl, thead, tbody, tfoot);\n scrollContainer.appendChild(table);\n // Sync caption text from prop\n effect(() => {\n captionEl.hidden = !(captionEl.textContent = props.caption.value ?? '');\n });\n\n // Initial build\n let cleanupCellObservers = buildTable(host, thead, tbody, tfoot);\n // Rebuild whenever direct children change (rows added / removed / reordered)\n const structureObserver = new MutationObserver(() => {\n cleanupCellObservers();\n cleanupCellObservers = buildTable(host, thead, tbody, tfoot);\n });\n\n structureObserver.observe(host, { childList: true });\n\n return () => {\n structureObserver.disconnect();\n cleanupCellObservers();\n };\n });\n\n return html`<div class=\"scroll-container\"></div>`;\n },\n styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n tag: 'bit-table',\n});\n","/* ========================================\n Base Styles & Defaults\n ======================================== */\n\n:host {\n /* Internal variables with CSS custom property fallbacks */\n --_size: var(--text-size, var(--text-base));\n --_weight: var(--text-weight, var(--font-normal));\n --_color: var(--text-color, var(--text-color-body));\n --_line-height: var(--text-line-height, var(--leading-normal));\n --_letter-spacing: var(--text-letter-spacing, normal);\n\n display: block;\n font-size: var(--_size);\n font-weight: var(--_weight);\n line-height: var(--_line-height);\n color: var(--_color);\n letter-spacing: var(--_letter-spacing);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n/* ========================================\n Unlayered display overrides\n These must live outside any @layer so they can beat the unlayered\n display: block on :host. Same cascade rule that was fixed for [lines].\n ======================================== */\n\n/* Multi-line truncation */\n:host([lines]) {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n overflow: hidden;\n -webkit-line-clamp: var(--_lines);\n}\n\n/* Inline semantic tags — but not when align/truncate force block layout */\n:host(:is([as='span'], [as='label'], [as='code']):not([align], [truncate])) {\n display: inline;\n}\n\n/* ========================================\n Variant Styles\n ======================================== */\n\n/* Body (default) — uses base defaults above */\n\n/* Heading\n Default size: --heading-md (24px)\n Letter-spacing: --tracking-header (-0.025em) per theme guidelines\n Line-height: --leading-tight (1.15) for display headings */\n:host([variant='heading']) {\n --_size: var(--text-size, var(--heading-md));\n --_weight: var(--text-weight, var(--font-semibold));\n --_color: var(--text-color, var(--text-color-heading));\n --_line-height: var(--text-line-height, var(--leading-tight));\n --_letter-spacing: var(--text-letter-spacing, var(--tracking-header));\n}\n\n/* Label — slightly tighter line-height for UI labels */\n:host([variant='label']) {\n --_size: var(--text-size, var(--text-sm));\n --_weight: var(--text-weight, var(--font-medium));\n --_color: var(--text-color, var(--text-color-heading));\n --_line-height: var(--text-line-height, var(--leading-snug));\n}\n\n/* Caption */\n:host([variant='caption']) {\n --_size: var(--text-size, var(--text-sm));\n --_color: var(--text-color, var(--text-color-secondary));\n}\n\n/* Overline */\n:host([variant='overline']) {\n --_size: var(--text-size, var(--text-xs));\n --_weight: var(--text-weight, var(--font-semibold));\n --_line-height: var(--text-line-height, var(--leading-none));\n --_letter-spacing: var(--text-letter-spacing, 0.08em);\n\n text-transform: uppercase;\n}\n\n/* Code */\n:host([variant='code']) {\n --_size: var(--text-size, var(--text-sm));\n\n font-family: var(--font-mono, monospace);\n}\n\n/* ========================================\n Size Variants — body scale (--text-*)\n Used by all variants except heading.\n ======================================== */\n\n:host([size='xs']) {\n --_size: var(--text-xs);\n}\n\n:host([size='sm']) {\n --_size: var(--text-sm);\n}\n\n:host([size='md']) {\n --_size: var(--text-base);\n}\n\n:host([size='lg']) {\n --_size: var(--text-lg);\n}\n\n:host([size='xl']) {\n --_size: var(--text-xl);\n}\n\n:host([size='2xl']) {\n --_size: var(--text-2xl);\n}\n\n/* ========================================\n Size Variants — heading scale (--heading-*)\n Compound selectors override the body-scale rules above when\n variant=\"heading\" and a size is also provided.\n ======================================== */\n\n:host([variant='heading'][size='xs']) {\n --_size: var(--heading-xs);\n}\n\n:host([variant='heading'][size='sm']) {\n --_size: var(--heading-sm);\n}\n\n:host([variant='heading'][size='md']) {\n --_size: var(--heading-md);\n}\n\n:host([variant='heading'][size='lg']) {\n --_size: var(--heading-lg);\n}\n\n:host([variant='heading'][size='xl']) {\n --_size: var(--heading-xl);\n}\n\n:host([variant='heading'][size='2xl']) {\n --_size: var(--heading-2xl);\n}\n\n/* ========================================\n Weight Variants\n ======================================== */\n\n:host([weight='normal']) {\n --_weight: var(--font-normal);\n}\n\n:host([weight='medium']) {\n --_weight: var(--font-medium);\n}\n\n:host([weight='semibold']) {\n --_weight: var(--font-semibold);\n}\n\n:host([weight='bold']) {\n --_weight: var(--font-bold);\n}\n\n/* ========================================\n Color Variants\n Semantic colors map to --text-color-* tokens.\n Theme colors map to --color-* base tokens.\n ======================================== */\n\n:host([color='primary']) {\n --_color: var(--color-primary);\n}\n\n:host([color='secondary']) {\n --_color: var(--color-secondary);\n}\n\n:host([color='info']) {\n --_color: var(--color-info);\n}\n\n:host([color='success']) {\n --_color: var(--color-success);\n}\n\n:host([color='warning']) {\n --_color: var(--color-warning);\n}\n\n:host([color='error']) {\n --_color: var(--color-error);\n}\n\n/* Semantic text colors */\n:host([color='heading']) {\n --_color: var(--text-color-heading); /* --color-contrast-900 */\n}\n\n:host([color='body']) {\n --_color: var(--text-color-body); /* --color-contrast-800 */\n}\n\n:host([color='muted']) {\n --_color: var(--text-color-secondary); /* --color-contrast-600 — AA compliant */\n}\n\n:host([color='tertiary']) {\n --_color: var(--text-color-tertiary); /* --color-contrast-500 — AA for large text */\n}\n\n:host([color='disabled']) {\n --_color: var(--text-color-disabled); /* --color-contrast-400 */\n}\n\n:host([color='contrast']) {\n --_color: var(--text-color-contrast); /* --color-contrast-100 */\n}\n\n@layer buildit.utilities {\n /* ========================================\n Alignment\n ======================================== */\n\n :host([align]) {\n display: block;\n }\n\n :host([align='left']) {\n text-align: start;\n }\n\n :host([align='center']) {\n text-align: center;\n }\n\n :host([align='right']) {\n text-align: end;\n }\n\n :host([align='justify']) {\n text-align: justify;\n }\n\n /* ========================================\n Truncate (single-line)\n ======================================== */\n\n :host([truncate]) {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* ========================================\n Italic\n ======================================== */\n\n :host([italic]) {\n font-style: italic;\n }\n\n /* ========================================\n Block Display for Certain Tags\n ======================================== */\n\n :host([as='p']),\n :host([as='div']),\n :host(:is([as='h1'], [as='h2'], [as='h3'], [as='h4'], [as='h5'], [as='h6'])) {\n display: block;\n }\n\n /* Note: display: inline for span/label/code is handled outside this @layer\n (above) so it can override the unlayered :host { display: block }. */\n}\n","import { defineComponent, html, typed, watch } from '@vielzeug/craftit';\n\nimport styles from './text.css?inline';\n\n/** Text component properties */\nexport type BitTextProps = {\n /** Text alignment */\n align?: 'left' | 'center' | 'right' | 'justify';\n /** Semantic HTML element to render as — sets the correct ARIA role/level on the host */\n as?: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'code';\n /** Text color (semantic + theme colors) */\n color?:\n | 'primary'\n | 'secondary'\n | 'info'\n | 'success'\n | 'warning'\n | 'error'\n | 'heading'\n | 'body'\n | 'muted'\n | 'tertiary'\n | 'disabled'\n | 'contrast';\n /** Italic text style */\n italic?: boolean;\n /** Clamp text to N lines with an ellipsis (multi-line truncation) */\n lines?: number;\n /** Text size — maps to --text-* tokens for body variants and --heading-* tokens for the heading variant */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n /** Enable single-line text truncation with ellipsis */\n truncate?: boolean;\n /** Text semantic variant */\n variant?: 'body' | 'heading' | 'label' | 'caption' | 'overline' | 'code';\n /** Font weight */\n weight?: 'normal' | 'medium' | 'semibold' | 'bold';\n};\n\n/**\n * A typography component with semantic variants and responsive sizing.\n *\n * @element bit-text\n *\n * @attr {string} variant - Text variant: 'body' | 'heading' | 'label' | 'caption' | 'overline' | 'code'\n * @attr {string} size - Font size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'. Maps to --text-* tokens for body variants and --heading-* tokens for the heading variant.\n * @attr {string} weight - Font weight: 'normal' | 'medium' | 'semibold' | 'bold'\n * @attr {string} color - Text color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error' | 'heading' | 'body' | 'muted' | 'tertiary' | 'disabled' | 'contrast'\n * @attr {string} align - Text alignment: 'left' | 'center' | 'right' | 'justify'\n * @attr {boolean} truncate - Truncate text with ellipsis when it overflows (single-line)\n * @attr {number} lines - Clamp to N lines with ellipsis (multi-line truncation)\n * @attr {boolean} italic - Italic text style\n * @attr {string} as - Semantic HTML element: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'code'\n *\n * @slot - Text content\n *\n * @cssprop --text-size - Font size\n * @cssprop --text-weight - Font weight\n * @cssprop --text-color - Text color\n * @cssprop --text-line-height - Line height\n * @cssprop --text-letter-spacing - Letter spacing\n *\n * @example\n * ```html\n * <bit-text variant=\"heading\" size=\"3xl\" weight=\"bold\">Welcome</bit-text>\n * <bit-text as=\"h2\" variant=\"heading\" size=\"xl\">Section title</bit-text>\n * <bit-text color=\"primary\" weight=\"semibold\">Important notice</bit-text>\n * <bit-text variant=\"code\">npm install</bit-text>\n * <bit-text lines=\"2\">Long paragraph that clamps at two lines…</bit-text>\n * ```\n */\n\nexport const TEXT_TAG = defineComponent<BitTextProps>({\n props: {\n align: typed<BitTextProps['align']>(undefined),\n as: typed<BitTextProps['as']>(undefined),\n color: typed<BitTextProps['color']>(undefined),\n italic: typed<boolean>(false),\n lines: typed<number | undefined>(undefined, { type: Number }),\n size: typed<BitTextProps['size']>(undefined),\n truncate: typed<boolean>(false),\n variant: typed<BitTextProps['variant']>(undefined),\n weight: typed<BitTextProps['weight']>(undefined),\n },\n setup({ host, props }) {\n // Single watcher drives both role + aria-level from `as`.\n // h1–h6 → role=\"heading\" + aria-level; everything else → remove both.\n watch(\n props.as,\n (tag) => {\n const match = /^h([1-6])$/.exec((tag as string | undefined) ?? '');\n\n if (match) {\n host.setAttribute('role', 'heading');\n host.setAttribute('aria-level', match[1]);\n } else {\n host.removeAttribute('role');\n host.removeAttribute('aria-level');\n }\n },\n { immediate: true },\n );\n // Drive --_lines on the host so the CSS line-clamp rule works.\n watch(\n props.lines,\n (n) => {\n if (n != null) host.style.setProperty('--_lines', String(n));\n else host.style.removeProperty('--_lines');\n },\n { immediate: true },\n );\n\n return html`<slot></slot>`;\n },\n styles: [styles],\n tag: 'bit-text',\n});\n","@layer buildit.base {\n :host {\n display: flex;\n flex-direction: column;\n gap: var(--size-2);\n width: 100%;\n }\n\n ::slotted(bit-accordion-item) {\n width: 100%;\n }\n}\n\n@layer buildit.variants {\n /* ========================================\n Visual Variants\n ======================================== */\n\n /* Bordered variant */\n :host([variant='bordered']) {\n gap: var(--size-2);\n }\n\n /* Text variant - borderless with dividers */\n :host([variant='text']) {\n gap: 0;\n }\n\n :host([variant='text']) ::slotted(bit-accordion-item:not(:last-child)) {\n border-bottom: 1px solid var(--color-contrast-200);\n }\n\n /* Contained variants - grouped appearance */\n :host([variant='solid']),\n :host([variant='flat']),\n :host([variant='glass']),\n :host([variant='frost']) {\n gap: 0;\n padding: var(--size-2);\n border-radius: var(--rounded-lg);\n }\n\n /* Solid variant (default) */\n :host([variant='solid']) {\n background: var(--color-contrast-50);\n border: var(--border) solid var(--color-contrast-200);\n box-shadow: var(--shadow-xs);\n }\n\n /* Flat variant */\n :host([variant='flat']) {\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n box-shadow: var(--inset-shadow-xs);\n }\n\n /* Glass & Frost - Shared styles */\n :host([variant='glass']),\n :host([variant='frost']) {\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n /* Glass variant - translucent with blur */\n :host([variant='glass']) {\n background: color-mix(in srgb, var(--color-secondary) 30%, var(--color-contrast) 10%);\n }\n\n /* Frost variant - canvas-based transparency */\n :host([variant='frost']) {\n background: color-mix(in srgb, var(--color-canvas) 55%, transparent);\n }\n\n /* Nested item border radius for glass and frost variants */\n :host(:is([variant='glass'], [variant='frost'])) ::slotted(bit-accordion-item) {\n border-radius: 0;\n }\n\n :host(:is([variant='glass'], [variant='frost'])) ::slotted(bit-accordion-item:first-child) {\n border-radius: var(--rounded-lg) var(--rounded-lg) 0 0;\n }\n\n :host(:is([variant='glass'], [variant='frost'])) ::slotted(bit-accordion-item:last-child) {\n border-radius: 0 0 var(--rounded-lg) var(--rounded-lg);\n }\n\n :host(:is([variant='glass'], [variant='frost'])) ::slotted(bit-accordion-item:only-child) {\n border-radius: var(--rounded-lg);\n }\n}\n","import {\n computed,\n createContext,\n defineComponent,\n handle,\n html,\n typed,\n provide,\n type ReadonlySignal,\n} from '@vielzeug/craftit';\n\nimport type { ComponentSize, VisualVariant } from '../../types';\n\n/** Context provided by bit-accordion to its bit-accordion-item children. */\nexport type AccordionContext = {\n notifyExpand: (expandedItem: HTMLElement) => void;\n selectionMode: ReadonlySignal<'single' | 'multiple' | undefined>;\n size: ReadonlySignal<ComponentSize | undefined>;\n variant: ReadonlySignal<VisualVariant | undefined>;\n};\n/** Injection key for the accordion context. */\nexport const ACCORDION_CTX = createContext<AccordionContext>('AccordionContext');\n\nimport styles from './accordion.css?inline';\n\n/** Accordion component properties */\n\nexport type BitAccordionEvents = {\n change: { expandedItem: HTMLElement };\n};\n\nexport type BitAccordionProps = {\n /** Selection mode (single = only one opens, multiple = multiple can be open) */\n selectionMode?: 'single' | 'multiple';\n /** Size for all items (propagated via context) */\n size?: ComponentSize;\n /** Visual variant for all items (propagated via context) */\n variant?: VisualVariant;\n};\n\n/**\n * A container for accordion items with single or multiple selection modes.\n *\n * @element bit-accordion\n *\n * @attr {string} selection-mode - Selection mode: 'single' | 'multiple'\n * @attr {string} size - Size for all items: 'sm' | 'md' | 'lg' (propagated to children)\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'text' | 'glass' | 'frost' (propagated to children)\n *\n * @fires expand - Emitted when an item expands\n * @fires change - Emitted when selection changes (single mode)\n *\n * @slot - Accordion item elements (bit-accordion-item)\n *\n * @example\n * ```html\n * <bit-accordion selection-mode=\"single\"><bit-accordion-item>...</bit-accordion-item></bit-accordion>\n * <bit-accordion variant=\"frost\" size=\"lg\"><bit-accordion-item>...</bit-accordion-item></bit-accordion>\n * ```\n */\n\nexport const ACCORDION_TAG = defineComponent<BitAccordionProps, BitAccordionEvents>({\n props: {\n selectionMode: typed<BitAccordionProps['selectionMode']>(undefined),\n size: typed<BitAccordionProps['size']>(undefined),\n variant: typed<BitAccordionProps['variant']>(undefined),\n },\n setup({ emit, host, props }) {\n const notifyExpand = (expandedItem: HTMLElement) => {\n if (props.selectionMode.value === 'single') {\n host.querySelectorAll('bit-accordion-item').forEach((item) => {\n if (item !== expandedItem && item.hasAttribute('expanded')) {\n item.removeAttribute('expanded');\n }\n });\n emit('change', { expandedItem });\n }\n };\n\n provide(ACCORDION_CTX, {\n notifyExpand,\n selectionMode: computed(() => props.selectionMode.value),\n size: props.size,\n variant: props.variant,\n });\n\n // Listen for expanded events bubbling up from child accordion-items.\n // This allows single-selection management without tight coupling via context calls.\n const handleExpand = (e: Event) => notifyExpand(e.target as HTMLElement);\n\n handle(host, 'expand', handleExpand);\n // Group-level arrow-key navigation between accordion item summaries (WAI-ARIA Accordion pattern).\n handle(host, 'keydown', (e: KeyboardEvent) => {\n if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.key !== 'Home' && e.key !== 'End') return;\n\n const items = [...host.querySelectorAll<HTMLElement>('bit-accordion-item:not([disabled])')];\n const summaries = items\n .map((item) => item.shadowRoot?.querySelector<HTMLElement>('summary'))\n .filter(Boolean) as HTMLElement[];\n\n if (!summaries.length) return;\n\n const focused = summaries.indexOf(document.activeElement as HTMLElement);\n\n if (focused === -1) return; // the focus is not on a summary — let native handling proceed\n\n let next = focused;\n\n if (e.key === 'ArrowDown') next = (focused + 1) % summaries.length;\n else if (e.key === 'ArrowUp') next = (focused - 1 + summaries.length) % summaries.length;\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = summaries.length - 1;\n\n e.preventDefault();\n summaries[next]?.focus();\n });\n\n return html`<slot></slot>`;\n },\n styles: [styles],\n tag: 'bit-accordion',\n});\n","@layer buildit.base {\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n\n --tabs-transition: var(--transition-normal);\n --tabs-radius: var(--rounded-lg);\n }\n\n .tablist-wrapper {\n position: relative;\n flex-shrink: 0;\n }\n\n [role='tablist'] {\n position: relative;\n display: flex;\n gap: var(--tabs-tab-gap, var(--size-1));\n align-items: stretch;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n [role='tablist']::-webkit-scrollbar {\n display: none;\n }\n\n .indicator {\n position: absolute;\n bottom: 0;\n height: 2px;\n pointer-events: none;\n background: var(--tabs-indicator-color, var(--_theme-base));\n border-radius: var(--rounded-full);\n transition:\n left var(--tabs-transition),\n width var(--tabs-transition);\n }\n\n .panels {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n}\n\n@layer buildit.orientation {\n /* ─── vertical orientation ─── */\n :host([orientation='vertical']) {\n flex-direction: row;\n align-items: flex-start;\n }\n\n :host([orientation='vertical']) .tablist-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n :host([orientation='vertical']) [role='tablist'] {\n flex-direction: column;\n width: max-content;\n overflow-x: unset;\n overflow-y: auto;\n }\n\n :host([orientation='vertical']) .indicator {\n inset-inline-start: 0;\n\n /* Reposition indicator to inline-start side for vertical */\n bottom: unset;\n width: 2px;\n height: unset;\n transition:\n top var(--tabs-transition),\n height var(--tabs-transition);\n }\n}\n\n@layer buildit.variants {\n /* ─── solid (default) ─── */\n :host,\n :host([variant='solid']) {\n --tabs-tab-gap: var(--size-1);\n }\n\n :host [role='tablist'],\n :host([variant='solid']) [role='tablist'] {\n padding: var(--size-1);\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-radius: var(--tabs-radius);\n }\n\n :host .indicator,\n :host([variant='solid']) .indicator {\n display: none;\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) {\n overflow: hidden;\n background: var(--color-contrast-100);\n border: var(--border) solid var(--color-contrast-200);\n border-radius: var(--tabs-radius);\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='flat']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--color-contrast-200);\n border-radius: 0;\n }\n\n :host([variant='flat']) .indicator {\n display: none;\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) [role='tablist'] {\n gap: var(--size-1);\n padding: var(--size-1);\n background: transparent;\n border: var(--border) solid var(--color-contrast-200);\n border-bottom: none;\n border-radius: var(--tabs-radius) var(--tabs-radius) 0 0;\n }\n\n :host([variant='bordered']) .indicator {\n display: none;\n }\n\n :host([variant='bordered']) .panels {\n border: var(--border) solid var(--color-contrast-200);\n border-radius: 0 0 var(--tabs-radius) var(--tabs-radius);\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) [role='tablist'] {\n gap: var(--size-1);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 0;\n }\n\n :host([variant='ghost']) .indicator {\n display: none;\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) [role='tablist'] {\n padding: var(--size-1);\n background: color-mix(in srgb, var(--color-secondary) 20%, transparent);\n border: var(--border) solid color-mix(in srgb, var(--color-secondary-contrast) 15%, transparent);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n :host([variant='glass']) .indicator {\n display: none;\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) [role='tablist'] {\n padding: var(--size-1);\n background: color-mix(in srgb, var(--color-canvas) 55%, transparent);\n border: var(--border) solid color-mix(in srgb, var(--color-contrast-300) 50%, transparent);\n border-radius: var(--tabs-radius);\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='frost']) .indicator {\n display: none;\n }\n\n /* ─── size variants ─── */\n :host([size='sm']) {\n --tabs-tab-size: var(--text-xs);\n --tabs-tab-padding: var(--size-1) var(--size-3);\n }\n\n :host(:not([size])),\n :host([size='md']) {\n --tabs-tab-size: var(--text-sm);\n --tabs-tab-padding: var(--size-1-5) var(--size-4);\n }\n\n :host([size='lg']) {\n --tabs-tab-size: var(--text-base);\n --tabs-tab-padding: var(--size-2) var(--size-5);\n }\n}\n","import {\n computed,\n createContext,\n defineComponent,\n handle,\n html,\n onMount,\n provide,\n type ReadonlySignal,\n ref,\n signal,\n watch,\n} from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { colorThemeMixin } from '../../styles';\n\n/** Context provided by bit-tabs to its bit-tab-item and bit-tab-panel children. */\nexport type TabsContext = {\n color: ReadonlySignal<ThemeColor | undefined>;\n orientation: ReadonlySignal<'horizontal' | 'vertical'>;\n size: ReadonlySignal<ComponentSize | undefined>;\n value: ReadonlySignal<string | undefined>;\n variant: ReadonlySignal<VisualVariant | undefined>;\n};\n/** Injection key for the tabs context. */\nexport const TABS_CTX = createContext<TabsContext>('TabsContext');\n\nimport styles from './tabs.css?inline';\n\nexport type BitTabsEvents = {\n change: { value: string };\n};\n\nexport type BitTabsProps = {\n /**\n * Keyboard activation mode.\n * - `'auto'` (default): Selecting a tab on arrow-key focus immediately activates it (ARIA recommendation for most cases).\n * - `'manual'`: Arrow keys only move focus; the user must press Enter or Space to activate the focused tab.\n */\n activation?: 'auto' | 'manual';\n /** Theme color */\n color?: ThemeColor;\n /** Accessible label for the tablist (passed as aria-label). Use when there is no visible heading labelling the tabs. */\n label?: string;\n /** Tab list orientation */\n orientation?: 'horizontal' | 'vertical';\n /** Component size */\n size?: ComponentSize;\n /** Currently selected tab value */\n value?: string;\n /** Visual style variant */\n variant?: VisualVariant;\n};\n\n/**\n * Tabs container. Manages tab selection and syncs state to child tab items and panels.\n *\n * @element bit-tabs\n *\n * @attr {string} value - The value of the currently selected tab\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'ghost' | 'glass' | 'frost'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @fires change - Emitted when the active tab changes, detail: { value: string }\n *\n * @slot tabs - Place `bit-tab-item` elements here\n * @slot - Place `bit-tab-panel` elements here\n *\n * @example\n * ```html\n * <bit-tabs value=\"tab1\" variant=\"underline\">\n * <bit-tab-item slot=\"tabs\" value=\"tab1\">Overview</bit-tab-item>\n * <bit-tab-item slot=\"tabs\" value=\"tab2\">Settings</bit-tab-item>\n * <bit-tab-panel value=\"tab1\"><p>Overview content</p></bit-tab-panel>\n * <bit-tab-panel value=\"tab2\"><p>Settings content</p></bit-tab-panel>\n * </bit-tabs>\n * ```\n */\nexport const TABS_TAG = defineComponent<BitTabsProps, BitTabsEvents>({\n props: {\n activation: { default: 'auto' },\n color: { default: undefined },\n label: { default: undefined },\n orientation: { default: 'horizontal' },\n size: { default: undefined },\n value: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const tablistRef = ref<HTMLElement>();\n const indicatorRef = ref<HTMLElement>();\n const selectedValue = signal<string | undefined>(props.value.value);\n const getTabs = () => [...host.querySelectorAll<HTMLElement>('bit-tab-item')];\n\n const setSelection = (value: string | undefined, shouldEmit = false) => {\n selectedValue.value = value;\n\n if (value == null) host.removeAttribute('value');\n else if (host.getAttribute('value') !== value) host.setAttribute('value', value);\n\n if (shouldEmit && value) emit('change', { value });\n };\n\n const ensureSelection = () => {\n const tabs = getTabs();\n\n // During initial connection, slotted tab items may not be assigned yet.\n // Keep current selection until tabs exist instead of falling back to undefined.\n if (tabs.length === 0) return;\n\n const current = selectedValue.value;\n const hasCurrent = current\n ? tabs.some((tab) => tab.getAttribute('value') === current && !tab.hasAttribute('disabled'))\n : false;\n\n if (hasCurrent) return;\n\n const firstEnabled = tabs.find((tab) => !tab.hasAttribute('disabled'))?.getAttribute('value') ?? undefined;\n\n setSelection(firstEnabled, false);\n };\n\n watch(props.value, (value) => {\n selectedValue.value = value;\n ensureSelection();\n });\n\n provide(TABS_CTX, {\n color: props.color,\n orientation: computed(() => props.orientation.value ?? 'horizontal'),\n size: props.size,\n value: selectedValue,\n variant: props.variant,\n });\n\n const moveIndicator = (activeTab: HTMLElement | undefined) => {\n const indicator = indicatorRef.value;\n const tablist = tablistRef.value;\n\n if (!indicator || !tablist || !activeTab) return;\n\n if (props.orientation.value === 'vertical') {\n const tabRect = activeTab.getBoundingClientRect();\n const listRect = tablist.getBoundingClientRect();\n\n indicator.style.top = `${tabRect.top - listRect.top + tablist.scrollTop}px`;\n indicator.style.height = `${tabRect.height}px`;\n indicator.style.left = '0';\n indicator.style.width = '';\n } else {\n const tabRect = activeTab.getBoundingClientRect();\n const listRect = tablist.getBoundingClientRect();\n\n indicator.style.left = `${tabRect.left - listRect.left + tablist.scrollLeft}px`;\n indicator.style.width = `${tabRect.width}px`;\n indicator.style.top = '';\n indicator.style.height = '';\n }\n };\n const triggerIndicator = () => {\n const value = selectedValue.value;\n\n if (!value) return;\n\n const activeTab = getTabs().find((t) => t.getAttribute('value') === value);\n\n moveIndicator(activeTab);\n };\n\n watch(selectedValue, () => requestAnimationFrame(triggerIndicator));\n\n const handleTabClick = (e: Event) => {\n const tab = (e.target as HTMLElement).closest('bit-tab-item') as HTMLElement | null;\n\n if (!tab || tab.hasAttribute('disabled')) return;\n\n // Guard: only respond to tab-items that belong to THIS tabs instance, not nested ones.\n if (tab.closest('bit-tabs') !== host) return;\n\n const value = tab.getAttribute('value');\n\n if (!value || value === selectedValue.value) return;\n\n setSelection(value, true);\n };\n const handleKeydown = (e: KeyboardEvent) => {\n const tabs = getTabs().filter((t) => !t.hasAttribute('disabled'));\n const current = tabs.findIndex((t) => t.getAttribute('value') === selectedValue.value);\n const isVertical = props.orientation.value === 'vertical';\n // eslint-disable-next-line no-useless-assignment\n let next = current;\n\n if (e.key === (isVertical ? 'ArrowDown' : 'ArrowRight')) next = (current + 1) % tabs.length;\n else if (e.key === (isVertical ? 'ArrowUp' : 'ArrowLeft')) next = (current - 1 + tabs.length) % tabs.length;\n else if (!isVertical && e.key === 'ArrowDown') next = (current + 1) % tabs.length;\n else if (!isVertical && e.key === 'ArrowUp') next = (current - 1 + tabs.length) % tabs.length;\n else if (e.key === 'Home') next = 0;\n else if (e.key === 'End') next = tabs.length - 1;\n else if (props.activation.value === 'manual' && (e.key === 'Enter' || e.key === ' ')) {\n // Manual mode: activate the currently focused tab\n const focused = tabs.find(\n (t) => t === document.activeElement || t.shadowRoot?.activeElement === document.activeElement,\n );\n const focusedValue = focused?.getAttribute('value');\n\n if (focusedValue && focusedValue !== selectedValue.value) {\n setSelection(focusedValue, true);\n }\n\n return;\n } else return;\n\n e.preventDefault();\n\n const value = tabs[next]?.getAttribute('value');\n\n if (value) {\n (tabs[next] as HTMLElement)?.focus();\n\n if (props.activation.value !== 'manual') {\n // Auto mode: activate on focus\n setSelection(value, true);\n }\n }\n };\n\n handle(host, 'click', handleTabClick);\n handle(host, 'keydown', handleKeydown);\n onMount(() => {\n const syncSelection = () => {\n ensureSelection();\n triggerIndicator();\n };\n const tabsSlot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"tabs\"]');\n\n if (tabsSlot) {\n tabsSlot.addEventListener('slotchange', syncSelection);\n }\n\n syncSelection();\n requestAnimationFrame(syncSelection);\n\n return () => {\n if (tabsSlot) {\n tabsSlot.removeEventListener('slotchange', syncSelection);\n }\n };\n });\n\n return html`\n <div class=\"tablist-wrapper\">\n <div\n role=\"tablist\"\n ref=${tablistRef}\n part=\"tablist\"\n :aria-orientation=\"${() => props.orientation.value}\"\n :aria-label=\"${() => props.label.value ?? null}\">\n <slot name=\"tabs\"></slot>\n </div>\n <div class=\"indicator\" ref=${indicatorRef} part=\"indicator\"></div>\n </div>\n <div class=\"panels\" part=\"panels\">\n <slot></slot>\n </div>\n `;\n },\n styles: [colorThemeMixin, styles],\n tag: 'bit-tabs',\n});\n","@layer buildit.base {\n /* ========================================\n Base Styles & Defaults\n ======================================== */\n\n :host {\n display: block;\n color: var(--accordion-item-body-color, var(--text-color-body));\n\n --accordion-details-radius: var(--rounded-lg);\n --accordion-item-transition: var(--transition-normal);\n }\n\n details {\n width: 100%;\n overflow: hidden;\n border-radius: var(--accordion-item-radius);\n transition: all var(--accordion-item-transition);\n }\n\n summary {\n position: relative;\n display: flex;\n gap: var(--size-4);\n align-items: center;\n min-height: var(--_touch-target);\n padding: var(--accordion-item-details-padding, var(--size-3) var(--size-4));\n font-size: var(--accordion-item-title);\n cursor: pointer;\n user-select: none;\n outline: none;\n list-style: none;\n background: var(--accordion-item-bg);\n border: var(--border) solid var(--accordion-item-border-color);\n border-radius: var(--accordion-details-radius);\n transition: all var(--accordion-item-transition);\n }\n\n summary::-webkit-details-marker {\n display: none;\n }\n\n summary:focus {\n outline: none;\n }\n\n summary:focus-visible {\n outline: var(--border-2) solid currentcolor;\n outline-offset: var(--border-2);\n box-shadow: 0 0 0 3px color-mix(in srgb, currentcolor 20%, transparent);\n }\n\n .header-content {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-width: 0;\n }\n\n .subtitle {\n font-size: var(--accordion-item-subtitle-size);\n line-height: var(--leading-normal);\n color: var(--accordion-item-subtitle-color, var(--text-color-secondary));\n }\n\n .title {\n overflow: hidden;\n text-overflow: ellipsis;\n font-weight: var(--font-medium);\n color: var(--accordion-item-title-color, var(--text-color-heading));\n white-space: nowrap;\n }\n\n .content-wrapper {\n display: grid;\n grid-template-rows: 0fr;\n font-size: var(--accordion-item-body);\n background: var(--accordion-item-bg);\n border-inline: 1px solid var(--accordion-item-border-color);\n border-bottom: 1px solid var(--accordion-item-border-color);\n border-radius: var(--accordion-summary-radius);\n transition: grid-template-rows var(--accordion-item-transition);\n }\n\n details[open] .content-wrapper {\n grid-template-rows: 1fr;\n }\n\n .content-inner {\n padding: var(--accordion-item-summary-padding, var(--size-2) var(--size-4));\n overflow: hidden;\n }\n}\n\n@layer buildit.variants {\n /* ========================================\n Visual Variants\n ======================================== */\n\n :host,\n :host([variant='solid']) {\n --accordion-item-bg: var(--color-contrast-50);\n --accordion-item-border-color: transparent;\n }\n\n :host summary:hover,\n :host([variant='solid']) summary:hover {\n --accordion-item-bg: var(--color-contrast-200);\n }\n\n :host([variant='flat']) {\n --accordion-item-bg: var(--color-contrast-100);\n }\n\n :host([variant='flat']) summary:hover {\n --accordion-item-bg: var(--color-contrast-200);\n }\n\n :host([variant='bordered']) {\n --accordion-item-bg: var(--color-contrast-100);\n --accordion-item-border-color: var(--color-contrast-300);\n\n box-shadow: var(--inset-shadow-xs), var(--shadow-2xs);\n }\n\n :host([variant='bordered']) summary:hover {\n background: var(--color-contrast-200);\n }\n\n :host([variant='outline']) {\n --accordion-item-bg: transparent;\n --accordion-item-border-color: var(--color-contrast-300);\n }\n\n :host([variant='outline']) summary:hover {\n background: var(--color-contrast-300);\n }\n\n :host([variant='ghost']) {\n --accordion-item-bg: transparent;\n --accordion-item-border-color: transparent;\n }\n\n :host([variant='ghost']) summary:hover {\n background: var(--color-contrast-200);\n }\n\n :host([variant='text']) {\n --accordion-item-bg: transparent;\n --accordion-item-border-color: transparent;\n }\n\n :host([variant='text']) summary:hover {\n background: transparent;\n }\n\n /* Glass & Frost - Shared Styles */\n :host([variant='glass']) details,\n :host([variant='frost']) details {\n border-radius: inherit;\n }\n\n :host([variant='glass']) summary,\n :host([variant='frost']) summary {\n border-radius: inherit;\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n :host([variant='glass']) .content-wrapper,\n :host([variant='frost']) .content-wrapper {\n border-radius: 0;\n backdrop-filter: blur(var(--blur-lg)) saturate(180%);\n }\n\n /* Glass */\n :host([variant='glass']) {\n --accordion-item-bg: color-mix(in srgb, var(--color-secondary) 30%, var(--color-contrast) 10%);\n --accordion-item-border-color: transparent;\n --accordion-item-title-color: color-mix(in srgb, var(--color-secondary-contrast) 100%, transparent);\n --accordion-item-subtitle-color: color-mix(in srgb, var(--color-secondary-contrast) 60%, transparent);\n --accordion-item-body-color: color-mix(in srgb, var(--color-secondary-contrast) 80%, transparent);\n }\n\n :host([variant='glass']) summary {\n text-shadow: var(--text-shadow-xs);\n }\n\n :host([variant='glass']) summary:hover {\n background: color-mix(in srgb, var(--color-secondary) 20%, transparent);\n }\n\n :host([variant='glass']) .content-wrapper {\n filter: brightness(1.05);\n }\n\n /* Frost */\n :host([variant='frost']) {\n --accordion-item-bg: color-mix(in srgb, var(--color-canvas) 55%, transparent);\n --accordion-item-border-color: transparent;\n }\n\n :host([variant='frost']) summary {\n text-shadow: var(--text-shadow-2xs);\n }\n\n :host([variant='frost']) summary:hover {\n background: color-mix(in srgb, var(--color-canvas) 20%, transparent);\n }\n\n /* ========================================\n Size Variants\n ======================================== */\n\n :host([size='sm']) {\n --accordion-item-details-padding: var(--size-2) var(--size-4);\n --accordion-item-summary-padding: var(--size-1) var(--size-5);\n --accordion-item-title: var(--text-sm);\n --accordion-item-subtitle-size: var(--text-xs);\n --accordion-item-body: var(--text-xs);\n }\n\n :host(:not([size])),\n :host([size='md']) {\n --accordion-item-details-padding: var(--size-3) var(--size-4);\n --accordion-item-summary-padding: var(--size-1) var(--size-5);\n --accordion-item-title: var(--text-base);\n --accordion-item-subtitle-size: var(--text-sm);\n --accordion-item-body: var(--text-sm);\n }\n\n :host([size='lg']) {\n --accordion-item-details-padding: var(--size-4) var(--size-4);\n --accordion-item-summary-padding: var(--size-1) var(--size-5);\n --accordion-item-title: var(--text-lg);\n --accordion-item-subtitle-size: var(--text-base);\n --accordion-item-body: var(--text-base);\n }\n\n /* ========================================\n States\n ======================================== */\n\n :host([disabled]) {\n pointer-events: none;\n opacity: 0.6;\n }\n\n /* ========================================\n Chevron Animation\n ======================================== */\n\n .chevron {\n width: var(--size-5);\n height: var(--size-5);\n margin-inline-start: auto;\n transition: transform var(--accordion-item-transition);\n }\n\n details[open] .chevron {\n transform: rotate(-90deg);\n }\n\n /* Expanded state - adjust border radius */\n :host([expanded]) {\n --accordion-details-radius: var(--rounded-lg) var(--rounded-lg) 0 0;\n --accordion-summary-radius: 0 0 var(--rounded-lg) var(--rounded-lg);\n }\n\n @media (forced-colors: active) {\n /* Default variant uses a transparent border — ensure a visible border\n renders in HCM so the summary is distinguishable from the body */\n summary {\n border-color: ButtonText;\n }\n }\n}\n","import {\n computed,\n defineComponent,\n handle,\n html,\n typed,\n inject,\n onMount,\n ref,\n syncContextProps,\n watch,\n} from '@vielzeug/craftit';\n\nimport type { ComponentSize, VisualVariant } from '../../types';\n\nimport { coarsePointerMixin } from '../../styles';\nimport { ACCORDION_CTX } from '../accordion/accordion';\nimport styles from './accordion-item.css?inline';\n\n/** Accordion item component properties */\n\nexport type BitAccordionItemEvents = {\n collapse: { expanded: boolean; item: HTMLElement };\n expand: { expanded: boolean; item: HTMLElement };\n};\n\nexport type BitAccordionItemProps = {\n /** Disable accordion item interaction */\n disabled?: boolean;\n /** Whether the item is expanded/open */\n expanded?: boolean;\n /** Item size */\n size?: ComponentSize;\n /** Visual style variant */\n variant?: VisualVariant;\n};\n\n/**\n * An individual accordion item with expand/collapse functionality using native details/summary.\n *\n * @element bit-accordion-item\n *\n * @attr {boolean} expanded - Whether the item is expanded/open\n * @attr {boolean} disabled - Disable accordion item interaction\n * @attr {string} size - Item size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text' | 'glass' | 'frost'\n *\n * @fires expand - Emitted when item expands\n * @fires collapse - Emitted when item collapses\n *\n * @slot prefix - Content before the title (e.g., icons)\n * @slot title - Main accordion item title\n * @slot subtitle - Optional subtitle text\n * @slot suffix - Content after the title (e.g., badges)\n * @slot - Accordion item content (shown when expanded)\n *\n * @cssprop --accordion-item-bg - Background color\n * @cssprop --accordion-item-border-color - Border color\n * @cssprop --accordion-item-title-color - Title text color\n * @cssprop --accordion-item-subtitle-color - Subtitle text color\n * @cssprop --accordion-item-body-color - Body text color\n * @cssprop --accordion-item-radius - Border radius\n * @cssprop --accordion-item-transition - Transition duration\n * @cssprop --accordion-item-title - Title font size\n * @cssprop --accordion-item-subtitle-size - Subtitle font size\n * @cssprop --accordion-item-body - Body font size\n * @cssprop --accordion-item-details-padding - Summary/header padding\n * @cssprop --accordion-item-summary-padding - Content padding\n *\n * @example\n * ```html\n * <bit-accordion-item><span slot=\"title\">Click to expand</span><p>Content</p></bit-accordion-item>\n * <bit-accordion-item expanded variant=\"bordered\"><span slot=\"title\">Title</span><p>Content</p></bit-accordion-item>\n * ```\n */\n\nexport const ACCORDION_ITEM_TAG = defineComponent<BitAccordionItemProps, BitAccordionItemEvents>({\n props: {\n disabled: typed<boolean>(false),\n expanded: typed<boolean>(false),\n size: typed<BitAccordionItemProps['size']>(undefined),\n variant: typed<BitAccordionItemProps['variant']>(undefined),\n },\n setup({ emit, host, props }) {\n // Inherit size/variant from a parent bit-accordion when present.\n const accordionCtx = inject(ACCORDION_CTX, undefined);\n\n syncContextProps(accordionCtx, props, ['size', 'variant']);\n\n const titleId = 'accordion-item-title';\n const detailsRef = ref<HTMLDetailsElement>();\n const summaryRef = ref<HTMLElement>();\n const handleToggle = () => {\n const isOpen = detailsRef.value?.open ?? false;\n\n // Notify accordion parent for single-selection management\n if (isOpen && !host.hasAttribute('expanded')) {\n host.setAttribute('expanded', '');\n emit('expand', { expanded: true, item: host });\n } else if (!isOpen && host.hasAttribute('expanded')) {\n host.removeAttribute('expanded');\n emit('collapse', { expanded: false, item: host });\n }\n };\n\n onMount(() => {\n const details = detailsRef.value;\n const summary = summaryRef.value;\n\n if (!details || !summary) return;\n\n // Sync details.open when expanded prop changes (needs live DOM refs)\n watch(\n props.expanded,\n (v) => {\n const expanded = Boolean(v);\n\n details.open = expanded;\n summary.setAttribute('aria-expanded', expanded ? 'true' : 'false');\n },\n { immediate: true },\n );\n handle(details, 'toggle', handleToggle);\n });\n\n const ariaExpanded = computed(() => (props.expanded.value ? 'true' : 'false'));\n const ariaDisabled = computed(() => (props.disabled.value ? 'true' : 'false'));\n\n return html` <details part=\"item\" ?open=${props.expanded} ref=${detailsRef}>\n <summary part=\"summary\" :aria-expanded=${ariaExpanded} :aria-disabled=${ariaDisabled} ref=${summaryRef}>\n <slot name=\"prefix\"></slot>\n <div class=\"header-content\" part=\"header\">\n <span class=\"title\" part=\"title\" id=\"${titleId}\">\n <slot name=\"title\"></slot>\n </span>\n <span class=\"subtitle\" part=\"subtitle\">\n <slot name=\"subtitle\"></slot>\n </span>\n </div>\n <slot name=\"suffix\"></slot>\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"chevron\"\n part=\"chevron\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"m 14.999979,5.9999793 -5.9999997,5.9999997 5.9999997,6\" />\n </svg>\n </summary>\n <div class=\"content-wrapper\" part=\"content\" role=\"region\" aria-labelledby=\"${titleId}\">\n <div class=\"content-inner\">\n <slot></slot>\n </div>\n </div>\n </details>`;\n },\n styles: [coarsePointerMixin, styles],\n tag: 'bit-accordion-item',\n});\n","@layer buildit.base {\n :host {\n display: inline-flex;\n outline: none;\n\n --tab-item-transition: var(--transition-normal);\n --tab-item-radius: var(--rounded-lg);\n }\n\n button {\n position: relative;\n display: inline-flex;\n gap: var(--size-2);\n align-items: center;\n justify-content: center;\n width: 100%;\n min-height: var(--_touch-target);\n padding: var(--tab-item-padding, var(--size-1-5) var(--size-4));\n font-family: inherit;\n font-size: var(--tab-item-font-size, var(--text-sm));\n font-weight: var(--font-medium);\n color: var(--tab-item-color, var(--text-color-secondary));\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n background: transparent;\n border: none;\n border-radius: var(--tab-item-radius);\n transition:\n background var(--tab-item-transition),\n color var(--tab-item-transition),\n box-shadow var(--tab-item-transition);\n }\n\n button:focus {\n outline: none;\n }\n\n :host(:focus-visible) button,\n button:focus-visible {\n outline: var(--border-2) solid var(--_theme-focus);\n outline-offset: 2px;\n box-shadow: 0 0 0 3px var(--_theme-shadow);\n }\n}\n\n@layer buildit.variants {\n /* ─── solid / default ─── */\n :host button:hover,\n :host([variant='solid']) button:hover {\n color: var(--text-color-heading);\n background: var(--color-contrast-200);\n }\n\n :host([active]) button,\n :host([variant='solid'][active]) button {\n color: var(--text-color-heading);\n background: var(--color-contrast-0, var(--color-canvas));\n box-shadow: var(--shadow-xs), var(--inset-shadow-xs);\n }\n\n /* ─── flat ─── */\n :host([variant='flat']) button:hover {\n color: var(--text-color-heading);\n background: var(--color-contrast-200);\n }\n\n :host([variant='flat'][active]) button {\n color: var(--text-color-heading);\n background: var(--color-contrast-0, var(--color-canvas));\n box-shadow: var(--shadow-xs), var(--inset-shadow-xs);\n }\n\n /* ─── bordered ─── */\n :host([variant='bordered']) button:hover {\n color: var(--text-color-heading);\n background: var(--color-contrast-200);\n }\n\n :host([variant='bordered'][active]) button {\n color: var(--text-color-heading);\n background: var(--color-contrast-0, var(--color-canvas));\n box-shadow: var(--shadow-xs);\n }\n\n /* ─── ghost ─── */\n :host([variant='ghost']) button:hover {\n color: var(--text-color-heading);\n background: var(--color-contrast-100);\n }\n\n :host([variant='ghost'][active]) button {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n }\n\n /* ─── glass ─── */\n :host([variant='glass']) button {\n color: color-mix(in srgb, var(--color-secondary-contrast) 70%, transparent);\n text-shadow: var(--text-shadow-2xs);\n }\n\n :host([variant='glass']) button:hover {\n color: var(--color-secondary-contrast);\n background: color-mix(in srgb, var(--color-secondary-contrast) 10%, transparent);\n }\n\n :host([variant='glass'][active]) button {\n color: var(--color-secondary-contrast);\n background: color-mix(in srgb, var(--color-secondary-contrast) 15%, transparent);\n box-shadow: var(--shadow-xs), var(--inset-shadow-xs);\n }\n\n /* ─── frost ─── */\n :host([variant='frost']) button {\n color: var(--text-color-secondary);\n }\n\n :host([variant='frost']) button:hover {\n color: var(--text-color-heading);\n background: color-mix(in srgb, var(--color-contrast) 10%, transparent);\n }\n\n :host([variant='frost'][active]) button {\n color: var(--text-color-heading);\n background: color-mix(in srgb, var(--color-canvas) 60%, transparent);\n box-shadow: var(--shadow-xs), var(--inset-shadow-xs);\n }\n\n /* ─── sizes ─── */\n :host([size='sm']) {\n --tab-item-font-size: var(--text-xs);\n --tab-item-padding: var(--size-1) var(--size-3);\n }\n\n :host(:not([size])),\n :host([size='md']) {\n --tab-item-font-size: var(--text-sm);\n --tab-item-padding: var(--size-1-5) var(--size-4);\n }\n\n :host([size='lg']) {\n --tab-item-font-size: var(--text-base);\n --tab-item-padding: var(--size-2) var(--size-5);\n }\n\n /* ─── disabled ─── */\n :host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n }\n\n @media (forced-colors: active) {\n /* Ensure focus ring is visible regardless of variant theme color */\n button:focus-visible {\n outline: 2px solid Highlight;\n box-shadow: none;\n }\n\n /* Active tab: box-shadow raised indicator is stripped; use outline inste\n ad so the selected tab remains distinguishable */\n :host([active]) button {\n outline: 2px solid Highlight;\n outline-offset: -2px;\n }\n }\n}\n","import { computed, defineComponent, effect, fire, html, typed, inject, syncContextProps } from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsFocusMixin } from '../../styles';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-item.css?inline';\n\nexport type BitTabItemProps = {\n /** Whether this tab is currently selected (set by bit-tabs) */\n active?: boolean;\n /** Theme color (inherited from bit-tabs) */\n color?: ThemeColor;\n /** Disable this tab */\n disabled?: boolean;\n /** Size (inherited from bit-tabs) */\n size?: ComponentSize;\n /** Unique value identifier — must match a bit-tab-panel value */\n value: string;\n /** Visual variant (inherited from bit-tabs) */\n variant?: VisualVariant;\n};\n\n/**\n * Individual tab trigger. Must be placed in the `tabs` slot of `bit-tabs`.\n *\n * @element bit-tab-item\n *\n * @attr {string} value - Unique identifier, matches the corresponding bit-tab-panel value\n * @attr {boolean} active - Set by the parent bit-tabs when this tab is selected\n * @attr {boolean} disabled - Prevents selection\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} variant - Inherited from bit-tabs\n * @attr {string} color - Inherited from bit-tabs: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n *\n * @slot prefix - Icon or content before the label\n * @slot - Tab label\n * @slot suffix - Badge or count after the label\n *\n * @example\n * ```html\n * <bit-tab-item slot=\"tabs\" value=\"overview\">Overview</bit-tab-item>\n * <bit-tab-item slot=\"tabs\" value=\"settings\" disabled>Settings</bit-tab-item>\n * ```\n */\nexport const TAB_ITEM_TAG = defineComponent<BitTabItemProps>({\n props: {\n active: typed<boolean>(false),\n color: typed<BitTabItemProps['color']>(undefined),\n disabled: typed<boolean>(false),\n size: typed<BitTabItemProps['size']>(undefined),\n value: typed<string>(''),\n variant: typed<BitTabItemProps['variant']>(undefined),\n },\n setup({ host, props }) {\n const tabsCtx = inject(TABS_CTX, undefined);\n\n syncContextProps(tabsCtx, props, ['color', 'size', 'variant']);\n\n const isActive = tabsCtx\n ? computed(() => !!tabsCtx.value.value && tabsCtx.value.value === props.value.value)\n : props.active;\n\n effect(() => {\n host.toggleAttribute('active', isActive.value);\n });\n\n const ariaSelected = computed(() => String(isActive.value));\n const tabIndex = computed(() => (isActive.value ? '0' : '-1'));\n const handleClick = () => {\n if (props.disabled.value) return;\n\n fire.custom(host, 'click', {\n detail: { value: props.value.value },\n });\n };\n\n return html`\n <button\n role=\"tab\"\n type=\"button\"\n part=\"tab\"\n :id=\"${() => `tab-${props.value.value}`}\"\n :aria-selected=${ariaSelected}\n :tabindex=${tabIndex}\n :aria-disabled=${computed(() => String(props.disabled.value))}\n :aria-controls=\"${() => `tabpanel-${props.value.value}`}\"\n @click=${handleClick}>\n <slot name=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\"></slot>\n </button>\n `;\n },\n styles: [colorThemeMixin, forcedColorsFocusMixin('button'), coarsePointerMixin, styles],\n tag: 'bit-tab-item',\n});\n","@layer buildit.base {\n :host {\n display: none;\n width: 100%;\n }\n\n :host([active]) {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-height: 0;\n }\n\n .panel {\n box-sizing: border-box;\n flex: 1;\n height: 100%;\n min-height: 0;\n padding: var(--tab-panel-padding, var(--size-4));\n overflow: auto;\n font-size: var(--tab-panel-font-size, var(--text-sm));\n color: var(--text-color-body);\n animation: var(--_motion-animation, tab-panel-in var(--transition-normal) var(--ease-out) both);\n }\n}\n\n@layer buildit.variants {\n @keyframes tab-panel-in {\n from {\n opacity: 0;\n translate: 0 4px;\n }\n\n to {\n opacity: 1;\n translate: 0 0;\n }\n }\n}\n","import { computed, defineComponent, effect, html, typed, inject, signal } from '@vielzeug/craftit';\n\nimport { reducedMotionMixin } from '../../styles';\nimport { TABS_CTX } from '../tabs/tabs';\nimport styles from './tab-panel.css?inline';\n\nexport type BitTabPanelProps = {\n /** Active state (managed by bit-tabs) */\n active?: boolean;\n /** When true, the panel content is not rendered until first activation (preserves resources) */\n lazy?: boolean;\n /** Panel padding size: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' (default: 'md' = var(--size-4)) */\n padding?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n /** Must match the `value` of its corresponding bit-tab-item */\n value: string;\n};\n\n/**\n * Content panel for a tab. Shown when its `value` matches the selected tab.\n *\n * @element bit-tab-panel\n *\n * @attr {string} value - Must match the corresponding bit-tab-item value\n * @attr {boolean} active - Toggled by the parent bit-tabs\n * @attr {string} padding - Panel padding: 'none' | 'xs' | 'sm' | 'md' (default) | 'lg' | 'xl' | '2xl'\n *\n * @slot - Panel content\n *\n * @example\n * ```html\n * <bit-tab-panel value=\"overview\"><p>Overview content here</p></bit-tab-panel>\n * <bit-tab-panel value=\"settings\" padding=\"lg\"><p>Large padding</p></bit-tab-panel>\n * <bit-tab-panel value=\"code\" padding=\"none\"><pre>No padding for code</pre></bit-tab-panel>\n * ```\n */\nexport const TAB_PANEL_TAG = defineComponent<BitTabPanelProps>({\n props: {\n active: typed<boolean>(false),\n lazy: typed<boolean>(false),\n padding: typed<BitTabPanelProps['padding']>('md'),\n value: typed<string>(''),\n },\n setup({ host, props }) {\n const tabsCtx = inject(TABS_CTX, undefined);\n const isActive = tabsCtx\n ? computed(() => !!tabsCtx.value.value && tabsCtx.value.value === props.value.value)\n : props.active;\n // Map padding prop to CSS variable\n const paddingValue = computed(() => {\n const paddingMap: Record<string, string> = {\n '2xl': 'var(--size-12)',\n lg: 'var(--size-6)',\n md: 'var(--size-4)',\n none: '0',\n sm: 'var(--size-2)',\n xl: 'var(--size-8)',\n xs: 'var(--size-1)',\n };\n const key = props.padding.value ?? 'md';\n\n return paddingMap[key] ?? paddingMap.md;\n });\n // Track whether the panel has ever been active (for lazy rendering)\n const hasBeenActive = signal(false);\n\n effect(() => {\n host.toggleAttribute('active', isActive.value);\n\n if (isActive.value) hasBeenActive.value = true;\n });\n\n // shouldRender: true if not lazy OR has been active at least once\n const shouldRender = computed(() => !props.lazy.value || hasBeenActive.value);\n\n return html`\n <div\n class=\"panel\"\n part=\"panel\"\n role=\"tabpanel\"\n :id=\"${() => `tabpanel-${props.value.value}`}\"\n :aria-labelledby=\"${() => `tab-${props.value.value}`}\"\n :aria-hidden=${() => String(!isActive.value)}\n :style=\"${() => `--tab-panel-padding: ${paddingValue.value}`}\"\n tabindex=\"0\">\n ${() => (shouldRender.value ? html`<slot></slot>` : '')}\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n tag: 'bit-tab-panel',\n});\n","import { html } from '@vielzeug/craftit';\n\n// ─── Shared SVG icon utilities ────────────────────────────────────────────────\n// All icons use currentColor so they inherit whatever color the host applies.\n\nexport const closeIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n`;\n\nexport const checkIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n`;\n\n/** Used inline as an innerHTML string (e.g. for imperatively built option lists). */\nexport const checkIconHTML =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>';\n\nexport const chevronDownIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n`;\n\nexport const chevronLeftIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"15 18 9 12 15 6\"></polyline>\n </svg>\n`;\n\nexport const chevronRightIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n`;\n\nexport const eyeIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n width=\"14\"\n height=\"14\"\n aria-hidden=\"true\">\n <path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n`;\n\nexport const eyeOffIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n width=\"14\"\n height=\"14\"\n aria-hidden=\"true\">\n <path d=\"M9.88 9.88a3 3 0 1 0 4.24 4.24\" />\n <path d=\"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\" />\n <path d=\"M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\" />\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n </svg>\n`;\n\nexport const clearIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n`;\n\nexport const uploadIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"36\"\n height=\"36\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <polyline points=\"16 16 12 12 8 16\" />\n <line x1=\"12\" y1=\"12\" x2=\"12\" y2=\"21\" />\n <path d=\"M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3\" />\n </svg>\n`;\n\nexport const fileIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n`;\n\nexport const minusIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n aria-hidden=\"true\">\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n`;\n\nexport const plusIcon = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n aria-hidden=\"true\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n`;\n","/**\n * Waits for a CSS exit animation or transition to finish, then calls `onDone`.\n *\n * When the element has no animation/transition running (e.g. reduced-motion or\n * overridden styles), `onDone` is called synchronously on the next microtask so\n * callers can safely set exit state before this call.\n *\n * @param el - The element whose animation/transition to observe.\n * @param onDone - Callback invoked exactly once when the animation ends.\n * @param type - `'animation'` (default) or `'transition'`.\n */\n/** Safety buffer added to the computed CSS duration before the fallback timer fires. */\nconst ANIMATION_FALLBACK_BUFFER_MS = 50;\n\nexport function awaitExit(el: Element, onDone: () => void, type: 'animation' | 'transition' = 'animation'): void {\n let finished = false;\n let fallbackTimer: ReturnType<typeof setTimeout> | null = null;\n\n const finish = () => {\n if (finished) return;\n\n finished = true;\n\n if (fallbackTimer !== null) {\n clearTimeout(fallbackTimer);\n fallbackTimer = null;\n }\n\n onDone();\n };\n\n queueMicrotask(() => {\n const styles = getComputedStyle(el);\n\n if (type === 'animation') {\n const names = styles.animationName.split(',').map((v) => v.trim());\n const durations = styles.animationDuration.split(',').map((v) => {\n if (v.endsWith('ms')) return Number.parseFloat(v);\n\n if (v.endsWith('s')) return Number.parseFloat(v) * 1000;\n\n return 0;\n });\n\n const hasAnimation = names.some((n) => n && n !== 'none');\n const maxDuration = Math.max(0, ...durations);\n\n if (!hasAnimation || maxDuration <= 0) {\n finish();\n\n return;\n }\n\n el.addEventListener('animationend', finish, { once: true });\n fallbackTimer = setTimeout(finish, maxDuration + ANIMATION_FALLBACK_BUFFER_MS);\n } else {\n const duration = Number.parseFloat(styles.transitionDuration);\n\n if (!duration || duration <= 0) {\n finish();\n\n return;\n }\n\n el.addEventListener('transitionend', finish, { once: true });\n fallbackTimer = setTimeout(finish, duration * 1000 + ANIMATION_FALLBACK_BUFFER_MS);\n }\n });\n}\n","@layer buildit.base {\n :host {\n --_bg: var(--alert-bg, var(--_theme-backdrop));\n --_color: var(--alert-color, var(--_theme-base));\n --_border-color: var(--alert-border-color, var(--_theme-border));\n --_radius: var(--alert-radius, var(--rounded-lg));\n --_padding: var(--alert-padding, var(--size-4));\n --_gap: var(--alert-gap, var(--size-3));\n --_font-size: var(--alert-font-size, var(--text-sm));\n --_shadow: var(--alert-shadow, var(--shadow-none));\n\n display: block;\n }\n\n :host([dismissed]) {\n display: none;\n }\n\n :host([dismissing]) {\n overflow: hidden;\n pointer-events: none;\n animation: var(--_motion-animation, bit-alert-exit var(--transition-slow, 0.3s) ease forwards);\n }\n\n @keyframes bit-alert-exit {\n 0% {\n /* Use a large enough value to cover any realistic alert height. */\n max-height: 600px;\n margin-bottom: var(--size-3);\n opacity: 1;\n transform: scaleY(1);\n }\n\n 60% {\n opacity: 0;\n transform: scaleY(0.8);\n }\n\n 100% {\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n margin-bottom: 0;\n opacity: 0;\n transform: scaleY(0);\n }\n }\n\n .alert {\n display: grid;\n grid-template-columns: auto 1fr auto;\n row-gap: var(--size-1);\n padding: var(--_padding);\n overflow: hidden;\n font-size: var(--_font-size);\n line-height: var(--leading-normal);\n color: var(--_color);\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--_shadow);\n transition:\n background var(--transition-normal),\n border-color var(--transition-normal),\n box-shadow var(--transition-normal),\n color var(--transition-normal);\n }\n\n /* ── Icon ──────────────────────────────────────── */\n\n .icon {\n display: inline-flex;\n grid-row: 1;\n grid-column: 1;\n align-items: center;\n align-self: start;\n justify-content: center;\n margin-inline-end: var(--_gap);\n }\n\n /* Without heading: icon aligns with the body content */\n .alert:has(.header[hidden]) .icon {\n align-self: center;\n }\n\n .icon[hidden] {\n display: none;\n }\n\n /* ── Header row (heading + meta) ───────────────── */\n\n .header {\n display: flex;\n grid-row: 1;\n grid-column: 2;\n gap: var(--size-2);\n align-items: baseline;\n }\n\n .header[hidden] {\n display: none;\n }\n\n .heading {\n overflow: hidden;\n text-overflow: ellipsis;\n font-weight: var(--font-semibold);\n line-height: var(--leading-normal);\n white-space: nowrap;\n }\n\n .meta {\n margin-inline-start: auto;\n font-size: var(--text-xs);\n white-space: nowrap;\n opacity: 0.7;\n }\n\n :host(:not(:has([slot='meta']))) .meta {\n display: none;\n }\n\n /* ── Body ──────────────────────────────────────── */\n\n .body {\n grid-row: 2;\n grid-column: 1 / -1;\n min-width: 0;\n margin-top: var(--size-1);\n }\n\n /* Without heading: body moves up to share row with icon and close */\n .alert:has(.header[hidden]) .body {\n grid-row: 1;\n grid-column: 2;\n margin-top: 0;\n }\n\n /* ── Content ───────────────────────────────────── */\n\n .content {\n line-height: var(--leading-relaxed);\n }\n\n /* ── Actions ───────────────────────────────────── */\n\n .actions {\n display: flex;\n flex-wrap: wrap;\n grid-row: 3;\n grid-column: 1 / -1;\n gap: var(--size-2);\n margin-top: var(--size-2);\n }\n\n /* Without heading: actions move to row 2 */\n .alert:has(.header[hidden]) .actions {\n grid-row: 2;\n }\n\n .actions[hidden] {\n display: none;\n }\n\n /* Horizontal mode: 4-column grid — icon | body | actions | close */\n :host([horizontal]) .alert {\n grid-template-columns: auto 1fr auto auto;\n }\n\n :host([horizontal]) .body {\n grid-row: 1;\n grid-column: 2;\n align-self: center;\n margin-top: 0;\n }\n\n :host([horizontal]) .actions:not([hidden]) {\n flex-wrap: nowrap;\n grid-row: 1;\n grid-column: 3;\n margin-inline-start: var(--_gap);\n margin-top: 0;\n }\n\n :host([horizontal]) .close {\n grid-column: 4;\n align-self: center;\n }\n\n /* ── Close button ──────────────────────────────── */\n\n .close {\n display: inline-flex;\n grid-row: 1;\n grid-column: 3;\n align-items: center;\n align-self: start;\n justify-content: center;\n width: var(--size-5);\n min-width: var(--_touch-target);\n height: var(--size-5);\n min-height: var(--_touch-target);\n padding: 0;\n margin-inline-start: var(--_gap);\n color: inherit;\n cursor: pointer;\n background: transparent;\n border: none;\n border-radius: var(--rounded-sm);\n opacity: 0.7;\n transition: var(--_motion-transition, opacity var(--transition-fast), background var(--transition-fast));\n }\n\n .close[hidden] {\n display: none;\n }\n\n .close:hover {\n background: color-mix(in srgb, currentcolor 12%, transparent);\n opacity: 1;\n }\n\n .close:focus-visible {\n outline: var(--border-2) solid currentcolor;\n outline-offset: var(--border-2);\n opacity: 1;\n }\n\n /* Accented left border for flat and bordered variants */\n :host([variant='flat'][accented]) .alert,\n :host([variant='bordered'][accented]) .alert {\n border-inline-start-width: var(--border-4, 4px);\n }\n}\n\n@layer buildit.variants {\n :host(:not([variant])) .alert,\n :host([variant='flat']) .alert {\n color: var(--_theme-base);\n background: var(--color-canvas);\n border-color: var(--_theme-base);\n box-shadow: var(--shadow-none);\n }\n\n :host([variant='solid']) .alert {\n color: var(--_theme-contrast);\n background: var(--_theme-base);\n border-color: var(--_theme-base);\n box-shadow: var(--shadow-xs);\n }\n\n :host([variant='solid']) .close {\n color: var(--_theme-contrast);\n }\n\n :host([variant='bordered']) .alert {\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-backdrop), var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 30%, transparent);\n box-shadow: var(--inset-shadow-2xs);\n }\n}\n","import { defineComponent, guard, html, onMount, onSlotChange, signal } from '@vielzeug/craftit';\n\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport { closeIcon } from '../../icons';\nimport { forcedColorsMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { awaitExit } from '../../utils/animation';\nimport componentStyles from './alert.css?inline';\n\nexport type BitAlertEvents = {\n dismiss: { originalEvent: MouseEvent };\n};\n\nexport type BitAlertProps = {\n /** Show a left accent border (for flat/bordered variants) */\n accented?: boolean;\n /** Theme color */\n color?: ThemeColor;\n /** Show a dismissable (×) button */\n dismissible?: boolean;\n /** Heading text shown above the content */\n heading?: string;\n /** Position action buttons to the right instead of below */\n horizontal?: boolean;\n /** Border radius */\n rounded?: RoundedSize | '';\n /** Alert size */\n size?: ComponentSize;\n /** Visual style variant */\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\n/**\n * A status/feedback banner with optional heading, icon slot, and dismiss button.\n *\n * @element bit-alert\n *\n * @attr {string} color - Theme color (primary/success/warning/error…)\n * @attr {string} variant - Visual style: 'flat' | 'solid' | 'bordered'\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius size\n * @attr {string} heading - Bold heading text above the content\n * @attr {boolean} dismissible - Show a close (×) button\n * @attr {boolean} accented - Add a left accent border (flat/bordered only)\n * @attr {boolean} horizontal - Position action buttons to the right instead of below\n *\n * @fires dismiss - Fired when the alert is dismissed\n *\n * @slot - Default slot for the alert message content\n * @slot icon - Icon on the left side\n * @slot meta - Metadata displayed alongside the heading (lighter, right-aligned)\n * @slot actions - Action buttons shown below the message\n *\n * @cssprop --alert-bg - Background color\n * @cssprop --alert-color - Text/icon color\n * @cssprop --alert-border-color - Border color\n * @cssprop --alert-radius - Border radius\n * @cssprop --alert-padding - Padding\n * @cssprop --alert-gap - Gap between icon, body, and close button\n * @cssprop --alert-font-size - Font size\n *\n * @example\n * ```html\n * <bit-alert color=\"success\">Your changes have been saved.</bit-alert>\n * <bit-alert color=\"error\" variant=\"solid\" dismissible heading=\"Something went wrong\">\n * Please try again later.\n * </bit-alert>\n * ```\n */\nexport const ALERT_TAG = defineComponent<BitAlertProps, BitAlertEvents>({\n props: {\n accented: { default: false },\n color: { default: undefined },\n dismissible: { default: false },\n heading: { default: '' },\n horizontal: { default: false },\n rounded: { default: undefined },\n size: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const handleDismiss = guard(\n () => props.dismissible.value,\n (e: MouseEvent) => {\n host.setAttribute('dismissing', '');\n awaitExit(host, () => {\n host.removeAttribute('dismissing');\n host.setAttribute('dismissed', '');\n emit('dismiss', { originalEvent: e });\n });\n },\n );\n const hasIcon = signal(false);\n const hasActions = signal(false);\n\n onMount(() => {\n onSlotChange('icon', (els) => {\n hasIcon.value = els.length > 0;\n });\n onSlotChange('actions', (els) => {\n hasActions.value = els.length > 0;\n });\n });\n\n return html`\n <div class=\"alert\" :role=\"${() => (props.color.value === 'error' ? 'alert' : 'status')}\" part=\"alert\">\n <span class=\"icon\" part=\"icon\" aria-hidden=\"true\" ?hidden=${() => !hasIcon.value}>\n <slot name=\"icon\"></slot>\n </span>\n <div class=\"header\" part=\"header\" ?hidden=${() => !props.heading.value}>\n <span class=\"heading\" part=\"heading\">${() => props.heading.value}</span>\n <span class=\"meta\" part=\"meta\">\n <slot name=\"meta\"></slot>\n </span>\n </div>\n <div class=\"body\" part=\"body\">\n <div class=\"content\" part=\"content\">\n <slot></slot>\n </div>\n </div>\n <div class=\"actions\" part=\"actions\" ?hidden=${() => !hasActions.value}>\n <slot name=\"actions\"></slot>\n </div>\n <button\n class=\"close\"\n part=\"close\"\n type=\"button\"\n aria-label=\"Dismiss alert\"\n ?hidden=${() => !props.dismissible.value}\n @click=${handleDismiss}>\n ${closeIcon}\n </button>\n </div>\n `;\n },\n styles: [\n ...formFieldMixins,\n forcedColorsMixin,\n sizeVariantMixin({\n lg: { '--_padding': 'var(--size-4) var(--size-5)', fontSize: 'var(--text-base)', gap: 'var(--size-3-5)' },\n sm: { '--_padding': 'var(--size-2) var(--size-3)', fontSize: 'var(--text-xs)', gap: 'var(--size-2)' },\n }),\n componentStyles,\n ],\n tag: 'bit-alert',\n});\n","@layer buildit.base {\n :host {\n --_bg: var(--badge-bg, var(--_theme-backdrop));\n --_color: var(--badge-color, var(--_theme-base));\n --_border-color: var(--badge-border-color, var(--_theme-border));\n --_radius: var(--badge-radius, var(--rounded-full));\n --_font-size: var(--badge-font-size, var(--text-xs));\n --_font-weight: var(--badge-font-weight, var(--font-semibold));\n --_padding-x: var(--badge-padding-x, var(--size-1-5));\n --_padding-y: var(--badge-padding-y, var(--size-0-5));\n --_gap: var(--badge-gap, var(--size-1));\n\n display: inline-flex;\n vertical-align: middle;\n }\n\n .badge {\n display: inline-flex;\n gap: var(--_gap);\n align-items: center;\n justify-content: center;\n\n /* Dot-only (no text slot) gets circular shape */\n min-width: var(--size-2);\n max-width: var(--badge-max-width, 24ch);\n padding: var(--_padding-y) var(--_padding-x);\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--_font-size);\n font-weight: var(--_font-weight);\n line-height: 1;\n color: var(--_color);\n white-space: nowrap;\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n }\n\n ::slotted([slot='icon']) {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 1em;\n height: 1em;\n }\n}\n\n@layer buildit.variants {\n /* Solid (Default) - Full theme color background */\n :host(:not([variant])),\n :host([variant='solid']) {\n --_bg: var(--badge-bg, var(--_theme-base));\n --_color: var(--badge-color, var(--_theme-contrast));\n --_border-color: var(--badge-border-color, var(--_theme-base));\n }\n\n /* Flat - Subtle background with theme color text */\n :host([variant='flat']) {\n --_bg: var(--badge-bg, color-mix(in srgb, var(--_theme-backdrop) 8%, var(--color-contrast-100)));\n --_color: var(--badge-color, var(--_theme-base));\n --_border-color: var(--badge-border-color, color-mix(in srgb, var(--_theme-focus) 20%, transparent));\n }\n\n /* Bordered - Outlined with filled background */\n :host([variant='bordered']) {\n --_bg: var(--badge-bg, var(--_theme-backdrop));\n --_color: var(--badge-color, var(--_theme-base));\n --_border-color: var(--badge-border-color, var(--_theme-border));\n }\n\n /* Outline - Transparent with colored border */\n :host([variant='outline']) {\n --_bg: var(--badge-bg, transparent);\n --_color: var(--badge-color, var(--_theme-base));\n --_border-color: var(--badge-border-color, var(--_theme-base));\n }\n\n /* Dot-only mode */\n :host([dot]) .badge {\n min-width: unset;\n padding: var(--size-1);\n line-height: 0;\n }\n}\n\n@layer buildit.overrides {\n /* Dot — always force badge background and border regardless of variant */\n :host([dot]) {\n --_bg: var(--badge-bg, var(--_theme-base));\n --_border-color: var(--badge-border-color, var(--_theme-base));\n }\n\n /* ========================================\n Anchor overlay mode\n ======================================== */\n\n :host([anchor]) {\n position: relative;\n display: inline-flex;\n }\n\n /*\n * Per-direction multiplier: +1 in LTR, -1 in RTL.\n * Used to flip the translateX offset so the badge always overflows\n * the correct physical edge that corresponds to its logical corner.\n */\n :host {\n --_dir: 1;\n }\n\n :host(:dir(rtl)) {\n --_dir: -1;\n }\n\n /* Default position: top-end */\n :host([anchor]) .badge {\n position: absolute;\n inset-inline-end: 0;\n top: 0;\n z-index: 1;\n transform: translate(calc(var(--_dir) * 50%), -50%);\n }\n\n :host([anchor='top-start']) .badge {\n inset-inline-start: 0;\n inset-inline-end: unset;\n transform: translate(calc(var(--_dir) * -50%), -50%);\n }\n\n :host([anchor='bottom-end']) .badge {\n top: unset;\n bottom: 0;\n transform: translate(calc(var(--_dir) * 50%), 50%);\n }\n\n :host([anchor='bottom-start']) .badge {\n inset-inline-start: 0;\n inset-inline-end: unset;\n top: unset;\n bottom: 0;\n transform: translate(calc(var(--_dir) * -50%), 50%);\n }\n}\n","import { computed, defineComponent, html } from '@vielzeug/craftit';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { colorThemeMixin, frostVariantMixin, roundedVariantMixin, sizeVariantMixin } from '../../styles';\nimport componentStyles from './badge.css?inline';\n\ntype BadgeVariant = Extract<VisualVariant, 'solid' | 'flat' | 'bordered' | 'outline' | 'frost'>;\n\n/** Badge component properties */\nexport type BitBadgeProps = {\n /**\n * When set, switches to overlay mode: the host becomes `position:relative`\n * and the badge pins to a corner over the slotted content.\n * Value controls which corner: 'top-end' (default) | 'top-start' | 'bottom-end' | 'bottom-start'\n */\n anchor?: 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start';\n /** Accessible label for assistive technology. Recommended for count-only and dot mode. */\n ariaLabel?: string;\n /** Theme color */\n color?: ThemeColor;\n /** Numeric count to display */\n count?: number;\n /** Render as a small dot with no label */\n dot?: boolean;\n /** Max count — displays \"<max>+\" when count exceeds this value */\n max?: number;\n /** Border radius override */\n rounded?: RoundedSize;\n /** Badge size */\n size?: ComponentSize;\n /** Visual style variant */\n variant?: BadgeVariant;\n};\n\n/**\n * A compact badge/chip for counts, statuses, and labels.\n * Supports numeric counts with overflow, dot mode, and icon slots.\n *\n * @element bit-badge\n *\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'frost'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {number} count - Numeric count to display\n * @attr {number} max - Max count before showing \"<max>+\"\n * @attr {boolean} dot - Render as a dot indicator (no text)\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'full' etc.\n *\n * @slot - Badge label text\n * @slot icon - Icon displayed before the label\n * @slot target - Element the badge is anchored to (used with the anchor attribute)\n *\n * @cssprop --badge-bg - Badge background color\n * @cssprop --badge-color - Badge text color\n * @cssprop --badge-border-color - Badge border color\n * @cssprop --badge-radius - Border radius\n * @cssprop --badge-font-size - Font size\n * @cssprop --badge-font-weight - Font weight\n * @cssprop --badge-padding-x - Horizontal padding\n * @cssprop --badge-padding-y - Vertical padding\n * @cssprop --badge-gap - Gap between icon and label\n *\n * @example\n * ```html\n * <bit-badge color=\"primary\">New</bit-badge>\n * <bit-badge color=\"error\" count=\"5\"></bit-badge>\n * <bit-badge color=\"error\" count=\"120\" max=\"99\"></bit-badge>\n * <bit-badge color=\"success\" dot></bit-badge>\n * <bit-badge color=\"warning\" variant=\"flat\">Beta</bit-badge>\n * ```\n */\nexport const BADGE_TAG = defineComponent<BitBadgeProps>({\n props: {\n anchor: { default: undefined },\n ariaLabel: { default: undefined },\n color: { default: undefined },\n count: { default: undefined },\n dot: { default: false },\n max: { default: undefined },\n rounded: { default: undefined },\n size: { default: undefined },\n variant: { default: undefined },\n },\n setup({ props }) {\n const label = computed(() => {\n const count = props.count.value != null ? Number(props.count.value) : undefined;\n const max = props.max.value != null ? Number(props.max.value) : undefined;\n\n if (count === undefined || Number.isNaN(count)) return undefined;\n\n if (max !== undefined && !Number.isNaN(max) && count > max) return `${max}+`;\n\n return String(count);\n });\n\n return html`<span class=\"badge\" part=\"badge\" aria-label=${() => props.ariaLabel.value}>\n <slot name=\"icon\"></slot>\n <span ?hidden=${() => label.value == null}>${() => label.value}</span>\n <slot ?hidden=${() => label.value != null}></slot>\n </span>\n <slot name=\"target\"></slot>`;\n },\n styles: [\n colorThemeMixin,\n roundedVariantMixin,\n frostVariantMixin('.badge'),\n sizeVariantMixin({\n lg: { '--_padding-x': 'var(--size-2-5)', '--_padding-y': 'var(--size-1)', fontSize: 'var(--text-sm)' },\n md: { '--_padding-x': 'var(--size-2)', '--_padding-y': 'var(--size-0-5)', fontSize: 'var(--text-xs)' },\n sm: { '--_padding-x': 'var(--size-1-5)', '--_padding-y': 'var(--size-px)', fontSize: 'var(--text-xs)' },\n }),\n componentStyles,\n ],\n tag: 'bit-badge',\n});\n","@layer buildit.base {\n :host {\n --_bg: var(--chip-bg, var(--color-contrast-150, var(--color-contrast-100)));\n --_color: var(--chip-color, var(--color-contrast-800));\n --_border-color: var(--chip-border-color, transparent);\n --_radius: var(--chip-radius, var(--rounded-full));\n --_font-size: var(--chip-font-size, var(--text-sm));\n --_font-weight: var(--chip-font-weight, var(--font-medium));\n --_padding-x: var(--chip-padding-x, var(--size-2-5));\n --_padding-y: var(--chip-padding-y, var(--size-0-5));\n --_gap: var(--chip-gap, var(--size-1));\n\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n vertical-align: middle;\n }\n\n .chip {\n position: relative;\n box-sizing: border-box;\n display: inline-flex;\n gap: var(--_gap);\n align-items: center;\n max-width: 100%;\n padding: var(--_padding-y) var(--_padding-x);\n font-size: var(--_font-size);\n font-weight: var(--_font-weight);\n line-height: 1.2;\n color: var(--_color);\n white-space: nowrap;\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n transition:\n background var(--transition-fast),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast),\n color var(--transition-fast);\n }\n\n .label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* ========================================\n Remove Button\n ======================================== */\n\n .remove-btn {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 1.35em;\n height: 1.35em;\n padding: 0;\n margin-inline: var(--size-0-5) calc(var(--size-2) * -1);\n color: inherit;\n cursor: pointer;\n background: color-mix(in srgb, currentcolor 12%, transparent);\n border: none;\n border-radius: var(--_radius);\n opacity: 0.7;\n transition:\n background var(--transition-fast),\n opacity var(--transition-fast);\n }\n\n .remove-btn:hover {\n background: color-mix(in srgb, currentcolor 28%, transparent);\n opacity: 1;\n }\n\n .remove-btn:focus-visible {\n outline: 2px solid currentcolor;\n outline-offset: 1px;\n opacity: 1;\n }\n\n /* ========================================\n Icon slot\n ======================================== */\n\n ::slotted([slot='icon']) {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 1em;\n height: 1em;\n }\n\n .chip-btn {\n display: inline-flex;\n width: 100%;\n padding: 0;\n margin: 0;\n font: inherit;\n color: inherit;\n text-align: inherit;\n cursor: pointer;\n background: none;\n border: none;\n }\n\n .chip-btn:disabled {\n cursor: not-allowed;\n }\n\n :host([mode='selectable'][checked]) .chip {\n outline: var(--border-2) solid var(--_theme-base, currentColor);\n outline-offset: -2px;\n }\n\n :host([mode='selectable']:not([disabled])) .chip,\n :host([mode='action']:not([disabled])) .chip {\n cursor: pointer;\n }\n\n .chip-btn:focus-visible .chip {\n outline: 2px solid var(--_theme-base, currentColor);\n outline-offset: 2px;\n }\n}\n\n@layer buildit.variants {\n /* Solid (Default) — full theme color fill */\n :host(:not([variant])) .chip,\n :host([variant='solid']) .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-base, var(--color-contrast-700));\n border-color: transparent;\n }\n\n /* Flat — subtle tint */\n :host([variant='flat']) .chip {\n color: var(--_theme-base, var(--color-contrast-800));\n background: color-mix(in srgb, var(--_theme-backdrop, var(--color-contrast-200)) 55%, transparent);\n border-color: transparent;\n }\n\n /* Bordered — backdrop fill with themed border */\n :host([variant='bordered']) .chip {\n color: var(--_theme-base, var(--color-contrast-900));\n background: var(--_theme-backdrop, var(--color-contrast-50));\n border-color: var(--_theme-border, var(--color-contrast-300));\n }\n\n :host([variant='bordered']) .remove-btn {\n color: var(--_theme-backdrop, var(--color-contrast-50));\n background: var(--_theme-focus, var(--color-contrast-700));\n border: var(--border) solid var(--_theme-focus, var(--color-contrast-700));\n }\n\n :host([variant='bordered']) .remove-btn:hover {\n background: color-mix(in srgb, var(--_theme-focus, var(--color-contrast-700)) 80%, black);\n opacity: 1;\n }\n\n /* Outline — transparent with colored border */\n :host([variant='outline']) .chip {\n color: var(--_theme-base, var(--color-contrast-900));\n background: transparent;\n border-color: var(--_theme-base, var(--color-contrast-400));\n }\n\n :host([variant='outline']) .remove-btn {\n color: var(--_theme-backdrop, var(--color-contrast-50));\n background: var(--_theme-focus, var(--color-contrast-700));\n border: var(--border) solid var(--_theme-focus, var(--color-contrast-700));\n }\n\n :host([variant='outline']) .remove-btn:hover {\n background: color-mix(in srgb, var(--_theme-focus, var(--color-contrast-700)) 80%, black);\n opacity: 1;\n }\n\n /* Ghost — transparent, no border */\n :host([variant='ghost']) .chip {\n color: var(--_theme-base, var(--color-contrast-900));\n background: transparent;\n border-color: transparent;\n }\n\n :host([variant='ghost']) .remove-btn {\n border: var(--border) solid var(--_theme-focus, var(--color-contrast-400));\n }\n\n :host([variant='ghost']) .remove-btn:hover {\n background: color-mix(in srgb, currentcolor 15%, transparent);\n }\n\n /* ========================================\n Hover / Active Feedback — interactive modes\n ======================================== */\n\n /* Solid (default) */\n :host(:not([variant]):is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip,\n :host([variant='solid']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip {\n background: var(--_theme-focus, var(--color-contrast-800));\n }\n\n :host(:not([variant]):is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip,\n :host([variant='solid']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip {\n background: var(--_theme-content, var(--color-contrast-900));\n box-shadow: var(--inset-shadow-2xs);\n }\n\n /* Flat */\n :host([variant='flat']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-focus, var(--color-contrast-700));\n }\n\n :host([variant='flat']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-content, var(--color-contrast-900));\n box-shadow: var(--inset-shadow-sm);\n }\n\n /* Bordered */\n :host([variant='bordered']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-focus, var(--color-contrast-700));\n border-color: var(--_theme-focus, var(--color-contrast-700));\n }\n\n :host([variant='bordered']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-content, var(--color-contrast-900));\n box-shadow: var(--inset-shadow-sm);\n }\n\n /* Outline */\n :host([variant='outline']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip {\n background: var(--_theme-backdrop, var(--color-contrast-100));\n border-color: var(--_theme-focus, var(--color-contrast-700));\n }\n\n :host([variant='outline']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-base, var(--color-contrast-700));\n box-shadow: var(--inset-shadow-2xs);\n }\n\n /* Ghost */\n :host([variant='ghost']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:hover .chip {\n background: var(--_theme-backdrop, var(--color-contrast-100));\n }\n\n :host([variant='ghost']:is([mode='selectable'], [mode='action']):not([disabled])) .chip-btn:active .chip {\n color: var(--_theme-contrast, var(--color-contrast-50));\n background: var(--_theme-base, var(--color-contrast-700));\n box-shadow: var(--inset-shadow-2xs);\n }\n}\n","import { computed, defineComponent, html, signal, typed, watch } from '@vielzeug/craftit';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport {\n colorThemeMixin,\n disabledStateMixin,\n forcedColorsMixin,\n roundedVariantMixin,\n sizeVariantMixin,\n} from '../../styles';\n// ============================================\n// Styles\n// ============================================\nimport componentStyles from './chip.css?inline';\n\n// ============================================\n// Icons\n// ============================================\n\n// Small close icon for remove button (relative sizing for chip)\nconst CHIP_CLOSE_ICON = html`\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n width=\"0.75em\"\n height=\"0.75em\"\n aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n`;\n\n// ============================================\n// Types\n// ============================================\n\n/** Chip component properties */\ntype ChipBaseProps = {\n /** Accessible label (required for icon-only chips) */\n 'aria-label'?: string;\n /** Theme color */\n color?: ThemeColor;\n /** Disable interactions */\n disabled?: boolean;\n /** Border radius override */\n rounded?: RoundedSize | '';\n /** Component size */\n size?: ComponentSize;\n /** Value associated with this chip — included in emitted event detail */\n value?: string;\n /** Visual style variant */\n variant?: Exclude<VisualVariant, 'glass' | 'text' | 'frost'>;\n};\n\ntype BitChipMode = 'static' | 'removable' | 'selectable' | 'action';\n\n/** Read-only presentation chip */\ntype StaticChipProps = {\n mode?: Extract<BitChipMode, 'static'>;\n};\n\n/** Removable chip mode */\ntype RemovableChipProps = {\n mode: Extract<BitChipMode, 'removable'>;\n};\n\n/** Selectable chip mode */\ntype SelectableChipProps = {\n /** Controlled checked state for `mode=\"selectable\"` */\n checked?: boolean | undefined;\n /** Initial checked state for uncontrolled `mode=\"selectable\"` */\n 'default-checked'?: boolean;\n mode: Extract<BitChipMode, 'selectable'>;\n};\n\n/** Action chip mode — behaves like a button, fires a click event without maintaining state */\ntype ActionChipProps = {\n mode: Extract<BitChipMode, 'action'>;\n};\n\ntype BitChipComponentProps = ChipBaseProps & {\n checked?: boolean | undefined;\n 'default-checked'?: boolean;\n mode?: BitChipMode;\n};\n\nexport type BitChipEvents = {\n change: { checked: boolean; originalEvent: Event; value: string | undefined };\n click: { originalEvent: MouseEvent; value: string | undefined };\n remove: { originalEvent: MouseEvent; value: string | undefined };\n};\n\nexport type BitChipProps = ChipBaseProps &\n (StaticChipProps | RemovableChipProps | SelectableChipProps | ActionChipProps);\n\n/**\n * A compact, styled label element. Supports icons, a remove button, colors, sizes, and variants.\n * Commonly used to represent tags, filters, or selected options in a multiselect field.\n *\n * @element bit-chip\n *\n * @attr {string} aria-label - Accessible label (required for icon-only chips)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} mode - Interaction mode: 'static' | 'removable' | 'selectable' | 'action'\n * @attr {boolean} disabled - Disable the chip\n * @attr {string} value - Value included in emitted event detail\n * @attr {boolean} checked - Controlled checked state for selectable chips\n * @attr {boolean} default-checked - Initial checked state for uncontrolled selectable chips\n *\n * @slot - Chip label text\n * @slot icon - Leading icon or decoration\n *\n * @event remove - Fired when the remove button is clicked, with `detail.value` and `detail.originalEvent`\n * @event change - Fired when a selectable chip toggles, with `detail.checked`, `detail.value`, and `detail.originalEvent`\n * @event click - Fired when an action chip is clicked, with `detail.value` and `detail.originalEvent`\n *\n * @cssprop --chip-bg - Background color\n * @cssprop --chip-color - Text color\n * @cssprop --chip-border-color - Border color\n * @cssprop --chip-radius - Border radius\n * @cssprop --chip-font-size - Font size\n * @cssprop --chip-font-weight - Font weight\n * @cssprop --chip-padding-x - Horizontal padding\n * @cssprop --chip-padding-y - Vertical padding\n * @cssprop --chip-gap - Gap between icon, label and remove button\n *\n * @example\n * ```html\n * <!-- Static chip (read-only) -->\n * <bit-chip color=\"primary\">Design</bit-chip>\n *\n * <!-- Removable chip -->\n * <bit-chip color=\"success\" variant=\"flat\" mode=\"removable\" value=\"ts\">\n * TypeScript\n * </bit-chip>\n *\n * <!-- Selectable chip (controlled) -->\n * <bit-chip color=\"info\" variant=\"flat\" mode=\"selectable\" checked value=\"ui\">\n * UI\n * </bit-chip>\n *\n * <!-- Selectable chip (uncontrolled) -->\n * <bit-chip color=\"info\" variant=\"flat\" mode=\"selectable\" default-checked value=\"ui\">\n * UI\n * </bit-chip>\n *\n * <!-- Action chip (acts like a button) -->\n * <bit-chip color=\"warning\" mode=\"action\" value=\"add\">\n * <svg slot=\"icon\" ...></svg>\n * Add Item\n * </bit-chip>\n *\n * <!-- Icon-only chip -->\n * <bit-chip color=\"error\" mode=\"action\" aria-label=\"Delete\">\n * <svg slot=\"icon\" ...></svg>\n * </bit-chip>\n * ```\n */\nexport const CHIP_TAG = defineComponent<BitChipComponentProps, BitChipEvents>({\n props: {\n 'aria-label': typed<BitChipComponentProps['aria-label']>(undefined),\n checked: typed<BitChipComponentProps['checked']>(undefined, {\n parse: (value) => (value == null ? undefined : value !== 'false'),\n }),\n color: typed<BitChipComponentProps['color']>(undefined),\n 'default-checked': typed<boolean>(false),\n disabled: typed<boolean>(false),\n mode: typed<BitChipMode>('static'),\n rounded: typed<BitChipComponentProps['rounded']>(undefined),\n size: typed<BitChipComponentProps['size']>(undefined),\n value: typed<BitChipComponentProps['value']>(undefined),\n variant: typed<BitChipComponentProps['variant']>(undefined),\n },\n setup({ emit, host, props }) {\n const checkedProp = props.checked;\n const ariaLabelProp = props['aria-label'];\n // ============================================\n // State Management\n // ============================================\n // Once a checked prop is provided, treat the chip as controlled for the rest of its lifecycle.\n const isControlled = signal(checkedProp.value !== undefined);\n // Internal tracking for uncontrolled selectable chips; seeded from default-checked.\n const checkedState = signal(!isControlled.value && props['default-checked'].value);\n\n watch(checkedProp, (value) => {\n if (value !== undefined) {\n isControlled.value = true;\n }\n });\n\n // Effective checked value — reactive to checked prop changes in controlled mode.\n const isChecked = computed(() => {\n if (props.mode.value !== 'selectable') return false;\n\n if (isControlled.value) {\n return checkedProp.value ?? false;\n }\n\n return checkedState.value;\n });\n\n // Sync the [checked] attribute for CSS selectors across controlled and uncontrolled modes.\n watch(\n [isChecked, props.mode],\n () => {\n host.toggleAttribute('checked', props.mode.value === 'selectable' && isChecked.value);\n },\n { immediate: true },\n );\n // ============================================\n // Event Handlers\n // ============================================\n function handleRemove(e: MouseEvent) {\n e.stopPropagation();\n\n if (props.disabled.value) return;\n\n // Button's disabled attribute prevents this from firing when disabled\n emit('remove', { originalEvent: e, value: props.value.value });\n }\n function handleSelectableActivate(e: MouseEvent) {\n e.stopPropagation();\n\n if (props.disabled.value) return;\n\n const nextChecked = !isChecked.value;\n\n if (!isControlled.value) {\n checkedState.value = nextChecked;\n }\n\n emit('change', { checked: nextChecked, originalEvent: e, value: props.value.value });\n }\n function handleActionClick(e: MouseEvent) {\n e.stopPropagation();\n\n if (props.disabled.value) return;\n\n emit('click', { originalEvent: e, value: props.value.value });\n }\n\n // ============================================\n // Template Helpers\n // ============================================\n const renderChipContent = () => html`\n <slot name=\"icon\"></slot>\n <span class=\"label\"><slot></slot></span>\n `;\n const renderRemoveButton = () => html`\n <button\n class=\"remove-btn\"\n part=\"remove-btn\"\n type=\"button\"\n :aria-label=\"${() => {\n const label = ariaLabelProp.value || props.value.value;\n\n return label ? `Remove ${label}` : 'Remove';\n }}\"\n ?hidden=\"${() => props.mode.value !== 'removable'}\"\n :disabled=\"${() => props.disabled.value}\"\n @click=\"${handleRemove}\">\n ${CHIP_CLOSE_ICON}\n </button>\n `;\n const renderSelectableChip = () => html`\n <button\n class=\"chip-btn\"\n part=\"chip-btn\"\n type=\"button\"\n role=\"checkbox\"\n :aria-checked=\"${() => String(isChecked.value)}\"\n :aria-label=\"${() => ariaLabelProp.value}\"\n :disabled=\"${() => props.disabled.value}\"\n @click=\"${handleSelectableActivate}\">\n <span class=\"chip\" part=\"chip\"> ${renderChipContent()} </span>\n </button>\n `;\n const renderActionChip = () => html`\n <button\n class=\"chip-btn\"\n part=\"chip-btn\"\n type=\"button\"\n :aria-label=\"${() => ariaLabelProp.value}\"\n :disabled=\"${() => props.disabled.value}\"\n @click=\"${handleActionClick}\">\n <span class=\"chip\" part=\"chip\"> ${renderChipContent()} </span>\n </button>\n `;\n const renderStaticChip = () => html` <span class=\"chip\" part=\"chip\"> ${renderChipContent()} </span> `;\n const renderRemovableChip = () => html`\n <span class=\"chip\" part=\"chip\"> ${renderChipContent()} ${renderRemoveButton()} </span>\n `;\n\n // ============================================\n // Render\n // ============================================\n return html`\n ${() => {\n const mode = props.mode.value;\n\n if (mode === 'selectable') return renderSelectableChip();\n\n if (mode === 'action') return renderActionChip();\n\n if (mode === 'removable') return renderRemovableChip();\n\n return renderStaticChip();\n }}\n `;\n },\n styles: [\n colorThemeMixin,\n disabledStateMixin(),\n roundedVariantMixin,\n sizeVariantMixin({\n lg: {\n '--_font-size': 'var(--text-sm)',\n '--_gap': 'var(--size-1-5)',\n '--_padding-x': 'var(--size-3)',\n '--_padding-y': 'var(--size-1)',\n },\n sm: {\n '--_font-size': 'var(--text-xs)',\n '--_gap': 'var(--size-0-5)',\n '--_padding-x': 'var(--size-2-5)',\n '--_padding-y': 'var(--size-px)',\n },\n }),\n forcedColorsMixin,\n componentStyles,\n ],\n tag: 'bit-chip',\n});\n","@layer buildit.base {\n :host {\n --_height: var(--progress-height, var(--size-2, 0.5rem));\n --_radius: var(--progress-radius, var(--rounded-full, 9999px));\n --_circle-size: var(--progress-circle-size, 6rem);\n --_circular-label-size: var(--progress-circular-label-size, var(--text-xl, 1.25rem));\n --_circular-title-size: var(--progress-circular-title-size, var(--text-xs, 0.75rem));\n\n display: block;\n\n /* Stretch to fill the parent container (matches native <progress> behaviour).\n The host's width is set against its parent, so % widths inside shadow DOM\n (.track, .fill) resolve correctly in any flex/grid/block context. */\n width: 100%;\n }\n\n /* ========================================\n Linear Bar\n ======================================== */\n\n .track {\n width: 100%;\n height: var(--_height);\n overflow: hidden;\n\n /* contrast-300 (88% lightness) gives a visible groove in light mode */\n background: var(--progress-track-bg, var(--color-contrast-300, #ddd));\n border-radius: var(--_radius);\n }\n\n .fill {\n width: var(--_percent, 0%);\n height: 100%;\n background: var(--progress-fill, var(--_theme-base, #3b82f6));\n border-radius: inherit;\n transform-origin: left;\n transition: var(--_motion-transition, width var(--transition-normal));\n }\n\n /* In RTL the fill grows from the inline-end (physical right) side */\n :host(:dir(rtl)) .fill {\n transform-origin: right;\n }\n\n /* Indeterminate: sliding bar */\n @keyframes bit-progress-slide {\n 0% {\n transform: translateX(-150%) scaleX(0.6);\n }\n\n 50% {\n transform: translateX(50%) scaleX(1);\n }\n\n 100% {\n transform: translateX(300%) scaleX(0.6);\n }\n }\n\n :host([indeterminate]) .fill {\n width: 40%;\n animation: var(--_motion-animation, bit-progress-slide 1.5s cubic-bezier(0.4, 0, 0.2, 1) infinite);\n }\n\n /* In RTL the indeterminate bar sweeps right-to-left */\n :host(:dir(rtl)[indeterminate]) .fill {\n animation-direction: reverse;\n }\n\n /* ========================================\n Wrapper / Label / Title / Floating label\n ======================================== */\n\n /* Flex-column shell for the linear variant */\n .wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--progress-label-gap, var(--space-1, 0.25rem));\n width: 100%;\n }\n\n /* Header row ─ visible only when [title] is present */\n .header {\n display: none;\n gap: var(--space-2, 0.5rem);\n align-items: baseline;\n justify-content: space-between;\n }\n\n :host([title]) .header {\n display: flex;\n }\n\n .progress-title {\n font-size: var(--text-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: 1.25;\n color: var(--progress-title-color, currentColor);\n }\n\n /* Label inside the header ─ only when both [title] and [label] are set */\n .header-label {\n display: none;\n }\n\n :host([title][label]) .header-label {\n display: inline;\n }\n\n /* Bar row ─ transparent wrapper by default; becomes a flex row when\n [label] is present without [title] so the label sits beside the bar */\n .bar-row {\n display: contents;\n }\n\n :host([label]:not([title])) .bar-row {\n display: flex;\n gap: var(--progress-label-gap, var(--space-2, 0.5rem));\n align-items: center;\n width: 100%;\n }\n\n /* Outer track container ─ always position:relative for floating-label */\n .track-outer {\n position: relative;\n width: 100%;\n }\n\n :host([label]:not([title])) .track-outer {\n flex: 1 1 0%;\n width: auto;\n min-width: 0;\n }\n\n /* Shared label typography */\n .end-label {\n flex-shrink: 0;\n font-size: var(--text-sm, 0.875rem);\n line-height: 1.25;\n color: var(--progress-label-color, currentColor);\n white-space: nowrap;\n }\n\n /* Trailing end label ─ shown only when [label] is present without [title] */\n .row-label {\n display: none;\n }\n\n :host([label]:not([title])) .row-label {\n display: inline;\n }\n\n /* Floating label chip ─────────────────────────────────────────────────\n Positioned above the fill endpoint.\n Formula: left = X% (fill width) − Y (half chip width)\n Implemented as: left: var(--_percent); transform: translateX(-50%) */\n .floating-label {\n position: absolute;\n bottom: calc(100% + var(--space-1, 0.25rem));\n left: var(--_percent, 0%);\n display: none;\n padding: var(--space-0-5, 0.125rem) var(--space-2, 0.5rem);\n font-size: var(--text-xs, 0.75rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: 1;\n color: var(--color-white, #fff);\n white-space: nowrap;\n pointer-events: none;\n user-select: none;\n background: var(--progress-fill, var(--_theme-base, #3b82f6));\n border-radius: var(--rounded-md, 0.375rem);\n transform: translateX(-50%);\n }\n\n :host([floating-label]:not([indeterminate])) .floating-label {\n display: block;\n }\n\n /* Reserve vertical space above the track so the chip does not clip */\n :host([floating-label]:not([indeterminate])) .wrapper {\n padding-top: calc(var(--text-xs, 0.75rem) + var(--space-1, 0.25rem) * 3);\n }\n\n /* ========================================\n Circular variant\n ======================================== */\n\n .circular-track {\n position: relative; /* anchor the inner text overlay */\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--_circle-size);\n height: var(--_circle-size);\n }\n\n .circular-track svg {\n width: 100%;\n height: 100%;\n overflow: visible;\n transform: rotate(-90deg);\n }\n\n /* Inner overlay — label + title stacked and centered inside the ring */\n .circular-inner {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n gap: var(--space-0-5, 0.125rem);\n align-items: center;\n justify-content: center;\n\n /* Inset from the stroke edge so text stays clear of the ring */\n padding: calc(8% + var(--_height));\n overflow: hidden;\n text-align: center;\n pointer-events: none;\n }\n\n .circular-label {\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--_circular-label-size);\n font-weight: var(--font-weight-semibold, 600);\n line-height: 1;\n color: var(--progress-label-color, currentColor);\n white-space: nowrap;\n }\n\n .circular-title {\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--_circular-title-size);\n line-height: 1.25;\n color: var(--progress-title-color, var(--color-contrast-500, #6b7280));\n white-space: nowrap;\n }\n\n /* Hide empty inner text nodes so flexbox gap doesn't create phantom space */\n .circular-label:empty,\n .circular-title:empty {\n display: none;\n }\n\n .circle-bg {\n fill: none;\n stroke: var(--progress-track-bg, var(--color-contrast-300, #ddd));\n stroke-width: var(--progress-stroke-width, calc(var(--_height) * 1.2));\n }\n\n .circle-fill {\n fill: none;\n stroke: var(--progress-fill, var(--_theme-base, #3b82f6));\n stroke-width: var(--progress-stroke-width, calc(var(--_height) * 1.2));\n stroke-linecap: round;\n transition: var(--_motion-transition, stroke-dashoffset var(--transition-normal));\n }\n\n @keyframes bit-progress-spin {\n from {\n transform: rotate(-90deg);\n }\n\n to {\n transform: rotate(270deg);\n }\n }\n\n @keyframes bit-progress-dash {\n 0% {\n stroke-dasharray: 1px var(--_circ);\n stroke-dashoffset: var(--_circ);\n }\n\n 40% {\n stroke-dasharray: calc(var(--_circ) * 0.75) var(--_circ);\n stroke-dashoffset: calc(var(--_circ) * -0.1);\n }\n\n 60% {\n stroke-dasharray: calc(var(--_circ) * 0.75) var(--_circ);\n stroke-dashoffset: calc(var(--_circ) * -0.1);\n }\n\n 100% {\n stroke-dasharray: 1px var(--_circ);\n stroke-dashoffset: calc(var(--_circ) * -0.9);\n }\n }\n\n :host([indeterminate]) .circular-track svg {\n animation: var(--_motion-animation, bit-progress-spin 1.4s linear infinite);\n }\n\n :host([indeterminate]) .circle-fill {\n animation: var(--_motion-animation, bit-progress-dash 1.4s ease-in-out infinite);\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --_height: var(--size-1, 0.25rem);\n --_circle-size: 4rem;\n --_circular-label-size: var(--text-sm, 0.875rem);\n --_circular-title-size: var(--text-2xs, 0.625rem);\n }\n\n :host([size='md']) {\n --_height: var(--size-2, 0.5rem);\n --_circle-size: 6rem;\n }\n\n :host([size='lg']) {\n --_height: var(--size-3-5, 0.875rem);\n --_circle-size: 9rem;\n --_circular-label-size: var(--text-3xl, 1.875rem);\n --_circular-title-size: var(--text-sm, 0.875rem);\n }\n}\n\n/* Extra indeterminate state overrides — cannot be expressed via CSS variables alone */\n@media (prefers-reduced-motion: reduce) {\n :host([indeterminate]) .fill {\n width: 100%;\n opacity: 0.6;\n }\n\n :host([indeterminate]) .circle-fill {\n stroke-dasharray: none;\n }\n}\n","import { computed, defineComponent, html, watch } from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { colorThemeMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport componentStyles from './progress.css?inline';\n\n/** Progress bar component properties */\nexport type BitProgressProps = {\n /** Theme color for the fill bar */\n color?: ThemeColor;\n /** Floating chip centered above the fill endpoint (linear only). Hidden in indeterminate mode. Position formula: left = fill% − half chip width (CSS: left:X%; transform:translateX(−50%)). */\n 'floating-label'?: string;\n /** When true, shows an infinite animation — use when progress is unknown. */\n indeterminate?: boolean;\n /** Accessible name AND visible text label.\n * - Linear without `title`: rendered at the end of the bar.\n * - Linear with `title`: moved into the header row above the bar.\n * - Circular: large text centered inside the ring. */\n label?: string;\n /** Maximum value. Defaults to 100. */\n max?: number;\n /** Size variant controlling bar height */\n size?: ComponentSize;\n /** Title text.\n * - Linear: displayed as a header above the bar; moves `label` into the header row.\n * - Circular: smaller text displayed below the `label` inside the ring. */\n title?: string;\n /** 'linear' (default) or 'circular' */\n type?: 'linear' | 'circular';\n /** Current progress value (0 to `max`). Ignored when `indeterminate`. */\n value?: number;\n /** Human-readable value text for screen readers (e.g. \"Step 2 of 5\", \"75%\"). Overrides the raw aria-valuenow when set. */\n 'value-text'?: string;\n};\n\n/**\n * A linear progress bar for conveying operation progress.\n * Supports determinate (known value) and indeterminate (unknown duration) modes.\n *\n * @element bit-progress\n *\n * @attr {number} value - Current value (0–max). Defaults to 0.\n * @attr {number} max - Maximum value. Defaults to 100.\n * @attr {boolean} indeterminate - Show infinite animation (ignores value/max).\n * @attr {string} color - Theme color: 'primary' | 'success' | 'warning' | 'error' | …\n * @attr {string} size - Bar height: 'sm' | 'md' | 'lg'\n * @attr {string} label - Visible text label + accessible name. Linear: at bar end (or header row with title). Circular: large text centered inside the ring.\n * @attr {string} title - Title text. Linear: header above the bar (moves label to header row). Circular: smaller text below the label inside the ring.\n * @attr {string} floating-label - Floating chip centered above the fill endpoint (linear only); hidden when indeterminate.\n *\n * @cssprop --progress-height - Bar height override\n * @cssprop --progress-track-bg - Track background color\n * @cssprop --progress-fill - Fill bar color\n * @cssprop --progress-radius - Border radius\n * @cssprop --progress-label-gap - Gap between header/bar row and between bar and trailing label (default 0.25 rem)\n * @cssprop --progress-title-color - Title text color (defaults to currentColor)\n * @cssprop --progress-label-color - Label text color (defaults to currentColor)\n * @cssprop --progress-circle-size - Circular indicator diameter (default 6rem)\n * @cssprop --progress-circular-label-size - Font size of the label inside the ring (default --text-xl)\n * @cssprop --progress-circular-title-size - Font size of the title inside the ring (default --text-xs)\n *\n * @example\n * ```html\n * <bit-progress value=\"45\"></bit-progress>\n * <bit-progress value=\"75\" max=\"100\" color=\"success\" size=\"lg\"></bit-progress>\n * <bit-progress indeterminate color=\"primary\" label=\"Loading…\"></bit-progress>\n * ```\n */\nexport const PROGRESS_TAG = defineComponent<BitProgressProps>({\n props: {\n color: { default: undefined },\n 'floating-label': { default: undefined },\n indeterminate: { default: false },\n label: { default: undefined },\n max: { default: 100 },\n size: { default: undefined },\n title: { default: undefined },\n type: { default: 'linear' },\n value: { default: 0 },\n 'value-text': { default: undefined },\n },\n setup({ host, props }) {\n // The SVG circle circumference for a radius of 45 (viewBox 0 0 100 100)\n const RADIUS = 45;\n const CIRC = 2 * Math.PI * RADIUS; // ~282.7\n const percent = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return `${(v / m) * 100}%`;\n });\n const dashoffset = computed(() => {\n const v = Math.max(0, Math.min(Number(props.value.value), Number(props.max.value)));\n const m = Math.max(1, Number(props.max.value));\n\n return CIRC - (v / m) * CIRC;\n });\n const isCircular = computed(() => props.type.value === 'circular');\n\n // Use watch([...], fn, { immediate: true }) at setup-level so it fires during\n // connectedCallback (when attributes are already synced) rather than deferring\n // to onMount. The immediate flag triggers the first run synchronously.\n watch(\n [props.value, props.max, props.indeterminate],\n () => {\n host.style.setProperty('--_percent', props.indeterminate.value ? '0%' : percent.value);\n },\n { immediate: true },\n );\n\n return html`\n ${() =>\n isCircular.value\n ? html` <div\n class=\"circular-track\"\n role=\"progressbar\"\n :aria-valuenow=\"${() => (props.indeterminate.value ? null : String(props.value.value))}\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"${() => String(props.max.value)}\"\n :aria-label=\"${() => props.label.value ?? props.title.value ?? 'Progress'}\"\n :aria-valuetext=\"${() => props['value-text'].value ?? null}\"\n :style=\"${() => `--_circ:${CIRC}px`}\">\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle class=\"circle-bg\" cx=\"50\" cy=\"50\" r=\"${RADIUS}\"></circle>\n <circle\n class=\"circle-fill\"\n cx=\"50\"\n cy=\"50\"\n r=\"${RADIUS}\"\n :stroke-dasharray=\"${() => (props.indeterminate.value ? undefined : `${CIRC}px`)}\"\n :stroke-dashoffset=\"${() =>\n props.indeterminate.value ? undefined : `${dashoffset.value}px`}\"></circle>\n </svg>\n <div class=\"circular-inner\">\n <span class=\"circular-label\">${() => props.label.value}</span>\n <span class=\"circular-title\">${() => props.title.value}</span>\n </div>\n </div>`\n : html` <div class=\"wrapper\">\n <div class=\"header\">\n <span class=\"progress-title\">${() => props.title.value}</span>\n <span class=\"end-label header-label\">${() => props.label.value}</span>\n </div>\n <div class=\"bar-row\">\n <div class=\"track-outer\">\n <div\n class=\"track\"\n role=\"progressbar\"\n :aria-valuenow=\"${() => (props.indeterminate.value ? null : String(props.value.value))}\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"${() => String(props.max.value)}\"\n :aria-label=\"${() => props.label.value ?? props.title.value ?? 'Progress'}\"\n :aria-valuetext=\"${() => props['value-text'].value ?? null}\">\n <div\n class=\"fill\"\n part=\"fill\"\n :style=\"${() => (!props.indeterminate.value ? `width:${percent.value}` : null)}\"></div>\n </div>\n <span class=\"floating-label\">${() => props['floating-label'].value}</span>\n </div>\n <span class=\"end-label row-label\">${() => props.label.value}</span>\n </div>\n </div>`}\n `;\n },\n styles: [colorThemeMixin, forcedColorsMixin, reducedMotionMixin, componentStyles],\n tag: 'bit-progress',\n});\n","import{onCleanup as e}from\"../core/runtime-lifecycle.js\";import\"../core/runtime.js\";import{signal as t}from\"@vielzeug/stateit\";var n=n=>{let r=t({height:0,width:0}),i=new ResizeObserver(([e])=>{if(!e)return;let t=e.contentBoxSize[0];t&&(r.value={height:t.blockSize,width:t.inlineSize})});return i.observe(n),e(()=>i.disconnect()),r},r=(n,r)=>{let i=t(null),a=new IntersectionObserver(([e])=>{e&&(i.value=e)},r);return a.observe(n),e(()=>a.disconnect()),i},i=n=>{let r=window.matchMedia(n),i=t(r.matches),a=e=>{i.value=e.matches};return r.addEventListener(`change`,a),e(()=>r.removeEventListener(`change`,a)),i};export{r as observeIntersection,i as observeMedia,n as observeResize};\n//# sourceMappingURL=observers.js.map","var e=e=>{let t=(e,t,n=!1)=>e<0?{index:-1,moved:!1,reason:`no-enabled-item`,wrapped:n}:e===t?{index:e,moved:!1,reason:`unchanged`,wrapped:n}:{index:e,moved:!0,reason:`moved`,wrapped:n},n={index:-1,moved:!1,reason:`empty`,wrapped:!1},r=(t,n)=>e.isItemDisabled?e.isItemDisabled(t,n):!!t.disabled,i=(e,t)=>{for(let n=t;n<e.length;n++)if(!r(e[n],n))return n;return-1},a=(e,t)=>{for(let n=t;n>=0;n--)if(!r(e[n],n))return n;return-1},o=r=>{let a=e.getItems();if(a.length===0)return n;let o=e.getIndex(),s=i(a,Math.max(0,r));return s===-1?e.loop?t(i(a,0),o,!0):t(o,o):t(s,o)};return{first:()=>{let r=e.getItems();if(r.length===0)return n;let a=e.getIndex(),o=t(i(r,0),a);return o.index>=0&&e.setIndex(o.index),o},getActiveItem:()=>{let t=e.getItems(),n=e.getIndex();if(!(n<0||n>=t.length))return t[n]},getEnabledIndex:o,last:()=>{let r=e.getItems();if(r.length===0)return n;let i=e.getIndex(),o=t(a(r,r.length-1),i);return o.index>=0&&e.setIndex(o.index),o},next:()=>{let r=e.getItems();if(r.length===0)return n;let a=e.getIndex(),o=i(r,Math.max(0,a+1));if(o!==-1)return e.setIndex(o),t(o,a);if(e.loop){let n=i(r,0);return n!==-1&&e.setIndex(n),t(n,a,!0)}return t(a,a)},prev:()=>{let r=e.getItems();if(r.length===0)return n;let i=e.getIndex(),o=a(r,i-1);if(o!==-1)return e.setIndex(o),t(o,i);if(e.loop){let n=a(r,r.length-1);return n!==-1&&e.setIndex(n),t(n,i,!0)}return t(i,i)},reset:()=>{e.setIndex(-1)},set:t=>{let n=o(t);return n.index>=0&&e.setIndex(n.index),n}}};export{e as createListNavigation};\n//# sourceMappingURL=list.js.map","import{autoUpdate as e}from\"@vielzeug/floatit\";var t=t=>{let n=null,r=()=>typeof t.restoreFocus==`function`?t.restoreFocus():t.restoreFocus??!0,i=()=>{let r=t.positioner;if(n?.(),n=null,!r)return;let i=r.reference(),a=r.floating();if(!i||!a){r.update();return}n=e(i,a,r.update)},a=()=>{n?.(),n=null},o=e=>{if(t.isDisabled?.()||t.isOpen())return;let n=e?.reason??`programmatic`;t.setOpen(!0,{reason:n}),i(),requestAnimationFrame(()=>t.positioner?.update()),t.onOpen?.(n)},s=e=>{if(!t.isOpen())return;let n=e?.reason??`programmatic`;t.setOpen(!1,{reason:n}),a(),(e?.restoreFocus??r())&&t.getTriggerElement?.()?.focus(),t.onClose?.(n)};return{bindOutsideClick:(e=document,n=!0)=>{let r=e=>{if(!t.isOpen())return;let n=t.getBoundaryElement(),r=t.getPanelElement?.(),i=e.target,a=typeof e.composedPath==`function`?e.composedPath():[];i&&(n&&(n.contains(i)||a.includes(n))||r&&(r.contains(i)||a.includes(r))||s({reason:`outside-click`}))};return e.addEventListener(`click`,r,n),()=>{e.removeEventListener(`click`,r,n)}},close:s,open:o,toggle:()=>{if(t.isOpen()){s({reason:`toggle`});return}o({reason:`toggle`})}}};export{t as createOverlayControl};\n//# sourceMappingURL=overlay.js.map","var e=e=>{let t=()=>e.getSelected().map(e.keyExtractor),n=e=>t().includes(e);return{clear:()=>{e.setSelected([])},isSelected:n,remove:t=>{e.setSelected(e.getSelected().filter(n=>e.keyExtractor(n)!==t))},select:t=>{let r=e.findByKey(t);if(r){if(e.getMode()===`single`){e.setSelected([r]);return}n(t)||e.setSelected([...e.getSelected(),r])}},serialize:(e=`,`)=>t().join(e),toggle:t=>{let r=e.findByKey(t);if(r){if(e.getMode()===`single`){e.setSelected([r]);return}if(n(t)){e.setSelected(e.getSelected().filter(n=>e.keyExtractor(n)!==t));return}e.setSelected([...e.getSelected(),r])}}}};export{e as createSelectionControl};\n//# sourceMappingURL=selection.js.map","import{effect as e,onMount as t}from\"../core/runtime-lifecycle.js\";import{createId as n}from\"../core/utilities.js\";import\"../core/runtime.js\";function r(r,i){let a=i.labelId||n(`a11y-label`),o=i.helperId||n(`a11y-helper`),s=null;return r.setAttribute(`role`,i.role),t(()=>{let t=r.shadowRoot;if(t&&(s=t.querySelector(`[data-a11y-helper]`)),t){let e=t.querySelector(`[data-a11y-label]`);if(e){let t=e.querySelector(`slot`);(t?t.assignedNodes().length>0:e.textContent?.trim().length??!1)&&(e.id=a,r.setAttribute(`aria-labelledby`,a))}}e(()=>{if(i.checked){let e=i.checked();e!==void 0&&r.setAttribute(`aria-checked`,e)}if(i.invalid){let e=i.invalid();r.setAttribute(`aria-invalid`,String(e))}if(i.helperText&&s){let e=i.helperText();e?(s.textContent=e,s.hidden=!1,r.setAttribute(`aria-describedby`,o),(i.helperTone?.()??`default`)===`error`?s.setAttribute(`role`,`alert`):s.removeAttribute(`role`)):(s.hidden=!0,r.removeAttribute(`aria-describedby`))}})}),{helperId:o,labelId:a}}export{r as useA11yControl};\n//# sourceMappingURL=a11y.js.map","import{signal as e}from\"@vielzeug/stateit\";function t(t){let n=t.indeterminate??e(!1);return{changePayload:e=>({checked:t.checked.value,fieldValue:t.value.value??``,originalEvent:e,value:t.checked.value}),checked:t.checked,indeterminate:n,toggle:e=>{if(!(t.disabled.value??!1)){if(t.group){n.value=!1,t.group.toggle(t.value.value??``,e),t.onToggle?.(e);return}t.clearIndeterminateFirst&&n.value||(t.checked.value=!t.checked.value),n.value=!1,t.onToggle?.(e)}}}}export{t as createCheckableControl};\n//# sourceMappingURL=selectable.js.map","@layer buildit.base {\n :host {\n --_bg: var(--skeleton-bg, var(--color-contrast-200));\n --_highlight: var(--skeleton-highlight, var(--color-contrast-100));\n --_radius: var(--skeleton-radius, var(--rounded-lg));\n --_circle-size: var(--skeleton-size, var(--size-10));\n --_width: var(--skeleton-width, 100%);\n --_height: var(--skeleton-height, var(--size-4));\n --_line-gap: var(--skeleton-line-gap, var(--size-2));\n --_last-line-width: var(--skeleton-last-line-width, 60%);\n --_duration: var(--skeleton-duration, 1.6s);\n --_stripe-size: var(--skeleton-stripe-size, 8px);\n\n display: inline-block;\n width: var(--_width);\n height: var(--_height);\n }\n\n .stack {\n display: grid;\n gap: var(--_line-gap);\n width: 100%;\n height: 100%;\n }\n\n .bone {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--_bg);\n border-radius: var(--_radius);\n }\n\n .bone::after {\n position: absolute;\n inset: 0;\n content: '';\n background: linear-gradient(90deg, var(--_bg) 0%, var(--_highlight) 50%, var(--_bg) 100%);\n transform: translateX(-100%);\n animation: var(--_motion-animation, bit-skeleton-shimmer var(--_duration) linear infinite);\n }\n\n :host([data-animated='false']) .bone::after {\n display: none;\n }\n\n /* Pause shimmer when scrolled out of the viewport — no visible effect, saves GPU */\n :host([data-paused]) .bone::after {\n animation-play-state: paused;\n }\n\n @keyframes bit-skeleton-shimmer {\n to {\n transform: translateX(100%);\n }\n }\n\n /* In RTL the shimmer should sweep right-to-left */\n :host(:dir(rtl)) .bone::after {\n animation-direction: reverse;\n }\n}\n\n@layer buildit.variants {\n /* Circle variant — avatars, icons */\n :host([variant='circle']) {\n --_radius: var(--rounded-full);\n\n width: var(--skeleton-width, var(--_circle-size));\n height: var(--skeleton-height, var(--_circle-size));\n aspect-ratio: 1 / 1;\n }\n\n /* Text variant — thinner, for inline text lines */\n :host([variant='text']) {\n --_height: var(--size-3);\n --_radius: var(--rounded-sm);\n\n height: auto;\n }\n\n :host([variant='text']) .stack {\n height: auto;\n }\n\n :host([variant='text']) .bone {\n height: var(--_height);\n }\n\n :host([variant='text']) .bone[data-last='true'] {\n width: var(--_last-line-width);\n }\n}\n\n@layer buildit.striped {\n :host([striped]) .stack {\n width: 99%;\n }\n\n :host([striped]) .bone {\n --_stripe-color: var(--skeleton-stripe-color, var(--color-contrast-400));\n\n background-color: transparent;\n border: var(--border) dashed var(--_stripe-color);\n }\n\n :host([striped]) .bone::before {\n --_stripe-color: var(--skeleton-stripe-color, var(--color-contrast-300));\n\n position: absolute;\n inset: 0;\n content: '';\n background-color: var(--_stripe-color);\n mask-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cline x1='0' y1='8' x2='8' y2='0' stroke='white' stroke-width='1'/%3E%3C/svg%3E\");\n mask-size: var(--_stripe-size) var(--_stripe-size);\n }\n\n :host([striped]) .bone::after {\n display: none;\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --_height: var(--size-3);\n --_circle-size: var(--size-8);\n }\n\n :host([size='md']) {\n --_height: var(--size-4);\n --_circle-size: var(--size-10);\n }\n\n :host([size='lg']) {\n --_height: var(--size-6);\n --_circle-size: var(--size-14);\n }\n}\n\n@media (forced-colors: active) {\n .bone {\n background: ButtonFace;\n border: 1px solid ButtonText;\n }\n\n .bone::after {\n display: none;\n }\n}\n","import { computed, defineComponent, html, onMount, watch } from '@vielzeug/craftit';\nimport { observeIntersection } from '@vielzeug/craftit/labs';\n\nimport type { ComponentSize } from '../../types';\n\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './skeleton.css?inline';\n\n/** Skeleton loader component properties */\nexport type BitSkeletonProps = {\n /** Toggle shimmer animation */\n animated?: boolean;\n /** Height override (e.g. '1rem', '3rem') */\n height?: string;\n /** Number of text lines for `variant='text'` */\n lines?: number;\n /** Radius override (e.g. '9999px', 'var(--rounded-xl)') */\n radius?: string;\n /** Size preset controlling line height and circle size */\n size?: ComponentSize;\n /** Render diagonal stripes instead of the shimmer — useful as a design-mode placeholder */\n striped?: boolean;\n /** Visual variant: 'rect' (default), 'circle', or 'text' */\n variant?: 'rect' | 'circle' | 'text';\n /** Width override (e.g. '12rem', '70%') */\n width?: string;\n};\n\n/**\n * A shimmer placeholder that represents loading content.\n * Control dimensions via the `--skeleton-width` and `--skeleton-height` CSS custom properties,\n * or via `width` / `height` inline styles.\n *\n * @element bit-skeleton\n *\n * @attr {string} variant - Shape: 'rect' (default) | 'circle' | 'text'\n * @attr {string} size - Height/circle preset: 'sm' | 'md' | 'lg'\n * @attr {string} width - Width override (CSS length/percentage)\n * @attr {string} height - Height override (CSS length)\n * @attr {string} radius - Radius override\n * @attr {boolean} animated - Disable with `animated=\"false\"`\n * @attr {number} lines - Text line count (only for `variant='text'`)\n * @attr {boolean} striped - Replace shimmer with diagonal stripes\n *\n * @cssprop --skeleton-bg - Base shimmer color\n * @cssprop --skeleton-highlight - Shimmer highlight color\n * @cssprop --skeleton-radius - Border radius\n * @cssprop --skeleton-size - Circle fallback size\n * @cssprop --skeleton-width - Width (default: 100%)\n * @cssprop --skeleton-height - Height (default: var(--size-4))\n * @cssprop --skeleton-line-gap - Vertical gap between text lines\n * @cssprop --skeleton-last-line-width - Width of the final text line\n * @cssprop --skeleton-duration - Shimmer animation duration\n * @cssprop --skeleton-stripe-size - Width of each diagonal stripe (default: 6px)\n *\n * @example\n * ```html\n * <!-- Paragraph lines -->\n * <bit-skeleton variant=\"text\" lines=\"3\" width=\"100%\"></bit-skeleton>\n *\n * <!-- Avatar -->\n * <bit-skeleton variant=\"circle\" size=\"md\"></bit-skeleton>\n *\n * <!-- Card image -->\n * <bit-skeleton width=\"100%\" height=\"10rem\"></bit-skeleton>\n * ```\n */\nexport const SKELETON_TAG = defineComponent<BitSkeletonProps>({\n props: {\n animated: { default: true },\n height: { default: undefined },\n lines: { default: 1 },\n radius: { default: undefined },\n size: { default: undefined },\n striped: { default: false },\n variant: { default: 'rect' },\n width: { default: undefined },\n },\n setup({ host, props }) {\n const lineCount = computed(() => {\n const value = Math.floor(Number(props.lines.value));\n\n return Number.isFinite(value) && value > 0 ? value : 1;\n });\n const renderLineCount = computed(() => (props.variant.value === 'text' ? lineCount.value : 1));\n\n watch(\n [props.width, props.height, props.radius, props.animated],\n () => {\n if (props.width.value) host.style.setProperty('--skeleton-width', props.width.value);\n else host.style.removeProperty('--skeleton-width');\n\n if (props.height.value) host.style.setProperty('--skeleton-height', props.height.value);\n else host.style.removeProperty('--skeleton-height');\n\n if (props.radius.value) host.style.setProperty('--skeleton-radius', props.radius.value);\n else host.style.removeProperty('--skeleton-radius');\n\n const rawAnimated = host.getAttribute('animated');\n const isAnimated = rawAnimated !== 'false' && props.animated.value !== false;\n\n host.setAttribute('data-animated', isAnimated ? 'true' : 'false');\n },\n { immediate: true },\n );\n onMount(() => {\n const entry = observeIntersection(host, { threshold: 0 });\n\n watch(entry, (e) => {\n host.toggleAttribute('data-paused', e !== null && !e.isIntersecting);\n });\n });\n\n return html`\n <div class=\"stack\" part=\"stack\">\n ${() =>\n Array.from({ length: renderLineCount.value }, (_, index) => {\n const isLastLine =\n props.variant.value === 'text' && renderLineCount.value > 1 && index === renderLineCount.value - 1;\n\n return html`<div\n class=\"bone\"\n part=\"bone\"\n aria-hidden=\"true\"\n :data-last=\"${() => (isLastLine ? 'true' : null)}\"></div>`;\n })}\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n tag: 'bit-skeleton',\n});\n","@layer buildit.base {\n :host {\n --_position: var(--toast-position, fixed);\n --_inset-top: var(--toast-inset-top, auto);\n --_inset-bottom: var(--toast-inset-bottom, 1rem);\n --_inset-right: var(--toast-inset-right, 1rem);\n --_inset-left: var(--toast-inset-left, auto);\n --_z-index: var(--toast-z-index, 9999);\n --_max-width: var(--toast-max-width, 400px);\n --_gap: var(--toast-gap, 0.5rem);\n\n position: var(--_position);\n inset: var(--_inset-top) var(--_inset-right) var(--_inset-bottom) var(--_inset-left);\n z-index: var(--_z-index);\n display: flex;\n flex-direction: column;\n gap: var(--_gap);\n max-width: var(--_max-width);\n pointer-events: none;\n }\n\n /* Position variants */\n :host([position='top-left']) {\n --_inset-top: 1rem;\n --_inset-bottom: auto;\n --_inset-left: 1rem;\n --_inset-right: auto;\n }\n\n :host([position='top-center']) {\n --_inset-top: 1rem;\n --_inset-bottom: auto;\n --_inset-left: 50%;\n --_inset-right: auto;\n\n transform: translateX(-50%);\n }\n\n :host([position='top-right']) {\n --_inset-top: 1rem;\n --_inset-bottom: auto;\n --_inset-right: 1rem;\n --_inset-left: auto;\n }\n\n :host([position='bottom-left']) {\n --_inset-bottom: 1rem;\n --_inset-left: 1rem;\n --_inset-right: auto;\n --_inset-top: auto;\n }\n\n :host([position='bottom-center']) {\n --_inset-bottom: 1rem;\n --_inset-left: 50%;\n --_inset-right: auto;\n --_inset-top: auto;\n\n transform: translateX(-50%);\n }\n\n :host([position='bottom-right']) {\n --_inset-bottom: 1rem;\n --_inset-right: 1rem;\n --_inset-left: auto;\n --_inset-top: auto;\n }\n\n .toast-container {\n display: grid;\n grid-template-rows: 1fr;\n grid-template-columns: 1fr;\n row-gap: 0;\n perspective: 1200px;\n perspective-origin: center center;\n transition: var(--_motion-transition, row-gap var(--transition-normal, 0.35s) ease);\n }\n\n /* Keep ARIA live regions without affecting stacking layout geometry. */\n .toast-live-region {\n display: contents;\n }\n\n :host(.hovered) .toast-container {\n row-gap: var(--_gap);\n }\n\n :host(:not(.hovered)) .toast-wrapper {\n grid-row: 1;\n grid-column: 1;\n align-self: end;\n }\n\n :host([position^='top']:not(.hovered)) .toast-wrapper {\n align-self: start;\n }\n\n .toast-wrapper {\n position: relative;\n pointer-events: auto;\n transform-origin: center bottom;\n transition: var(\n --_motion-transition,\n transform 0.5s cubic-bezier(0.34, 1.1, 0.64, 1),\n opacity 0.5s cubic-bezier(0.34, 1.1, 0.64, 1),\n filter 0.5s cubic-bezier(0.34, 1.1, 0.64, 1)\n );\n will-change: transform, opacity, filter;\n }\n\n /* Enter animation via @starting-style — no JS class needed */\n @starting-style {\n .toast-wrapper {\n opacity: 0;\n transform: translateY(1.5rem) scale(0.92);\n }\n\n :host([position^='top']) .toast-wrapper {\n transform: translateY(-1.5rem) scale(0.92);\n }\n }\n\n /* Exit animation */\n .toast-wrapper.exiting {\n z-index: -1 !important;\n pointer-events: none;\n transition: none !important;\n animation: var(--_motion-animation, toast-exit 0.3s ease-out forwards);\n }\n\n @keyframes toast-exit {\n to {\n opacity: 0;\n transform: scale(0.7);\n }\n }\n\n /* Stacking (collapsed) */\n :host(:not(.hovered)) .toast-wrapper:nth-last-child(1) {\n z-index: 3;\n opacity: 1;\n filter: brightness(1);\n transform: translateY(0) scale(1);\n }\n\n :host(:not(.hovered)) .toast-wrapper:nth-last-child(2) {\n z-index: 2;\n pointer-events: none;\n opacity: 0.85;\n filter: brightness(0.95);\n transform: translateY(-8px) scale(0.95) rotateX(3deg);\n }\n\n :host(:not(.hovered)) .toast-wrapper:nth-last-child(3) {\n z-index: 1;\n pointer-events: none;\n opacity: 0.7;\n filter: brightness(0.9);\n transform: translateY(-14px) scale(0.9) rotateX(5deg);\n }\n\n :host(:not(.hovered)) .toast-wrapper:nth-last-child(n + 4) {\n pointer-events: none;\n opacity: 0;\n }\n\n /* Expanded (hovered) */\n :host(.hovered) .toast-wrapper {\n z-index: auto !important;\n grid-row: auto;\n grid-column: 1;\n align-self: stretch;\n pointer-events: auto !important;\n opacity: 1 !important;\n filter: brightness(1) !important;\n transform: none !important;\n }\n\n /* Staggered expand delays */\n :host(.hovered) .toast-wrapper:nth-last-child(2) {\n transition-delay: 0.05s;\n }\n\n :host(.hovered) .toast-wrapper:nth-last-child(3) {\n transition-delay: 0.1s;\n }\n\n :host(.hovered) .toast-wrapper:nth-last-child(n + 4) {\n transition-delay: 0.15s;\n }\n\n /* Top positions: reverse stacking direction */\n :host([position^='top']) .toast-wrapper {\n transform-origin: center top;\n }\n\n :host([position^='top']:not(.hovered)) .toast-wrapper:nth-last-child(2) {\n transform: translateY(8px) scale(0.95) rotateX(-3deg);\n }\n\n :host([position^='top']:not(.hovered)) .toast-wrapper:nth-last-child(3) {\n transform: translateY(14px) scale(0.9) rotateX(-5deg);\n }\n\n ::slotted(bit-alert) {\n width: 100%;\n margin: 0;\n box-shadow: var(--shadow-lg);\n }\n\n .toast-wrapper.exiting ::slotted(bit-alert) {\n transition: none !important;\n }\n\n .toast-actions {\n display: flex;\n gap: var(--size-4);\n justify-content: flex-end;\n }\n\n /* ========================================\n Responsive: small screens\n ======================================== */\n\n @media (width <= 480px) {\n :host {\n --_max-width: calc(100vw - var(--size-4));\n --_inset-right: var(--size-2);\n --_inset-left: var(--size-2);\n }\n\n :host([position='top-center']),\n :host([position='bottom-center']) {\n --_inset-left: var(--size-2);\n\n inset-inline-start: var(--size-2);\n transform: none;\n }\n }\n}\n","import { defineComponent, html, onMount, ref, signal } from '@vielzeug/craftit';\nimport { classes, each } from '@vielzeug/craftit/directives';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { reducedMotionMixin } from '../../styles';\nimport { awaitExit } from '../../utils/animation';\nimport componentStyles from './toast.css?inline';\n\n/** Toast container properties */\n\nexport type BitToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type BitToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: VisualVariant;\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000) */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout) */\n horizontal?: boolean;\n /** Auto-generated via crypto.randomUUID() if omitted */\n id?: string;\n message: string;\n /** Metadata text (e.g. timestamp) shown in the alert meta slot */\n meta?: string;\n /** Called after the toast is fully dismissed and removed */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Urgency level for screen readers.\n * - `'polite'` (default): uses `aria-live=\"polite\"` — announced after the user finishes their current action.\n * - `'assertive'`: uses `aria-live=\"assertive\"` — interrupts the user immediately. Use only for critical errors.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype NormalizedToast = ToastItem & { id: string };\n\n/** Public API of the bit-toast element */\nexport interface ToastElement extends HTMLElement {\n add: (toast: ToastItem) => string;\n update: (id: string, updates: Partial<ToastItem>) => void;\n dismiss: (id: string) => void;\n clear: () => void;\n}\n\n/**\n * A toast notification container with Time Machine-style stacking animation.\n * Stacks up to 3 notifications with a 3D effect. Hover to expand all toasts.\n *\n * @element bit-toast\n *\n * @attr {string} position - 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n * @attr {number} max - Max toasts in DOM at once (default: 5)\n *\n * @fires add - When a toast is added `{ id }`\n * @fires dismiss - When a toast is dismissed `{ id }`\n *\n * @slot - Manually placed bit-alert elements\n *\n * @cssprop --toast-position - Position type (default: fixed)\n * @cssprop --toast-inset-top - Top inset\n * @cssprop --toast-inset-bottom - Bottom inset\n * @cssprop --toast-inset-left - Left inset\n * @cssprop --toast-inset-right - Right inset\n * @cssprop --toast-z-index - Z-index (default: 9999)\n * @cssprop --toast-max-width - Max width (default: 400px)\n * @cssprop --toast-gap - Gap between expanded toasts (default: 0.5rem)\n *\n * @example\n * ```html\n * <!-- Declarative: place once in HTML -->\n * <bit-toast position=\"bottom-right\"></bit-toast>\n *\n * <!-- Programmatic: use the singleton service -->\n * <script type=\"module\">\n * import { toast } from '@vielzeug/buildit';\n * toast.add({ message: 'Changes saved!', color: 'success' });\n * </script>\n * ```\n */\n/** Renders the actions slot for a toast item */\nfunction renderToastActions(toast: NormalizedToast, onDismiss: () => void) {\n if (!toast.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${toast.actions.map(\n (action) => html`\n <bit-button\n size=\"sm\"\n color=${action.color || toast.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n onDismiss();\n }}\n >${action.label}</bit-button\n >\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = defineComponent<BitToastProps, BitToastEvents>({\n props: {\n max: { default: 5 },\n position: { default: 'bottom-right' },\n },\n setup({ emit, host, props }) {\n const toasts = signal<NormalizedToast[]>([]);\n const exitingIds = signal<Set<string>>(new Set());\n const containerRef = ref<HTMLDivElement>();\n const timers = new Map<\n string,\n {\n remaining: number;\n startedAt: number;\n timeoutId: number;\n }\n >();\n // Sequential dismiss queue — only one toast exits at a time so animations never overlap.\n const dismissQueue: string[] = [];\n let isDismissing = false;\n const setExiting = (id: string, value: boolean) => {\n const next = new Set(exitingIds.value);\n\n if (value) next.add(id);\n else next.delete(id);\n\n exitingIds.value = next;\n };\n const scheduleRemoval = (id: string, duration: number) => {\n const timeoutId = window.setTimeout(() => {\n removeToast(id);\n timers.delete(id);\n }, duration);\n\n timers.set(id, { remaining: duration, startedAt: Date.now(), timeoutId });\n };\n let isPaused = false;\n const pauseTimers = () => {\n if (isPaused) return;\n\n isPaused = true;\n for (const [id, t] of timers) {\n clearTimeout(t.timeoutId);\n timers.set(id, { ...t, remaining: Math.max(0, t.remaining - (Date.now() - t.startedAt)) });\n }\n };\n const resumeTimers = () => {\n if (!isPaused) return;\n\n isPaused = false;\n for (const [id, t] of timers) {\n if (t.remaining <= 0) continue;\n\n scheduleRemoval(id, t.remaining);\n }\n };\n const addToast = (toast: ToastItem): string => {\n const id = toast.id || crypto.randomUUID();\n const item: NormalizedToast = { dismissible: true, duration: 5000, ...toast, id };\n\n toasts.value = [...toasts.value, item].slice(-(props.max.value ?? 5));\n emit('add', { id });\n\n if (item.duration! > 0) scheduleRemoval(id, item.duration!);\n\n return id;\n };\n const removeToast = (id: string) => {\n // Cancel the auto-dismiss timer if one is running.\n const timer = timers.get(id);\n\n if (timer) {\n clearTimeout(timer.timeoutId);\n timers.delete(id);\n }\n\n // Skip if already exiting or already queued.\n if (exitingIds.value.has(id) || dismissQueue.includes(id)) return;\n\n if (isDismissing) {\n dismissQueue.push(id);\n\n return;\n }\n\n isDismissing = true;\n executeRemoval(id);\n };\n // Internal: actually animate and remove. Always called from processNextInQueue or directly\n // when the queue is empty.\n const executeRemoval = (id: string) => {\n // Guard: could have been removed by clearAll between queue entry and execution.\n if (exitingIds.value.has(id)) {\n processNextInQueue();\n\n return;\n }\n\n const item = toasts.value.find((t) => t.id === id);\n const wrapper = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"]`);\n const finalize = () => {\n setExiting(id, false);\n toasts.value = toasts.value.filter((t) => t.id !== id);\n item?.onDismiss?.();\n emit('dismiss', { id });\n processNextInQueue();\n };\n\n if (wrapper) {\n setExiting(id, true);\n awaitExit(wrapper, finalize);\n } else {\n finalize();\n }\n };\n const processNextInQueue = () => {\n if (dismissQueue.length === 0) {\n isDismissing = false;\n\n return;\n }\n\n const nextId = dismissQueue.shift()!;\n\n executeRemoval(nextId);\n };\n const updateToast = (id: string, updates: Partial<ToastItem>) => {\n toasts.value = toasts.value.map((t) => (t.id === id ? { ...t, ...updates, id } : t));\n\n if (updates.duration === undefined) return;\n\n const timer = timers.get(id);\n\n if (timer) clearTimeout(timer.timeoutId);\n\n timers.delete(id);\n\n if (updates.duration > 0) scheduleRemoval(id, updates.duration);\n };\n const clearAll = () => {\n for (const [, t] of timers) clearTimeout(t.timeoutId);\n timers.clear();\n // Drain any pending queue entries and replace with the full current list so\n // they exit one-by-one in order.\n dismissQueue.length = 0;\n\n const ids = toasts.value.map((t) => t.id).filter((id) => !exitingIds.value.has(id));\n\n if (!ids.length) return;\n\n dismissQueue.push(...ids);\n\n if (!isDismissing) processNextInQueue();\n };\n\n onMount(() => {\n const el = host as ToastElement;\n\n el.add = addToast;\n el.update = updateToast;\n el.dismiss = removeToast;\n el.clear = clearAll;\n });\n\n const urgencyOf = (t: NormalizedToast) => t.urgency ?? (t.color === 'error' ? 'assertive' : 'polite');\n let focusPaused = false;\n let hoverPaused = false;\n const maybePause = () => pauseTimers();\n const maybeResume = () => {\n if (!focusPaused && !hoverPaused) resumeTimers();\n };\n const setHovered = (hovered: boolean) => {\n hoverPaused = hovered;\n host.classList.toggle('hovered', hovered);\n\n if (hovered) maybePause();\n else maybeResume();\n };\n const renderToastItem = (toast: NormalizedToast) => html`\n <div\n class=${classes({ exiting: () => exitingIds.value.has(toast.id), 'toast-wrapper': true })}\n data-toast-id=${toast.id}\n part=\"toast-wrapper\">\n <bit-alert\n color=${toast.color || (toast.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${toast.variant || 'solid'}\n size=${toast.size || 'md'}\n rounded=${toast.rounded || 'md'}\n ?dismissible=${toast.dismissible}\n ?horizontal=${toast.horizontal}\n heading=${toast.heading || ''}\n @dismiss=${() => removeToast(toast.id)}>\n ${toast.meta ? html`<span slot=\"meta\">${toast.meta}</span>` : ''} ${toast.message}\n ${renderToastActions(toast, () => removeToast(toast.id))}\n </bit-alert>\n </div>\n `;\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => setHovered(true)}\n @pointerleave=${() => setHovered(false)}\n @focusin=${() => {\n focusPaused = true;\n maybePause();\n }}\n @focusout=${() => {\n focusPaused = false;\n maybeResume();\n }}\n part=\"container\">\n <!-- Polite live region: normal informational toasts -->\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${each(() => toasts.value.filter((t) => urgencyOf(t) === 'polite'), renderToastItem, undefined, {\n key: (toast) => toast.id,\n })}\n </div>\n <!-- Assertive live region: critical errors that interrupt immediately -->\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${each(() => toasts.value.filter((t) => urgencyOf(t) === 'assertive'), renderToastItem, undefined, {\n key: (toast) => toast.id,\n })}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n tag: 'bit-toast',\n});\n\n// ─── Singleton toast service ─────────────────────────────────────────────────\n\nconst getHost = (): ToastElement => {\n let el = document.querySelector<ToastElement>('bit-toast');\n\n if (!el) {\n el = document.createElement('bit-toast') as ToastElement;\n document.body.appendChild(el);\n }\n\n return el;\n};\n\n/**\n * Singleton service for triggering toasts without direct DOM references.\n *\n * @example\n * ```ts\n * import { toast } from '@vielzeug/buildit';\n *\n * toast.add({ message: 'Saved!', color: 'success' });\n *\n * const id = toast.add({ message: 'Uploading…', duration: 0, dismissible: false });\n * toast.update(id, { message: 'Done!', color: 'success', duration: 3000, dismissible: true });\n *\n * await toast.promise(uploadFile(), {\n * loading: 'Uploading…',\n * success: (url) => `Uploaded to ${url}`,\n * error: 'Upload failed',\n * });\n * ```\n */\nexport const toast = {\n /** Add a toast and return its id */\n add(item: ToastItem): string {\n return getHost().add(item);\n },\n\n /** Dismiss all toasts (animated) */\n clear(): void {\n getHost().clear();\n },\n /** Configure the auto-created container. Call before the first `add()` if the defaults need to change. */\n configure(config: BitToastProps): void {\n const el = getHost();\n\n if (config.position) el.setAttribute('position', config.position);\n\n if (config.max != null) el.setAttribute('max', String(config.max));\n },\n\n /**\n * Shows a loading toast tied to a promise.\n * Updates to success/error when the promise settles.\n */\n async promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T> {\n const id = toast.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n toast.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n toast.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n /** Dismiss a toast by id */\n remove(id: string): void {\n getHost().dismiss(id);\n },\n\n /** Update an existing toast in-place */\n update(id: string, updates: Partial<ToastItem>): void {\n getHost().update(id, updates);\n },\n};\n","import { flip, positionFloat, shift, size } from '@vielzeug/floatit';\n\nexport function createDropdownPositioner(\n getReferenceEl: () => HTMLElement | null,\n getFloatingEl: () => HTMLElement | null,\n { padding = 6 }: { padding?: number } = {},\n) {\n function updatePosition(): void {\n const ref = getReferenceEl();\n const floating = getFloatingEl();\n\n if (!ref || !floating) return;\n\n const referenceWidth = ref.getBoundingClientRect().width;\n\n positionFloat(ref, floating, {\n middleware: [\n flip({ padding }),\n shift({ padding }),\n size({\n apply({ elements }) {\n elements.floating.style.width = `${referenceWidth}px`;\n },\n padding,\n }),\n ],\n placement: 'bottom-start',\n });\n }\n\n return {\n destroy(): void {\n // no-op: auto-update lifecycle is owned by createOverlayControl()\n },\n updatePosition,\n };\n}\n","export type CounterState = {\n atLimit: boolean;\n hidden: boolean;\n nearLimit: boolean;\n text: string;\n};\n\nexport type SplitAssistiveState = {\n errorHidden: boolean;\n errorText: string;\n helperHidden: boolean;\n helperText: string;\n};\n\nexport type MergedAssistiveState = {\n hidden: boolean;\n isError: boolean;\n text: string;\n};\n\n/** Shared counter-state thresholds for text controls with maxlength support. */\nexport function resolveCounterState(length: number, max: number | null): CounterState {\n if (max == null) {\n return { atLimit: false, hidden: true, nearLimit: false, text: '' };\n }\n\n const ratio = length / max;\n\n return {\n atLimit: ratio >= 1,\n hidden: false,\n nearLimit: ratio >= 0.9 && ratio < 1,\n text: `${length} / ${max}`,\n };\n}\n\n/** Split helper/error state for controls that render separate helper and error elements (input). */\nexport function resolveSplitAssistiveText(error: string | undefined, helper: string | undefined): SplitAssistiveState {\n const hasError = Boolean(error);\n const hasHelper = Boolean(helper);\n\n return {\n errorHidden: !hasError,\n errorText: error ?? '',\n helperHidden: hasError || !hasHelper,\n helperText: helper ?? '',\n };\n}\n\n/** Merged helper/error state for controls that render one assistive text element (textarea). */\nexport function resolveMergedAssistiveText(\n error: string | undefined,\n helper: string | undefined,\n): MergedAssistiveState {\n const isError = Boolean(error);\n const text = error || helper || '';\n\n return {\n hidden: !text,\n isError,\n text,\n };\n}\n","export type ChoiceChangeDetail = {\n labels: string[];\n originalEvent?: Event;\n value: string;\n values: string[];\n};\n\nexport function createChoiceChangeDetail(\n values: string[],\n labels: string[],\n originalEvent?: Event,\n): ChoiceChangeDetail {\n return {\n labels,\n originalEvent,\n value: values.join(','),\n values,\n };\n}\n","/** Parse comma-separated values used by multi-select style controls. */\nexport function parseCsvValues(value: string | undefined): string[] {\n if (!value) return [];\n\n return value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n}\n\n/** Parse positive numeric values from optional component props. */\nexport function parsePositiveNumber(value: unknown): number | null {\n if (value == null) return null;\n\n const n = Number(value);\n\n return Number.isFinite(n) && n > 0 ? n : null;\n}\n","import { parseCsvValues } from './field-values';\n\nexport type ControlledCsvState = {\n firstValue: string;\n formValue: string;\n isEmpty: boolean;\n values: string[];\n};\n\nexport function computeControlledCsvState(value: string | undefined): ControlledCsvState {\n const values = parseCsvValues(value);\n\n return {\n firstValue: values[0] ?? '',\n formValue: values.join(','),\n isEmpty: values.length === 0,\n values,\n };\n}\n","import { effect, handle, type ReadonlySignal } from '@vielzeug/craftit';\n\nimport {\n parsePositiveNumber,\n resolveCounterState,\n resolveMergedAssistiveText,\n resolveSplitAssistiveText,\n} from '../utils';\n\nexport type CounterConfig = {\n count: ReadonlySignal<number> | (() => number);\n format?: 'split' | 'merged';\n maxLength: ReadonlySignal<number | undefined> | (() => number | undefined);\n ref: { value: HTMLElement | null | undefined };\n};\n\nexport type SplitAssistiveConfig = {\n error: ReadonlySignal<string | undefined> | (() => string | undefined);\n errorRef: { value: HTMLDivElement | null | undefined };\n helper: ReadonlySignal<string | undefined> | (() => string | undefined);\n helperRef: { value: HTMLDivElement | null | undefined };\n};\n\nexport type MergedAssistiveConfig = {\n error: ReadonlySignal<string | undefined> | (() => string | undefined);\n helper: ReadonlySignal<string | undefined> | (() => string | undefined);\n ref: { value: HTMLDivElement | null | undefined };\n};\n\nexport function syncCounter(config: CounterConfig): void {\n effect(() => {\n const counterRef = config.ref.value;\n\n if (!counterRef) return;\n\n const count = typeof config.count === 'function' ? config.count() : config.count.value;\n const maxLen = typeof config.maxLength === 'function' ? config.maxLength() : config.maxLength.value;\n const state = resolveCounterState(count, parsePositiveNumber(maxLen));\n\n counterRef.hidden = state.hidden;\n\n if (config.format === 'merged') {\n counterRef.textContent = state.text.replace(' / ', '/');\n counterRef.className = state.atLimit ? 'counter at-limit' : state.nearLimit ? 'counter near-limit' : 'counter';\n } else {\n counterRef.textContent = state.text;\n counterRef.removeAttribute('data-near-limit');\n counterRef.removeAttribute('data-at-limit');\n\n if (state.atLimit) counterRef.setAttribute('data-at-limit', '');\n else if (state.nearLimit) counterRef.setAttribute('data-near-limit', '');\n }\n });\n}\n\nexport function syncSplitAssistive(config: SplitAssistiveConfig): void {\n effect(() => {\n const error = typeof config.error === 'function' ? config.error() : config.error.value;\n const helper = typeof config.helper === 'function' ? config.helper() : config.helper.value;\n const state = resolveSplitAssistiveText(error, helper);\n\n if (config.helperRef.value) {\n config.helperRef.value.textContent = state.helperText;\n config.helperRef.value.hidden = state.helperHidden;\n }\n\n if (config.errorRef.value) {\n config.errorRef.value.textContent = state.errorText;\n config.errorRef.value.hidden = state.errorHidden;\n }\n });\n}\n\nexport function syncMergedAssistive(config: MergedAssistiveConfig): void {\n effect(() => {\n const ref = config.ref.value;\n\n if (!ref) return;\n\n const error = typeof config.error === 'function' ? config.error() : config.error.value;\n const helper = typeof config.helper === 'function' ? config.helper() : config.helper.value;\n const state = resolveMergedAssistiveText(error, helper);\n\n ref.textContent = state.text;\n ref.hidden = state.hidden;\n });\n}\n\nexport type FieldEventHandlers = {\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n};\n\nexport function setupFieldEvents(\n element: HTMLInputElement | HTMLTextAreaElement | null | undefined,\n handlers: FieldEventHandlers,\n): void {\n if (!element) return;\n\n if (handlers.onInput) {\n handle(element, 'input', (event: Event) => {\n handlers.onInput!(event, element.value);\n });\n }\n\n if (handlers.onChange) {\n handle(element, 'change', (event: Event) => {\n handlers.onChange!(event, element.value);\n });\n }\n\n if (handlers.onBlur) {\n handle(element, 'blur', handlers.onBlur as EventListener);\n }\n}\n","import { createContext, type ReadonlySignal } from '@vielzeug/craftit';\n\nimport type { ComponentSize, VisualVariant } from '../../types';\n\nexport type FormContext = {\n /** Whether all child fields are disabled */\n disabled: ReadonlySignal<boolean>;\n /** Default size propagated to all child form fields */\n size: ReadonlySignal<ComponentSize | undefined>;\n /**\n * When to validate child form controls:\n * - `'submit'` (default): only on form submit\n * - `'blur'`: validate each field when it loses focus\n * - `'change'`: validate on every value change\n */\n validateOn: ReadonlySignal<'submit' | 'blur' | 'change'>;\n /** Default variant propagated to all child form fields */\n variant: ReadonlySignal<Exclude<VisualVariant, 'glass' | 'frost' | 'text'> | undefined>;\n};\n\nexport const FORM_CTX = createContext<FormContext>('FormContext');\n","import { effect, type ReadonlySignal } from '@vielzeug/craftit';\n\nimport { type FormContext } from '../form-context';\n\nexport interface FormContextSyncProps {\n disabled: ReadonlySignal<boolean | undefined>;\n size: ReadonlySignal<string | undefined>;\n variant?: ReadonlySignal<string | undefined>;\n}\n\n/**\n * Propagates form context `disabled`, `size`, and optionally `variant` to the\n * host element's attributes. Call this in setup or inside an `onMount` callback.\n *\n * - `disabled` is tracked with a flag so that context-driven removal only\n * clears the attribute when it was set by the context (not by the component).\n * - `size` and `variant` are only applied when the component's own prop is unset,\n * and removed when the context value disappears to prevent stale attributes.\n */\nexport function mountFormContextSync(\n host: HTMLElement,\n formCtx: FormContext | undefined,\n props: FormContextSyncProps,\n): void {\n if (!formCtx) return;\n\n let ctxDisabledActive = false;\n\n effect(() => {\n const ctxDisabled = formCtx.disabled.value;\n\n if (ctxDisabled && !ctxDisabledActive) {\n host.setAttribute('disabled', '');\n ctxDisabledActive = true;\n } else if (!ctxDisabled && ctxDisabledActive) {\n host.removeAttribute('disabled');\n ctxDisabledActive = false;\n }\n\n const ctxSize = formCtx.size.value;\n\n if (ctxSize && !props.size.value) host.setAttribute('size', ctxSize);\n else if (!props.size.value) host.removeAttribute('size');\n\n if (props.variant) {\n const ctxVariant = formCtx.variant.value;\n\n if (ctxVariant && !props.variant.value) host.setAttribute('variant', ctxVariant);\n else if (!props.variant.value) host.removeAttribute('variant');\n }\n });\n}\n","import { effect, type ReadonlySignal } from '@vielzeug/craftit';\n\nexport type LabelSyncProps = {\n label: ReadonlySignal<string | undefined>;\n 'label-placement': ReadonlySignal<'inset' | 'outside' | undefined>;\n};\n\n/**\n * Reactively synchronises label text and visibility for components that manage\n * their own `labelInsetRef` / `labelOutsideRef` refs (e.g. select, combobox).\n * Call inside `onMount` once DOM refs are ready.\n */\nexport function mountLabelSyncStandalone(\n labelInsetRef: { value: HTMLElement | null | undefined },\n labelOutsideRef: { value: HTMLElement | null | undefined },\n props: LabelSyncProps,\n): void {\n effect(() => {\n const placement = props['label-placement'].value ?? 'inset';\n const labelText = props.label.value ?? '';\n\n if (labelInsetRef.value) {\n labelInsetRef.value.textContent = labelText;\n labelInsetRef.value.hidden = !labelText || placement !== 'inset';\n }\n\n if (labelOutsideRef.value) {\n labelOutsideRef.value.textContent = labelText;\n labelOutsideRef.value.hidden = !labelText || placement !== 'outside';\n }\n });\n}\n","@layer buildit.base {\n :host {\n display: block;\n }\n\n fieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: none;\n }\n\n legend {\n padding: 0;\n margin-bottom: var(--size-2);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-contrast-600);\n }\n\n legend[hidden] {\n display: none;\n }\n\n .checkbox-group-items {\n display: flex;\n flex-direction: var(--checkbox-group-direction, column);\n gap: var(--checkbox-group-gap, var(--size-2));\n }\n\n .helper-text {\n padding-inline: 2px;\n margin-top: var(--size-1-5);\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n .error-text {\n padding-inline: 2px;\n margin-top: var(--size-1-5);\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n :host([orientation='horizontal']) .checkbox-group-items {\n --checkbox-group-direction: row;\n\n flex-wrap: wrap;\n }\n}\n","import {\n computed,\n createContext,\n createId,\n defineComponent,\n effect,\n handle,\n html,\n inject,\n onMount,\n onSlotChange,\n provide,\n type ReadonlySignal,\n signal,\n} from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { colorThemeMixin, disabledStateMixin, sizeVariantMixin } from '../../styles';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport { createChoiceChangeDetail, parseCsvValues, type ChoiceChangeDetail } from '../shared/utils';\nimport componentStyles from './checkbox-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type CheckboxGroupContext = {\n color: ReadonlySignal<ThemeColor | undefined>;\n disabled: ReadonlySignal<boolean>;\n size: ReadonlySignal<ComponentSize | undefined>;\n toggle: (value: string, originalEvent?: Event) => void;\n values: ReadonlySignal<string[]>;\n};\n\nexport const CHECKBOX_GROUP_CTX = createContext<CheckboxGroupContext>('CheckboxGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type BitCheckboxGroupProps = {\n /** Theme color — propagated to all child bit-checkbox elements */\n color?: ThemeColor;\n /** Disable all checkboxes in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Layout direction of the checkbox options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child bit-checkbox elements */\n size?: ComponentSize;\n /** Comma-separated list of currently checked values */\n values?: string;\n};\n\nexport type BitCheckboxGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `bit-checkbox` elements, provides shared\n * `color` and `size` via context, and manages multi-value selection state.\n *\n * @element bit-checkbox-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} values - Comma-separated list of checked values\n * @attr {boolean} disabled - Disable all checkboxes in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `bit-checkbox` elements here\n */\nexport const CHECKBOX_GROUP_TAG = defineComponent<BitCheckboxGroupProps, BitCheckboxGroupEvents>({\n props: {\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '' },\n helper: { default: '' },\n label: { default: '' },\n orientation: { default: 'vertical' },\n required: { default: false },\n size: { default: undefined },\n values: { default: '' },\n },\n setup({ emit, host, props }) {\n // Parse comma-separated value string into an array of checked values\n const parseValues = (v: string | undefined): string[] => parseCsvValues(v);\n const checkedValues = signal<string[]>(parseValues(props.values.value));\n\n const getCheckboxes = (): HTMLElement[] => Array.from(host.getElementsByTagName('bit-checkbox')) as HTMLElement[];\n const getLabelForValue = (value: string): string => {\n const checkbox = getCheckboxes().find((item) => (item.getAttribute('value') ?? '') === value);\n\n return checkbox?.textContent?.replace(/\\s+/g, ' ').trim() || value;\n };\n const emitChange = (originalEvent?: Event) => {\n const values = checkedValues.value;\n\n emit('change', createChoiceChangeDetail(values, values.map(getLabelForValue), originalEvent));\n };\n\n // Keep checkedValues in sync when prop changes externally\n effect(() => {\n checkedValues.value = parseValues(props.values.value);\n });\n\n const toggleCheckbox = (val: string, originalEvent?: Event) => {\n const current = checkedValues.value;\n const next = current.includes(val) ? current.filter((v) => v !== val) : [...current, val];\n\n checkedValues.value = next;\n host.setAttribute('values', next.join(','));\n emitChange(originalEvent);\n };\n const formCtx = inject(FORM_CTX, undefined);\n\n mountFormContextSync(host, formCtx, props);\n\n provide(CHECKBOX_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n toggle: toggleCheckbox,\n values: checkedValues,\n });\n\n // Sync checked state + color/size/disabled onto slotted bit-checkbox children\n const syncChildren = () => {\n const values = checkedValues.value;\n const color = props.color.value;\n const size = props.size.value;\n const disabled = props.disabled.value;\n const checkboxes = Array.from(host.getElementsByTagName('bit-checkbox')) as HTMLElement[];\n\n for (const checkbox of checkboxes) {\n const val = checkbox.getAttribute('value') ?? '';\n\n if (values.includes(val)) checkbox.setAttribute('checked', '');\n else checkbox.removeAttribute('checked');\n\n if (color) checkbox.setAttribute('color', color);\n else checkbox.removeAttribute('color');\n\n if (size) checkbox.setAttribute('size', size);\n else checkbox.removeAttribute('size');\n\n if (disabled) checkbox.setAttribute('disabled', '');\n else checkbox.removeAttribute('disabled');\n }\n };\n\n effect(syncChildren);\n\n onMount(() => {\n onSlotChange('default', syncChildren);\n syncChildren();\n\n handle(host, 'change', (e: Event) => {\n if (e.target === host) return;\n\n e.stopPropagation();\n\n const val = (e.target as HTMLElement).getAttribute('value') ?? '';\n\n toggleCheckbox(val, e);\n });\n });\n\n const legendId = createId('checkbox-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = computed(() => Boolean(props.error.value));\n const hasHelper = computed(() => Boolean(props.helper.value) && !hasError.value);\n\n return html`\n <fieldset\n role=\"group\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError.value)}\"\n aria-errormessage=\"${() => (hasError.value ? errorId : null)}\"\n aria-describedby=\"${() => (hasError.value ? errorId : hasHelper.value ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${() => props.label.value}${() => (props.required.value ? html`<span aria-hidden=\"true\"> *</span>` : '')}\n </legend>\n <div class=\"checkbox-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError.value}>\n ${() => props.error.value}\n </div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper.value}>${() => props.helper.value}</div>\n </fieldset>\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin(), disabledStateMixin(), componentStyles],\n tag: 'bit-checkbox-group',\n});\n","export type ValidationTrigger = 'blur' | 'change';\n\nexport type ValidationTriggerSource = {\n validateOn: { value: ValidationTrigger | 'submit' | undefined };\n};\n\nexport type ValidationReporter = {\n reportValidity: () => void;\n};\n\nexport function triggerValidationOnEvent(\n formCtx: ValidationTriggerSource | undefined,\n field: ValidationReporter,\n on: ValidationTrigger,\n): void {\n if (formCtx?.validateOn.value === on) field.reportValidity();\n}\n\nexport function createFieldValidation(formCtx: ValidationTriggerSource | undefined, field: ValidationReporter) {\n return {\n triggerValidation(on: ValidationTrigger): void {\n triggerValidationOnEvent(formCtx, field, on);\n },\n };\n}\n","/**\n * useTextField — shared setup composable for text-based form fields.\n *\n * Extracts the value-signal management, form-field registration, accessibility\n * IDs, and label-visibility sync that is identical between `bit-input` and\n * `bit-textarea`. Helper/error sync differs between the two and stays in each\n * component.\n *\n * Call this function synchronously inside a component factory. The returned\n * `mountLabelSync()` must be called inside `onMount` once DOM refs are ready.\n */\n\nimport {\n computed,\n createId,\n createFormIds,\n defineField,\n inject,\n type ReadonlySignal,\n ref,\n signal,\n watch,\n} from '@vielzeug/craftit';\n\nimport { mountLabelSyncStandalone } from '../dom-sync';\nimport { FORM_CTX } from '../form-context';\nimport { triggerValidationOnEvent } from '../validation';\n\nexport type TextFieldBaseProps = {\n disabled: ReadonlySignal<boolean | undefined>;\n label: ReadonlySignal<string | undefined>;\n 'label-placement': ReadonlySignal<'inset' | 'outside' | undefined>;\n name: ReadonlySignal<string | undefined>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport function useTextField(props: TextFieldBaseProps, fieldPrefix: string) {\n const formCtx = inject(FORM_CTX, undefined);\n const valueSignal = signal('');\n\n const fd = defineField(\n { disabled: computed(() => Boolean(props.disabled.value) || Boolean(formCtx?.disabled.value)), value: valueSignal },\n {\n onReset: () => {\n valueSignal.value = '';\n },\n },\n );\n\n watch(\n props.value,\n (v) => {\n valueSignal.value = String(v ?? '');\n },\n { immediate: true },\n );\n\n const {\n errorId,\n fieldId,\n helperId,\n labelId: labelInsetId,\n } = createFormIds(fieldPrefix, props.name.value || createId(fieldPrefix));\n const labelOutsideId = `${labelInsetId}-outside`;\n\n const labelInsetRef = ref<HTMLLabelElement>();\n const labelOutsideRef = ref<HTMLLabelElement>();\n\n /** Create label-visibility reactive effect. Call inside `onMount`. */\n function mountLabelSync(): void {\n mountLabelSyncStandalone(labelInsetRef, labelOutsideRef, props);\n }\n\n /** Call inside a blur or change handler to trigger validation if the form context warrants it. */\n function triggerValidation(on: 'blur' | 'change'): void {\n triggerValidationOnEvent(formCtx, fd, on);\n }\n\n return {\n errorId,\n fieldId,\n formCtx,\n helperId,\n labelInsetId,\n labelInsetRef,\n labelOutsideId,\n labelOutsideRef,\n mountLabelSync,\n triggerValidation,\n valueSignal,\n };\n}\n","import { computed, defineField, inject, type ReadonlySignal, signal, watch } from '@vielzeug/craftit';\n\nimport { FORM_CTX } from '../form-context';\nimport { createFieldValidation } from '../validation';\n\nexport interface ToggleFieldBaseProps {\n disabled: ReadonlySignal<boolean | undefined>;\n value: ReadonlySignal<string | undefined>;\n checked: ReadonlySignal<boolean | undefined>;\n}\n\n/**\n * Shared setup for toggle-style form fields (checkbox, switch).\n *\n * @param props - Component props object with `disabled`, `value`, and `checked`\n * @param onExtraReset - Optional callback invoked alongside the field reset (e.g. to reset `indeterminateSignal`)\n */\nexport function useToggleField(props: ToggleFieldBaseProps, onExtraReset?: () => void) {\n const formCtx = inject(FORM_CTX, undefined);\n const checkedSignal = signal(false);\n\n const fd = defineField(\n {\n disabled: computed(() => Boolean(props.disabled.value) || Boolean(formCtx?.disabled.value)),\n toFormValue: (v: string | null) => v,\n value: computed(() => (checkedSignal.value ? (props.value.value ?? '') : null)),\n },\n {\n onReset: () => {\n checkedSignal.value = props.checked.value ?? false;\n onExtraReset?.();\n },\n },\n );\n\n watch(\n props.checked,\n (v) => {\n checkedSignal.value = v ?? false;\n },\n { immediate: true },\n );\n\n const { triggerValidation } = createFieldValidation(formCtx, fd);\n\n return { checkedSignal, formCtx, triggerValidation };\n}\n","export const FIELD_SIZE_PRESET = {\n lg: {\n '--_field-height': 'var(--size-12)',\n '--_padding': 'var(--size-2-5) var(--size-3-5)',\n fontSize: 'var(--text-base)',\n gap: 'var(--size-2-5)',\n },\n md: {\n '--_field-height': 'var(--size-10)',\n '--_padding': 'var(--size-1-5) var(--size-3)',\n fontSize: 'var(--text-sm)',\n gap: 'var(--size-2)',\n },\n sm: {\n '--_field-height': 'var(--size-8)',\n '--_padding': 'var(--size-1) var(--size-2)',\n fontSize: 'var(--text-xs)',\n gap: 'var(--size-1-5)',\n },\n} as const;\n\nexport const TEXTAREA_SIZE_PRESET = {\n lg: {\n '--_padding': 'var(--size-2-5) var(--size-3-5)',\n fontSize: 'var(--text-base)',\n gap: 'var(--size-2-5)',\n },\n md: {\n '--_padding': 'var(--size-1-5) var(--size-3)',\n fontSize: 'var(--text-sm)',\n gap: 'var(--size-2)',\n },\n sm: {\n '--_padding': 'var(--size-1) var(--size-2)',\n fontSize: 'var(--text-xs)',\n gap: 'var(--size-1-5)',\n },\n} as const;\n\n/** Shared size preset for checkbox and radio (icon + label layout). */\nexport const CONTROL_SIZE_PRESET = {\n lg: {\n fontSize: 'var(--text-base)',\n gap: 'var(--size-2-5)',\n size: 'var(--size-6)',\n },\n sm: {\n fontSize: 'var(--text-xs)',\n gap: 'var(--size-1-5)',\n size: 'var(--size-4)',\n },\n} as const;\n\n/** Shared size preset for the switch toggle control. */\nexport const SWITCH_SIZE_PRESET = {\n lg: {\n fontSize: 'var(--text-base)',\n gap: 'var(--size-3)',\n height: 'var(--size-7)',\n thumbSize: 'var(--size-6)',\n width: 'var(--size-14)',\n },\n sm: {\n fontSize: 'var(--text-xs)',\n gap: 'var(--size-2)',\n height: 'var(--size-5)',\n thumbSize: 'var(--size-4)',\n width: 'var(--size-9)',\n },\n} as const;\n\n/** Shared size preset for the slider track/thumb. */\nexport const SLIDER_SIZE_PRESET = {\n lg: {\n fontSize: 'var(--text-base)',\n height: 'calc(var(--size-5) - var(--size-1))',\n size: 'var(--size-5)',\n },\n md: {\n fontSize: 'var(--text-base)',\n height: 'var(--size-3)',\n size: 'var(--size-5)',\n },\n sm: {\n fontSize: 'var(--text-xs)',\n height: 'var(--size-2)',\n size: 'var(--size-4)',\n },\n} as const;\n\n/** Shared size preset for the file-input dropzone. */\nexport const FILE_INPUT_SIZE_PRESET = {\n lg: {\n '--_min-height': 'var(--size-40)',\n fontSize: 'var(--text-base)',\n },\n sm: {\n '--_min-height': 'var(--size-28)',\n fontSize: 'var(--text-xs)',\n },\n} as const;\n","@layer buildit.base {\n /* ========================================\n Base Styles & Defaults\n ======================================== */\n\n :host {\n --_size: var(--checkbox-size, var(--size-5));\n --_radius: var(--checkbox-radius, var(--rounded-lg));\n --_font-size: var(--checkbox-font-size, var(--text-sm));\n --_bg: var(--checkbox-bg, var(--color-contrast-200));\n --_border: var(--checkbox-border-color, var(--color-contrast-300));\n\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--_gap, var(--size-2));\n align-items: center;\n min-height: var(--_touch-target);\n cursor: pointer;\n user-select: none;\n }\n\n .checkbox-wrapper {\n position: relative;\n display: block;\n flex-shrink: 0;\n width: var(--_size);\n height: var(--_size);\n }\n\n .box {\n position: relative;\n box-sizing: border-box;\n width: var(--_size);\n height: var(--_size);\n background: var(--_bg);\n border: var(--border-2) solid var(--_border);\n border-radius: var(--_radius);\n transition:\n background var(--transition-slower),\n border-color var(--transition-slower),\n box-shadow var(--transition-normal);\n }\n\n /* ========================================\n Focus State\n ======================================== */\n\n input:focus-visible + .box {\n box-shadow: var(--_focus-shadow);\n }\n\n /* ========================================\n Icons (Checkmark & Dash)\n ======================================== */\n\n .checkmark,\n .dash {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 80%;\n height: 80%;\n color: var(--_icon-color);\n opacity: 0;\n fill: none;\n stroke: currentcolor;\n stroke-width: 3;\n stroke-linecap: round;\n stroke-linejoin: round;\n transform: translate(-50%, -50%) scale(0.5);\n transition:\n opacity var(--transition-spring),\n transform var(--transition-spring);\n }\n\n /* ========================================\n Label\n ======================================== */\n\n .label {\n font-size: var(--_font-size);\n color: var(--color-contrast);\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n width: 100%;\n padding-inline-start: calc(var(--_size) + var(--size-2));\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n .helper-text[role='alert'] {\n color: var(--color-error);\n }\n}\n\n@layer buildit.overrides {\n /* Map theme variables to checkbox-specific variables */\n :host {\n --_active-bg: var(--checkbox-checked-bg, var(--_theme-base));\n --_icon-color: var(--checkbox-color, var(--_theme-contrast));\n --_focus-shadow: var(--_theme-shadow);\n }\n\n /* ========================================\n Checked & Indeterminate States\n ======================================== */\n\n :host([checked]) .box,\n :host([indeterminate]) .box {\n background: var(--_active-bg);\n border-color: var(--_active-bg);\n }\n\n :host([checked]) .checkmark,\n :host([indeterminate]:not([checked])) .dash {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n}\n","import { defineComponent, html, inject, signal, watch } from '@vielzeug/craftit';\nimport { useA11yControl, createCheckableControl } from '@vielzeug/craftit/labs';\n\nimport type { CheckableProps, DisablableProps, SizableProps, ThemableProps } from '../../types';\n\nimport { coarsePointerMixin, formControlMixins, sizeVariantMixin } from '../../styles';\nimport { CHECKBOX_GROUP_CTX } from '../checkbox-group/checkbox-group';\nimport { useToggleField } from '../shared/composables';\nimport { CONTROL_SIZE_PRESET } from '../shared/design-presets';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport componentStyles from './checkbox.css?inline';\n\nexport type BitCheckboxEvents = {\n change: { checked: boolean; fieldValue: string; originalEvent?: Event; value: boolean };\n};\n\nexport type BitCheckboxProps = CheckableProps &\n ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Error message (marks field as invalid) */\n error?: string;\n /** Helper text displayed below the checkbox */\n helper?: string;\n /** Indeterminate state (partially checked) */\n indeterminate?: boolean;\n };\n\n/**\n * A customizable checkbox component with theme colors, sizes, and indeterminate state support.\n *\n * @element bit-checkbox\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable checkbox interaction\n * @attr {boolean} indeterminate - Indeterminate (partially checked) state\n * @attr {string} value - Field value submitted with forms\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Checkbox size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the checkbox\n *\n * @fires change - Emitted when checkbox is toggled. detail: { value: boolean, checked: boolean, fieldValue: string, originalEvent?: Event }\n *\n * @slot - Checkbox label text\n *\n * @part checkbox - The checkbox wrapper element\n * @part box - The visual checkbox box\n * @part label - The label element\n * @part helper-text - The helper/error text element\n */\nexport const CHECKBOX_TAG = defineComponent<BitCheckboxProps, BitCheckboxEvents>({\n formAssociated: true,\n props: {\n checked: { default: false },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '' },\n helper: { default: '' },\n indeterminate: { default: false },\n name: { default: '' },\n size: { default: undefined },\n value: { default: 'on' },\n },\n setup({ emit, host, props, reflect }) {\n // Form integration — provides checkedSignal and triggerValidation\n const { checkedSignal, formCtx, triggerValidation } = useToggleField(props);\n\n mountFormContextSync(host, formCtx, props);\n\n // Separate writable indeterminate signal, synced from the prop\n const indeterminateSignal = signal(Boolean(props.indeterminate.value));\n\n watch(props.indeterminate, (v) => {\n indeterminateSignal.value = Boolean(v);\n });\n\n const groupCtx = inject(CHECKBOX_GROUP_CTX, undefined);\n\n // Pass the writable checkedSignal directly — toggle() mutates it in place\n const controlHandle = createCheckableControl({\n checked: checkedSignal,\n clearIndeterminateFirst: true,\n disabled: props.disabled,\n group: groupCtx,\n indeterminate: indeterminateSignal,\n onToggle: (e) => {\n triggerValidation('change');\n\n // In a checkbox-group, the group owns change emission/state updates.\n // Emitting here would bubble to the group and toggle a second time.\n if (groupCtx) return;\n\n emit('change', controlHandle.changePayload(e));\n },\n value: props.value,\n });\n\n const a11y = useA11yControl(host, {\n checked: () => {\n if (controlHandle.indeterminate.value) return 'mixed';\n\n return controlHandle.checked.value ? 'true' : 'false';\n },\n helperText: () => props.error.value || props.helper.value,\n helperTone: () => (props.error.value ? 'error' : 'default'),\n invalid: () => !!props.error.value,\n role: 'checkbox',\n });\n\n reflect({\n checked: () => controlHandle.checked.value,\n classMap: () => ({\n 'is-checked': controlHandle.checked.value,\n 'is-disabled': !!props.disabled.value,\n 'is-indeterminate': controlHandle.indeterminate.value,\n }),\n indeterminate: () => controlHandle.indeterminate.value,\n onClick: (e: Event) => controlHandle.toggle(e),\n onKeydown: (e: Event) => {\n const ke = e as KeyboardEvent;\n\n if (ke.key === ' ' || ke.key === 'Enter') {\n ke.preventDefault();\n controlHandle.toggle(e);\n }\n },\n tabindex: () => (props.disabled.value ? undefined : 0),\n });\n\n return html`\n <div class=\"checkbox-wrapper\" part=\"checkbox\">\n <div class=\"box\" part=\"box\">\n <svg\n class=\"checkmark\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M 20,6 9,17 4,12\" />\n </svg>\n <svg\n class=\"dash\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M 5,12 H 19\" />\n </svg>\n </div>\n </div>\n <span class=\"label\" part=\"label\" data-a11y-label id=\"${a11y.labelId}\"><slot></slot></span>\n <div\n class=\"helper-text\"\n part=\"helper-text\"\n data-a11y-helper\n id=\"${a11y.helperId}\"\n aria-live=\"polite\"\n hidden></div>\n `;\n },\n styles: [...formControlMixins, coarsePointerMixin, sizeVariantMixin(CONTROL_SIZE_PRESET), componentStyles],\n tag: 'bit-checkbox',\n});\n","import type { ComboboxOptionItem, ComboboxSelectionItem } from './combobox.types';\n\nexport function parseSlottedOptions(elements: Element[]): ComboboxOptionItem[] {\n return elements\n .filter((el) => el.localName === 'bit-combobox-option')\n .map((el) => ({\n disabled: el.hasAttribute('disabled'),\n iconEl: el.querySelector('[slot=\"icon\"]'),\n label:\n el.getAttribute('label') ||\n [...el.childNodes]\n .filter((node) => node.nodeType === Node.TEXT_NODE)\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .join(' ') ||\n '',\n value: el.getAttribute('value') ?? '',\n }));\n}\n\nexport function backfillSelectionLabels(\n selectedValues: ComboboxSelectionItem[],\n allOptions: ComboboxOptionItem[],\n): ComboboxSelectionItem[] {\n return selectedValues.map((selection) => {\n if (selection.label) return selection;\n\n const match = allOptions.find((option) => option.value === selection.value);\n\n return match ? { label: match.label, value: selection.value } : selection;\n });\n}\n\nexport function filterOptions(options: ComboboxOptionItem[], query: string, noFilter: boolean): ComboboxOptionItem[] {\n if (noFilter || !query) return options;\n\n const normalizedQuery = query.toLowerCase();\n\n return options.filter((option) => option.label.toLowerCase().includes(normalizedQuery));\n}\n\nexport function getCreatableLabel(query: string, creatable: boolean, filteredOptions: ComboboxOptionItem[]): string {\n if (!creatable || !query) return '';\n\n const trimmedQuery = query.trim();\n\n if (!trimmedQuery) return '';\n\n const exactMatch = filteredOptions.find((option) => option.label.toLowerCase() === trimmedQuery.toLowerCase());\n\n return exactMatch ? '' : trimmedQuery;\n}\n\nexport function makeCreatableValue(label: string): string {\n return label.toLowerCase().replace(/\\s+/g, '-');\n}\n","//#region src/virtualit.ts\nvar e = class {\n\t_count;\n\t_estimateSizeFn;\n\toverscan;\n\tonChange;\n\tmeasuredHeights = /* @__PURE__ */ new Map();\n\tvirtualItems = [];\n\ttotalSize = 0;\n\tscrollOffsets = new Float64Array();\n\tcontainerHeight = 0;\n\tscrollTop = 0;\n\tprevRenderStart = -1;\n\tprevRenderEnd = -1;\n\tattachedEl = null;\n\tresizeObserver = null;\n\tscrollHandler = null;\n\tpendingBuild = !1;\n\tconstructor(e) {\n\t\tthis._count = e.count;\n\t\tlet t = e.estimateSize ?? 36;\n\t\tthis._estimateSizeFn = typeof t == \"number\" ? () => t : t, this.overscan = e.overscan ?? 3, this.onChange = e.onChange, this.buildOffsets();\n\t}\n\tget count() {\n\t\treturn this._count;\n\t}\n\tset count(e) {\n\t\tthis._count = e, this.buildOffsets(), this.attachedEl && this.computeVisible();\n\t}\n\tset estimateSize(e) {\n\t\tthis._estimateSizeFn = typeof e == \"number\" ? () => e : e, this.measuredHeights.clear(), this.buildOffsets(), this.attachedEl && this.computeVisible();\n\t}\n\tattach(e) {\n\t\tthis.teardown(), this.attachedEl = e, this.containerHeight = e.clientHeight, this.scrollTop = e.scrollTop, this.scrollHandler = () => {\n\t\t\tthis.scrollTop = e.scrollTop, this.computeVisible();\n\t\t}, e.addEventListener(\"scroll\", this.scrollHandler, { passive: !0 }), this.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.containerHeight = e.clientHeight, this.computeVisible();\n\t\t}), this.resizeObserver.observe(e), this.computeVisible();\n\t}\n\tdestroy() {\n\t\tthis.teardown();\n\t}\n\t[Symbol.dispose]() {\n\t\tthis.destroy();\n\t}\n\tgetVirtualItems() {\n\t\treturn this.virtualItems;\n\t}\n\tgetTotalSize() {\n\t\treturn this.totalSize;\n\t}\n\tmeasureElement(e, t) {\n\t\tthis.heightAt(e) !== t && (this.measuredHeights.set(e, t), this.pendingBuild || (this.pendingBuild = !0, queueMicrotask(() => {\n\t\t\tthis.pendingBuild = !1, this.buildOffsets(), this.attachedEl && this.computeVisible();\n\t\t})));\n\t}\n\tscrollToIndex(e, t = {}) {\n\t\tlet n = this.attachedEl;\n\t\tif (!n) return;\n\t\tlet r = Math.max(0, Math.min(e, this._count - 1)), i = t.align ?? \"auto\", a = t.behavior ?? \"auto\", o = this.offsetAt(r), s = this.heightAt(r), c;\n\t\tif (i === \"start\") c = o;\n\t\telse if (i === \"end\") c = o + s - this.containerHeight;\n\t\telse if (i === \"center\") c = o - (this.containerHeight - s) / 2;\n\t\telse {\n\t\t\tlet e = n.scrollTop, t = e + this.containerHeight;\n\t\t\tif (o >= e && o + s <= t) return;\n\t\t\tc = o < e ? o : o + s - this.containerHeight;\n\t\t}\n\t\tn.scrollTo({\n\t\t\tbehavior: a,\n\t\t\ttop: Math.max(0, c)\n\t\t});\n\t}\n\tscrollToOffset(e, t = {}) {\n\t\tthis.attachedEl?.scrollTo({\n\t\t\tbehavior: t.behavior ?? \"auto\",\n\t\t\ttop: Math.max(0, e)\n\t\t});\n\t}\n\tinvalidate() {\n\t\tthis.measuredHeights.clear(), this.buildOffsets(), this.attachedEl && this.computeVisible();\n\t}\n\tteardown() {\n\t\tthis.scrollHandler && this.attachedEl && (this.attachedEl.removeEventListener(\"scroll\", this.scrollHandler), this.scrollHandler = null), this.resizeObserver?.disconnect(), this.resizeObserver = null, this.attachedEl = null;\n\t}\n\theightAt(e) {\n\t\treturn this.measuredHeights.get(e) ?? this._estimateSizeFn(e);\n\t}\n\toffsetAt(e) {\n\t\treturn this.scrollOffsets[e] ?? 0;\n\t}\n\tbuildOffsets() {\n\t\tthis.prevRenderStart = -1, this.prevRenderEnd = -1;\n\t\tlet e = new Float64Array(this._count + 1);\n\t\te[0] = 0;\n\t\tfor (let t = 0; t < this._count; t++) e[t + 1] = e[t] + this.heightAt(t);\n\t\tthis.scrollOffsets = e, this.totalSize = e[this._count] ?? 0;\n\t}\n\tcomputeVisible() {\n\t\tlet e = this.scrollTop, t = e + this.containerHeight, n = 0, r = this._count - 1;\n\t\tfor (; n < r;) {\n\t\t\tlet t = n + r >> 1;\n\t\t\tthis.scrollOffsets[t + 1] <= e ? n = t + 1 : r = t;\n\t\t}\n\t\tlet i = n, a = i, o = this._count - 1;\n\t\tfor (; a < o;) {\n\t\t\tlet e = a + o + 1 >> 1;\n\t\t\tthis.scrollOffsets[e] < t ? a = e : o = e - 1;\n\t\t}\n\t\tlet s = a, c = Math.max(0, i - this.overscan), l = Math.min(this._count - 1, s + this.overscan);\n\t\tif (c === this.prevRenderStart && l === this.prevRenderEnd) return;\n\t\tthis.prevRenderStart = c, this.prevRenderEnd = l;\n\t\tlet u = [];\n\t\tfor (let e = c; e <= l; e++) u.push({\n\t\t\theight: this.heightAt(e),\n\t\t\tindex: e,\n\t\t\ttop: this.scrollOffsets[e]\n\t\t});\n\t\tthis.virtualItems = u, this.onChange?.(u, this.totalSize);\n\t}\n};\nfunction t(t, n) {\n\tlet r = new e(n);\n\treturn r.attach(t), r;\n}\n//#endregion\nexport { e as Virtualizer, t as createVirtualizer };\n\n//# sourceMappingURL=virtualit.js.map","import { createVirtualizer as e } from \"../virtualit.js\";\n//#region src/dom/dom.ts\nfunction t(t) {\n\tlet n = [], r = null, i = null, a = null, o = (e) => typeof t.estimateSize == \"number\" ? t.estimateSize : t.estimateSize(e, n[e]), s = () => {\n\t\t!r || !a || (r.style.height = `${a.getTotalSize()}px`, r.style.position = \"relative\", r.style.contain = \"layout\");\n\t}, c = () => {\n\t\tr && (t.clear(r), r.style.height = \"\", r.style.position = \"\", r.style.contain = \"\");\n\t}, l = () => {\n\t\tlet l = t.getScrollElement(), u = t.getListElement();\n\t\tif (!l || !u || n.length === 0) {\n\t\t\ta?.destroy(), a = null, r = u, i = l, c();\n\t\t\treturn;\n\t\t}\n\t\tlet d = i !== l || r !== u;\n\t\tr = u, i = l, !a || d ? (a?.destroy(), a = e(i, {\n\t\t\tcount: n.length,\n\t\t\testimateSize: o,\n\t\t\tonChange: (e) => {\n\t\t\t\tr && t.render({\n\t\t\t\t\titems: n,\n\t\t\t\t\tlistEl: r,\n\t\t\t\t\tvirtualItems: e\n\t\t\t\t});\n\t\t\t},\n\t\t\toverscan: t.overscan ?? 3\n\t\t})) : (a.count = n.length, a.invalidate()), s();\n\t};\n\treturn {\n\t\tdestroy() {\n\t\t\ta?.destroy(), a = null, c();\n\t\t},\n\t\tscrollToIndex(e, t) {\n\t\t\ta?.scrollToIndex(e, t);\n\t\t},\n\t\tupdate(e, o) {\n\t\t\tif (n = e, !o || n.length === 0) {\n\t\t\t\ta?.destroy(), a = null, r = t.getListElement(), i = t.getScrollElement(), c();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tl();\n\t\t}\n\t};\n}\n//#endregion\nexport { t as createDomVirtualList };\n\n//# sourceMappingURL=dom.js.map","import { createDomVirtualList, type VirtualItem } from '@vielzeug/virtualit/dom';\n\nimport type { ComboboxOptionItem, ComboboxSelectionItem } from './combobox.types';\n\ntype ComboboxVirtualizerDeps = {\n checkIconHTML: string;\n comboId: string;\n getDropdownElement: () => HTMLElement | null;\n getFocusedIndex: () => number;\n getIsMultiple: () => boolean;\n getListboxElement: () => HTMLElement | null;\n getSelectedValue: () => string;\n getSelectedValues: () => ComboboxSelectionItem[];\n onSelectOption: (opt: ComboboxOptionItem, event?: Event) => void;\n setFocusedIndex: (index: number) => void;\n};\n\nexport function createComboboxVirtualizer(deps: ComboboxVirtualizerDeps) {\n let currentOptions: ComboboxOptionItem[] = [];\n let cachedListbox: HTMLElement | null = null;\n\n function isSelectedOption(option: ComboboxOptionItem): boolean {\n if (deps.getIsMultiple()) return deps.getSelectedValues().some((selected) => selected.value === option.value);\n\n return option.value === deps.getSelectedValue();\n }\n\n function renderVirtualItems(virtualItems: VirtualItem[]) {\n if (!cachedListbox) return;\n\n for (const element of Array.from(cachedListbox.querySelectorAll('.option'))) element.remove();\n\n const focused = deps.getFocusedIndex();\n\n for (const item of virtualItems) {\n const option = currentOptions[item.index];\n\n if (!option) continue;\n\n const isSelected = isSelectedOption(option);\n const optionElement = document.createElement('div');\n\n optionElement.className = 'option';\n optionElement.setAttribute('role', 'option');\n optionElement.id = `${deps.comboId}-opt-${item.index}`;\n optionElement.setAttribute('aria-selected', String(isSelected));\n optionElement.setAttribute('aria-disabled', String(!!option.disabled));\n optionElement.style.cssText = `position:absolute;top:0;left:0;right:0;transform:translateY(${item.top}px);`;\n\n if (focused === item.index) optionElement.setAttribute('data-focused', '');\n\n if (isSelected) optionElement.setAttribute('data-selected', '');\n\n if (option.disabled) optionElement.setAttribute('data-disabled', '');\n\n if (option.iconEl) {\n const iconWrapper = document.createElement('span');\n\n iconWrapper.className = 'option-icon';\n iconWrapper.setAttribute('aria-hidden', 'true');\n\n const iconClone = option.iconEl.cloneNode(true) as Element;\n\n iconClone.removeAttribute('slot');\n iconWrapper.appendChild(iconClone);\n optionElement.appendChild(iconWrapper);\n }\n\n const labelElement = document.createElement('span');\n\n labelElement.textContent = option.label;\n optionElement.appendChild(labelElement);\n\n const checkElement = document.createElement('span');\n\n checkElement.className = 'option-check';\n checkElement.setAttribute('aria-hidden', 'true');\n checkElement.innerHTML = deps.checkIconHTML;\n optionElement.appendChild(checkElement);\n optionElement.addEventListener('pointerdown', (event: PointerEvent) => {\n event.preventDefault();\n });\n optionElement.addEventListener('click', (event: MouseEvent) => {\n event.stopPropagation();\n deps.onSelectOption(option, event);\n });\n optionElement.addEventListener('pointerenter', () => {\n deps.setFocusedIndex(item.index);\n\n for (const focusedElement of cachedListbox!.querySelectorAll<HTMLElement>('[data-focused]')) {\n focusedElement.removeAttribute('data-focused');\n }\n optionElement.setAttribute('data-focused', '');\n });\n cachedListbox.appendChild(optionElement);\n }\n }\n\n function updateRenderedItemState() {\n if (!cachedListbox) return;\n\n const focused = deps.getFocusedIndex();\n\n for (const element of cachedListbox.querySelectorAll<HTMLElement>('.option')) {\n const idx = Number(element.id.replace(`${deps.comboId}-opt-`, ''));\n const option = currentOptions[idx];\n\n if (!option) continue;\n\n const isSelected = isSelectedOption(option);\n\n element.toggleAttribute('data-focused', idx === focused);\n element.toggleAttribute('data-selected', isSelected);\n element.setAttribute('aria-selected', String(isSelected));\n }\n }\n\n const domVirtualList = createDomVirtualList<ComboboxOptionItem>({\n clear: (listEl) => {\n for (const element of Array.from(listEl.querySelectorAll('.option'))) element.remove();\n },\n estimateSize: 36,\n getListElement: deps.getListboxElement,\n getScrollElement: deps.getDropdownElement,\n overscan: 4,\n render: ({ items, listEl, virtualItems }) => {\n currentOptions = items;\n cachedListbox = listEl;\n renderVirtualItems(virtualItems);\n },\n });\n\n function setupVirtualizer(options: ComboboxOptionItem[], isOpen: boolean) {\n currentOptions = options;\n domVirtualList.update(currentOptions, isOpen);\n }\n\n return { domVirtualList, setupVirtualizer, updateRenderedItemState };\n}\n","@layer buildit.base {\n :host {\n --_font-size: var(--combobox-font-size, var(--text-sm));\n --_gap: var(--combobox-gap, var(--size-2));\n --_field-height: var(--combobox-height, var(--size-10));\n --_row-min-height: calc(var(--leading-normal) * var(--_font-size) + 2px);\n --_padding: var(--combobox-padding, var(--size-1-5) var(--size-3));\n --_radius: var(--combobox-radius, var(--rounded-lg));\n --_placeholder: var(--combobox-placeholder-color, var(--color-contrast-500));\n --_bg: var(--combobox-bg, var(--color-contrast-100));\n --_border-color: var(--combobox-border-color, var(--color-contrast-300));\n\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n min-width: 12rem;\n }\n\n :host([fullwidth]) {\n width: 100%;\n }\n\n .combobox-wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--size-1-5);\n width: 100%;\n }\n\n /* ========================================\n Label\n ======================================== */\n\n .label-inset {\n margin-bottom: 2px;\n font-size: var(--text-xs);\n font-weight: var(--font-medium);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n cursor: pointer;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n .label-outside {\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n line-height: var(--leading-none);\n color: var(--color-contrast-500);\n cursor: pointer;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n /* ========================================\n Field / Input\n ======================================== */\n\n .field {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 0;\n align-items: stretch;\n justify-content: center;\n height: var(--_field-height);\n min-height: max(var(--_field-height), var(--_touch-target, 0px));\n padding: var(--_padding);\n padding-inline-end: var(--size-8);\n text-align: start;\n cursor: text;\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-2xs);\n transition: var(\n --_motion-transition,\n background var(--transition-fast),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast),\n transform var(--transition-fast)\n );\n }\n\n /* Expand height for multi-select chips or inset label */\n :host([multiple]) .field,\n .field:has(.label-inset:not([hidden])) {\n height: auto;\n }\n\n :host([clearable]) .field {\n padding-inline-end: var(--size-14);\n }\n\n .field-row {\n display: flex;\n flex-wrap: wrap;\n gap: var(--_gap);\n row-gap: var(--size-1);\n align-items: center;\n min-height: var(--_row-min-height);\n }\n\n .chips-row {\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: var(--size-1);\n align-items: center;\n min-width: 0;\n }\n\n .chips-list {\n /* Wrapper exists for list diffing isolation; keep chip layout unchanged. */\n display: contents;\n }\n\n .input {\n flex: 1 1 4rem;\n min-width: 4rem;\n height: var(--_row-min-height);\n padding: 0;\n font-family: inherit;\n font-size: var(--_font-size);\n line-height: 1;\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: 0;\n }\n\n :host([multiple]) .input {\n flex-basis: 6rem;\n min-width: 6rem;\n }\n\n :host([multiple]) .chips-row:has(bit-chip) .input {\n flex: 0 1 2.25rem;\n min-width: 2.25rem;\n }\n\n .input::placeholder {\n color: var(--_placeholder);\n }\n\n .chevron {\n position: absolute;\n inset-inline-end: var(--size-2-5);\n top: 50%;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n color: var(--color-contrast-500);\n pointer-events: none;\n transform: translateY(-50%);\n transition: var(--_motion-transition, transform var(--transition-fast), color var(--transition-fast));\n }\n\n :host([open]) .chevron {\n color: var(--_theme-focus, var(--color-primary));\n transform: translateY(-50%) rotate(180deg);\n }\n\n .chevron .loader {\n display: none;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid currentcolor;\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: var(--_motion-animation, bit-combobox-spin 0.6s linear infinite);\n }\n\n :host([loading]) .chevron .loader {\n display: inline-block;\n }\n\n :host([loading]) .chevron svg {\n display: none;\n }\n\n @keyframes bit-combobox-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .clear-btn {\n position: absolute;\n inset-inline-end: var(--size-9);\n top: 50%;\n display: inline-flex;\n visibility: hidden;\n flex-shrink: 0;\n align-items: center;\n padding: 0;\n color: var(--color-contrast-400);\n cursor: pointer;\n background: none;\n border: 0;\n transform: translateY(-50%);\n }\n\n .clear-btn:hover {\n color: var(--color-contrast-600);\n }\n\n :host([clearable]) .clear-btn:not([hidden]) {\n visibility: visible;\n }\n\n /* ========================================\n Dropdown / Listbox\n ======================================== */\n\n .dropdown {\n position: fixed;\n inset-inline-start: 0;\n top: 0;\n z-index: calc(var(--z-popover, 1000) + 1);\n box-sizing: border-box;\n visibility: hidden;\n max-height: min(16rem, 50dvh);\n padding: var(--size-1);\n margin: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n text-align: start;\n pointer-events: none;\n scrollbar-width: thin;\n background: var(--color-canvas);\n border: var(--border) solid var(--color-contrast-200);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-lg);\n opacity: 0;\n transform: translateY(-4px);\n transition: var(\n --_motion-transition,\n opacity var(--transition-fast),\n transform var(--transition-fast),\n visibility var(--transition-fast)\n );\n }\n\n .dropdown[data-open] {\n visibility: visible;\n pointer-events: auto;\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ========================================\n Option Items\n ======================================== */\n\n .option {\n display: flex;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-1-5) var(--size-2-5);\n font-size: var(--_font-size);\n line-height: var(--leading-normal);\n cursor: pointer;\n border-radius: var(--rounded-sm);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n }\n\n /* Truncate long labels so options always stay single-line (fixed virtualizer row height). */\n .option > span:not(.option-check, .option-icon) {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .option:hover:not([data-disabled]) {\n background: var(--color-contrast-100);\n }\n\n .option[data-focused]:not([data-disabled]) {\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-base) 12%, var(--color-contrast-100));\n }\n\n .option[data-selected] {\n font-weight: var(--font-medium);\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-base) 10%, var(--color-contrast-50));\n }\n\n .option[data-selected][data-focused] {\n background: color-mix(in srgb, var(--_theme-base) 20%, var(--color-contrast-100));\n }\n\n .option[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .option-check {\n display: inline-flex;\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--_theme-base);\n opacity: 0;\n transition: opacity var(--transition-fast);\n }\n\n .option[data-selected] .option-check {\n opacity: 1;\n }\n\n .no-results,\n .no-results-create,\n .dropdown-loading {\n padding: var(--size-3) var(--size-2-5);\n font-size: var(--_font-size);\n color: var(--color-contrast-400);\n text-align: center;\n }\n\n .no-results-create {\n display: flex;\n gap: var(--size-1-5);\n align-items: center;\n width: 100%;\n padding: var(--size-1-5) var(--size-2-5);\n font-size: var(--_font-size);\n color: var(--_theme-content, var(--color-primary-content));\n text-align: start;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: var(--rounded-sm);\n }\n\n .no-results-create:hover,\n .no-results-create[data-focused] {\n background: color-mix(in srgb, var(--_theme-base, var(--color-primary)) 10%, transparent);\n }\n\n /* ========================================\n Option Icon\n ======================================== */\n\n .option-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n }\n\n /* ========================================\n Slotted option elements (hidden data nodes)\n ======================================== */\n\n ::slotted(bit-combobox-option) {\n display: none;\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n /* ========================================\n Focus / Hover States\n ======================================== */\n\n :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n border-color: var(--color-contrast-400);\n }\n\n :host(:not([disabled], [variant='flat'])) .field:focus-within,\n :host([open]:not([disabled], [variant='flat'])) .field {\n background: var(--color-canvas);\n border-color: var(--_theme-focus);\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n transform: translateY(-1px);\n }\n\n :host(:not([disabled])) .field:focus-within .label-inset,\n :host(:not([disabled])) .field:focus-within .label-outside,\n :host([open]:not([disabled])) .label-inset {\n color: var(--_theme-focus);\n }\n\n :host([error]:not([error=''])) .field {\n border-color: var(--color-error);\n }\n\n :host([error]:not([error=''])) .field:focus-within {\n border-color: var(--color-error);\n box-shadow: var(--color-error-focus-shadow);\n }\n\n :host([error]:not([error=''])) .label-inset,\n :host([error]:not([error=''])) .label-outside {\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n /* Solid (Default) */\n :host(:not([variant])) .field,\n :host([variant='solid']) .field {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n box-shadow: var(--shadow-2xs);\n }\n\n :host(:not([variant], [disabled])) .field:focus-within,\n :host([variant='solid']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Flat */\n :host([variant='flat']) .field {\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) .field:hover {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .field:focus-within {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered */\n :host([variant='bordered']) .field {\n background: var(--_theme-backdrop);\n border-color: color-mix(in srgb, var(--_theme-focus) 70%, transparent);\n }\n\n :host([variant='bordered']) .input {\n color: var(--color-contrast-900);\n }\n\n :host([variant='bordered']) .input::placeholder {\n color: var(--_placeholder);\n }\n\n :host([variant='bordered']) .field:hover {\n border-color: var(--_theme-focus);\n }\n\n /* Outline */\n :host([variant='outline']) .field {\n background: transparent;\n box-shadow: none;\n }\n\n :host([variant='outline']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Ghost */\n :host([variant='ghost']) .field {\n background: transparent;\n border-color: transparent;\n box-shadow: none;\n }\n\n :host([variant='ghost']) .field:hover {\n background: var(--color-contrast-100);\n }\n\n :host([variant='ghost']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n}\n\n@layer buildit.utilities {\n :host([fullwidth]) {\n display: flex;\n width: 100%;\n }\n}\n","import {\n aria,\n computed,\n createFormIds,\n css,\n defineComponent,\n defineField,\n effect,\n html,\n inject,\n onMount,\n onSlotChange,\n ref,\n signal,\n typed,\n watch,\n} from '@vielzeug/craftit';\nimport {\n createListNavigation,\n createOverlayControl,\n createSelectionControl,\n type ListNavigationResult,\n type OverlayOpenReason,\n} from '@vielzeug/craftit/labs';\n\nimport type { AddEventListeners } from '../../types';\n\nimport '../../feedback/chip/chip';\nimport { checkIconHTML, chevronDownIcon, clearIcon } from '../../icons';\nimport { disabledLoadingMixin, forcedColorsFocusMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { FIELD_SIZE_PRESET } from '../shared/design-presets';\nimport { createDropdownPositioner, mountLabelSyncStandalone } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport { computeControlledCsvState, createChoiceChangeDetail, resolveMergedAssistiveText } from '../shared/utils';\nimport { createFieldValidation } from '../shared/validation';\nimport {\n backfillSelectionLabels,\n filterOptions,\n getCreatableLabel,\n makeCreatableValue,\n parseSlottedOptions,\n} from './combobox-options';\nimport { createComboboxVirtualizer } from './combobox-virtualizer';\nimport componentStyles from './combobox.css?inline';\nimport {\n type BitComboboxEvents,\n type BitComboboxProps,\n type ComboboxOptionItem,\n type ComboboxSelectionItem,\n} from './combobox.types';\n\nexport type { BitComboboxEvents, BitComboboxOptionProps, BitComboboxProps } from './combobox.types';\n\n// ============================================\n// Styles\n// ============================================\n\n// ============================================\n// ComboboxOption Component\n// ============================================\n\n/**\n * `bit-combobox-option` — A child element of `<bit-combobox>` that represents one option.\n *\n * @slot - Label text for the option.\n * @slot icon - Optional leading icon or decoration.\n */\nexport const COMBOBOX_OPTION_TAG = defineComponent({\n setup() {\n const optionStyles = /* css */ css`\n @layer buildit.base {\n :host {\n display: none;\n }\n }\n `;\n\n return html`<style>\n ${optionStyles}\n </style>`;\n },\n tag: 'bit-combobox-option',\n});\n\n// ============================================\n// Component\n// ============================================\n\n/**\n * `bit-combobox` — Autocomplete/combobox text input with a filterable listbox.\n *\n * Place `<bit-combobox-option>` elements as children to define the available options.\n * Each option supports a `label` attribute (falls back to text content) and an `icon` named slot.\n *\n * @example\n * ```html\n * <bit-combobox label=\"Country\" placeholder=\"Search\\u2026\">\n * <bit-combobox-option value=\"us\">United States</bit-combobox-option>\n * <bit-combobox-option value=\"gb\">United Kingdom</bit-combobox-option>\n * <bit-combobox-option value=\"de\" disabled>Germany</bit-combobox-option>\n * </bit-combobox>\n * ```\n */\nexport const COMBOBOX_TAG = defineComponent<BitComboboxProps, BitComboboxEvents>({\n formAssociated: true,\n props: {\n clearable: { default: false },\n color: { default: undefined },\n creatable: { default: false },\n disabled: { default: false },\n error: { default: '', omit: true },\n fullwidth: { default: false },\n helper: { default: '' },\n label: { default: '' },\n 'label-placement': { default: 'inset' },\n loading: { default: false },\n multiple: { default: false },\n name: { default: '' },\n 'no-filter': { default: false },\n options: typed<ComboboxOptionItem[] | undefined>(undefined, { reflect: false }),\n placeholder: { default: '' },\n rounded: { default: undefined },\n size: { default: undefined },\n value: { default: '' },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const { fieldId: comboId, helperId, labelId } = createFormIds('combobox', props.name.value);\n // Label refs\n const labelOutsideRef = ref<HTMLLabelElement>();\n const labelInsetRef = ref<HTMLLabelElement>();\n const formCtx = inject(FORM_CTX, undefined);\n // Signal for the form value\n const formValue = signal(String(props.value.value ?? ''));\n const fd = defineField(\n { disabled: computed(() => Boolean(props.disabled.value) || Boolean(formCtx?.disabled.value)), value: formValue },\n {\n onReset: () => {\n formValue.value = '';\n selectedValues.value = [];\n query.value = '';\n },\n },\n );\n\n const { triggerValidation } = createFieldValidation(formCtx, fd);\n\n // ── State ────────────────────────────────────────────────────────────────\n const isOpen = signal(false);\n const query = signal('');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const isMultiple = computed(() => Boolean(props.multiple.value));\n const isCreatable = computed(() => Boolean(props.creatable.value));\n const isNoFilter = computed(() => Boolean(props['no-filter'].value));\n\n watch(\n isOpen,\n (value) => {\n host.toggleAttribute('open', ((value) => Boolean(value))(value));\n },\n { immediate: true },\n );\n\n // Multi-value state: always an array; single mode uses at most one entry\n const selectedValues = signal<ComboboxSelectionItem[]>(\n props.value.value ? [{ label: '', value: props.value.value }] : [],\n );\n const focusedIndex = signal(-1);\n const selectionController = createSelectionControl<ComboboxSelectionItem>({\n findByKey: (value) => {\n const existing = selectedValues.value.find((item) => item.value === value);\n\n if (existing) return existing;\n\n // If not found in selection, try to find in all options to get label\n const option = allOptions.value.find((o) => o.value === value);\n\n if (option) return { label: option.label, value: option.value };\n\n // Fallback: key is the value\n return { label: '', value };\n },\n getMode: () => (isMultiple.value ? 'multiple' : 'single'),\n getSelected: () => selectedValues.value,\n keyExtractor: (item) => item.value,\n setSelected: (next) => {\n selectedValues.value = next;\n },\n });\n\n // Sync external value prop changes to selectedValues (controlled mode)\n const syncControlledValue = (nextValue: unknown): void => {\n const state = computeControlledCsvState(String(nextValue ?? ''));\n\n if (state.isEmpty) {\n selectionController.clear();\n query.value = '';\n formValue.value = '';\n\n return;\n }\n\n if (isMultiple.value) {\n selectedValues.value = state.values.map((value) => ({ label: '', value }));\n formValue.value = state.formValue;\n\n return;\n }\n\n // Single mode: one value\n selectedValues.value = [{ label: '', value: state.firstValue }];\n formValue.value = state.firstValue;\n };\n\n watch(props.value, (newValue) => syncControlledValue(newValue), { immediate: true });\n watch(props.multiple, () => syncControlledValue(props.value.value));\n\n // Convenience getter for single-select\n const selectedValue = computed(() => selectedValues.value[0]?.value ?? '');\n const hasValue = computed(() => selectedValues.value.length > 0);\n const hasLabel = computed(() => !!props.label.value);\n let inputEl: HTMLInputElement | null = null;\n let fieldEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\n let listboxEl: HTMLElement | null = null;\n\n function getLiveInput(): HTMLInputElement | null {\n const liveInput = host.shadowRoot?.querySelector<HTMLInputElement>('input[role=\"combobox\"]') ?? null;\n\n if (liveInput) inputEl = liveInput;\n\n return liveInput ?? inputEl;\n }\n\n function focusLiveInput() {\n getLiveInput()?.focus();\n }\n\n // ── Options ──────────────────────────────────────────────────────────────\n const slottedOptions = signal<ComboboxOptionItem[]>([]);\n const createdOptions = signal<ComboboxOptionItem[]>([]);\n const isLoading = computed(() => Boolean(props.loading.value));\n // Merged options: explicit prop value overrides slotted options.\n const allOptions = computed<ComboboxOptionItem[]>(() => {\n const base = props.options.value ?? slottedOptions.value;\n\n if (createdOptions.value.length === 0) return base;\n\n return [...base, ...createdOptions.value];\n });\n\n function readOptions(elements: Element[] = Array.from(host.children)) {\n slottedOptions.value = parseSlottedOptions(elements);\n\n // Backfill labels for any already-selected values that were set before options loaded\n if (selectedValues.value.length > 0) {\n selectedValues.value = backfillSelectionLabels(selectedValues.value, allOptions.value);\n\n // Also sync the query in single mode\n if (!isMultiple.value && selectedValues.value.length === 1) {\n query.value = selectedValues.value[0]?.label ?? '';\n }\n }\n }\n\n const filteredOptions = computed<ComboboxOptionItem[]>(() => {\n return filterOptions(allOptions.value, query.value, isNoFilter.value);\n });\n // \"Create\" option shown when creatable + query doesn't match any existing option\n const creatableLabel = computed(() => {\n return getCreatableLabel(query.value, isCreatable.value, filteredOptions.value);\n });\n const assistiveText = computed(() => resolveMergedAssistiveText(props.error.value, props.helper.value));\n const inputPlaceholder = computed(() =>\n isMultiple.value && selectedValues.value.length > 0 ? '' : props.placeholder.value || '',\n );\n\n const selectedValueItems = computed(() => selectedValues.value.map((s) => s.value));\n const selectedLabelItems = computed(() =>\n selectedValues.value.map((selection) => {\n if (selection.label) return selection.label;\n\n return allOptions.value.find((option) => option.value === selection.value)?.label ?? selection.value;\n }),\n );\n\n function syncMultipleFormValue() {\n formValue.value = selectionController.serialize(',');\n }\n\n function emitChange(originalEvent?: Event) {\n emit('change', createChoiceChangeDetail(selectedValueItems.value, selectedLabelItems.value, originalEvent));\n }\n\n function removeChip(event: Event): void {\n event.stopPropagation();\n\n const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n if (value === undefined) return;\n\n selectionController.remove(value);\n syncMultipleFormValue();\n emitChange(event);\n triggerValidation('change');\n }\n\n // ── Positioning (shared positioner) ──────────────────────────────────────\n const positioner = createDropdownPositioner(\n () => fieldEl,\n () => dropdownEl,\n );\n\n const listNavigation = createListNavigation<ComboboxOptionItem>({\n getIndex: () => focusedIndex.value,\n getItems: () => filteredOptions.value,\n isItemDisabled: (option) => option.disabled,\n setIndex: (index) => {\n focusedIndex.value = index;\n scrollFocusedIntoView();\n },\n });\n\n const overlay = createOverlayControl({\n getBoundaryElement: () => host,\n getPanelElement: () => dropdownEl,\n getTriggerElement: () => inputEl,\n isDisabled: () => isDisabled.value,\n isOpen: () => isOpen.value,\n positioner: {\n floating: () => dropdownEl,\n reference: () => fieldEl,\n update: () => positioner.updatePosition(),\n },\n restoreFocus: false,\n setOpen: (next, _context) => {\n isOpen.value = next;\n\n if (!next) listNavigation.reset();\n },\n });\n\n const applyNavigationResult = (result: ListNavigationResult): void => {\n if (result.reason === 'empty' || result.reason === 'no-enabled-item') {\n focusedIndex.value = -1;\n }\n };\n\n // ── Open / Close ─────────────────────────────────────────────────────────\n function open(clearFilter = true, reason: OverlayOpenReason = 'programmatic') {\n if (clearFilter) query.value = '';\n\n overlay.open({ reason });\n }\n\n function close(reason: 'escape' | 'programmatic' | 'outside-click' | 'toggle' = 'programmatic') {\n overlay.close({ reason, restoreFocus: false });\n\n // In single mode restore the query to the selected label (or clear)\n if (!isMultiple.value) {\n const match = allOptions.value.find((o) => o.value === selectedValue.value);\n\n query.value = match?.label ?? '';\n } else {\n query.value = '';\n }\n\n triggerValidation('blur');\n }\n // ── Selection ────────────────────────────────────────────────────────────\n function selectOption(opt: ComboboxOptionItem, originalEvent?: Event) {\n if (opt.disabled) return;\n\n if (isMultiple.value) {\n selectionController.toggle(opt.value);\n syncMultipleFormValue();\n query.value = '';\n emitChange(originalEvent);\n triggerValidation('change');\n // Keep dropdown open in multiple mode\n focusLiveInput();\n requestAnimationFrame(() => focusLiveInput());\n } else {\n selectionController.select(opt.value);\n query.value = opt.label;\n formValue.value = opt.value;\n emitChange(originalEvent);\n triggerValidation('change');\n close();\n focusLiveInput();\n }\n }\n function clearValue(e: Event) {\n e.stopPropagation();\n selectionController.clear();\n query.value = '';\n formValue.value = '';\n emitChange(e);\n triggerValidation('change');\n focusLiveInput();\n }\n function handleInput(e: Event) {\n const target = e.target as HTMLInputElement;\n\n query.value = target.value;\n\n if (!isMultiple.value) selectionController.clear();\n\n applyNavigationResult(listNavigation.first());\n\n if (!isOpen.value) open(false, 'trigger');\n\n emit('search', { query: target.value } as { query: string });\n }\n function handleFocus() {\n if (!isOpen.value) open(false, 'trigger');\n }\n // ── Keyboard Navigation ──────────────────────────────────────────────────\n function handleKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const opts = filteredOptions.value;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n\n if (!isOpen.value) {\n open(true, 'trigger');\n\n applyNavigationResult(listNavigation.first());\n } else {\n applyNavigationResult(listNavigation.next());\n }\n\n break;\n case 'ArrowUp':\n e.preventDefault();\n\n if (!isOpen.value) {\n open(true, 'trigger');\n } else {\n applyNavigationResult(listNavigation.prev());\n }\n\n break;\n case 'Backspace':\n // In multiple mode, remove the last chip when the input is empty\n if (isMultiple.value && !query.value && selectedValues.value.length > 0) {\n selectedValues.value = selectedValues.value.slice(0, -1);\n syncMultipleFormValue();\n emitChange(e);\n triggerValidation('change');\n }\n\n break;\n case 'End':\n if (isOpen.value) {\n e.preventDefault();\n applyNavigationResult(listNavigation.last());\n }\n\n break;\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value && focusedIndex.value >= 0 && focusedIndex.value < opts.length) {\n selectOption(opts[focusedIndex.value], e);\n } else if (isOpen.value && focusedIndex.value === -1 && creatableLabel.value) {\n // Focused on the \"create\" item\n createOption(creatableLabel.value, e);\n } else if (!isOpen.value) {\n open();\n }\n\n break;\n case 'Escape':\n e.preventDefault();\n\n if (isOpen.value) {\n close('escape');\n }\n\n break;\n case 'Home':\n if (isOpen.value) {\n e.preventDefault();\n applyNavigationResult(listNavigation.first());\n }\n\n break;\n case 'Tab':\n close('programmatic');\n break;\n default:\n break;\n }\n }\n function scrollFocusedIntoView() {\n if (focusedIndex.value >= 0) {\n domVirtualList.scrollToIndex(focusedIndex.value, { align: 'auto' });\n\n return;\n }\n\n if (!listboxEl) return;\n\n const focusedEl = listboxEl.querySelector<HTMLElement>('[data-focused]');\n\n focusedEl?.scrollIntoView({ block: 'nearest' });\n }\n\n // ── Virtualizer ──────────────────────────────────────────────────────────\n const { domVirtualList, setupVirtualizer, updateRenderedItemState } = createComboboxVirtualizer({\n checkIconHTML,\n comboId,\n getDropdownElement: () => dropdownEl,\n getFocusedIndex: () => focusedIndex.peek(),\n getIsMultiple: () => isMultiple.peek(),\n getListboxElement: () => listboxEl,\n getSelectedValue: () => selectedValue.peek(),\n getSelectedValues: () => selectedValues.peek(),\n onSelectOption: selectOption,\n setFocusedIndex: (index) => {\n focusedIndex.value = index;\n },\n });\n\n // ── Create option ────────────────────────────────────────────────────────\n function createOption(label: string, originalEvent?: Event) {\n const value = makeCreatableValue(label);\n const newOpt: ComboboxOptionItem = { disabled: false, iconEl: null, label, value };\n\n createdOptions.value = [...createdOptions.value, newOpt];\n selectOption(newOpt, originalEvent);\n }\n // ── Lifecycle ────────────────────────────────────────────────────────────\n onMount(() => {\n fieldEl = inputEl?.closest('.field') as HTMLElement | null;\n dropdownEl = host.shadowRoot?.querySelector<HTMLElement>('.dropdown') ?? null;\n listboxEl = host.shadowRoot?.querySelector<HTMLElement>('[role=\"listbox\"]') ?? null;\n\n const removeOutsideClick = overlay.bindOutsideClick(document);\n\n onSlotChange('default', readOptions);\n // Ensure initial light-DOM options are available for immediate keyboard interaction.\n readOptions();\n // Rebuild virtualizer when filtered options or open state changes\n effect(() => {\n const opts = filteredOptions.value;\n const open = isOpen.value;\n\n if (open && opts.length > 0) {\n requestAnimationFrame(() => setupVirtualizer(opts, open));\n } else {\n domVirtualList.update(opts, false);\n }\n });\n mountLabelSyncStandalone(labelInsetRef, labelOutsideRef, props);\n effect(() => {\n if (listboxEl) {\n // Remove existing state nodes\n for (const el of Array.from(listboxEl.querySelectorAll('.no-results,.no-results-create,.dropdown-loading')))\n el.remove();\n\n if (isLoading.value) {\n const loadingEl = document.createElement('div');\n\n loadingEl.className = 'dropdown-loading';\n loadingEl.textContent = 'Loading\\u2026';\n listboxEl.prepend(loadingEl);\n } else if (filteredOptions.value.length === 0) {\n if (creatableLabel.value) {\n const createEl = document.createElement('button');\n\n createEl.type = 'button';\n createEl.className = 'no-results-create';\n createEl.textContent = `Create \"${creatableLabel.value}\"`;\n\n // Apply focused state when keyboard nav lands here (focusedIndex === -1 means create row)\n if (focusedIndex.value === -1) createEl.setAttribute('data-focused', '');\n\n createEl.addEventListener('pointerdown', (e: PointerEvent) => {\n e.preventDefault();\n });\n\n createEl.addEventListener('click', (e) => {\n e.stopPropagation();\n createOption(creatableLabel.value, e);\n });\n listboxEl.appendChild(createEl);\n } else {\n const noResults = document.createElement('div');\n\n noResults.className = 'no-results';\n noResults.setAttribute('role', 'presentation');\n noResults.textContent = 'No results found';\n listboxEl.appendChild(noResults);\n }\n }\n\n // Update focused/selected state on already-rendered items without touching\n // the DOM structure. The virtualizer owns full re-renders via onChange.\n updateRenderedItemState();\n }\n });\n // Keep rendered option selected/focused attributes in sync while the popup stays open.\n watch(\n [isOpen, props.multiple, focusedIndex, selectedValues, selectedValue],\n () => {\n if (!isOpen.value) return;\n\n updateRenderedItemState();\n },\n { immediate: true },\n );\n\n return () => {\n domVirtualList.destroy();\n positioner.destroy();\n removeOutsideClick();\n };\n });\n\n return html`\n <slot></slot>\n <div class=\"combobox-wrapper\" part=\"wrapper\">\n <label\n class=\"label-outside\"\n for=\"${comboId}\"\n id=\"${labelId}\"\n ref=${labelOutsideRef}\n hidden\n part=\"label\"></label>\n <div\n class=\"field\"\n part=\"field\"\n @click=\"${() => {\n if (!isOpen.value) open(false, 'trigger');\n\n focusLiveInput();\n }}\">\n <label class=\"label-inset\" for=\"${comboId}\" id=\"${labelId}\" ref=${labelInsetRef} hidden part=\"label\"></label>\n <div class=\"field-row\">\n <div class=\"chips-row\">\n <!-- Keep chip list diffing isolated so input node identity stays stable. -->\n <span class=\"chips-list\">\n ${() =>\n (isMultiple.value ? selectedValues.value : []).map(\n (item) => html`\n <bit-chip\n value=${item.value}\n aria-label=${item.label || item.value}\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=${() => props.color.value}\n @remove=${removeChip}>\n ${item.label || item.value}\n </bit-chip>\n `,\n )}\n </span>\n <input\n ref=${(el: HTMLInputElement | null) => {\n inputEl = el;\n\n if (!el) {\n fieldEl = null;\n\n return;\n }\n\n fieldEl = el.closest('.field') as HTMLElement | null;\n aria(el, {\n activedescendant: () => (focusedIndex.value >= 0 ? `${comboId}-opt-${focusedIndex.value}` : null),\n autocomplete: 'list',\n controls: () => `${comboId}-listbox`,\n describedby: () => (props.error.value || props.helper.value ? helperId : null),\n disabled: () => isDisabled.value,\n expanded: () => (isOpen.value ? 'true' : 'false'),\n invalid: () => !!props.error.value,\n labelledby: () => (hasLabel.value ? labelId : null),\n });\n }}\n class=\"input\"\n part=\"input\"\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n id=\"${comboId}\"\n name=\"${() => props.name.value}\"\n placeholder=${() => inputPlaceholder.value}\n :disabled=\"${() => isDisabled.value}\"\n @input=${handleInput}\n @keydown=${handleKeydown}\n @focus=${handleFocus}\n .value=${query} />\n </div>\n <button\n class=\"clear-btn\"\n part=\"clear-btn\"\n type=\"button\"\n aria-label=\"Clear\"\n tabindex=\"-1\"\n ?hidden=${() => !hasValue.value}\n @click=\"${clearValue}\">\n ${clearIcon}\n </button>\n <span class=\"chevron\" aria-hidden=\"true\">\n ${chevronDownIcon}\n <span class=\"loader\" aria-label=\"Loading\"></span>\n </span>\n </div>\n </div>\n\n <div class=\"dropdown\" part=\"dropdown\" id=\"${() => `${comboId}-dropdown`}\" ?data-open=${() => isOpen.value}>\n <div\n role=\"listbox\"\n id=\"${() => `${comboId}-listbox`}\"\n aria-label=\"${() => props.label.value || props.placeholder.value || 'Options'}\"></div>\n </div>\n\n <span\n class=\"helper-text\"\n id=\"${helperId}\"\n part=\"helper-text\"\n aria-live=\"polite\"\n ?hidden=${() => assistiveText.value.hidden}\n style=${() => (assistiveText.value.isError ? 'color: var(--color-error);' : '')}\n >${() => assistiveText.value.text}</span\n >\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n sizeVariantMixin(FIELD_SIZE_PRESET),\n ...formFieldMixins,\n disabledLoadingMixin(),\n forcedColorsFocusMixin('.input'),\n componentStyles,\n ],\n tag: 'bit-combobox',\n}) as unknown as AddEventListeners<BitComboboxEvents>;\n","@layer buildit.base {\n :host {\n --_font-size: var(--file-input-font-size, var(--text-sm));\n --_radius: var(--file-input-radius, var(--rounded-lg));\n --_bg: var(--file-input-bg, var(--color-contrast-100));\n --_border-color: var(--file-input-border-color, var(--color-contrast-300));\n --_min-height: var(--file-input-min-height, var(--size-36));\n\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n .file-input-wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--size-1-5);\n width: 100%;\n }\n\n /* ========================================\n Label\n ======================================== */\n\n .label-outside {\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n line-height: var(--leading-none);\n color: var(--color-contrast-500);\n cursor: default;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n /* ========================================\n Dropzone\n ======================================== */\n\n .dropzone {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: var(--size-2);\n align-items: center;\n justify-content: center;\n min-height: var(--_min-height);\n padding: var(--size-6) var(--size-4);\n text-align: center;\n cursor: pointer;\n outline: none;\n background: var(--_bg);\n border: var(--border-2) dashed var(--_border-color);\n border-radius: var(--_radius);\n transition:\n background var(--transition-fast),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast);\n }\n\n .dropzone-content {\n display: flex;\n flex-direction: column;\n gap: var(--size-2);\n align-items: center;\n pointer-events: none;\n }\n\n .dropzone-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color-contrast-400);\n transition:\n color var(--transition-fast),\n transform var(--transition-fast);\n }\n\n .dropzone-title {\n font-size: var(--_font-size);\n font-weight: var(--font-medium);\n line-height: var(--leading-snug);\n color: var(--color-contrast-700);\n }\n\n .dropzone-title u {\n color: var(--_theme-focus, var(--color-primary));\n text-decoration: underline;\n text-decoration-color: transparent;\n text-underline-offset: 2px;\n transition: text-decoration-color var(--transition-fast);\n }\n\n .dropzone-hint {\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-400);\n }\n\n /* ========================================\n Helper Text\n ======================================== */\n\n .helper-text {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n /* ========================================\n File List\n ======================================== */\n\n .file-list {\n display: flex;\n flex-direction: column;\n gap: var(--size-1);\n padding: 0;\n margin: 0;\n list-style: none;\n }\n\n .file-item {\n box-sizing: border-box;\n display: flex;\n gap: var(--size-3);\n align-items: center;\n padding: var(--size-2) var(--size-3);\n background: var(--color-contrast-50);\n border: var(--border) solid var(--color-contrast-200);\n border-radius: var(--_radius);\n transition: background var(--transition-fast);\n }\n\n .file-item:hover {\n background: var(--color-contrast-100);\n }\n\n .file-icon {\n flex-shrink: 0;\n color: var(--_theme-focus, var(--color-primary));\n }\n\n .file-meta {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--size-0-5);\n min-width: 0;\n }\n\n .file-name {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-contrast-700);\n white-space: nowrap;\n }\n\n .file-size {\n font-size: var(--text-xs);\n color: var(--color-contrast-400);\n }\n\n .file-remove {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n padding: var(--size-1);\n color: var(--color-contrast-400);\n cursor: pointer;\n background: transparent;\n border: none;\n border-radius: var(--rounded-sm);\n transition:\n color var(--transition-fast),\n background var(--transition-fast);\n }\n\n .file-remove:hover {\n color: var(--color-error);\n background: var(--color-error-backdrop, color-mix(in srgb, var(--color-error) 12%, transparent));\n }\n\n /* ========================================\n Hover & Focus\n ======================================== */\n\n :host(:not([disabled])) .dropzone:hover {\n border-color: var(--color-contrast-400);\n }\n\n :host(:not([disabled])) .dropzone:hover .dropzone-title u {\n text-decoration-color: var(--_theme-focus, var(--color-primary));\n }\n\n :host(:not([disabled])) .dropzone:focus-visible {\n border-color: var(--_theme-focus, var(--color-primary));\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n }\n\n :host(:not([disabled])) .dropzone:hover .dropzone-icon,\n :host(:not([disabled])) .dropzone:focus-visible .dropzone-icon {\n color: var(--_theme-focus, var(--color-primary));\n transform: translateY(-2px);\n }\n\n /* ========================================\n Drag-Over State\n ======================================== */\n\n :host([drag-over]) .dropzone {\n background: color-mix(in srgb, var(--_theme-base, var(--color-primary)) 8%, var(--color-canvas));\n border-color: var(--_theme-focus, var(--color-primary));\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n }\n\n :host([drag-over]) .dropzone .dropzone-icon {\n color: var(--_theme-focus, var(--color-primary));\n transform: translateY(-4px) scale(1.1);\n }\n\n /* ========================================\n Error State\n ======================================== */\n\n :host([invalid]) .dropzone {\n border-color: var(--color-error);\n }\n\n :host([invalid]) .label-outside {\n color: var(--color-error);\n }\n\n /* ========================================\n Error Text\n ======================================== */\n\n .helper-text-error {\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n /* Solid (Default) */\n :host(:not([variant])) .dropzone,\n :host([variant='solid']) .dropzone {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n }\n\n /* Flat */\n :host([variant='flat']) .dropzone {\n border-color: var(--_theme-border);\n }\n\n :host([variant='flat']) .dropzone:hover {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .dropzone:focus-visible,\n :host([variant='flat'][drag-over]) .dropzone {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered */\n :host([variant='bordered']) .dropzone {\n background: var(--_theme-backdrop);\n border-color: color-mix(in srgb, var(--_theme-focus) 70%, transparent);\n }\n\n :host([variant='bordered']) .dropzone:hover {\n border-color: var(--_theme-focus);\n }\n\n /* Outline */\n :host([variant='outline']) .dropzone {\n background: transparent;\n }\n\n /* Ghost */\n :host([variant='ghost']) .dropzone {\n background: transparent;\n border-color: var(--color-contrast-200);\n }\n\n :host([variant='ghost']) .dropzone:hover {\n background: var(--color-contrast-100);\n }\n}\n\n@layer buildit.utilities {\n :host([fullwidth]) {\n width: 100%;\n }\n}\n","import {\n computed,\n createId,\n defineComponent,\n defineField,\n effect,\n handle,\n html,\n onCleanup,\n onMount,\n ref,\n signal,\n} from '@vielzeug/craftit';\nimport { each } from '@vielzeug/craftit/directives';\nimport { createDropZone } from '@vielzeug/dragit';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { clearIcon, fileIcon, uploadIcon } from '../../icons';\nimport { disabledLoadingMixin, forcedColorsFocusMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { FILE_INPUT_SIZE_PRESET } from '../shared/design-presets';\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n\n const units = ['B', 'KB', 'MB', 'GB'] as const;\n const k = 1024;\n const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), units.length - 1);\n\n return `${Number.parseFloat((bytes / k ** i).toFixed(1))} ${units[i]}`;\n}\n\nfunction matchesAccept(file: File, accept: string | undefined): boolean {\n if (!accept) return true;\n\n return accept\n .split(',')\n .map((s) => s.trim())\n .some((pattern) => {\n if (pattern.startsWith('.')) return file.name.toLowerCase().endsWith(pattern.toLowerCase());\n\n if (pattern.endsWith('/*')) return file.type.startsWith(pattern.slice(0, -1));\n\n return file.type === pattern;\n });\n}\n\nfunction isFileAccepted(file: File, accept: string | undefined): boolean {\n return !accept || matchesAccept(file, accept);\n}\n\nfunction isFileSizeAllowed(file: File, maxBytes: number | undefined): boolean {\n if (maxBytes == null) return true;\n\n return maxBytes === 0 || file.size <= maxBytes;\n}\n\n// ============================================\n// Component Styles\n// ============================================\n\nimport componentStyles from './file-input.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\n/** FileInput component properties */\n\nexport type BitFileInputEvents = {\n change: { files: File[]; originalEvent?: Event; value: File[] };\n remove: { file: File; files: File[]; originalEvent?: Event; value: File[] };\n};\n\nexport type BitFileInputProps = {\n /** Accepted file types (MIME types or extensions, comma-separated) */\n accept?: string;\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message (marks field as invalid) */\n error?: string;\n /** Full width mode */\n fullwidth?: boolean;\n /** Helper text */\n helper?: string;\n /** Label text */\n label?: string;\n /** Maximum number of files (0 = unlimited) */\n 'max-files'?: number;\n /** Maximum file size in bytes (0 = unlimited) */\n 'max-size'?: number;\n /** Allow multiple file selection */\n multiple?: boolean;\n /** Form field name */\n name?: string;\n /** Mark as required */\n required?: boolean;\n /** Border radius */\n rounded?: Exclude<RoundedSize, 'full'>;\n /** Component size */\n size?: ComponentSize;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'glass' | 'text' | 'frost'>;\n};\n\n// ============================================\n// Component Definition\n// ============================================\n\n/**\n * A file upload component with drag-and-drop support, file list management,\n * and full form integration.\n *\n * @element bit-file-input\n *\n * @attr {string} accept - Accepted file types (MIME types or extensions, e.g. \"image/*,.pdf\")\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {boolean} disabled - Disable all interaction\n * @attr {string} error - Error message\n * @attr {boolean} fullwidth - Full width mode\n * @attr {string} helper - Helper text below the dropzone\n * @attr {string} label - Label text displayed above the dropzone\n * @attr {number} max-files - Maximum number of files (0 = unlimited)\n * @attr {number} max-size - Maximum file size in bytes (0 = unlimited)\n * @attr {boolean} multiple - Allow selecting multiple files\n * @attr {string} name - Form field name\n * @attr {boolean} required - Mark as required\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n *\n * @fires change - Emitted when the file selection changes. detail: { value: File[], files: File[], originalEvent?: Event }\n * @fires remove - Emitted when a file is removed from the list. detail: { value: File[], file: File, files: File[], originalEvent?: Event }\n *\n * @part wrapper - The outer wrapper div\n * @part label - The label element\n * @part dropzone - The drag-and-drop zone\n * @part input - The hidden native file input\n * @part helper - The helper text element\n * @part error - The error text element\n *\n * @cssprop --file-input-bg - Dropzone background color\n * @cssprop --file-input-border-color - Dropzone border color\n * @cssprop --file-input-radius - Border radius\n * @cssprop --file-input-min-height - Minimum dropzone height\n * @cssprop --file-input-font-size - Font size\n *\n * @example\n * ```html\n * <bit-file-input label=\"Upload files\" accept=\"image/*\" multiple />\n * <bit-file-input label=\"Resume\" accept=\".pdf,.doc,.docx\" max-size=\"5242880\" />\n * <bit-file-input variant=\"bordered\" color=\"primary\" />\n * ```\n */\nexport const FILE_INPUT_TAG = defineComponent<BitFileInputProps, BitFileInputEvents>({\n formAssociated: true,\n props: {\n accept: { default: '' },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '', omit: true },\n fullwidth: { default: false },\n helper: { default: '' },\n label: { default: '' },\n 'max-files': { default: 0, type: Number },\n 'max-size': { default: 0, type: Number },\n multiple: { default: false },\n name: { default: '' },\n required: { default: false },\n rounded: { default: undefined },\n size: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n // ============================================\n // State\n // ============================================\n const files = signal<File[]>([]);\n const isDragging = signal(false);\n\n // ============================================\n // Form Integration\n // ============================================\n defineField(\n {\n disabled: computed(() => Boolean(props.disabled.value)),\n toFormValue: (fi: File[]) => {\n if (fi.length === 0) return null;\n\n const name = props.name.value || 'file';\n const fd = new FormData();\n\n for (const file of fi) fd.append(name, file);\n\n return fd;\n },\n value: files,\n },\n {\n onReset: () => {\n files.value = [];\n },\n },\n );\n\n // Sync host attributes for CSS selectors\n const isInvalid = computed(() => Boolean(props.error.value));\n\n effect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isInvalid.value ? host.setAttribute('invalid', '') : host.removeAttribute('invalid');\n });\n effect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isDragging.value ? host.setAttribute('drag-over', '') : host.removeAttribute('drag-over');\n });\n\n // ============================================\n // IDs\n // ============================================\n const fileInputId = createId('file-input');\n const labelId = `label-${fileInputId}`;\n const helperId = `helper-${fileInputId}`;\n const errorId = `error-${fileInputId}`;\n // ============================================\n // Refs\n // ============================================\n const dropzoneRef = ref<HTMLDivElement>();\n const inputRef = ref<HTMLInputElement>();\n const hintText = computed(() => {\n const parts: string[] = [];\n\n if (props.accept.value) {\n parts.push(\n props.accept.value\n .split(',')\n .map((s: string) => s.trim())\n .join(', '),\n );\n }\n\n const maxSize = props['max-size'].value ?? 0;\n\n if (maxSize > 0) parts.push(`max ${formatBytes(maxSize)}`);\n\n const maxFiles = props['max-files'].value ?? 0;\n\n if (maxFiles > 0) parts.push(`up to ${maxFiles} file${maxFiles !== 1 ? 's' : ''}`);\n\n return parts.join(' · ');\n });\n\n // ============================================\n // File Management\n // ============================================\n function addFiles(newFiles: File[], originalEvent?: Event): void {\n if (props.disabled.value) return;\n\n const maxFilesLimit = props['max-files'].value ?? 0;\n const maxSizeLimit = props['max-size'].value ?? 0;\n const acceptVal = props.accept.value;\n const isMultiple = Boolean(props.multiple.value);\n let incoming = Array.from(newFiles);\n\n if (!isMultiple) incoming = incoming.slice(0, 1);\n\n incoming = incoming.filter((f) => isFileAccepted(f, acceptVal) && isFileSizeAllowed(f, maxSizeLimit));\n\n let updated: File[] = isMultiple ? [...files.value] : [];\n\n for (const f of incoming) {\n if (!updated.includes(f)) updated.push(f);\n }\n\n if (maxFilesLimit > 0 && updated.length > maxFilesLimit) {\n updated = updated.slice(0, maxFilesLimit);\n }\n\n files.value = updated;\n emit('change', { files: files.value, originalEvent, value: files.value });\n }\n function removeFile(file: File, originalEvent?: Event): void {\n files.value = files.value.filter((f) => f !== file);\n emit('remove', { file, files: files.value, originalEvent, value: files.value });\n emit('change', { files: files.value, originalEvent, value: files.value });\n }\n // ============================================\n // Mount\n // ============================================\n onMount(() => {\n const inp = inputRef.value!;\n const dz = dropzoneRef.value!;\n\n // Native input → add files\n handle(inp, 'change', (e: Event) => {\n const input = e.target as HTMLInputElement;\n\n if (input.files?.length) addFiles(Array.from(input.files), e);\n\n input.value = ''; // reset so the same file triggers change again\n });\n // Click dropzone → open file picker\n handle(dz, 'click', () => {\n if (!props.disabled.value) inp.click();\n });\n // Keyboard: Enter / Space → open picker\n handle(dz, 'keydown', (e: KeyboardEvent) => {\n if ((e.key === 'Enter' || e.key === ' ') && !props.disabled.value) {\n e.preventDefault();\n inp.click();\n }\n });\n\n const dropZone = createDropZone({\n disabled: () => Boolean(props.disabled.value),\n element: dz,\n onDrop: (droppedFiles, e) => addFiles(droppedFiles, e),\n onHoverChange: (hovered) => {\n isDragging.value = hovered;\n },\n });\n\n onCleanup(() => dropZone.destroy());\n });\n\n // ============================================\n // Template\n // ============================================\n return html`\n <div class=\"file-input-wrapper\" part=\"wrapper\">\n <label class=\"label-outside\" id=\"${labelId}\" part=\"label\" ?hidden=${() => !props.label.value}\n >${() => props.label.value}</label\n >\n <div\n class=\"dropzone\"\n part=\"dropzone\"\n ref=${dropzoneRef}\n role=\"button\"\n :tabindex=${() => (props.disabled.value ? '-1' : '0')}\n :aria-disabled=${() => String(props.disabled.value)}\n :aria-label=${() => (!props.label.value ? 'File upload drop zone' : null)}\n :aria-labelledby=${() => (props.label.value ? labelId : null)}\n aria-describedby=\"${helperId}\">\n <input\n type=\"file\"\n ref=${inputRef}\n part=\"input\"\n id=\"${fileInputId}\"\n :accept=${() => props.accept.value}\n ?multiple=${() => props.multiple.value}\n ?required=${() => props.required.value}\n ?disabled=${() => props.disabled.value}\n :name=${() => props.name.value}\n hidden\n inert\n tabindex=\"-1\" />\n <div class=\"dropzone-content\">\n <span class=\"dropzone-icon\" aria-hidden=\"true\"> ${uploadIcon} </span>\n <span class=\"dropzone-title\">Drop files here or <u>click to browse</u></span>\n <span class=\"dropzone-hint\" ?hidden=${() => !hintText.value}>${hintText}</span>\n </div>\n </div>\n <ul class=\"file-list\" role=\"list\" aria-label=\"Selected files\" ?hidden=${() => files.value.length === 0}>\n ${each(\n files,\n (file: File) => html`\n <li class=\"file-item\">\n <span class=\"file-icon\" aria-hidden=\"true\"> ${fileIcon} </span>\n <span class=\"file-meta\">\n <span class=\"file-name\" title=\"${file.name}\">${file.name}</span>\n <span class=\"file-size\">${formatBytes(file.size)}</span>\n </span>\n <button\n class=\"file-remove\"\n type=\"button\"\n aria-label=\"${`Remove ${file.name}`}\"\n @click=${(e: Event) => removeFile(file, e)}>\n ${clearIcon}\n </button>\n </li>\n `,\n undefined,\n {\n key: (file: File) => `${file.name}:${file.size}:${file.lastModified}`,\n },\n )}\n </ul>\n <div class=\"helper-text\" id=\"${helperId}\" part=\"helper\" ?hidden=${() => isInvalid.value || !props.helper.value}>\n ${() => props.helper.value}\n </div>\n <div\n class=\"helper-text helper-text-error\"\n id=\"${errorId}\"\n role=\"alert\"\n part=\"error\"\n ?hidden=${() => !isInvalid.value}>\n ${() => props.error.value}\n </div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n ...formFieldMixins,\n sizeVariantMixin(FILE_INPUT_SIZE_PRESET),\n disabledLoadingMixin(),\n forcedColorsFocusMixin('.dropzone'),\n componentStyles,\n ],\n tag: 'bit-file-input',\n});\n","@layer buildit.base {\n :host {\n display: block;\n }\n\n form {\n display: grid;\n gap: var(--form-gap, var(--size-4, 1rem));\n align-items: start;\n }\n}\n\n@layer buildit.orientation {\n :host([orientation='horizontal']) form {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n }\n}\n","import { computed, defineComponent, html, typed, provide } from '@vielzeug/craftit';\n\nimport type { ComponentSize, VisualVariant } from '../../types';\n\nimport { FORM_CTX } from '../shared/form-context';\n// ============================================\n// Styles\n// ============================================\nimport componentStyles from './form.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\nexport type BitFormEvents = {\n reset: { originalEvent: Event };\n submit: { formData: FormData; originalEvent: SubmitEvent };\n};\n\nexport type BitFormProps = {\n /** Disable all child form fields */\n disabled?: boolean;\n /** Native form novalidate */\n novalidate?: boolean;\n /** Form layout orientation */\n orientation?: 'vertical' | 'horizontal';\n /** Default size for all child fields */\n size?: ComponentSize;\n /**\n * When to validate child form controls.\n * - `'submit'` (default): validate only when the form is submitted\n * - `'blur'`: validate each field as it loses focus\n * - `'change'`: validate on every value change (most immediate feedback)\n */\n validateOn?: 'submit' | 'blur' | 'change';\n /** Default variant for all child fields */\n variant?: Exclude<VisualVariant, 'glass' | 'frost' | 'text'>;\n};\n\n/**\n * `bit-form` — Native `<form>` wrapper that propagates `disabled`, `size`, and `variant`\n * context to all child `bit-*` form fields. Intercepts submit/reset events.\n *\n * @element bit-form\n *\n * @attr {boolean} disabled - Disable all child form fields\n * @attr {string} size - Default size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Default visual variant for child fields\n * @attr {string} orientation - Layout direction: 'vertical' | 'horizontal'\n * @attr {boolean} novalidate - Skip native browser validation\n *\n * @fires submit - Fired on form submit; detail contains `formData` and `originalEvent`\n * @fires reset - Fired on form reset; detail contains `originalEvent`\n *\n * @slot - Form content (bit-input, bit-select, etc.)\n *\n * @cssprop --form-gap - Spacing between child form controls\n *\n * @example\n * ```html\n * <bit-form id=\"my-form\" size=\"sm\" variant=\"flat\">\n * <bit-input name=\"email\" label=\"Email\" type=\"email\"></bit-input>\n * <bit-select name=\"role\" label=\"Role\">\n * <option value=\"admin\">Admin</option>\n * </bit-select>\n * <bit-button type=\"submit\">Submit</bit-button>\n * </bit-form>\n * ```\n */\nexport const FORM_TAG = defineComponent<BitFormProps, BitFormEvents>({\n props: {\n disabled: typed<boolean>(false),\n novalidate: typed<boolean>(false),\n orientation: typed<BitFormProps['orientation']>('vertical'),\n size: typed<BitFormProps['size']>(undefined),\n validateOn: typed<BitFormProps['validateOn']>(undefined),\n variant: typed<BitFormProps['variant']>(undefined),\n },\n setup({ emit, host, props }) {\n // Provide context to all child bit-* form fields\n provide(FORM_CTX, {\n disabled: computed(() => Boolean(props.disabled.value)),\n size: props.size,\n validateOn: computed(() => props.validateOn.value ?? 'submit'),\n variant: props.variant,\n });\n // ── Event handlers ────────────────────────────────────────────────────────\n function handleSubmit(e: Event) {\n const submitEvent = e as SubmitEvent;\n const formEl = host.shadowRoot?.querySelector('form');\n\n if (!formEl) return;\n\n e.preventDefault();\n\n const formData = new FormData(formEl);\n\n emit('submit', { formData, originalEvent: submitEvent });\n }\n function handleReset(e: Event) {\n emit('reset', { originalEvent: e });\n }\n\n return html`\n <form\n part=\"form\"\n :novalidate=\"${() => props.novalidate.value || null}\"\n :aria-disabled=\"${() => (props.disabled.value ? 'true' : null)}\"\n @submit=\"${handleSubmit}\"\n @reset=\"${handleReset}\">\n <slot></slot>\n </form>\n `;\n },\n shadow: { delegatesFocus: false },\n styles: [componentStyles],\n tag: 'bit-form',\n});\n","@layer buildit.base {\n /* ========================================\n Base Styles & Defaults\n ======================================== */\n\n :host {\n --_font-size: var(--input-font-size, var(--text-sm));\n --_gap: var(--input-gap, var(--size-2));\n --_field-height: var(--input-height, var(--size-10));\n --_padding: var(--input-padding, var(--size-1-5) var(--size-3));\n --_radius: var(--input-radius, var(--rounded-lg));\n --_placeholder: var(--input-placeholder-color, var(--color-contrast-500));\n --_bg: var(--input-bg, var(--color-contrast-100));\n --_border-color: var(--input-border-color, var(--color-contrast-300));\n\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n .input-wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--size-1-5);\n width: 100%;\n }\n\n .field {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 0;\n align-items: stretch;\n justify-content: center;\n height: var(--_field-height);\n min-height: var(--_field-height);\n padding: var(--_padding);\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--_shadow, var(--shadow-2xs));\n transition: var(\n --_motion-transition,\n background var(--transition-fast),\n backdrop-filter var(--transition-slow),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast),\n transform var(--transition-fast)\n );\n }\n\n /* Expand height to fit inset label + input row */\n .field:has(.label-inset:not([hidden])) {\n height: auto;\n }\n\n .input-row {\n display: flex;\n flex: 1;\n gap: var(--_gap);\n align-items: center;\n }\n\n /* ========================================\n Label Styles\n ======================================== */\n\n .label-inset,\n .label-outside,\n label.label-inset,\n label.label-outside {\n overflow: hidden;\n text-overflow: ellipsis;\n font-weight: var(--font-medium);\n color: var(--color-contrast-500);\n white-space: nowrap;\n cursor: pointer;\n user-select: none;\n transition: var(--_motion-transition, color var(--transition-fast));\n }\n\n .label-inset,\n label.label-inset {\n margin-bottom: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n }\n\n .label-outside,\n label.label-outside {\n font-size: var(--text-sm);\n line-height: var(--leading-none);\n }\n\n /* ========================================\n Helper Text\n ======================================== */\n\n .helper-text {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n overflow-wrap: anywhere;\n }\n\n /* ========================================\n Slotted Prefix/Suffix Icons\n ======================================== */\n\n ::slotted(svg) {\n flex-shrink: 0;\n width: var(--_icon-size, var(--leading-6));\n height: var(--_icon-size, var(--leading-6));\n }\n}\n\n@layer buildit.overrides {\n /* ========================================\n Input Element\n ======================================== */\n\n input {\n flex: 1;\n min-width: 0;\n font: inherit;\n font-size: var(--_font-size);\n line-height: var(--leading-normal);\n\n /* No all: unset needed - reset layer handles it */\n color: var(--color-contrast-900);\n outline: none;\n background: transparent;\n border: none;\n }\n\n input::placeholder {\n color: var(--_placeholder);\n transition: color var(--transition-fast);\n }\n\n input:focus-visible {\n outline: none;\n }\n\n /* ========================================\n Hover & Focus States\n ======================================== */\n\n :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n border-color: var(--color-contrast-400);\n }\n\n :host(:not([disabled], [variant='text'], [variant='flat'])) .field:focus-within {\n background: var(--color-canvas);\n border-color: var(--_theme-focus);\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n transform: translateY(-1px);\n }\n\n :host(:not([disabled])) .field:focus-within .label-inset,\n :host(:not([disabled])) .field:focus-within .label-outside {\n color: var(--_theme-focus);\n }\n\n :host(:not([disabled])) .field:focus-within ::slotted([slot='prefix']),\n :host(:not([disabled])) .field:focus-within ::slotted([slot='suffix']) {\n color: var(--_theme-focus);\n }\n\n /* ========================================\n Clear button\n ======================================== */\n\n .clear-btn {\n display: none;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-5);\n min-width: var(--_touch-target);\n height: var(--size-5);\n min-height: var(--_touch-target);\n padding: 0;\n color: var(--color-contrast-500);\n cursor: pointer;\n background: transparent;\n border: none;\n border-radius: var(--rounded-sm);\n transition: var(--_motion-transition, color var(--transition-fast));\n }\n\n .clear-btn:hover {\n color: var(--color-contrast-900);\n }\n\n .clear-btn:focus-visible {\n outline: var(--border-2) solid var(--_theme-focus);\n outline-offset: var(--border);\n }\n\n :host([clearable]) .clear-btn {\n display: flex;\n }\n\n :host([clearable]:not([has-value])) .clear-btn {\n visibility: hidden;\n pointer-events: none;\n }\n\n /* ========================================\n Password visibility toggle\n ======================================== */\n\n .pwd-toggle-btn {\n display: none;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-5);\n min-width: var(--_touch-target);\n height: var(--size-5);\n min-height: var(--_touch-target);\n padding: 0;\n color: var(--color-contrast-500);\n cursor: pointer;\n background: transparent;\n border: none;\n border-radius: var(--rounded-sm);\n transition: var(--_motion-transition, color var(--transition-fast));\n }\n\n .pwd-toggle-btn:hover {\n color: var(--color-contrast-900);\n }\n\n .pwd-toggle-btn:focus-visible {\n outline: var(--border-2) solid var(--_theme-focus);\n outline-offset: var(--border);\n }\n\n :host([type='password']) .pwd-toggle-btn {\n display: flex;\n }\n\n /* ========================================\n Character counter\n ======================================== */\n\n .char-counter {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-400);\n text-align: end;\n white-space: nowrap;\n }\n\n .char-counter[data-near-limit] {\n color: var(--color-warning, #f59e0b);\n }\n\n .char-counter[data-at-limit] {\n color: var(--color-error);\n }\n\n /* ========================================\n Error State\n ======================================== */\n\n :host([error]:not([error=''])) .field {\n border-color: var(--color-error);\n }\n\n :host([error]:not([error=''])) .field:focus-within {\n border-color: var(--color-error);\n box-shadow: var(--color-error-focus-shadow);\n }\n\n :host([error]:not([error=''])) .label-inset,\n :host([error]:not([error=''])) .label-outside {\n color: var(--color-error);\n }\n\n .helper-text[role='alert'] {\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n /* ========================================\n Visual Variants\n ======================================== */\n\n /* Solid (Default) - Standard input with background */\n :host(:not([variant])) .field,\n :host([variant='solid']) .field {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n box-shadow: var(--shadow-2xs);\n }\n\n :host(:not([variant], [disabled])) .field:focus-within,\n :host([variant='solid']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Flat - Minimal with subtle color hint */\n :host([variant='flat']) .field {\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) .field:hover {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .field:focus-within {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered - Filled with theme color */\n :host([variant='bordered']) .field {\n background: var(--_theme-backdrop);\n border-color: color-mix(in srgb, var(--_theme-focus) 70%, transparent);\n }\n\n :host([variant='bordered']) input {\n color: var(--color-contrast-900);\n }\n\n :host([variant='bordered']) input::placeholder {\n color: var(--_placeholder);\n }\n\n :host([variant='bordered']) .field:hover {\n border-color: var(--_theme-focus);\n }\n\n /* Outline - Transparent background */\n :host([variant='outline']) .field {\n background: transparent;\n box-shadow: none;\n }\n\n :host([variant='outline']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Ghost - Transparent until hover */\n :host([variant='ghost']) .field {\n background: transparent;\n border-color: transparent;\n box-shadow: none;\n }\n\n :host([variant='ghost']) .field:hover {\n background: var(--color-contrast-100);\n }\n\n :host([variant='ghost']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Text - Underline style */\n :host([variant='text']) .field {\n background: transparent;\n border: none;\n border-bottom: var(--border) solid var(--_border-color);\n border-radius: 0;\n box-shadow: none;\n }\n\n :host([variant='text']) .field:focus-within {\n border-bottom: var(--border-2) solid var(--_theme-focus);\n transform: none;\n }\n}\n\n@layer buildit.utilities {\n /* Full width */\n :host([fullwidth]) {\n width: 100%;\n }\n}\n","import { defineComponent, effect, handle, html, onMount, ref, signal } from '@vielzeug/craftit';\nimport { attr } from '@vielzeug/craftit/directives';\n\nimport type { InputType, VisualVariant } from '../../types';\nimport type { TextFieldProps } from '../shared/base-props';\n\nimport { clearIcon, eyeIcon, eyeOffIcon } from '../../icons';\nimport { disabledLoadingMixin, forcedColorsFocusMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { useTextField } from '../shared/composables';\nimport { FIELD_SIZE_PRESET } from '../shared/design-presets';\nimport { setupFieldEvents, syncCounter, syncSplitAssistive } from '../shared/dom-sync';\nimport { parsePositiveNumber } from '../shared/utils';\nimport componentStyles from './input.css?inline';\n\n/** Input component properties */\n\nexport type BitInputEvents = {\n change: { originalEvent: Event; value: string };\n input: { originalEvent: Event; value: string };\n};\n\nexport type BitInputProps = TextFieldProps<Exclude<VisualVariant, 'glass' | 'frost'>> & {\n /** Autocomplete hint */\n autocomplete?: string;\n /** Show a clear (×) button when the field has a value */\n clearable?: boolean;\n /** Virtual keyboard hint for mobile devices */\n inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';\n /** Maximum character length — shows a counter below the input */\n maxlength?: number;\n /** Minimum character length */\n minlength?: number;\n /** HTML pattern attribute for client-side validation */\n pattern?: string;\n /** HTML input type */\n type?: InputType;\n};\n\nconst VALID_INPUT_TYPES = [\n 'text',\n 'email',\n 'password',\n 'search',\n 'url',\n 'tel',\n 'number',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n] as const;\n\nconst validateInputType = (type: string | null | undefined): string => {\n return VALID_INPUT_TYPES.includes(type as (typeof VALID_INPUT_TYPES)[number]) ? type! : 'text';\n};\n\n/**\n * A customizable text input component with multiple variants, label placements, and form features.\n *\n * @element bit-input\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - Label placement: 'inset' | 'outside'\n * @attr {string} type - HTML input type: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search'\n * @attr {string} value - Current input value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {string} helper - Helper text displayed below the input\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {boolean} disabled - Disable input interaction\n * @attr {boolean} readonly - Make the input read-only\n * @attr {boolean} required - Mark the field as required\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost' | 'text'\n * @attr {string} size - Input size: 'sm' | 'md' | 'lg'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n *\n * @fires input - Emitted when input value changes (on every keystroke)\n * @fires change - Emitted when input loses focus with changed value\n *\n * @slot prefix - Content before the input (e.g., icons)\n * @slot suffix - Content after the input (e.g., clear button, validation icon)\n * @slot helper - Complex helper content below the input\n *\n * @part wrapper - The input wrapper element\n * @part label - The label element (inset or outside)\n * @part field - The field container element\n * @part input-row - The input row container element\n * @part input - The input element\n * @part helper - The helper text element\n *\n * @cssprop --input-bg - Background color\n * @cssprop --input-color - Text color\n * @cssprop --input-border-color - Border color\n * @cssprop --input-focus - Focus border color\n * @cssprop --input-placeholder-color - Placeholder text color\n * @cssprop --input-radius - Border radius\n * @cssprop --input-padding - Inner padding (vertical horizontal)\n * @cssprop --input-gap - Gap between prefix/suffix and input\n * @cssprop --input-font-size - Font size\n *\n * @example\n * ```html\n * <bit-input type=\"email\" label=\"Email\" placeholder=\"you@example.com\" />\n * <bit-input label=\"Name\" variant=\"bordered\" color=\"primary\" />\n * ```\n */\nexport const INPUT_TAG = defineComponent<BitInputProps, BitInputEvents>({\n formAssociated: true,\n props: {\n autocomplete: { default: undefined },\n clearable: { default: false },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '', omit: true },\n fullwidth: { default: false },\n helper: { default: '' },\n inputmode: { default: undefined },\n label: { default: '' },\n 'label-placement': { default: 'inset' },\n maxlength: { default: undefined },\n minlength: { default: undefined },\n name: { default: '' },\n pattern: { default: undefined },\n placeholder: { default: '' },\n readonly: { default: false },\n required: { default: false },\n rounded: { default: undefined },\n size: { default: undefined },\n type: { default: 'text' },\n value: { default: '' },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const showPassword = signal(false);\n\n const resolvedInputType = (): string =>\n props.type.value === 'password' && showPassword.value ? 'text' : validateInputType(props.type.value);\n\n const tf = useTextField(props, 'input');\n const {\n errorId,\n fieldId: inputId,\n helperId,\n labelInsetId,\n labelInsetRef,\n labelOutsideId,\n labelOutsideRef,\n valueSignal,\n } = tf;\n\n const inputRef = ref<HTMLInputElement>();\n const helperRef = ref<HTMLDivElement>();\n const errorRef = ref<HTMLDivElement>();\n const clearBtnRef = ref<HTMLButtonElement>();\n const charCounterRef = ref<HTMLDivElement>();\n\n const syncOptionalAttr = (\n inp: HTMLInputElement,\n name: 'autocomplete' | 'inputmode' | 'pattern',\n value: string | null | undefined,\n ) => {\n if (value == null || value === '') inp.removeAttribute(name);\n else inp.setAttribute(name, value);\n };\n\n onMount(() => {\n const inp = inputRef.value;\n\n if (!inp) return;\n\n setupFieldEvents(inp, {\n onBlur: () => tf.triggerValidation('blur'),\n onChange: (e, value) => {\n emit('change', { originalEvent: e, value });\n tf.triggerValidation('change');\n },\n onInput: (e, value) => emit('input', { originalEvent: e, value }),\n });\n\n tf.mountLabelSync();\n\n effect(() => {\n const maxLen = parsePositiveNumber(props.maxlength.value);\n\n if (maxLen != null) inp.maxLength = maxLen;\n else inp.removeAttribute('maxlength');\n\n const minLen = parsePositiveNumber(props.minlength.value);\n\n if (minLen != null) inp.minLength = minLen;\n else inp.removeAttribute('minlength');\n\n syncOptionalAttr(inp, 'pattern', props.pattern.value ?? null);\n syncOptionalAttr(inp, 'inputmode', props.inputmode.value ?? null);\n\n const autocomplete = props.autocomplete.value;\n\n if (autocomplete == null || autocomplete === '') inp.removeAttribute('autocomplete');\n else inp.autocomplete = autocomplete as AutoFill;\n });\n\n syncSplitAssistive({\n error: () => props.error.value,\n errorRef,\n helper: () => props.helper.value,\n helperRef,\n });\n\n syncCounter({\n count: () => valueSignal.value.length,\n format: 'split',\n maxLength: () => props.maxlength.value,\n ref: charCounterRef,\n });\n\n effect(() => {\n if (valueSignal.value) host.setAttribute('has-value', '');\n else host.removeAttribute('has-value');\n });\n\n // TODO: migrate aria() on inner elements to a future useA11yField() composable\n // For now, keep the imperative aria() call inside onMount as-is\n import('@vielzeug/craftit').then(({ aria }) => {\n aria(inp, {\n describedby: () => (props.error.value ? errorId : helperId),\n errormessage: () => (props.error.value ? errorId : null),\n invalid: () => !!props.error.value,\n });\n });\n\n if (clearBtnRef.value) {\n handle(clearBtnRef.value, 'click', (e: MouseEvent) => {\n e.preventDefault();\n valueSignal.value = '';\n emit('input', { originalEvent: e, value: '' });\n emit('change', { originalEvent: e, value: '' });\n tf.triggerValidation('change');\n inputRef.value?.focus();\n });\n }\n });\n\n return html`\n <div class=\"input-wrapper\" part=\"wrapper\">\n <label\n class=\"label-outside\"\n for=\"${inputId}\"\n id=\"${labelOutsideId}\"\n part=\"label\"\n ref=${labelOutsideRef}\n hidden></label>\n <div class=\"field\" part=\"field\">\n <label\n class=\"label-inset\"\n for=\"${inputId}\"\n id=\"${labelInsetId}\"\n part=\"label\"\n ref=${labelInsetRef}\n hidden></label>\n <div class=\"input-row\" part=\"input-row\">\n <slot name=\"prefix\"></slot>\n <input\n part=\"input\"\n id=\"${inputId}\"\n ${attr({\n disabled: props.disabled,\n name: props.name,\n placeholder: props.placeholder,\n readOnly: props.readonly,\n required: props.required,\n type: resolvedInputType,\n value: valueSignal,\n })}\n :aria-labelledby=\"${() => (props['label-placement'].value === 'outside' ? labelOutsideId : labelInsetId)}\"\n aria-describedby=\"${helperId}\"\n ref=${inputRef} />\n <slot name=\"suffix\"></slot>\n <button\n class=\"pwd-toggle-btn\"\n part=\"pwd-toggle\"\n type=\"button\"\n :aria-label=\"${() => (showPassword.value ? 'Hide password' : 'Show password')}\"\n :aria-pressed=\"${() => String(showPassword.value)}\"\n tabindex=\"-1\"\n @click=\"${() => {\n showPassword.value = !showPassword.value;\n inputRef.value?.focus();\n }}\">\n ${() => (showPassword.value ? eyeOffIcon : eyeIcon)}\n </button>\n <button class=\"clear-btn\" part=\"clear\" type=\"button\" aria-label=\"Clear\" tabindex=\"-1\" ref=${clearBtnRef}>\n ${clearIcon}\n </button>\n </div>\n </div>\n <div class=\"helper-text\" id=\"${helperId}\" part=\"helper\" ref=${helperRef} hidden></div>\n <div class=\"helper-text\" id=\"${errorId}\" role=\"alert\" part=\"error\" ref=${errorRef} hidden></div>\n <div class=\"char-counter\" part=\"char-counter\" ref=${charCounterRef} hidden></div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n sizeVariantMixin(FIELD_SIZE_PRESET),\n ...formFieldMixins,\n disabledLoadingMixin(),\n forcedColorsFocusMixin('input'),\n componentStyles,\n ],\n tag: 'bit-input',\n});\n","@layer buildit.base {\n :host {\n display: inline-flex;\n width: fit-content;\n }\n\n :host([fullwidth]) {\n width: 100%;\n }\n\n .wrapper {\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n width: 100%;\n }\n\n /* Style the inner <input> through bit-input's exported part */\n bit-input::part(input) {\n text-align: center;\n }\n\n bit-input {\n width: var(--size-20);\n }\n\n :host([fullwidth]) bit-input {\n flex: 1;\n width: auto;\n min-width: 0;\n }\n}\n","import { computed, defineComponent, defineField, html, signal, watch } from '@vielzeug/craftit';\n\nimport type { DisablableProps, SizableProps, ThemableProps, VisualVariant } from '../../types';\n\nimport { minusIcon, plusIcon } from '../../icons';\nimport { disabledStateMixin } from '../../styles';\n// Ensure child components are registered\nimport '../button/button';\nimport '../input/input';\nimport styles from './number-input.css?inline';\n\nexport type BitNumberInputEvents = {\n change: { originalEvent?: Event; value: number | null };\n input: { originalEvent?: Event; value: number | null };\n};\n\n/** Number Input props */\nexport type BitNumberInputProps = ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Stretch to full width of container */\n fullwidth?: boolean;\n /** Visible label */\n label?: string;\n /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n 'label-placement'?: 'inset' | 'outside';\n /** Large step (for Page Up/Down, default: 10 × step) */\n 'large-step'?: number;\n /** Maximum allowed value */\n max?: number;\n /** Minimum allowed value */\n min?: number;\n name?: string;\n /** Allow null/empty value */\n nullable?: boolean;\n /** Form field name */\n\n /** Placeholder text */\n placeholder?: string;\n /** Make the input read-only */\n readonly?: boolean;\n /** Step size for increment/decrement */\n step?: number;\n /** Current numeric value */\n value?: number;\n /** Visual variant */\n variant?: VisualVariant;\n };\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element bit-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires change - On committed value change. detail: { value: number | null, originalEvent?: Event }\n * @fires input - On every keystroke. detail: { value: number | null, originalEvent?: Event }\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @example\n * ```html\n * <bit-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></bit-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = defineComponent<BitNumberInputProps, BitNumberInputEvents>({\n formAssociated: true,\n props: {\n color: { default: undefined },\n disabled: { default: false },\n fullwidth: { default: false },\n label: { default: undefined },\n 'label-placement': { default: 'inset' },\n 'large-step': { default: undefined },\n max: { default: undefined },\n min: { default: undefined },\n name: { default: undefined },\n nullable: { default: false },\n placeholder: { default: undefined },\n readonly: { default: false },\n size: { default: undefined },\n step: { default: 1 },\n value: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n const inputValue = signal<string>(props.value.value != null ? String(props.value.value) : '');\n\n defineField(\n {\n disabled: computed(() => Boolean(props.disabled.value)),\n value: computed(() => (inputValue.value !== '' ? inputValue.value : null)),\n },\n {\n onReset: () => {\n inputValue.value = props.value.value != null ? String(props.value.value) : '';\n },\n },\n );\n watch(props.value, (v) => {\n const newVal = v != null ? String(v) : '';\n\n if (inputValue.value !== newVal) inputValue.value = newVal;\n });\n function clamp(n: number): number {\n const min = props.min.value;\n const max = props.max.value;\n\n if (min != null && n < Number(min)) return Number(min);\n\n if (max != null && n > Number(max)) return Number(max);\n\n return n;\n }\n function parseValue(): number | null {\n const v = inputValue.value.trim();\n\n if (!v) return null;\n\n const n = Number.parseFloat(v);\n\n return Number.isNaN(n) ? null : n;\n }\n function commit(val: number | null, originalEvent?: Event) {\n const clamped = val != null ? clamp(val) : null;\n\n inputValue.value = clamped != null ? String(clamped) : '';\n\n if (clamped != null) host.setAttribute('value', String(clamped));\n else host.removeAttribute('value');\n\n emit('change', { originalEvent, value: clamped });\n }\n function increment(delta: number, originalEvent?: Event) {\n if (props.disabled.value || props.readonly.value) return;\n\n const current = parseValue() ?? (props.min.value != null ? Number(props.min.value) : 0);\n\n commit(current + delta, originalEvent);\n }\n function handleKeydown(e: KeyboardEvent) {\n if (props.disabled.value || props.readonly.value) return;\n\n const step = Number(props.step.value) || 1;\n const largeStep = Number(props['large-step'].value) || step * 10;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n increment(-step, e);\n break;\n case 'ArrowUp':\n e.preventDefault();\n increment(step, e);\n break;\n case 'End':\n if (props.max.value != null) {\n e.preventDefault();\n commit(Number(props.max.value), e);\n }\n\n break;\n case 'Home':\n if (props.min.value != null) {\n e.preventDefault();\n commit(Number(props.min.value), e);\n }\n\n break;\n case 'PageDown':\n e.preventDefault();\n increment(-largeStep, e);\n break;\n case 'PageUp':\n e.preventDefault();\n increment(largeStep, e);\n break;\n }\n }\n\n const atMin = computed(\n () => props.min.value != null && parseValue() != null && parseValue()! <= Number(props.min.value),\n );\n const atMax = computed(\n () => props.max.value != null && parseValue() != null && parseValue()! >= Number(props.max.value),\n );\n\n return html`\n <div\n class=\"wrapper\"\n role=\"spinbutton\"\n part=\"control\"\n :aria-valuenow=\"${() => parseValue() ?? null}\"\n :aria-valuemin=\"${() => props.min.value ?? null}\"\n :aria-valuemax=\"${() => props.max.value ?? null}\"\n :aria-label=\"${() => props.label.value || null}\"\n :aria-disabled=\"${() => (props.disabled.value ? 'true' : null)}\"\n :aria-readonly=\"${() => (props.readonly.value ? 'true' : null)}\"\n @keydown=\"${handleKeydown}\">\n <bit-button\n icon-only\n type=\"button\"\n part=\"decrement-btn\"\n aria-label=\"Decrease\"\n variant=\"ghost\"\n :size=\"${() => props.size.value || null}\"\n :color=\"${() => props.color.value || null}\"\n ?disabled=\"${() => props.disabled.value || props.readonly.value || atMin.value}\"\n @click=\"${(e: Event) => increment(-(Number(props.step.value) || 1), e)}\"\n >${minusIcon}</bit-button\n >\n <bit-input\n part=\"input\"\n type=\"text\"\n inputmode=\"decimal\"\n aria-hidden=\"true\"\n :value=\"${() => inputValue.value}\"\n :label=\"${() => props.label.value || null}\"\n :label-placement=\"${() => props['label-placement'].value}\"\n :placeholder=\"${() => props.placeholder.value || null}\"\n :color=\"${() => props.color.value || null}\"\n :size=\"${() => props.size.value || null}\"\n :variant=\"${() => props.variant.value || null}\"\n ?disabled=\"${() => props.disabled.value}\"\n ?readonly=\"${() => props.readonly.value}\"\n @input=\"${(e: Event) => {\n const v = (\n e as CustomEvent<{\n value?: string;\n }>\n ).detail?.value;\n\n if (typeof v !== 'string') return;\n\n inputValue.value = v;\n\n const originalEvent = (e as CustomEvent<{ originalEvent?: Event }>).detail?.originalEvent ?? e;\n\n emit('input', { originalEvent, value: parseValue() });\n }}\"\n @change=\"${(e: Event) => {\n const v = (\n e as CustomEvent<{\n value?: string;\n }>\n ).detail?.value;\n\n if (typeof v !== 'string') return;\n\n inputValue.value = v;\n\n const originalEvent = (e as CustomEvent<{ originalEvent?: Event }>).detail?.originalEvent ?? e;\n\n commit(parseValue(), originalEvent);\n }}\"></bit-input>\n <bit-button\n icon-only\n type=\"button\"\n part=\"increment-btn\"\n aria-label=\"Increase\"\n variant=\"ghost\"\n :size=\"${() => props.size.value || null}\"\n :color=\"${() => props.color.value || null}\"\n ?disabled=\"${() => props.disabled.value || props.readonly.value || atMax.value}\"\n @click=\"${(e: Event) => increment(Number(props.step.value) || 1, e)}\"\n >${plusIcon}</bit-button\n >\n </div>\n `;\n },\n styles: [disabledStateMixin(), styles],\n tag: 'bit-number-input',\n});\n","@layer buildit.base {\n :host {\n --_cell-size: var(--otp-cell-size, var(--size-12));\n --_cell-gap: var(--otp-cell-gap, var(--size-2));\n --_cell-font-size: var(--otp-cell-font-size, var(--text-xl));\n --_cell-radius: var(--otp-cell-radius, var(--rounded-lg));\n --_cell-border: var(--otp-cell-border, var(--border));\n --_cell-border-color: var(--otp-cell-border-color, var(--color-contrast-300));\n --_cell-bg: var(--otp-cell-bg, var(--color-canvas));\n --_cell-focus-border: var(--otp-cell-focus-border, var(--_theme-base, var(--color-contrast-700)));\n\n display: inline-flex;\n flex-direction: column;\n gap: var(--size-1);\n }\n\n .otp-group {\n display: flex;\n gap: var(--_cell-gap);\n align-items: center;\n }\n\n .cell {\n box-sizing: border-box;\n display: block;\n width: var(--_cell-size);\n height: var(--_cell-size);\n padding: 0;\n font-size: var(--_cell-font-size);\n font-weight: var(--font-semibold);\n line-height: 1;\n color: var(--color-contrast-900);\n text-align: center;\n caret-color: var(--_cell-focus-border);\n background: var(--_cell-bg);\n border: var(--_cell-border) solid var(--_cell-border-color);\n border-radius: var(--_cell-radius);\n transition:\n border-color var(--transition-fast),\n box-shadow var(--transition-fast);\n }\n\n .cell::selection {\n background: var(--_theme-backdrop, var(--color-contrast-100));\n }\n\n .cell:focus {\n outline: none;\n border-color: var(--_cell-focus-border);\n box-shadow: 0 0 0 var(--border-2) color-mix(in srgb, var(--_cell-focus-border) 20%, transparent);\n }\n\n .cell:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n .separator {\n font-size: var(--_cell-font-size);\n color: var(--color-contrast-400);\n user-select: none;\n }\n}\n\n@layer buildit.variants {\n /* Solid (default) */\n :host(:not([variant])) .cell,\n :host([variant='solid']) .cell {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n box-shadow: var(--shadow-2xs);\n }\n\n /* Flat */\n :host([variant='flat']) .cell {\n background: var(--color-contrast-100);\n border-color: var(--_theme-border, var(--color-contrast-200));\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) .cell:hover:not(:disabled) {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .cell:focus {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_cell-focus-border) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered */\n :host([variant='bordered']) .cell {\n color: var(--_theme-content, var(--color-contrast-900));\n caret-color: var(--_theme-content, var(--_cell-focus-border));\n background: var(--_theme-backdrop, var(--color-contrast-50));\n border-color: color-mix(in srgb, var(--_cell-focus-border) 70%, transparent);\n }\n\n :host([variant='bordered'][color='secondary']) .cell {\n color: var(--_theme-base);\n caret-color: var(--_theme-base);\n }\n\n :host([variant='bordered']) .cell:hover:not(:disabled) {\n border-color: var(--_cell-focus-border);\n }\n\n /* Outline */\n :host([variant='outline']) .cell {\n background: transparent;\n box-shadow: none;\n }\n\n /* Ghost */\n :host([variant='ghost']) .cell {\n background: transparent;\n border-color: transparent;\n box-shadow: none;\n }\n\n :host([variant='ghost']) .cell:hover:not(:disabled) {\n background: var(--color-contrast-100);\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --_cell-size: var(--size-9);\n --_cell-font-size: var(--text-base);\n }\n\n :host([size='lg']) {\n --_cell-size: var(--size-14);\n --_cell-font-size: var(--text-2xl);\n }\n}\n","import { computed, defineComponent, html, onMount, typed } from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { colorThemeMixin, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport styles from './otp-input.css?inline';\n\nexport type BitOtpInputEvents = {\n change: { complete: boolean; originalEvent?: Event; value: string };\n complete: { originalEvent?: Event; value: string };\n};\n\n/** OTP Input props */\nexport type BitOtpInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Make inputs disabled */\n disabled?: boolean;\n /** Accessible label */\n label?: string;\n /** Number of input cells */\n length?: number;\n /** Mask input (show dots instead of characters) */\n masked?: boolean;\n /** Form field name */\n name?: string;\n /** Show a separator in the middle (e.g. \"–\") */\n separator?: string;\n /** Component size */\n size?: ComponentSize;\n /** Input type: 'numeric' (digits only) or 'alphanumeric' */\n type?: 'numeric' | 'alphanumeric';\n /** Current value */\n value?: string;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'text' | 'frost' | 'glass'>;\n};\n\n/**\n * A segmented OTP (One-Time Password) input with N individual cells.\n * Auto-advances focus on input, auto-backs on Backspace, handles paste.\n *\n * @element bit-otp-input\n *\n * @attr {number} length - Number of cells (default: 6)\n * @attr {string} type - 'numeric' (default) | 'alphanumeric'\n * @attr {string} value - Current code value\n * @attr {boolean} disabled - Disable all cells\n * @attr {boolean} masked - Show as password\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color\n * @attr {string} name - Form field name\n * @attr {string} label - Group aria-label\n * @attr {string} separator - Optional separator character shown in the middle\n *\n * @fires change - Emitted whenever a cell changes. detail: { value: string, complete: boolean, originalEvent?: Event }\n * @fires complete - Emitted when all cells are filled. detail: { value: string, originalEvent?: Event }\n *\n * @cssprop --otp-cell-size - Width and height of each cell\n * @cssprop --otp-cell-gap - Gap between cells\n * @cssprop --otp-cell-font-size - Font size inside cells\n * @cssprop --otp-cell-radius - Border radius of cells\n * @cssprop --otp-cell-border-color - Default border color\n * @cssprop --otp-cell-focus-border - Focused border color\n *\n * @example\n * ```html\n * <bit-otp-input length=\"6\" color=\"primary\"></bit-otp-input>\n * ```\n */\nexport const OTP_INPUT_TAG = defineComponent<BitOtpInputProps, BitOtpInputEvents>({\n props: {\n color: typed<BitOtpInputProps['color']>(undefined),\n disabled: typed<boolean>(false),\n label: typed<string>('One-time password'),\n length: typed<number>(6),\n masked: typed<boolean>(false),\n name: typed<string | undefined>(undefined),\n separator: typed<string | undefined>(undefined),\n size: typed<BitOtpInputProps['size']>(undefined),\n type: typed<BitOtpInputProps['type']>('numeric'),\n value: typed<string>(''),\n variant: typed<BitOtpInputProps['variant']>(undefined),\n },\n setup({ emit, host, props }) {\n const cells = computed(() => Array.from({ length: Number(props.length.value) || 6 }, (_, i) => i));\n\n function getInputs(): HTMLInputElement[] {\n return [...(host.shadowRoot?.querySelectorAll<HTMLInputElement>('input.cell') ?? [])];\n }\n function getValue(): string {\n return getInputs()\n .map((i) => i.value)\n .join('');\n }\n function isAllowed(char: string): boolean {\n if (props.type.value === 'numeric') return /^\\d$/.test(char);\n\n return /^[a-z\\d]$/i.test(char);\n }\n function handleInput(e: Event, index: number) {\n const input = e.target as HTMLInputElement;\n let val = input.value;\n\n // Keep only last character if multiple were typed somehow\n if (val.length > 1) val = val.slice(-1);\n\n // Validate character\n if (val && !isAllowed(val)) {\n input.value = '';\n\n return;\n }\n\n input.value = val;\n\n const allInputs = getInputs();\n const full = getValue();\n const complete = full.length === allInputs.length && full.split('').every(Boolean);\n\n host.setAttribute('value', full);\n emit('change', { complete, originalEvent: e, value: full });\n\n if (complete) emit('complete', { originalEvent: e, value: full });\n\n // Auto-advance\n if (val && index < allInputs.length - 1) {\n allInputs[index + 1].focus();\n allInputs[index + 1].select();\n }\n }\n function handleKeydown(e: KeyboardEvent, index: number) {\n const input = e.target as HTMLInputElement;\n const allInputs = getInputs();\n\n if (e.key === 'Backspace') {\n if (input.value) {\n input.value = '';\n } else if (index > 0) {\n allInputs[index - 1].focus();\n allInputs[index - 1].select();\n allInputs[index - 1].value = '';\n }\n\n const full = getValue();\n\n host.setAttribute('value', full);\n emit('change', { complete: false, originalEvent: e, value: full });\n e.preventDefault();\n } else if (e.key === 'ArrowLeft' && index > 0) {\n allInputs[index - 1].focus();\n e.preventDefault();\n } else if (e.key === 'ArrowRight' && index < allInputs.length - 1) {\n allInputs[index + 1].focus();\n e.preventDefault();\n } else if (e.key === 'Home') {\n allInputs[0].focus();\n e.preventDefault();\n } else if (e.key === 'End') {\n allInputs[allInputs.length - 1].focus();\n e.preventDefault();\n }\n }\n function handlePaste(e: ClipboardEvent) {\n e.preventDefault();\n\n const pasted = e.clipboardData?.getData('text') ?? '';\n const chars = pasted\n .split('')\n .filter((c) => isAllowed(c))\n .slice(0, Number(props.length.value) || 6);\n const allInputs = getInputs();\n\n chars.forEach((char, i) => {\n if (allInputs[i]) allInputs[i].value = char;\n });\n\n const full = getValue();\n const complete = full.length === allInputs.length && full.split('').every(Boolean);\n\n host.setAttribute('value', full);\n emit('change', { complete, originalEvent: e, value: full });\n\n if (complete) emit('complete', { originalEvent: e, value: full });\n\n // Focus the cell after last pasted char\n const focusIdx = Math.min(chars.length, allInputs.length - 1);\n\n allInputs[focusIdx]?.focus();\n }\n onMount(() => {\n // Populate cells from value prop on mount\n const initialVal = String(props.value.value || '');\n const allInputs = getInputs();\n\n initialVal.split('').forEach((c, i) => {\n if (allInputs[i]) allInputs[i].value = c;\n });\n });\n\n const separatorIdx = computed(() => {\n const len = Number(props.length.value) || 6;\n\n return props.separator.value != null ? Math.floor(len / 2) : -1;\n });\n\n return html`\n <div class=\"otp-group\" part=\"group\" role=\"group\" :aria-label=\"${() => props.label.value}\">\n ${() =>\n cells.value.map(\n (i) => html`\n ${() =>\n separatorIdx.value > 0 && i === separatorIdx.value\n ? html`<span class=\"separator\" aria-hidden=\"true\">${() => props.separator.value || '-'}</span>`\n : ''}\n <input\n class=\"cell\"\n part=\"cell\"\n :type=\"${() => (props.masked.value ? 'password' : 'text')}\"\n :inputmode=\"${() => (props.type.value === 'numeric' ? 'numeric' : 'text')}\"\n maxlength=\"1\"\n :autocomplete=\"${() => (i === 0 ? 'one-time-code' : 'off')}\"\n :aria-label=\"${() => `Digit ${i + 1} of ${props.length.value}`}\"\n :disabled=\"${() => props.disabled.value || null}\"\n :name=\"${() => (props.name.value ? `${props.name.value}[${i}]` : null)}\"\n @input=\"${(e: Event) => handleInput(e, i)}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, i)}\"\n @paste=\"${(e: ClipboardEvent) => (i === 0 ? handlePaste(e) : e.preventDefault())}\"\n @focus=\"${(e: FocusEvent) => (e.target as HTMLInputElement).select()}\" />\n `,\n )}\n </div>\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), forcedColorsFocusMixin('.cell'), styles],\n tag: 'bit-otp-input',\n});\n","@layer buildit.base {\n :host {\n display: block;\n }\n\n fieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: none;\n }\n\n legend {\n padding: 0;\n margin-bottom: var(--size-2);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-contrast-600);\n }\n\n legend[hidden] {\n display: none;\n }\n\n .radio-group-items {\n display: flex;\n flex-direction: var(--radio-group-direction, column);\n gap: var(--radio-group-gap, var(--size-2));\n }\n\n .helper-text {\n padding-inline: 2px;\n margin-top: var(--size-1-5);\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n .error-text {\n padding-inline: 2px;\n margin-top: var(--size-1-5);\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n :host([orientation='horizontal']) .radio-group-items {\n --radio-group-direction: row;\n\n flex-wrap: wrap;\n }\n}\n","import {\n computed,\n createContext,\n createId,\n defineComponent,\n effect,\n handle,\n html,\n inject,\n onMount,\n onSlotChange,\n provide,\n type ReadonlySignal,\n signal,\n watch,\n} from '@vielzeug/craftit';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { colorThemeMixin, disabledStateMixin, sizeVariantMixin } from '../../styles';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport { createChoiceChangeDetail, type ChoiceChangeDetail } from '../shared/utils';\nimport componentStyles from './radio-group.css?inline';\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nexport type RadioGroupContext = {\n color: ReadonlySignal<ThemeColor | undefined>;\n disabled: ReadonlySignal<boolean>;\n name: ReadonlySignal<string | undefined>;\n select: (value: string, originalEvent?: Event) => void;\n size: ReadonlySignal<ComponentSize | undefined>;\n value: ReadonlySignal<string>;\n};\n\nexport const RADIO_GROUP_CTX = createContext<RadioGroupContext>('RadioGroupContext');\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type BitRadioGroupProps = {\n /** Theme color — propagated to all child bit-radio elements */\n color?: ThemeColor;\n /** Disable all radios in the group */\n disabled?: boolean;\n /** Error message shown below the group */\n error?: string;\n /** Helper text shown below the group */\n helper?: string;\n /** Legend / label for the fieldset. Required for accessibility. */\n label?: string;\n /** Form field name — propagated to all child bit-radio elements */\n name?: string;\n /** Layout direction of the radio options */\n orientation?: 'vertical' | 'horizontal';\n /** Mark the group as required */\n required?: boolean;\n /** Size — propagated to all child bit-radio elements */\n size?: ComponentSize;\n /** Currently selected value */\n value?: string;\n};\n\nexport type BitRadioGroupEvents = {\n change: ChoiceChangeDetail;\n};\n\n/**\n * A fieldset wrapper that groups `bit-radio` elements, provides shared\n * `name`, `color`, and `size` via context, and manages roving tabindex\n * keyboard navigation.\n *\n * @element bit-radio-group\n *\n * @attr {string} label - Legend text (required for a11y)\n * @attr {string} value - Currently selected value\n * @attr {string} name - Form field name (propagated to all bit-radio children)\n * @attr {boolean} disabled - Disable all radios in the group\n * @attr {string} error - Error message\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} orientation - Layout: 'vertical' | 'horizontal'\n * @attr {boolean} required - Required field\n *\n * @fires change - Emitted when a radio is selected. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - Place `bit-radio` elements here\n */\nexport const RADIO_GROUP_TAG = defineComponent<BitRadioGroupProps, BitRadioGroupEvents>({\n props: {\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '' },\n helper: { default: '' },\n label: { default: '' },\n name: { default: '' },\n orientation: { default: 'vertical' },\n required: { default: false },\n size: { default: undefined },\n value: { default: '' },\n },\n setup({ emit, host, props }) {\n const selectedValue = signal('');\n\n watch(\n props.value,\n (v) => {\n selectedValue.value = (v as string | undefined) ?? '';\n },\n { immediate: true },\n );\n\n const getSlottedRadios = (): HTMLElement[] => Array.from(host.getElementsByTagName('bit-radio')) as HTMLElement[];\n\n const getLabelForValue = (value: string): string => {\n const radio = getSlottedRadios().find((el) => (el.getAttribute('value') ?? '') === value);\n\n return radio?.textContent?.replace(/\\s+/g, ' ').trim() || value;\n };\n\n const selectRadio = (val: string, originalEvent?: Event) => {\n selectedValue.value = val;\n\n const labels = val ? [getLabelForValue(val)] : [];\n const values = val ? [val] : [];\n\n emit('change', createChoiceChangeDetail(values, labels, originalEvent));\n };\n\n const formCtx = inject(FORM_CTX, undefined);\n\n mountFormContextSync(host, formCtx, props);\n\n provide(RADIO_GROUP_CTX, {\n color: props.color,\n disabled: computed(() => Boolean(props.disabled.value)),\n name: props.name,\n select: selectRadio,\n size: props.size,\n value: selectedValue,\n });\n\n // Sync name/color/size/disabled onto slotted bit-radio children.\n // Checked state is handled reactively inside bit-radio via group context.\n const syncChildren = () => {\n for (const radio of getSlottedRadios()) {\n const val = radio.getAttribute('value') ?? '';\n\n if (val === selectedValue.value) radio.setAttribute('checked', '');\n else radio.removeAttribute('checked');\n\n if (props.name.value) radio.setAttribute('name', props.name.value);\n\n if (props.color.value) radio.setAttribute('color', props.color.value);\n else radio.removeAttribute('color');\n\n if (props.size.value) radio.setAttribute('size', props.size.value);\n else radio.removeAttribute('size');\n\n if (props.disabled.value) radio.setAttribute('disabled', '');\n else radio.removeAttribute('disabled');\n }\n };\n\n onMount(() => {\n onSlotChange('default', syncChildren);\n // Apply group props to already-slotted radios on first mount.\n syncChildren();\n effect(syncChildren);\n\n // Roving tabindex: only the selected (or first) radio is tabbable\n effect(() => {\n const radios = getSlottedRadios();\n let hasFocusable = false;\n\n for (const radio of radios) {\n const isSelected = radio.getAttribute('value') === selectedValue.value;\n\n if (isSelected && !props.disabled.value) {\n radio.setAttribute('tabindex', '0');\n hasFocusable = true;\n } else {\n radio.setAttribute('tabindex', '-1');\n }\n }\n\n // If nothing is selected, make the first non-disabled radio tabbable\n if (!hasFocusable && radios.length > 0) {\n const first = radios.find((r) => !r.hasAttribute('disabled'));\n\n if (first) first.setAttribute('tabindex', '0');\n }\n });\n\n // Arrow-key navigation within the group\n handle(host, 'keydown', (e: KeyboardEvent) => {\n if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) return;\n\n const radios = getSlottedRadios().filter((el) => !el.hasAttribute('disabled'));\n\n if (!radios.length) return;\n\n const focused = radios.indexOf(document.activeElement as HTMLElement);\n\n if (focused === -1) return;\n\n e.preventDefault();\n\n const next =\n e.key === 'ArrowDown' || e.key === 'ArrowRight'\n ? (focused + 1) % radios.length\n : (focused - 1 + radios.length) % radios.length;\n\n radios[next].focus();\n selectRadio(radios[next].getAttribute('value') ?? '', e);\n });\n\n handle(host, 'change', (e: Event) => {\n if (e.target === host) return;\n\n e.stopPropagation();\n selectRadio((e.target as HTMLElement).getAttribute('value') ?? '', e);\n });\n });\n\n const legendId = createId('radio-group-legend');\n const errorId = `${legendId}-error`;\n const helperId = `${legendId}-helper`;\n const hasError = computed(() => Boolean(props.error.value));\n const hasHelper = computed(() => Boolean(props.helper.value) && !hasError.value);\n\n return html`\n <fieldset\n role=\"radiogroup\"\n aria-required=\"${() => String(Boolean(props.required.value))}\"\n aria-invalid=\"${() => String(hasError.value)}\"\n aria-errormessage=\"${() => (hasError.value ? errorId : null)}\"\n aria-describedby=\"${() => (hasError.value ? errorId : hasHelper.value ? helperId : null)}\">\n <legend id=\"${legendId}\" ?hidden=${() => !props.label.value}>\n ${() => props.label.value}${() => (props.required.value ? html`<span aria-hidden=\"true\"> *</span>` : '')}\n </legend>\n <div class=\"radio-group-items\" part=\"items\">\n <slot></slot>\n </div>\n <div class=\"error-text\" id=\"${errorId}\" role=\"alert\" ?hidden=${() => !hasError.value}>\n ${() => props.error.value}\n </div>\n <div class=\"helper-text\" id=\"${helperId}\" ?hidden=${() => !hasHelper.value}>${() => props.helper.value}</div>\n </fieldset>\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin(), disabledStateMixin(), componentStyles],\n tag: 'bit-radio-group',\n});\n","@layer buildit.base {\n /* ========================================\n Base Styles & Defaults\n ======================================== */\n\n :host {\n --_size: var(--radio-size, var(--size-5));\n --_font-size: var(--radio-font-size, var(--text-sm));\n --_bg: var(--radio-bg, var(--color-contrast-200));\n --_border: var(--radio-border-color, var(--color-contrast-300));\n\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--_gap, var(--size-2));\n align-items: center;\n min-height: var(--_touch-target);\n cursor: pointer;\n user-select: none;\n }\n\n .radio-wrapper {\n position: relative;\n display: block;\n flex-shrink: 0;\n width: var(--_size);\n height: var(--_size);\n }\n\n .circle {\n position: relative;\n box-sizing: border-box;\n width: var(--_size);\n height: var(--_size);\n background: var(--_bg);\n border: var(--border-2) solid var(--_border);\n border-radius: 50%;\n transition:\n background var(--transition-slower),\n border-color var(--transition-slower),\n box-shadow var(--transition-normal);\n }\n\n /* ========================================\n Focus State\n ======================================== */\n\n :host(:focus-visible) .circle {\n box-shadow: var(--_focus-shadow);\n }\n\n /* ========================================\n Inner Dot\n ======================================== */\n\n .dot {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 50%;\n height: 50%;\n background: var(--_dot-color);\n border-radius: 50%;\n opacity: 0;\n transform: translate(-50%, -50%) scale(0.5);\n transition:\n opacity var(--transition-spring),\n transform var(--transition-spring);\n }\n\n /* ========================================\n Label\n ======================================== */\n\n .label {\n font-size: var(--_font-size);\n color: var(--color-contrast);\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n width: 100%;\n padding-inline-start: calc(var(--_size) + var(--size-2));\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n .helper-text[role='alert'] {\n color: var(--color-error);\n }\n}\n\n@layer buildit.overrides {\n /* Map theme variables to radio-specific variables */\n :host {\n --_active-bg: var(--radio-checked-bg, var(--_theme-base));\n --_dot-color: var(--radio-color, var(--_theme-contrast));\n --_focus-shadow: var(--_theme-shadow);\n }\n\n /* ========================================\n Checked State\n ======================================== */\n\n :host([checked]) .circle {\n background: var(--_active-bg);\n border-color: var(--_active-bg);\n }\n\n :host([checked]) .dot {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n}\n","import { computed, defineComponent, defineField, html, inject, signal, watch } from '@vielzeug/craftit';\nimport { useA11yControl, createCheckableControl } from '@vielzeug/craftit/labs';\n\nimport type { CheckableProps, DisablableProps, SizableProps, ThemableProps } from '../../types';\n\nimport { coarsePointerMixin, formControlMixins, sizeVariantMixin } from '../../styles';\nimport { RADIO_GROUP_CTX } from '../radio-group/radio-group';\nimport { CONTROL_SIZE_PRESET } from '../shared/design-presets';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport componentStyles from './radio.css?inline';\n\n/** Radio component properties */\n\nexport type BitRadioEvents = {\n change: { checked: boolean; fieldValue: string; originalEvent?: Event; value: boolean };\n};\n\nexport type BitRadioProps = CheckableProps &\n ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Error message (marks field as invalid) */\n error?: string;\n /** Helper text displayed below the radio */\n helper?: string;\n };\n\n/**\n * A customizable radio button component for mutually exclusive selections.\n *\n * @element bit-radio\n *\n * @attr {boolean} checked - Checked state\n * @attr {boolean} disabled - Disable radio interaction\n * @attr {string} value - Field value (required for radio groups)\n * @attr {string} name - Form field name (required for radio groups)\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Radio size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the radio\n *\n * @fires change - Emitted when radio is selected. detail: { value: boolean, checked: boolean, fieldValue: string, originalEvent?: Event }\n *\n * @slot - Radio button label text\n *\n * @part radio - The radio wrapper element\n * @part circle - The visual radio circle\n * @part label - The label element\n * @part helper-text - The helper/error text element\n */\nexport const RADIO_TAG = defineComponent<BitRadioProps, BitRadioEvents>({\n formAssociated: true,\n props: {\n checked: { default: false },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '' },\n helper: { default: '' },\n name: { default: '' },\n size: { default: undefined },\n value: { default: '' },\n },\n setup({ emit, host, props, reflect }) {\n const groupCtx = inject(RADIO_GROUP_CTX, undefined);\n const formCtx = inject(FORM_CTX, undefined);\n\n const effectiveName = computed(() => groupCtx?.name.value || props.name.value || '');\n const effectiveSize = computed(() => groupCtx?.size.value ?? props.size.value);\n const effectiveColor = computed(() => groupCtx?.color.value ?? props.color.value);\n const effectiveDisabled = computed(() => Boolean(groupCtx?.disabled.value || props.disabled.value));\n\n mountFormContextSync(host, formCtx, props);\n\n // Local signal — source of truth for checked state.\n // Driven by group context when inside a radio-group, otherwise by the checked prop.\n const checkedSignal = signal(Boolean(props.checked.value));\n\n if (groupCtx) {\n watch(\n computed(() => groupCtx.value.value === props.value.value),\n (isChecked) => {\n checkedSignal.value = isChecked;\n },\n { immediate: true },\n );\n } else {\n watch(\n props.checked,\n (v) => {\n checkedSignal.value = Boolean(v);\n },\n { immediate: true },\n );\n }\n\n const control = createCheckableControl({\n checked: checkedSignal,\n disabled: props.disabled,\n onToggle: (e) => {\n emit('change', {\n checked: control.checked.value,\n fieldValue: props.value.value ?? '',\n originalEvent: e,\n value: control.checked.value,\n });\n },\n value: props.value,\n });\n\n defineField(\n {\n disabled: effectiveDisabled,\n toFormValue: (v: string | null) => v,\n value: computed(() => (checkedSignal.value ? (props.value.value ?? '') : null)),\n },\n {\n onReset: () => {\n checkedSignal.value = Boolean(props.checked.value);\n },\n },\n );\n\n const getRadioGroup = (): HTMLElement[] => {\n const radioName = effectiveName.value;\n\n if (!radioName) return [];\n\n return Array.from(document.querySelectorAll<HTMLElement>(`bit-radio[name=\"${radioName}\"]`)).filter(\n (r) => !r.hasAttribute('disabled'),\n );\n };\n\n const a11y = useA11yControl(host, {\n checked: () => (control.checked.value ? 'true' : 'false'),\n helperText: () => props.error.value || props.helper.value,\n helperTone: () => (props.error.value ? 'error' : 'default'),\n invalid: () => !!props.error.value,\n role: 'radio',\n });\n\n reflect({\n checked: () => control.checked.value,\n classMap: () => ({\n 'is-checked': control.checked.value,\n 'is-disabled': effectiveDisabled.value,\n }),\n color: () => effectiveColor.value,\n disabled: () => (effectiveDisabled.value ? true : undefined),\n name: () => effectiveName.value || undefined,\n onClick: (e: Event) => {\n if (effectiveDisabled.value) return;\n\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', e);\n } else {\n // For non-grouped radios, require a name attribute\n // (radios should be part of a group, either via radio-group or via name)\n if (!effectiveName.value) return;\n\n // Only toggle if not already checked\n // (radio buttons can only be checked, never unchecked by clicking)\n if (!control.checked.value) {\n // Uncheck all other radios with the same name\n const radioName = props.name.value;\n const allRadios = document.querySelectorAll<HTMLElement>(`bit-radio[name=\"${radioName}\"]`);\n\n allRadios.forEach((radio) => {\n if (radio !== host) {\n radio.removeAttribute('checked');\n }\n });\n\n control.toggle(e);\n }\n }\n },\n onKeydown: (e: Event) => {\n const ke = e as KeyboardEvent;\n const radios = getRadioGroup();\n\n if (radios.length === 0) return;\n\n const currentIndex = radios.indexOf(host);\n\n if (currentIndex === -1) return;\n\n if (ke.key === ' ' || ke.key === 'Enter') {\n ke.preventDefault();\n\n if (!control.checked.value) {\n if (groupCtx) {\n groupCtx.select(props.value.value ?? '', ke);\n } else {\n control.toggle(ke);\n }\n }\n } else if (ke.key === 'ArrowDown' || ke.key === 'ArrowRight') {\n ke.preventDefault();\n\n const nextIndex = (currentIndex + 1) % radios.length;\n const nextRadio = radios[nextIndex];\n\n nextRadio.focus();\n\n if (groupCtx) {\n groupCtx.select(nextRadio.getAttribute('value') ?? '');\n } else {\n // For non-grouped radios, trigger the select on the focused radio\n nextRadio.click();\n }\n } else if (ke.key === 'ArrowUp' || ke.key === 'ArrowLeft') {\n ke.preventDefault();\n\n const prevIndex = currentIndex === 0 ? radios.length - 1 : currentIndex - 1;\n const prevRadio = radios[prevIndex];\n\n prevRadio.focus();\n\n if (groupCtx) {\n groupCtx.select(prevRadio.getAttribute('value') ?? '');\n } else {\n // For non-grouped radios, trigger the select on the focused radio\n prevRadio.click();\n }\n }\n },\n size: () => effectiveSize.value,\n tabindex: () => {\n if (effectiveDisabled.value) return undefined;\n\n return control.checked.value ? 0 : -1;\n },\n });\n\n return html`\n <div class=\"radio-wrapper\" part=\"radio\">\n <div class=\"circle\" part=\"circle\">\n <div class=\"dot\" part=\"dot\"></div>\n </div>\n </div>\n <span class=\"label\" part=\"label\" data-a11y-label id=\"${a11y.labelId}\"><slot></slot></span>\n <div\n class=\"helper-text\"\n part=\"helper-text\"\n data-a11y-helper\n id=\"${a11y.helperId}\"\n aria-live=\"polite\"\n hidden></div>\n `;\n },\n styles: [...formControlMixins, coarsePointerMixin, sizeVariantMixin(CONTROL_SIZE_PRESET), componentStyles],\n tag: 'bit-radio',\n});\n","@layer buildit.base {\n :host {\n --_star-size: var(--rating-star-size, var(--size-7));\n --_color-empty: var(--rating-color-empty, var(--color-contrast-200));\n --_color-filled: var(--rating-color-filled, var(--_theme-base, var(--color-warning)));\n --_gap: var(--rating-gap, var(--size-0_5));\n\n display: inline-flex;\n align-items: center;\n }\n\n .stars {\n position: relative;\n display: flex;\n gap: var(--_gap);\n align-items: center;\n }\n\n .sparkle-layer {\n position: absolute;\n inset: 0;\n overflow: visible;\n pointer-events: none;\n }\n\n .sparkle {\n position: absolute;\n pointer-events: none;\n background: var(--_color-filled);\n border-radius: 50%;\n animation: var(--_motion-animation, sparkle-fly var(--_dur, 500ms) ease-out forwards);\n }\n\n @keyframes sparkle-fly {\n from {\n opacity: 0.9;\n transform: translate(-50%, -50%) rotate(var(--_angle)) translateY(0) scale(1);\n }\n\n to {\n opacity: 0;\n transform: translate(-50%, -50%) rotate(var(--_angle)) translateY(calc(-1 * var(--_dist))) scale(0);\n }\n }\n\n .star-btn {\n all: unset;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--_star-size);\n min-width: var(--_touch-target);\n height: var(--_star-size);\n min-height: var(--_touch-target);\n color: var(--_color-empty);\n cursor: pointer;\n border-radius: var(--rounded-sm);\n transition:\n color var(--transition-fast),\n transform var(--transition-fast);\n }\n\n .star-btn[data-filled] {\n color: var(--_color-filled);\n }\n\n .star-btn:hover:not([disabled]),\n .star-btn:focus-visible:not([disabled]) {\n transform: scale(1.15);\n }\n\n .star-btn:focus-visible {\n outline: var(--border-2) solid var(--_color-filled);\n outline-offset: var(--border-2);\n }\n\n .star-btn[disabled] {\n cursor: default;\n }\n\n :host([readonly]) .star-btn,\n :host([disabled]) .star-btn {\n pointer-events: none;\n }\n\n :host([disabled]) {\n opacity: 0.5;\n }\n\n svg {\n width: 100%;\n height: 100%;\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) {\n --_star-size: var(--size-5);\n }\n\n :host([size='lg']) {\n --_star-size: var(--size-9);\n }\n\n @media (forced-colors: active) {\n /* Distinguish filled vs unfilled stars with system button colors */\n .star-btn {\n color: ButtonText;\n }\n\n .star-btn[data-filled] {\n color: Highlight;\n forced-color-adjust: none;\n }\n\n .star-btn:focus-visible {\n outline: 2px solid Highlight;\n box-shadow: none;\n }\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sparkle {\n display: none;\n }\n}\n","import { computed, defineComponent, typed, defineField, html, inject, signal } from '@vielzeug/craftit';\n\nimport type { DisablableProps, SizableProps, ThemableProps } from '../../types';\n\nimport { coarsePointerMixin, colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport { createFieldValidation } from '../shared/validation';\nimport styles from './rating.css?inline';\n\nconst FULL_STAR_PATH = 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z';\n\nexport type BitRatingEvents = {\n change: { originalEvent?: Event; value: number };\n};\n\n/** Rating props */\nexport type BitRatingProps = ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Accessible group label */\n label?: string;\n /** Maximum rating (number of stars) */\n max?: number;\n /** Form field name */\n name?: string;\n /** Make rating read-only */\n readonly?: boolean;\n /** Current rating value */\n value?: number;\n };\n\n/**\n * A star rating input.\n *\n * @element bit-rating\n *\n * @attr {number} value - Current rating value (default: 0)\n * @attr {number} max - Maximum number of stars (default: 5)\n * @attr {boolean} readonly - Read-only display mode\n * @attr {boolean} disabled - Disabled state\n * @attr {string} label - aria-label for the group (default: 'Rating')\n * @attr {string} color - Theme color for filled stars\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} name - Form field name\n *\n * @fires change - Emitted when value changes. detail: { value: number, originalEvent?: Event }\n *\n * @cssprop --rating-star-size - Star diameter\n * @cssprop --rating-color-empty - Empty star color\n * @cssprop --rating-color-filled - Filled star color\n * @cssprop --rating-gap - Gap between stars\n *\n * @example\n * ```html\n * <bit-rating value=\"3\" max=\"5\" color=\"warning\"></bit-rating>\n * ```\n */\nexport const RATING_TAG = defineComponent<BitRatingProps, BitRatingEvents>({\n formAssociated: true,\n props: {\n color: typed<BitRatingProps['color']>(undefined),\n disabled: typed<boolean>(false),\n label: typed<string>('Rating'),\n max: typed<number>(5),\n name: typed<string | undefined>(undefined),\n readonly: typed<boolean>(false),\n size: typed<BitRatingProps['size']>(undefined),\n value: typed<number>(0),\n },\n setup({ emit, host, props }) {\n const formCtx = inject(FORM_CTX, undefined);\n\n mountFormContextSync(host, formCtx, props);\n\n const normalizedValue = computed(() => {\n const max = Math.max(1, Number(props.max.value) || 5);\n const raw = Number(props.value.value);\n const safe = Number.isFinite(raw) ? raw : 0;\n\n return Math.min(max, Math.max(0, safe));\n });\n\n const fd = defineField(\n {\n disabled: computed(() => Boolean(props.disabled.value)),\n value: computed(() => String(normalizedValue.value || 0)),\n },\n {\n onReset: () => {\n host.removeAttribute('value');\n },\n },\n );\n\n const { triggerValidation } = createFieldValidation(formCtx, fd);\n\n const hovered = signal<number | null>(null);\n const displayValue = computed(() => hovered.value ?? normalizedValue.value);\n\n function spawnSparkles(star: number) {\n const layer = host.shadowRoot?.querySelector<HTMLElement>('.sparkle-layer');\n const btn = host.shadowRoot?.querySelector<HTMLElement>(`[data-star=\"${star}\"]`);\n\n if (!layer || !btn) return;\n\n const cx = btn.offsetLeft + btn.offsetWidth / 2;\n const cy = btn.offsetTop + btn.offsetHeight / 2;\n const count = 10;\n\n for (let i = 0; i < count; i++) {\n const p = document.createElement('span');\n const angle = (360 / count) * i + (Math.random() * 30 - 15);\n const dist = 18 + Math.random() * 20;\n const size = 3 + Math.random() * 4;\n const dur = 380 + Math.random() * 220;\n\n p.className = 'sparkle';\n p.style.cssText = [\n `left:${cx}px`,\n `top:${cy}px`,\n `--_angle:${angle}deg`,\n `--_dist:${dist}px`,\n `width:${size}px`,\n `height:${size}px`,\n `--_dur:${dur}ms`,\n `animation-delay:${Math.random() * 60}ms`,\n ].join(';');\n layer.appendChild(p);\n p.addEventListener('animationend', () => p.remove(), { once: true });\n }\n }\n function select(star: number, originalEvent?: Event) {\n if (props.readonly.value || props.disabled.value) return;\n\n const max = Math.max(1, Number(props.max.value) || 5);\n const nextValue = Math.min(max, Math.max(0, star));\n\n if (nextValue === normalizedValue.value) return;\n\n // Write through the reactive prop signal; craftit handles host reflection.\n props.value.value = nextValue;\n emit('change', { originalEvent, value: nextValue });\n triggerValidation('change');\n spawnSparkles(nextValue);\n }\n function handleKeydown(e: KeyboardEvent, star: number) {\n const max = Number(props.max.value) || 5;\n\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault();\n select(Math.min(max, star + 1), e);\n\n const nextBtn = host.shadowRoot?.querySelector<HTMLButtonElement>(`[data-star=\"${Math.min(max, star + 1)}\"]`);\n\n nextBtn?.focus();\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault();\n select(Math.max(1, star - 1), e);\n\n const prevBtn = host.shadowRoot?.querySelector<HTMLButtonElement>(`[data-star=\"${Math.max(1, star - 1)}\"]`);\n\n prevBtn?.focus();\n }\n }\n\n const stars = computed(() => {\n const max = Number(props.max.value) || 5;\n\n return Array.from({ length: max }, (_, i) => i + 1);\n });\n\n return html`\n <div\n class=\"stars\"\n part=\"stars\"\n role=\"radiogroup\"\n :aria-label=\"${() => props.label.value}\"\n :aria-required=\"${() => null}\">\n ${() =>\n stars.value.map(\n (star) =>\n html`<button\n class=\"star-btn\"\n part=\"star\"\n type=\"button\"\n role=\"radio\"\n :aria-label=\"${() => `${star} ${star === 1 ? 'star' : 'stars'}`}\"\n :aria-checked=\"${() => String(star === normalizedValue.value)}\"\n :data-star=\"${star}\"\n ?data-filled=\"${() => star <= displayValue.value}\"\n :disabled=\"${() => props.disabled.value || props.readonly.value || null}\"\n @click=\"${(e: Event) => select(star, e)}\"\n @pointerenter=\"${() => {\n if (!props.readonly.value && !props.disabled.value) hovered.value = star;\n }}\"\n @pointerleave=\"${() => {\n hovered.value = null;\n }}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, star)}\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n fill=\"${() => (star <= displayValue.value ? 'currentColor' : 'none')}\"\n stroke=\"currentColor\"\n stroke-width=\"${() => (star <= displayValue.value ? 0 : 1.5)}\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\">\n <path d=\"${FULL_STAR_PATH}\" />\n </svg>\n </button>`,\n )}\n <div class=\"sparkle-layer\"></div>\n </div>\n `;\n },\n styles: [colorThemeMixin, sizeVariantMixin({}), coarsePointerMixin, reducedMotionMixin, styles],\n tag: 'bit-rating',\n});\n","@layer buildit.base {\n :host {\n --_font-size: var(--select-font-size, var(--text-sm));\n --_gap: var(--select-gap, var(--size-2));\n --_field-height: var(--select-height, var(--size-10));\n --_row-min-height: calc(var(--leading-normal) * var(--_font-size) + 2px);\n --_padding: var(--select-padding, var(--size-1-5) var(--size-3));\n --_radius: var(--select-radius, var(--rounded-lg));\n --_placeholder: var(--select-placeholder-color, var(--color-contrast-500));\n --_bg: var(--select-bg, var(--color-contrast-100));\n --_border-color: var(--select-border-color, var(--color-contrast-300));\n\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n min-width: 12rem;\n }\n\n :host([fullwidth]) {\n width: 100%;\n }\n\n /* Hide native <option> elements — we render our own UI */\n ::slotted(option),\n ::slotted(optgroup) {\n display: none;\n }\n\n .select-wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--size-1-5);\n width: 100%;\n }\n\n /* ========================================\n Trigger Field\n ======================================== */\n\n .field {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n height: var(--_field-height);\n min-height: max(var(--_field-height), var(--_touch-target, 0px));\n padding: var(--_padding);\n padding-inline-end: var(--size-8);\n text-align: start;\n cursor: pointer;\n user-select: none;\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-2xs);\n transition: var(\n --_motion-transition,\n background var(--transition-fast),\n backdrop-filter var(--transition-slow),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast),\n transform var(--transition-fast)\n );\n }\n\n .field:focus {\n outline: none;\n }\n\n /* Expand height for multi-select chips or inset label */\n :host([multiple]) .field,\n .field:has(.label-inset:not([hidden])) {\n height: auto;\n }\n\n .label-inset {\n margin-bottom: 2px;\n font-size: var(--text-xs);\n font-weight: var(--font-medium);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n cursor: pointer;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n .label-outside {\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n line-height: var(--leading-none);\n color: var(--color-contrast-500);\n cursor: pointer;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n .trigger-row {\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: var(--_gap);\n align-items: center;\n max-width: calc(100% - var(--size-10));\n min-height: var(--_row-min-height);\n }\n\n .chips-row {\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: var(--size-1);\n align-items: center;\n min-width: 0;\n }\n\n .chips-row[hidden],\n .trigger-value[hidden] {\n display: none;\n }\n\n .trigger-value {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--_font-size);\n line-height: 1;\n color: var(--color-contrast-900);\n white-space: nowrap;\n transition: color var(--transition-fast);\n }\n\n .trigger-placeholder {\n color: var(--_placeholder);\n transition: color var(--transition-fast);\n }\n\n .trigger-icon {\n position: absolute;\n inset-inline-end: var(--size-2);\n top: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--size-6);\n height: 100%;\n color: var(--color-contrast-500);\n transition: transform var(--transition-fast);\n }\n\n :host([open]) .trigger-icon {\n transform: rotate(180deg);\n }\n\n .loader {\n display: none;\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n border: 2px solid currentcolor;\n border-inline-end-color: transparent;\n border-radius: 50%;\n animation: var(--_motion-animation, bit-select-spin 0.6s linear infinite);\n }\n\n :host([loading]) .loader {\n display: inline-block;\n }\n\n :host([loading]) .trigger-icon svg {\n display: none;\n }\n\n @keyframes bit-select-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n /* ========================================\n Dropdown Listbox\n ======================================== */\n\n .dropdown {\n position: fixed;\n z-index: var(--z-dropdown, 8000);\n box-sizing: border-box;\n display: flex;\n visibility: hidden;\n flex-direction: column;\n gap: var(--size-0-5);\n max-height: 260px;\n padding: var(--size-1);\n overflow-y: auto;\n overscroll-behavior: contain;\n text-align: start;\n pointer-events: none;\n background: var(--color-canvas);\n border: var(--border) solid var(--color-contrast-200);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-lg);\n\n /* Hidden by default */\n opacity: 0;\n transform: translateY(-4px);\n transition: var(\n --_motion-transition,\n opacity var(--transition-fast),\n transform var(--transition-fast),\n visibility var(--transition-fast)\n );\n }\n\n .dropdown[data-open] {\n visibility: visible;\n pointer-events: auto;\n opacity: 1;\n transform: translateY(0);\n }\n\n .options-list {\n display: flex;\n flex-direction: column;\n gap: 0;\n }\n\n /* ========================================\n Option Items\n ======================================== */\n\n .option {\n display: flex;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-1-5) var(--size-2-5);\n font-size: var(--_font-size);\n line-height: var(--leading-normal);\n cursor: pointer;\n border-radius: var(--rounded-sm);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n }\n\n /* Truncate long labels to keep option rows compact and readable. */\n .option > span:first-child {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .option:hover:not([data-disabled]) {\n background: var(--color-contrast-100);\n }\n\n .option[data-focused]:not([data-disabled]) {\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-base) 12%, var(--color-contrast-100));\n }\n\n .option[data-selected] {\n font-weight: var(--font-medium);\n color: var(--_theme-base);\n background: color-mix(in srgb, var(--_theme-base) 10%, var(--color-contrast-50));\n }\n\n .option[data-selected][data-focused] {\n background: color-mix(in srgb, var(--_theme-base) 20%, var(--color-contrast-100));\n }\n\n .option[data-disabled] {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .option-check {\n display: inline-flex;\n flex-shrink: 0;\n margin-inline-start: auto;\n color: var(--_theme-base);\n opacity: 0;\n transition: opacity var(--transition-fast);\n }\n\n .option[data-selected] .option-check {\n opacity: 1;\n }\n\n /* ========================================\n Option Groups\n ======================================== */\n\n .optgroup-label {\n padding: var(--size-1-5) var(--size-2-5) var(--size-1);\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: var(--tracking-wide, 0.05em);\n }\n\n /* ========================================\n Loading / No-Results\n ======================================== */\n\n .dropdown-loading,\n .dropdown-empty {\n padding: var(--size-3) var(--size-2-5);\n font-size: var(--_font-size);\n color: var(--color-contrast-500);\n text-align: center;\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n /* ========================================\n States\n ======================================== */\n\n :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n border-color: var(--color-contrast-400);\n }\n\n :host(:not([disabled], [variant='flat'])) .field:focus-within,\n :host([open]:not([disabled], [variant='flat'])) .field {\n background: var(--color-canvas);\n border-color: var(--_theme-focus);\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n transform: translateY(-1px);\n }\n\n :host(:not([disabled])) .field:focus-within .label-inset,\n :host(:not([disabled])) .field:focus-within .label-outside,\n :host([open]:not([disabled])) .label-inset {\n color: var(--_theme-focus);\n }\n\n /* ========================================\n Error State\n ======================================== */\n\n :host([has-error]) .field {\n border-color: var(--color-error);\n }\n\n :host([has-error]) .field:focus-within {\n border-color: var(--color-error);\n box-shadow: var(--color-error-focus-shadow);\n }\n\n :host([has-error]) .label-inset,\n :host([has-error]) .label-outside {\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n /* ========================================\n Visual Variants\n ======================================== */\n\n /* Solid (Default) - Standard select with background */\n :host(:not([variant])) .field,\n :host([variant='solid']) .field {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n box-shadow: var(--shadow-2xs);\n }\n\n :host(:not([variant], [disabled])) .field:focus-within,\n :host([variant='solid']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Flat - Minimal with subtle color hint */\n :host([variant='flat']) .field {\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) .field:hover {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .field:focus-within {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered - Filled with theme color */\n :host([variant='bordered']) .field {\n background: var(--_theme-backdrop);\n border-color: color-mix(in srgb, var(--_theme-focus) 70%, transparent);\n }\n\n :host([variant='bordered']) .trigger-value {\n color: var(--color-contrast-900);\n }\n\n :host([variant='bordered']) .trigger-placeholder {\n color: var(--_placeholder);\n }\n\n :host([variant='bordered']) .field:hover {\n border-color: var(--_theme-focus);\n }\n\n /* Outline - Transparent background */\n :host([variant='outline']) .field {\n background: transparent;\n box-shadow: none;\n }\n\n :host([variant='outline']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Ghost - Transparent until hover */\n :host([variant='ghost']) .field {\n background: transparent;\n border-color: transparent;\n box-shadow: none;\n }\n\n :host([variant='ghost']) .field:hover {\n background: var(--color-contrast-100);\n }\n\n :host([variant='ghost']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n}\n\n@layer buildit.utilities {\n :host([fullwidth]) {\n display: flex;\n width: 100%;\n }\n}\n","import {\n aria,\n computed,\n createFormIds,\n defineComponent,\n defineField,\n effect,\n html,\n inject,\n onMount,\n onSlotChange,\n ref,\n signal,\n typed,\n watch,\n} from '@vielzeug/craftit';\nimport { createListNavigation, createOverlayControl } from '@vielzeug/craftit/labs';\n\nimport type { VisualVariant } from '../../types';\n\nimport '../../feedback/chip/chip';\nimport type { SelectableFieldProps } from '../shared/base-props';\n\nimport { checkIcon, chevronDownIcon } from '../../icons';\nimport { disabledLoadingMixin, forcedColorsFocusMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { FIELD_SIZE_PRESET } from '../shared/design-presets';\nimport { createDropdownPositioner, mountLabelSyncStandalone } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport {\n type ChoiceChangeDetail,\n computeControlledCsvState,\n createChoiceChangeDetail,\n resolveMergedAssistiveText,\n} from '../shared/utils';\nimport { createFieldValidation } from '../shared/validation';\nimport componentStyles from './select.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\ntype OptionItem = {\n disabled: boolean;\n group?: string;\n label: string;\n value: string;\n};\n\ntype FlatRow =\n | {\n idx: number;\n opt: OptionItem;\n type: 'option';\n }\n | {\n label: string;\n type: 'group';\n };\n\n// ============================================\n// Styles\n// ============================================\n\n// ============================================\n// Component Props\n// ============================================\n\n/** Select component properties */\n\nexport type BitSelectEvents = {\n change: ChoiceChangeDetail;\n};\n\nexport type BitSelectProps = SelectableFieldProps<Exclude<VisualVariant, 'glass' | 'text' | 'frost'>> & {\n /** Show loading state in dropdown */\n loading?: boolean;\n /** Allow selecting multiple options */\n multiple?: boolean;\n /** JS options array (alternative to slotted <option> elements) */\n options?: OptionItem[];\n /** Mark the field as required */\n required?: boolean;\n};\n\n/**\n * A fully custom form-associated select dropdown with keyboard navigation and ARIA support.\n * Reads `<option>` and `<optgroup>` children from the default slot.\n *\n * @element bit-select\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current selected value(s) (comma-separated for multiple)\n * @attr {string} placeholder - Placeholder when no option selected\n * @attr {string} name - Form field name\n * @attr {boolean} multiple - Enable multi-select\n * @attr {boolean} disabled - Disable the select\n * @attr {boolean} required - Required field\n * @attr {string} helper - Helper text below the select\n * @attr {string} error - Error message\n * @attr {string} color - Theme color\n * @attr {string} variant - Visual variant\n * @attr {string} size - Component size\n * @attr {string} rounded - Border radius\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @fires change - Fired when selection changes. detail: { value: string, values: string[], labels: string[], originalEvent?: Event }\n *\n * @slot - `<option>` and `<optgroup>` elements\n *\n * @cssprop --select-bg - Background\n * @cssprop --select-border-color - Border color\n * @cssprop --select-radius - Border radius\n * @cssprop --select-padding - Padding\n * @cssprop --select-font-size - Font size\n * @cssprop --select-placeholder-color - Placeholder text color\n *\n * @example\n * ```html\n * <bit-select label=\"Role\" value=\"admin\">\n * <option value=\"admin\">Administrator</option>\n * <option value=\"editor\">Editor</option>\n * <option value=\"viewer\">Viewer</option>\n * </bit-select>\n *\n * <bit-select label=\"Tags\" multiple color=\"primary\">\n * <optgroup label=\"Frontend\">\n * <option value=\"react\">React</option>\n * <option value=\"vue\">Vue</option>\n * </optgroup>\n * <optgroup label=\"Backend\">\n * <option value=\"node\">Node.js</option>\n * </optgroup>\n * </bit-select>\n * ```\n */\nexport const SELECT_TAG = defineComponent<BitSelectProps, BitSelectEvents>({\n formAssociated: true,\n props: {\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '', omit: true },\n fullwidth: { default: false },\n helper: { default: '' },\n label: { default: '' },\n 'label-placement': { default: 'inset' },\n loading: { default: false },\n multiple: { default: false },\n name: { default: '' },\n options: typed<OptionItem[] | undefined>(undefined, { reflect: false }),\n placeholder: { default: '' },\n required: { default: false },\n rounded: { default: undefined },\n size: { default: undefined },\n value: { default: '' },\n variant: { default: undefined },\n },\n setup({ emit, host, props }) {\n // ============================================\n // State\n // ============================================\n const selectedValues = signal<string[]>([]);\n const slottedOptions = signal<OptionItem[]>([]);\n const isOpen = signal(false);\n const focusedIndex = signal(-1);\n const isLoading = computed(() => Boolean(props.loading.value));\n // Merged options: explicit prop value overrides slotted options.\n const options = computed(() => {\n const propOptions = props.options.value;\n\n return propOptions !== undefined ? propOptions : slottedOptions.value;\n });\n const formCtx = inject(FORM_CTX, undefined);\n // Form-associated value (comma-separated for multiple)\n const formValue = computed(() => selectedValues.value.join(','));\n const fd = defineField(\n { disabled: computed(() => Boolean(props.disabled.value) || Boolean(formCtx?.disabled.value)), value: formValue },\n {\n onReset: () => {\n selectedValues.value = [];\n },\n },\n );\n\n const { triggerValidation } = createFieldValidation(formCtx, fd);\n\n // Sync host attributes from component state for CSS hooks.\n watch(\n isOpen,\n (value) => {\n host.toggleAttribute('open', ((value) => Boolean(value))(value));\n },\n { immediate: true },\n );\n watch(\n props.error,\n (value) => {\n host.toggleAttribute('has-error', ((value) => Boolean(value))(value));\n },\n { immediate: true },\n );\n\n // Accessibility IDs\n const { fieldId: selectId, labelId } = createFormIds('select', props.name.value);\n const listboxId = `listbox-${selectId}`;\n // DOM refs\n let triggerEl: HTMLElement | null = null;\n let dropdownEl: HTMLElement | null = null;\n // Refs for dynamic content\n const labelOutsideRef = ref<HTMLSpanElement>();\n const labelInsetRef = ref<HTMLSpanElement>();\n\n // ============================================\n // Option reading from slot\n // ============================================\n function readOptions() {\n const slot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot');\n\n if (!slot) return;\n\n const assigned = slot.assignedElements({ flatten: true });\n const items: OptionItem[] = [];\n\n for (const el of assigned) {\n if (el.tagName === 'OPTION') {\n const opt = el as HTMLOptionElement;\n\n items.push({ disabled: opt.disabled, label: opt.text || opt.value, value: opt.value });\n } else if (el.tagName === 'OPTGROUP') {\n const group = el as HTMLOptGroupElement;\n const groupLabel = group.label;\n\n for (const child of Array.from(group.querySelectorAll('option'))) {\n const opt = child as HTMLOptionElement;\n\n items.push({ disabled: opt.disabled, group: groupLabel, label: opt.text || opt.value, value: opt.value });\n }\n }\n }\n slottedOptions.value = items;\n }\n // Initialize selectedValues from prop\n effect(() => {\n selectedValues.value = computeControlledCsvState(props.value.value).values;\n });\n\n // ============================================\n // Display value\n // ============================================\n const displayLabel = computed(() => {\n if (selectedValues.value.length === 0) return '';\n\n if (props.multiple.value && selectedValues.value.length > 1) {\n return `${selectedValues.value.length} selected`;\n }\n\n const first = selectedValues.value[0];\n\n return options.value.find((o) => o.value === first)?.label ?? first;\n });\n const selectedChipItems = computed(() => {\n if (!props.multiple.value) return [];\n\n return selectedValues.value.map((value) => ({\n label: options.value.find((o) => o.value === value)?.label ?? value,\n value,\n }));\n });\n const assistiveText = computed(() => resolveMergedAssistiveText(props.error.value, props.helper.value));\n const showChips = computed(() => props.multiple.value && selectedValues.value.length > 0);\n const triggerText = computed(() => displayLabel.value || props.placeholder.value || '');\n const hasLabel = computed(() => !!props.label.value);\n\n function buildFlatList(opts: OptionItem[]): FlatRow[] {\n const flat: FlatRow[] = [];\n const groups = new Map<string | undefined, OptionItem[]>();\n\n for (const opt of opts) {\n const key = opt.group;\n\n if (!groups.has(key)) groups.set(key, []);\n\n groups.get(key)!.push(opt);\n }\n\n let globalIdx = 0;\n\n for (const [groupLabel, groupOpts] of groups) {\n if (groupLabel !== undefined) flat.push({ label: groupLabel, type: 'group' });\n\n for (const opt of groupOpts) flat.push({ idx: globalIdx++, opt, type: 'option' });\n }\n\n return flat;\n }\n\n const flatRows = computed(() => buildFlatList(options.value));\n\n function getLabelForValue(value: string): string {\n return options.value.find((option) => option.value === value)?.label ?? value;\n }\n\n function emitChange(originalEvent?: Event): void {\n const values = selectedValues.value;\n const labels = values.map((value) => getLabelForValue(value));\n\n emit('change', createChoiceChangeDetail(values, labels, originalEvent));\n }\n\n function removeChip(event: Event): void {\n event.stopPropagation();\n\n const value = (event as CustomEvent<{ value?: string }>).detail?.value;\n\n if (value === undefined) return;\n\n selectedValues.value = selectedValues.value.filter((v) => v !== value);\n emitChange(event);\n triggerValidation('change');\n }\n\n // ============================================\n // Dropdown positioning (shared positioner)\n // ============================================\n const positioner = createDropdownPositioner(\n () => triggerEl,\n () => dropdownEl,\n );\n\n const listNavigation = createListNavigation<OptionItem>({\n getIndex: () => focusedIndex.value,\n getItems: () => options.value,\n isItemDisabled: (option) => option.disabled,\n setIndex: (index) => {\n focusedIndex.value = index;\n scrollFocusedIntoView();\n },\n });\n\n const overlay = createOverlayControl({\n getBoundaryElement: () => host,\n getPanelElement: () => dropdownEl,\n getTriggerElement: () => triggerEl,\n isDisabled: () => Boolean(props.disabled.value),\n isOpen: () => isOpen.value,\n positioner: {\n floating: () => dropdownEl,\n reference: () => triggerEl,\n update: () => positioner.updatePosition(),\n },\n setOpen: (next) => {\n isOpen.value = next;\n\n if (!next) listNavigation.reset();\n },\n });\n\n // ============================================\n // Open / Close\n // ============================================\n function open() {\n overlay.open();\n\n requestAnimationFrame(() => {\n const selectedIndex =\n selectedValues.value.length > 0\n ? options.value.findIndex((option) => option.value === selectedValues.value[0])\n : 0;\n\n listNavigation.set(selectedIndex >= 0 ? selectedIndex : 0);\n });\n }\n\n function close(reason: 'escape' | 'programmatic' = 'programmatic') {\n overlay.close({ reason });\n triggerValidation('blur');\n }\n // ============================================\n // Selection\n // ============================================\n function selectOption(opt: OptionItem, e?: Event) {\n if (opt.disabled) return;\n\n if (props.multiple.value) {\n selectedValues.value = selectedValues.value.includes(opt.value)\n ? selectedValues.value.filter((entry) => entry !== opt.value)\n : [...selectedValues.value, opt.value];\n } else {\n selectedValues.value = [opt.value];\n close();\n }\n\n emitChange(e);\n triggerValidation('change');\n }\n // ============================================\n // Keyboard navigation\n // ============================================\n function scrollFocusedIntoView() {\n const idx = focusedIndex.value;\n\n if (idx >= 0) {\n const focusedOptionEl = dropdownEl?.querySelector<HTMLElement>(`#${selectId}-opt-${idx}`);\n\n focusedOptionEl?.scrollIntoView({ block: 'nearest' });\n\n return;\n }\n\n if (!dropdownEl) return;\n\n const focusedEl = dropdownEl.querySelector<HTMLElement>('[data-focused]');\n\n focusedEl?.scrollIntoView({ block: 'nearest' });\n }\n function handleTriggerKeydown(e: KeyboardEvent) {\n if (props.disabled.value) return;\n\n const opts = options.value;\n\n switch (e.key) {\n case ' ':\n case 'Enter':\n e.preventDefault();\n\n if (isOpen.value) {\n const idx = focusedIndex.value;\n\n if (idx >= 0 && idx < opts.length) selectOption(opts[idx], e);\n } else {\n open();\n }\n\n break;\n case 'ArrowDown':\n e.preventDefault();\n\n if (!isOpen.value) {\n open();\n } else {\n listNavigation.next();\n }\n\n break;\n case 'ArrowUp':\n e.preventDefault();\n\n if (!isOpen.value) {\n open();\n } else {\n listNavigation.prev();\n }\n\n break;\n case 'End':\n if (isOpen.value) {\n e.preventDefault();\n listNavigation.last();\n }\n\n break;\n case 'Escape':\n e.preventDefault();\n close('escape');\n break;\n case 'Home':\n if (isOpen.value) {\n e.preventDefault();\n listNavigation.first();\n }\n\n break;\n case 'Tab':\n close();\n break;\n }\n }\n onMount(() => {\n onSlotChange('default', readOptions);\n // Ensure initial light-DOM <option>/<optgroup> content is available immediately.\n readOptions();\n mountLabelSyncStandalone(labelInsetRef, labelOutsideRef, props);\n\n if (triggerEl) {\n aria(triggerEl, {\n activedescendant: () => (focusedIndex.value >= 0 ? `${selectId}-opt-${focusedIndex.value}` : null),\n disabled: () => props.disabled.value,\n expanded: () => (isOpen.value ? 'true' : 'false'),\n invalid: () => !!props.error.value,\n labelledby: () => (hasLabel.value ? labelId : null),\n });\n }\n\n const removeOutsideClick = overlay.bindOutsideClick(document);\n\n return () => {\n positioner.destroy();\n removeOutsideClick();\n };\n });\n\n return html`<slot style=\"display:none\"></slot>\n <div class=\"select-wrapper\">\n <label class=\"label-outside\" id=\"${labelId}\" ref=${labelOutsideRef} hidden></label>\n <div\n class=\"field\"\n ref=${(el: HTMLElement) => {\n triggerEl = el;\n }}\n role=\"combobox\"\n tabindex=${() => (props.disabled.value ? '-1' : '0')}\n aria-controls=\"${listboxId}\"\n aria-expanded=\"false\"\n aria-labelledby=\"${labelId}\"\n @click=${(e: MouseEvent) => {\n e.stopPropagation();\n\n if (isOpen.value) close();\n else open();\n }}\n @keydown=${handleTriggerKeydown}>\n <label class=\"label-inset\" id=\"${labelId}\" ref=${labelInsetRef} hidden></label>\n <div class=\"trigger-row\">\n <div class=\"chips-row\" ?hidden=${() => !showChips.value}>\n ${() =>\n selectedChipItems.value.map(\n (item) => html`\n <bit-chip\n value=${item.value}\n aria-label=${item.label}\n mode=\"removable\"\n variant=\"flat\"\n size=\"sm\"\n color=${() => props.color.value}\n @remove=${removeChip}>\n ${item.label}\n </bit-chip>\n `,\n )}\n </div>\n <span\n class=\"trigger-value ${() => (displayLabel.value ? '' : 'trigger-placeholder')}\"\n ?hidden=${() => showChips.value}\n >${() => triggerText.value}</span\n >\n </div>\n <span class=\"trigger-icon\" aria-hidden=\"true\">\n ${chevronDownIcon}\n <span class=\"loader\" aria-label=\"Loading\"></span>\n </span>\n </div>\n <div\n class=\"helper-text\"\n aria-live=\"polite\"\n ?hidden=${() => assistiveText.value.hidden}\n style=${() => (assistiveText.value.isError ? 'color: var(--color-error);' : '')}>\n ${() => assistiveText.value.text}\n </div>\n </div>\n <div\n class=\"dropdown\"\n ?data-open=${() => isOpen.value}\n role=\"listbox\"\n id=\"${listboxId}\"\n aria-label=\"Options\"\n ref=${(el: HTMLElement) => {\n dropdownEl = el;\n }}>\n <div class=\"dropdown-loading\" ?hidden=${() => !isLoading.value}>Loading…</div>\n <div class=\"dropdown-empty\" ?hidden=${() => isLoading.value || options.value.length > 0}>No options</div>\n <div class=\"options-list\" ?hidden=${() => isLoading.value || options.value.length === 0}>\n ${() =>\n flatRows.value.map((row) =>\n row.type === 'group'\n ? html`<div class=\"optgroup-label\" role=\"presentation\">${row.label}</div>`\n : html`<div\n class=\"option\"\n role=\"option\"\n id=${`${selectId}-opt-${row.idx}`}\n data-option-index=${() => String(row.idx)}\n data-option-value=${row.opt.value}\n aria-selected=${() => String(selectedValues.value.includes(row.opt.value))}\n aria-disabled=${() => String(row.opt.disabled)}\n ?data-focused=${() => focusedIndex.value === row.idx}\n ?data-selected=${() => selectedValues.value.includes(row.opt.value)}\n ?data-disabled=${() => row.opt.disabled}\n @click=${(e: MouseEvent) => {\n e.stopPropagation();\n selectOption(row.opt, e);\n }}\n @pointerenter=${() => {\n focusedIndex.value = row.idx;\n }}>\n <span>${row.opt.label}</span>\n <span class=\"option-check\" aria-hidden=\"true\">${checkIcon}</span>\n </div>`,\n )}\n </div>\n </div>`;\n },\n shadow: { delegatesFocus: true },\n styles: [\n sizeVariantMixin(FIELD_SIZE_PRESET),\n ...formFieldMixins,\n disabledLoadingMixin(),\n forcedColorsFocusMixin('.field'),\n componentStyles,\n ],\n tag: 'bit-select',\n});\n","@layer buildit.base {\n /* ========================================\n Base Styles & Defaults\n ======================================== */\n\n :host {\n --_size: var(--slider-size, var(--size-5));\n --_height: var(--slider-height, var(--size-3));\n --_track: var(--slider-track, var(--color-contrast-300));\n --_fill: var(--slider-fill, var(--color-neutral));\n --_thumb: var(--slider-thumb, var(--color-contrast-100));\n --_thumb-size: calc(var(--_size) - var(--size-1));\n --_font-size: var(--text-sm);\n --_shadow: var(--color-neutral-focus-shadow);\n\n position: relative;\n display: inline-flex;\n gap: var(--_gap, var(--size-3));\n align-items: center;\n width: 100%;\n touch-action: none;\n cursor: pointer;\n user-select: none;\n }\n}\n\n/* ========================================\n Track, Fill & Thumb\n ======================================== */\n\n.slider-container {\n position: relative;\n display: flex;\n flex: 1;\n align-items: center;\n width: 100%;\n height: var(--_size);\n min-height: var(--_touch-target);\n}\n\n.slider-track {\n position: relative;\n width: 100%;\n height: var(--_height);\n background: var(--_track);\n border-radius: var(--rounded-full);\n}\n\n/* Fill: always driven by --_fill-start / --_fill-width */\n.slider-fill {\n position: absolute;\n top: 0;\n left: var(--_fill-start, 0%);\n width: var(--_fill-width, 0%);\n height: 100%;\n background: var(--_fill);\n border-radius: var(--rounded-full);\n transition:\n left var(--transition-normal),\n width var(--transition-normal);\n}\n\n:host([data-dragging]) .slider-fill {\n transition: none;\n}\n\n.slider-thumb {\n position: absolute;\n top: 50%;\n z-index: 1;\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n cursor: grab;\n background: var(--_thumb);\n border: 2px solid var(--_fill);\n border-radius: var(--rounded-full);\n box-shadow: var(--shadow-sm);\n transform: translate(-50%, -50%);\n transition:\n box-shadow var(--transition-normal),\n transform var(--transition-fast),\n left var(--transition-normal);\n}\n\n:host([data-dragging]) .slider-thumb {\n transition:\n box-shadow var(--transition-normal),\n transform var(--transition-fast);\n}\n\n/* ── Single-value thumb ─────────────────────────────────── */\n\n.slider-thumb-sole {\n left: var(--_thumb-pos, 0%);\n}\n\n:host(:focus-visible) .slider-thumb-sole,\n:host(:active) .slider-thumb-sole {\n box-shadow: var(--_shadow);\n transform: translate(-50%, -50%) scale(1.1);\n}\n\n/* ── Range thumbs ───────────────────────────────────────── */\n\n.slider-thumb-start {\n left: var(--_thumb-start, 0%);\n}\n\n.slider-thumb-end {\n left: var(--_thumb-end, 100%);\n}\n\n.slider-thumb-start:focus-visible,\n.slider-thumb-end:focus-visible {\n z-index: 2;\n cursor: grabbing;\n outline: var(--border-2) solid var(--_fill);\n outline-offset: 2px;\n box-shadow: var(--_shadow);\n transform: translate(-50%, -50%) scale(1.1);\n}\n\n/* ── Visibility gating ──────────────────────────────────── */\n\n:host(:not([range])) .slider-thumb-start,\n:host(:not([range])) .slider-thumb-end {\n display: none;\n}\n\n:host([range]) .slider-thumb-sole {\n display: none;\n}\n\n@media (forced-colors: active) {\n /* Replace box-shadow focus ring with outline for sole-thumb focus visibility */\n :host(:focus-visible) .slider-thumb-sole {\n outline: 2px solid Highlight;\n outline-offset: 2px;\n box-shadow: none;\n }\n}\n\n@layer buildit.overrides {\n :host {\n --_fill: var(--slider-fill, var(--_theme-base));\n --_shadow: var(--_theme-shadow);\n }\n}\n\n/* ========================================\n Label\n ======================================== */\n\n.label {\n font-size: var(--_font-size);\n color: var(--color-contrast);\n white-space: nowrap;\n}\n\n@media (pointer: coarse) {\n :host {\n --_thumb-size: calc(var(--_size) + var(--size-2));\n --_size: var(--size-7);\n }\n}\n","import {\n aria,\n computed,\n createId,\n defineComponent,\n defineField,\n guard,\n handle,\n html,\n inject,\n onMount,\n ref,\n signal,\n watch,\n} from '@vielzeug/craftit';\n\nimport type { DisablableProps, SizableProps, ThemableProps } from '../../types';\n\nimport { coarsePointerMixin, colorThemeMixin, disabledStateMixin, sizeVariantMixin } from '../../styles';\nimport { SLIDER_SIZE_PRESET } from '../shared/design-presets';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport { FORM_CTX } from '../shared/form-context';\nimport { createFieldValidation } from '../shared/validation';\nimport componentStyles from './slider.css?inline';\n\n/** Slider component properties */\n\nexport type BitSliderEvents = {\n change: { from?: number; originalEvent?: Event; to?: number; value: number | { from: number; to: number } };\n};\n\nexport type BitSliderProps = ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Range mode: lower bound */\n from?: number | string;\n /** Range mode a11y label for the start thumb (e.g. \"$20\") */\n 'from-value-text'?: string;\n /** Maximum value */\n max?: number | string;\n /** Minimum value */\n min?: number | string;\n /** Single-value mode: form field name */\n name?: string;\n /** Activate two-thumb range selection */\n range?: boolean;\n /** Step increment */\n step?: number | string;\n /** Range mode: upper bound */\n to?: number | string;\n /** Range mode a11y label for the end thumb (e.g. \"$80\") */\n 'to-value-text'?: string;\n /** Single-value mode: current value */\n value?: number | string;\n /** Single-value mode a11y label override (e.g. \"75%\"). Overrides raw aria-valuenow. */\n 'value-text'?: string;\n };\n\n/**\n * A slider for selecting a single numeric value or a numeric range.\n *\n * Add the boolean `range` attribute to activate two-thumb range mode.\n *\n * @element bit-slider\n *\n * @attr {number} min - Minimum value (default: 0)\n * @attr {number} max - Maximum value (default: 100)\n * @attr {number} step - Step increment (default: 1)\n * @attr {number} value - Current value (single mode)\n * @attr {number} from - Lower bound (range mode)\n * @attr {number} to - Upper bound (range mode)\n * @attr {boolean} range - Activate range mode\n * @attr {boolean} disabled - Disable interaction\n * @attr {string} name - Form field name (single mode)\n * @attr {string} color - Theme color\n * @attr {string} size - 'sm' | 'md' | 'lg'\n *\n * @fires change - detail always includes `value`; single mode: { value: number }, range mode: { value: { from, to }, from, to }, plus optional originalEvent\n *\n * @slot - Slider label text\n *\n * @part slider - Slider container\n * @part track - Track element\n * @part fill - Fill element\n * @part thumb - Single-value thumb\n * @part thumb-start - Range start thumb\n * @part thumb-end - Range end thumb\n * @part label - Label element\n *\n * @cssprop --slider-height - Track height\n * @cssprop --slider-size - Thumb dimensions\n * @cssprop --slider-track - Track background color\n * @cssprop --slider-fill - Fill background color\n * @cssprop --slider-thumb - Thumb background color\n *\n * @example\n * ```html\n * <bit-slider value=\"50\" name=\"volume\">Volume</bit-slider>\n * <bit-slider range from=\"20\" to=\"80\" color=\"primary\">Price range</bit-slider>\n * ```\n */\nexport const SLIDER_TAG = defineComponent<BitSliderProps, BitSliderEvents>({\n formAssociated: true,\n props: {\n color: { default: undefined },\n disabled: { default: false },\n from: { default: '0' },\n 'from-value-text': { default: undefined },\n max: { default: '100' },\n min: { default: '0' },\n name: { default: '' },\n range: { default: false },\n size: { default: undefined },\n step: { default: '1' },\n to: { default: '100' },\n 'to-value-text': { default: undefined },\n value: { default: '0' },\n 'value-text': { default: undefined },\n },\n setup({ emit, host, props, slots }) {\n // Treat `range` as static — determined at first render\n const isRange = props.range.value;\n // ── Shared helpers ────────────────────────────────────────────\n const getNum = (v: string | number | undefined, fallback: number) => {\n const n = Number(v);\n\n return Number.isFinite(n) ? n : fallback;\n };\n const snapVal = (value: number) => {\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n const step = getNum(props.step.value, 1);\n\n return Math.max(min, Math.min(max, Math.round(value / step) * step));\n };\n const toPercent = (value: number) => {\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n\n return ((value - min) / (max - min)) * 100;\n };\n // ── Single-value state ────────────────────────────────────────\n const formCtx = inject(FORM_CTX, undefined);\n\n mountFormContextSync(host, formCtx, props);\n\n let sliderFd:\n | {\n reportValidity: () => boolean;\n }\n | undefined;\n const valueSignal = signal('0');\n\n if (!isRange) {\n sliderFd = defineField(\n { disabled: computed(() => Boolean(props.disabled.value)), value: valueSignal },\n {\n onReset: () => {\n valueSignal.value = '0';\n },\n },\n );\n watch(\n props.value,\n (v) => {\n valueSignal.value = String(v);\n },\n { immediate: true },\n );\n aria({\n disabled: () => Boolean(props.disabled.value),\n valuemax: () => getNum(props.max.value, 100),\n valuemin: () => getNum(props.min.value, 0),\n valuenow: () => Number(valueSignal.value || 0),\n valuetext: () => props['value-text'].value ?? null,\n });\n }\n\n // ── Range state ───────────────────────────────────────────────\n const startVal = signal(0);\n const endVal = signal(100);\n\n if (isRange) {\n sliderFd = defineField<{\n from: number;\n to: number;\n }>(\n {\n disabled: computed(() => Boolean(props.disabled.value)),\n toFormValue: ({ from, to }) => {\n const name = props.name.value;\n\n if (!name) return null;\n\n const fd = new FormData();\n\n fd.append(`${name}[from]`, String(from));\n fd.append(`${name}[to]`, String(to));\n\n return fd;\n },\n value: computed(() => ({ from: startVal.value, to: endVal.value })),\n },\n {\n onReset: () => {\n startVal.value = snapVal(getNum(props.from.value, 0));\n endVal.value = snapVal(getNum(props.to.value, 100));\n },\n },\n );\n watch(\n props.from,\n (v) => {\n startVal.value = snapVal(getNum(v as string | number | undefined, 0));\n },\n { immediate: true },\n );\n watch(\n props.to,\n (v) => {\n endVal.value = snapVal(getNum(v as string | number | undefined, 100));\n },\n { immediate: true },\n );\n }\n\n // ── Refs ──────────────────────────────────────────────────────\n const containerRef = ref<HTMLDivElement>();\n const labelRef = ref<HTMLSpanElement>();\n const thumbStartRef = ref<HTMLDivElement>();\n const thumbEndRef = ref<HTMLDivElement>();\n const startId = createId('slider-start');\n const endId = createId('slider-end');\n // ── CSS update helpers ────────────────────────────────────────\n const updateSingleCSS = (value: number) => {\n const pct = toPercent(value);\n\n host.style.setProperty('--_thumb-pos', `${pct}%`);\n host.style.setProperty('--_fill-start', '0%');\n host.style.setProperty('--_fill-width', `${pct}%`);\n };\n const updateRangeCSS = () => {\n const s = toPercent(startVal.value);\n const e = toPercent(endVal.value);\n\n host.style.setProperty('--_thumb-start', `${s}%`);\n host.style.setProperty('--_thumb-end', `${e}%`);\n host.style.setProperty('--_fill-start', `${s}%`);\n host.style.setProperty('--_fill-width', `${e - s}%`);\n };\n // ── Key-delta maps (avoids switch complexity) ─────────────────\n const keyDelta = (key: string, step: number, min: number, max: number, current: number): number | null => {\n if (key === 'ArrowRight' || key === 'ArrowUp') return current + step;\n\n if (key === 'ArrowLeft' || key === 'ArrowDown') return current - step;\n\n if (key === 'Home') return min;\n\n if (key === 'End') return max;\n\n return null;\n };\n\n // ── Range mode setup ──────────────────────────────────────────\n const { triggerValidation } = createFieldValidation(formCtx, {\n reportValidity: () => sliderFd?.reportValidity() ?? false,\n });\n\n const setupRangeMode = (container: HTMLDivElement) => {\n updateRangeCSS();\n\n const clientToValue = (clientX: number) => {\n const rect = container.getBoundingClientRect();\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n\n return snapVal(min + pct * (max - min));\n };\n let dragging: 'start' | 'end' | null = null;\n const applyDrag = (val: number) => {\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n\n if (dragging === 'start') startVal.value = Math.min(snapVal(val), endVal.value);\n else if (dragging === 'end') endVal.value = Math.max(snapVal(val), startVal.value);\n\n startVal.value = Math.max(min, Math.min(startVal.value, max));\n endVal.value = Math.max(min, Math.min(endVal.value, max));\n updateRangeCSS();\n emit('change', {\n from: startVal.value,\n to: endVal.value,\n value: { from: startVal.value, to: endVal.value },\n });\n triggerValidation('change');\n };\n\n handle(\n container,\n 'pointerdown',\n guard(\n () => !props.disabled.value,\n (e: PointerEvent) => {\n e.preventDefault();\n\n const val = clientToValue(e.clientX);\n\n dragging = Math.abs(val - startVal.value) <= Math.abs(val - endVal.value) ? 'start' : 'end';\n host.setAttribute('data-dragging', '');\n (e.target as Element).setPointerCapture(e.pointerId);\n applyDrag(val);\n },\n ),\n );\n handle(\n container,\n 'pointermove',\n guard(\n () => !!dragging,\n (e: PointerEvent) => {\n e.preventDefault();\n applyDrag(clientToValue(e.clientX));\n },\n ),\n );\n handle(\n container,\n 'pointerup',\n guard(\n () => !!dragging,\n (e: PointerEvent) => {\n e.preventDefault();\n dragging = null;\n host.removeAttribute('data-dragging');\n (e.target as Element).releasePointerCapture(e.pointerId);\n },\n ),\n );\n\n const makeThumbKeydown = (getVal: () => number, setVal: (v: number) => void) => (e: KeyboardEvent) => {\n if (props.disabled.value) return;\n\n const step = getNum(props.step.value, 1);\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n const next = keyDelta(e.key, step, min, max, getVal());\n\n if (next === null) return;\n\n e.preventDefault();\n setVal(snapVal(Math.max(min, Math.min(max, next))));\n updateRangeCSS();\n emit('change', {\n from: startVal.value,\n originalEvent: e,\n to: endVal.value,\n value: { from: startVal.value, to: endVal.value },\n });\n triggerValidation('change');\n };\n const thumbStartEl = thumbStartRef.value;\n const thumbEndEl = thumbEndRef.value;\n\n if (thumbStartEl) {\n thumbStartEl.addEventListener(\n 'keydown',\n makeThumbKeydown(\n () => startVal.value,\n (v) => {\n startVal.value = Math.min(v, endVal.value);\n },\n ),\n );\n aria(thumbStartEl, {\n label: 'Range start',\n valuemax: () => endVal.value,\n valuemin: () => getNum(props.min.value, 0),\n valuenow: () => startVal.value,\n valuetext: () => props['from-value-text'].value ?? null,\n });\n }\n\n if (thumbEndEl) {\n thumbEndEl.addEventListener(\n 'keydown',\n makeThumbKeydown(\n () => endVal.value,\n (v) => {\n endVal.value = Math.max(v, startVal.value);\n },\n ),\n );\n aria(thumbEndEl, {\n label: 'Range end',\n valuemax: () => getNum(props.max.value, 100),\n valuemin: () => startVal.value,\n valuenow: () => endVal.value,\n valuetext: () => props['to-value-text'].value ?? null,\n });\n }\n };\n // ── Single-value mode setup ───────────────────────────────────\n const setupSingleMode = (container: HTMLDivElement) => {\n host.setAttribute('role', 'slider');\n\n if (!props.disabled.value) host.setAttribute('tabindex', '0');\n\n updateSingleCSS(Number(valueSignal.value));\n\n const updateValue = (clientX: number) => {\n if (props.disabled.value) return;\n\n const rect = container.getBoundingClientRect();\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n const step = getNum(props.step.value, 1);\n const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n const newValue = Math.max(min, Math.min(max, Math.round((min + pct * (max - min)) / step) * step));\n\n if (Number(valueSignal.value) !== newValue) {\n valueSignal.value = newValue.toString();\n updateSingleCSS(newValue);\n emit('change', { value: newValue });\n triggerValidation('change');\n }\n };\n let isDragging = false;\n\n handle(\n container,\n 'pointerdown',\n guard(\n () => !props.disabled.value,\n (e: PointerEvent) => {\n e.preventDefault();\n isDragging = true;\n updateValue(e.clientX);\n (e.target as Element).setPointerCapture(e.pointerId);\n },\n ),\n );\n handle(\n container,\n 'pointermove',\n guard(\n () => isDragging,\n (e: PointerEvent) => {\n e.preventDefault();\n\n if (!host.hasAttribute('data-dragging')) host.setAttribute('data-dragging', '');\n\n updateValue(e.clientX);\n },\n ),\n );\n handle(\n container,\n 'pointerup',\n guard(\n () => isDragging,\n (e: PointerEvent) => {\n e.preventDefault();\n isDragging = false;\n host.removeAttribute('data-dragging');\n (e.target as Element).releasePointerCapture(e.pointerId);\n },\n ),\n );\n handle(\n host,\n 'keydown',\n guard(\n () => !props.disabled.value,\n (e: KeyboardEvent) => {\n const min = getNum(props.min.value, 0);\n const max = getNum(props.max.value, 100);\n const step = getNum(props.step.value, 1);\n const val = Number(valueSignal.value || 0);\n const next = keyDelta(e.key, step, min, max, val);\n\n if (next === null) return;\n\n e.preventDefault();\n\n const newValue = Math.max(min, Math.min(max, next));\n\n if (newValue !== val) {\n valueSignal.value = newValue.toString();\n updateSingleCSS(newValue);\n emit('change', { originalEvent: e, value: newValue });\n triggerValidation('change');\n }\n },\n ),\n );\n };\n\n onMount(() => {\n const container = containerRef.value;\n\n if (!container) return;\n\n if (slots.has('default').value && labelRef.value) {\n const labelId = createId('slider-label');\n\n labelRef.value.id = labelId;\n\n if (!isRange) aria({ labelledby: labelId });\n }\n\n if (isRange) setupRangeMode(container);\n else setupSingleMode(container);\n });\n\n return html`\n <div class=\"slider-container\" part=\"slider\" ref=${containerRef}>\n <div class=\"slider-track\" part=\"track\">\n <div class=\"slider-fill\" part=\"fill\"></div>\n <div class=\"slider-thumb slider-thumb-sole\" part=\"thumb\"></div>\n <div\n class=\"slider-thumb slider-thumb-start\"\n part=\"thumb-start\"\n ref=${thumbStartRef}\n role=\"slider\"\n tabindex=\"${() => (props.disabled.value ? '-1' : '0')}\"\n id=\"${startId}\"></div>\n <div\n class=\"slider-thumb slider-thumb-end\"\n part=\"thumb-end\"\n ref=${thumbEndRef}\n role=\"slider\"\n tabindex=\"${() => (props.disabled.value ? '-1' : '0')}\"\n id=\"${endId}\"></div>\n </div>\n </div>\n <span class=\"label\" part=\"label\" ref=${labelRef}><slot></slot></span>\n `;\n },\n styles: [\n disabledStateMixin(),\n colorThemeMixin,\n sizeVariantMixin(SLIDER_SIZE_PRESET),\n componentStyles,\n coarsePointerMixin,\n ],\n tag: 'bit-slider',\n});\n","@layer buildit.base {\n :host {\n --_width: var(--switch-width, var(--size-10));\n --_height: var(--switch-height, var(--size-5));\n --_padding: var(--size-0-5);\n --_thumb-size: calc(var(--_height) - var(--_padding) * 2);\n --_track-bg: var(--switch-track, var(--color-contrast-300));\n --_thumb-bg: var(--switch-thumb, white);\n --_font-size: var(--switch-font-size, var(--text-sm));\n\n display: inline-flex;\n flex-wrap: wrap;\n gap: var(--_gap, var(--size-2-5));\n align-items: center;\n min-height: var(--size-11);\n touch-action: manipulation;\n cursor: pointer;\n user-select: none;\n }\n\n /* ========================================\n Track & Thumb\n ======================================== */\n\n .switch-wrapper {\n display: flex;\n flex-shrink: 0;\n }\n\n .switch-track {\n position: relative;\n width: var(--_width);\n height: var(--_height);\n background: var(--_track-bg);\n border-radius: var(--rounded-full);\n transition:\n background var(--transition-slower),\n box-shadow var(--transition-normal);\n will-change: background;\n }\n\n .switch-thumb {\n position: absolute;\n inset-inline-start: var(--_padding);\n top: var(--_padding);\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n background: var(--_thumb-bg);\n border-radius: var(--rounded-full);\n box-shadow: var(--shadow-sm);\n transition:\n transform var(--transition-spring),\n box-shadow var(--transition-normal);\n will-change: transform;\n }\n\n /* ========================================\n Focus State\n ======================================== */\n\n input:focus-visible ~ .switch-track {\n box-shadow: var(--_focus-shadow);\n }\n\n /* ========================================\n Label\n ======================================== */\n\n .label {\n font-size: var(--_font-size);\n color: var(--color-contrast);\n }\n}\n\n@layer buildit.overrides {\n /* Map theme variables to switch-specific variables */\n :host {\n --_active-bg: var(--switch-bg, var(--_theme-base));\n --_focus-shadow: var(--_theme-shadow);\n }\n\n /* ========================================\n Checked State\n ======================================== */\n\n :host([checked]) .switch-track {\n background: var(--_active-bg);\n }\n\n :host([checked]) .switch-thumb {\n transform: translateX(calc(var(--_width) - var(--_height)));\n }\n\n /* In RTL the thumb starts at the inline-end edge; slide left to reach inline-start */\n :host(:dir(rtl)[checked]) .switch-thumb {\n transform: translateX(calc(-1 * (var(--_width) - var(--_height))));\n }\n\n /* ========================================\n Hover & Active States\n ======================================== */\n\n :host(:hover:not([disabled], [checked])) .switch-track {\n background: var(--color-contrast-400);\n }\n\n :host(:hover:not([disabled])[checked]) .switch-track {\n filter: brightness(1.1);\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n width: 100%;\n padding-inline-start: calc(var(--_width) + var(--size-2-5));\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n .helper-text[role='alert'] {\n color: var(--color-error);\n }\n}\n","import { defineComponent, html } from '@vielzeug/craftit';\nimport { useA11yControl, createCheckableControl } from '@vielzeug/craftit/labs';\n\nimport type { CheckableProps, DisablableProps, SizableProps, ThemableProps } from '../../types';\n\nimport { formControlMixins, sizeVariantMixin } from '../../styles';\nimport { useToggleField } from '../shared/composables';\nimport { SWITCH_SIZE_PRESET } from '../shared/design-presets';\nimport { mountFormContextSync } from '../shared/dom-sync';\nimport componentStyles from './switch.css?inline';\n\nexport type BitSwitchEvents = {\n change: { checked: boolean; originalEvent?: Event; value: boolean };\n};\n\nexport type BitSwitchProps = CheckableProps &\n ThemableProps &\n SizableProps &\n DisablableProps & {\n /** Error message (marks field as invalid) */\n error?: string;\n /** Helper text displayed below the switch */\n helper?: string;\n };\n\n/**\n * A toggle switch component for binary on/off states.\n *\n * @element bit-switch\n *\n * @attr {boolean} checked - Checked/on state\n * @attr {boolean} disabled - Disable switch interaction\n * @attr {string} value - Field value\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Switch size: 'sm' | 'md' | 'lg'\n * @attr {string} error - Error message (marks field as invalid)\n * @attr {string} helper - Helper text displayed below the switch\n *\n * @fires change - Emitted when switch is toggled. detail: { value: boolean, checked: boolean, originalEvent?: Event }\n *\n * @slot - Switch label text\n *\n * @part switch - The switch wrapper element\n * @part track - The switch track element\n * @part thumb - The switch thumb element\n * @part label - The label element\n * @part helper-text - The helper/error text element\n */\nexport const SWITCH_TAG = defineComponent<BitSwitchProps, BitSwitchEvents>({\n formAssociated: true,\n props: {\n checked: { default: false },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '' },\n helper: { default: '' },\n name: { default: '' },\n size: { default: undefined },\n value: { default: 'on' },\n },\n setup({ emit, host, props, reflect }) {\n const { checkedSignal, formCtx, triggerValidation } = useToggleField(props);\n\n mountFormContextSync(host, formCtx, props);\n\n // Pass writable checkedSignal directly — toggle() mutates it in place\n const control = createCheckableControl({\n checked: checkedSignal,\n clearIndeterminateFirst: false,\n disabled: props.disabled,\n onToggle: (e) => {\n triggerValidation('change');\n emit('change', control.changePayload(e));\n },\n value: props.value,\n });\n\n const a11y = useA11yControl(host, {\n checked: () => (control.checked.value ? 'true' : 'false'),\n helperText: () => props.error.value || props.helper.value,\n helperTone: () => (props.error.value ? 'error' : 'default'),\n invalid: () => !!props.error.value,\n role: 'switch',\n });\n\n reflect({\n checked: () => control.checked.value,\n classMap: () => ({\n 'is-checked': control.checked.value,\n 'is-disabled': !!props.disabled.value,\n }),\n onClick: (e: Event) => control.toggle(e),\n onKeydown: (e: Event) => {\n const ke = e as KeyboardEvent;\n\n if (ke.key === ' ' || ke.key === 'Enter') {\n ke.preventDefault();\n control.toggle(e);\n }\n },\n tabindex: () => (props.disabled.value ? undefined : 0),\n });\n\n return html`\n <div class=\"switch-wrapper\" part=\"switch\">\n <div class=\"switch-track\" part=\"track\">\n <div class=\"switch-thumb\" part=\"thumb\"></div>\n </div>\n </div>\n <span class=\"label\" part=\"label\" data-a11y-label id=\"${a11y.labelId}\"><slot></slot></span>\n <div\n class=\"helper-text\"\n part=\"helper-text\"\n data-a11y-helper\n id=\"${a11y.helperId}\"\n aria-live=\"polite\"\n hidden></div>\n `;\n },\n styles: [...formControlMixins, sizeVariantMixin(SWITCH_SIZE_PRESET), componentStyles],\n tag: 'bit-switch',\n});\n","@layer buildit.base {\n :host {\n --_font-size: var(--textarea-font-size, var(--text-sm));\n --_gap: var(--textarea-gap, var(--size-2));\n --_padding: var(--textarea-padding, var(--size-2) var(--size-3));\n --_radius: var(--textarea-radius, var(--rounded-lg));\n --_placeholder: var(--textarea-placeholder-color, var(--color-contrast-500));\n --_bg: var(--textarea-bg, var(--color-contrast-100));\n --_border-color: var(--textarea-border-color, var(--color-contrast-300));\n --_min-height: var(--textarea-min-height, var(--size-24));\n --_max-height: var(--textarea-max-height, none);\n --_resize: var(--textarea-resize, vertical);\n\n display: inline-flex;\n flex-direction: column;\n align-items: stretch;\n min-width: 12rem;\n }\n\n .textarea-wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--size-1-5);\n min-width: 0; /* Allow shrinking below content size */\n }\n\n .field {\n box-sizing: border-box;\n display: grid; /* Grid automatically sizes to content */\n min-width: 0; /* Allow shrinking */\n padding: var(--_padding);\n background: var(--_bg);\n border: var(--border) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--shadow-2xs);\n transition:\n background var(--transition-fast),\n backdrop-filter var(--transition-slow),\n border-color var(--transition-fast),\n box-shadow var(--transition-fast),\n transform var(--transition-fast);\n }\n\n /* ========================================\n Label Styles\n ======================================== */\n\n .label-inset,\n .label-outside,\n label.label-inset,\n label.label-outside {\n font-weight: var(--font-medium);\n color: var(--color-contrast-500);\n cursor: pointer;\n user-select: none;\n transition: color var(--transition-fast);\n }\n\n .label-inset,\n label.label-inset {\n margin-bottom: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n }\n\n .label-outside,\n label.label-outside {\n font-size: var(--text-sm);\n line-height: var(--leading-none);\n }\n\n /* ========================================\n Helper / Error Text\n ======================================== */\n\n .helper-text {\n padding-inline: 2px;\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-500);\n }\n\n /* ========================================\n Textarea Element\n ======================================== */\n\n textarea {\n box-sizing: border-box;\n min-width: 12rem; /* Match :host min-width to prevent resize below minimum */\n min-height: var(--_min-height);\n max-height: var(--_max-height);\n padding: 0;\n font: inherit;\n font-size: var(--_font-size);\n line-height: var(--leading-relaxed);\n color: var(--_theme-content);\n resize: vertical; /* Default resize, can be overridden by inline style */\n outline: none;\n background: transparent;\n border: none;\n }\n\n textarea::placeholder {\n color: var(--_placeholder);\n transition: color var(--transition-fast);\n }\n\n textarea:focus-visible {\n outline: none;\n }\n\n /* ========================================\n Character Counter\n ======================================== */\n\n .counter {\n align-self: flex-end;\n padding-inline: 2px;\n margin-top: var(--size-1);\n font-size: var(--text-xs);\n line-height: var(--leading-tight);\n color: var(--color-contrast-400);\n transition: color var(--transition-fast);\n }\n\n .counter.near-limit {\n color: var(--color-warning);\n }\n\n .counter.at-limit {\n color: var(--color-error);\n }\n\n /* ========================================\n Hover & Focus States\n ======================================== */\n\n :host(:not([disabled], [variant='bordered'], [variant='flat'])) .field:hover {\n border-color: var(--color-contrast-400);\n }\n\n :host(:not([disabled], [variant='text'], [variant='flat'])) .field:focus-within {\n background: var(--color-canvas);\n border-color: var(--_theme-focus);\n box-shadow: var(--_theme-shadow, var(--color-primary-focus-shadow));\n transform: translateY(-1px);\n }\n\n :host(:not([disabled])) .field:focus-within .label-inset,\n :host(:not([disabled])) .field:focus-within .label-outside {\n color: var(--_theme-focus);\n }\n\n /* Error State */\n :host([error]:not([error=''])) .field {\n border-color: var(--color-error);\n }\n\n :host([error]:not([error=''])) .field:focus-within {\n border-color: var(--color-error);\n box-shadow: var(--color-error-focus-shadow);\n }\n\n :host([error]:not([error=''])) .label-inset,\n :host([error]:not([error=''])) .label-outside {\n color: var(--color-error);\n }\n}\n\n@layer buildit.variants {\n /* Solid (Default) */\n :host(:not([variant])) .field,\n :host([variant='solid']) .field {\n background: var(--color-contrast-50);\n border-color: var(--color-contrast-300);\n box-shadow: var(--shadow-2xs);\n }\n\n :host(:not([variant], [disabled])) .field:focus-within,\n :host([variant='solid']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Flat */\n :host([variant='flat']) .field {\n border-color: var(--_theme-border);\n box-shadow: var(--inset-shadow-2xs);\n }\n\n :host([variant='flat']) .field:hover {\n background: color-mix(in srgb, var(--_theme-base) 6%, var(--color-contrast-100));\n border-color: color-mix(in srgb, var(--_theme-base) 35%, var(--color-contrast-300));\n }\n\n :host([variant='flat']) .field:focus-within {\n background: color-mix(in srgb, var(--_theme-base) 8%, var(--color-canvas));\n border-color: color-mix(in srgb, var(--_theme-focus) 60%, transparent);\n box-shadow: var(--_theme-shadow);\n }\n\n /* Bordered */\n :host([variant='bordered']) .field {\n background: var(--_theme-backdrop);\n border-color: color-mix(in srgb, var(--_theme-focus) 70%, transparent);\n }\n\n :host([variant='bordered']) textarea {\n color: var(--_theme-content);\n }\n\n :host([variant='bordered'][color='secondary']) textarea {\n color: var(--_theme-base);\n }\n\n :host([variant='bordered']) textarea::placeholder {\n color: color-mix(in srgb, var(--_theme-content) 45%, transparent);\n }\n\n :host([variant='bordered'][color='secondary']) textarea::placeholder {\n color: color-mix(in srgb, var(--_theme-base) 45%, transparent);\n }\n\n :host([variant='bordered']) .field:hover {\n border-color: var(--_theme-focus);\n }\n\n /* Outline */\n :host([variant='outline']) .field {\n background: transparent;\n box-shadow: none;\n }\n\n :host([variant='outline']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n\n /* Ghost */\n :host([variant='ghost']) .field {\n background: transparent;\n border-color: transparent;\n box-shadow: none;\n }\n\n :host([variant='ghost']) .field:hover {\n background: var(--color-contrast-100);\n }\n\n :host([variant='ghost']:not([disabled])) .field:focus-within {\n box-shadow: var(--_theme-shadow);\n }\n}\n\n@layer buildit.utilities {\n /* Auto-resize hides overflow */\n :host([auto-resize]) textarea {\n overflow: hidden;\n }\n\n /* Full width */\n :host([fullwidth]) {\n width: 100%;\n }\n}\n","import { computed, defineComponent, effect, html, onMount, ref } from '@vielzeug/craftit';\nimport { attr } from '@vielzeug/craftit/directives';\n\nimport type { VisualVariant } from '../../types';\nimport type { TextFieldProps } from '../shared/base-props';\n\nimport { disabledLoadingMixin, forcedColorsFocusMixin, formFieldMixins, sizeVariantMixin } from '../../styles';\nimport { useTextField } from '../shared/composables';\nimport { TEXTAREA_SIZE_PRESET } from '../shared/design-presets';\nimport { setupFieldEvents, syncCounter, syncMergedAssistive } from '../shared/dom-sync';\nimport { parsePositiveNumber } from '../shared/utils';\nimport componentStyles from './textarea.css?inline';\n\n/** Textarea component properties */\n\nexport type BitTextareaEvents = {\n change: { originalEvent: Event; value: string };\n input: { originalEvent: Event; value: string };\n};\n\nexport type BitTextareaProps = TextFieldProps<Exclude<VisualVariant, 'glass' | 'frost' | 'text'>> & {\n /** Allow auto-grow with content */\n 'auto-resize'?: boolean;\n /** Maximum character count; shows a counter when set */\n maxlength?: number;\n /** Disable manual resize handle */\n 'no-resize'?: boolean;\n /** Resize direction override */\n resize?: 'none' | 'horizontal' | 'both' | 'vertical';\n /** Number of visible text rows */\n rows?: number;\n};\n\n/**\n * A multi-line text input with label, helper text, character counter, and auto-resize.\n *\n * @element bit-textarea\n *\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} value - Current value\n * @attr {string} placeholder - Placeholder text\n * @attr {string} name - Form field name\n * @attr {number} rows - Visible row count\n * @attr {number} maxlength - Max character count (shows counter)\n * @attr {string} helper - Helper text below the textarea\n * @attr {string} error - Error message\n * @attr {boolean} disabled - Disable interaction\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} required - Required field\n * @attr {boolean} no-resize - Disable manual resize\n * @attr {boolean} auto-resize - Grow with content\n * @attr {string} resize - Resize direction: 'none' | 'horizontal' | 'both' | 'vertical'\n * @attr {string} color - Theme color\n * @attr {string} variant - Visual variant\n * @attr {string} size - Component size\n * @attr {string} rounded - Border radius\n *\n * @fires input - Fired on every keystroke with current value\n * @fires change - Fired on blur with changed value\n *\n * @slot helper - Complex helper content\n */\nexport const TEXTAREA_TAG = defineComponent<BitTextareaProps, BitTextareaEvents>({\n formAssociated: true,\n props: {\n 'auto-resize': { default: false },\n color: { default: undefined },\n disabled: { default: false },\n error: { default: '', omit: true },\n fullwidth: { default: false },\n helper: { default: '' },\n label: { default: '' },\n 'label-placement': { default: 'inset' },\n maxlength: { default: undefined },\n name: { default: '' },\n 'no-resize': { default: false },\n placeholder: { default: '' },\n readonly: { default: false },\n required: { default: false },\n resize: { default: undefined },\n rounded: { default: undefined },\n rows: { default: undefined },\n size: { default: undefined },\n value: { default: '' },\n variant: { default: undefined },\n },\n setup({ emit, props }) {\n const tf = useTextField(props, 'textarea');\n const {\n fieldId: textareaId,\n helperId,\n labelInsetId,\n labelInsetRef,\n labelOutsideId,\n labelOutsideRef,\n valueSignal,\n } = tf;\n const maxLen = computed<number | undefined>(() => props.maxlength.value);\n\n const textareaRef = ref<HTMLTextAreaElement>();\n const helperRef = ref<HTMLDivElement>();\n const counterRef = ref<HTMLSpanElement>();\n\n onMount(() => {\n const ta = textareaRef.value;\n\n if (!ta) return;\n\n const autoGrow = () => {\n if (!props['auto-resize'].value || !ta) return;\n\n ta.style.height = 'auto';\n ta.style.height = `${ta.scrollHeight}px`;\n };\n\n tf.mountLabelSync();\n\n effect(() => {\n const rows = parsePositiveNumber(props.rows.value);\n\n if (rows != null) ta.rows = rows;\n else ta.removeAttribute('rows');\n\n const max = parsePositiveNumber(maxLen.value);\n\n if (max != null) ta.maxLength = max;\n else ta.removeAttribute('maxlength');\n\n ta.style.resize =\n props['auto-resize'].value || props['no-resize'].value ? 'none' : props.resize.value || 'vertical';\n });\n\n syncMergedAssistive({\n error: () => props.error.value,\n helper: () => props.helper.value,\n ref: helperRef,\n });\n\n syncCounter({\n count: computed(() => valueSignal.value.length),\n format: 'merged',\n maxLength: maxLen,\n ref: counterRef,\n });\n\n // TODO: migrate aria() on inner elements to a future useA11yField() composable\n import('@vielzeug/craftit').then(({ aria }) => {\n aria(ta, {\n describedby: () => (props.error.value ? tf.errorId : helperId),\n invalid: () => !!props.error.value,\n labelledby: () => (props['label-placement'].value === 'outside' ? labelOutsideId : labelInsetId),\n });\n });\n\n setupFieldEvents(ta, {\n onBlur: () => tf.triggerValidation('blur'),\n onChange: (e, value) => {\n emit('change', { originalEvent: e, value });\n tf.triggerValidation('change');\n },\n onInput: (e, value) => {\n autoGrow();\n emit('input', { originalEvent: e, value });\n },\n });\n\n if (props['auto-resize'].value) requestAnimationFrame(autoGrow);\n });\n\n return html`\n <div class=\"textarea-wrapper\">\n <label class=\"label-outside\" for=\"${textareaId}\" id=\"${labelOutsideId}\" ref=${labelOutsideRef} hidden></label>\n <div class=\"field\">\n <label class=\"label-inset\" for=\"${textareaId}\" id=\"${labelInsetId}\" ref=${labelInsetRef} hidden></label>\n <textarea\n ref=${textareaRef}\n id=\"${textareaId}\"\n ${attr({\n disabled: props.disabled,\n name: props.name,\n placeholder: props.placeholder,\n readOnly: props.readonly,\n required: props.required,\n value: valueSignal,\n })}\n aria-describedby=\"${helperId}\"></textarea>\n </div>\n <span class=\"counter\" aria-live=\"polite\" ref=${counterRef} hidden></span>\n <div id=\"${helperId}\" class=\"helper-text\" aria-live=\"polite\" ref=${helperRef} hidden></div>\n </div>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [\n ...formFieldMixins,\n sizeVariantMixin(TEXTAREA_SIZE_PRESET),\n disabledLoadingMixin(),\n forcedColorsFocusMixin('textarea'),\n componentStyles,\n ],\n tag: 'bit-textarea',\n});\n","@layer buildit.base {\n :host {\n --_bg: var(--box-bg, var(--color-canvas));\n --_color: var(--box-color, var(--color-contrast-900));\n --_border-width: var(--box-border, var(--border));\n --_border-color: var(--box-border-color, var(--color-contrast-300));\n --_radius: var(--box-radius, var(--rounded-lg));\n --_padding: var(--box-padding, var(--size-4));\n --_shadow: var(--box-shadow, var(--shadow-sm));\n\n position: relative;\n display: block;\n }\n\n .box {\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n padding: var(--_padding);\n color: var(--_color);\n background: var(--_bg);\n border: var(--_border-width) solid var(--_border-color);\n border-radius: var(--_radius);\n box-shadow: var(--_shadow);\n transition:\n backdrop-filter var(--transition-slow),\n box-shadow var(--transition-normal),\n background var(--transition-normal),\n border-color var(--transition-normal);\n will-change: box-shadow;\n }\n}\n\n@layer buildit.variants {\n /* Color theme integration — custom props still take priority */\n :host([color]) {\n --_bg: var(--box-bg, var(--_theme-backdrop));\n --_border-color: var(--box-border-color, var(--_theme-border));\n }\n\n /* Flat - border only, no shadow */\n :host([variant='flat']) {\n --_shadow: none;\n }\n\n /* Glass */\n :host([variant='glass']:not([color])) {\n --_bg: color-mix(in srgb, var(--color-secondary) 20%, transparent);\n --_border-color: color-mix(in srgb, var(--color-secondary-contrast) 15%, transparent);\n }\n\n :host([variant='glass'][color]) {\n --_bg: color-mix(in srgb, var(--_theme-base) 20%, transparent);\n --_border-color: color-mix(in srgb, var(--_theme-contrast) 15%, transparent);\n --_color: var(--_theme-content);\n }\n\n :host([variant='glass']) .box {\n box-shadow: var(--shadow-md), var(--inset-shadow-xs);\n backdrop-filter: blur(var(--blur-lg)) saturate(180%) brightness(1.05);\n }\n\n /* Subtle hover for solid/default + color (glass & frost manage their own hover) */\n :host([color]:not([variant='glass'], [variant='frost']):hover) {\n --_bg: color-mix(in srgb, var(--_theme-base) 16%, var(--color-contrast-50));\n --_border-color: var(--_theme-focus);\n }\n}\n\n@layer buildit.utilities {\n :host([fullwidth]) {\n width: 100%;\n }\n}\n","import { defineComponent, html } from '@vielzeug/craftit';\n\nimport type { ElevationLevel, PaddingSize, RoundedSize, ThemeColor } from '../../types';\n\nimport { frostVariantMixin, rainbowEffectMixin, surfaceMixins } from '../../styles';\nimport componentStyles from './box.css?inline';\n\n/** Box component properties */\nexport type BitBoxProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Shadow elevation level (0–5) */\n elevation?: `${ElevationLevel}`;\n /** Full width mode (100% of container) */\n fullwidth?: boolean;\n /** Internal padding size */\n padding?: PaddingSize;\n /** Enable animated rainbow border effect */\n rainbow?: boolean;\n /** Border radius size */\n rounded?: RoundedSize;\n /** Visual style variant */\n variant?: 'solid' | 'flat' | 'glass' | 'frost';\n};\n\n/**\n * bit-box — A foundational layout primitive with theming support.\n *\n * @element bit-box\n *\n * @attr {string} variant - Style variant: 'solid' | 'flat' | 'glass' | 'frost'\n * @attr {string} color - Color theme: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} padding - Padding size: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n * @attr {string} elevation - Shadow elevation: '0' | '1' | '2' | '3' | '4' | '5'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {boolean} rainbow - Enable animated rainbow border effect\n * @attr {boolean} fullwidth - Expand to full width\n *\n * @slot - Default slot for content\n *\n * @part box - The inner box element\n *\n * @cssprop --box-bg - Background color\n * @cssprop --box-color - Text color\n * @cssprop --box-border - Border width\n * @cssprop --box-border-color - Border color\n * @cssprop --box-radius - Border radius\n * @cssprop --box-padding - Inner padding\n * @cssprop --box-shadow - Box shadow\n *\n * @example\n * ```html\n * <bit-box padding=\"lg\" elevation=\"2\">Simple content</bit-box>\n * <bit-box variant=\"glass\" color=\"primary\">Glass effect</bit-box>\n * <bit-box variant=\"frost\" rainbow>Frosted glass</bit-box>\n * ```\n */\nexport const BOX_TAG = defineComponent({\n setup() {\n return html`<div class=\"box\" part=\"box\"><slot></slot></div>`;\n },\n styles: [...surfaceMixins, rainbowEffectMixin('.box'), frostVariantMixin('.box'), componentStyles],\n tag: 'bit-box',\n});\n","@layer buildit.base {\n :host {\n display: block;\n }\n}\n\n@layer buildit.utilities {\n :host([align='start']) {\n align-self: start;\n }\n\n :host([align='center']) {\n align-self: center;\n }\n\n :host([align='end']) {\n align-self: end;\n }\n\n :host([align='stretch']) {\n align-self: stretch;\n }\n\n :host([justify='start']) {\n justify-self: start;\n }\n\n :host([justify='center']) {\n justify-self: center;\n }\n\n :host([justify='end']) {\n justify-self: end;\n }\n\n :host([justify='stretch']) {\n justify-self: stretch;\n }\n}\n","import { defineComponent, effect, html } from '@vielzeug/craftit';\n\nimport styles from './grid-item.css?inline';\n\n/** Grid item component properties */\nexport type BitGridItemProps = {\n /** Align self vertically within the grid cell */\n align?: 'start' | 'center' | 'end' | 'stretch';\n /** Explicit grid-column value — overrides col-span (e.g. '2 / 5', 'span 3', '1 / -1'). */\n col?: string;\n /** Span N columns. Use 'full' to span all columns (1 / -1). */\n colSpan?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'full';\n /** Justify self horizontally within the grid cell */\n justify?: 'start' | 'center' | 'end' | 'stretch';\n /** Explicit grid-row value — overrides row-span (e.g. '1 / 3', 'span 2'). */\n row?: string;\n /** Span N rows. Use 'full' to span all rows (1 / -1). */\n rowSpan?: '1' | '2' | '3' | '4' | '5' | '6' | 'full';\n};\n\n/**\n * bit-grid-item — A grid cell with declarative placement and span control.\n *\n * Use `col-span` / `row-span` for the common case of spanning columns/rows.\n * Use `col` / `row` for full CSS grid-column / grid-row shorthand power\n * (e.g. explicit placement, mixed span + start, negative lines).\n *\n * @element bit-grid-item\n *\n * @attr {string} col-span - Columns to span: '1'–'12' | 'full'\n * @attr {string} row-span - Rows to span: '1'–'6' | 'full'\n * @attr {string} col - CSS grid-column value (overrides col-span)\n * @attr {string} row - CSS grid-row value (overrides row-span)\n * @attr {string} align - align-self: 'start' | 'center' | 'end' | 'stretch'\n * @attr {string} justify - justify-self: 'start' | 'center' | 'end' | 'stretch'\n *\n * @slot - Grid item content\n *\n * @example\n * <!-- Span 2 columns -->\n * <bit-grid-item col-span=\"2\">Wide</bit-grid-item>\n *\n * @example\n * <!-- Full-width row -->\n * <bit-grid-item col-span=\"full\">Banner</bit-grid-item>\n *\n * @example\n * <!-- Explicit placement -->\n * <bit-grid-item col=\"2 / 5\" row=\"1 / 3\">Placed</bit-grid-item>\n */\nexport const GRID_ITEM_TAG = defineComponent<BitGridItemProps>({\n props: {\n align: { default: undefined },\n col: { default: '' },\n colSpan: { default: undefined },\n justify: { default: undefined },\n row: { default: '' },\n rowSpan: { default: undefined },\n },\n setup({ host, props }) {\n effect(() => {\n const col = props.col.value;\n const span = props.colSpan.value;\n\n if (col) {\n host.style.setProperty('grid-column', col);\n } else if (span === 'full') {\n host.style.setProperty('grid-column', '1 / -1');\n } else if (span) {\n host.style.setProperty('grid-column', `span ${span}`);\n } else {\n host.style.removeProperty('grid-column');\n }\n });\n effect(() => {\n const row = props.row.value;\n const span = props.rowSpan.value;\n\n if (row) {\n host.style.setProperty('grid-row', row);\n } else if (span === 'full') {\n host.style.setProperty('grid-row', '1 / -1');\n } else if (span) {\n host.style.setProperty('grid-row', `span ${span}`);\n } else {\n host.style.removeProperty('grid-row');\n }\n });\n\n return html`<slot></slot>`;\n },\n styles: [styles],\n tag: 'bit-grid-item',\n});\n","@layer buildit.base {\n :host {\n --_cols: var(--grid-cols, repeat(auto-fit, minmax(250px, 1fr)));\n --_rows: var(--grid-rows, auto);\n --_gap: var(--grid-gap, var(--size-4));\n --_row-gap: var(--grid-row-gap, var(--_gap));\n --_col-gap: var(--grid-col-gap, var(--_gap));\n\n display: grid;\n grid-template-rows: var(--_rows);\n grid-template-columns: var(--_cols);\n grid-auto-flow: row;\n gap: var(--_row-gap) var(--_col-gap);\n }\n\n :host([gap='none']) {\n --_row-gap: 0;\n --_col-gap: 0;\n }\n\n :host([gap='xs']) {\n --_row-gap: var(--size-1);\n --_col-gap: var(--size-1);\n }\n\n :host([gap='sm']) {\n --_row-gap: var(--size-2);\n --_col-gap: var(--size-2);\n }\n\n :host([gap='md']) {\n --_row-gap: var(--size-4);\n --_col-gap: var(--size-4);\n }\n\n :host([gap='lg']) {\n --_row-gap: var(--size-6);\n --_col-gap: var(--size-6);\n }\n\n :host([gap='xl']) {\n --_row-gap: var(--size-8);\n --_col-gap: var(--size-8);\n }\n\n :host([gap='2xl']) {\n --_row-gap: var(--size-12);\n --_col-gap: var(--size-12);\n }\n\n :host([align='start']) {\n align-items: start;\n }\n\n :host([align='center']) {\n align-items: center;\n }\n\n :host([align='end']) {\n align-items: end;\n }\n\n :host([align='stretch']) {\n align-items: stretch;\n }\n\n :host([align='baseline']) {\n align-items: baseline;\n }\n\n :host([justify='start']) {\n justify-items: start;\n }\n\n :host([justify='center']) {\n justify-items: center;\n }\n\n :host([justify='end']) {\n justify-items: end;\n }\n\n :host([justify='stretch']) {\n justify-items: stretch;\n }\n\n :host([flow='row']) {\n grid-auto-flow: row;\n }\n\n :host([flow='column']) {\n grid-auto-flow: column;\n }\n\n :host([flow='row-dense']) {\n grid-auto-flow: row dense;\n }\n\n :host([flow='column-dense']) {\n grid-auto-flow: column dense;\n }\n\n :host([fullwidth]) {\n width: 100%;\n }\n}\n","import { defineComponent, effect, html, onMount } from '@vielzeug/craftit';\nimport { observeResize } from '@vielzeug/craftit/labs';\n\nconst BREAKPOINTS: ['cols2xl' | 'colsXl' | 'colsLg' | 'colsMd' | 'colsSm', string][] = [\n ['cols2xl', '--size-screen-2xl'],\n ['colsXl', '--size-screen-xl'],\n ['colsLg', '--size-screen-lg'],\n ['colsMd', '--size-screen-md'],\n ['colsSm', '--size-screen-sm'],\n];\n\nconst AREAS_BREAKPOINTS: ['areas2xl' | 'areasXl' | 'areasLg' | 'areasMd' | 'areasSm', string][] = [\n ['areas2xl', '--size-screen-2xl'],\n ['areasXl', '--size-screen-xl'],\n ['areasLg', '--size-screen-lg'],\n ['areasMd', '--size-screen-md'],\n ['areasSm', '--size-screen-sm'],\n];\n\nconst resolveBp = (host: HTMLElement, varName: string, fallback: number): number => {\n const raw = getComputedStyle(host).getPropertyValue(varName).trim();\n const parsed = Number.parseFloat(raw);\n\n return Number.isFinite(parsed) ? parsed : fallback;\n};\n\nconst BP_FALLBACKS: Record<string, number> = {\n '--size-screen-2xl': 1536,\n '--size-screen-lg': 1024,\n '--size-screen-md': 768,\n '--size-screen-sm': 640,\n '--size-screen-xl': 1280,\n};\n\nimport styles from './grid.css?inline';\n\ntype ColCount = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n\n/** Grid component properties */\nexport type BitGridProps = {\n /** Align items vertically */\n align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';\n /** CSS grid-template-areas value */\n areas?: string;\n /** grid-template-areas at 2xl breakpoint (≥1536px) */\n areas2xl?: string;\n /** grid-template-areas at lg breakpoint (≥1024px) */\n areasLg?: string;\n /** grid-template-areas at md breakpoint (≥768px) */\n areasMd?: string;\n /** grid-template-areas at sm breakpoint (≥640px) */\n areasSm?: string;\n /** grid-template-areas at xl breakpoint (≥1280px) */\n areasXl?: string;\n /** Number of columns: '1'-'12' | 'auto' */\n cols?: ColCount;\n /** Columns at 2xl breakpoint (≥1536px) */\n cols2xl?: ColCount;\n /** Columns at lg breakpoint (≥1024px) */\n colsLg?: ColCount;\n /** Columns at md breakpoint (≥768px) */\n colsMd?: ColCount;\n /** Columns at sm breakpoint (≥640px) */\n colsSm?: ColCount;\n /** Columns at xl breakpoint (≥1280px) */\n colsXl?: ColCount;\n /** Grid auto flow direction */\n flow?: 'row' | 'column' | 'row-dense' | 'column-dense';\n /** Stretch the grid to fill its container's full width */\n fullwidth?: boolean;\n /** Gap between items */\n gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n /** Justify items horizontally */\n justify?: 'start' | 'center' | 'end' | 'stretch';\n /** Minimum column width for responsive mode (default: 250px) */\n minColWidth?: string;\n /** Use auto-fit responsive columns */\n responsive?: boolean;\n /** Number of rows: '1'-'12' | 'auto' */\n rows?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n};\n\n/**\n * bit-grid — Flexible grid layout with responsive column control.\n *\n * Columns are computed in JS and applied as `--_cols` inline, so they respond\n * to the element's own width via ResizeObserver. CSS custom properties\n * `--grid-cols`, `--grid-rows`, `--grid-gap`, `--grid-row-gap`, `--grid-col-gap`\n * are honoured as fallbacks when no attribute is set.\n *\n * @element bit-grid\n *\n * @attr {string} cols - Column count: '1'–'12' | 'auto'\n * @attr {string} cols-sm - Columns when width ≥ 640px\n * @attr {string} cols-md - Columns when width ≥ 768px\n * @attr {string} cols-lg - Columns when width ≥ 1024px\n * @attr {string} cols-xl - Columns when width ≥ 1280px\n * @attr {string} cols-2xl - Columns when width ≥ 1536px\n * @attr {string} rows - Row count: '1'–'12' | 'auto'\n * @attr {string} gap - Gap token: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n * @attr {string} align - align-items: 'start' | 'center' | 'end' | 'stretch' | 'baseline'\n * @attr {string} justify - justify-items: 'start' | 'center' | 'end' | 'stretch'\n * @attr {string} flow - grid-auto-flow: 'row' | 'column' | 'row-dense' | 'column-dense'\n * @attr {boolean} responsive - Enables auto-fit columns without a fixed count\n * @attr {string} min-col-width - Min column width for responsive mode (default: 250px)\n * @attr {boolean} fullwidth - Stretch the grid to fill its container's full width\n * @attr {string} areas - CSS grid-template-areas value (e.g. \"'header header' 'nav main'\")\n * @attr {string} areas-sm - grid-template-areas when width ≥ 640px\n * @attr {string} areas-md - grid-template-areas when width ≥ 768px\n * @attr {string} areas-lg - grid-template-areas when width ≥ 1024px\n * @attr {string} areas-xl - grid-template-areas when width ≥ 1280px\n * @attr {string} areas-2xl - grid-template-areas when width ≥ 1536px\n *\n * @slot - Grid items\n *\n * @cssprop --grid-cols - Fallback column template (used when no cols attr is set)\n * @cssprop --grid-rows - Fallback row template\n * @cssprop --grid-gap - Fallback gap\n * @cssprop --grid-row-gap - Fallback row gap\n * @cssprop --grid-col-gap - Fallback column gap\n *\n * @example\n * <bit-grid cols=\"1\" cols-sm=\"2\" cols-lg=\"4\" gap=\"md\">\n * <div>Item</div>\n * </bit-grid>\n *\n * @example\n * <!-- Responsive auto-fit -->\n * <bit-grid responsive min-col-width=\"200px\" gap=\"sm\">\n * <div>Card</div>\n * </bit-grid>\n *\n * @example\n * <!-- Named grid areas -->\n * <bit-grid cols=\"2\" rows=\"2\" areas=\"'header header' 'nav main'\">\n * <header style=\"grid-area: header\">Header</header>\n * <nav style=\"grid-area: nav\">Nav</nav>\n * <main style=\"grid-area: main\">Main</main>\n * </bit-grid>\n */\nexport const GRID_TAG = defineComponent<BitGridProps>({\n props: {\n align: { default: undefined },\n areas: { default: '' },\n areas2xl: { default: '' },\n areasLg: { default: '' },\n areasMd: { default: '' },\n areasSm: { default: '' },\n areasXl: { default: '' },\n cols: { default: undefined },\n cols2xl: { default: undefined },\n colsLg: { default: undefined },\n colsMd: { default: undefined },\n colsSm: { default: undefined },\n colsXl: { default: undefined },\n flow: { default: undefined },\n fullwidth: { default: false },\n gap: { default: undefined },\n justify: { default: undefined },\n minColWidth: { default: '' },\n responsive: { default: false },\n rows: { default: undefined },\n },\n setup({ host, props }) {\n const computeCols = (activeCols: string | undefined, responsive: boolean, minW: string): string | null => {\n if (activeCols === 'auto' || (!activeCols && responsive)) {\n return `repeat(auto-fit, minmax(${minW || '250px'}, 1fr))`;\n }\n\n return activeCols ? `repeat(${activeCols}, 1fr)` : null;\n };\n const updateCols = () => {\n const w = host.offsetWidth;\n const responsive = Boolean(props.responsive.value);\n const minW = props.minColWidth.value ?? '';\n let activeCols: string | undefined;\n\n for (const [key, cssVar] of BREAKPOINTS) {\n if (w >= resolveBp(host, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n activeCols = props[key].value!;\n break;\n }\n }\n activeCols ||= props.cols.value || undefined;\n\n const colsValue = computeCols(activeCols, responsive, minW);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n colsValue ? host.style.setProperty('--_cols', colsValue) : host.style.removeProperty('--_cols');\n };\n\n // Re-run cols whenever any responsive prop changes\n effect(() => {\n void [\n props.cols.value,\n props.colsSm.value,\n props.colsMd.value,\n props.colsLg.value,\n props.colsXl.value,\n props.cols2xl.value,\n props.responsive.value,\n props.minColWidth.value,\n ];\n updateCols();\n });\n\n const updateAreas = () => {\n const w = host.offsetWidth;\n let active = '';\n\n for (const [key, cssVar] of AREAS_BREAKPOINTS) {\n if (w >= resolveBp(host, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n active = props[key].value!;\n break;\n }\n }\n active ||= props.areas.value || '';\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n active ? host.style.setProperty('grid-template-areas', active) : host.style.removeProperty('grid-template-areas');\n };\n\n // Also, update on element resize (drives breakpoint switching)\n onMount(() => {\n const size = observeResize(host);\n\n effect(() => {\n void size.value;\n updateCols();\n updateAreas();\n });\n });\n // Rows\n effect(() => {\n const rows = props.rows.value;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n rows && rows !== 'auto'\n ? host.style.setProperty('--_rows', `repeat(${rows}, 1fr)`)\n : host.style.removeProperty('--_rows');\n });\n // Grid template areas (responsive)\n effect(() => {\n void [\n props.areas.value,\n props.areasSm.value,\n props.areasMd.value,\n props.areasLg.value,\n props.areasXl.value,\n props.areas2xl.value,\n ];\n updateAreas();\n });\n\n return html`<slot></slot>`;\n },\n styles: [styles],\n tag: 'bit-grid',\n});\n","@layer buildit.base {\n :host {\n --_sidebar-width: var(--sidebar-width, 16rem);\n --_sidebar-collapsed-width: var(--sidebar-collapsed-width, 3.5rem);\n --_sidebar-transition: var(--transition-normal);\n --_panel-bg: var(\n --sidebar-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 85%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 85%, transparent)\n )\n );\n --_panel-blur: var(--sidebar-panel-blur, var(--blur-md));\n --_panel-border-color: var(\n --sidebar-border-color,\n light-dark(\n color-mix(in srgb, var(--color-contrast-900) 8%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 8%, transparent)\n )\n );\n --_panel-radius: var(--sidebar-radius, 0);\n --_panel-shadow: var(--sidebar-shadow, var(--shadow-xl));\n\n box-sizing: border-box;\n display: block;\n width: 100%;\n min-width: var(--size-2xs);\n max-width: var(--_sidebar-width);\n height: 100%;\n min-height: 0;\n overflow: visible;\n transition: var(--_motion-transition, width var(--_sidebar-transition), min-width var(--_sidebar-transition));\n }\n\n :host > nav {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_panel-radius);\n box-shadow: var(--_panel-shadow);\n backdrop-filter: blur(var(--_panel-blur));\n }\n\n :host([data-collapsed]) {\n width: var(--_sidebar-collapsed-width);\n min-width: var(--_sidebar-collapsed-width);\n max-width: var(--_sidebar-collapsed-width);\n }\n\n .sidebar-header {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n min-height: var(--size-14);\n padding: var(--size-2);\n overflow: hidden;\n border-bottom: var(--border) solid var(--color-contrast-200);\n }\n\n .sidebar-header slot {\n display: block;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sidebar-content {\n display: grid;\n flex: 1;\n grid-template-columns: minmax(0, 1fr);\n gap: var(--size-2);\n align-content: start;\n min-width: 0;\n padding: var(--size-4);\n overflow: clip auto;\n scrollbar-width: thin;\n }\n\n .sidebar-footer {\n flex-shrink: 0;\n padding: var(--size-4);\n border-top: var(--border) solid var(--color-contrast-200);\n }\n\n .toggle-btn {\n all: unset;\n box-sizing: border-box;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-8);\n height: var(--size-8);\n margin-inline-start: auto;\n color: var(--color-contrast-500);\n cursor: pointer;\n border-radius: var(--rounded-sm);\n transition:\n color var(--transition-fast),\n background var(--transition-fast);\n }\n\n .toggle-btn:hover {\n color: var(--color-contrast-800);\n background: var(--color-contrast-200);\n }\n\n .toggle-btn:focus-visible {\n outline: var(--focus-ring);\n }\n\n .toggle-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n transition: var(--_motion-transition, transform var(--_sidebar-transition));\n }\n\n :host([data-collapsed]) .toggle-icon {\n transform: rotate(180deg);\n }\n\n :host(:not([dir='rtl'])[data-collapsed]) .toggle-icon,\n :host(:dir(ltr)[data-collapsed]) .toggle-icon {\n transform: rotate(180deg);\n }\n\n :host(:dir(rtl)) .toggle-icon {\n transform: rotate(180deg);\n }\n\n :host(:dir(rtl)[data-collapsed]) .toggle-icon {\n transform: rotate(0deg);\n }\n}\n\n@layer buildit.variants {\n /* ── floating ── */\n :host([variant='floating']) {\n height: calc(100% - var(--size-4));\n margin: var(--size-2);\n\n --_panel-radius: var(--rounded-xl);\n }\n\n /* ── inset ── */\n :host([variant='inset']) {\n --_panel-bg: var(--color-contrast-50);\n --_panel-shadow: none;\n --_panel-border-color: transparent;\n }\n}\n","@layer buildit.base {\n :host {\n display: block;\n width: 100%;\n }\n\n .group {\n display: block;\n }\n\n .group-header {\n all: unset;\n position: relative;\n box-sizing: border-box;\n display: flex;\n gap: var(--size-2);\n align-items: center;\n justify-content: flex-start;\n width: 100%;\n min-height: var(--size-8);\n padding: var(--size-1) var(--size-2);\n color: inherit;\n cursor: pointer;\n user-select: none;\n outline: none;\n border-radius: var(--rounded-sm);\n transition: background var(--transition-fast);\n }\n\n .group-header::-webkit-details-marker {\n display: none;\n }\n\n /* Only show hover & focus when the group is collapsible */\n :host([collapsible]) .group-header:hover {\n background: var(--color-contrast-100);\n }\n\n :host([collapsible]) .group-header:focus-visible {\n outline: var(--focus-ring);\n }\n\n :host(:not([collapsible])) .group-header {\n cursor: default;\n }\n\n .group-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--text-xs);\n font-weight: var(--font-semibold);\n color: var(--color-contrast-500);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n white-space: nowrap;\n transition: opacity var(--transition-fast);\n }\n\n .group-icon {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n color: var(--color-contrast-400);\n }\n\n .chevron {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n color: var(--color-contrast-400);\n transition: var(--_motion-transition, transform var(--transition-normal));\n }\n\n :host([collapsible][open]) .chevron {\n transform: rotate(90deg);\n }\n\n .group-items {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: var(--size-0-5);\n min-width: 0;\n }\n\n /* Collapsed-sidebar: hide label text but keep icon */\n :host([sidebar-collapsed]) .group-label,\n :host([sidebar-collapsed]) .chevron {\n pointer-events: none;\n opacity: 0;\n }\n}\n\n@layer buildit.variants {\n /* When the parent sidebar is collapsed, center the group icon */\n :host([sidebar-collapsed]) .group-header {\n justify-content: center;\n padding-inline: var(--size-2);\n }\n}\n","@layer buildit.base {\n :host {\n display: block;\n min-width: 0;\n max-width: 100%;\n }\n\n .item {\n position: relative;\n box-sizing: border-box;\n display: flex;\n gap: var(--size-2);\n align-items: center;\n min-width: 0;\n min-height: var(--_touch-target);\n padding: var(--size-1-5) var(--size-2);\n font-size: var(--sidebar-item-font-size, var(--text-sm));\n font-weight: var(--font-medium);\n color: var(--sidebar-item-color, var(--color-contrast-700));\n text-decoration: none;\n cursor: pointer;\n user-select: none;\n outline: none;\n border-radius: var(--rounded-sm);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n }\n\n /* Make <a> items look like the container */\n a.item {\n text-decoration: none;\n }\n\n .item:hover {\n color: var(--sidebar-item-hover-color, var(--color-contrast-900));\n background: var(--sidebar-item-hover-bg, var(--color-contrast-100));\n }\n\n .item:focus-visible {\n outline: var(--focus-ring);\n outline-offset: 1px;\n }\n\n :host([active]) .item {\n font-weight: var(--font-semibold);\n color: var(--sidebar-item-active-color, var(--color-primary));\n background: var(\n --sidebar-item-active-bg,\n var(--color-primary-100, color-mix(in srgb, var(--color-primary) 12%, transparent))\n );\n }\n\n :host([active]) .item::before {\n position: absolute;\n inset-block: var(--size-1);\n inset-inline-start: 0;\n width: 3px;\n content: '';\n background: var(--sidebar-item-indicator, var(--color-primary));\n border-radius: var(--rounded-full);\n }\n\n :host([disabled]) .item {\n pointer-events: none;\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n .item-icon {\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-5);\n height: var(--size-5);\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n transition: opacity var(--transition-fast);\n }\n\n .item-end {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-1);\n align-items: center;\n transition: opacity var(--transition-fast);\n }\n\n /* Collapsed sidebar: hide text/end content */\n :host([sidebar-collapsed]) .item-label,\n :host([sidebar-collapsed]) .item-end {\n width: 0;\n overflow: hidden;\n pointer-events: none;\n opacity: 0;\n }\n\n :host([sidebar-collapsed]) .item {\n gap: 0;\n justify-content: center;\n padding: var(--size-2) var(--size-4);\n }\n\n :host([sidebar-collapsed][active]) .item::before {\n inset-block: var(--size-2);\n }\n}\n","import {\n computed,\n createContext,\n defineComponent,\n effect,\n html,\n inject,\n onMount,\n provide,\n signal,\n type ReadonlySignal,\n watch,\n} from '@vielzeug/craftit';\n\nimport { chevronLeftIcon, chevronRightIcon } from '../../icons';\nimport { coarsePointerMixin, reducedMotionMixin } from '../../styles';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\ntype SidebarVariant = 'floating' | 'inset';\ntype SidebarCollapseSource = 'api' | 'responsive' | 'toggle';\n\n/** Context provided by `bit-sidebar` to its `bit-sidebar-group` and `bit-sidebar-item` children. */\nexport type SidebarContext = {\n collapsed: ReadonlySignal<boolean>;\n variant: ReadonlySignal<SidebarVariant | undefined>;\n};\n\n/** Injection key for the sidebar context. */\nexport const SIDEBAR_CTX = createContext<SidebarContext>('SidebarContext');\n\n// ─── bit-sidebar styles ──────────────────────────────────────────────────────\n\nimport sidebarStyles from './sidebar.css?inline';\n\n/** bit-sidebar element interface */\nexport type SidebarElement = HTMLElement &\n BitSidebarProps & {\n /** Set collapsed state imperatively. */\n setCollapsed(next: boolean): void;\n /** Toggle between collapsed and expanded. */\n toggle(): void;\n };\n\n/** Sidebar component properties */\n\nexport type BitSidebarEvents = {\n 'collapsed-change': { collapsed: boolean; source: SidebarCollapseSource };\n};\n\nexport type BitSidebarGroupEvents = {\n 'open-change': { open: boolean };\n};\n\nexport type BitSidebarProps = {\n /** Controlled collapsed state */\n collapsed?: boolean;\n /** Whether the sidebar supports collapsing */\n collapsible?: boolean;\n /** Initial collapsed state in uncontrolled mode */\n 'default-collapsed'?: boolean;\n /**\n * Accessible label for the navigation landmark.\n * Use to distinguish multiple navigation regions on a page.\n * @default 'Sidebar navigation'\n */\n label?: string;\n /**\n * CSS media query that, when it matches, automatically collapses the sidebar.\n * Unset by default — no automatic collapse.\n * @example 'responsive=\"(max-width: 768px)\"'\n */\n responsive?: string;\n /** Visual style variant */\n variant?: SidebarVariant;\n};\n\n/**\n * `bit-sidebar` — A collapsible navigation sidebar with group and item support.\n *\n * @element bit-sidebar\n *\n * @attr {boolean} collapsed - Controlled collapsed state\n * @attr {boolean} default-collapsed - Initial collapsed state for uncontrolled sidebars\n * @attr {boolean} collapsible - Show the collapse toggle button\n * @attr {string} variant - Visual variant: 'floating' | 'inset'\n * @attr {string} label - Accessible aria-label for the nav landmark\n *\n * @slot header - Branding or logo content above the nav\n * @slot - Navigation content (bit-sidebar-group / bit-sidebar-item)\n * @slot footer - Footer content below the nav (user info, settings, etc.)\n *\n * @fires collapsed-change - Fired when collapsed state changes\n *\n * @cssprop --sidebar-width - Expanded sidebar width (default: 16rem)\n * @cssprop --sidebar-collapsed-width - Collapsed sidebar width (default: 3.5rem)\n * @cssprop --sidebar-bg - Sidebar background color\n * @cssprop --sidebar-border-color - Border color\n *\n * @attr {string} responsive - CSS media query that auto-collapses the sidebar when it matches (e.g. '(max-width: 768px)')\n *\n * @example\n * ```html\n * <bit-sidebar collapsible label=\"App navigation\">\n * <span slot=\"header\">My App</span>\n * <bit-sidebar-group label=\"Main\">\n * <bit-sidebar-item href=\"/dashboard\" active>Dashboard</bit-sidebar-item>\n * <bit-sidebar-item href=\"/settings\">Settings</bit-sidebar-item>\n * </bit-sidebar-group>\n * </bit-sidebar>\n *\n * <!-- Auto-collapse on mobile -->\n * <bit-sidebar collapsible responsive=\"(max-width: 768px)\">...</bit-sidebar>\n * ```\n */\nexport const SIDEBAR_TAG = defineComponent<BitSidebarProps, BitSidebarEvents>({\n props: {\n collapsed: { default: undefined, type: Boolean },\n collapsible: { default: false, type: Boolean },\n 'default-collapsed': { default: false, type: Boolean },\n label: { default: 'Sidebar navigation' },\n responsive: { default: undefined },\n variant: { default: undefined },\n },\n setup({ emit, host, props, slots }) {\n const hasHeader = computed(() => slots.has('header').value);\n const hasFooter = computed(() => slots.has('footer').value);\n\n const isControlled = signal(host.hasAttribute('collapsed'));\n const collapsedState = signal(\n isControlled.value ? host.hasAttribute('collapsed') : props['default-collapsed'].value,\n );\n\n const isCollapsed = computed(() => collapsedState.value);\n\n provide(SIDEBAR_CTX, {\n collapsed: isCollapsed as ReadonlySignal<boolean>,\n variant: props.variant as ReadonlySignal<SidebarVariant | undefined>,\n });\n\n const setCollapsed = (next: boolean, source: SidebarCollapseSource) => {\n if (isCollapsed.value === next) return;\n\n if (!isControlled.value) {\n collapsedState.value = next;\n }\n\n emit('collapsed-change', { collapsed: next, source });\n };\n const doToggle = () => {\n setCollapsed(!isCollapsed.value, 'toggle');\n };\n\n effect(() => {\n host.toggleAttribute('data-collapsed', isCollapsed.value);\n });\n\n onMount(() => {\n const el = host as SidebarElement;\n\n el.setCollapsed = (next) => setCollapsed(Boolean(next), 'api');\n el.toggle = doToggle;\n\n let mediaCleanup: (() => void) | undefined;\n const observer = new MutationObserver(() => {\n if (!host.hasAttribute('collapsed') && !isControlled.value) return;\n\n isControlled.value = true;\n collapsedState.value = host.hasAttribute('collapsed');\n });\n\n observer.observe(host, {\n attributeFilter: ['collapsed'],\n attributes: true,\n });\n\n watch(\n props.responsive,\n (query) => {\n mediaCleanup?.();\n mediaCleanup = undefined;\n\n const mediaQuery = String(query ?? '').trim();\n\n if (!mediaQuery) return;\n\n const mql = window.matchMedia(mediaQuery);\n const onChange = (event: MediaQueryListEvent) => {\n setCollapsed(event.matches, 'responsive');\n };\n\n setCollapsed(mql.matches, 'responsive');\n mql.addEventListener('change', onChange);\n\n mediaCleanup = () => {\n mql.removeEventListener('change', onChange);\n };\n },\n { immediate: true },\n );\n\n return () => {\n observer.disconnect();\n mediaCleanup?.();\n };\n });\n\n return html`\n <nav aria-label=\"${() => props.label.value}\" part=\"nav\">\n <div class=\"sidebar-header\" part=\"header\" ?hidden=${() => !hasHeader.value && !props.collapsible.value}>\n <slot name=\"header\"></slot>\n <button\n class=\"toggle-btn\"\n part=\"toggle-btn\"\n type=\"button\"\n ?hidden=${() => !props.collapsible.value}\n aria-label=\"${() => (isCollapsed.value ? 'Expand sidebar' : 'Collapse sidebar')}\"\n aria-expanded=\"${() => String(!isCollapsed.value)}\"\n @click=\"${doToggle}\">\n <span class=\"toggle-icon\" aria-hidden=\"true\">${chevronLeftIcon}</span>\n </button>\n </div>\n <div class=\"sidebar-content\" part=\"content\">\n <slot></slot>\n </div>\n <div class=\"sidebar-footer\" part=\"footer\" ?hidden=${() => !hasFooter.value}>\n <slot name=\"footer\"></slot>\n </div>\n </nav>\n `;\n },\n styles: [coarsePointerMixin, reducedMotionMixin, sidebarStyles],\n tag: 'bit-sidebar',\n});\n\n// ─── bit-sidebar-group styles ────────────────────────────────────────────────\n\nimport groupStyles from './sidebar-group.css?inline';\n\n/** Sidebar group properties */\nexport type BitSidebarGroupProps = {\n /** Whether this group can be collapsed */\n collapsible?: boolean;\n /** Initial open state in uncontrolled mode */\n 'default-open'?: boolean;\n /** Accessible label for the group */\n label?: string;\n /** Controlled open state */\n open?: boolean;\n};\n\n/**\n * `bit-sidebar-group` — A labelled section within `bit-sidebar`.\n *\n * @element bit-sidebar-group\n *\n * @attr {string} label - Group label text\n * @attr {boolean} collapsible - Whether this group can be toggled open/closed\n * @attr {boolean} open - Controlled expanded state\n * @attr {boolean} default-open - Initial expanded state in uncontrolled mode\n *\n * @slot - Navigation items (`bit-sidebar-item`)\n * @slot icon - Icon displayed before the label\n *\n * @fires open-change - Fired when the group open state changes (collapsible groups only)\n *\n * @example\n * ```html\n * <bit-sidebar-group label=\"Main\" collapsible open>\n * <bit-sidebar-item href=\"/home\">Home</bit-sidebar-item>\n * </bit-sidebar-group>\n * ```\n */\nexport const SIDEBAR_GROUP_TAG = defineComponent<BitSidebarGroupProps, BitSidebarGroupEvents>({\n props: {\n collapsible: { default: false, type: Boolean },\n 'default-open': { default: true, type: Boolean },\n label: { default: '' },\n open: { default: undefined, type: Boolean },\n },\n setup({ emit, host, props, slots }) {\n const hasIcon = computed(() => slots.has('icon').value);\n const sidebarCtx = inject(SIDEBAR_CTX, undefined);\n\n effect(() => {\n host.toggleAttribute('sidebar-collapsed', sidebarCtx?.collapsed.value ?? false);\n });\n\n const isControlled = computed(() => props.open.value !== undefined);\n const openState = signal(props['default-open'].value);\n const isOpen = computed(() => {\n if (!props.collapsible.value) return true;\n\n if (isControlled.value) return props.open.value ?? false;\n\n return openState.value;\n });\n\n watch(props.open, (value) => {\n if (value === undefined) return;\n\n openState.value = value;\n });\n\n effect(() => {\n host.toggleAttribute('open', isOpen.value);\n });\n\n const handleGroupClick = (e: MouseEvent) => {\n if (!(e.target instanceof HTMLElement) || !e.target.closest('.group-header')) return;\n\n e.stopPropagation();\n e.preventDefault();\n\n if (!props.collapsible.value) {\n return;\n }\n\n const next = !isOpen.value;\n\n if (props.open.value === next) return;\n\n if (!isControlled.value) {\n openState.value = next;\n }\n\n emit('open-change', { open: next });\n };\n\n return html`\n <details class=\"group\" part=\"group\" ?open=${() => isOpen.value} @click=\"${handleGroupClick}\">\n <summary\n class=\"group-header\"\n part=\"group-header\"\n :aria-expanded=\"${() => (props.collapsible.value ? String(props.open.value) : null)}\">\n <span class=\"group-icon\" part=\"group-icon\" ?hidden=${() => !hasIcon.value} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"group-label\" part=\"group-label\">${() => props.label.value}</span>\n <span class=\"chevron\" ?hidden=${() => !props.collapsible.value} aria-hidden=\"true\">${chevronRightIcon}</span>\n </summary>\n <div class=\"group-items\" part=\"group-items\" role=\"list\">\n <slot></slot>\n </div>\n </details>\n `;\n },\n styles: [reducedMotionMixin, groupStyles],\n tag: 'bit-sidebar-group',\n});\n\n// ─── bit-sidebar-item styles ─────────────────────────────────────────────────\n\nimport itemStyles from './sidebar-item.css?inline';\n\n/** Sidebar item properties */\nexport type BitSidebarItemProps = {\n /** Whether this item represents the current page/section */\n active?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Navigation href — renders an `<a>` when set, otherwise a `<button>` */\n href?: string;\n /**\n * Relationship of the linked URL (`rel` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n rel?: string;\n /**\n * Browsing context for the link (`target` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n target?: string;\n};\n\n/**\n * `bit-sidebar-item` — An individual navigation item in a `bit-sidebar`.\n *\n * Renders as an `<a>` when `href` is provided, otherwise as a `<button>`.\n * Marks the active page via `aria-current=\"page\"` when the `active` attribute is set.\n *\n * @element bit-sidebar-item\n *\n * @attr {string} href - Link URL; renders an anchor when set\n * @attr {boolean} active - Marks the item as the current page\n * @attr {boolean} disabled - Disables the item\n * @attr {string} rel - Anchor `rel` attribute (links only)\n * @attr {string} target - Anchor `target` attribute (links only)\n *\n * @slot - Label text\n * @slot icon - Leading icon\n * @slot end - Trailing content (badge, shortcut, arrow, etc.)\n *\n * @part item - The inner anchor or button element\n * @part item-icon - The icon wrapper\n * @part item-label - The label wrapper\n * @part item-end - The trailing content wrapper\n *\n * @cssprop --sidebar-item-color - Default text color\n * @cssprop --sidebar-item-hover-bg - Hover background\n * @cssprop --sidebar-item-hover-color - Hover text color\n * @cssprop --sidebar-item-active-bg - Active background\n * @cssprop --sidebar-item-active-color - Active text color\n * @cssprop --sidebar-item-indicator - Active indicator bar color\n *\n * @example\n * ```html\n * <bit-sidebar-item href=\"/dashboard\" active>\n * <span slot=\"icon\">🏠</span>\n * Dashboard\n * </bit-sidebar-item>\n *\n * <bit-sidebar-item href=\"/users\">\n * <span slot=\"icon\">👤</span>\n * Users\n * <bit-badge slot=\"end\" color=\"primary\">3</bit-badge>\n * </bit-sidebar-item>\n * ```\n */\nexport const SIDEBAR_ITEM_TAG = defineComponent<BitSidebarItemProps>({\n props: {\n active: { default: false, type: Boolean },\n disabled: { default: false, type: Boolean },\n href: { default: undefined },\n rel: { default: undefined },\n target: { default: undefined },\n },\n setup({ host, props, slots }) {\n const hasIcon = computed(() => slots.has('icon').value);\n const hasEnd = computed(() => slots.has('end').value);\n const sidebarCtx = inject(SIDEBAR_CTX, undefined);\n\n effect(() => {\n host.toggleAttribute('sidebar-collapsed', sidebarCtx?.collapsed.value ?? false);\n });\n\n const isLink = computed(() => !!props.href.value && !props.disabled.value);\n const renderItemContent = () => html`\n <span class=\"item-icon\" part=\"item-icon\" ?hidden=${() => !hasIcon.value} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"item-label\" part=\"item-label\"><slot></slot></span>\n <span class=\"item-end\" part=\"item-end\" ?hidden=${() => !hasEnd.value}>\n <slot name=\"end\"></slot>\n </span>\n `;\n\n return html`\n ${() =>\n isLink.value\n ? html`\n <a\n class=\"item\"\n part=\"item\"\n href=\"${() => props.href.value}\"\n :rel=\"${() => props.rel.value ?? null}\"\n :target=\"${() => props.target.value ?? null}\"\n :aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </a>\n `\n : html`\n <button\n class=\"item\"\n part=\"item\"\n type=\"button\"\n :aria-current=\"${() => (props.active.value ? 'page' : null)}\"\n :disabled=\"${() => props.disabled.value || null}\">\n ${renderItemContent()}\n </button>\n `}\n `;\n },\n styles: [coarsePointerMixin, itemStyles],\n tag: 'bit-sidebar-item',\n});\n","/**\n * Shared background-lock utility for overlay components (dialog, drawer, etc.).\n *\n * Uses a reference count so that multiple stacked overlays each call\n * lockBackground / unlockBackground independently without interfering with\n * each other. The `inert` attribute is applied once when the first overlay\n * opens and removed once the last one closes.\n */\n\nlet lockCount = 0;\nlet lockedEls: Element[] = [];\n\n/**\n * Marks all `document.body` children except the direct ancestor of `host` as\n * `inert`. Safe to call from multiple overlays at once — only the first call\n * actually mutates the DOM.\n */\nexport function lockBackground(host: Element): void {\n if (lockCount === 0) {\n let ancestor: Element = host;\n\n while (ancestor.parentElement && ancestor.parentElement !== document.body) {\n ancestor = ancestor.parentElement;\n }\n\n lockedEls = Array.from(document.body.children).filter((el) => el !== ancestor && !el.hasAttribute('inert'));\n\n for (const el of lockedEls) el.setAttribute('inert', '');\n }\n\n lockCount++;\n}\n\n/**\n * Decrements the lock count. When it reaches zero, removes `inert` from all\n * elements that were locked by `lockBackground`.\n */\nexport function unlockBackground(): void {\n lockCount = Math.max(0, lockCount - 1);\n\n if (lockCount === 0) {\n for (const el of lockedEls) el.removeAttribute('inert');\n lockedEls = [];\n }\n}\n","import { type ReadonlySignal } from '@vielzeug/craftit';\n\nimport { awaitExit } from './animation';\n\nexport interface OverlayProps {\n 'initial-focus': ReadonlySignal<string | undefined>;\n 'return-focus': ReadonlySignal<boolean | undefined>;\n}\n\n/**\n * Shared overlay composable for dialog-based components.\n *\n * Encapsulates the `returnFocusEl` variable, `applyInitialFocus`, the guarded\n * `closeWithAnimation` (with `isClosing` flag to prevent double-close), and\n * the focus-restore helper so that `bit-dialog` and `bit-drawer` don't repeat\n * this logic.\n *\n * Call at **setup scope** (outside `onMount`) so that the returned\n * `closeWithAnimation` is available before mount (e.g. to expose as an\n * imperative API or use inside `requestClose`).\n */\nexport function useOverlay(\n host: HTMLElement,\n dialogRef: { value: HTMLDialogElement | null | undefined },\n getPanelEl: () => HTMLElement | null | undefined,\n props: OverlayProps,\n) {\n let returnFocusEl: HTMLElement | null = null;\n let isClosing = false;\n\n const captureReturnFocus = () => {\n returnFocusEl = document.activeElement as HTMLElement;\n };\n\n const restoreFocus = () => {\n if (props['return-focus'].value !== false && returnFocusEl) {\n returnFocusEl.focus();\n returnFocusEl = null;\n }\n };\n\n const applyInitialFocus = () => {\n const selector = props['initial-focus'].value;\n\n if (selector) {\n const target = host.querySelector<HTMLElement>(selector);\n\n if (target) requestAnimationFrame(() => target.focus());\n }\n };\n\n const closeWithAnimation = () => {\n const dialog = dialogRef.value;\n\n if (!dialog?.open || isClosing) return;\n\n isClosing = true;\n dialog.classList.add('closing');\n\n const finish = () => {\n dialog.classList.remove('closing');\n isClosing = false;\n dialog.close();\n };\n\n const panel = getPanelEl();\n\n if (panel) {\n awaitExit(panel, finish, 'transition');\n } else {\n finish();\n }\n };\n\n return {\n applyInitialFocus,\n captureReturnFocus,\n closeWithAnimation,\n restoreFocus,\n };\n}\n","@layer buildit.base {\n :host {\n --_radius: var(--dialog-radius, var(--rounded-lg));\n --_padding: var(--dialog-padding, var(--size-4));\n --_gap: var(--dialog-gap, var(--size-4));\n --_max-width: var(--dialog-max-width, 32rem);\n --_elevation: var(--shadow-xl);\n --_backdrop-filter: none;\n --_backdrop-bg: var(--dialog-backdrop, color-mix(in srgb, var(--color-canvas) 40%, transparent));\n --_panel-bg: var(\n --dialog-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 85%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 85%, transparent)\n )\n );\n --_panel-blur: var(--dialog-panel-blur, var(--blur-md));\n --_panel-border-color: var(\n --dialog-border-color,\n light-dark(\n color-mix(in srgb, var(--color-contrast-900) 8%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 8%, transparent)\n )\n );\n\n display: contents;\n }\n\n /* =====================\n Native <dialog> resets\n ===================== */\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n padding: 0;\n margin: 0;\n overflow: hidden;\n pointer-events: none;\n background: transparent;\n border: none;\n }\n\n /* all:unset removes the UA stylesheet's dialog:not([open]){display:none} — restore it */\n dialog:not([open]) {\n display: none;\n }\n\n dialog[open] {\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: var(--_backdrop-filter);\n transition: var(\n --_motion-transition,\n opacity var(--transition-normal) ease,\n overlay var(--transition-normal) ease allow-discrete,\n display var(--transition-normal) ease allow-discrete\n );\n\n @starting-style {\n opacity: 0;\n }\n }\n\n dialog.closing::backdrop {\n opacity: 0;\n }\n\n /* =====================\n Panel (the visible dialog box)\n ===================== */\n\n .panel {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--_max-width);\n max-width: calc(100vw - var(--size-8));\n max-height: calc(100dvh - var(--size-8));\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--_radius);\n box-shadow: var(--dialog-shadow, var(--_elevation));\n opacity: 1;\n backdrop-filter: blur(var(--_panel-blur));\n transform: scale(1) translateY(0);\n transition: var(\n --_motion-transition,\n opacity var(--transition-normal) cubic-bezier(0.16, 1, 0.3, 1),\n transform var(--transition-normal) cubic-bezier(0.16, 1, 0.3, 1)\n );\n\n @starting-style {\n opacity: 0;\n transform: scale(0.96) translateY(var(--size-2));\n }\n }\n\n dialog.closing .panel {\n opacity: 0;\n transform: scale(0.96) translateY(var(--size-2));\n }\n\n /* =====================\n Sizes\n ===================== */\n\n .panel[data-size='sm'] {\n --_max-width: var(--dialog-max-width, 22rem);\n }\n\n .panel[data-size='md'] {\n --_max-width: var(--dialog-max-width, 32rem);\n }\n\n .panel[data-size='lg'] {\n --_max-width: var(--dialog-max-width, 48rem);\n }\n\n .panel[data-size='xl'] {\n --_max-width: var(--dialog-max-width, 64rem);\n }\n\n .panel[data-size='full'] {\n width: calc(100vw - var(--size-8));\n max-width: calc(100vw - var(--size-8));\n max-height: calc(100dvh - var(--size-8));\n }\n\n /* =====================\n Header\n ===================== */\n\n .header {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--_padding);\n padding-bottom: 0;\n }\n\n .header[hidden] {\n display: none;\n }\n\n .title {\n flex: 1;\n font-size: var(--text-lg);\n font-weight: var(--font-semibold);\n line-height: var(--leading-tight);\n color: var(--color-contrast-900);\n }\n\n .close {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-8);\n min-width: var(--_touch-target);\n height: var(--size-8);\n min-height: var(--_touch-target);\n padding: 0;\n margin-inline-start: auto;\n color: var(--color-contrast-500);\n cursor: pointer;\n background: transparent;\n border: none;\n border-radius: var(--rounded-md);\n transition: var(--_motion-transition, background var(--transition-fast), color var(--transition-fast));\n }\n\n .close:hover {\n color: var(--color-contrast-900);\n background: var(--color-contrast-200);\n }\n\n .close:focus-visible {\n outline: var(--border-2) solid var(--color-focus);\n outline-offset: var(--border-2);\n }\n\n .close[hidden] {\n display: none;\n }\n\n /* =====================\n Body\n ===================== */\n\n .body {\n flex: 1;\n padding: var(--_padding);\n overflow-y: auto;\n overscroll-behavior: contain;\n font-size: var(--text-sm);\n line-height: var(--leading-relaxed);\n color: var(--color-contrast-700);\n }\n\n /* =====================\n Footer\n ===================== */\n\n .footer {\n display: flex;\n flex-shrink: 0;\n flex-wrap: wrap;\n gap: var(--_gap);\n align-items: center;\n justify-content: flex-end;\n padding: var(--_padding);\n padding-top: 0;\n }\n\n .footer[hidden] {\n display: none;\n }\n\n /* =====================\n Dividers when header/footer present\n ===================== */\n\n .header:not([hidden]) + .body {\n padding-top: var(--size-4);\n }\n\n .body + .footer:not([hidden]) {\n padding-top: var(--size-4);\n border-top: var(--border) solid var(--color-contrast-100);\n }\n\n @media (width <= 640px) {\n .panel,\n .panel[data-size='sm'],\n .panel[data-size='md'],\n .panel[data-size='lg'],\n .panel[data-size='xl'] {\n width: calc(100vw - var(--size-4));\n max-width: calc(100vw - var(--size-4));\n max-height: calc(100dvh - var(--size-4));\n }\n\n .header,\n .body,\n .footer {\n padding-inline: var(--size-3);\n }\n }\n}\n\n@layer buildit.config {\n :host([backdrop='blur']) {\n --_backdrop-filter: blur(var(--blur-xs));\n }\n\n :host([backdrop='transparent']) {\n --_backdrop-bg: transparent;\n }\n\n /* Panel elevation / shadow scale */\n :host([elevation='none']) {\n --_elevation: var(--shadow-none);\n }\n\n :host([elevation='sm']) {\n --_elevation: var(--shadow-sm);\n }\n\n :host([elevation='md']) {\n --_elevation: var(--shadow-md);\n }\n\n :host([elevation='lg']) {\n --_elevation: var(--shadow-lg);\n }\n\n :host([elevation='xl']) {\n --_elevation: var(--shadow-xl);\n }\n\n :host([elevation='2xl']) {\n --_elevation: var(--shadow-2xl);\n }\n\n /* Padding scale */\n :host([padding='none']) {\n --_padding: var(--size-0);\n }\n\n :host([padding='sm']) {\n --_padding: var(--size-3);\n }\n\n :host([padding='md']) {\n --_padding: var(--size-4);\n }\n\n :host([padding='lg']) {\n --_padding: var(--size-6);\n }\n\n :host([padding='xl']) {\n --_padding: var(--size-8);\n }\n}\n","import { computed, defineComponent, handle, html, onMount, ref, watch, fire } from '@vielzeug/craftit';\n\nimport type { PaddingSize, RoundedSize } from '../../types';\n\nimport { closeIcon } from '../../icons';\nimport { coarsePointerMixin, elevationMixin, reducedMotionMixin, roundedVariantMixin } from '../../styles';\nimport { awaitExit } from '../../utils/animation';\nimport { lockBackground, unlockBackground } from '../../utils/background-lock';\nimport { useOverlay } from '../../utils/use-overlay';\nimport componentStyles from './dialog.css?inline';\n\ntype DialogSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';\ntype DialogBackdrop = 'opaque' | 'blur' | 'transparent';\ntype DialogElevation = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\n/** Dialog component properties */\n\nexport type BitDialogEvents = {\n close: undefined;\n open: undefined;\n};\n\nexport type BitDialogProps = {\n /** Backdrop style — 'blur' (default): dark overlay + blur; 'opaque': dark overlay only; 'transparent': no overlay */\n backdrop?: DialogBackdrop;\n /** Show a close (×) button in the header */\n dismissible?: boolean;\n /** Panel shadow elevation — defaults to 'xl' */\n elevation?: DialogElevation;\n /**\n * CSS selector for the element inside the dialog that should receive focus when the dialog opens.\n * Defaults to the first focusable element (browser default).\n * @example 'input[name=\"email\"]' | '#confirm-btn'\n */\n 'initial-focus'?: string;\n /** Dialog title shown in the header (used as aria-label when no header slot) */\n label?: string;\n /** Controls the open state of the dialog */\n open?: boolean;\n /** Internal padding size */\n padding?: PaddingSize;\n /** When true, clicking the backdrop does not close the dialog */\n persistent?: boolean;\n /**\n * When true (default), focus returns to the element that triggered the dialog after it closes.\n * Set to false if you want to manage focus manually.\n */\n 'return-focus'?: boolean;\n /** Border radius */\n rounded?: RoundedSize | '';\n /** Dialog size */\n size?: DialogSize;\n};\n\n/**\n * A modal dialog that traps focus, blocks page interaction, and dismisses on\n * `Escape`. Built on the native `<dialog>` element for correct top-layer stacking\n * and browser-managed accessibility.\n *\n * @element bit-dialog\n *\n * @attr {boolean} open - Open/close the dialog\n * @attr {string} label - Dialog title (also used as aria-label)\n * @attr {string} size - Size: 'sm' | 'md' | 'lg' | 'xl' | 'full'\n * @attr {boolean} dismissible - Show a close (×) button in the header\n * @attr {boolean} persistent - Prevent backdrop-click from closing\n * @attr {string} rounded - Border radius size\n * @attr {string} backdrop - Backdrop style: 'opaque' (default) | 'blur' | 'transparent'\n * @attr {string} elevation - Panel shadow: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n * @attr {string} padding - Padding: 'none' | 'sm' | 'md' | 'lg' | 'xl'\n *\n * @fires open - Fired when the dialog opens\n * @fires close - Fired when the dialog closes (any trigger)\n *\n * @slot - Dialog body content\n * @slot header - Custom header content (replaces the default title + close layout)\n * @slot footer - Action buttons or additional content at the bottom\n *\n * @cssprop --dialog-bg - Panel background color\n * @cssprop --dialog-border-color - Panel border color\n * @cssprop --dialog-radius - Panel border radius\n * @cssprop --dialog-shadow - Panel drop shadow\n * @cssprop --dialog-padding - Padding for header, body, and footer sections\n * @cssprop --dialog-gap - Gap between footer action buttons\n * @cssprop --dialog-backdrop - Backdrop overlay color\n * @cssprop --dialog-max-width - Maximum panel width (overridden by size prop)\n *\n * @example\n * ```html\n * <bit-dialog label=\"Confirm action\" dismissible>\n * <p>Are you sure you want to delete this item?</p>\n * <div slot=\"footer\">\n * <bit-button variant=\"ghost\" id=\"cancel\">Cancel</bit-button>\n * <bit-button color=\"error\" id=\"confirm\">Delete</bit-button>\n * </div>\n * </bit-dialog>\n *\n * <script type=\"module\">\n * import '@vielzeug/buildit/dialog';\n * const dialog = document.querySelector('bit-dialog');\n * document.querySelector('#open-btn').addEventListener('click', () => {\n * dialog.setAttribute('open', '');\n * });\n * document.querySelector('#cancel').addEventListener('click', () => {\n * dialog.removeAttribute('open');\n * });\n * </script>\n * ```\n */\nexport const DIALOG_TAG = defineComponent<BitDialogProps, BitDialogEvents>({\n props: {\n backdrop: { default: undefined },\n dismissible: { default: false },\n elevation: { default: undefined },\n 'initial-focus': { default: undefined },\n label: { default: '' },\n open: { default: false },\n padding: { default: undefined },\n persistent: { default: false },\n 'return-focus': { default: true },\n rounded: { default: undefined },\n size: { default: 'md' },\n },\n setup({ emit, host, props, slots }) {\n const dialogRef = ref<HTMLDialogElement>();\n const hasHeader = computed(() => slots.has('header').value || !!props.label.value || props.dismissible.value);\n const hasFooter = computed(() => slots.has('footer').value);\n const { applyInitialFocus, captureReturnFocus, closeWithAnimation, restoreFocus } = useOverlay(\n host,\n dialogRef,\n () => dialogRef.value?.querySelector<HTMLElement>('.panel'),\n props,\n );\n\n onMount(() => {\n const dialog = dialogRef.value;\n\n if (!dialog) return;\n\n // Sync prop changes → native dialog\n watch(\n props.open,\n (open) => {\n if (open) {\n if (!dialog.open) {\n captureReturnFocus();\n dialog.showModal();\n applyInitialFocus();\n lockBackground(host);\n emit('open');\n }\n } else {\n closeWithAnimation();\n }\n },\n { immediate: true },\n );\n\n // Native dialog 'close' fires after animation finishes or on programmatic .close()\n const handleNativeClose = () => {\n unlockBackground();\n // Sync the open prop back to the host attribute if closed externally\n host.removeAttribute('open');\n // Return focus to the triggering element unless opted out\n restoreFocus();\n emit('close');\n };\n // Intercept Escape to play exit animation first; also enforce persistent mode\n const handleKeydown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n\n if (!props.persistent.value) {\n closeWithAnimation();\n }\n }\n };\n // Backdrop click: the click target is the <dialog> element itself (not the panel)\n const handleBackdropClick = (e: MouseEvent) => {\n if (props.persistent.value) return;\n\n // When clicking the backdrop, the event target is the <dialog> element itself.\n // Clicks inside the panel bubble up with a more specific target.\n if (e.target === dialog) {\n closeWithAnimation();\n }\n };\n\n handle(dialog, 'close', handleNativeClose);\n handle(dialog, 'click', handleBackdropClick);\n handle(dialog, 'keydown', handleKeydown);\n\n return () => {\n // Ensure the native dialog is closed on unmount to release top-layer\n if (dialog.open) dialog.close();\n\n unlockBackground();\n };\n });\n\n const handleDismiss = () => {\n const dialog = dialogRef.value;\n\n if (!dialog) return;\n\n fire.custom(dialog, 'close-request');\n dialog.classList.add('closing');\n\n const panel = dialog.querySelector<HTMLElement>('.panel');\n const finish = () => {\n dialog.classList.remove('closing');\n dialog.close();\n };\n\n if (panel) {\n awaitExit(panel, finish, 'transition');\n } else {\n finish();\n }\n };\n\n return html`\n <dialog\n ref=${dialogRef}\n class=\"dialog\"\n part=\"dialog\"\n :aria-label=\"${() => props.label.value || null}\"\n aria-modal=\"true\">\n <div class=\"overlay\" part=\"overlay\" aria-hidden=\"true\"></div>\n <div class=\"panel\" part=\"panel\" :data-size=\"${props.size}\">\n <div class=\"header\" part=\"header\" ?hidden=${() => !hasHeader.value}>\n <slot name=\"header\">\n <span class=\"title\" part=\"title\">${() => props.label.value}</span>\n </slot>\n <button\n class=\"close\"\n part=\"close\"\n type=\"button\"\n aria-label=\"Close dialog\"\n ?hidden=${() => !props.dismissible.value}\n @click=${handleDismiss}>\n ${closeIcon}\n </button>\n </div>\n <div class=\"body\" part=\"body\">\n <slot></slot>\n </div>\n <div class=\"footer\" part=\"footer\" ?hidden=${() => !hasFooter.value}>\n <slot name=\"footer\"></slot>\n </div>\n </div>\n </dialog>\n `;\n },\n styles: [elevationMixin, roundedVariantMixin, coarsePointerMixin, reducedMotionMixin, componentStyles],\n tag: 'bit-dialog',\n});\n","@layer buildit.base {\n :host {\n --_backdrop-bg: var(--drawer-backdrop, color-mix(in srgb, var(--color-canvas) 40%, transparent));\n --_backdrop-filter: none;\n --_panel-bg: var(\n --drawer-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 85%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 85%, transparent)\n )\n );\n --_panel-blur: var(--drawer-panel-blur, var(--blur-md));\n --_panel-shadow: var(--drawer-shadow, var(--shadow-xl));\n --_panel-border-color: light-dark(\n color-mix(in srgb, var(--color-contrast-900) 8%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 8%, transparent)\n );\n --_panel-bleed: var(--size-8);\n\n display: contents;\n }\n\n dialog {\n all: unset;\n position: fixed;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n width: 100%;\n max-width: 100%;\n height: 100%;\n max-height: 100%;\n pointer-events: none;\n transition:\n display var(--transition-normal) allow-discrete,\n overlay var(--transition-normal) allow-discrete;\n }\n\n dialog:not([open]) {\n display: none;\n }\n\n dialog[open] {\n display: flex;\n pointer-events: auto;\n }\n\n dialog::backdrop {\n background: var(--_backdrop-bg);\n opacity: 1;\n backdrop-filter: var(--_backdrop-filter);\n transition:\n display var(--transition-normal) allow-discrete,\n overlay var(--transition-normal) allow-discrete,\n opacity var(--transition-normal),\n backdrop-filter var(--transition-normal);\n }\n\n @starting-style {\n dialog[open]::backdrop {\n opacity: 0;\n backdrop-filter: blur(0);\n }\n }\n\n .panel {\n position: absolute;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n box-shadow: var(--_panel-shadow);\n opacity: 1;\n backdrop-filter: blur(var(--_panel-blur));\n transform: translate3d(0, 0, 0);\n transition:\n opacity var(--transition-normal),\n transform var(--transition-normal),\n display var(--transition-normal) allow-discrete;\n }\n\n @starting-style {\n dialog[open] .panel {\n opacity: 0;\n transform: var(--_panel-exit-transform, translate3d(0, 0, 0));\n }\n }\n\n /* left */\n :host([placement='left']) .panel {\n --_panel-exit-transform: translateX(calc(-100% - var(--_panel-bleed)));\n\n inset-block: 0;\n inset-inline-start: 0;\n width: calc(var(--drawer-size, 20rem) + var(--_panel-bleed));\n max-width: calc(100dvw + var(--_panel-bleed));\n padding-inline-start: var(--_panel-bleed);\n margin-inline-start: calc(var(--_panel-bleed) * -1);\n border-block: none;\n border-inline-start: none;\n }\n\n /* right (default) */\n :host(:not([placement])) .panel,\n :host([placement='right']) .panel {\n --_panel-exit-transform: translateX(calc(100% + var(--_panel-bleed)));\n\n inset-block: 0;\n inset-inline-end: 0;\n width: calc(var(--drawer-size, 20rem) + var(--_panel-bleed));\n max-width: calc(100dvw + var(--_panel-bleed));\n padding-inline-end: var(--_panel-bleed);\n margin-inline-end: calc(var(--_panel-bleed) * -1);\n border-block: none;\n border-inline-end: none;\n }\n\n /* top */\n :host([placement='top']) .panel {\n --_panel-exit-transform: translateY(calc(-100% - var(--_panel-bleed)));\n\n inset-block-start: 0;\n inset-inline: 0;\n height: calc(var(--drawer-size, 16rem) + var(--_panel-bleed));\n max-height: calc(100dvh + var(--_panel-bleed));\n padding-block-start: var(--_panel-bleed);\n margin-block-start: calc(var(--_panel-bleed) * -1);\n border-block-start: none;\n border-inline: none;\n }\n\n /* bottom */\n :host([placement='bottom']) .panel {\n --_panel-exit-transform: translateY(calc(100% + var(--_panel-bleed)));\n\n inset-block-end: 0;\n inset-inline: 0;\n height: calc(var(--drawer-size, 16rem) + var(--_panel-bleed));\n max-height: calc(100dvh + var(--_panel-bleed));\n padding-block-end: var(--_panel-bleed);\n margin-block-end: calc(var(--_panel-bleed) * -1);\n border-block-end: none;\n border-inline: none;\n }\n\n /* RTL overrides */\n :host(:dir(rtl)[placement='left']) .panel {\n --_panel-exit-transform: translateX(calc(100% + var(--_panel-bleed)));\n }\n\n :host(:dir(rtl)[placement='right']) .panel,\n :host(:dir(rtl):not([placement])) .panel {\n --_panel-exit-transform: translateX(calc(-100% - var(--_panel-bleed)));\n }\n\n /* Size utilities */\n :host([size='sm']) {\n --drawer-size: 14rem;\n }\n\n :host([size='lg']) {\n --drawer-size: 32rem;\n }\n\n :host([size='full']) {\n --drawer-size: 100%;\n }\n\n :host([size='full']) .panel {\n width: calc(100% + var(--_panel-bleed));\n max-width: none;\n height: calc(100% + var(--_panel-bleed));\n max-height: none;\n border: none;\n }\n\n /* Header / Body / Footer */\n .header {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n align-items: center;\n padding: var(--size-4);\n border-bottom: var(--border) solid var(--color-contrast-200);\n }\n\n .header-title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--text-lg);\n font-weight: var(--font-semibold);\n white-space: nowrap;\n }\n\n .body {\n flex: 1;\n padding: var(--size-4);\n overflow-y: auto;\n }\n\n .footer {\n display: flex;\n flex-shrink: 0;\n gap: var(--size-2);\n justify-content: flex-end;\n padding: var(--size-4);\n border-top: var(--border) solid var(--color-contrast-200);\n }\n\n .header[hidden],\n .footer[hidden],\n .close-btn[hidden] {\n display: none;\n }\n\n .close-btn {\n all: unset;\n box-sizing: border-box;\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: var(--size-8);\n height: var(--size-8);\n margin-inline-start: auto;\n color: var(--color-contrast-500);\n cursor: pointer;\n border-radius: var(--rounded-sm);\n transition: var(--transition-fast);\n }\n\n .close-btn:hover {\n color: var(--color-contrast-800);\n background: var(--color-contrast-200);\n }\n\n .close-btn:focus-visible {\n outline: var(--focus-ring);\n }\n\n @media (width <= 640px) {\n :host([placement='left']) .panel,\n :host(:not([placement])) .panel,\n :host([placement='right']) .panel {\n width: calc(min(var(--drawer-size, 20rem), calc(100vw - var(--size-2))) + var(--_panel-bleed));\n max-width: calc(100vw - var(--size-2) + var(--_panel-bleed));\n }\n\n :host([placement='top']) .panel,\n :host([placement='bottom']) .panel {\n height: calc(min(var(--drawer-size, 16rem), calc(100dvh - var(--size-2))) + var(--_panel-bleed));\n max-height: calc(100dvh - var(--size-2) + var(--_panel-bleed));\n }\n\n .header,\n .body,\n .footer {\n padding: var(--size-3);\n }\n }\n}\n\n@layer buildit.config {\n :host([backdrop='blur']) {\n --_backdrop-filter: blur(var(--blur-xs));\n }\n\n :host([backdrop='transparent']) {\n --_backdrop-bg: transparent;\n }\n}\n","import { computed, createId, defineComponent, fire, handle, html, onMount, ref, watch } from '@vielzeug/craftit';\n\nimport { closeIcon } from '../../icons';\nimport { coarsePointerMixin, elevationMixin, forcedColorsMixin, reducedMotionMixin } from '../../styles';\nimport { lockBackground, unlockBackground, useOverlay } from '../../utils';\nimport styles from './drawer.css?inline';\n\ntype DrawerPlacement = 'left' | 'right' | 'top' | 'bottom';\ntype DrawerSize = 'sm' | 'lg' | 'full';\ntype DrawerBackdrop = 'opaque' | 'blur' | 'transparent';\n\n/** Element interface exposing the imperative API for `bit-drawer`. */\nexport interface DrawerElement extends HTMLElement, Omit<BitDrawerProps, 'title'> {\n /** Programmatically open the drawer. Equivalent to setting `open`. */\n show(): void;\n /** Programmatically close the drawer with the exit animation. */\n hide(): void;\n}\n\n/** Drawer component properties */\n\nexport type BitDrawerEvents = {\n close: { placement: DrawerPlacement };\n open: { placement: DrawerPlacement };\n};\n\nexport type BitDrawerProps = {\n /** Backdrop style — 'opaque' (default), 'blur', or 'transparent' */\n backdrop?: DrawerBackdrop;\n /** Show the close (×) button in the header (default: true) */\n dismissable?: boolean;\n /**\n * CSS selector for the element inside the drawer that should receive focus on open.\n * Defaults to native dialog focus management (first focusable element).\n * @example '#submit-btn' | 'input[name=\"email\"]'\n */\n 'initial-focus'?: string;\n /**\n * Invisible accessible label for the dialog (`aria-label`).\n * Use when the drawer has no visible title (e.g. image-only content).\n * When omitted, `aria-labelledby` points to the visible header title instead.\n */\n label?: string;\n /** Controlled open state */\n open?: boolean;\n /** When true, backdrop clicks do not close the drawer (default: false) */\n persistent?: boolean;\n /** Side from which the drawer slides in */\n placement?: DrawerPlacement;\n /**\n * When true (default), focus returns to the triggering element after the drawer closes.\n * Set to false to manage focus manually.\n */\n 'return-focus'?: boolean;\n /** Drawer width/height preset */\n size?: DrawerSize;\n /**\n * Visible title text rendered inside the header.\n * Used as the dialog's accessible label via `aria-labelledby` when `label` is not set.\n */\n title?: string;\n};\n\n/**\n * A panel that slides in from any edge of the screen, built on the native `<dialog>` element.\n *\n * @element bit-drawer\n *\n * @attr {boolean} open - Controlled open/close state\n * @attr {string} placement - 'left' | 'right' (default) | 'top' | 'bottom'\n * @attr {string} size - 'sm' | 'lg' | 'full'\n * @attr {string} title - Visible header title text\n * @attr {string} label - Invisible aria-label (for drawers without a visible title)\n * @attr {boolean} dismissable - Show the close (×) button (default: true)\n * @attr {string} backdrop - Backdrop style: 'opaque' (default) | 'blur' | 'transparent'\n * @attr {boolean} persistent - Prevent backdrop-click from closing (default: false)\n *\n * @slot header - Drawer header content\n * @slot - Main body content\n * @slot footer - Drawer footer content\n *\n * @fires open - When the drawer opens\n * @fires close - When the drawer closes\n *\n * @cssprop --drawer-backdrop - Backdrop background\n * @cssprop --drawer-bg - Panel background color\n * @cssprop --drawer-size - Panel width (horizontal) or height (vertical)\n * @cssprop --drawer-shadow - Panel box-shadow\n *\n * @example\n * ```html\n * <!-- With visible title -->\n * <bit-drawer open title=\"Settings\" placement=\"right\">\n * <p>Settings content here.</p>\n * </bit-drawer>\n *\n * <!-- With custom header slot -->\n * <bit-drawer open placement=\"right\">\n * <span slot=\"header\">Settings</span>\n * <p>Settings content here.</p>\n * </bit-drawer>\n * ```\n */\nexport const DRAWER_TAG = defineComponent<BitDrawerProps, BitDrawerEvents>({\n props: {\n backdrop: { default: undefined },\n dismissable: { default: true },\n 'initial-focus': { default: undefined },\n label: { default: undefined },\n open: { default: false },\n persistent: { default: false },\n placement: { default: 'right' },\n 'return-focus': { default: true },\n size: { default: undefined },\n title: { default: undefined },\n },\n setup({ emit, host, props, slots }) {\n const drawerLabelId = createId('drawer-label');\n const dialogRef = ref<HTMLDialogElement>();\n const panelRef = ref<HTMLDivElement>();\n\n // Header is visible when there is slot content, a title prop, or a close button.\n const hasHeader = computed(() => slots.has('header').value || !!props.title.value || props.dismissable.value);\n const hasFooter = computed(() => slots.has('footer').value);\n\n const { applyInitialFocus, captureReturnFocus, restoreFocus } = useOverlay(\n host,\n dialogRef,\n () => panelRef.value,\n props,\n );\n\n const close = () => {\n const dialog = dialogRef.value;\n\n if (!dialog?.open) return;\n\n dialog.close();\n };\n\n const requestClose = (trigger: 'backdrop' | 'button' | 'escape') => {\n const allowed = fire.custom(host, 'close-request', {\n cancelable: true,\n detail: { placement: props.placement.value ?? 'right', trigger },\n });\n\n if (allowed) close();\n };\n\n const openDrawer = () => {\n const dialog = dialogRef.value;\n\n if (!dialog || dialog.open) return;\n\n captureReturnFocus();\n dialog.showModal();\n lockBackground(host);\n\n applyInitialFocus();\n emit('open', { placement: props.placement.value ?? 'right' });\n };\n\n onMount(() => {\n const dialog = dialogRef.value;\n\n if (!dialog) return;\n\n // Expose imperative API\n const el = host as DrawerElement;\n\n el.show = openDrawer;\n el.hide = close;\n\n const handleNativeClose = () => {\n unlockBackground();\n host.removeAttribute('open');\n restoreFocus();\n emit('close', { placement: props.placement.value ?? 'right' });\n };\n\n const handleCancel = (e: Event) => {\n e.preventDefault();\n\n if (!props.persistent.value) requestClose('escape');\n };\n\n const handleBackdropClick = (e: MouseEvent) => {\n if (!props.persistent.value && e.target === dialog) requestClose('backdrop');\n };\n\n watch(\n props.open,\n (isOpen) => {\n if (isOpen) openDrawer();\n else close();\n },\n { immediate: true },\n );\n\n handle(dialog, 'close', handleNativeClose);\n handle(dialog, 'cancel', handleCancel);\n handle(dialog, 'click', handleBackdropClick);\n\n return () => {\n if (dialog.open) {\n unlockBackground();\n dialog.close();\n }\n };\n });\n\n return html`\n <dialog\n ref=${dialogRef}\n aria-modal=\"true\"\n :aria-label=\"${() => props.label.value ?? null}\"\n :aria-labelledby=\"${() => (!props.label.value ? drawerLabelId : null)}\">\n <div class=\"panel\" part=\"panel\" ref=${panelRef}>\n <div class=\"header\" part=\"header\" ?hidden=${() => !hasHeader.value}>\n <span class=\"header-title\" id=\"${drawerLabelId}\">\n <slot name=\"header\">${() => props.title.value ?? ''}</slot>\n </span>\n <button\n class=\"close-btn\"\n part=\"close-btn\"\n type=\"button\"\n aria-label=\"Close\"\n ?hidden=${() => !props.dismissable.value}\n @click=\"${() => requestClose('button')}\">\n ${closeIcon}\n </button>\n </div>\n <div class=\"body\" part=\"body\">\n <slot></slot>\n </div>\n <div class=\"footer\" part=\"footer\" ?hidden=${() => !hasFooter.value}>\n <slot name=\"footer\"></slot>\n </div>\n </div>\n </dialog>\n `;\n },\n styles: [elevationMixin, forcedColorsMixin, coarsePointerMixin, reducedMotionMixin, styles],\n tag: 'bit-drawer',\n});\n","@layer buildit.base {\n :host {\n --_menu-panel-bg: var(\n --menu-panel-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 85%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 85%, transparent)\n )\n );\n --_menu-panel-border-color: var(\n --menu-panel-border-color,\n light-dark(\n color-mix(in srgb, var(--color-contrast-900) 8%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 8%, transparent)\n )\n );\n --_menu-panel-blur: var(--menu-panel-blur, var(--blur-md));\n --_menu-panel-shadow: var(--menu-panel-shadow, var(--shadow-xl));\n\n position: relative;\n display: inline-block;\n }\n\n /* ========================================\n Menu Panel\n ======================================== */\n\n .menu-panel {\n position: fixed;\n inset-inline-start: 0;\n top: 0;\n z-index: calc(var(--z-popover, 1000) + 1);\n box-sizing: border-box;\n visibility: hidden;\n min-width: var(--menu-panel-min-width, 10rem);\n padding: var(--size-1);\n margin: 0;\n pointer-events: none;\n background: var(--_menu-panel-bg);\n border: var(--border) solid var(--_menu-panel-border-color);\n border-radius: var(--menu-panel-radius, var(--rounded-lg));\n box-shadow: var(--_menu-panel-shadow);\n opacity: 0;\n backdrop-filter: blur(var(--_menu-panel-blur));\n transform: translateY(-4px) scale(0.97);\n transform-origin: top;\n transition:\n opacity var(--transition-fast),\n transform var(--transition-fast),\n visibility var(--transition-fast);\n }\n\n .menu-panel[data-open] {\n visibility: visible;\n pointer-events: auto;\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n /* ========================================\n Menu Items (slotted bit-menu-item)\n ======================================== */\n\n ::slotted(bit-menu-item) {\n display: block;\n }\n\n ::slotted(bit-menu-separator) {\n display: block;\n }\n}\n","import {\n aria,\n computed,\n createId,\n css,\n defineComponent,\n effect,\n handle,\n html,\n onMount,\n onSlotChange,\n signal,\n} from '@vielzeug/craftit';\nimport {\n createListNavigation,\n createOverlayControl,\n type OverlayOpenReason,\n type OverlayCloseReason,\n} from '@vielzeug/craftit/labs';\nimport { flip, offset, positionFloat, shift } from '@vielzeug/floatit';\n\nimport type { AddEventListeners, ComponentSize, ThemeColor } from '../../types';\n\nimport { coarsePointerMixin, colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\n\n// ============================================\n// Types\n// ============================================\n\nexport interface MenuSelectDetail {\n value: string;\n checked?: boolean;\n}\n\nexport type BitMenuItemType = 'checkbox' | 'radio';\n\nexport type BitMenuEvents = {\n close: { reason: OverlayCloseReason };\n open: { reason: OverlayOpenReason };\n select: MenuSelectDetail;\n};\n\nexport type BitMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: BitMenuItemType;\n value?: string;\n};\n\nexport type BitMenuProps = {\n color?: ThemeColor;\n disabled?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ============================================\n// Styles\n// ============================================\n\nimport componentStyles from './menu.css?inline';\n\nconst themeStyles = /* css */ css`\n ${colorThemeMixin}\n ${sizeVariantMixin}\n ${forcedColorsMixin}\n`;\n\n// ============================================\n// Menu Item Component\n// ============================================\n\nexport const MENU_ITEM_TAG = defineComponent<BitMenuItemProps>({\n props: {\n checked: { default: false, type: Boolean },\n disabled: { default: false, type: Boolean },\n type: { default: undefined },\n value: { default: undefined },\n },\n setup({ props }) {\n const itemStyles = /* css */ css`\n @layer buildit.base {\n :host {\n display: block;\n outline: none;\n }\n\n .item {\n align-items: center;\n border-radius: 0;\n cursor: pointer;\n display: flex;\n font-size: var(--text-sm);\n gap: var(--size-2);\n line-height: var(--leading-normal);\n padding: var(--size-1-5) var(--size-3);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n user-select: none;\n white-space: nowrap;\n }\n\n :host(:first-of-type) .item {\n border-radius: var(--rounded-sm) var(--rounded-sm) 0 0;\n }\n\n :host(:last-child) .item {\n border-radius: 0 0 var(--rounded-sm) var(--rounded-sm);\n }\n\n :host(:first-of-type:last-child) .item {\n border-radius: var(--rounded-sm);\n }\n\n :host(:not([disabled])) .item:hover {\n background: var(--color-contrast-100);\n }\n\n :host(:focus-visible) .item {\n background: color-mix(in srgb, var(--color-primary) 12%, var(--color-contrast-100));\n color: var(--color-primary);\n }\n\n /* Driven by JS via sync() — avoids :host() attribute selector edge-cases */\n .item.is-checkable {\n background: color-mix(in srgb, var(--color-contrast-900) 5%, var(--color-canvas));\n }\n\n .item.is-checked {\n background: color-mix(in srgb, var(--color-primary) 18%, var(--color-canvas));\n color: var(--color-primary);\n font-weight: var(--font-medium);\n }\n\n :host([disabled]) .item {\n color: var(--color-contrast-400);\n cursor: not-allowed;\n opacity: 0.6;\n pointer-events: none;\n }\n\n .icon-slot {\n display: contents;\n }\n\n .item-check {\n align-items: center;\n color: currentColor;\n display: inline-flex;\n flex-shrink: 0;\n justify-content: center;\n width: 1.25rem;\n }\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n }\n ${coarsePointerMixin}\n `;\n\n const isCheckable = computed(() => props.type.value === 'checkbox' || props.type.value === 'radio');\n const isChecked = computed(() => isCheckable.value && props.checked.value);\n const itemRole = computed(() => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n });\n const checkIndicator = computed(() => {\n if (props.type.value === 'checkbox') return props.checked.value ? '☑' : '☐';\n\n if (props.type.value === 'radio') return props.checked.value ? '◉' : '◯';\n\n return '';\n });\n const itemClass = computed(\n () => `item${isCheckable.value ? ' is-checkable' : ''}${isChecked.value ? ' is-checked' : ''}`,\n );\n const renderContent = () => html`\n <span class=\"item-check\" aria-hidden=\"true\">${() => checkIndicator.value}</span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n `;\n\n return html`\n <style>\n ${itemStyles}\n </style>\n ${() =>\n isCheckable.value\n ? html`\n <div\n class=\"${() => itemClass.value}\"\n tabindex=\"-1\"\n role=\"${() => itemRole.value}\"\n aria-checked=\"${() => String(isChecked.value)}\"\n aria-disabled=\"${() => String(props.disabled.value)}\">\n ${renderContent()}\n </div>\n `\n : html`\n <div\n class=\"${() => itemClass.value}\"\n tabindex=\"-1\"\n role=\"menuitem\"\n aria-disabled=\"${() => String(props.disabled.value)}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `}\n `;\n },\n tag: 'bit-menu-item',\n});\n\n// ============================================\n// Menu Separator\n// ============================================\n\nexport const SEPARATOR_TAG = defineComponent({\n setup() {\n return html`<style>\n @layer buildit.base {\n :host {\n display: block;\n margin: var(--size-1) 0;\n border-top: var(--border) solid var(--color-contrast-200);\n }\n }\n </style>`;\n },\n tag: 'bit-menu-separator',\n});\n\n// ============================================\n// Menu Component\n// ============================================\n\n/**\n * `bit-menu` — Action dropdown menu triggered by a slotted trigger element.\n * Nest `<bit-menu-item>` elements inside for menu options.\n *\n * @example\n * ```html\n * <bit-menu>\n * <button slot=\"trigger\">Actions</button>\n * <bit-menu-item value=\"edit\">Edit</bit-menu-item>\n * <bit-menu-item value=\"delete\">Delete</bit-menu-item>\n * </bit-menu>\n * ```\n */\nexport const MENU_TAG = defineComponent<BitMenuProps, BitMenuEvents>({\n props: {\n color: { default: undefined },\n disabled: { default: false },\n placement: { default: 'bottom-start' },\n size: { default: undefined },\n },\n setup({ emit, host, props }) {\n const menuId = createId('menu');\n const isOpen = signal(false);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(host.querySelectorAll<HTMLElement>('bit-menu-item:not([disabled])'));\n }\n\n let focusedIndex = -1;\n\n const listNavigation = createListNavigation<HTMLElement>({\n getIndex: () => focusedIndex,\n getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n setIndex: (index) => {\n focusedIndex = index;\n getItems()[index]?.focus();\n },\n });\n\n function updatePosition() {\n if (!panelEl || !triggerEl) return;\n\n positionFloat(triggerEl, panelEl, {\n middleware: [offset(4), flip({ padding: 6 }), shift({ padding: 6 })],\n placement: props.placement.value,\n });\n }\n\n const overlay = createOverlayControl({\n getBoundaryElement: () => host,\n getPanelElement: () => panelEl,\n getTriggerElement: () => triggerEl,\n isDisabled: () => Boolean(props.disabled.value),\n isOpen: () => isOpen.value,\n onClose: (reason) => emit('close', { reason }),\n onOpen: (reason) => emit('open', { reason }),\n positioner: {\n floating: () => panelEl,\n reference: () => triggerEl,\n update: updatePosition,\n },\n setOpen: (next) => {\n isOpen.value = next;\n\n if (!next) listNavigation.reset();\n },\n });\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n\n if (type === 'checkbox') {\n const next = !item.hasAttribute('checked');\n\n if (next) item.setAttribute('checked', '');\n else item.removeAttribute('checked');\n } else if (type === 'radio') {\n for (const radio of host.querySelectorAll<HTMLElement>('bit-menu-item[type=\"radio\"]')) {\n radio.removeAttribute('checked');\n }\n item.setAttribute('checked', '');\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = type === 'checkbox' || type === 'radio' ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (type !== 'checkbox' && type !== 'radio') {\n overlay.close({ reason: 'programmatic' });\n }\n };\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n const open = isOpen.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {\n e.preventDefault();\n overlay.open();\n requestAnimationFrame(() => listNavigation.first());\n }\n\n return;\n }\n\n // When open: navigate and activate\n switch (e.key) {\n case ' ': {\n e.preventDefault();\n\n const focused = listNavigation.getActiveItem();\n\n if (focused) activateItem(focused);\n\n break;\n }\n case 'ArrowDown':\n e.preventDefault();\n listNavigation.next();\n break;\n case 'ArrowUp':\n e.preventDefault();\n listNavigation.prev();\n break;\n case 'End':\n e.preventDefault();\n listNavigation.last();\n break;\n case 'Enter': {\n e.preventDefault();\n\n const focused = listNavigation.getActiveItem();\n\n if (focused) activateItem(focused);\n\n break;\n }\n case 'Escape':\n e.preventDefault();\n overlay.close({ reason: 'escape' });\n break;\n case 'Home':\n e.preventDefault();\n listNavigation.first();\n break;\n case 'Tab':\n overlay.close({ reason: 'programmatic' });\n break;\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n onMount(() => {\n const triggerSlot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"trigger\"]');\n\n panelEl = host.shadowRoot?.querySelector<HTMLElement>('.menu-panel') ?? null;\n\n let prevTriggerEl: HTMLElement | null = null;\n\n function resolveTrigger() {\n if (prevTriggerEl) {\n prevTriggerEl.removeEventListener('click', toggleMenu);\n prevTriggerEl.removeEventListener('keydown', handleMenuKeydown);\n }\n\n const assigned = triggerSlot?.assignedElements({ flatten: true });\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n prevTriggerEl = triggerEl;\n\n if (triggerEl) {\n aria(triggerEl, {\n controls: () => menuId,\n disabled: () => props.disabled.value,\n expanded: () => (isOpen.value ? 'true' : 'false'),\n haspopup: 'menu',\n });\n triggerEl.addEventListener('click', toggleMenu);\n triggerEl.addEventListener('keydown', handleMenuKeydown);\n }\n }\n\n function toggleMenu() {\n overlay.toggle();\n }\n\n onSlotChange('trigger', resolveTrigger);\n\n // Item activation via click\n handle(host, 'click', ((e: Event) => {\n if (!isOpen.value) return;\n\n const me = e as MouseEvent;\n const path = me.composedPath();\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'BIT-MENU-ITEM',\n );\n const item = itemFromPath ?? (me.target as HTMLElement | null)?.closest<HTMLElement>('bit-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n }) as EventListener);\n\n const removeOutsideClick = overlay.bindOutsideClick(document);\n\n effect(() => {\n panelEl?.toggleAttribute('data-open', isOpen.value);\n });\n\n handle(panelEl, 'keydown', handleMenuKeydown as EventListener);\n\n return () => {\n removeOutsideClick();\n\n if (prevTriggerEl) {\n prevTriggerEl.removeEventListener('click', toggleMenu);\n prevTriggerEl.removeEventListener('keydown', handleMenuKeydown);\n }\n };\n });\n\n return html`\n <style>\n ${componentStyles}${themeStyles}\n </style>\n <slot name=\"trigger\"></slot>\n <div class=\"menu-panel\" id=\"${menuId}\" role=\"menu\" aria-orientation=\"vertical\">\n <slot></slot>\n </div>\n `;\n },\n tag: 'bit-menu',\n}) as unknown as AddEventListeners<BitMenuEvents>;\n","@layer buildit.base {\n :host {\n --_panel-bg: var(\n --popover-bg,\n light-dark(\n color-mix(in srgb, var(--color-contrast-50) 85%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 85%, transparent)\n )\n );\n --_panel-blur: var(--popover-panel-blur, var(--blur-md));\n --_panel-border-color: var(\n --popover-border-color,\n light-dark(\n color-mix(in srgb, var(--color-contrast-900) 8%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 8%, transparent)\n )\n );\n --_panel-shadow: var(--popover-shadow, var(--shadow-xl));\n\n position: relative;\n display: inline-block;\n }\n\n .panel {\n position: fixed;\n\n /* Popover UA resets */\n inset: unset;\n box-sizing: border-box;\n min-width: var(--popover-min-width, 12rem);\n max-width: var(--popover-max-width, 24rem);\n max-height: var(--popover-max-height, min(70vh, 32rem));\n padding: 0;\n margin: 0;\n overflow: auto;\n word-break: auto-phrase;\n overflow-wrap: anywhere;\n background: var(--_panel-bg);\n border: var(--border) solid var(--_panel-border-color);\n border-radius: var(--rounded-lg);\n box-shadow: var(--_panel-shadow);\n\n /* Hidden by default */\n opacity: 0;\n backdrop-filter: blur(var(--_panel-blur));\n transform: scale(0.96) translateY(var(--size-2));\n transition: var(\n --_motion-transition,\n opacity var(--transition-fast),\n transform var(--transition-normal) cubic-bezier(0.16, 1, 0.3, 1),\n display var(--transition-fast) allow-discrete,\n overlay var(--transition-fast) allow-discrete\n );\n }\n\n .panel:popover-open {\n opacity: 1;\n transform: scale(1) translateY(0);\n\n @starting-style {\n opacity: 0;\n transform: scale(0.96) translateY(var(--size-2));\n }\n }\n}\n","import type { Placement } from '@vielzeug/floatit';\n\nimport { computed, createId, defineComponent, html, onMount, onSlotChange, signal, watch } from '@vielzeug/craftit';\nimport { autoUpdate, flip, offset, positionFloat, shift } from '@vielzeug/floatit';\n\nimport { reducedMotionMixin } from '../../styles';\n\nexport type PopoverTrigger = 'click' | 'hover' | 'focus';\n\nconst PANEL_OFFSET = 8;\nconst VALID_TRIGGERS = new Set<PopoverTrigger>(['click', 'hover', 'focus']);\n\nfunction normalizeTriggers(value: unknown): PopoverTrigger[] {\n const parsed = String(value)\n .split(',')\n .map((item) => item.trim())\n .filter((item): item is PopoverTrigger => VALID_TRIGGERS.has(item as PopoverTrigger));\n\n // Keep behavior predictable for invalid input.\n return parsed.length > 0 ? parsed : ['click'];\n}\n\nimport styles from './popover.css?inline';\n\nexport type BitPopoverEvents = {\n /** Emitted when the popover closes */\n close: undefined;\n /** Emitted when the popover opens */\n open: undefined;\n};\n\n/** Popover component properties */\nexport type BitPopoverProps = {\n /** Disable the popover */\n disabled?: boolean;\n /** Accessible label for the panel */\n label?: string;\n /** Gap between trigger and panel in px */\n offset?: number;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to the trigger */\n placement?: Placement;\n /** Which trigger(s) open/close the popover — comma-separated */\n trigger?: string;\n};\n\n/**\n * A floating informational or interactive panel anchored to a trigger element.\n * Unlike tooltips, popovers support arbitrary interactive content via slots.\n *\n * @element bit-popover\n *\n * @attr {string} placement - Preferred placement (default: 'bottom')\n * @attr {string} trigger - 'click' | 'hover' | 'focus' or comma-separated (default: 'click')\n * @attr {boolean} open - Controlled open state\n * @attr {number} offset - Gap in px between trigger and panel (default: 8)\n * @attr {boolean} disabled - Disables the popover\n * @attr {string} label - aria-label on the panel\n *\n * @slot - The trigger element\n * @slot content - Panel content\n *\n * @fires open - When the panel opens\n * @fires close - When the panel closes\n *\n * @cssprop --popover-min-width - Min width of the panel\n * @cssprop --popover-max-width - Max width of the panel\n * @cssprop --popover-max-height - Max height of the panel\n *\n * @example\n * ```html\n * <bit-popover>\n * <button>Open</button>\n * <div slot=\"content\">Panel content here</div>\n * </bit-popover>\n * ```\n */\nexport const POPOVER_TAG = defineComponent<BitPopoverProps, BitPopoverEvents>({\n props: {\n disabled: { default: false },\n label: { default: undefined },\n offset: { default: PANEL_OFFSET },\n open: { default: undefined },\n placement: { default: 'bottom' },\n trigger: { default: 'click' },\n },\n setup({ emit, host, props }) {\n const visible = signal(false);\n const panelId = createId('popover');\n let panelEl: HTMLElement | null = null;\n let currentTrigger: HTMLElement | null = null;\n let autoUpdateCleanup: (() => void) | null = null;\n const triggers = computed<PopoverTrigger[]>(() => normalizeTriggers(props.trigger.value));\n\n function updatePosition() {\n if (!panelEl || !currentTrigger) return;\n\n positionFloat(currentTrigger, panelEl, {\n middleware: [offset(props.offset.value ?? PANEL_OFFSET), flip(), shift({ padding: 8 })],\n placement: props.placement.value,\n }).then((resolvedPlacement) => {\n if (panelEl) panelEl.dataset.placement = resolvedPlacement;\n });\n }\n /** Show the panel and start auto-updating its position. */\n function showFloat() {\n visible.value = true;\n currentTrigger?.setAttribute('aria-expanded', 'true');\n\n if (panelEl && !panelEl.matches(':popover-open')) panelEl.showPopover();\n\n if (currentTrigger && panelEl) {\n autoUpdateCleanup?.();\n autoUpdateCleanup = autoUpdate(currentTrigger, panelEl, updatePosition);\n }\n\n updatePosition();\n }\n /** Hide the panel and stop auto-updating its position. */\n function hideFloat() {\n autoUpdateCleanup?.();\n autoUpdateCleanup = null;\n currentTrigger?.setAttribute('aria-expanded', 'false');\n visible.value = false;\n\n if (panelEl?.matches(':popover-open')) panelEl.hidePopover();\n }\n function open() {\n if (props.open.value !== undefined) return;\n\n if (props.disabled.value) return;\n\n if (visible.value) return;\n\n showFloat();\n emit('open');\n }\n function close() {\n if (props.open.value !== undefined) return;\n\n if (!visible.value) return;\n\n hideFloat();\n emit('close');\n }\n function toggle() {\n if (visible.value) close();\n else open();\n }\n function handleKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') close();\n }\n function handleClickOutside(e: MouseEvent) {\n if (!visible.value) return;\n\n const path = e.composedPath();\n\n if (path.includes(host)) return;\n\n if (panelEl && path.includes(panelEl)) return;\n\n if (currentTrigger && path.includes(currentTrigger)) return;\n\n close();\n }\n // Don't close when focus moves from the trigger into the panel content.\n function handleFocusOut(e: FocusEvent) {\n const next = e.relatedTarget as Element | null;\n\n if (next && panelEl?.contains(next)) return;\n\n if (next && currentTrigger?.contains(next)) return;\n\n close();\n }\n onMount(() => {\n const triggerSlot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n\n if (!triggerSlot) return;\n\n const bindEvents = () => {\n unbindEvents();\n\n const el = triggerSlot.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!el) return;\n\n currentTrigger = el;\n el.setAttribute('aria-controls', panelId);\n el.setAttribute('aria-haspopup', 'dialog');\n el.setAttribute('aria-expanded', String(visible.value));\n el.setAttribute('aria-disabled', String(Boolean(props.disabled.value)));\n\n const t = triggers.value;\n\n if (t.includes('click')) {\n el.addEventListener('click', toggle);\n document.addEventListener('click', handleClickOutside, { capture: true });\n }\n\n if (t.includes('hover')) {\n el.addEventListener('pointerenter', open);\n el.addEventListener('pointerleave', close);\n panelEl?.addEventListener('pointerenter', open);\n panelEl?.addEventListener('pointerleave', close);\n }\n\n if (t.includes('focus')) {\n el.addEventListener('focusin', open);\n el.addEventListener('focusout', handleFocusOut);\n panelEl?.addEventListener('focusout', handleFocusOut);\n }\n\n document.addEventListener('keydown', handleKeydown);\n };\n const unbindEvents = () => {\n if (!currentTrigger) return;\n\n currentTrigger.removeAttribute('aria-controls');\n currentTrigger.removeAttribute('aria-haspopup');\n currentTrigger.removeAttribute('aria-expanded');\n currentTrigger.removeAttribute('aria-disabled');\n currentTrigger.removeEventListener('click', toggle);\n currentTrigger.removeEventListener('pointerenter', open);\n currentTrigger.removeEventListener('pointerleave', close);\n currentTrigger.removeEventListener('focusin', open);\n currentTrigger.removeEventListener('focusout', handleFocusOut);\n panelEl?.removeEventListener('pointerenter', open);\n panelEl?.removeEventListener('pointerleave', close);\n panelEl?.removeEventListener('focusout', handleFocusOut);\n document.removeEventListener('click', handleClickOutside, { capture: true });\n document.removeEventListener('keydown', handleKeydown);\n currentTrigger = null;\n };\n\n onSlotChange('default', bindEvents);\n // Controlled mode\n watch(props.open, (openVal) => {\n if (openVal === undefined || openVal === null) return;\n\n if (openVal) {\n showFloat();\n emit('open');\n } else {\n hideFloat();\n emit('close');\n }\n });\n watch(props.trigger, bindEvents);\n watch(props.disabled, (isDisabled) => {\n currentTrigger?.setAttribute('aria-disabled', String(Boolean(isDisabled)));\n\n if (isDisabled) {\n close();\n }\n });\n\n return () => {\n unbindEvents();\n autoUpdateCleanup?.();\n autoUpdateCleanup = null;\n\n if (panelEl?.matches(':popover-open')) panelEl.hidePopover();\n };\n });\n\n return html`\n <slot></slot>\n <div\n class=\"panel\"\n part=\"panel\"\n id=\"${panelId}\"\n role=\"dialog\"\n aria-modal=\"false\"\n popover=\"manual\"\n :aria-label=\"${() => props.label.value ?? null}\"\n :aria-hidden=\"${() => String(!visible.value)}\"\n ref=${(el: HTMLElement) => {\n panelEl = el;\n }}>\n <slot name=\"content\"></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, styles],\n tag: 'bit-popover',\n});\n","/* ========================================\n Popover UA resets — unlayered so they unconditionally beat\n the browser's [popover] UA stylesheet (padding / inset / border / margin).\n Must NOT be inside @layer; unlayered author rules win over every layer and\n every UA default.\n ======================================== */\n.tooltip {\n inset: unset;\n padding: var(--size-1-5) var(--size-3);\n margin: 0;\n overflow: visible;\n border: var(--_tooltip-border-width, var(--border-0)) solid var(--_tooltip-border-color, transparent);\n transform-origin: center;\n will-change: opacity, transform, filter;\n}\n\n@layer buildit.base {\n :host {\n position: relative;\n display: inline-block;\n }\n\n .tooltip {\n --_tooltip-fg: light-dark(var(--color-contrast-100), var(--color-contrast-900));\n --_tooltip-bg: light-dark(\n color-mix(in srgb, var(--color-contrast-900) 80%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 80%, transparent)\n );\n --_tooltip-border-width: var(--border);\n --_tooltip-border-color: light-dark(\n color-mix(in srgb, var(--color-contrast-100) 12%, transparent),\n color-mix(in srgb, var(--color-contrast-900) 12%, transparent)\n );\n --_tooltip-shadow: var(--shadow-md);\n --_tooltip-closed-transform: translateY(var(--size-1)) scale(0.98);\n\n /* Positioning — JS sets top/left inline */\n position: fixed;\n max-width: var(--tooltip-max-width, var(--size-72));\n font-size: var(--text-xs);\n font-weight: var(--font-medium);\n line-height: var(--leading-snug);\n color: var(--_tooltip-fg);\n word-break: auto-phrase;\n white-space: pre-line;\n pointer-events: none;\n background: var(--_tooltip-bg);\n border-radius: var(--rounded);\n box-shadow: var(--_tooltip-shadow);\n\n /* Hidden by default (also serves as exit state) */\n opacity: 0;\n backdrop-filter: blur(var(--blur-sm));\n transform: var(--_tooltip-closed-transform);\n transition:\n opacity var(--transition-fast),\n transform var(--transition-normal) var(--ease-out),\n display var(--transition-fast) allow-discrete,\n overlay var(--transition-fast) allow-discrete;\n }\n\n .tooltip[data-placement='top'] {\n --_tooltip-closed-transform: translateY(var(--size-2)) scale(0.96);\n }\n\n .tooltip[data-placement='bottom'] {\n --_tooltip-closed-transform: translateY(calc(var(--size-2) * -1)) scale(0.96);\n }\n\n .tooltip[data-placement='left'] {\n --_tooltip-closed-transform: translateX(var(--size-2)) scale(0.96);\n }\n\n .tooltip[data-placement='right'] {\n --_tooltip-closed-transform: translateX(calc(var(--size-2) * -1)) scale(0.96);\n }\n\n /* Entry animation via @starting-style */\n .tooltip:popover-open {\n opacity: 1;\n transform: translate(0, 0) scale(1);\n transition:\n opacity var(--transition-normal),\n transform var(--transition-spring),\n display var(--transition-normal) allow-discrete,\n overlay var(--transition-normal) allow-discrete;\n\n @starting-style {\n opacity: 0;\n transform: var(--_tooltip-closed-transform);\n }\n }\n}\n\n@layer buildit.variants {\n /* Light tooltip */\n :host([variant='light']) .tooltip {\n --_tooltip-fg: light-dark(var(--color-contrast-900), var(--color-contrast-100));\n --_tooltip-bg: light-dark(\n color-mix(in srgb, var(--color-contrast-100) 80%, transparent),\n color-mix(in srgb, var(--color-contrast-900) 80%, transparent)\n );\n --_tooltip-border-color: light-dark(\n color-mix(in srgb, var(--color-contrast-900) 12%, transparent),\n color-mix(in srgb, var(--color-contrast-100) 12%, transparent)\n );\n --_tooltip-shadow: var(--shadow-md);\n }\n}\n\n@layer buildit.utilities {\n :host([size='sm']) .tooltip {\n font-size: var(--text-xs);\n }\n\n :host([size='lg']) .tooltip {\n font-size: var(--text-base);\n }\n}\n","import type { Placement } from '@vielzeug/floatit';\n\nimport { computed, createId, defineComponent, html, onMount, onSlotChange, signal, watch } from '@vielzeug/craftit';\nimport { autoUpdate, computePosition, flip, offset, shift } from '@vielzeug/floatit';\n\nimport type { ComponentSize } from '../../types';\n\nimport { forcedColorsMixin } from '../../styles';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'hover' | 'focus' | 'click';\n\nconst TOOLTIP_OFFSET = 8; // gap from trigger to tooltip edge\nconst LEFT_GAP_COMPENSATION = 4; // left placement looks visually tighter in practice\n\nimport styles from './tooltip.css?inline';\n\n/** Tooltip component properties */\nexport type BitTooltipProps = {\n /** Hide delay in ms (useful to keep tooltip open when moving focus between trigger and tooltip) */\n 'close-delay'?: number;\n /** Tooltip text content */\n content?: string;\n /** Show delay in ms */\n delay?: number;\n /** Disable the tooltip */\n disabled?: boolean;\n /** Controlled open state. When provided, the tooltip acts as a controlled component and ignores trigger events for open/close. */\n open?: boolean;\n /** Preferred placement relative to trigger */\n placement?: TooltipPlacement;\n /** Tooltip size */\n size?: ComponentSize;\n /** Which trigger(s) show/hide the tooltip — comma-separated if multiple, e.g. \"hover,focus\" */\n trigger?: string;\n /** Visual variant: 'dark' (default) or 'light' */\n variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element bit-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @example\n * ```html\n * <bit-tooltip content=\"Copy to clipboard\">\n * <button>Copy</button>\n * </bit-tooltip>\n *\n * <bit-tooltip placement=\"right\" trigger=\"focus,hover\" content=\"Required field\">\n * <input type=\"text\" />\n * </bit-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = defineComponent<BitTooltipProps>({\n props: {\n 'close-delay': { default: 0 },\n content: { default: '' },\n delay: { default: 0 },\n disabled: { default: false },\n open: { default: undefined },\n placement: { default: 'top' },\n size: { default: undefined },\n trigger: { default: 'hover,focus' },\n variant: { default: undefined },\n },\n setup({ host, props }) {\n const visible = signal(false);\n const activePlacement = signal<TooltipPlacement>('top');\n let autoUpdateCleanup: (() => void) | null = null;\n let showTimer: ReturnType<typeof setTimeout> | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n let tooltipEl: HTMLElement | null = null;\n const tooltipId = createId('tooltip');\n const triggers = computed<TooltipTrigger[]>(() =>\n String(props.trigger.value)\n .split(',')\n .map((t: string) => t.trim() as TooltipTrigger)\n .filter(Boolean),\n );\n\n function getTriggerEl(): Element | null {\n // First slotted element is the trigger\n const slot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n const assigned = slot?.assignedElements({ flatten: true });\n\n return assigned?.[0] ?? null;\n }\n function updatePosition() {\n if (!tooltipEl) return;\n\n const triggerEl = getTriggerEl();\n\n if (!triggerEl) return;\n\n computePosition(triggerEl, tooltipEl, {\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: 6 })],\n placement: props.placement.value as Placement,\n }).then(({ placement, x, y }) => {\n if (!tooltipEl) return;\n\n const side = placement.split('-')[0] as TooltipPlacement;\n const adjustedX = side === 'left' ? x - LEFT_GAP_COMPENSATION : x;\n\n tooltipEl.style.left = `${adjustedX}px`;\n tooltipEl.style.top = `${y}px`;\n\n activePlacement.value = side;\n });\n }\n function show() {\n if (props.open.value !== undefined) return; // controlled mode\n\n const hasSlottedContent = () => {\n const contentSlot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"content\"]');\n\n return (contentSlot?.assignedNodes({ flatten: true }).length ?? 0) > 0;\n };\n\n if (props.disabled.value || (!props.content.value && !hasSlottedContent())) return;\n\n if (hideTimer) {\n clearTimeout(hideTimer);\n hideTimer = null;\n }\n\n if (showTimer) clearTimeout(showTimer);\n\n showTimer = setTimeout(\n () => {\n visible.value = true;\n\n if (tooltipEl && !tooltipEl.matches(':popover-open')) {\n tooltipEl.showPopover();\n }\n\n // Start autoUpdate: repositions on scroll, resize, and reference size change\n const triggerEl = getTriggerEl();\n\n if (triggerEl && tooltipEl) {\n autoUpdateCleanup?.();\n autoUpdateCleanup = autoUpdate(triggerEl, tooltipEl, updatePosition);\n } else {\n requestAnimationFrame(() => updatePosition());\n }\n },\n Number(props.delay.value) || 0,\n );\n }\n function hide() {\n if (props.open.value !== undefined) return; // controlled mode\n\n if (showTimer) {\n clearTimeout(showTimer);\n showTimer = null;\n }\n\n const closeDelay = Number(props['close-delay'].value) || 0;\n\n if (closeDelay > 0) {\n if (hideTimer) clearTimeout(hideTimer);\n\n hideTimer = setTimeout(() => {\n hideTimer = null;\n _doHide();\n }, closeDelay);\n } else {\n _doHide();\n }\n }\n function _doHide() {\n autoUpdateCleanup?.();\n autoUpdateCleanup = null;\n visible.value = false;\n\n if (tooltipEl?.matches(':popover-open')) {\n tooltipEl.hidePopover();\n }\n }\n function toggleClick() {\n if (visible.value) hide();\n else show();\n }\n onMount(() => {\n const slot = host.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n\n if (!slot) return;\n\n const bindTriggerEvents = () => {\n unbindTriggerEvents(); // clean up previous bindings\n\n const triggerEl = slot.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n triggerEl.setAttribute('aria-describedby', tooltipId);\n\n const t = triggers.value;\n\n if (t.includes('hover')) {\n triggerEl.addEventListener('pointerenter', show);\n triggerEl.addEventListener('pointerleave', hide);\n }\n\n if (t.includes('focus')) {\n triggerEl.addEventListener('focusin', show);\n triggerEl.addEventListener('focusout', hide);\n }\n\n if (t.includes('click')) {\n triggerEl.addEventListener('click', toggleClick);\n }\n\n // Keyboard escape to dismiss\n document.addEventListener('keydown', handleKeydown);\n };\n const unbindTriggerEvents = () => {\n const triggerEl = slot.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n triggerEl.removeAttribute('aria-describedby');\n triggerEl.removeEventListener('pointerenter', show);\n triggerEl.removeEventListener('pointerleave', hide);\n triggerEl.removeEventListener('focusin', show);\n triggerEl.removeEventListener('focusout', hide);\n triggerEl.removeEventListener('click', toggleClick);\n document.removeEventListener('keydown', handleKeydown);\n };\n\n onSlotChange('default', bindTriggerEvents);\n // Controlled mode: watch the `open` prop and show/hide accordingly\n watch(props.open, (openVal) => {\n if (openVal === undefined || openVal === null) return;\n\n if (openVal) {\n visible.value = true;\n\n if (tooltipEl && !tooltipEl.matches(':popover-open')) tooltipEl.showPopover();\n\n const triggerEl = getTriggerEl();\n\n if (triggerEl && tooltipEl) {\n autoUpdateCleanup?.();\n autoUpdateCleanup = autoUpdate(triggerEl, tooltipEl, updatePosition);\n } else {\n requestAnimationFrame(() => updatePosition());\n }\n } else {\n _doHide();\n }\n });\n\n return () => {\n unbindTriggerEvents();\n\n if (showTimer) clearTimeout(showTimer);\n\n if (hideTimer) clearTimeout(hideTimer);\n\n autoUpdateCleanup?.();\n autoUpdateCleanup = null;\n\n if (tooltipEl?.matches(':popover-open')) {\n tooltipEl.hidePopover();\n }\n };\n });\n function handleKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') hide();\n }\n\n return html`\n <slot></slot>\n <div\n class=\"tooltip\"\n part=\"tooltip\"\n id=\"${tooltipId}\"\n role=\"tooltip\"\n popover=\"manual\"\n ref=${(el: HTMLElement) => {\n tooltipEl = el;\n }}\n :data-placement=\"${activePlacement}\"\n :aria-hidden=\"${() => String(!visible.value)}\">\n <slot name=\"content\">${() => props.content.value}</slot>\n </div>\n `;\n },\n styles: [forcedColorsMixin, styles],\n tag: 'bit-tooltip',\n});\n"],"mappings":"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"}