@mono-lit/helper 0.0.0-stage → 0.0.2

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 (539) hide show
  1. package/LICENSE.md +55 -0
  2. package/README.md +35 -3
  3. package/dist/breakpoints-CAbhDUht.js +84 -0
  4. package/dist/checkbox-Cqpie9Ap.js +4 -0
  5. package/dist/chip-DBUUa2eB.js +4 -0
  6. package/dist/chip-limits-BMoO31JM.js +213 -0
  7. package/dist/chip-strip-Cw3gyz0q.js +213 -0
  8. package/dist/color-DHYrfXsX.js +253 -0
  9. package/dist/css-class-BRKRzHx-.js +60 -0
  10. package/dist/css-size-DhHSVZJK.js +37 -0
  11. package/dist/data/theme/presets.json.d.ts +140 -0
  12. package/dist/data-source-controller-B_rgHCjw.js +241 -0
  13. package/dist/data-source-controller-Dbb4fd8I.js +241 -0
  14. package/dist/data-source-options-CP-X62Pa.js +535 -0
  15. package/dist/data-source-options-Jqj7LU3Z.js +537 -0
  16. package/dist/data-source-read-B4DGp6UQ.js +216 -0
  17. package/dist/data-source-read-DL88aH8t.js +217 -0
  18. package/dist/decorate-DEXtNagw.js +141 -0
  19. package/dist/element-props-CLB6yvbm.js +114 -0
  20. package/dist/esm-Ptok4SQZ.js +2026 -0
  21. package/dist/excel-CY6zGkcx.js +608 -0
  22. package/dist/excel-DopRbEMK.js +608 -0
  23. package/dist/export-BiGVyxt6.js +2302 -0
  24. package/dist/export.d.ts +1 -0
  25. package/dist/export.js +2302 -0
  26. package/dist/field-icons-DELrSdqJ.js +86 -0
  27. package/dist/field-path-C92eGLg3.js +251 -0
  28. package/dist/filter-builder-Bke3qOgJ.js +205 -0
  29. package/dist/filter-builder-CE4zE0V5.js +205 -0
  30. package/dist/filter-eval-DIfU2EAn.js +173 -0
  31. package/dist/filter-odata-C1vSGZaY.js +591 -0
  32. package/dist/form-control-core-B8d7k6vk.js +223 -0
  33. package/dist/form-control-core-eeRr0zLU.js +223 -0
  34. package/dist/hydration-flush-RB5Tz5nl.js +1001 -0
  35. package/dist/icon-CJkTlmTb.js +55 -0
  36. package/dist/icon-dVhYJUIH.js +17 -0
  37. package/dist/import-BgJdkwBI.js +606 -0
  38. package/dist/import.d.ts +1 -0
  39. package/dist/import.js +606 -0
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.js +16 -0
  42. package/dist/index.node-BIqEGehH.js +396 -0
  43. package/dist/index.node.d.ts +1 -0
  44. package/dist/index.node.js +16 -0
  45. package/dist/input-zGOULADt.js +4 -0
  46. package/dist/layout-var-CZnzMC0s.js +73 -0
  47. package/dist/light-slots-BVJwyg_2.js +244 -0
  48. package/dist/light-slots-DW1WgfgT.js +254 -0
  49. package/dist/markdown-DfqrfOJN.js +20146 -0
  50. package/dist/mono-button-simcTQdW.js +873 -0
  51. package/dist/mono-button.shadow-B_rKOY9N.js +784 -0
  52. package/dist/mono-data-chart-CEv29_NS.js +779 -0
  53. package/dist/mono-data-dropdown-Wnoke6zO.js +357 -0
  54. package/dist/mono-data-grid-CjkEqxgE.js +3913 -0
  55. package/dist/mono-data-grid-YjR3n9Ar.js +3915 -0
  56. package/dist/mono-element-B0kP_96P.js +232 -0
  57. package/dist/mono-event-Bi1qP9uN.js +129 -0
  58. package/dist/mono-form-controller-5PfsU4qa.js +409 -0
  59. package/dist/mono-modal-controller-BMO3n3rP.js +223 -0
  60. package/dist/mono-ui-CPV7rrdo.js +358 -0
  61. package/dist/normalize-error-Gcgmgh5i.js +871 -0
  62. package/dist/notifier-CE4yxMUQ.js +88 -0
  63. package/dist/nuxt.d.ts +1 -0
  64. package/dist/nuxt.js +130 -0
  65. package/dist/popup-portal-BziRX1yG.js +465 -0
  66. package/dist/popup-stack-CEEMib__.js +189 -0
  67. package/dist/rate-limit-BBa2PO79.js +521 -0
  68. package/dist/reactive-D3EERqgO.js +47 -0
  69. package/dist/reactive-Di3mTMnV.js +1087 -0
  70. package/dist/search.d.ts +1 -0
  71. package/dist/search.js +97 -0
  72. package/dist/src/components/accordion/accordion-core.d.ts +62 -0
  73. package/dist/src/components/accordion/accordion-types.d.ts +62 -0
  74. package/dist/src/components/accordion/index.d.ts +3 -0
  75. package/dist/src/components/accordion/index.shadow.d.ts +5 -0
  76. package/dist/src/components/accordion/mono-accordion.d.ts +55 -0
  77. package/dist/src/components/accordion/mono-accordion.shadow.d.ts +56 -0
  78. package/dist/src/components/alert/alert-core.d.ts +46 -0
  79. package/dist/src/components/alert/alert-types.d.ts +44 -0
  80. package/dist/src/components/alert/index.d.ts +3 -0
  81. package/dist/src/components/alert/index.shadow.d.ts +5 -0
  82. package/dist/src/components/alert/mono-alert.d.ts +44 -0
  83. package/dist/src/components/alert/mono-alert.shadow.d.ts +34 -0
  84. package/dist/src/components/breadcrumb/breadcrumb-core.d.ts +61 -0
  85. package/dist/src/components/breadcrumb/breadcrumb-list-core.d.ts +49 -0
  86. package/dist/src/components/breadcrumb/breadcrumb-render.d.ts +31 -0
  87. package/dist/src/components/breadcrumb/breadcrumb-types.d.ts +117 -0
  88. package/dist/src/components/breadcrumb/breadcrumb-utils.d.ts +43 -0
  89. package/dist/src/components/breadcrumb/index.d.ts +6 -0
  90. package/dist/src/components/breadcrumb/index.shadow.d.ts +8 -0
  91. package/dist/src/components/breadcrumb/mono-breadcrumb-list.d.ts +29 -0
  92. package/dist/src/components/breadcrumb/mono-breadcrumb-list.shadow.d.ts +48 -0
  93. package/dist/src/components/breadcrumb/mono-breadcrumb.d.ts +38 -0
  94. package/dist/src/components/breadcrumb/mono-breadcrumb.shadow.d.ts +73 -0
  95. package/dist/src/components/button/button-core.d.ts +90 -0
  96. package/dist/src/components/button/button-dropdown-core.d.ts +57 -0
  97. package/dist/src/components/button/button-dropdown-types.d.ts +129 -0
  98. package/dist/src/components/button/button-types.d.ts +219 -0
  99. package/dist/src/components/button/button-utils.d.ts +18 -0
  100. package/dist/src/components/button/index.button-dropdown.d.ts +4 -0
  101. package/dist/src/components/button/index.button-dropdown.shadow.d.ts +4 -0
  102. package/dist/src/components/button/index.d.ts +8 -0
  103. package/dist/src/components/button/index.shadow.d.ts +5 -0
  104. package/dist/src/components/button/mono-button-dropdown.d.ts +35 -0
  105. package/dist/src/components/button/mono-button-dropdown.shadow.d.ts +45 -0
  106. package/dist/src/components/button/mono-button.d.ts +123 -0
  107. package/dist/src/components/button/mono-button.shadow.d.ts +56 -0
  108. package/dist/src/components/card/card-core.d.ts +75 -0
  109. package/dist/src/components/card/card-types.d.ts +137 -0
  110. package/dist/src/components/card/card-utils.d.ts +23 -0
  111. package/dist/src/components/card/index.d.ts +4 -0
  112. package/dist/src/components/card/index.shadow.d.ts +6 -0
  113. package/dist/src/components/card/mono-card.d.ts +56 -0
  114. package/dist/src/components/card/mono-card.shadow.d.ts +52 -0
  115. package/dist/src/components/chart/chart-core.d.ts +43 -0
  116. package/dist/src/components/chart/chart-odata.d.ts +52 -0
  117. package/dist/src/components/chart/chart-types.d.ts +356 -0
  118. package/dist/src/components/chart/index.d.ts +8 -0
  119. package/dist/src/components/chart/index.shadow.d.ts +7 -0
  120. package/dist/src/components/chart/mono-chart-presets.d.ts +43 -0
  121. package/dist/src/components/chart/mono-chart-presets.shadow.d.ts +43 -0
  122. package/dist/src/components/chart/mono-chart.d.ts +30 -0
  123. package/dist/src/components/chart/mono-chart.shadow.d.ts +22 -0
  124. package/dist/src/components/chart/mono-data-chart.d.ts +27 -0
  125. package/dist/src/components/checkbox/checkbox-core.d.ts +53 -0
  126. package/dist/src/components/checkbox/checkbox-types.d.ts +69 -0
  127. package/dist/src/components/checkbox/checkbox-utils.d.ts +35 -0
  128. package/dist/src/components/checkbox/index.d.ts +4 -0
  129. package/dist/src/components/checkbox/index.shadow.d.ts +5 -0
  130. package/dist/src/components/checkbox/mono-checkbox.d.ts +34 -0
  131. package/dist/src/components/checkbox/mono-checkbox.shadow.d.ts +45 -0
  132. package/dist/src/components/chip/chip-core.d.ts +58 -0
  133. package/dist/src/components/chip/chip-types.d.ts +142 -0
  134. package/dist/src/components/chip/chip-utils.d.ts +24 -0
  135. package/dist/src/components/chip/index.d.ts +8 -0
  136. package/dist/src/components/chip/index.shadow.d.ts +6 -0
  137. package/dist/src/components/chip/mono-chip.d.ts +48 -0
  138. package/dist/src/components/chip/mono-chip.shadow.d.ts +33 -0
  139. package/dist/src/components/chip/mono-status-dot.d.ts +34 -0
  140. package/dist/src/components/date/date-core.d.ts +80 -0
  141. package/dist/src/components/date/date-types.d.ts +163 -0
  142. package/dist/src/components/date/index.d.ts +3 -0
  143. package/dist/src/components/date/index.shadow.d.ts +4 -0
  144. package/dist/src/components/date/mono-date.d.ts +22 -0
  145. package/dist/src/components/date/mono-date.shadow.d.ts +31 -0
  146. package/dist/src/components/drawer/drawer-core.d.ts +99 -0
  147. package/dist/src/components/drawer/drawer-types.d.ts +153 -0
  148. package/dist/src/components/drawer/index.d.ts +3 -0
  149. package/dist/src/components/drawer/index.shadow.d.ts +4 -0
  150. package/dist/src/components/drawer/mono-drawer.d.ts +45 -0
  151. package/dist/src/components/drawer/mono-drawer.shadow.d.ts +46 -0
  152. package/dist/src/components/dropdown/dropdown-core.d.ts +33 -0
  153. package/dist/src/components/dropdown/dropdown-types.d.ts +88 -0
  154. package/dist/src/components/dropdown/index.d.ts +3 -0
  155. package/dist/src/components/dropdown/index.shadow.d.ts +4 -0
  156. package/dist/src/components/dropdown/mono-dropdown.d.ts +34 -0
  157. package/dist/src/components/dropdown/mono-dropdown.shadow.d.ts +28 -0
  158. package/dist/src/components/dropdown-table/dropdown-table-core.d.ts +65 -0
  159. package/dist/src/components/dropdown-table/dropdown-table-types.d.ts +278 -0
  160. package/dist/src/components/dropdown-table/index.d.ts +5 -0
  161. package/dist/src/components/dropdown-table/index.shadow.d.ts +6 -0
  162. package/dist/src/components/dropdown-table/mono-data-dropdown.d.ts +152 -0
  163. package/dist/src/components/dropdown-table/mono-dropdown-table.d.ts +46 -0
  164. package/dist/src/components/dropdown-table/mono-dropdown-table.shadow.d.ts +22 -0
  165. package/dist/src/components/file-upload/file-upload-core.d.ts +60 -0
  166. package/dist/src/components/file-upload/file-upload-types.d.ts +145 -0
  167. package/dist/src/components/file-upload/file-upload-utils.d.ts +16 -0
  168. package/dist/src/components/file-upload/index.d.ts +4 -0
  169. package/dist/src/components/file-upload/index.shadow.d.ts +5 -0
  170. package/dist/src/components/file-upload/mono-file-upload.d.ts +33 -0
  171. package/dist/src/components/file-upload/mono-file-upload.shadow.d.ts +50 -0
  172. package/dist/src/components/filter/filter-builder-core.d.ts +36 -0
  173. package/dist/src/components/filter/filter-builder.d.ts +23 -0
  174. package/dist/src/components/filter/filter-odata.d.ts +27 -0
  175. package/dist/src/components/filter/filter-operators.d.ts +13 -0
  176. package/dist/src/components/filter/filter-types.d.ts +253 -0
  177. package/dist/src/components/filter/index.d.ts +6 -0
  178. package/dist/src/components/filter/index.shadow.d.ts +7 -0
  179. package/dist/src/components/filter/mono-filter-builder.d.ts +21 -0
  180. package/dist/src/components/filter/mono-filter-builder.shadow.d.ts +17 -0
  181. package/dist/src/components/form/form-control-core.d.ts +37 -0
  182. package/dist/src/components/form/form-rules.d.ts +25 -0
  183. package/dist/src/components/form/form-types.d.ts +307 -0
  184. package/dist/src/components/form/index.d.ts +6 -0
  185. package/dist/src/components/form/mono-form-controller.d.ts +16 -0
  186. package/dist/src/components/input/index.d.ts +6 -0
  187. package/dist/src/components/input/index.shadow.d.ts +8 -0
  188. package/dist/src/components/input/input-core.d.ts +91 -0
  189. package/dist/src/components/input/input-format.d.ts +118 -0
  190. package/dist/src/components/input/input-types.d.ts +179 -0
  191. package/dist/src/components/input/input-utils.d.ts +10 -0
  192. package/dist/src/components/input/mono-input.d.ts +46 -0
  193. package/dist/src/components/input/mono-input.shadow.d.ts +34 -0
  194. package/dist/src/components/menu/index.d.ts +6 -0
  195. package/dist/src/components/menu/index.shadow.d.ts +7 -0
  196. package/dist/src/components/menu/menu-core.d.ts +65 -0
  197. package/dist/src/components/menu/menu-render.d.ts +55 -0
  198. package/dist/src/components/menu/menu-types.d.ts +195 -0
  199. package/dist/src/components/menu/menu-utils.d.ts +53 -0
  200. package/dist/src/components/menu/mono-menu-list.d.ts +118 -0
  201. package/dist/src/components/menu/mono-menu.d.ts +39 -0
  202. package/dist/src/components/menu/mono-menu.shadow.d.ts +40 -0
  203. package/dist/src/components/modal/index.d.ts +4 -0
  204. package/dist/src/components/modal/index.shadow.d.ts +5 -0
  205. package/dist/src/components/modal/modal-core.d.ts +110 -0
  206. package/dist/src/components/modal/modal-types.d.ts +304 -0
  207. package/dist/src/components/modal/mono-modal-controller.d.ts +4 -0
  208. package/dist/src/components/modal/mono-modal.d.ts +45 -0
  209. package/dist/src/components/modal/mono-modal.shadow.d.ts +50 -0
  210. package/dist/src/components/nav/index.d.ts +4 -0
  211. package/dist/src/components/nav/index.shadow.d.ts +6 -0
  212. package/dist/src/components/nav/mono-nav.d.ts +41 -0
  213. package/dist/src/components/nav/mono-nav.shadow.d.ts +21 -0
  214. package/dist/src/components/nav/nav-core.d.ts +34 -0
  215. package/dist/src/components/nav/nav-types.d.ts +48 -0
  216. package/dist/src/components/nav/nav-utils.d.ts +12 -0
  217. package/dist/src/components/radio/index.d.ts +4 -0
  218. package/dist/src/components/radio/index.shadow.d.ts +5 -0
  219. package/dist/src/components/radio/mono-radio.d.ts +31 -0
  220. package/dist/src/components/radio/mono-radio.shadow.d.ts +35 -0
  221. package/dist/src/components/radio/radio-core.d.ts +45 -0
  222. package/dist/src/components/radio/radio-types.d.ts +58 -0
  223. package/dist/src/components/radio/radio-utils.d.ts +12 -0
  224. package/dist/src/components/rich-text-editor/index.d.ts +5 -0
  225. package/dist/src/components/rich-text-editor/index.shadow.d.ts +6 -0
  226. package/dist/src/components/rich-text-editor/mono-rich-text-editor.d.ts +31 -0
  227. package/dist/src/components/rich-text-editor/mono-rich-text-editor.shadow.d.ts +34 -0
  228. package/dist/src/components/rich-text-editor/rich-text-editor-core.d.ts +100 -0
  229. package/dist/src/components/rich-text-editor/rich-text-editor-loader.d.ts +17 -0
  230. package/dist/src/components/rich-text-editor/rich-text-editor-toolbar.d.ts +65 -0
  231. package/dist/src/components/rich-text-editor/rich-text-editor-types.d.ts +231 -0
  232. package/dist/src/components/select/index.d.ts +4 -0
  233. package/dist/src/components/select/index.shadow.d.ts +5 -0
  234. package/dist/src/components/select/mono-select.d.ts +69 -0
  235. package/dist/src/components/select/mono-select.shadow.d.ts +48 -0
  236. package/dist/src/components/select/select-core.d.ts +98 -0
  237. package/dist/src/components/select/select-types.d.ts +284 -0
  238. package/dist/src/components/select/select-utils.d.ts +7 -0
  239. package/dist/src/components/sidebar/index.d.ts +4 -0
  240. package/dist/src/components/sidebar/index.shadow.d.ts +6 -0
  241. package/dist/src/components/sidebar/mono-sidebar.d.ts +34 -0
  242. package/dist/src/components/sidebar/mono-sidebar.shadow.d.ts +27 -0
  243. package/dist/src/components/sidebar/sidebar-core.d.ts +51 -0
  244. package/dist/src/components/sidebar/sidebar-types.d.ts +119 -0
  245. package/dist/src/components/sidebar/sidebar-utils.d.ts +55 -0
  246. package/dist/src/components/switch/index.d.ts +4 -0
  247. package/dist/src/components/switch/index.shadow.d.ts +5 -0
  248. package/dist/src/components/switch/mono-switch.d.ts +31 -0
  249. package/dist/src/components/switch/mono-switch.shadow.d.ts +36 -0
  250. package/dist/src/components/switch/switch-core.d.ts +49 -0
  251. package/dist/src/components/switch/switch-types.d.ts +64 -0
  252. package/dist/src/components/switch/switch-utils.d.ts +12 -0
  253. package/dist/src/components/table/array-source.d.ts +44 -0
  254. package/dist/src/components/table/date-filter-tree.d.ts +93 -0
  255. package/dist/src/components/table/grouping.d.ts +55 -0
  256. package/dist/src/components/table/index.d.ts +33 -0
  257. package/dist/src/components/table/index.shadow.d.ts +47 -0
  258. package/dist/src/components/table/mono-data-grid.d.ts +1756 -0
  259. package/dist/src/components/table/mono-table-checkbox-core.d.ts +76 -0
  260. package/dist/src/components/table/mono-table-checkbox.d.ts +34 -0
  261. package/dist/src/components/table/mono-table-checkbox.shadow.d.ts +26 -0
  262. package/dist/src/components/table/mono-table-detail-core.d.ts +87 -0
  263. package/dist/src/components/table/mono-table-detail.d.ts +32 -0
  264. package/dist/src/components/table/mono-table-detail.shadow.d.ts +31 -0
  265. package/dist/src/components/table/mono-table-empty-core.d.ts +60 -0
  266. package/dist/src/components/table/mono-table-empty.d.ts +35 -0
  267. package/dist/src/components/table/mono-table-empty.shadow.d.ts +40 -0
  268. package/dist/src/components/table/mono-table-error-core.d.ts +84 -0
  269. package/dist/src/components/table/mono-table-error.d.ts +28 -0
  270. package/dist/src/components/table/mono-table-error.shadow.d.ts +21 -0
  271. package/dist/src/components/table/mono-table-info-core.d.ts +13 -0
  272. package/dist/src/components/table/mono-table-info.d.ts +19 -0
  273. package/dist/src/components/table/mono-table-info.shadow.d.ts +14 -0
  274. package/dist/src/components/table/mono-table-loading-core.d.ts +41 -0
  275. package/dist/src/components/table/mono-table-loading.d.ts +50 -0
  276. package/dist/src/components/table/mono-table-loading.shadow.d.ts +14 -0
  277. package/dist/src/components/table/mono-table-page-size-core.d.ts +14 -0
  278. package/dist/src/components/table/mono-table-page-size.d.ts +16 -0
  279. package/dist/src/components/table/mono-table-page-size.shadow.d.ts +11 -0
  280. package/dist/src/components/table/mono-table-paging-core.d.ts +22 -0
  281. package/dist/src/components/table/mono-table-paging-group-core.d.ts +18 -0
  282. package/dist/src/components/table/mono-table-paging-group.d.ts +20 -0
  283. package/dist/src/components/table/mono-table-paging-group.shadow.d.ts +13 -0
  284. package/dist/src/components/table/mono-table-paging.d.ts +16 -0
  285. package/dist/src/components/table/mono-table-paging.shadow.d.ts +11 -0
  286. package/dist/src/components/table/mono-table-search-core.d.ts +74 -0
  287. package/dist/src/components/table/mono-table-search.d.ts +34 -0
  288. package/dist/src/components/table/mono-table-search.shadow.d.ts +21 -0
  289. package/dist/src/components/table/mono-table-sort-core.d.ts +35 -0
  290. package/dist/src/components/table/mono-table-sort.d.ts +38 -0
  291. package/dist/src/components/table/mono-table-sort.shadow.d.ts +20 -0
  292. package/dist/src/components/table/mono-table-summary-core.d.ts +26 -0
  293. package/dist/src/components/table/mono-table-summary.d.ts +24 -0
  294. package/dist/src/components/table/mono-table-summary.shadow.d.ts +14 -0
  295. package/dist/src/components/table/mono-table-th-core.d.ts +56 -0
  296. package/dist/src/components/table/mono-table-th.d.ts +41 -0
  297. package/dist/src/components/table/mono-table-th.shadow.d.ts +19 -0
  298. package/dist/src/components/table/store-group-source.d.ts +24 -0
  299. package/dist/src/components/table/table-controller-core.d.ts +40 -0
  300. package/dist/src/components/table/table-filter-icons.d.ts +3 -0
  301. package/dist/src/components/table/table-menu-core.d.ts +65 -0
  302. package/dist/src/components/table/table-overlay.d.ts +165 -0
  303. package/dist/src/components/table/table-sort-icons.d.ts +4 -0
  304. package/dist/src/components/table/table-sort-utils.d.ts +20 -0
  305. package/dist/src/components/table/table-types.d.ts +475 -0
  306. package/dist/src/components/tabs/index.d.ts +3 -0
  307. package/dist/src/components/tabs/index.shadow.d.ts +4 -0
  308. package/dist/src/components/tabs/mono-tabs.d.ts +33 -0
  309. package/dist/src/components/tabs/mono-tabs.shadow.d.ts +37 -0
  310. package/dist/src/components/tabs/tabs-core.d.ts +57 -0
  311. package/dist/src/components/tabs/tabs-types.d.ts +65 -0
  312. package/dist/src/components/tag-input/index.d.ts +4 -0
  313. package/dist/src/components/tag-input/index.shadow.d.ts +5 -0
  314. package/dist/src/components/tag-input/mono-tag-input.d.ts +66 -0
  315. package/dist/src/components/tag-input/mono-tag-input.shadow.d.ts +40 -0
  316. package/dist/src/components/tag-input/tag-input-core.d.ts +108 -0
  317. package/dist/src/components/tag-input/tag-input-types.d.ts +420 -0
  318. package/dist/src/components/tag-input/tag-input-utils.d.ts +8 -0
  319. package/dist/src/components/textarea/index.d.ts +4 -0
  320. package/dist/src/components/textarea/index.shadow.d.ts +5 -0
  321. package/dist/src/components/textarea/mono-textarea.d.ts +29 -0
  322. package/dist/src/components/textarea/mono-textarea.shadow.d.ts +31 -0
  323. package/dist/src/components/textarea/textarea-core.d.ts +60 -0
  324. package/dist/src/components/textarea/textarea-types.d.ts +131 -0
  325. package/dist/src/components/textarea/textarea-utils.d.ts +7 -0
  326. package/dist/src/components/tooltip/control-tooltip.d.ts +36 -0
  327. package/dist/src/components/tooltip/index.d.ts +6 -0
  328. package/dist/src/components/tooltip/tooltip-config.d.ts +27 -0
  329. package/dist/src/components/tooltip/tooltip-declarative.d.ts +41 -0
  330. package/dist/src/components/tooltip/tooltip-loader.d.ts +1 -0
  331. package/dist/src/components/tooltip/tooltip-types.d.ts +110 -0
  332. package/dist/src/composables/breakpoints.d.ts +59 -0
  333. package/dist/src/composables/chip-limits.d.ts +48 -0
  334. package/dist/src/composables/chip-strip.d.ts +93 -0
  335. package/dist/src/composables/color.d.ts +103 -0
  336. package/dist/src/composables/css-class.d.ts +27 -0
  337. package/dist/src/composables/css-size.d.ts +40 -0
  338. package/dist/src/composables/data-source-controller.d.ts +113 -0
  339. package/dist/src/composables/element-props.d.ts +46 -0
  340. package/dist/src/composables/field-icons.d.ts +15 -0
  341. package/dist/src/composables/hybird-prop.d.ts +79 -0
  342. package/dist/src/composables/hydration-flush.d.ts +34 -0
  343. package/dist/src/composables/icon.d.ts +17 -0
  344. package/dist/src/composables/layout-var.d.ts +34 -0
  345. package/dist/src/composables/light-slots.d.ts +133 -0
  346. package/dist/src/composables/mdi-glyphs.d.ts +4 -0
  347. package/dist/src/composables/mono-element.d.ts +9 -0
  348. package/dist/src/composables/mono-event.d.ts +55 -0
  349. package/dist/src/composables/mono-pending.d.ts +8 -0
  350. package/dist/src/composables/mono-skeleton.d.ts +193 -0
  351. package/dist/src/composables/mono-ui.d.ts +58 -0
  352. package/dist/src/composables/notifier.d.ts +46 -0
  353. package/dist/src/composables/popup-portal.d.ts +226 -0
  354. package/dist/src/composables/popup-stack.d.ts +70 -0
  355. package/dist/src/composables/rate-limit.d.ts +108 -0
  356. package/dist/src/composables/reactive.d.ts +53 -0
  357. package/dist/src/composables/shadow-css.d.ts +42 -0
  358. package/dist/src/composables/visibility.d.ts +36 -0
  359. package/dist/src/data/theme/index.d.ts +30 -0
  360. package/dist/src/data/theme/presets.d.ts +94 -0
  361. package/dist/src/entries/index.d.ts +2 -0
  362. package/dist/src/entries/index.node.d.ts +42 -0
  363. package/dist/src/entries/search.d.ts +3 -0
  364. package/dist/src/export/detail.d.ts +29 -0
  365. package/dist/src/export/download.d.ts +9 -0
  366. package/dist/src/export/excel/index.d.ts +27 -0
  367. package/dist/src/export/excel/nodes.d.ts +123 -0
  368. package/dist/src/export/expression.d.ts +36 -0
  369. package/dist/src/export/helpers.d.ts +6 -0
  370. package/dist/src/export/index.d.ts +13 -0
  371. package/dist/src/export/markdown.d.ts +52 -0
  372. package/dist/src/export/resolve-data.d.ts +31 -0
  373. package/dist/src/export/sentinel.d.ts +97 -0
  374. package/dist/src/export/sheet-name.d.ts +45 -0
  375. package/dist/src/export/styles.d.ts +33 -0
  376. package/dist/src/export/template.d.ts +10 -0
  377. package/dist/src/export/types.d.ts +259 -0
  378. package/dist/src/import/coerce.d.ts +38 -0
  379. package/dist/src/import/index.d.ts +16 -0
  380. package/dist/src/import/match.d.ts +54 -0
  381. package/dist/src/import/parse.d.ts +15 -0
  382. package/dist/src/import/types.d.ts +153 -0
  383. package/dist/src/nuxt/index.d.ts +94 -0
  384. package/dist/src/search/data-search.d.ts +207 -0
  385. package/dist/src/search/field-path.d.ts +107 -0
  386. package/dist/src/search/filter-eval.d.ts +30 -0
  387. package/dist/src/search/index.d.ts +22 -0
  388. package/dist/src/search/odata-search.d.ts +18 -0
  389. package/dist/src/search/search-expr.d.ts +160 -0
  390. package/dist/src/utils/data-source-apply.d.ts +97 -0
  391. package/dist/src/utils/data-source-options.d.ts +116 -0
  392. package/dist/src/utils/data-source-read.d.ts +85 -0
  393. package/dist/src/utils/data-source-summary.d.ts +55 -0
  394. package/dist/src/utils/normalize-error.d.ts +90 -0
  395. package/dist/src/vite/index.d.ts +48 -0
  396. package/dist/src/vite/mono-client-only.d.ts +35 -0
  397. package/dist/src/vite/mono-ssr-stub.d.ts +20 -0
  398. package/dist/src/vite/shadow-manifest.d.ts +8 -0
  399. package/dist/styles-BIJ31TM4.js +20146 -0
  400. package/dist/tooltip-DQqNpqk2.js +795 -0
  401. package/dist/tooltip.d.ts +1 -0
  402. package/dist/tooltip.js +2 -0
  403. package/dist/ui/accordion.d.ts +1 -0
  404. package/dist/ui/accordion.js +466 -0
  405. package/dist/ui/alert.d.ts +1 -0
  406. package/dist/ui/alert.js +221 -0
  407. package/dist/ui/breadcrumb.d.ts +1 -0
  408. package/dist/ui/breadcrumb.js +902 -0
  409. package/dist/ui/button-dropdown.d.ts +1 -0
  410. package/dist/ui/button-dropdown.js +679 -0
  411. package/dist/ui/button.d.ts +1 -0
  412. package/dist/ui/button.js +63 -0
  413. package/dist/ui/card.d.ts +1 -0
  414. package/dist/ui/card.js +524 -0
  415. package/dist/ui/chart.d.ts +1 -0
  416. package/dist/ui/chart.js +885 -0
  417. package/dist/ui/checkbox.d.ts +1 -0
  418. package/dist/ui/checkbox.js +413 -0
  419. package/dist/ui/chip.d.ts +1 -0
  420. package/dist/ui/chip.js +558 -0
  421. package/dist/ui/date.d.ts +1 -0
  422. package/dist/ui/date.js +686 -0
  423. package/dist/ui/drawer.d.ts +1 -0
  424. package/dist/ui/drawer.js +901 -0
  425. package/dist/ui/dropdown-table.d.ts +1 -0
  426. package/dist/ui/dropdown-table.js +1291 -0
  427. package/dist/ui/dropdown.d.ts +1 -0
  428. package/dist/ui/dropdown.js +586 -0
  429. package/dist/ui/file-upload.d.ts +1 -0
  430. package/dist/ui/file-upload.js +688 -0
  431. package/dist/ui/filter.d.ts +1 -0
  432. package/dist/ui/filter.js +400 -0
  433. package/dist/ui/font/files/geist-47c091c9.woff2 +0 -0
  434. package/dist/ui/font/files/geist-8dd77544.woff2 +0 -0
  435. package/dist/ui/font/files/geist-b9248b1e.woff2 +0 -0
  436. package/dist/ui/font/files/geist-d40d74b4.woff2 +0 -0
  437. package/dist/ui/font/files/geist-f493429a.woff2 +0 -0
  438. package/dist/ui/font/files/geistmono-03737868.woff2 +0 -0
  439. package/dist/ui/font/files/geistmono-421a7e38.woff2 +0 -0
  440. package/dist/ui/font/files/geistmono-48ef518d.woff2 +0 -0
  441. package/dist/ui/font/files/geistmono-5df35d39.woff2 +0 -0
  442. package/dist/ui/font/files/geistmono-7de289a4.woff2 +0 -0
  443. package/dist/ui/font/files/geistmono-e976128f.woff2 +0 -0
  444. package/dist/ui/font/files/inter-05cf802c.woff2 +0 -0
  445. package/dist/ui/font/files/inter-2b2f25a4.woff2 +0 -0
  446. package/dist/ui/font/files/inter-467acc7a.woff2 +0 -0
  447. package/dist/ui/font/files/inter-6e85163c.woff2 +0 -0
  448. package/dist/ui/font/files/inter-7048add3.woff2 +0 -0
  449. package/dist/ui/font/files/inter-9be0371e.woff2 +0 -0
  450. package/dist/ui/font/files/inter-a28b7e31.woff2 +0 -0
  451. package/dist/ui/font/files/poppins-054df55a.woff2 +0 -0
  452. package/dist/ui/font/files/poppins-0ee5dc9a.woff2 +0 -0
  453. package/dist/ui/font/files/poppins-0f44cb18.woff2 +0 -0
  454. package/dist/ui/font/files/poppins-0ff0d30c.woff2 +0 -0
  455. package/dist/ui/font/files/poppins-13045147.woff2 +0 -0
  456. package/dist/ui/font/files/poppins-1db57cd9.woff2 +0 -0
  457. package/dist/ui/font/files/poppins-2cf2a902.woff2 +0 -0
  458. package/dist/ui/font/files/poppins-39e7f079.woff2 +0 -0
  459. package/dist/ui/font/files/poppins-9607042d.woff2 +0 -0
  460. package/dist/ui/font/files/poppins-9a88fc1f.woff2 +0 -0
  461. package/dist/ui/font/files/poppins-b8f4f752.woff2 +0 -0
  462. package/dist/ui/font/files/poppins-f5e57db4.woff2 +0 -0
  463. package/dist/ui/font/geist-mono.css +104 -0
  464. package/dist/ui/font/geist.css +168 -0
  465. package/dist/ui/font/inter.css +232 -0
  466. package/dist/ui/font/poppins.css +104 -0
  467. package/dist/ui/form.d.ts +1 -0
  468. package/dist/ui/form.js +3 -0
  469. package/dist/ui/index.css +21989 -0
  470. package/dist/ui/input.d.ts +1 -0
  471. package/dist/ui/input.js +1176 -0
  472. package/dist/ui/menu.d.ts +1 -0
  473. package/dist/ui/menu.js +1289 -0
  474. package/dist/ui/modal.d.ts +1 -0
  475. package/dist/ui/modal.js +996 -0
  476. package/dist/ui/nav.d.ts +1 -0
  477. package/dist/ui/nav.js +295 -0
  478. package/dist/ui/radio.d.ts +1 -0
  479. package/dist/ui/radio.js +379 -0
  480. package/dist/ui/rich-text-editor.d.ts +1 -0
  481. package/dist/ui/rich-text-editor.js +1338 -0
  482. package/dist/ui/select.d.ts +1 -0
  483. package/dist/ui/select.js +2200 -0
  484. package/dist/ui/shadow/accordion.js +442 -0
  485. package/dist/ui/shadow/alert.js +218 -0
  486. package/dist/ui/shadow/breadcrumb.js +919 -0
  487. package/dist/ui/shadow/button-dropdown.js +696 -0
  488. package/dist/ui/shadow/button.js +63 -0
  489. package/dist/ui/shadow/card.js +538 -0
  490. package/dist/ui/shadow/chart.js +1685 -0
  491. package/dist/ui/shadow/checkbox.js +457 -0
  492. package/dist/ui/shadow/chip.js +559 -0
  493. package/dist/ui/shadow/date.js +712 -0
  494. package/dist/ui/shadow/drawer.js +869 -0
  495. package/dist/ui/shadow/dropdown-table.js +1620 -0
  496. package/dist/ui/shadow/dropdown.js +547 -0
  497. package/dist/ui/shadow/file-upload.js +731 -0
  498. package/dist/ui/shadow/filter.js +402 -0
  499. package/dist/ui/shadow/input.js +1150 -0
  500. package/dist/ui/shadow/menu.js +899 -0
  501. package/dist/ui/shadow/modal.js +1194 -0
  502. package/dist/ui/shadow/nav.js +240 -0
  503. package/dist/ui/shadow/radio.js +408 -0
  504. package/dist/ui/shadow/rich-text-editor.js +1344 -0
  505. package/dist/ui/shadow/select.js +2167 -0
  506. package/dist/ui/shadow/sidebar.js +606 -0
  507. package/dist/ui/shadow/switch.js +428 -0
  508. package/dist/ui/shadow/table.js +4755 -0
  509. package/dist/ui/shadow/tabs.js +372 -0
  510. package/dist/ui/shadow/tag-input.js +2974 -0
  511. package/dist/ui/shadow/textarea.js +816 -0
  512. package/dist/ui/sidebar.d.ts +1 -0
  513. package/dist/ui/sidebar.js +659 -0
  514. package/dist/ui/switch.d.ts +1 -0
  515. package/dist/ui/switch.js +398 -0
  516. package/dist/ui/table.d.ts +1 -0
  517. package/dist/ui/table.js +4654 -0
  518. package/dist/ui/tabs.d.ts +1 -0
  519. package/dist/ui/tabs.js +379 -0
  520. package/dist/ui/tag-input.d.ts +1 -0
  521. package/dist/ui/tag-input.js +2947 -0
  522. package/dist/ui/textarea.d.ts +1 -0
  523. package/dist/ui/textarea.js +819 -0
  524. package/dist/ui/theme/legacy.css +293 -0
  525. package/dist/ui/theme/luma.css +743 -0
  526. package/dist/ui/theme/lyra.css +754 -0
  527. package/dist/ui/theme/maia.css +673 -0
  528. package/dist/ui/theme/mira.css +802 -0
  529. package/dist/ui/theme/nova.css +662 -0
  530. package/dist/ui/theme/one.css +699 -0
  531. package/dist/ui/theme/rhea.css +742 -0
  532. package/dist/ui/theme/sera.css +845 -0
  533. package/dist/ui/theme/tokens.css +261 -0
  534. package/dist/ui/theme/vega.css +467 -0
  535. package/dist/vite-C5iUK7so.js +329 -0
  536. package/dist/vite.d.ts +1 -0
  537. package/dist/vite.js +2 -0
  538. package/dist/vue.d.ts +282 -0
  539. package/package.json +411 -3
@@ -0,0 +1,2947 @@
1
+ import { r as readAllRows } from "../data-source-read-DL88aH8t.js";
2
+ import { a as errorTitle, f as MonoSourceSearch, i as errorText, n as describeError, x as searchRowPredicate, y as resolveSearchFields } from "../normalize-error-Gcgmgh5i.js";
3
+ import { n as unwrapReactive, r as unwrapReactiveDeep } from "../reactive-D3EERqgO.js";
4
+ import { l as monoHostChildNodes } from "../mono-ui-CPV7rrdo.js";
5
+ import { t as customElement } from "../mono-element-B0kP_96P.js";
6
+ import { a as defineHybridPropAliases, n as arrayHasChanged, r as booleanStringConverter, t as __decorate } from "../decorate-DEXtNagw.js";
7
+ import { t as dispatchMonoEvent } from "../mono-event-Bi1qP9uN.js";
8
+ import { s as placeSlotNode, t as LateSlotWatcher } from "../light-slots-DW1WgfgT.js";
9
+ import { n as toCssSize, t as buildSizeStyle } from "../css-size-DhHSVZJK.js";
10
+ import { t as PopupPortalController } from "../popup-portal-BziRX1yG.js";
11
+ import { a as spinnerIcon, i as refreshIcon, n as chevronIcon, t as caretIcon } from "../field-icons-DELrSdqJ.js";
12
+ import { t as MonoFormControlCore } from "../form-control-core-eeRr0zLU.js";
13
+ import { t as DataSourceController } from "../data-source-controller-B_rgHCjw.js";
14
+ import { n as visibleChipCap, r as ChipStripController, t as resolveChipLimit } from "../chip-limits-BMoO31JM.js";
15
+ import { LitElement, html, isServer, nothing, unsafeCSS } from "lit";
16
+ import { property, query, state } from "lit/decorators.js";
17
+ import { ifDefined } from "lit/directives/if-defined.js";
18
+ import { styleMap } from "lit/directives/style-map.js";
19
+ //#region src/components/tag-input/tag-input-core.ts
20
+ var numberStringConverter = {
21
+ fromAttribute(value) {
22
+ if (value === null || value === "") return void 0;
23
+ const parsed = Number(value);
24
+ return Number.isFinite(parsed) ? parsed : void 0;
25
+ },
26
+ toAttribute(value) {
27
+ if (value === void 0 || value === null) return null;
28
+ return String(value);
29
+ }
30
+ };
31
+ /**
32
+ * `MonoTagInputCore` — render-mode-agnostic logic for `mono-tag-input` (props,
33
+ * hybrid aliases, array value/model sync, DataSource paging, search, grouping,
34
+ * keyboard, tag chips, the popup controller, and the full `render()`). SSR-safe:
35
+ * every `document`/`window`/focus access is `isServer`-guarded. Each build
36
+ * supplies `createRenderRoot()` + `static styles`, the slot strategy (light
37
+ * captures children into `data-mono-slot` placeholders; shadow uses native
38
+ * `<slot>`), and the `_slotOutlet` / `renderIcon` hooks. Mirrors `select-core`.
39
+ */
40
+ var MonoTagInputCore = (superClass) => {
41
+ class MonoTagInputCoreClass extends MonoFormControlCore(superClass) {
42
+ constructor(...args) {
43
+ super(...args);
44
+ this.size = "md";
45
+ this.color = "primary";
46
+ this.variant = "outlined";
47
+ this.chip = {};
48
+ this.modelValue = [];
49
+ this.value = [];
50
+ this.name = "";
51
+ this.label = "";
52
+ this.placeholder = "Add tag...";
53
+ this.loadingText = "Loading…";
54
+ this.retryLabel = "Retry";
55
+ this.loading = false;
56
+ this.loadingError = null;
57
+ this.helperText = "";
58
+ this.validationState = "default";
59
+ this.validationMessage = "";
60
+ this.errorMessage = "";
61
+ this.successMessage = "";
62
+ this.disabled = false;
63
+ this.readonly = false;
64
+ this.required = false;
65
+ this.clearable = false;
66
+ this.allowCustom = true;
67
+ this.checkable = false;
68
+ this.selectAll = true;
69
+ this.selectAllLabel = "All";
70
+ this.groupSelectAll = true;
71
+ this.items = [];
72
+ this.dataSource = null;
73
+ this.immediate = true;
74
+ this.pageSize = 10;
75
+ this.dropdownHeight = "";
76
+ this.dropdownMaxHeight = "";
77
+ this.flip = true;
78
+ this.shift = true;
79
+ this.keyValue = "";
80
+ this.displayValue = "";
81
+ this.displayGroup = [];
82
+ this.groupKey = "key";
83
+ this.groupItems = "items";
84
+ this.group = false;
85
+ this.groupSticky = false;
86
+ this.searchable = true;
87
+ this.stayOpen = false;
88
+ this.searchValue = "";
89
+ this.searchOperation = "contains";
90
+ this.searchDebounce = 300;
91
+ this.cssClass = {};
92
+ this.cssClassName = "";
93
+ this._inputValue = "";
94
+ this._open = false;
95
+ this._activeIndex = -1;
96
+ this._cursorPending = false;
97
+ this._moreOpen = false;
98
+ this._selectAllPending = false;
99
+ this._scrollAutoMaxHeight = "";
100
+ this._hasLabelSlotState = false;
101
+ this._hasHelperSlotState = false;
102
+ this._chipStrip = new ChipStripController(this, {
103
+ strip: () => this.renderRoot?.querySelector(".mono-tag-input-chip-strip"),
104
+ enabled: () => this._chipBehaviour === "inline"
105
+ });
106
+ this._popup = new PopupPortalController(this, {
107
+ getPanel: () => this.renderRoot.querySelector(".mono-tag-input-dropdown"),
108
+ getAnchor: () => this.renderRoot.querySelector(".mono-tag-input-field"),
109
+ getStyleScope: () => this.renderRoot.querySelector(".mono-tag-input"),
110
+ isOpen: () => this._open,
111
+ matchWidth: () => !toCssSize(this.dropdown?.width),
112
+ offset: () => 6,
113
+ flip: () => this.flip,
114
+ shift: () => this.shift,
115
+ constrainSize: () => true
116
+ });
117
+ this._morePopup = new PopupPortalController(this, {
118
+ getPanel: () => this.renderRoot.querySelector(".mono-tag-input-more-panel"),
119
+ getAnchor: () => this.renderRoot.querySelector(".mono-tag-input-field"),
120
+ getStyleScope: () => this.renderRoot.querySelector(".mono-tag-input"),
121
+ isOpen: () => this._moreOpen,
122
+ matchWidth: () => true,
123
+ offset: () => 6,
124
+ flip: () => true,
125
+ shift: () => true,
126
+ constrainSize: () => true
127
+ });
128
+ this._inputId = `mono-tag-input-${Math.random().toString(36).slice(2)}`;
129
+ this._messageId = `${this._inputId}-message`;
130
+ this._listboxId = `${this._inputId}-listbox`;
131
+ this._lateListSlot = new LateSlotWatcher(this, "list", () => this._onLateListSlot());
132
+ this._sourceSearch = new MonoSourceSearch();
133
+ this._searchVersion = 0;
134
+ this._appliedQuery = "";
135
+ this._appFailure = null;
136
+ this._retry = (event) => {
137
+ event.preventDefault();
138
+ event.stopPropagation();
139
+ const error = this._failure;
140
+ if (this.disabled || this._busy || !error) return;
141
+ const fromApp = !!this._appFailure;
142
+ dispatchMonoEvent(this, "retry", {
143
+ error,
144
+ source: fromApp ? "app" : "dataSource"
145
+ });
146
+ if (fromApp || !this.dataSource || !this._ds.error) return;
147
+ const clearSearch = !!this._appliedQuery && this._serverSearch();
148
+ this._ds.retry(clearSearch ? () => this._pushSearch("") : void 0);
149
+ };
150
+ this._selectedItemCache = /* @__PURE__ */ new Map();
151
+ this._handleDocumentClick = (event) => {
152
+ if (this.stayOpen) return;
153
+ if (!this._open && !this._moreOpen) return;
154
+ const path = event.composedPath();
155
+ if (path.includes(this) || this._popup.containsInPath(path) || this._morePopup.containsInPath(path)) return;
156
+ this._close();
157
+ this._moreOpen = false;
158
+ };
159
+ this._handleDocumentFocusIn = (event) => {
160
+ if (this.stayOpen) return;
161
+ if (!this._open && !this._moreOpen) return;
162
+ const path = event.composedPath();
163
+ if (path.includes(this) || this._popup.containsInPath(path) || this._morePopup.containsInPath(path)) return;
164
+ this._close();
165
+ this._moreOpen = false;
166
+ };
167
+ this._handleDocumentKeydown = (event) => {
168
+ if (!this._open && !this._moreOpen) return;
169
+ if (event.key === "Escape") {
170
+ event.preventDefault();
171
+ this._close();
172
+ this._moreOpen = false;
173
+ }
174
+ };
175
+ this._renderedChipCount = 0;
176
+ this._measuredChipCount = 0;
177
+ this._handleDropdownScroll = (event) => {
178
+ if (this._loadMoreMode !== "scroll") return;
179
+ if (this._ds.loadingMore || this._ds.atLastPage) return;
180
+ const el = event.currentTarget;
181
+ if (!el) return;
182
+ if (el.scrollHeight - el.scrollTop - el.clientHeight <= 24) this._ds.loadMore();
183
+ };
184
+ this._hasListSlotState = false;
185
+ this._publishedEntries = [];
186
+ this._onListSlotClick = (event) => {
187
+ if (this._inert) return;
188
+ const target = event.target;
189
+ const entry = target ? this._entryFromNode(target) : void 0;
190
+ if (!entry) return;
191
+ if (entry.type === "group") {
192
+ if (!this.checkable || !this.groupSelectAll) return;
193
+ const usable = (entry.items ?? []).filter((item) => this._isSelectable(item));
194
+ if (!usable.length) return;
195
+ event.preventDefault();
196
+ this._toggleMany(usable, event);
197
+ return;
198
+ }
199
+ const item = entry.item;
200
+ if (!item || !this._isSelectable(item)) return;
201
+ event.preventDefault();
202
+ this._toggleValue(this._resolveItemValue(item), event);
203
+ };
204
+ defineHybridPropAliases(this, [
205
+ "modelValue",
206
+ "loadingText",
207
+ "loadingError",
208
+ "helperText",
209
+ "validationState",
210
+ "validationMessage",
211
+ "errorMessage",
212
+ "successMessage",
213
+ "allowCustom",
214
+ "maxVisible",
215
+ "minVisible",
216
+ "ariaLabelText",
217
+ "cssClass",
218
+ "keyValue",
219
+ "displayValue",
220
+ "displayGroup",
221
+ "groupKey",
222
+ "groupItems",
223
+ "groupSticky",
224
+ "groupSelectAll",
225
+ "selectAll",
226
+ "selectAllLabel",
227
+ "searchValue",
228
+ "searchOperation",
229
+ "searchDebounce",
230
+ "dataSource",
231
+ "loadMore",
232
+ "pageSize",
233
+ "dropdownHeight",
234
+ "dropdownMaxHeight",
235
+ "minWidth",
236
+ "maxWidth",
237
+ "minHeight",
238
+ "maxHeight",
239
+ "stayOpen"
240
+ ]);
241
+ /**
242
+ * Vue support:
243
+ *
244
+ * <mono-tag-input :cssClass="{}" />
245
+ * <mono-tag-input :css-class="{}" />
246
+ * <mono-tag-input :cssclass="{}" />
247
+ */
248
+ Object.defineProperty(this, "css-class", {
249
+ get: () => this.cssClass,
250
+ set: (value) => {
251
+ this._setCssClass(value);
252
+ },
253
+ configurable: true,
254
+ enumerable: false
255
+ });
256
+ Object.defineProperty(this, "cssclass", {
257
+ get: () => this.cssClass,
258
+ set: (value) => {
259
+ this._setCssClass(value);
260
+ },
261
+ configurable: true,
262
+ enumerable: false
263
+ });
264
+ Object.defineProperty(this, "ariaLabel", {
265
+ get: () => this.ariaLabelText,
266
+ set: (value) => {
267
+ this.ariaLabelText = value == null ? void 0 : String(value);
268
+ },
269
+ configurable: true,
270
+ enumerable: false
271
+ });
272
+ Object.defineProperty(this, "aria-label", {
273
+ get: () => this.ariaLabelText,
274
+ set: (value) => {
275
+ this.ariaLabelText = value == null ? void 0 : String(value);
276
+ },
277
+ configurable: true,
278
+ enumerable: false
279
+ });
280
+ Object.defineProperty(this, "arialabel", {
281
+ get: () => this.ariaLabelText,
282
+ set: (value) => {
283
+ this.ariaLabelText = value == null ? void 0 : String(value);
284
+ },
285
+ configurable: true,
286
+ enumerable: false
287
+ });
288
+ this._ds = new DataSourceController(this, {
289
+ getDataSource: () => this.dataSource,
290
+ getItems: () => this.items,
291
+ getImmediate: () => this.immediate,
292
+ getLoadMoreMode: () => this._loadMoreMode,
293
+ getPageSize: () => this._pageSize
294
+ });
295
+ }
296
+ static {
297
+ this.monoPendingAuto = "data";
298
+ }
299
+ _monoPendingReady() {
300
+ return !this.dataSource || !this._ds.loading;
301
+ }
302
+ static get observedAttributes() {
303
+ return [
304
+ ...super.observedAttributes ?? [],
305
+ "modelvalue",
306
+ "loadingtext",
307
+ "loadingerror",
308
+ "helpertext",
309
+ "validationstate",
310
+ "validationmessage",
311
+ "errormessage",
312
+ "successmessage",
313
+ "allowcustom",
314
+ "maxvisible",
315
+ "minvisible",
316
+ "arialabeltext",
317
+ "arialabel",
318
+ "css-class",
319
+ "cssclass",
320
+ "chip",
321
+ "keyvalue",
322
+ "displayvalue",
323
+ "display-value",
324
+ "stayopen"
325
+ ];
326
+ }
327
+ attributeChangedCallback(name, oldValue, newValue) {
328
+ super.attributeChangedCallback(name, oldValue, newValue);
329
+ if (oldValue === newValue) return;
330
+ if (name === "modelvalue") {
331
+ this.modelValue = this._normalizeValue(newValue);
332
+ return;
333
+ }
334
+ if (name === "loadingtext") {
335
+ this.loadingText = newValue ?? "Loading…";
336
+ return;
337
+ }
338
+ if (name === "loadingerror") {
339
+ this.loadingError = newValue;
340
+ return;
341
+ }
342
+ if (name === "helpertext") {
343
+ this.helperText = newValue ?? "";
344
+ return;
345
+ }
346
+ if (name === "validationstate") {
347
+ this.validationState = newValue ?? "default";
348
+ return;
349
+ }
350
+ if (name === "validationmessage") {
351
+ this.validationMessage = newValue ?? "";
352
+ return;
353
+ }
354
+ if (name === "errormessage") {
355
+ this.errorMessage = newValue ?? "";
356
+ return;
357
+ }
358
+ if (name === "successmessage") {
359
+ this.successMessage = newValue ?? "";
360
+ return;
361
+ }
362
+ if (name === "allowcustom") {
363
+ this.allowCustom = this._toBoolean(newValue);
364
+ return;
365
+ }
366
+ if (name === "maxvisible") {
367
+ this.maxVisible = this._toOptionalNumber(newValue);
368
+ return;
369
+ }
370
+ if (name === "minvisible") {
371
+ this.minVisible = this._toOptionalNumber(newValue);
372
+ return;
373
+ }
374
+ if (name === "arialabeltext" || name === "arialabel") {
375
+ this.ariaLabelText = newValue ?? void 0;
376
+ return;
377
+ }
378
+ if (name === "keyvalue") {
379
+ this.keyValue = newValue ?? "";
380
+ return;
381
+ }
382
+ if (name === "displayvalue" || name === "display-value") {
383
+ if (typeof this.displayValue === "function") return;
384
+ const next = newValue ?? "";
385
+ if (this._looksLikeSerializedFunction(next)) return;
386
+ this.displayValue = next;
387
+ return;
388
+ }
389
+ if (name === "stayopen") {
390
+ this.stayOpen = this._toBoolean(newValue);
391
+ return;
392
+ }
393
+ if (name === "css-class" || name === "cssclass") {
394
+ this._setCssClass(newValue);
395
+ return;
396
+ }
397
+ if (name === "chip") this._setChip(newValue);
398
+ }
399
+ /**
400
+ * The dropdown panel is relocated into a `<body>` portal while open — query
401
+ * it through `panelRoot` (the portal when adopted, else the host render root).
402
+ */
403
+ get _dropdownEl() {
404
+ return this._popup.panelRoot.querySelector(".mono-tag-input-dropdown");
405
+ }
406
+ /**
407
+ * Where the consumer's list wrapper is parked, through the SAME portal-aware root as the panel
408
+ * itself — while the dropdown is open it lives in a body portal, so a host query would miss it.
409
+ */
410
+ get _listSlotTarget() {
411
+ return this._popup.panelRoot.querySelector("[data-mono-slot=\"list\"]");
412
+ }
413
+ /** A late wrapper arrived. Overridden per build — one adopts it, the other rescans. */
414
+ _onLateListSlot() {}
415
+ connectedCallback() {
416
+ super.connectedCallback();
417
+ this._lateListSlot.start();
418
+ if (isServer) return;
419
+ document.addEventListener("click", this._handleDocumentClick, true);
420
+ document.addEventListener("focusin", this._handleDocumentFocusIn, true);
421
+ document.addEventListener("keydown", this._handleDocumentKeydown);
422
+ }
423
+ disconnectedCallback() {
424
+ if (this._searchTimer) {
425
+ clearTimeout(this._searchTimer);
426
+ this._searchTimer = void 0;
427
+ }
428
+ this._sourceSearch.clear(this.dataSource);
429
+ this._lateListSlot.stop();
430
+ this._stopWatchingListChrome();
431
+ if (!isServer) {
432
+ document.removeEventListener("click", this._handleDocumentClick, true);
433
+ document.removeEventListener("focusin", this._handleDocumentFocusIn, true);
434
+ document.removeEventListener("keydown", this._handleDocumentKeydown);
435
+ }
436
+ super.disconnectedCallback();
437
+ }
438
+ willUpdate(changed) {
439
+ for (const key of [
440
+ "disabled",
441
+ "loading",
442
+ "readonly",
443
+ "required",
444
+ "clearable",
445
+ "allowCustom",
446
+ "checkable",
447
+ "immediate",
448
+ "group",
449
+ "groupSticky",
450
+ "searchable",
451
+ "stayOpen",
452
+ "selectAll",
453
+ "groupSelectAll"
454
+ ]) {
455
+ const v = this[key];
456
+ if (typeof v !== "boolean") this[key] = this._toBoolean(v);
457
+ }
458
+ if (changed.has("loadingError")) {
459
+ const v = this.loadingError;
460
+ this._appFailure = v == null || v === false || v === "" ? null : describeError(v === true ? void 0 : v);
461
+ }
462
+ if (this._open && this._dsInert) {
463
+ this._open = false;
464
+ this._dropQuery();
465
+ }
466
+ if (changed.has("modelValue") && !this._arrayEqual(this.value, this.modelValue)) this.value = [...unwrapReactiveDeep(this.modelValue)];
467
+ if (changed.has("value") && !this._arrayEqual(this.modelValue, this.value)) this.modelValue = [...unwrapReactiveDeep(this.value)];
468
+ if (this.group && (changed.has("dataSource") || changed.has("displayGroup") || changed.has("group"))) {
469
+ const fields = this._groupSortFields();
470
+ if (fields.length) this.dataSource?.sort?.(fields);
471
+ }
472
+ if (changed.has("dataSource")) {
473
+ this._ds.bind(this.dataSource);
474
+ this._sourceSearch.bind(this.dataSource);
475
+ }
476
+ if (changed.has("searchValue") || changed.has("searchOperation") || changed.has("displayValue") || changed.has("keyValue") || changed.has("dataSource") || changed.has("items")) this._searchVersion++;
477
+ if (changed.has("immediate")) this._ds.maybeImmediateLoad();
478
+ if (changed.has("loadMore")) this._ds.onLoadMoreModeChange();
479
+ if (changed.has("items") || changed.has("loadMore") || changed.has("pageSize")) this._ds.resetVisible();
480
+ }
481
+ updated(changed) {
482
+ super.updated(changed);
483
+ this._syncListEntries();
484
+ if (isServer) return;
485
+ this._rememberSelected(this._selectedValues);
486
+ if (changed.has("_open")) {
487
+ this._cursorPending = this._open;
488
+ if (!this._open) this._activeIndex = -1;
489
+ }
490
+ if (this._moreOpen && !this._overflowChips.length) this._moreOpen = false;
491
+ if (this._cursorPending && this._open && this._filteredItems.length) {
492
+ this._activeIndex = this._initialActiveIndex();
493
+ this._cursorPending = false;
494
+ }
495
+ if (changed.has("_activeIndex") && this._open && this._activeIndex >= 0) (this._popup.panelRoot?.querySelectorAll?.(".mono-tag-input-item")?.[this._activeIndex])?.scrollIntoView?.({ block: "nearest" });
496
+ this._updateScrollAutoHeight();
497
+ if (changed.has("chip") || changed.has("size") || changed.has("disabled") || changed.has("readonly") || this._renderedChipCount !== this._measuredChipCount) {
498
+ this._measuredChipCount = this._renderedChipCount;
499
+ this._chipStrip.invalidate();
500
+ }
501
+ }
502
+ _setCssClass(value) {
503
+ if (value == null) {
504
+ this.cssClass = {};
505
+ this.cssClassName = "";
506
+ return;
507
+ }
508
+ if (typeof value === "object") {
509
+ this.cssClass = value;
510
+ return;
511
+ }
512
+ if (typeof value === "string") {
513
+ const trimmed = value.trim();
514
+ if (!trimmed) {
515
+ this.cssClass = {};
516
+ this.cssClassName = "";
517
+ return;
518
+ }
519
+ /**
520
+ * Optional HTML object support:
521
+ *
522
+ * <mono-tag-input css-class='{"root":"...", "field":"..."}'></mono-tag-input>
523
+ */
524
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) try {
525
+ this.cssClass = JSON.parse(trimmed);
526
+ return;
527
+ } catch {}
528
+ this.cssClassName = trimmed;
529
+ }
530
+ }
531
+ /**
532
+ * `chip` is an object prop, so the real binding is `:chip.prop="{…}"`. This
533
+ * covers the two ways a *string* can arrive: a hand-written JSON attribute
534
+ * (`chip='{"size":"md"}'`, incl. DSD/SSR), and Vue's `String(value)` mirror of
535
+ * a plain `:chip="{…}"` binding — which yields `"[object Object]"` and must be
536
+ * ignored, or it would wipe the property set moments later.
537
+ */
538
+ _setChip(value) {
539
+ if (value == null) {
540
+ this.chip = {};
541
+ return;
542
+ }
543
+ if (typeof value === "object") {
544
+ this.chip = value;
545
+ return;
546
+ }
547
+ if (typeof value !== "string") return;
548
+ const trimmed = value.trim();
549
+ if (!trimmed) {
550
+ this.chip = {};
551
+ return;
552
+ }
553
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return;
554
+ try {
555
+ this.chip = JSON.parse(trimmed);
556
+ } catch {}
557
+ }
558
+ _toBoolean(value) {
559
+ if (typeof value === "boolean") return value;
560
+ if (typeof value === "string") {
561
+ const normalized = value.toLowerCase().trim();
562
+ return normalized === "" || normalized === "true";
563
+ }
564
+ return Boolean(value);
565
+ }
566
+ _toOptionalNumber(value) {
567
+ if (value === void 0 || value === null || value === "") return void 0;
568
+ const parsed = Number(value);
569
+ return Number.isFinite(parsed) ? parsed : void 0;
570
+ }
571
+ _normalizeValue(value) {
572
+ if (Array.isArray(value)) return value.filter((item) => item !== null && item !== void 0);
573
+ if (typeof value === "string") {
574
+ const trimmed = value.trim();
575
+ if (!trimmed) return [];
576
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) try {
577
+ return this._normalizeValue(JSON.parse(trimmed));
578
+ } catch {
579
+ return [];
580
+ }
581
+ return trimmed.split(",").map((item) => item.trim()).filter(Boolean);
582
+ }
583
+ return [];
584
+ }
585
+ _normalizeItems(items) {
586
+ if (Array.isArray(items)) return items.map((item) => {
587
+ if (typeof item === "object" && item !== null) return item;
588
+ return { value: item };
589
+ });
590
+ if (typeof items === "string") try {
591
+ const parsed = JSON.parse(items);
592
+ return this._normalizeItems(parsed);
593
+ } catch {
594
+ return [];
595
+ }
596
+ return [];
597
+ }
598
+ _resolveItemValue(item) {
599
+ if (item == null) return item;
600
+ if (typeof item !== "object") return item;
601
+ if (this.keyValue && this.keyValue in item) return item[this.keyValue];
602
+ if (!this.keyValue) {
603
+ if ("value" in item) return item.value;
604
+ return item;
605
+ }
606
+ }
607
+ /** Whether `item` resolves to a value that can actually be stored (see above). */
608
+ _isSelectable(item) {
609
+ if (item == null || item.disabled) return false;
610
+ return this._resolveItemValue(item) !== void 0;
611
+ }
612
+ _resolveItemDisplay(item) {
613
+ if (item == null) return "";
614
+ if (typeof this.displayValue === "function") return String(this.displayValue(item));
615
+ if (typeof this.displayValue === "string" && this.displayValue) {
616
+ if (typeof item === "object" && this.displayValue in item) return String(item[this.displayValue]);
617
+ return "";
618
+ }
619
+ if (typeof item === "object" && "label" in item) {
620
+ const label = item.label;
621
+ return label == null ? "" : String(label);
622
+ }
623
+ if (typeof item === "object" && "value" in item) {
624
+ const value = item.value;
625
+ return value == null ? "" : String(value);
626
+ }
627
+ return String(item);
628
+ }
629
+ _looksLikeSerializedFunction(value) {
630
+ const trimmed = value.trim();
631
+ if (!trimmed) return false;
632
+ return /^(?:async\s+)?(?:function\b|\([^)]*\)\s*=>|[A-Za-z_$][\w$]*\s*=>)/.test(trimmed);
633
+ }
634
+ /**
635
+ * Value equality. With no `key-value` the whole item IS the value, so this is
636
+ * identity — with one correction that is load-bearing under Vue.
637
+ *
638
+ * The model round-trips through the consumer's `ref`, which hands each tag back
639
+ * wrapped in a **reactive Proxy**; `items` normally stays raw, so `proxy === row`
640
+ * is false, an already-selected option reads as unselected, and clicking it
641
+ * again APPENDS a duplicate instead of toggling it off. Comparing the raw
642
+ * targets restores it. Still identity, not deep equality: two distinct rows with
643
+ * equal contents remain different values.
644
+ */
645
+ _isSameValue(a, b) {
646
+ if (a === b) return true;
647
+ if (a == null || b == null) return false;
648
+ const rawA = unwrapReactive(a);
649
+ const rawB = unwrapReactive(b);
650
+ if (rawA === rawB) return true;
651
+ if (typeof rawA !== "object" || typeof rawB !== "object") return false;
652
+ return false;
653
+ }
654
+ _arrayEqual(a, b) {
655
+ if (a.length !== b.length) return false;
656
+ return a.every((item, index) => this._isSameValue(item, b[index]));
657
+ }
658
+ _cls(base, key) {
659
+ const extra = this.cssClass?.[key];
660
+ return extra ? `${base} ${extra}` : base;
661
+ }
662
+ /** Full normalized source (for resolving chip labels by value). */
663
+ get _normalizedItems() {
664
+ return this._normalizeItems(this._ds.sourceItems);
665
+ }
666
+ /** Normalized rows actually available to show (paged slice in array mode). */
667
+ get _visibleItems() {
668
+ return this._normalizeItems(this._ds.visibleItems);
669
+ }
670
+ /** Effective load-more mode (scroll is the default when enabled). */
671
+ get _loadMoreMode() {
672
+ const v = this.loadMore;
673
+ if (v === void 0 || v === null || v === false) return void 0;
674
+ return v === "button" ? "button" : "scroll";
675
+ }
676
+ /** Sanitised chunk size for array-mode paging (>= 1). */
677
+ get _pageSize() {
678
+ const n = Math.floor(Number(this.pageSize));
679
+ return Number.isFinite(n) && n > 0 ? n : 10;
680
+ }
681
+ get _selectedValues() {
682
+ return this.value ?? [];
683
+ }
684
+ get _hasValue() {
685
+ return this._selectedValues.length > 0;
686
+ }
687
+ get _hasLabelSlot() {
688
+ return this._hasLabelSlotState;
689
+ }
690
+ get _hasHelperSlot() {
691
+ return this._hasHelperSlotState;
692
+ }
693
+ get _resolvedValidationState() {
694
+ if (this.validationState && this.validationState !== "default") return this.validationState;
695
+ if (this.errorMessage) return "invalid";
696
+ if (this.successMessage) return "valid";
697
+ return "default";
698
+ }
699
+ _isSelected(item) {
700
+ const value = this._resolveItemValue(item);
701
+ return this._selectedValues.some((v) => this._isSameValue(v, value));
702
+ }
703
+ /** Whether `search-value` names anything explicitly (vs falling back). */
704
+ get _hasSearchValue() {
705
+ const sv = this.searchValue;
706
+ if (Array.isArray(sv)) return sv.length > 0;
707
+ return typeof sv === "string" && !!sv.trim();
708
+ }
709
+ /**
710
+ * The natural fields searched alongside the `'*'` default when `search-value` is
711
+ * empty — the safety net, not the whole list.
712
+ *
713
+ * `'*'` resolves against loaded rows, so on a bound DataSource it expands to
714
+ * NOTHING until the first page lands (nothing loads on open, and a query can
715
+ * fire inside the debounce) — these keep that first query working. They are also
716
+ * exempt from the remote string-only rule, so a numeric `key-value` stays
717
+ * searchable. `display-value` contributes only when it's a string; a function
718
+ * builds text that no field expression can reach, which is why `_searchMatches`
719
+ * keeps matching the rendered display separately.
720
+ */
721
+ _fallbackSearchFields() {
722
+ return [typeof this.displayValue === "string" ? this.displayValue : void 0, this.keyValue];
723
+ }
724
+ /**
725
+ * A cheap signature of the rows' SHAPE, for the memo keys below.
726
+ *
727
+ * Row count alone isn't enough once `'*'` is in play: the resolved field list
728
+ * depends on the rows' keys, and a remote source paging from one full page to
729
+ * the next keeps the same length while the shape can differ. Sampling the first
730
+ * and last row keeps this O(1) while catching that case.
731
+ */
732
+ _rowsShapeKey(rows) {
733
+ const keysOf = (row) => row && typeof row === "object" ? Object.keys(row).join(",") : typeof row;
734
+ if (!rows.length) return "0";
735
+ return `${rows.length}:${keysOf(rows[0])}|${keysOf(rows[rows.length - 1])}`;
736
+ }
737
+ /**
738
+ * `search-value` resolved to concrete entries — `*` patterns expanded against
739
+ * the loaded rows. Memoized: a pattern samples up to 20 rows, so resolving per
740
+ * item (this feeds `_searchMatches`) would be O(items × fields) per keystroke.
741
+ *
742
+ * With no `search-value` this defaults to `'*'` (every top-level field) plus the
743
+ * natural fallbacks — see {@link _fallbackSearchFields}.
744
+ */
745
+ _searchEntries(remote) {
746
+ const rows = this._normalizedItems;
747
+ const key = `${this._searchVersion} ${remote ? 1 : 0} ${this._rowsShapeKey(rows)}`;
748
+ if (this._entriesCache?.key === key) return this._entriesCache.entries;
749
+ const entries = resolveSearchFields({
750
+ searchValue: this.searchValue,
751
+ fallbackFields: this._fallbackSearchFields(),
752
+ rows,
753
+ remote,
754
+ defaultToWildcard: true
755
+ });
756
+ this._entriesCache = {
757
+ key,
758
+ entries
759
+ };
760
+ return entries;
761
+ }
762
+ /** The compiled client-side predicate for the current query (memoized). */
763
+ _searchPredicate() {
764
+ const query = this._inputValue.trim();
765
+ const operation = this.searchOperation || "contains";
766
+ const rows = this._normalizedItems;
767
+ const key = `${this._searchVersion} ${operation} ${this._rowsShapeKey(rows)} ${query}`;
768
+ if (this._predicateCache?.key === key) return this._predicateCache.pred;
769
+ const pred = searchRowPredicate(this._searchEntries(false), query, operation);
770
+ this._predicateCache = {
771
+ key,
772
+ pred
773
+ };
774
+ return pred;
775
+ }
776
+ /** A bound DataSource is searched on the server; a plain array, client-side. */
777
+ _serverSearch() {
778
+ return !!this.dataSource;
779
+ }
780
+ /** Run the server search, reset to page 0. A failure becomes the field's error. */
781
+ async _applySearch(query) {
782
+ if (!this._serverSearch()) return;
783
+ await this._pushSearch(query).catch((err) => {
784
+ this._ds.setError(err);
785
+ });
786
+ }
787
+ /** Push `query` onto the source and reload it; rejects when the load fails. */
788
+ _pushSearch(query) {
789
+ this._appliedQuery = query;
790
+ return this._sourceSearch.apply(this.dataSource, {
791
+ query,
792
+ searchValue: this.searchValue,
793
+ fallbackFields: this._fallbackSearchFields(),
794
+ rows: this._normalizedItems,
795
+ remote: true,
796
+ defaultToWildcard: true,
797
+ operation: this.searchOperation || "contains"
798
+ });
799
+ }
800
+ /** Forget the typed query without touching the source. */
801
+ _dropQuery() {
802
+ if (this._searchTimer) {
803
+ clearTimeout(this._searchTimer);
804
+ this._searchTimer = void 0;
805
+ }
806
+ this._inputValue = "";
807
+ this._activeIndex = -1;
808
+ }
809
+ /** Loading: the app says so (`loading`), or the bound source's first load / retry. */
810
+ get _busy() {
811
+ return this.loading || !!this.dataSource && this._ds.busy;
812
+ }
813
+ /** The failure to paint: the app's `loading-error`, else the source's own; none while busy. */
814
+ get _failure() {
815
+ if (this._busy) return null;
816
+ return this._appFailure ?? (this.dataSource ? this._ds.error : null);
817
+ }
818
+ /** Enter / Space on the focused field retries a failure. */
819
+ _retryKey(event) {
820
+ if (event.key !== "Enter" && event.key !== " ") return false;
821
+ if (!this._failure || this.disabled) return false;
822
+ this._retry(event);
823
+ return true;
824
+ }
825
+ /** Loading, or failed: the field refuses every gesture but ↻. */
826
+ get _dsInert() {
827
+ return this._busy || !!this._failure;
828
+ }
829
+ /** Every interaction is off: disabled, read-only, or the source isn't usable. */
830
+ get _inert() {
831
+ return this.disabled || this.readonly || this._dsInert;
832
+ }
833
+ /**
834
+ * Clear the typed query — the visible one AND the one applied to the source.
835
+ *
836
+ * These are two independent tracks, and with a bound DataSource only the second
837
+ * one actually filters anything: `_searchMatches` short-circuits to `true`
838
+ * because the rows arrive pre-filtered. So clearing `_inputValue` on its own
839
+ * looks like it worked and changes nothing, which is exactly how a query that
840
+ * is no longer visible anywhere kept filtering the list.
841
+ *
842
+ * Cancelling the debounce FIRST is load-bearing: a timer armed before the reset
843
+ * fires afterwards and re-applies the stale query.
844
+ */
845
+ _resetSearch() {
846
+ if (this._searchTimer) {
847
+ clearTimeout(this._searchTimer);
848
+ this._searchTimer = void 0;
849
+ }
850
+ const had = !!this._inputValue;
851
+ this._inputValue = "";
852
+ this._activeIndex = -1;
853
+ if (had && this._serverSearch()) this._applySearch("");
854
+ }
855
+ /**
856
+ * The single way the panel closes. Every exit resets the search, so reopening
857
+ * never shows a list filtered by a query the box no longer holds.
858
+ */
859
+ _close() {
860
+ this._open = false;
861
+ this._resetSearch();
862
+ }
863
+ /** Debounce a server search for the current input text. */
864
+ _scheduleSearch() {
865
+ if (!this.searchable || !this._serverSearch()) return;
866
+ if (this._searchTimer) clearTimeout(this._searchTimer);
867
+ const wait = Math.max(0, Number(this.searchDebounce) || 0);
868
+ this._searchTimer = setTimeout(() => void this._applySearch(this._inputValue), wait);
869
+ }
870
+ /** Whether an option matches the current typed query. */
871
+ _searchMatches(item) {
872
+ if (!this.searchable) return true;
873
+ if (this._serverSearch()) return true;
874
+ const query = this._inputValue.trim().toLowerCase();
875
+ if (!query) return true;
876
+ if (this._hasSearchValue) {
877
+ const pred = this._searchPredicate();
878
+ return pred ? pred(item) : true;
879
+ }
880
+ const itemValue = this._resolveItemValue(item);
881
+ const display = this._resolveItemDisplay(item).toLowerCase();
882
+ const valueStr = itemValue == null ? "" : String(itemValue).toLowerCase();
883
+ const desc = typeof item === "object" && item && typeof item.description === "string" ? item.description.toLowerCase() : "";
884
+ const pred = this._searchPredicate();
885
+ return display.includes(query) || valueStr.includes(query) || desc.includes(query) || (pred ? pred(item) : false);
886
+ }
887
+ /**
888
+ * Grouping is active when `display-group` names at least one level — OR when the
889
+ * source already loaded PRE-GROUPED `{ key, items }` nodes.
890
+ *
891
+ * The second half is what makes "feed pre-grouped data directly" actually work.
892
+ * Without it, a devextreme DataSource carrying `group:` loaded its group nodes and,
893
+ * because `displayGroup` was empty, they were treated as ordinary OPTIONS: the
894
+ * headers became rows, `keyValue` was absent on them so they resolved to
895
+ * `undefined`, and selecting one wrote `undefined` into the value.
896
+ *
897
+ * `group` mode is excluded: there the source is deliberately FLAT and
898
+ * `display-group` is what buckets it client-side.
899
+ */
900
+ get _grouped() {
901
+ if (Array.isArray(this.displayGroup) && this.displayGroup.length > 0) return true;
902
+ if (this.group) return false;
903
+ const src = this._ds.sourceItems ?? [];
904
+ return src.length > 0 && src.some((n) => this._isGroupNode(n));
905
+ }
906
+ /** A node is a group when its `groupItems` field holds an array. */
907
+ _isGroupNode(x) {
908
+ return !!x && typeof x === "object" && Array.isArray(x[this.groupItems]);
909
+ }
910
+ /** Descend `groupItems[0]` to the first leaf row — the group's representative. */
911
+ _firstLeaf(node) {
912
+ let cur = node;
913
+ let guard = 0;
914
+ while (this._isGroupNode(cur) && guard++ < 50) cur = cur[this.groupItems]?.[0];
915
+ return cur ?? void 0;
916
+ }
917
+ /** Resolve a group header's label from `displayGroup[level]` over a leaf row. */
918
+ _resolveGroupLabel(node, level) {
919
+ const accessor = this.displayGroup[level];
920
+ const leaf = this._firstLeaf(node);
921
+ if (typeof accessor === "function") return String(accessor(leaf ?? {}) ?? "");
922
+ if (typeof accessor === "string" && leaf && accessor in leaf) return String(leaf[accessor] ?? "");
923
+ const key = node[this.groupKey];
924
+ return key == null ? "" : String(key);
925
+ }
926
+ /** The string `display-group` entries — usable as server group/sort fields. */
927
+ _groupSortFields() {
928
+ return (this.displayGroup ?? []).filter((a) => typeof a === "string");
929
+ }
930
+ /** A `display-group` level's key for a row (string → field, function → call). */
931
+ _groupKeyOf(row, level) {
932
+ const accessor = this.displayGroup[level];
933
+ if (typeof accessor === "function") return accessor(row);
934
+ if (typeof accessor === "string") return row[accessor];
935
+ }
936
+ /** `group` mode: bucket flat rows into `{ [groupKey], [groupItems] }` by level. */
937
+ _buildClientTree(rows) {
938
+ const build = (items, level) => {
939
+ if (level >= this.displayGroup.length) return items;
940
+ const buckets = /* @__PURE__ */ new Map();
941
+ for (const row of items) {
942
+ const key = this._groupKeyOf(row, level);
943
+ const ks = String(key);
944
+ let bucket = buckets.get(ks);
945
+ if (!bucket) buckets.set(ks, bucket = {
946
+ key,
947
+ rows: []
948
+ });
949
+ bucket.rows.push(row);
950
+ }
951
+ return [...buckets.values()].map((b) => ({
952
+ [this.groupKey]: b.key,
953
+ [this.groupItems]: build(b.rows, level + 1)
954
+ }));
955
+ };
956
+ return build(rows, 0);
957
+ }
958
+ /** Every leaf row (all loaded) — for chip-label / value lookup. */
959
+ get _leafItems() {
960
+ if (!this._grouped) return this._normalizedItems;
961
+ if (this.group) return this._normalizeItems(this._ds.sourceItems);
962
+ const out = [];
963
+ const walk = (nodes) => {
964
+ for (const n of nodes) if (this._isGroupNode(n)) walk(n[this.groupItems]);
965
+ else if (n != null) out.push(n);
966
+ };
967
+ walk(this._ds.sourceItems ?? []);
968
+ return out;
969
+ }
970
+ /** The nested group nodes to render — built client-side in `group` mode. */
971
+ _groupNodes() {
972
+ if (this.group) {
973
+ const leaves = this._visibleItems.filter((it) => this._searchMatches(it));
974
+ return this._buildClientTree(leaves);
975
+ }
976
+ return this._ds.visibleItems ?? [];
977
+ }
978
+ /**
979
+ * Flatten the visible group tree into ordered render rows (headers + items).
980
+ * `index` is the item's position among rendered leaves (drives `_activeIndex`
981
+ * and keyboard nav). Leaves are search-filtered; empty groups are dropped.
982
+ */
983
+ _groupRows() {
984
+ const filterLeaves = !this.group;
985
+ const build = (nodes, level, parentKey) => {
986
+ const rows = [];
987
+ nodes.forEach((node, i) => {
988
+ if (!this._isGroupNode(node)) {
989
+ const item = node;
990
+ if (item == null) return;
991
+ if (filterLeaves && !this._searchMatches(item)) return;
992
+ rows.push({
993
+ kind: "item",
994
+ item,
995
+ index: -1,
996
+ level
997
+ });
998
+ return;
999
+ }
1000
+ const rec = node;
1001
+ const path = `${parentKey}/${String(rec[this.groupKey])}#${i}`;
1002
+ const children = build(rec[this.groupItems] ?? [], level + 1, path);
1003
+ if (!children.length) return;
1004
+ rows.push({
1005
+ kind: "group",
1006
+ level,
1007
+ label: this._resolveGroupLabel(rec, level),
1008
+ key: `g:${level}:${path}`,
1009
+ items: children.filter((r) => r.kind === "item").map((r) => r.item)
1010
+ });
1011
+ rows.push(...children);
1012
+ });
1013
+ return rows;
1014
+ };
1015
+ let idx = 0;
1016
+ return build(this._groupNodes(), 0, "").map((r) => r.kind === "item" ? {
1017
+ ...r,
1018
+ index: idx++
1019
+ } : r);
1020
+ }
1021
+ /**
1022
+ * Where the keyboard cursor goes when the list opens: the row holding the most
1023
+ * recently picked tag, else the first row.
1024
+ *
1025
+ * "Most recent" is the TAIL of the value array — every add appends and nothing
1026
+ * sorts, so removing and re-adding a tag correctly moves it to the end. The
1027
+ * `Backspace` handler already leans on that same invariant.
1028
+ *
1029
+ * Selected rows stay in the suggestion list (see `_renderOption`), so this can
1030
+ * actually find them; the predicate is the one that paints `.selected`, so the
1031
+ * cursor lands on the row drawn as selected. `0` when the tag is not in the
1032
+ * loaded page — the behaviour this component has always had.
1033
+ */
1034
+ _initialActiveIndex() {
1035
+ const items = this._filteredItems;
1036
+ if (!items.length) return -1;
1037
+ const values = this._selectedValues;
1038
+ const last = values.length ? values[values.length - 1] : void 0;
1039
+ if (last === void 0) return 0;
1040
+ const index = items.findIndex((item) => this._isSameValue(this._resolveItemValue(item), last));
1041
+ return index >= 0 ? index : 0;
1042
+ }
1043
+ get _filteredItems() {
1044
+ if (this._grouped) return this._groupRows().filter((r) => r.kind === "item").map((r) => r.item);
1045
+ return this._visibleItems.filter((item) => this._searchMatches(item));
1046
+ }
1047
+ /**
1048
+ * The selection limits in force: `chip.max` / `chip.min` pin, the element's
1049
+ * `max` / `min` are the fallback (the rule `chip.color` follows). Undefined =
1050
+ * unlimited / no floor.
1051
+ */
1052
+ get _selectionLimits() {
1053
+ const chip = this._chipProps;
1054
+ return {
1055
+ max: resolveChipLimit(chip, "max", this.max),
1056
+ min: resolveChipLimit(chip, "min", this.min)
1057
+ };
1058
+ }
1059
+ /** Room left under `max`, or Infinity without one. */
1060
+ get _room() {
1061
+ const max = this._selectionLimits.max;
1062
+ return max === void 0 ? Infinity : Math.max(0, max - this._selectedValues.length);
1063
+ }
1064
+ get _canAddMore() {
1065
+ return this._room > 0;
1066
+ }
1067
+ /** The selection sits above its floor, so one more removal is allowed. */
1068
+ get _canRemoveMore() {
1069
+ const min = this._selectionLimits.min;
1070
+ return min === void 0 || this._selectedValues.length > min;
1071
+ }
1072
+ /**
1073
+ * A bulk deselect keeps the FIRST `min` values (selection order) — "remove
1074
+ * these" then means "down to the floor", the most a user gesture may do.
1075
+ */
1076
+ _keepFloor(next) {
1077
+ const min = this._selectionLimits.min ?? 0;
1078
+ if (next.length >= min) return next;
1079
+ const kept = [...next];
1080
+ for (const v of this._selectedValues) {
1081
+ if (kept.length >= min) break;
1082
+ if (!kept.some((k) => this._isSameValue(k, v))) kept.push(v);
1083
+ }
1084
+ return this._selectedValues.filter((v) => kept.some((k) => this._isSameValue(k, v)));
1085
+ }
1086
+ get _wrapperClasses() {
1087
+ return [
1088
+ "mono-tag-input",
1089
+ this.size,
1090
+ this.color,
1091
+ this.variant,
1092
+ this._open ? "open" : "",
1093
+ this._moreOpen ? "more-open" : "",
1094
+ this.disabled ? "disabled" : "",
1095
+ this.readonly ? "readonly" : "",
1096
+ this._resolvedValidationState !== "default" ? `is-${this._resolvedValidationState}` : "",
1097
+ this._hasValue ? "has-value" : "",
1098
+ this.checkable ? "checkable" : "",
1099
+ this.cssClassName,
1100
+ this.cssClass?.root
1101
+ ].filter(Boolean).join(" ");
1102
+ }
1103
+ /**
1104
+ * Whether the clear button renders. A getter because BOTH the field class list
1105
+ * and `render()` need it: the button is pinned to the top-right corner, and the
1106
+ * gutter that keeps wrapped chips from running under it is reserved by
1107
+ * `.has-clear` on the field.
1108
+ */
1109
+ get _showClear() {
1110
+ return this.clearable && this._hasValue && !this._inert && !((this._selectionLimits.min ?? 0) > 0);
1111
+ }
1112
+ /** The input's placeholder: the source's state while it isn't usable, else the prompt. */
1113
+ get _inputPlaceholder() {
1114
+ if (this._busy) return this.loadingText;
1115
+ if (this._failure) return errorText(this._failure);
1116
+ return this._hasValue ? void 0 : this.placeholder;
1117
+ }
1118
+ /** Full error text (detail first) on hover, since the placeholder may truncate. */
1119
+ get _dsErrorTitle() {
1120
+ const err = this._failure;
1121
+ return err ? errorTitle(err) : void 0;
1122
+ }
1123
+ get _fieldClasses() {
1124
+ return [
1125
+ this._cls("mono-tag-input-field", "field"),
1126
+ this.size,
1127
+ this.color,
1128
+ this.variant,
1129
+ this.disabled ? "disabled" : "",
1130
+ this.readonly ? "readonly" : "",
1131
+ this._showClear ? "has-clear" : "",
1132
+ "has-actions",
1133
+ this._chipBehaviour === "inline" ? "is-inline" : "",
1134
+ this._inputValue ? "is-typing" : ""
1135
+ ].filter(Boolean).join(" ");
1136
+ }
1137
+ _cacheKey(value) {
1138
+ if (value == null || typeof value === "object") return void 0;
1139
+ return String(value);
1140
+ }
1141
+ /**
1142
+ * Remember the rows behind `values` while they are still loaded.
1143
+ *
1144
+ * Called from `_setValue`, i.e. at the moment of selection — the row is in the
1145
+ * list by definition right then, which is why this needs no request. Values
1146
+ * that cannot be resolved yet are skipped, not cached as misses, so a later
1147
+ * load can still fill them in.
1148
+ */
1149
+ _rememberSelected(values) {
1150
+ if (!this.keyValue) return;
1151
+ for (const value of values) {
1152
+ const key = this._cacheKey(value);
1153
+ if (key === void 0 || this._selectedItemCache.has(key)) continue;
1154
+ const item = this._findLoadedItem(value);
1155
+ if (item !== void 0) this._selectedItemCache.set(key, item);
1156
+ }
1157
+ }
1158
+ /** Look a value up in the currently loaded rows only. */
1159
+ _findLoadedItem(value) {
1160
+ return this._leafItems.find((item) => this._isSameValue(this._resolveItemValue(item), value));
1161
+ }
1162
+ _getItemByValue(value) {
1163
+ const loaded = this._findLoadedItem(value);
1164
+ if (loaded !== void 0) {
1165
+ const key = this._cacheKey(value);
1166
+ if (key !== void 0 && this.keyValue) this._selectedItemCache.set(key, loaded);
1167
+ return loaded;
1168
+ }
1169
+ const key = this._cacheKey(value);
1170
+ return key === void 0 ? void 0 : this._selectedItemCache.get(key);
1171
+ }
1172
+ /**
1173
+ * Whether this value still has no row behind it — the list has not loaded it (or
1174
+ * not loaded yet).
1175
+ *
1176
+ * Only meaningful when `keyValue` is set: that prop is the statement "values are
1177
+ * KEYS into the items", so an unmatched key has no label anyone would want to
1178
+ * read — showing the bare key renders a chip like `1` or `1|MKT`. Without
1179
+ * `keyValue` the value IS its own label (and `allow-custom` tags rely on that),
1180
+ * so nothing is ever hidden there.
1181
+ */
1182
+ _isUnresolvedKey(value) {
1183
+ if (!this.keyValue) return false;
1184
+ if (value == null) return false;
1185
+ if (typeof value === "object") return false;
1186
+ return this._getItemByValue(value) === void 0;
1187
+ }
1188
+ _getLabelByValue(value) {
1189
+ const item = this._getItemByValue(value);
1190
+ if (item) return this._resolveItemDisplay(item);
1191
+ if (value == null) return "";
1192
+ if (typeof value === "object") return this._resolveItemDisplay(value);
1193
+ if (this._isUnresolvedKey(value)) return "";
1194
+ return String(value);
1195
+ }
1196
+ _createModelDetail(args) {
1197
+ return {
1198
+ modelValue: args.modelValue,
1199
+ currentValue: args.modelValue,
1200
+ oldValue: args.oldValue,
1201
+ value: args.modelValue,
1202
+ addedValue: args.addedValue,
1203
+ removedValue: args.removedValue,
1204
+ selectedItem: args.addedValue !== void 0 ? this._getItemByValue(args.addedValue) : void 0,
1205
+ sourceEvent: args.sourceEvent
1206
+ };
1207
+ }
1208
+ _emitChange(detail) {
1209
+ dispatchMonoEvent(this, "change", detail);
1210
+ }
1211
+ _emitAdd(detail) {
1212
+ dispatchMonoEvent(this, "add", detail);
1213
+ }
1214
+ _emitRemove(detail) {
1215
+ dispatchMonoEvent(this, "remove", detail);
1216
+ }
1217
+ _emitClear(detail) {
1218
+ dispatchMonoEvent(this, "clear", detail);
1219
+ }
1220
+ _setValue(nextValue, args = {}) {
1221
+ const oldValue = [...this._selectedValues];
1222
+ const normalized = [...nextValue];
1223
+ this._rememberSelected(normalized);
1224
+ this.value = normalized;
1225
+ this.modelValue = normalized;
1226
+ const detail = this._createModelDetail({
1227
+ modelValue: normalized,
1228
+ oldValue,
1229
+ addedValue: args.addedValue,
1230
+ removedValue: args.removedValue,
1231
+ sourceEvent: args.sourceEvent
1232
+ });
1233
+ this._emitChange(detail);
1234
+ if (args.emitAdd) this._emitAdd(detail);
1235
+ if (args.emitRemove) this._emitRemove(detail);
1236
+ if (args.emitClear) this._emitClear(detail);
1237
+ if (args.emitAdd && this._chipBehaviour === "inline") this.updateComplete.then(() => this._chipStrip.scrollToEnd());
1238
+ }
1239
+ _addValue(value, event) {
1240
+ if (this._inert) return;
1241
+ if (!this._canAddMore) return this._resetSearch();
1242
+ if (!this.allowCustom && !this._getItemByValue(value)) return;
1243
+ if (!this._selectedValues.some((v) => this._isSameValue(v, value))) this._setValue([...this._selectedValues, value], {
1244
+ addedValue: value,
1245
+ sourceEvent: event,
1246
+ emitAdd: true
1247
+ });
1248
+ this._close();
1249
+ this._inputEl?.focus();
1250
+ }
1251
+ /**
1252
+ * Checkbox-mode toggle: add or remove a value while keeping the dropdown open
1253
+ * (and the typed filter intact), so the user can check several rows in a row.
1254
+ */
1255
+ _toggleValue(value, event) {
1256
+ if (this._inert) return;
1257
+ if (this._selectedValues.some((v) => this._isSameValue(v, value))) {
1258
+ if (!this._canRemoveMore) return;
1259
+ this._setValue(this._selectedValues.filter((v) => !this._isSameValue(v, value)), {
1260
+ removedValue: value,
1261
+ sourceEvent: event,
1262
+ emitRemove: true
1263
+ });
1264
+ } else {
1265
+ if (!this._canAddMore) return this._resetSearch();
1266
+ this._setValue([...this._selectedValues, value], {
1267
+ addedValue: value,
1268
+ sourceEvent: event,
1269
+ emitAdd: true
1270
+ });
1271
+ }
1272
+ if (!this.checkable) {
1273
+ this._close();
1274
+ this._inputEl?.focus();
1275
+ return;
1276
+ }
1277
+ this._open = true;
1278
+ this._inputEl?.focus();
1279
+ }
1280
+ /**
1281
+ * How much of `items` is selected — what paints a select-all box unchecked,
1282
+ * indeterminate or checked. Disabled options are ignored, so a group whose only
1283
+ * unselected row is disabled still reads as fully selected.
1284
+ */
1285
+ _selectionStateOf(items) {
1286
+ const usable = items.filter((item) => this._isSelectable(item));
1287
+ if (!usable.length) return "none";
1288
+ let hit = 0;
1289
+ for (const item of usable) if (this._isSelected(item)) hit += 1;
1290
+ if (hit === 0) return "none";
1291
+ return hit === usable.length ? "all" : "some";
1292
+ }
1293
+ /**
1294
+ * Whether the "All" row reaches the SERVER rather than the loaded rows.
1295
+ *
1296
+ * Gated on a bound `DataSource` + `load-more`, which together mean "the list is
1297
+ * a window onto something bigger". A plain `items` array is static and already
1298
+ * wholly in memory, so it keeps the loaded-only behaviour.
1299
+ */
1300
+ get _serverSelectAll() {
1301
+ return !!this.dataSource && !!this._loadMoreMode;
1302
+ }
1303
+ /** The source's own page size, when it pages; `0` otherwise. */
1304
+ _sourcePageSize() {
1305
+ const ds = this.dataSource;
1306
+ if (!ds || typeof ds.pageSize !== "function") return 0;
1307
+ if (typeof ds.paginate === "function" && !ds.paginate()) return 0;
1308
+ const n = Number(ds.pageSize());
1309
+ return Number.isFinite(n) && n > 0 ? n : 0;
1310
+ }
1311
+ /** The source's row count, when it knows one. */
1312
+ _serverTotal() {
1313
+ const n = Number(this.dataSource?.totalCount?.());
1314
+ return Number.isFinite(n) && n >= 0 ? n : void 0;
1315
+ }
1316
+ /**
1317
+ * The "All" box, judged against the SERVER total rather than the loaded rows.
1318
+ *
1319
+ * Without this the box reads `'all'` the moment the loaded page is selected —
1320
+ * and the next click would CLEAR, so the drain could never be reached. Every
1321
+ * state below `all` therefore has to mean "clicking me selects more".
1322
+ *
1323
+ * BOTH halves of the `'all'` test matter, and each rules out a way of being
1324
+ * wrong. `_selectionStateOf` alone says `'all'` after one page of 250. The count
1325
+ * alone says `'all'` whenever the selection is merely LARGER than the total,
1326
+ * which a search makes routine: hold 111 rows, narrow the query to 11, and a
1327
+ * bare `111 >= 11` paints a finished box over eleven rows none of which are
1328
+ * selected — and the next click would clear instead of selecting them.
1329
+ *
1330
+ * Falls back to the loaded-scope reading when the source cannot say how many
1331
+ * rows it has, which is the honest answer: nothing here can tell whether the
1332
+ * selection is complete.
1333
+ */
1334
+ _selectAllState(usable) {
1335
+ const loaded = this._selectionStateOf(usable);
1336
+ if (!this._serverSelectAll) return loaded;
1337
+ const total = this._serverTotal();
1338
+ if (total === void 0) return loaded;
1339
+ if (loaded === "all" && total > 0 && this._selectedValues.length >= total) return "all";
1340
+ return this._selectedValues.length > 0 ? "some" : "none";
1341
+ }
1342
+ /**
1343
+ * Select every row the source returns for the CURRENT search — the tag-input's
1344
+ * counterpart to `<mono-table-checkbox type="all">`.
1345
+ *
1346
+ * `readAllRows` walks the store in chunks and rebuilds the source's live filter
1347
+ * plus its folded search (`searchFilterOf`), so this means "everything the user
1348
+ * is currently looking at", not the whole table. Deliberately NOT routed through
1349
+ * `_ds`: its `_onChanged` resets the accumulated pages whenever a `changed`
1350
+ * fires outside its own load, and `readAllRows` talks to the store directly.
1351
+ */
1352
+ async _selectAllFromServer(event) {
1353
+ if (this._selectAllPending) return;
1354
+ if (this._searchTimer) {
1355
+ clearTimeout(this._searchTimer);
1356
+ this._searchTimer = void 0;
1357
+ await this._applySearch(this._inputValue);
1358
+ }
1359
+ this._selectAllPending = true;
1360
+ try {
1361
+ const rows = await readAllRows(this.dataSource, { chunkSize: Math.max(1, this._pageSize, this._sourcePageSize()) });
1362
+ const usable = this._normalizeItems(rows).filter((item) => this._isSelectable(item));
1363
+ const values = usable.map((item) => this._resolveItemValue(item));
1364
+ const seen = new Set(this._selectedValues.map((v) => this._cacheKey(v)).filter((k) => k !== void 0));
1365
+ const additions = [];
1366
+ for (let i = 0; i < values.length; i++) {
1367
+ const key = this._cacheKey(values[i]);
1368
+ if (key !== void 0 && seen.has(key)) continue;
1369
+ if (key !== void 0) seen.add(key);
1370
+ additions.push(values[i]);
1371
+ if (key !== void 0 && this.keyValue) this._selectedItemCache.set(key, usable[i]);
1372
+ }
1373
+ if (!additions.length) return;
1374
+ const room = this._room;
1375
+ if (!room) return;
1376
+ this._setValue([...this._selectedValues, ...additions.slice(0, room)], {
1377
+ sourceEvent: event,
1378
+ emitAdd: true
1379
+ });
1380
+ } catch (err) {
1381
+ this._ds.setError(err);
1382
+ } finally {
1383
+ this._selectAllPending = false;
1384
+ this._open = true;
1385
+ this._inputEl?.focus();
1386
+ }
1387
+ }
1388
+ /**
1389
+ * Where the "All" row's click goes.
1390
+ *
1391
+ * Only a state BELOW `all` drains; once `_selectAllState` says everything on the
1392
+ * server is held, the row goes back to being a clear button. `_toggleMany` still
1393
+ * owns both directions for a plain `items` array.
1394
+ *
1395
+ * A drain is for the rows NOT yet here. Once the controller has walked the source
1396
+ * to its last page — `load-more` scrolled to the end, or a source whose whole
1397
+ * result fit its first page — every row the query matches is already in
1398
+ * memory, and `items` (the visible, server-filtered set) IS the answer: select
1399
+ * it as a plain array would, with no request. A query still inside its debounce
1400
+ * disqualifies that shortcut, because the loaded rows belong to the PREVIOUS
1401
+ * search; the drain path flushes it first.
1402
+ */
1403
+ _onSelectAllClick(items, state, event) {
1404
+ if (this._selectAllPending) return;
1405
+ if (!this._serverSelectAll) {
1406
+ this._toggleMany(items, event);
1407
+ return;
1408
+ }
1409
+ if (state !== "all") {
1410
+ if (this._ds.atLastPage && !this._searchTimer) {
1411
+ this._toggleMany(items, event);
1412
+ return;
1413
+ }
1414
+ this._selectAllFromServer(event);
1415
+ return;
1416
+ }
1417
+ this._clearAllFromServer(event);
1418
+ }
1419
+ /**
1420
+ * Untick "All" after a drain.
1421
+ *
1422
+ * NOT `_toggleMany`: that only removes the values present in `items`, which on a
1423
+ * paged source is one page — so clearing 1,085 drained rows would drop ten of
1424
+ * them and leave the box reading `'some'`. `'all'` here means the selection is
1425
+ * the drain, so the inverse is emptying it, the same reading
1426
+ * `<mono-table-checkbox>` gives its own clear.
1427
+ */
1428
+ _clearAllFromServer(event) {
1429
+ if (this._inert) return;
1430
+ if (!this._selectedValues.length) return;
1431
+ this._setValue([], {
1432
+ sourceEvent: event,
1433
+ emitRemove: true
1434
+ });
1435
+ this._open = true;
1436
+ this._inputEl?.focus();
1437
+ }
1438
+ /**
1439
+ * Select every one of `items`, or clear them all if they are already selected —
1440
+ * the "All" row and every group header run through here.
1441
+ *
1442
+ * ONE `_setValue` call, so a bulk toggle is a single `mno-change` carrying the
1443
+ * whole next array rather than N events a consumer would have to coalesce.
1444
+ * `addedValue` / `removedValue` are deliberately left undefined for the same
1445
+ * reason: there is no single value to name, and guessing one would be worse than
1446
+ * saying nothing (`modelValue` and `oldValue` carry the full before/after).
1447
+ */
1448
+ _toggleMany(items, event) {
1449
+ if (this._inert) return;
1450
+ const usable = items.filter((item) => this._isSelectable(item));
1451
+ if (!usable.length) return;
1452
+ const values = usable.map((item) => this._resolveItemValue(item));
1453
+ const current = this._selectedValues;
1454
+ const isOn = (v) => current.some((c) => this._isSameValue(c, v));
1455
+ if (values.every(isOn)) this._setValue(this._keepFloor(current.filter((c) => !values.some((v) => this._isSameValue(c, v)))), {
1456
+ sourceEvent: event,
1457
+ emitRemove: true
1458
+ });
1459
+ else {
1460
+ const missing = values.filter((v) => !isOn(v));
1461
+ const room = Math.min(missing.length, this._room);
1462
+ if (!room) return;
1463
+ this._setValue([...current, ...missing.slice(0, room)], {
1464
+ sourceEvent: event,
1465
+ emitAdd: true
1466
+ });
1467
+ }
1468
+ this._open = true;
1469
+ this._inputEl?.focus();
1470
+ }
1471
+ _removeValue(value, event) {
1472
+ event?.stopPropagation();
1473
+ if (this._inert) return;
1474
+ if (!this._canRemoveMore) return;
1475
+ this._setValue(this._selectedValues.filter((item) => !this._isSameValue(item, value)), {
1476
+ removedValue: value,
1477
+ sourceEvent: event,
1478
+ emitRemove: true
1479
+ });
1480
+ this._inputEl?.focus();
1481
+ }
1482
+ _clear(event) {
1483
+ event.stopPropagation();
1484
+ if (this._inert) return;
1485
+ this._setValue(this._keepFloor([]), {
1486
+ sourceEvent: event,
1487
+ emitClear: true
1488
+ });
1489
+ this._close();
1490
+ this._inputEl?.focus();
1491
+ }
1492
+ _handleInput(event) {
1493
+ if (this._inert) return;
1494
+ const input = event.currentTarget;
1495
+ if (!this.searchable) {
1496
+ input.value = "";
1497
+ return;
1498
+ }
1499
+ this._inputValue = input.value;
1500
+ this._open = true;
1501
+ this._activeIndex = this._filteredItems.length ? 0 : -1;
1502
+ this._cursorPending = false;
1503
+ this._scheduleSearch();
1504
+ }
1505
+ /**
1506
+ * Focus alone opens nothing: a Tab into the field is not a request to see the
1507
+ * list — typing, ↓, a click in a searchable field or the chevron are. (It used
1508
+ * to open, which also meant every chip-remove's refocus popped the list.)
1509
+ */
1510
+ _handleFocus() {}
1511
+ /**
1512
+ * A click in the field focuses the input and, when the field is searchable,
1513
+ * OPENS the list — the input is the point there, and clicking into it is how
1514
+ * you start typing; it never closes, because a click in a text input while
1515
+ * the list is open is caret placement, not a toggle (the chevron, Escape and
1516
+ * an outside click close). A non-searchable field has nothing to type into,
1517
+ * so there the click TOGGLES: a second click on the field closes the list.
1518
+ */
1519
+ _handleFieldClick() {
1520
+ if (this._inert) return;
1521
+ this._inputEl?.focus();
1522
+ this._moreOpen = false;
1523
+ if (this.searchable) this._open = true;
1524
+ else if (this._open) this._close();
1525
+ else this._open = true;
1526
+ }
1527
+ /** The chevron: the one mouse gesture that both opens and closes. */
1528
+ _toggleFromCaret(event) {
1529
+ event.stopPropagation();
1530
+ if (this._inert) return;
1531
+ this._moreOpen = false;
1532
+ if (this._open) this._close();
1533
+ else {
1534
+ this._open = true;
1535
+ this._inputEl?.focus();
1536
+ }
1537
+ }
1538
+ _handleKeydown(event) {
1539
+ if (this._retryKey(event)) return;
1540
+ if (this._inert) return;
1541
+ const items = this._filteredItems;
1542
+ if (event.key === "ArrowDown") {
1543
+ event.preventDefault();
1544
+ this._open = true;
1545
+ this._activeIndex = items.length ? Math.min(this._activeIndex + 1, items.length - 1) : -1;
1546
+ return;
1547
+ }
1548
+ if (event.key === "ArrowUp") {
1549
+ event.preventDefault();
1550
+ this._activeIndex = items.length ? Math.max(this._activeIndex - 1, 0) : -1;
1551
+ return;
1552
+ }
1553
+ if (event.key === "Enter") {
1554
+ event.preventDefault();
1555
+ const activeItem = this._activeIndex >= 0 ? items[this._activeIndex] : void 0;
1556
+ if (activeItem && !activeItem.disabled) {
1557
+ this._toggleValue(this._resolveItemValue(activeItem), event);
1558
+ return;
1559
+ }
1560
+ const customValue = this._inputValue.trim();
1561
+ if (customValue && this.allowCustom) this._addValue(customValue, event);
1562
+ return;
1563
+ }
1564
+ if (event.key === "," || event.key === "Tab") {
1565
+ const customValue = this._inputValue.trim();
1566
+ if (customValue && this.allowCustom) {
1567
+ event.preventDefault();
1568
+ this._addValue(customValue, event);
1569
+ }
1570
+ return;
1571
+ }
1572
+ if (event.key === "Backspace" && !this._inputValue && this._selectedValues.length) {
1573
+ event.preventDefault();
1574
+ const lastValue = this._selectedValues[this._selectedValues.length - 1];
1575
+ this._removeValue(lastValue, event);
1576
+ return;
1577
+ }
1578
+ if (event.key === "Escape") {
1579
+ event.preventDefault();
1580
+ this._close();
1581
+ }
1582
+ }
1583
+ _renderLabel() {
1584
+ const hasContent = !!this.label || this._hasLabelSlotState;
1585
+ if (!hasContent && !this._slotsAlwaysRender) return nothing;
1586
+ return html`
1587
+ <label
1588
+ class=${this._cls("mono-tag-input-label", "label")}
1589
+ mono-label
1590
+ for=${this._inputId}
1591
+ ?mono-empty=${!hasContent}
1592
+ >
1593
+ ${this._slotOutlet("label", this.label)}
1594
+
1595
+ ${this.required ? html`
1596
+ <span class=${this._cls("mono-tag-input-required", "required")} mono-required-mark>
1597
+ *
1598
+ </span>
1599
+ ` : nothing}
1600
+ </label>
1601
+ `;
1602
+ }
1603
+ /**
1604
+ * How many chips to draw before the rest collapse into "+N more" — Infinity
1605
+ * when uncapped or while the total sits under the collapse floor
1606
+ * (`visibleChipCap`). `chip.maxVisible` / `chip.minVisible` pin, the element
1607
+ * props are the fallback. Applies to `inline` as well: the "+N more" chip
1608
+ * then sits in the strip after the visible ones, and its panel lists the rest
1609
+ * exactly as in `flex`. Every downstream consumer (`_overflowChips`,
1610
+ * `_renderChips`, the more panel) reads this, so the rule lives in one place.
1611
+ */
1612
+ get _maxChips() {
1613
+ const chip = this._chipProps;
1614
+ return visibleChipCap(this._resolvedValues.length, resolveChipLimit(chip, "maxVisible", this.maxVisible), resolveChipLimit(chip, "minVisible", this.minVisible));
1615
+ }
1616
+ /** Selected values that have a row behind them — what the chips actually draw. */
1617
+ get _resolvedValues() {
1618
+ return this._selectedValues.filter((v) => !this._isUnresolvedKey(v));
1619
+ }
1620
+ get _overflowChips() {
1621
+ const max = this._maxChips;
1622
+ return max === Infinity ? [] : this._resolvedValues.slice(max);
1623
+ }
1624
+ _closeSvg() {
1625
+ return this.renderIcon("close");
1626
+ }
1627
+ /** The `chip` prop, always an object (it can be assigned null from a binding). */
1628
+ get _chipProps() {
1629
+ return this.chip ?? {};
1630
+ }
1631
+ /** Chip layout: `inline` = one scrolling line, anything else = today's wrap. */
1632
+ get _chipBehaviour() {
1633
+ return this._chipProps.behaviour === "inline" ? "inline" : "flex";
1634
+ }
1635
+ /**
1636
+ * Chip skin matching the field skin: a `filled` field already tints its own
1637
+ * surface, so a soft chip would vanish into it — go solid; `underlined` is
1638
+ * minimal, so the chip stays outline. `chip.variant` pins one instead.
1639
+ */
1640
+ get _chipVariantClass() {
1641
+ const pinned = this._chipProps.variant;
1642
+ if (pinned) return pinned;
1643
+ if (this.variant === "filled") return "solid";
1644
+ if (this.variant === "underlined") return "outline";
1645
+ return "soft";
1646
+ }
1647
+ /** Chips wear the control's color unless `chip.color` pins another. */
1648
+ get _chipColorClass() {
1649
+ return this._chipProps.color ?? this.color;
1650
+ }
1651
+ /**
1652
+ * Classes shared by the tag chips and the "+N more" chip, in `mono-chip`'s own
1653
+ * order (`mono-chip <size> <variant>-<color> <shape>`), so chip.css paints them
1654
+ * exactly as it paints a real `<mono-chip>`.
1655
+ *
1656
+ * `mono-tag-input-chip` is a marker only — it scopes the `--mono-chip-*` bridge
1657
+ * in tag-input.css so the bridge never reaches a `<mono-chip>` a consumer slots
1658
+ * into the field. `chip.color` deliberately picks a hue OTHER than the control
1659
+ * accent, so it adds the `-pinned` marker that switches the bridge back off.
1660
+ */
1661
+ get _chipBaseClasses() {
1662
+ const chip = this._chipProps;
1663
+ return [
1664
+ "mono-tag-input-chip",
1665
+ chip.color ? "mono-tag-input-chip-pinned" : "",
1666
+ chip.size ?? (this.size === "xs" || this.size === "sm" ? "xs" : "sm"),
1667
+ `${this._chipVariantClass}-${this._chipColorClass}`,
1668
+ "",
1669
+ chip.dot ? "has-dot" : ""
1670
+ ].filter(Boolean).join(" ");
1671
+ }
1672
+ /**
1673
+ * Class for one chip part. Both class APIs append: the tag-input-level key
1674
+ * (`cssClass.chip` / `.chipLabel` / `.chipRemove`, the established surface) and
1675
+ * the chip-level one (`chip.cssClass.*`, which additionally reaches the parts
1676
+ * tag-input has no key for — `main`, `content`, `dot`).
1677
+ */
1678
+ _chipCls(base, chipKey, key) {
1679
+ return [
1680
+ base,
1681
+ key ? this.cssClass?.[key] : void 0,
1682
+ this._chipProps.cssClass?.[chipKey]
1683
+ ].filter(Boolean).join(" ");
1684
+ }
1685
+ /** Render one chip with shared mono-chip markup/classes. */
1686
+ _renderChip(value, removable) {
1687
+ const chip = this._chipProps;
1688
+ const label = this._getLabelByValue(value);
1689
+ const canRemove = removable && !this._inert && this._canRemoveMore;
1690
+ return html`
1691
+ <div
1692
+ class=${this._chipCls(`${this._chipBaseClasses}${canRemove ? " removable" : ""}`, "root", "chip")}
1693
+ mono-chip
1694
+ ?mono-removable=${canRemove}
1695
+ mono-chip-color=${chip.color ?? nothing}
1696
+ >
1697
+ <span class=${ifDefined(chip.cssClass?.main)} mono-chip-main>
1698
+ <span class=${this._chipCls("chip-content", "content")} mono-chip-content>
1699
+ ${chip.dot ? html`<span
1700
+ class=${this._chipCls("chip-dot", "dot")}
1701
+ mono-chip-dot
1702
+ aria-hidden="true"
1703
+ ></span>` : nothing}
1704
+ <span class=${this._chipCls("chip-label", "label", "chipLabel")} mono-chip-label>${label}</span>
1705
+ ${canRemove ? html`
1706
+ <button
1707
+ type="button"
1708
+ class=${this._chipCls("chip-close", "close", "chipRemove")}
1709
+ mono-chip-close
1710
+ aria-label=${chip.closeLabel ?? `Remove ${label}`}
1711
+ @click=${(event) => this._removeValue(value, event)}
1712
+ >
1713
+ ${this._closeSvg()}
1714
+ </button>
1715
+ ` : nothing}
1716
+ </span>
1717
+ </span>
1718
+ </div>
1719
+ `;
1720
+ }
1721
+ /**
1722
+ * The chip region. `flex` returns the chips as bare siblings of the input, so
1723
+ * they wrap with it — the historical markup, unchanged. `inline` nests them in
1724
+ * one `overflow-x: hidden` strip instead, which is what makes the row scroll
1725
+ * as a unit while the input keeps its own space beside it.
1726
+ */
1727
+ _renderChipRegion() {
1728
+ const chips = this._renderChips();
1729
+ if (this._chipBehaviour !== "inline") return chips;
1730
+ return html`
1731
+ <div class=${this._cls("mono-tag-input-chip-strip", "chipStrip")} mono-chip-strip>${chips}</div>
1732
+ `;
1733
+ }
1734
+ _renderChips() {
1735
+ const max = this._maxChips;
1736
+ const visible = max === Infinity ? this._resolvedValues : this._resolvedValues.slice(0, max);
1737
+ this._renderedChipCount = visible.length;
1738
+ const chips = visible.map((value) => this._renderChip(value, true));
1739
+ const overflow = this._overflowChips;
1740
+ if (overflow.length) chips.push(html`
1741
+ <div
1742
+ class=${this._cls(`${this._chipBaseClasses.replace(" has-dot", "")} clickable mono-tag-input-more`, "moreChip")}
1743
+ mono-chip
1744
+ mono-more
1745
+ mono-chip-color=${this._chipProps.color ?? nothing}
1746
+ >
1747
+ <span
1748
+ class=${ifDefined(this._chipProps.cssClass?.main)}
1749
+ mono-chip-main
1750
+ role="button"
1751
+ tabindex="0"
1752
+ @mousedown=${(event) => event.preventDefault()}
1753
+ @click=${(event) => {
1754
+ event.stopPropagation();
1755
+ this._moreOpen = !this._moreOpen;
1756
+ if (this._moreOpen) this._close();
1757
+ }}
1758
+ >
1759
+ <span class=${this._chipCls("chip-content", "content")} mono-chip-content>
1760
+ <span class=${this._chipCls("chip-label", "label")} mono-chip-label>+${overflow.length} more</span>
1761
+ </span>
1762
+ </span>
1763
+ </div>
1764
+ `);
1765
+ return chips;
1766
+ }
1767
+ /**
1768
+ * The trailing control row: `‹ › ✕` or `‹ › ⌄`.
1769
+ *
1770
+ * The scroll buttons only exist in `inline` mode, and each only while there is
1771
+ * something to scroll toward — so a strip that fits shows neither, and a strip
1772
+ * parked at its start shows only `›`.
1773
+ *
1774
+ * Clear and caret are MUTUALLY EXCLUSIVE, in both layouts: whenever the clear
1775
+ * button is available the field has a value and clearing is the useful action,
1776
+ * and whenever it is not (empty field, or `clearable`/`disabled`/`readonly`
1777
+ * ruling it out) the caret advertises the dropdown instead. That keeps the row
1778
+ * one glyph wide, which is what lets `flex` mode go on reserving a single-icon
1779
+ * gutter.
1780
+ *
1781
+ * The scroll buttons suppress `mousedown` and stay out of the tab order: they
1782
+ * are a view control, so paging must not blur the input (which would close the
1783
+ * dropdown mid-interaction) or move focus off the field. The clear button
1784
+ * keeps its existing focus behaviour.
1785
+ */
1786
+ /**
1787
+ * One scroll button. `active` false keeps the box — and therefore the row's
1788
+ * width — but hides it (`is-idle` → `visibility: hidden`), so reaching an end
1789
+ * of the strip costs no layout. `disabled` and `aria-hidden` keep the hidden
1790
+ * one out of reach of the pointer and of assistive tech.
1791
+ */
1792
+ _renderScrollButton(dir, active) {
1793
+ const back = dir === -1;
1794
+ const base = `mono-tag-input-scroll mono-tag-input-scroll-${back ? "prev" : "next"}${active ? "" : " is-idle"}`;
1795
+ return html`
1796
+ <button
1797
+ type="button"
1798
+ class=${this._cls(base, back ? "scrollPrev" : "scrollNext")}
1799
+ mono-scroll=${back ? "prev" : "next"}
1800
+ ?mono-idle=${!active}
1801
+ aria-label=${back ? "Scroll tags backward" : "Scroll tags forward"}
1802
+ aria-hidden=${active ? "false" : "true"}
1803
+ ?disabled=${!active}
1804
+ tabindex="-1"
1805
+ @mousedown=${(event) => event.preventDefault()}
1806
+ @click=${(event) => {
1807
+ event.stopPropagation();
1808
+ this._chipStrip.page(dir);
1809
+ }}
1810
+ >
1811
+ ${chevronIcon(dir)}
1812
+ </button>
1813
+ `;
1814
+ }
1815
+ /** Spinner while the source first loads, ↻ after it failed; else nothing. */
1816
+ _renderSourceState() {
1817
+ if (this._busy) return html`<span mono-ds-spinner role="status" aria-label=${this.loadingText}>${spinnerIcon()}</span>`;
1818
+ if (this._failure && !this.disabled) return html`
1819
+ <button
1820
+ type="button"
1821
+ tabindex="-1"
1822
+ mono-ds-retry
1823
+ aria-label=${this.retryLabel}
1824
+ title=${this.retryLabel}
1825
+ @mousedown=${(event) => event.preventDefault()}
1826
+ @click=${this._retry}
1827
+ >
1828
+ ${refreshIcon()}
1829
+ </button>
1830
+ `;
1831
+ return nothing;
1832
+ }
1833
+ _renderActions() {
1834
+ const showScroll = this._chipBehaviour === "inline" && this._chipStrip.overflowing;
1835
+ const showArrow = !this._showClear && !this._inert;
1836
+ return html`
1837
+ <div class=${this._cls("mono-tag-input-actions", "actions")} mono-actions>
1838
+ ${showScroll ? html`
1839
+ ${this._renderScrollButton(-1, this._chipStrip.canScrollStart)}
1840
+ ${this._renderScrollButton(1, this._chipStrip.canScrollEnd)}
1841
+ ` : nothing}
1842
+ ${this._showClear ? html`
1843
+ <button
1844
+ type="button"
1845
+ class=${this._cls("mono-tag-input-clear", "clear")}
1846
+ mono-clear
1847
+ aria-label="Clear tags"
1848
+ @click=${this._clear}
1849
+ >
1850
+ ${this.renderIcon("close")}
1851
+ </button>
1852
+ ` : nothing}
1853
+ ${showArrow ? html`
1854
+ <span
1855
+ role="button"
1856
+ tabindex="-1"
1857
+ class=${this._cls("mono-tag-input-arrow", "arrow")}
1858
+ mono-arrow
1859
+ aria-label="Toggle suggestions"
1860
+ aria-expanded=${this._open ? "true" : "false"}
1861
+ @mousedown=${(event) => event.preventDefault()}
1862
+ @click=${this._toggleFromCaret}
1863
+ >
1864
+ ${caretIcon()}
1865
+ </span>
1866
+ ` : nothing}
1867
+ ${this._renderSourceState()}
1868
+ </div>
1869
+ `;
1870
+ }
1871
+ /**
1872
+ * Always rendered, shown by the root's `more-open` class: the panel lives in a
1873
+ * body portal while open and a portaled node cannot be removed by a
1874
+ * conditional render (Lit's ChildPart no longer contains it).
1875
+ */
1876
+ _renderMorePanel() {
1877
+ const overflow = this._moreOpen ? this._overflowChips : [];
1878
+ return html`
1879
+ <div class=${this._cls("mono-tag-input-more-panel", "morePanel")} mono-more-panel>
1880
+ ${overflow.map((value) => this._renderChip(value, true))}
1881
+ </div>
1882
+ `;
1883
+ }
1884
+ _toCssLength(value) {
1885
+ if (value == null || value === "") return void 0;
1886
+ if (typeof value === "number") return `${value}px`;
1887
+ const trimmed = String(value).trim();
1888
+ if (!trimmed) return void 0;
1889
+ return /^-?\d+(?:\.\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed;
1890
+ }
1891
+ /**
1892
+ * The author's cap goes out as the custom property `--_mono-tag-input-panel-max-h`
1893
+ * rather than a direct `max-height`: the popup controller also constrains this
1894
+ * same element (via `--mono-popup-avail-h`) to keep it inside the viewport, and
1895
+ * two writers on one declaration would clobber each other. The CSS `min()`s them.
1896
+ */
1897
+ get _dropdownStyle() {
1898
+ const style = {};
1899
+ const panel = this.dropdown;
1900
+ const width = toCssSize(panel?.width);
1901
+ if (width) style.width = width;
1902
+ const minWidth = toCssSize(panel?.minWidth);
1903
+ if (minWidth) style["min-width"] = minWidth;
1904
+ const maxWidth = toCssSize(panel?.maxWidth);
1905
+ if (maxWidth) style["max-width"] = maxWidth;
1906
+ const minHeight = toCssSize(panel?.minHeight);
1907
+ if (minHeight) style["min-height"] = minHeight;
1908
+ const height = toCssSize(panel?.height) ?? this._toCssLength(this.dropdownHeight);
1909
+ if (height) style.height = height;
1910
+ const maxHeight = toCssSize(panel?.maxHeight) ?? this._toCssLength(this.dropdownMaxHeight);
1911
+ if (maxHeight) style["--_mono-tag-input-panel-max-h"] = maxHeight;
1912
+ else if (height) style["--_mono-tag-input-panel-max-h"] = height;
1913
+ else if (this._scrollAutoMaxHeight) style["--_mono-tag-input-panel-max-h"] = this._scrollAutoMaxHeight;
1914
+ return style;
1915
+ }
1916
+ /**
1917
+ * Scroll-mode ergonomics (see mono-select): cap the list height to the loaded
1918
+ * rows minus a sliver so a short page is still scrollable, instead of eagerly
1919
+ * fetching another page on open.
1920
+ */
1921
+ _updateScrollAutoHeight() {
1922
+ const userSetHeight = this._toCssLength(this.dropdownHeight) != null || this._toCssLength(this.dropdownMaxHeight) != null || toCssSize(this.dropdown?.height) != null || toCssSize(this.dropdown?.maxHeight) != null;
1923
+ const rowsShown = this._filteredItems.length;
1924
+ if (!(this._loadMoreMode === "scroll" && this._open && !this._ds.atLastPage && !userSetHeight && rowsShown > 0)) {
1925
+ this._setScrollAutoMaxHeight("");
1926
+ return;
1927
+ }
1928
+ const el = this._dropdownEl;
1929
+ const rowH = (el?.querySelector(".mono-tag-input-item"))?.offsetHeight ?? 0;
1930
+ if (!el || !rowH) return;
1931
+ const CAP_ROWS = 7;
1932
+ let visible = Math.min(rowsShown, CAP_ROWS);
1933
+ if (rowsShown <= CAP_ROWS) visible -= .5;
1934
+ this._setScrollAutoMaxHeight(`${Math.round(visible * rowH)}px`);
1935
+ }
1936
+ _setScrollAutoMaxHeight(value) {
1937
+ if (value === this._scrollAutoMaxHeight) return;
1938
+ queueMicrotask(() => {
1939
+ this._scrollAutoMaxHeight = value;
1940
+ });
1941
+ }
1942
+ _renderLoadMore() {
1943
+ if (!this._loadMoreMode) return nothing;
1944
+ if (!this._visibleItems.length || this._ds.atLastPage) return nothing;
1945
+ if (this._ds.loadingMore) return html`
1946
+ <div class=${`${this._cls("mono-tag-input-load-more", "loadMore")} loading`} mono-load-more mono-loading>
1947
+ Loading…
1948
+ </div>
1949
+ `;
1950
+ if (this._loadMoreMode !== "button") return nothing;
1951
+ return html`
1952
+ <button
1953
+ type="button"
1954
+ class=${this._cls("mono-tag-input-load-more", "loadMore")}
1955
+ mono-load-more
1956
+ @mousedown=${(event) => event.preventDefault()}
1957
+ @click=${(event) => {
1958
+ event.preventDefault();
1959
+ event.stopPropagation();
1960
+ this._ds.loadMore();
1961
+ }}
1962
+ >
1963
+ Load more
1964
+ </button>
1965
+ `;
1966
+ }
1967
+ /**
1968
+ * The reused `.mono-checkbox` box. Tri-state: `'some'` paints the indeterminate
1969
+ * dash, which is what tells a user a group is PARTLY selected — the one thing a
1970
+ * two-state box could not say.
1971
+ */
1972
+ _renderCheckBox(state, loading = false) {
1973
+ const cls = [
1974
+ this._cls("mono-checkbox", "check"),
1975
+ this.color,
1976
+ state === "all" ? "mono-checkbox-checked" : "",
1977
+ state === "some" ? "mono-checkbox-indeterminate" : "",
1978
+ loading ? "is-loading" : ""
1979
+ ].filter(Boolean).join(" ");
1980
+ const boxCls = [
1981
+ "mono-checkbox-box",
1982
+ "sm",
1983
+ loading ? "has-custom-icon has-custom-indeterminate-icon" : ""
1984
+ ].filter(Boolean).join(" ");
1985
+ return html`
1986
+ <span
1987
+ class=${cls}
1988
+ mono-check-box
1989
+ mono-checkbox
1990
+ mono-size="sm"
1991
+ mono-color=${this.color === "primary" ? nothing : this.color}
1992
+ ?mono-checked=${state === "all"}
1993
+ ?mono-indeterminate=${state === "some"}
1994
+ ?mono-loading=${loading}
1995
+ aria-hidden="true"
1996
+ >
1997
+ <span class=${boxCls} mono-box ?mono-custom-icon=${loading} ?mono-custom-indeterminate-icon=${loading}>${loading ? this._renderCheckSpinner() : nothing}</span>
1998
+ </span>
1999
+ `;
2000
+ }
2001
+ /**
2002
+ * The drain spinner. Inline SVG rather than the `i-mdi-loading` UnoCSS class
2003
+ * because a page stylesheet cannot reach the shadow build's root — one template
2004
+ * serves both, the same reason `composables/field-icons` exists.
2005
+ *
2006
+ * `.mono-checkbox-spinner` carries the sizing and the keyframes; checkbox.css is
2007
+ * already on the page for the light build and adopted into the shadow root for
2008
+ * the other, which is what the box itself depends on too.
2009
+ */
2010
+ _renderCheckSpinner() {
2011
+ return html`<svg
2012
+ class="mono-checkbox-spinner"
2013
+ mono-spinner
2014
+ viewBox="0 0 24 24"
2015
+ fill="none"
2016
+ stroke="currentColor"
2017
+ stroke-width="3"
2018
+ stroke-linecap="round"
2019
+ aria-hidden="true"
2020
+ >
2021
+ <path d="M12 3a9 9 0 1 0 9 9" />
2022
+ </svg>`;
2023
+ }
2024
+ /**
2025
+ * The leading "All" row. Scoped to the rows the current search leaves visible,
2026
+ * which is what `items` already is at every call site.
2027
+ *
2028
+ * `role="option"` because that is what it behaves like — an option meaning "every
2029
+ * one of these" — so a screen reader announces it inside the same listbox as the
2030
+ * rows it toggles.
2031
+ */
2032
+ _renderSelectAll(items) {
2033
+ if (!this.selectAll || this.disabled || this.readonly) return nothing;
2034
+ const usable = items.filter((item) => this._isSelectable(item));
2035
+ if (!usable.length) return nothing;
2036
+ const state = this._selectAllState(usable);
2037
+ const pending = this._selectAllPending;
2038
+ return html`
2039
+ <button
2040
+ type="button"
2041
+ role="option"
2042
+ class=${[
2043
+ this._cls("mono-tag-input-item", "item"),
2044
+ this._cls("mono-tag-input-select-all", "selectAll"),
2045
+ "has-check",
2046
+ state !== "none" ? "selected" : "",
2047
+ pending ? "is-loading" : ""
2048
+ ].filter(Boolean).join(" ")}
2049
+ mono-item
2050
+ mono-select-all
2051
+ mono-check
2052
+ ?mono-selected=${state !== "none"}
2053
+ ?mono-loading=${pending}
2054
+ aria-selected=${state === "all" ? "true" : "false"}
2055
+ aria-busy=${pending ? "true" : "false"}
2056
+ ?disabled=${pending}
2057
+ @mousedown=${(event) => event.preventDefault()}
2058
+ @click=${(event) => this._onSelectAllClick(usable, state, event)}
2059
+ >
2060
+ ${this._renderCheckBox(state, pending)}
2061
+ <div class=${this._cls("mono-tag-input-item-text", "itemText")} mono-item-text>
2062
+ <div class=${this._cls("mono-tag-input-item-title", "itemTitle")} mono-item-title>
2063
+ ${this.selectAllLabel}
2064
+ </div>
2065
+ </div>
2066
+ </button>
2067
+ `;
2068
+ }
2069
+ /**
2070
+ * A group header — a plain label, or its own select-all when `groupSelectAll` is
2071
+ * on and the group has rows to toggle. It stays a header either way: same class,
2072
+ * same sticky behaviour, same indent, so a grouped list does not reflow when the
2073
+ * feature is switched off.
2074
+ */
2075
+ _renderGroupHeader(row) {
2076
+ const base = `${this._cls("mono-tag-input-group", "group")}${this.groupSticky ? " sticky" : ""}`;
2077
+ const usable = row.items.filter((item) => this._isSelectable(item));
2078
+ if (!this.groupSelectAll || this.disabled || this.readonly || !usable.length) return html`<div class=${base} mono-group mono-level=${row.level} ?mono-sticky=${this.groupSticky} data-level=${row.level} role="presentation">
2079
+ ${row.label}
2080
+ </div>`;
2081
+ const state = this._selectionStateOf(usable);
2082
+ return html`
2083
+ <button
2084
+ type="button"
2085
+ class=${`${base} is-toggle${state !== "none" ? " selected" : ""}`}
2086
+ mono-group
2087
+ mono-toggle
2088
+ mono-level=${row.level}
2089
+ ?mono-sticky=${this.groupSticky}
2090
+ ?mono-selected=${state !== "none"}
2091
+ data-level=${row.level}
2092
+ aria-pressed=${state === "all" ? "true" : "false"}
2093
+ @mousedown=${(event) => event.preventDefault()}
2094
+ @click=${(event) => this._toggleMany(usable, event)}
2095
+ >
2096
+ ${this._renderCheckBox(state)}
2097
+ <span class=${this._cls("mono-tag-input-group-label", "groupLabel")} mono-group-label>
2098
+ ${row.label}
2099
+ </span>
2100
+ </button>
2101
+ `;
2102
+ }
2103
+ /**
2104
+ * The flat entry list published to `form.items()[key].list`.
2105
+ *
2106
+ * The SAME sequence the component renders — group headers interleaved with their leaves — so a
2107
+ * consumer looping it produces one node per row, in order, and the two stay paired by position
2108
+ * with nothing to key by hand. `_groupRows()` already computes exactly this for the grouped case.
2109
+ *
2110
+ * `key` is `item[keyValue]` via `_resolveItemValue`, the same value selection is keyed by, so the
2111
+ * feature introduces no second notion of a key.
2112
+ */
2113
+ _listEntries() {
2114
+ const rowEntry = (item, level, index) => ({
2115
+ type: "row",
2116
+ key: String(this._resolveItemValue(item) ?? ""),
2117
+ item,
2118
+ level,
2119
+ selected: this._isSelected(item),
2120
+ active: index >= 0 && index === this._activeIndex
2121
+ });
2122
+ if (this._grouped) return this._groupRows().map((row) => row.kind === "group" ? {
2123
+ type: "group",
2124
+ key: row.key,
2125
+ label: row.label,
2126
+ level: row.level,
2127
+ items: row.items
2128
+ } : rowEntry(row.item, row.level, row.index));
2129
+ return this._filteredItems.map((item, index) => rowEntry(item, 0, index));
2130
+ }
2131
+ /**
2132
+ * Hand the form the current entries — but only a NEW array when they actually moved.
2133
+ *
2134
+ * This runs from `updated()`, so it fires on every render; the controller notifies on a changed
2135
+ * list, and that notify re-renders this control. Returning the same array reference is what keeps
2136
+ * that from looping forever. Identity of `item` counts as a change: a reloaded DataSource hands
2137
+ * back fresh row objects under the same keys, and a consumer reading `e.item.Nama` must see them.
2138
+ */
2139
+ _syncListEntries() {
2140
+ const next = this._listEntries();
2141
+ const prev = this._publishedEntries;
2142
+ let same = prev.length === next.length;
2143
+ if (same) for (let i = 0; i < next.length; i++) {
2144
+ const a = prev[i];
2145
+ const b = next[i];
2146
+ if (a.type !== b.type || a.key !== b.key || a.item !== b.item || a.selected !== b.selected || a.active !== b.active) {
2147
+ same = false;
2148
+ break;
2149
+ }
2150
+ }
2151
+ if (same) return;
2152
+ this._publishedEntries = next;
2153
+ this._publishList(next);
2154
+ }
2155
+ _renderOption(item, index, level = 0) {
2156
+ const active = index === this._activeIndex;
2157
+ const checked = this._isSelected(item);
2158
+ const itemClass = [
2159
+ this._cls("mono-tag-input-item", "item"),
2160
+ this.checkable ? "has-check" : "",
2161
+ active ? `active ${this.cssClass?.itemActive ?? ""}` : "",
2162
+ checked ? `selected ${this.cssClass?.itemSelected ?? ""}` : "",
2163
+ item.disabled ? `disabled ${this.cssClass?.itemDisabled ?? ""}` : ""
2164
+ ].filter(Boolean).join(" ");
2165
+ const itemValue = this._resolveItemValue(item);
2166
+ return html`
2167
+ <button
2168
+ type="button"
2169
+ role="option"
2170
+ class=${itemClass}
2171
+ mono-item
2172
+ ?mono-check=${this.checkable}
2173
+ ?mono-active=${active}
2174
+ ?mono-selected=${checked}
2175
+ ?mono-disabled=${!!item.disabled}
2176
+ mono-level=${level}
2177
+ data-level=${level}
2178
+ aria-selected=${checked ? "true" : "false"}
2179
+ ?disabled=${item.disabled}
2180
+ @mousedown=${(event) => event.preventDefault()}
2181
+ @click=${(event) => itemValue === void 0 ? void 0 : this._toggleValue(itemValue, event)}
2182
+ >
2183
+ ${this.checkable ? this._renderCheckBox(checked ? "all" : "none") : nothing}
2184
+
2185
+ <div class=${this._cls("mono-tag-input-item-text", "itemText")} mono-item-text>
2186
+ <div class=${this._cls("mono-tag-input-item-title", "itemTitle")} mono-item-title>
2187
+ ${this._resolveItemDisplay(item)}
2188
+ </div>
2189
+
2190
+ ${item.description ? html`
2191
+ <div class=${this._cls("mono-tag-input-item-sub", "itemSub")} mono-item-sub>
2192
+ ${item.description}
2193
+ </div>
2194
+ ` : nothing}
2195
+ </div>
2196
+ </button>
2197
+ `;
2198
+ }
2199
+ _renderEmpty() {
2200
+ const text = this.dataSource && this._ds.loading ? this.loadingText : "No items";
2201
+ return html`<div class=${this._cls("mono-tag-input-empty", "empty")} mono-empty-row>${text}</div>`;
2202
+ }
2203
+ _renderItems() {
2204
+ const visible = this._filteredItems;
2205
+ const empty = !visible.length;
2206
+ if (this._hasListSlotState) return html`
2207
+ ${empty ? this._renderEmpty() : this._renderSelectAll(visible)}
2208
+ ${this.renderListSlot()}
2209
+ `;
2210
+ if (empty) return this._renderEmpty();
2211
+ if (this._grouped) return html`
2212
+ ${this._renderSelectAll(visible)}
2213
+ ${this._groupRows().map((row) => row.kind === "group" ? this._renderGroupHeader(row) : this._renderOption(row.item, row.index, row.level))}
2214
+ `;
2215
+ return html`
2216
+ ${this._renderSelectAll(visible)}
2217
+ ${visible.map((item, index) => this._renderOption(item, index))}
2218
+ `;
2219
+ }
2220
+ /**
2221
+ * Where the consumer's `slot="list"` content goes — overridden per build.
2222
+ *
2223
+ * mono places that content as ONE block and never reaches inside it. Moving a `v-for`'s children
2224
+ * is not survivable: Vue inserts a new row with `parent.insertBefore(node, anchor)` where the
2225
+ * anchor is the existing node at that position, so relocating one makes the consumer's next
2226
+ * insert throw `NotFoundError`. Hence one block, and hence `data-mono-item-key` — with the rows
2227
+ * out of reach, a delegated click is the only way back to the item.
2228
+ */
2229
+ renderListSlot() {
2230
+ return html``;
2231
+ }
2232
+ /**
2233
+ * The entry a click landed on — by POSITION, so a consumer writes a plain `v-for` and nothing else.
2234
+ *
2235
+ * mono cannot read a node's item off the node: it published the list, but the DOM was built by
2236
+ * someone else. What it CAN do is count. The wrapper's Nth element child is the Nth published
2237
+ * entry, because that is the contract the slot already states — one flat loop, one node per entry,
2238
+ * in order — and here that contract is CHECKED rather than assumed: if the two lengths disagree,
2239
+ * this refuses the click instead of picking the wrong row.
2240
+ *
2241
+ * Position is resolved at CLICK time, never cached. That is what makes it safe with no observer
2242
+ * and no re-stamping: by the time a human clicks, the framework has long finished patching, so
2243
+ * there is no window where a stale pairing could be consulted.
2244
+ *
2245
+ * `data-mono-item-key` still wins when present — the escape hatch for a wrapper that cannot emit
2246
+ * exactly one element per entry (a sticky header of your own, a row that renders as a fragment).
2247
+ */
2248
+ /**
2249
+ * The consumer's `slot="list"` wrapper, wherever the build keeps it.
2250
+ *
2251
+ * The shadow build never moves it — it stays a light child of the host and is PROJECTED — so
2252
+ * that is the default. The light build moves it into the panel and overrides this with the node
2253
+ * it captured, which is also findable while the panel is closed and the wrapper parked.
2254
+ */
2255
+ get _listSlotWrapper() {
2256
+ return this._lateListSlot.find();
2257
+ }
2258
+ /**
2259
+ * Re-decorate whenever the consumer re-renders their rows.
2260
+ *
2261
+ * `_syncListChrome()` runs from `updated()`, but a framework patches the wrapper on ITS next
2262
+ * tick — so a row the search box just revealed would be born undecorated and stay that way until
2263
+ * something else made mono render. This closes that gap.
2264
+ *
2265
+ * `childList` on the WRAPPER, which is exactly the churn {@link LateSlotWatcher} refuses on the
2266
+ * host: there the consumer's row traffic is noise, here it IS the signal. No `subtree`, so
2267
+ * mono's own writes — attributes, and a checkbox appended INSIDE a row — cannot re-trigger it.
2268
+ */
2269
+ _watchListChrome() {
2270
+ if (typeof MutationObserver === "undefined") return;
2271
+ const wrapper = this._listSlotWrapper;
2272
+ if (!wrapper || wrapper === this._observedListWrapper) return;
2273
+ this._listChromeObserver?.disconnect();
2274
+ this._observedListWrapper = wrapper;
2275
+ this._listChromeObserver = new MutationObserver(() => this._syncListChrome());
2276
+ this._listChromeObserver.observe(wrapper, { childList: true });
2277
+ }
2278
+ _stopWatchingListChrome() {
2279
+ this._listChromeObserver?.disconnect();
2280
+ this._listChromeObserver = void 0;
2281
+ this._observedListWrapper = void 0;
2282
+ }
2283
+ /**
2284
+ * Decorate the lines the consumer rendered — the half of this feature that keeps the SLOT about
2285
+ * markup and mono about behaviour.
2286
+ *
2287
+ * Your template says what a line LOOKS like. Everything that carries state or acts on the value
2288
+ * stays here: mono walks the lines it just published and stamps the state as `data-*`
2289
+ * attributes, then puts its own checkbox in — the same markup `_renderCheckBox` produces for
2290
+ * mono's own rows, so it inherits the same CSS and the same colour prop.
2291
+ *
2292
+ * Three rules keep this safe beside a framework:
2293
+ * · children are ANNOTATED and APPENDED TO, never moved, reordered or removed — every
2294
+ * `insertBefore` anchor a `v-for` patches against stays valid;
2295
+ * · `data-*` only, never `class` — `class` is the consumer's binding and would be clobbered;
2296
+ * · the injected node is marked `data-mono-chrome`, so it is never mistaken for content and is
2297
+ * updated in place instead of recreated.
2298
+ */
2299
+ _syncListChrome() {
2300
+ if (!this._hasListSlotState) return;
2301
+ const wrapper = this._listSlotWrapper;
2302
+ if (!wrapper) return;
2303
+ const children = Array.from(wrapper.children);
2304
+ const entries = this._publishedEntries;
2305
+ if (children.length !== entries.length) return;
2306
+ for (let i = 0; i < children.length; i++) {
2307
+ const node = children[i];
2308
+ const entry = entries[i];
2309
+ node.setAttribute("data-mono-type", entry.type);
2310
+ node.setAttribute("data-mono-level", String(entry.level ?? 0));
2311
+ node.setAttribute("data-mono-key", entry.key);
2312
+ if (entry.type === "group") {
2313
+ const usable = (entry.items ?? []).filter((item) => this._isSelectable(item));
2314
+ const state = this._selectionStateOf(usable);
2315
+ node.setAttribute("data-mono-state", state);
2316
+ node.toggleAttribute("data-mono-selected", state === "all");
2317
+ this._syncListCheckBox(node, this.checkable && this.groupSelectAll && !this.disabled && !this.readonly && usable.length > 0, state);
2318
+ continue;
2319
+ }
2320
+ node.toggleAttribute("data-mono-selected", !!entry.selected);
2321
+ node.toggleAttribute("data-mono-active", !!entry.active);
2322
+ this._syncListCheckBox(node, this.checkable, entry.selected ? "all" : "none");
2323
+ }
2324
+ }
2325
+ /**
2326
+ * mono's own checkbox, inside a line mono does not own.
2327
+ *
2328
+ * Same markup as `_renderCheckBox`, built by hand because Lit cannot render into a subtree it
2329
+ * does not control. It is created once and then only re-classed, so the consumer's framework
2330
+ * never sees a node appear and disappear under it.
2331
+ */
2332
+ _syncListCheckBox(row, wanted, state) {
2333
+ let box = row.querySelector("[data-mono-chrome]");
2334
+ if (!wanted) {
2335
+ box?.remove();
2336
+ return;
2337
+ }
2338
+ if (!box) {
2339
+ box = document.createElement("span");
2340
+ box.setAttribute("data-mono-chrome", "");
2341
+ box.setAttribute("aria-hidden", "true");
2342
+ const inner = document.createElement("span");
2343
+ inner.className = "mono-checkbox-box sm";
2344
+ inner.setAttribute("mono-box", "");
2345
+ box.setAttribute("mono-check-box", "");
2346
+ box.setAttribute("mono-checkbox", "");
2347
+ box.setAttribute("mono-size", "sm");
2348
+ box.appendChild(inner);
2349
+ const anchor = row.querySelector("[data-mono-check]");
2350
+ if (anchor) anchor.appendChild(box);
2351
+ else row.insertBefore(box, row.firstChild);
2352
+ }
2353
+ box.className = [
2354
+ this._cls("mono-checkbox", "check"),
2355
+ this.color,
2356
+ state === "all" ? "mono-checkbox-checked" : "",
2357
+ state === "some" ? "mono-checkbox-indeterminate" : ""
2358
+ ].filter(Boolean).join(" ");
2359
+ if (this.color === "primary") box.removeAttribute("mono-color");
2360
+ else box.setAttribute("mono-color", this.color);
2361
+ box.toggleAttribute("mono-checked", state === "all");
2362
+ box.toggleAttribute("mono-indeterminate", state === "some");
2363
+ }
2364
+ _entryFromNode(node) {
2365
+ const keyed = node.closest?.("[data-mono-item-key]");
2366
+ if (keyed) {
2367
+ const key = keyed.getAttribute("data-mono-item-key");
2368
+ return this._publishedEntries.find((e) => e.key === key);
2369
+ }
2370
+ const wrapper = node.closest?.("[slot=\"list\"]");
2371
+ if (!wrapper) return void 0;
2372
+ let row = node;
2373
+ while (row && row.parentElement !== wrapper) row = row.parentElement;
2374
+ if (!row) return void 0;
2375
+ const children = Array.from(wrapper.children);
2376
+ if (children.length !== this._publishedEntries.length) {
2377
+ console.warn(`[mono-tag-input] slot="list" rendered ${children.length} element(s) for ${this._publishedEntries.length} option(s), so a click cannot be paired with its row. Render exactly one element per entry, or put data-mono-item-key="<entry.key>" on each row.`);
2378
+ return;
2379
+ }
2380
+ return this._publishedEntries[children.indexOf(row)];
2381
+ }
2382
+ _renderHelper() {
2383
+ const base = this._cls("mono-tag-input-message", "message");
2384
+ if (this.validationMessage) {
2385
+ const state = this._resolvedValidationState;
2386
+ return html`
2387
+ <div class=${`${base} ${state}`} mono-message=${state} role=${state === "invalid" ? "alert" : nothing}>
2388
+ ${this.validationMessage}
2389
+ </div>
2390
+ `;
2391
+ }
2392
+ if (this.errorMessage) return html`
2393
+ <div class=${`${base} invalid`} mono-message="invalid" role="alert">
2394
+ ${this.errorMessage}
2395
+ </div>
2396
+ `;
2397
+ if (this.successMessage) return html`
2398
+ <div class=${`${base} valid`} mono-message="valid">
2399
+ ${this.successMessage}
2400
+ </div>
2401
+ `;
2402
+ if (this.helperText || this._hasHelperSlot || this._slotsAlwaysRender) return html`
2403
+ <div
2404
+ class=${`${base} helper`}
2405
+ mono-message="helper"
2406
+ ?mono-empty=${!this.helperText && !this._hasHelperSlot}
2407
+ >
2408
+ ${this._slotOutlet("helper", this.helperText)}
2409
+ </div>
2410
+ `;
2411
+ return nothing;
2412
+ }
2413
+ /** Inline sizing applied to the root wrapper. */
2414
+ _sizeStyle() {
2415
+ return buildSizeStyle(this);
2416
+ }
2417
+ render() {
2418
+ const describedBy = this.validationMessage || this.errorMessage || this.successMessage || this.helperText || this._hasHelperSlot ? this._messageId : void 0;
2419
+ const ariaLabel = this.ariaLabelText || this.label || this.placeholder || void 0;
2420
+ const state = this._resolvedValidationState;
2421
+ return html`
2422
+ <div
2423
+ class=${this._wrapperClasses}
2424
+ style=${styleMap(this._sizeStyle())}
2425
+ mono-tag-input
2426
+ mono-size=${this.size === "md" ? nothing : this.size}
2427
+ mono-color=${this.color === "primary" ? nothing : this.color}
2428
+ mono-variant=${this.variant === "outlined" ? nothing : this.variant}
2429
+ mono-validation-state=${state === "default" ? nothing : state}
2430
+ ?mono-open=${this._open}
2431
+ ?mono-more-open=${this._moreOpen}
2432
+ ?mono-disabled=${this.disabled}
2433
+ ?mono-readonly=${this.readonly}
2434
+ ?mono-required=${this.required}
2435
+ ?mono-clearable=${this.clearable}
2436
+ ?mono-checkable=${this.checkable}
2437
+ ?mono-searchable=${this.searchable}
2438
+ ?mono-ds-loading=${this._busy}
2439
+ ?mono-ds-error=${!!this._failure}
2440
+ aria-busy=${this._busy ? "true" : nothing}
2441
+ >
2442
+ ${this._renderLabel()}
2443
+
2444
+ <div
2445
+ class=${this._fieldClasses}
2446
+ mono-field
2447
+ ?mono-inline=${this._chipBehaviour === "inline"}
2448
+ ?mono-typing=${!!this._inputValue}
2449
+ @click=${this._handleFieldClick}
2450
+ >
2451
+ ${this._renderChipRegion()}
2452
+
2453
+ <input
2454
+ id=${this._inputId}
2455
+ class=${this._cls("mono-tag-input-native", "native")}
2456
+ mono-native
2457
+ type="text"
2458
+ .value=${this._inputValue}
2459
+ name=${ifDefined(this.name || void 0)}
2460
+ placeholder=${ifDefined(this._inputPlaceholder)}
2461
+ title=${ifDefined(this._dsErrorTitle)}
2462
+ ?disabled=${this.disabled}
2463
+ ?readonly=${this.readonly || !this.searchable || this._dsInert}
2464
+ ?required=${this.required && !this._hasValue}
2465
+ aria-label=${ifDefined(ariaLabel)}
2466
+ aria-invalid=${this._resolvedValidationState === "invalid" ? "true" : "false"}
2467
+ aria-describedby=${ifDefined(describedBy)}
2468
+ aria-controls=${this._listboxId}
2469
+ aria-expanded=${this._open ? "true" : "false"}
2470
+ autocomplete="off"
2471
+ @input=${this._handleInput}
2472
+ @focus=${this._handleFocus}
2473
+ @keydown=${this._handleKeydown}
2474
+ />
2475
+
2476
+ ${this._renderActions()}
2477
+ </div>
2478
+
2479
+ ${this._renderMorePanel()}
2480
+
2481
+ <div
2482
+ id=${this._listboxId}
2483
+ role="listbox"
2484
+ class=${this._cls("mono-tag-input-dropdown", "dropdown")}
2485
+ mono-dropdown
2486
+ style=${styleMap(this._dropdownStyle)}
2487
+ @scroll=${this._handleDropdownScroll}
2488
+ >
2489
+ ${this._renderItems()}
2490
+ ${this._renderLoadMore()}
2491
+ </div>
2492
+
2493
+ <div id=${this._messageId} class=${this.cssClass?.messageWrap ?? ""} mono-message-wrap>
2494
+ ${this._renderHelper()}
2495
+ </div>
2496
+ </div>
2497
+ `;
2498
+ }
2499
+ focus(options) {
2500
+ this._inputEl?.focus(options);
2501
+ }
2502
+ blur() {
2503
+ this._inputEl?.blur();
2504
+ }
2505
+ /**
2506
+ * Open / close the suggestion panel. Mirrors `mono-select`'s API so anything
2507
+ * driving an editor generically — e.g. the data grid opening the focused
2508
+ * inline editor on `Enter` — can treat the two the same.
2509
+ */
2510
+ /** Whether the suggestion panel is currently open. */
2511
+ get isOpen() {
2512
+ return this._open;
2513
+ }
2514
+ open() {
2515
+ if (this._inert) return;
2516
+ this._open = true;
2517
+ this._inputEl?.focus();
2518
+ }
2519
+ close() {
2520
+ this._close();
2521
+ }
2522
+ toggle() {
2523
+ if (this._open) this.close();
2524
+ else this.open();
2525
+ }
2526
+ clearTags() {
2527
+ if (this._inert) return;
2528
+ this._setValue(this._keepFloor([]), { emitClear: true });
2529
+ this._resetSearch();
2530
+ }
2531
+ addTag(value) {
2532
+ this._addValue(value);
2533
+ }
2534
+ removeTag(value) {
2535
+ this._removeValue(value);
2536
+ }
2537
+ /** Whether the slot regions render even when empty. Light: no (omit empty
2538
+ * regions). Shadow: yes — the native `<slot>`s must exist to project DSD
2539
+ * content + be scanned (hidden via `[mono-empty]` when empty). */
2540
+ get _slotsAlwaysRender() {
2541
+ return false;
2542
+ }
2543
+ _hasSlot(name) {
2544
+ return name === "label" ? this._hasLabelSlotState : this._hasHelperSlotState;
2545
+ }
2546
+ _setSlotState(name, has) {
2547
+ if (name === "label") this._hasLabelSlotState = has;
2548
+ else if (name === "list") this._hasListSlotState = has;
2549
+ else this._hasHelperSlotState = has;
2550
+ }
2551
+ /**
2552
+ * Slot outlet. Light build (default): a `data-mono-slot` placeholder the
2553
+ * captured light-DOM nodes are re-parented into when present, else the prop
2554
+ * `fallback`. Shadow build overrides this with a native `<slot name>` carrying
2555
+ * the fallback as native slot content.
2556
+ */
2557
+ _slotOutlet(name, fallback = nothing) {
2558
+ return this._hasSlot(name) ? html`<span data-mono-slot=${name}></span>` : html`${fallback}`;
2559
+ }
2560
+ /**
2561
+ * Icon hook. Light build (default): the global `.mono-icon` / `i-mdi-*` UnoCSS
2562
+ * icon. Shadow overrides with inline SVG (UnoCSS can't reach a shadow root).
2563
+ *
2564
+ * Only the close glyph goes through here. The caret and the scroll chevrons
2565
+ * are inline SVG from `composables/field-icons`, shared with
2566
+ * `<mono-dropdown-table>` — see `_renderActions`.
2567
+ */
2568
+ renderIcon(_name) {
2569
+ return html`<span class="mono-icon i-mdi-close" mono-icon aria-hidden="true"></span>`;
2570
+ }
2571
+ }
2572
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "size", void 0);
2573
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "color", void 0);
2574
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "variant", void 0);
2575
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "chip", void 0);
2576
+ __decorate([property({
2577
+ attribute: "model-value",
2578
+ reflect: false,
2579
+ hasChanged: arrayHasChanged
2580
+ })], MonoTagInputCoreClass.prototype, "modelValue", void 0);
2581
+ __decorate([property({
2582
+ attribute: false,
2583
+ hasChanged: arrayHasChanged
2584
+ })], MonoTagInputCoreClass.prototype, "value", void 0);
2585
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "name", void 0);
2586
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "label", void 0);
2587
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "placeholder", void 0);
2588
+ __decorate([property({
2589
+ type: String,
2590
+ attribute: "loading-text"
2591
+ })], MonoTagInputCoreClass.prototype, "loadingText", void 0);
2592
+ __decorate([property({
2593
+ type: String,
2594
+ attribute: "retry-label"
2595
+ })], MonoTagInputCoreClass.prototype, "retryLabel", void 0);
2596
+ __decorate([property({ converter: booleanStringConverter })], MonoTagInputCoreClass.prototype, "loading", void 0);
2597
+ __decorate([property({ attribute: "loading-error" })], MonoTagInputCoreClass.prototype, "loadingError", void 0);
2598
+ __decorate([property({
2599
+ type: String,
2600
+ attribute: "helper-text"
2601
+ })], MonoTagInputCoreClass.prototype, "helperText", void 0);
2602
+ __decorate([property({
2603
+ type: String,
2604
+ attribute: "validation-state"
2605
+ })], MonoTagInputCoreClass.prototype, "validationState", void 0);
2606
+ __decorate([property({
2607
+ type: String,
2608
+ attribute: "validation-message"
2609
+ })], MonoTagInputCoreClass.prototype, "validationMessage", void 0);
2610
+ __decorate([property({
2611
+ type: String,
2612
+ attribute: "error-message"
2613
+ })], MonoTagInputCoreClass.prototype, "errorMessage", void 0);
2614
+ __decorate([property({
2615
+ type: String,
2616
+ attribute: "success-message"
2617
+ })], MonoTagInputCoreClass.prototype, "successMessage", void 0);
2618
+ __decorate([property({
2619
+ type: String,
2620
+ attribute: "aria-label"
2621
+ })], MonoTagInputCoreClass.prototype, "ariaLabelText", void 0);
2622
+ __decorate([property({
2623
+ reflect: true,
2624
+ converter: booleanStringConverter
2625
+ })], MonoTagInputCoreClass.prototype, "disabled", void 0);
2626
+ __decorate([property({
2627
+ reflect: true,
2628
+ converter: booleanStringConverter
2629
+ })], MonoTagInputCoreClass.prototype, "readonly", void 0);
2630
+ __decorate([property({
2631
+ reflect: true,
2632
+ converter: booleanStringConverter
2633
+ })], MonoTagInputCoreClass.prototype, "required", void 0);
2634
+ __decorate([property({
2635
+ reflect: true,
2636
+ converter: booleanStringConverter
2637
+ })], MonoTagInputCoreClass.prototype, "clearable", void 0);
2638
+ __decorate([property({
2639
+ attribute: "allow-custom",
2640
+ reflect: true,
2641
+ converter: booleanStringConverter
2642
+ })], MonoTagInputCoreClass.prototype, "allowCustom", void 0);
2643
+ __decorate([property({
2644
+ attribute: "max",
2645
+ converter: numberStringConverter
2646
+ })], MonoTagInputCoreClass.prototype, "max", void 0);
2647
+ __decorate([property({
2648
+ attribute: "min",
2649
+ converter: numberStringConverter
2650
+ })], MonoTagInputCoreClass.prototype, "min", void 0);
2651
+ __decorate([property({
2652
+ reflect: true,
2653
+ converter: booleanStringConverter
2654
+ })], MonoTagInputCoreClass.prototype, "checkable", void 0);
2655
+ __decorate([property({
2656
+ attribute: "select-all",
2657
+ reflect: true,
2658
+ converter: booleanStringConverter
2659
+ })], MonoTagInputCoreClass.prototype, "selectAll", void 0);
2660
+ __decorate([property({
2661
+ type: String,
2662
+ attribute: "select-all-label",
2663
+ reflect: true
2664
+ })], MonoTagInputCoreClass.prototype, "selectAllLabel", void 0);
2665
+ __decorate([property({
2666
+ attribute: "group-select-all",
2667
+ reflect: true,
2668
+ converter: booleanStringConverter
2669
+ })], MonoTagInputCoreClass.prototype, "groupSelectAll", void 0);
2670
+ __decorate([property({
2671
+ attribute: "max-visible",
2672
+ converter: numberStringConverter
2673
+ })], MonoTagInputCoreClass.prototype, "maxVisible", void 0);
2674
+ __decorate([property({
2675
+ attribute: "min-visible",
2676
+ converter: numberStringConverter
2677
+ })], MonoTagInputCoreClass.prototype, "minVisible", void 0);
2678
+ __decorate([property({
2679
+ attribute: false,
2680
+ hasChanged: arrayHasChanged
2681
+ })], MonoTagInputCoreClass.prototype, "items", void 0);
2682
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "dataSource", void 0);
2683
+ __decorate([property({
2684
+ attribute: "immediate",
2685
+ reflect: true,
2686
+ converter: booleanStringConverter
2687
+ })], MonoTagInputCoreClass.prototype, "immediate", void 0);
2688
+ __decorate([property({
2689
+ attribute: "load-more",
2690
+ reflect: true
2691
+ })], MonoTagInputCoreClass.prototype, "loadMore", void 0);
2692
+ __decorate([property({
2693
+ attribute: "page-size",
2694
+ reflect: true,
2695
+ type: Number
2696
+ })], MonoTagInputCoreClass.prototype, "pageSize", void 0);
2697
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "dropdown", void 0);
2698
+ __decorate([property({
2699
+ attribute: "dropdown-height",
2700
+ reflect: true
2701
+ })], MonoTagInputCoreClass.prototype, "dropdownHeight", void 0);
2702
+ __decorate([property({
2703
+ attribute: "dropdown-max-height",
2704
+ reflect: true
2705
+ })], MonoTagInputCoreClass.prototype, "dropdownMaxHeight", void 0);
2706
+ __decorate([property({ converter: booleanStringConverter })], MonoTagInputCoreClass.prototype, "flip", void 0);
2707
+ __decorate([property({ converter: booleanStringConverter })], MonoTagInputCoreClass.prototype, "shift", void 0);
2708
+ __decorate([property({
2709
+ type: String,
2710
+ attribute: "key-value",
2711
+ reflect: true
2712
+ })], MonoTagInputCoreClass.prototype, "keyValue", void 0);
2713
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "displayValue", void 0);
2714
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "displayGroup", void 0);
2715
+ __decorate([property({
2716
+ type: String,
2717
+ attribute: "group-key",
2718
+ reflect: true
2719
+ })], MonoTagInputCoreClass.prototype, "groupKey", void 0);
2720
+ __decorate([property({
2721
+ type: String,
2722
+ attribute: "group-items",
2723
+ reflect: true
2724
+ })], MonoTagInputCoreClass.prototype, "groupItems", void 0);
2725
+ __decorate([property({
2726
+ attribute: "group",
2727
+ reflect: true,
2728
+ converter: booleanStringConverter
2729
+ })], MonoTagInputCoreClass.prototype, "group", void 0);
2730
+ __decorate([property({
2731
+ attribute: "group-sticky",
2732
+ reflect: true,
2733
+ converter: booleanStringConverter
2734
+ })], MonoTagInputCoreClass.prototype, "groupSticky", void 0);
2735
+ __decorate([property({
2736
+ attribute: "searchable",
2737
+ reflect: true,
2738
+ converter: booleanStringConverter
2739
+ })], MonoTagInputCoreClass.prototype, "searchable", void 0);
2740
+ __decorate([property({
2741
+ attribute: "stay-open",
2742
+ reflect: true,
2743
+ converter: booleanStringConverter
2744
+ })], MonoTagInputCoreClass.prototype, "stayOpen", void 0);
2745
+ __decorate([property({ attribute: "search-value" })], MonoTagInputCoreClass.prototype, "searchValue", void 0);
2746
+ __decorate([property({
2747
+ type: String,
2748
+ attribute: "search-operation"
2749
+ })], MonoTagInputCoreClass.prototype, "searchOperation", void 0);
2750
+ __decorate([property({
2751
+ attribute: "search-debounce",
2752
+ type: Number
2753
+ })], MonoTagInputCoreClass.prototype, "searchDebounce", void 0);
2754
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "cssClass", void 0);
2755
+ __decorate([property({ attribute: false })], MonoTagInputCoreClass.prototype, "cssClassName", void 0);
2756
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_inputValue", void 0);
2757
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_open", void 0);
2758
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_activeIndex", void 0);
2759
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_moreOpen", void 0);
2760
+ __decorate([state(), state()], MonoTagInputCoreClass.prototype, "_selectAllPending", void 0);
2761
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_hasLabelSlotState", void 0);
2762
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_hasHelperSlotState", void 0);
2763
+ __decorate([query(".mono-tag-input-native")], MonoTagInputCoreClass.prototype, "_inputEl", void 0);
2764
+ __decorate([state()], MonoTagInputCoreClass.prototype, "_hasListSlotState", void 0);
2765
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "width", void 0);
2766
+ __decorate([property({ type: String })], MonoTagInputCoreClass.prototype, "height", void 0);
2767
+ __decorate([property({
2768
+ type: String,
2769
+ attribute: "min-width"
2770
+ })], MonoTagInputCoreClass.prototype, "minWidth", void 0);
2771
+ __decorate([property({
2772
+ type: String,
2773
+ attribute: "max-width"
2774
+ })], MonoTagInputCoreClass.prototype, "maxWidth", void 0);
2775
+ __decorate([property({
2776
+ type: String,
2777
+ attribute: "min-height"
2778
+ })], MonoTagInputCoreClass.prototype, "minHeight", void 0);
2779
+ __decorate([property({
2780
+ type: String,
2781
+ attribute: "max-height"
2782
+ })], MonoTagInputCoreClass.prototype, "maxHeight", void 0);
2783
+ return MonoTagInputCoreClass;
2784
+ };
2785
+ //#endregion
2786
+ //#region src/components/tag-input/tag-input.css?raw
2787
+ var tag_input_default = "/* =========================================================================\r\n mono-tag-input — a port of Basecoat's multi-select combobox: `.combobox-chips`\r\n (the field), `.combobox-chip` (+ `-remove`) and the `.combobox [data-popover]`\r\n list (basecoat-css@1.0.2, vega style), on the `.field` / `.label` chrome the\r\n ported input already carries.\r\n\r\n Styled by ATTRIBUTE, like Basecoat — and the attributes mirror the element's\r\n props one for one, so hand-written markup reads like the Lit / Vue tag:\r\n\r\n <mono-tag-input size=\"sm\" color=\"danger\" variant=\"filled\" label=\"Tags\">\r\n <div mono-tag-input mono-size=\"sm\" mono-color=\"danger\" mono-variant=\"filled\">\r\n <label mono-label>Tags</label>\r\n <div mono-field>\r\n <div mono-chip mono-removable><span mono-chip-main><span mono-chip-content>\r\n <span mono-chip-label>Vue</span><button mono-chip-close>…</button></span></span></div>\r\n <input mono-native /> <div mono-actions><span mono-arrow>…</span></div>\r\n </div>\r\n </div>\r\n\r\n An absent attribute is the prop's default (`:not([mono-size])` = md,\r\n `:not([mono-color])` = primary, `:not([mono-variant])` = outlined). The element\r\n renders these attributes on its wrapper (both builds) plus the STATES\r\n `mono-open` / `mono-more-open`; the old classes (`.mono-tag-input.sm.open`) are\r\n still emitted as inert hooks until 2.0 but no rule here reads them. The tag\r\n chips are NOT `.mono-chip`s any more: they are Basecoat combobox chips, painted\r\n here (`[mono-tag-input] [mono-chip]`), and chip.css never sees them.\r\n\r\n Selector map (ours ≡ upstream):\r\n [mono-tag-input] ≡ .field (gap-3, as margins — see the root rule) + .combobox (position: relative)\r\n [mono-tag-input] > [mono-label] ≡ .field > label / .label\r\n [mono-tag-input] > [mono-field] ≡ .combobox-chips (min-h-9 gap-1.5 rounded-md border-input px-1.5 py-1.5 text-sm shadow-xs)\r\n [mono-field] > [mono-native] ≡ .combobox-chips > input[role='combobox'] (min-w-16 flex-1, borderless)\r\n [mono-field] [mono-chip] > [mono-chip-main] ≡ .combobox-chip (h-5.5 gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium)\r\n [mono-chip] [mono-chip-close] ≡ .combobox-chip-remove (-ms-1 opacity-50 hover:100, svg size-3.5)\r\n [mono-chip][mono-more] ≡ EXTENSION (the \"+N more\" counter chip, same box)\r\n [mono-actions] > [mono-arrow] > svg ≡ .combobox-trigger-icon (size-4 text-muted-foreground)\r\n [mono-actions] > [mono-clear] ≡ .combobox [data-clear] (size-6, painted as .btn[data-variant='ghost'])\r\n [mono-actions] > [mono-scroll] ≡ EXTENSION (the inline strip's ‹ › pager, same box)\r\n [mono-dropdown] ≡ .combobox [data-popover] + [role='listbox'] (bg-popover ring-1 rounded-md shadow-md, max-h-72 p-1 scroll)\r\n [mono-item] ≡ .combobox [role='option'] (gap-2 rounded-sm py-1.5 ps-2 text-sm)\r\n [mono-item][mono-active] / :hover ≡ [role='option'].active (bg-muted text-foreground)\r\n [mono-item][mono-selected] ≡ [role='option'][aria-selected='true'] — the --check-icon, unless the row has its own checkbox\r\n [mono-group] ≡ .combobox [role='heading'] (px-2 py-1.5 text-xs text-muted-foreground)\r\n [mono-select-all] ≡ EXTENSION (a sticky option row over the list)\r\n [mono-more-panel] ≡ [data-popover] holding the overflow chips\r\n [mono-empty-row] ≡ [role='listbox']::before (py-6 text-center text-sm)\r\n [mono-message-wrap] > [mono-message] ≡ .field > p / .field [role='alert']\r\n [mono-validation-state=\"invalid\"] ≡ .combobox-chips:has([aria-invalid=true]) + .field[data-invalid]\r\n [mono-validation-state=\"valid|warning\"] ≡ EXTENSION (the invalid pattern in --success / --warning)\r\n [mono-size=\"xs|sm|lg|xl|xxl\"] ≡ EXTENSION (the --mono-control-height-* ladder)\r\n [mono-variant=\"filled\"] ≡ EXTENSION (luma's .combobox-chips)\r\n [mono-variant=\"underlined\"] ≡ EXTENSION (sera's .combobox-chips: bottom edge only, no ring)\r\n\r\n Inner parts: [mono-label] (+ [mono-required-mark]), [mono-field] (+ [mono-inline],\r\n [mono-typing]), [mono-chip-strip], [mono-chip] (+ [mono-removable], [mono-more],\r\n [mono-chip-color=\"…\"]) > [mono-chip-main] > [mono-chip-content] > [mono-chip-dot] /\r\n [mono-chip-label] / [mono-chip-close] > [mono-icon], [mono-native], [mono-actions] >\r\n [mono-scroll=\"prev|next\"] (+ [mono-idle]) / [mono-clear] > [mono-icon] / [mono-arrow],\r\n [mono-dropdown], [mono-select-all] (+ [mono-loading]), [mono-item] (+ [mono-active],\r\n [mono-selected], [mono-disabled], [mono-check], [mono-level=\"n\"]) > [mono-check-box] /\r\n [mono-item-text] > [mono-item-title] / [mono-item-sub], [mono-group] (+ [mono-level],\r\n [mono-sticky], [mono-toggle], [mono-selected]) > [mono-group-label], [mono-empty-row],\r\n [mono-load-more] (+ [mono-loading]), [mono-list-slot], [mono-more-panel],\r\n [mono-message-wrap] > [mono-message=\"helper|valid|invalid|warning\"]. The shadow build\r\n marks an unassigned slot wrapper [mono-empty].\r\n\r\n THE PANELS ARE PORTALED (light build): [mono-dropdown] and [mono-more-panel] move\r\n into a `<div data-mono-popup-portal>` under <body> while open, and the portal\r\n mirrors the wrapper's class AND mono-* attributes, so every rule here is scoped\r\n under `[mono-tag-input]` and never relies on the panel being inside the field.\r\n\r\n FLAVORS set the same knobs as mono-input, renamed `--mono-tag-input-*`, plus the\r\n select's panel / option / group set (`--mono-tag-input-dropdown-*`,\r\n `--mono-tag-input-option-*`, `--mono-tag-input-group-*`) and the chip set\r\n (`--mono-tag-input-chip-{radius,bg,color,font-size,font-weight}`). Every fallback\r\n here is vega's value (`node scripts/basecoat-styles.mjs --varying \"^\\.combobox\"`).\r\n ========================================================================= */\r\n\r\nmono-tag-input {\r\n display: block;\r\n}\r\n\r\n[mono-tag-input] {\r\n /* ── palette: each slot is a public knob over a Basecoat token ─────────── */\r\n --_mono-tag-input-text: var(--mono-tag-input-color, var(--mono-tag-input-text, var(--foreground)));\r\n --_mono-tag-input-placeholder: var(--mono-tag-input-placeholder, var(--muted-foreground));\r\n --_mono-tag-input-muted: var(--mono-tag-input-muted, var(--muted-foreground));\r\n --_mono-tag-input-primary: var(--mono-tag-input-primary, var(--ring));\r\n --_mono-tag-input-secondary: var(--mono-tag-input-secondary, var(--muted-foreground));\r\n --_mono-tag-input-success: var(--mono-tag-input-success, var(--success));\r\n --_mono-tag-input-danger: var(--mono-tag-input-danger, var(--destructive));\r\n --_mono-tag-input-warning: var(--mono-tag-input-warning, var(--warning));\r\n --_mono-tag-input-info: var(--mono-tag-input-info, var(--info));\r\n --_mono-tag-input-teal: var(--mono-tag-input-teal, var(--teal));\r\n --_mono-tag-input-purple: var(--mono-tag-input-purple, var(--purple));\r\n --_mono-tag-input-neutral: var(--mono-tag-input-neutral, var(--neutral));\r\n --_mono-tag-input-dark: var(--mono-tag-input-dark, var(--dark));\r\n --_mono-tag-input-valid: var(--mono-tag-input-valid, var(--success));\r\n --_mono-tag-input-invalid: var(--mono-tag-input-invalid, var(--destructive));\r\n\r\n /* ── the painted result — three tiers, base = .combobox-chips (vega) ──── */\r\n --_mono-tag-input-ring-color: var(--mono-tag-input-ring-color, var(--mono-tag-input-focus-color, var(--_mono-tag-input-ring-color-preset, var(--_mono-tag-input-primary))));\r\n --_mono-tag-input-ring-width: var(--mono-tag-input-ring-width, var(--_mono-tag-input-ring-width-preset, var(--mono-ring-width)));\r\n --_mono-tag-input-ring-alpha: var(--mono-tag-input-ring-alpha, var(--mono-ring-alpha));\r\n --_mono-tag-input-border-color: var(--mono-tag-input-rest-border, var(--mono-tag-input-border-color, var(--mono-tag-input-border, var(--_mono-tag-input-border-color-preset, var(--input)))));\r\n --_mono-tag-input-bg: var(--mono-tag-input-bg, var(--mono-tag-input-surface, var(--_mono-tag-input-bg-preset, var(--mono-mode-surface))));\r\n --_mono-tag-input-shadow: var(--mono-tag-input-shadow, var(--_mono-tag-input-shadow-preset, 0 0 #0000));\r\n --_mono-tag-input-icon: var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 4));\r\n\r\n /* ── md metrics live on the unqualified root ON PURPOSE: hand-written\r\n `<div mono-tag-input>` that names no size renders exactly like size=\"md\".\r\n basecoat@1.0.2 styles/vega.css .combobox-chips — min-h-9 gap-1.5 rounded-md\r\n px-1.5 py-1.5 text-sm; .combobox-chip h-5.5 ── */\r\n --_mono-tag-input-height: var(--mono-tag-input-height-md, var(--mono-control-height-md));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-md, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-md, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, calc(var(--mono-spacing) * 1.5))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-md, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 1.5)));\r\n --_mono-tag-input-gap: var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 1.5));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-md, var(--mono-text-sm));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-md, var(--mono-text-sm--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-md, min(calc(var(--mono-spacing) * 5.5), var(--_mono-tag-input-chip-fit)));\r\n /* The room one row of chips has: the field's height minus its block padding and borders. Each\r\n size's DEFAULT chip height is capped by it, so the rule \"chip h + 2·py + 2px ≤ token\" holds\r\n under ANY control ladder — a dense flavor (mira: xs 20px) shrinks the chip instead of growing\r\n an empty field past the token. An explicit `--mono-tag-input-chip-height-*` is not capped. */\r\n --_mono-tag-input-chip-fit: calc(var(--_mono-tag-input-height) - 2 * var(--_mono-tag-input-padding-y) - 2 * var(--mono-border-width));\r\n --_mono-tag-input-chip-font-size: var(--mono-tag-input-chip-font-size, var(--mono-text-xs));\r\n --_mono-tag-input-chip-line-height: var(--mono-tag-input-chip-line-height, var(--mono-text-xs--lh));\r\n --_mono-tag-input-action: calc(var(--mono-spacing) * 6);\r\n --_mono-tag-input-clear-glyph: calc(var(--mono-spacing) * 3.5);\r\n\r\n /* basecoat@1.0.2 styles/vega.css .field — flex w-full flex-col gap-3; mono: BLOCK\r\n flow with the gap as margins, so a hand-written panel that no controller\r\n positions lands at its static position — right under the field, above the\r\n message — instead of a flex container's content-box top (see select.css) */\r\n --_mono-tag-input-gap-y: var(--mono-tag-input-gap, calc(var(--mono-spacing) * 3));\r\n position: relative;\r\n display: block;\r\n width: 100%;\r\n font-family: inherit;\r\n color: var(--_mono-tag-input-text);\r\n}\r\n\r\n[mono-tag-input],\r\n[mono-tag-input] *,\r\n[mono-tag-input] *::before,\r\n[mono-tag-input] *::after {\r\n box-sizing: border-box;\r\n}\r\n\r\n[mono-tag-input] :is([mono-label], [mono-message])[mono-empty] {\r\n display: none;\r\n}\r\n\r\n/* =========================================\r\n Sizes — an EMPTY field's painted height IS the token (tests/perf/field-heights);\r\n a second row of chips grows it. Each step keeps one row of chips + its block\r\n padding under the token: chip h + 2·py + 2px ≤ token.\r\n ========================================= */\r\n\r\n[mono-tag-input][mono-size=\"xs\"] {\r\n --_mono-tag-input-height: var(--mono-tag-input-height-xs, var(--mono-control-height-xs));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-xs, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-xs, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, var(--mono-spacing))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-xs, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 0.5)));\r\n --_mono-tag-input-gap: var(--mono-tag-input-chip-gap, var(--mono-spacing));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-xs, var(--mono-text-xs));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-xs, var(--mono-text-xs--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-xs, min(calc(var(--mono-spacing) * 4.5), var(--_mono-tag-input-chip-fit)));\r\n --_mono-tag-input-icon: var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 3.5));\r\n --_mono-tag-input-action: calc(var(--mono-spacing) * 4);\r\n --_mono-tag-input-clear-glyph: calc(var(--mono-spacing) * 3);\r\n}\r\n\r\n[mono-tag-input][mono-size=\"sm\"] {\r\n --_mono-tag-input-height: var(--mono-tag-input-height-sm, var(--mono-control-height-sm));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-sm, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-sm, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, var(--mono-spacing))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-sm, var(--mono-tag-input-padding-y, var(--mono-spacing)));\r\n --_mono-tag-input-gap: var(--mono-tag-input-chip-gap, var(--mono-spacing));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-sm, var(--mono-tag-input-font-md, var(--mono-text-sm)));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-sm, var(--mono-text-sm--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-sm, min(calc(var(--mono-spacing) * 5), var(--_mono-tag-input-chip-fit)));\r\n --_mono-tag-input-action: calc(var(--mono-spacing) * 5);\r\n}\r\n\r\n[mono-tag-input][mono-size=\"lg\"] {\r\n --_mono-tag-input-height: var(--mono-tag-input-height-lg, var(--mono-control-height-lg));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-lg, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-lg, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, calc(var(--mono-spacing) * 1.5))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-lg, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 1.5)));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-lg, var(--mono-tag-input-font-md, var(--mono-text-sm)));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-lg, var(--mono-text-sm--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-lg, min(calc(var(--mono-spacing) * 6), var(--_mono-tag-input-chip-fit)));\r\n}\r\n\r\n[mono-tag-input][mono-size=\"xl\"] {\r\n --_mono-tag-input-height: var(--mono-tag-input-height-xl, var(--mono-control-height-xl));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-xl, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-xl, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, calc(var(--mono-spacing) * 2))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-xl, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 2)));\r\n --_mono-tag-input-gap: var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 2));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-xl, var(--mono-text-base));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-xl, var(--mono-text-base--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-xl, min(calc(var(--mono-spacing) * 6.5), var(--_mono-tag-input-chip-fit)));\r\n --_mono-tag-input-chip-font-size: var(--mono-tag-input-chip-font-size, var(--mono-text-sm));\r\n --_mono-tag-input-chip-line-height: var(--mono-tag-input-chip-line-height, var(--mono-text-sm--lh));\r\n --_mono-tag-input-icon: var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 5));\r\n --_mono-tag-input-action: calc(var(--mono-spacing) * 7);\r\n --_mono-tag-input-clear-glyph: calc(var(--mono-spacing) * 4);\r\n}\r\n\r\n[mono-tag-input][mono-size=\"xxl\"] {\r\n --_mono-tag-input-height: var(--mono-tag-input-height-xxl, var(--mono-control-height-xxl));\r\n --_mono-tag-input-radius: var(--mono-tag-input-radius-xxl, var(--_mono-tag-input-radius-preset, var(--mono-tag-input-radius, var(--mono-radius-md))));\r\n --_mono-tag-input-padding-x: var(--mono-tag-input-padding-x-xxl, var(--mono-tag-input-padding-x, var(--_mono-tag-input-padding-x-preset, calc(var(--mono-spacing) * 2.5))));\r\n --_mono-tag-input-padding-y: var(--mono-tag-input-padding-y-xxl, var(--mono-tag-input-padding-y, calc(var(--mono-spacing) * 2)));\r\n --_mono-tag-input-gap: var(--mono-tag-input-chip-gap, calc(var(--mono-spacing) * 2));\r\n --_mono-tag-input-font-size: var(--mono-tag-input-font-xxl, var(--mono-text-lg));\r\n --_mono-tag-input-line-height: var(--mono-tag-input-line-height, var(--mono-tag-input-line-height-xxl, var(--mono-text-lg--lh)));\r\n --_mono-tag-input-chip-height: var(--mono-tag-input-chip-height-xxl, min(calc(var(--mono-spacing) * 7), var(--_mono-tag-input-chip-fit)));\r\n --_mono-tag-input-chip-font-size: var(--mono-tag-input-chip-font-size, var(--mono-text-sm));\r\n --_mono-tag-input-chip-line-height: var(--mono-tag-input-chip-line-height, var(--mono-text-sm--lh));\r\n --_mono-tag-input-icon: var(--mono-tag-input-icon-size, calc(var(--mono-spacing) * 5));\r\n --_mono-tag-input-action: calc(var(--mono-spacing) * 8);\r\n --_mono-tag-input-clear-glyph: calc(var(--mono-spacing) * 4);\r\n}\r\n\r\n/* =========================================\r\n Variants — each writes only `*-preset` slots\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — rounded-md border border-input\r\n bg-transparent shadow-xs (dark:bg-input/30 via --mono-mode-surface) */\r\n[mono-tag-input]:is(:not([mono-variant]), [mono-variant=\"outlined\"]) {\r\n --_mono-tag-input-bg-preset: var(--mono-tag-input-outline-bg);\r\n --_mono-tag-input-border-color-preset: var(--mono-tag-input-outline-border-color);\r\n --_mono-tag-input-side-border-color-preset: var(--mono-tag-input-outline-side-border-color);\r\n --_mono-tag-input-shadow-preset: var(--mono-tag-input-outline-shadow, var(--mono-shadow-xs));\r\n --_mono-tag-input-ring-width-preset: var(--mono-tag-input-outline-ring-width);\r\n --_mono-tag-input-radius-preset: var(--mono-tag-input-outline-radius);\r\n --_mono-tag-input-padding-x-preset: var(--mono-tag-input-outline-padding-x);\r\n}\r\n\r\n/* EXTENSION — filled ≡ basecoat@1.0.2 styles/luma.css .combobox-chips */\r\n[mono-tag-input][mono-variant=\"filled\"] {\r\n --_mono-tag-input-bg-preset: var(--mono-tag-input-filled-bg, color-mix(in oklab, var(--input) 50%, transparent));\r\n --_mono-tag-input-border-color-preset: transparent;\r\n --_mono-tag-input-shadow-preset: 0 0 #0000;\r\n}\r\n\r\n/* EXTENSION — underlined ≡ basecoat@1.0.2 styles/sera.css .combobox-chips */\r\n[mono-tag-input][mono-variant=\"underlined\"] {\r\n --_mono-tag-input-bg-preset: transparent;\r\n --_mono-tag-input-side-border-color-preset: transparent;\r\n --_mono-tag-input-shadow-preset: 0 0 #0000;\r\n --_mono-tag-input-ring-width-preset: 0px;\r\n --_mono-tag-input-radius-preset: 0;\r\n --_mono-tag-input-padding-x-preset: 0;\r\n}\r\n\r\n/* =========================================\r\n Colours — the `color` prop is the FOCUS colour (ring + focused border)\r\n ========================================= */\r\n\r\n[mono-tag-input]:is(:not([mono-color]), [mono-color=\"primary\"]) {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-primary);\r\n}\r\n[mono-tag-input][mono-color=\"secondary\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-secondary);\r\n}\r\n[mono-tag-input][mono-color=\"success\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-success);\r\n}\r\n[mono-tag-input][mono-color=\"danger\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-danger);\r\n}\r\n[mono-tag-input][mono-color=\"warning\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-warning);\r\n}\r\n[mono-tag-input][mono-color=\"info\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-info);\r\n}\r\n[mono-tag-input][mono-color=\"teal\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-teal);\r\n}\r\n[mono-tag-input][mono-color=\"purple\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-purple);\r\n}\r\n[mono-tag-input][mono-color=\"neutral\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-neutral);\r\n}\r\n[mono-tag-input][mono-color=\"dark\"] {\r\n --_mono-tag-input-ring-color-preset: var(--_mono-tag-input-dark);\r\n}\r\n\r\n/* =========================================\r\n Label\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field > label, .label — flex items-center\r\n gap-2 text-sm leading-none font-medium select-none w-fit */\r\n[mono-tag-input] > [mono-label] {\r\n display: flex;\r\n align-items: center;\r\n width: fit-content;\r\n margin: 0 0 var(--_mono-tag-input-gap-y);\r\n gap: var(--mono-tag-input-label-gap, calc(var(--mono-spacing) * 2));\r\n font-size: var(--mono-tag-input-label-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-label-line-height, 1);\r\n font-weight: var(--mono-tag-input-label-font-weight, var(--mono-label-font-weight, var(--mono-font-weight-medium)));\r\n text-transform: var(--mono-tag-input-label-text-transform, none);\r\n letter-spacing: var(--mono-tag-input-label-letter-spacing, normal);\r\n color: var(--_mono-tag-input-text);\r\n user-select: none;\r\n}\r\n\r\n[mono-tag-input][mono-disabled] > [mono-label] {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field — data-invalid:text-destructive */\r\n[mono-tag-input][mono-validation-state=\"invalid\"] > [mono-label] {\r\n color: var(--_mono-tag-input-invalid);\r\n}\r\n\r\n[mono-tag-input] [mono-required-mark] {\r\n color: var(--_mono-tag-input-danger);\r\n}\r\n\r\n/* =========================================\r\n The field — the chip box\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chips — flex w-full min-w-0\r\n flex-wrap items-center */\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — min-h-9 gap-1.5 rounded-md\r\n border border-input bg-transparent bg-clip-padding px-1.5 py-1.5 text-sm\r\n shadow-xs transition-[color,box-shadow] focus-within:border-ring\r\n focus-within:ring-3 focus-within:ring-ring/50 has-[[aria-invalid=true]]:…;\r\n mono: `--tw-ring-*` flattened to the ring + shadow slots, the min-height is\r\n the control token, the side edges read their own slot */\r\n[mono-tag-input] > [mono-field] {\r\n --_mono-tag-input-bc: var(--_mono-tag-input-border-color);\r\n --_mono-tag-input-side-bc: var(--mono-tag-input-side-border-color, var(--_mono-tag-input-side-border-color-preset, var(--_mono-tag-input-bc)));\r\n --_mono-tag-input-ring: 0 0 #0000;\r\n\r\n position: relative;\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: var(--_mono-tag-input-gap);\r\n width: 100%;\r\n min-width: 0;\r\n min-height: var(--_mono-tag-input-height);\r\n padding-block: var(--_mono-tag-input-padding-y);\r\n padding-inline: var(--_mono-tag-input-padding-x);\r\n outline-style: none;\r\n border: var(--mono-border-width) solid var(--_mono-tag-input-bc);\r\n border-top-color: var(--_mono-tag-input-side-bc);\r\n border-inline-color: var(--_mono-tag-input-side-bc);\r\n border-radius: var(--_mono-tag-input-radius);\r\n background: var(--_mono-tag-input-bg);\r\n background-clip: padding-box;\r\n color: var(--_mono-tag-input-text);\r\n box-shadow: var(--_mono-tag-input-ring), var(--_mono-tag-input-shadow);\r\n font-size: var(--_mono-tag-input-font-size);\r\n line-height: var(--_mono-tag-input-line-height);\r\n cursor: text;\r\n transition-property: color, box-shadow, border-color, background-color;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n\r\n /* focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 */\r\n &:focus-within {\r\n --_mono-tag-input-bc: var(--_mono-tag-input-ring-color);\r\n --_mono-tag-input-ring: 0 0 0 var(--_mono-tag-input-ring-width) color-mix(in oklab, var(--_mono-tag-input-ring-color) var(--_mono-tag-input-ring-alpha), transparent);\r\n }\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chips — has-[[aria-invalid=true]]:border-destructive\r\n has-[[aria-invalid=true]]:ring-3 has-[[aria-invalid=true]]:ring-destructive/20 */\r\n[mono-tag-input][mono-validation-state=\"invalid\"] > [mono-field],\r\n[mono-tag-input] > [mono-field]:has(> [mono-native][aria-invalid=\"true\"]) {\r\n --_mono-tag-input-bc: var(--mono-mode-invalid-border);\r\n --_mono-tag-input-ring: 0 0 0 var(--_mono-tag-input-ring-width) var(--mono-mode-invalid-ring);\r\n}\r\n\r\n/* EXTENSION — valid / warning are the invalid pattern in the role's colour */\r\n[mono-tag-input][mono-validation-state=\"valid\"] > [mono-field] {\r\n --_mono-tag-input-bc: color-mix(in oklab, var(--_mono-tag-input-valid) var(--mono-mode-state-border-alpha), transparent);\r\n --_mono-tag-input-ring: 0 0 0 var(--_mono-tag-input-ring-width) color-mix(in oklab, var(--_mono-tag-input-valid) var(--mono-mode-state-ring-alpha), transparent);\r\n}\r\n[mono-tag-input][mono-validation-state=\"warning\"] > [mono-field] {\r\n --_mono-tag-input-bc: color-mix(in oklab, var(--_mono-tag-input-warning) var(--mono-mode-state-border-alpha), transparent);\r\n --_mono-tag-input-ring: 0 0 0 var(--_mono-tag-input-ring-width) color-mix(in oklab, var(--_mono-tag-input-warning) var(--mono-mode-state-ring-alpha), transparent);\r\n}\r\n\r\n/* EXTENSION — the bound dataSource failed: the invalid outline ONLY. Label,\r\n message and validation state stay as they are; it is not a validation error. */\r\n[mono-tag-input][mono-ds-error] > [mono-field] {\r\n --_mono-tag-input-bc: var(--mono-tag-input-ds-error-border, var(--mono-mode-invalid-border));\r\n --_mono-tag-input-ring: 0 0 0 var(--_mono-tag-input-ring-width) var(--mono-tag-input-ds-error-ring, var(--mono-mode-invalid-ring));\r\n}\r\n\r\n[mono-tag-input][mono-ds-error] [mono-native]::placeholder {\r\n color: var(--mono-tag-input-ds-error-text, var(--_mono-tag-input-invalid));\r\n}\r\n\r\n/* EXTENSION — the first load (or a retry) is in flight: read-only */\r\n[mono-tag-input][mono-ds-loading] > [mono-field],\r\n[mono-tag-input][mono-ds-loading] [mono-native] {\r\n cursor: progress;\r\n}\r\n\r\n/* EXTENSION — readonly: a muted surface */\r\n[mono-tag-input][mono-readonly] > [mono-field] {\r\n background: var(--mono-tag-input-readonly-bg, var(--muted));\r\n cursor: default;\r\n}\r\n\r\n/* .combobox-chips > input:disabled — opacity-50 (on the box, so the chips fade\r\n with it). The strip's ‹ › pager opts back in so the chips can still be read. */\r\n[mono-tag-input][mono-disabled] > [mono-field] {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n background: var(--mono-tag-input-disabled-bg, var(--_mono-tag-input-bg));\r\n}\r\n\r\n[mono-tag-input][mono-disabled] [mono-scroll]:not([mono-idle]) {\r\n pointer-events: auto;\r\n cursor: pointer;\r\n}\r\n\r\n/* ── the actions row stays on the FIRST row ──────────────────────────────\r\n The field wraps, and the row is its last child, so once the chips wrapped it\r\n rode down to the bottom-right. Pinned out of that flow instead; `top` centres\r\n it on the single-row height. Not in inline mode: an inline field never wraps,\r\n so the row sits in normal flow and the strip flexes against it. */\r\n[mono-tag-input] > [mono-field]:not([mono-inline]) {\r\n padding-inline-end: calc(var(--_mono-tag-input-padding-x) + var(--_mono-tag-input-action) + var(--mono-spacing));\r\n}\r\n\r\n[mono-tag-input] > [mono-field]:not([mono-inline]) > [mono-actions] {\r\n position: absolute;\r\n inset-inline-end: var(--_mono-tag-input-padding-x);\r\n top: calc((var(--_mono-tag-input-height) - var(--_mono-tag-input-action)) / 2);\r\n}\r\n\r\n/* =========================================\r\n The text box\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chips > input[role='combobox']\r\n — min-w-16 flex-1 bg-transparent outline-none placeholder:text-muted-foreground */\r\n[mono-tag-input] [mono-native] {\r\n flex: 1 1 calc(var(--mono-spacing) * 16);\r\n min-width: calc(var(--mono-spacing) * 16);\r\n align-self: stretch;\r\n appearance: none;\r\n margin: 0;\r\n padding: 0;\r\n border: 0;\r\n border-radius: 0;\r\n outline: none;\r\n background: transparent;\r\n box-shadow: none;\r\n color: var(--_mono-tag-input-text);\r\n font-family: inherit;\r\n font-size: var(--_mono-tag-input-font-size);\r\n line-height: var(--_mono-tag-input-line-height);\r\n /* The chip row is the box's height; the text box never exceeds it. `height`, not only\r\n `min-height`: an input's own line box is its floor, so with a chip shorter than the line (a\r\n dense flavor's capped chip — mira xs: 14px chip, 16px line) the input set the row and an\r\n empty field came out 2px over the control token. The 12px glyphs still fit. */\r\n min-height: var(--_mono-tag-input-chip-height);\r\n height: var(--_mono-tag-input-chip-height);\r\n\r\n &:focus,\r\n &:focus-visible {\r\n outline: none !important;\r\n }\r\n\r\n &::placeholder {\r\n color: var(--_mono-tag-input-placeholder);\r\n }\r\n\r\n &:disabled,\r\n &:read-only {\r\n cursor: inherit;\r\n }\r\n}\r\n\r\n/* =========================================\r\n Chips\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chip — inline-flex w-fit\r\n shrink-0 items-center whitespace-nowrap */\r\n[mono-tag-input] [mono-chip] {\r\n display: inline-flex;\r\n width: fit-content;\r\n max-width: 100%;\r\n flex-shrink: 0;\r\n align-items: center;\r\n white-space: nowrap;\r\n vertical-align: middle;\r\n line-height: 1;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chip — h-5.5 gap-1 rounded-sm bg-muted\r\n px-1.5 text-xs font-medium text-foreground, has-[>.combobox-chip-remove]:pe-0 */\r\n[mono-tag-input] [mono-chip] > [mono-chip-main] {\r\n display: inline-flex;\r\n align-items: center;\r\n height: var(--_mono-tag-input-chip-height);\r\n max-width: 100%;\r\n gap: var(--mono-tag-input-chip-content-gap, var(--mono-spacing));\r\n margin: 0;\r\n padding-inline: var(--mono-tag-input-chip-padding-x, calc(var(--mono-spacing) * 1.5));\r\n border: 0;\r\n border-radius: var(--mono-tag-input-chip-radius, var(--mono-radius-sm));\r\n background: var(--mono-tag-input-chip-bg, var(--muted));\r\n color: var(--mono-tag-input-chip-color, var(--_mono-tag-input-text));\r\n font-family: inherit;\r\n font-size: var(--_mono-tag-input-chip-font-size);\r\n line-height: var(--_mono-tag-input-chip-line-height);\r\n font-weight: var(--mono-tag-input-chip-font-weight, var(--mono-font-weight-medium));\r\n text-decoration: none;\r\n cursor: default;\r\n}\r\n\r\n[mono-tag-input] [mono-chip][mono-removable] > [mono-chip-main] {\r\n padding-inline-end: 0;\r\n}\r\n\r\n[mono-tag-input] [mono-chip] [mono-chip-content] {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: inherit;\r\n min-width: 0;\r\n max-width: 100%;\r\n height: 100%;\r\n}\r\n\r\n[mono-tag-input] [mono-chip] [mono-chip-label] {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* EXTENSION — `chip.dot`: a coloured dot before the label (the badge's dot idiom) */\r\n[mono-tag-input] [mono-chip] [mono-chip-dot] {\r\n flex: 0 0 auto;\r\n width: calc(var(--mono-spacing) * 1.5);\r\n height: calc(var(--mono-spacing) * 1.5);\r\n border-radius: var(--mono-radius-full);\r\n background: currentColor;\r\n}\r\n\r\n/* EXTENSION — `chip.color` pins a hue: the tonal pattern (bg-x/10 text-x, dark 20) */\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"primary\"] > [mono-chip-main] { background: color-mix(in oklab, var(--primary) var(--mono-mode-tint), transparent); color: var(--primary); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"secondary\"] > [mono-chip-main] { background: var(--secondary); color: var(--secondary-foreground); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"success\"] > [mono-chip-main] { background: color-mix(in oklab, var(--success) var(--mono-mode-tint), transparent); color: var(--success); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"danger\"] > [mono-chip-main] { background: color-mix(in oklab, var(--destructive) var(--mono-mode-tint), transparent); color: var(--destructive); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"warning\"] > [mono-chip-main] { background: color-mix(in oklab, var(--warning) var(--mono-mode-tint), transparent); color: var(--warning); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"info\"] > [mono-chip-main] { background: color-mix(in oklab, var(--info) var(--mono-mode-tint), transparent); color: var(--info); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"teal\"] > [mono-chip-main] { background: color-mix(in oklab, var(--teal) var(--mono-mode-tint), transparent); color: var(--teal); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"purple\"] > [mono-chip-main] { background: color-mix(in oklab, var(--purple) var(--mono-mode-tint), transparent); color: var(--purple); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"neutral\"] > [mono-chip-main] { background: color-mix(in oklab, var(--neutral) var(--mono-mode-tint), transparent); color: var(--neutral); }\r\n[mono-tag-input] [mono-chip][mono-chip-color=\"dark\"] > [mono-chip-main] { background: var(--dark); color: var(--dark-foreground); }\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox-chip-remove — inline-flex\r\n shrink-0 items-center justify-center */\r\n/* basecoat@1.0.2 styles/vega.css .combobox-chip-remove — -ms-1 opacity-50\r\n hover:opacity-100, svg size-3.5 */\r\n[mono-tag-input] [mono-chip] [mono-chip-close] {\r\n display: inline-flex;\r\n flex-shrink: 0;\r\n align-items: center;\r\n justify-content: center;\r\n /* explicit: the element still carries chip.css's `.chip-close` class as a hook,\r\n which pins a 1rem box — the raw markup has no such class */\r\n width: auto;\r\n height: 100%;\r\n min-width: 0;\r\n margin: 0;\r\n transform: none;\r\n margin-inline-start: calc(var(--mono-spacing) * -1);\r\n padding: 0 var(--mono-spacing);\r\n border: 0;\r\n border-radius: inherit;\r\n background: transparent;\r\n color: inherit;\r\n font: inherit;\r\n line-height: 1;\r\n opacity: 0.5;\r\n cursor: pointer;\r\n outline-style: none;\r\n transition-property: opacity;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n\r\n &:focus-visible {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-tag-input] [mono-chip] [mono-chip-close]:hover {\r\n opacity: 1;\r\n }\r\n}\r\n\r\n[mono-tag-input] [mono-chip] [mono-chip-close] > :is(svg, .mono-icon, [mono-icon]) {\r\n display: block;\r\n width: calc(var(--mono-spacing) * 3.5);\r\n height: calc(var(--mono-spacing) * 3.5);\r\n pointer-events: none;\r\n}\r\n\r\n/* EXTENSION — the \"+N more\" counter chip is a control */\r\n[mono-tag-input] [mono-chip][mono-more] > [mono-chip-main] {\r\n cursor: pointer;\r\n outline-style: none;\r\n}\r\n\r\n[mono-tag-input] [mono-chip][mono-more] > [mono-chip-main]:focus-visible {\r\n box-shadow: 0 0 0 var(--_mono-tag-input-ring-width) color-mix(in oklab, var(--_mono-tag-input-ring-color) var(--_mono-tag-input-ring-alpha), transparent);\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-tag-input] [mono-chip][mono-more] > [mono-chip-main]:hover {\r\n background: var(--mono-mode-surface-hover);\r\n }\r\n}\r\n\r\n/* ── the inline chip strip (`chip.behaviour: 'inline'`) ──────────────────\r\n One line that never grows: the field stops wrapping, the chips live in their\r\n own strip, and the strip absorbs the overflow instead of the field.\r\n\r\n `overflow-x: hidden` — NOT `auto` — is the whole scroll contract. Hidden still\r\n honours a programmatic `scrollLeft`, so `ChipStripController` can page the\r\n strip while the browser paints no scrollbar. */\r\n[mono-tag-input] > [mono-field][mono-inline] {\r\n flex-wrap: nowrap;\r\n min-width: 0;\r\n}\r\n\r\n[mono-tag-input] [mono-chip-strip] {\r\n display: flex;\r\n flex-wrap: nowrap;\r\n align-items: center;\r\n gap: var(--_mono-tag-input-gap);\r\n flex: 0 1 auto;\r\n min-width: 0;\r\n overflow-x: hidden;\r\n overflow-y: hidden;\r\n /* NO `scroll-behavior: smooth` — see ChipStripController (one scroll event per\r\n frame would reposition every open popup). */\r\n}\r\n\r\n[mono-tag-input] [mono-chip-strip] > * {\r\n flex-shrink: 0;\r\n}\r\n\r\n/* The text box takes the SLACK: `flex-basis: 0` contributes nothing to the\r\n overflow calculation, so when the chips overflow it collapses and the strip\r\n runs up to the pager; focus earns a caret's room, typing earns a real box. */\r\n[mono-tag-input] > [mono-field][mono-inline] > [mono-native] {\r\n flex: 1 1 0;\r\n min-width: 0;\r\n}\r\n\r\n[mono-tag-input] > [mono-field][mono-inline] > [mono-native]:focus,\r\n[mono-tag-input] > [mono-field][mono-inline] > [mono-native]:focus-visible {\r\n min-width: calc(var(--mono-spacing) * 5);\r\n}\r\n\r\n[mono-tag-input] > [mono-field][mono-inline][mono-typing] > [mono-native] {\r\n min-width: calc(var(--mono-spacing) * 24);\r\n}\r\n\r\n/* =========================================\r\n Actions — ‹ › pager, clear, caret\r\n ========================================= */\r\n\r\n[mono-tag-input] [mono-actions] {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--mono-spacing);\r\n flex: 0 0 auto;\r\n line-height: 1;\r\n}\r\n\r\n/* basecoat@1.0.2 components/combobox.css .combobox [data-clear] — size-6 border-0\r\n bg-transparent p-0 text-current; the caret ≡ .combobox-trigger-icon (size-4\r\n text-muted-foreground), the pager the same box. Painted as .btn[data-variant='ghost']. */\r\n[mono-tag-input] [mono-clear],\r\n[mono-tag-input] [mono-arrow],\r\n[mono-tag-input] [mono-scroll],\r\n[mono-tag-input] [mono-ds-retry],\r\n[mono-tag-input] [mono-ds-spinner] {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: 0 0 auto;\r\n width: var(--_mono-tag-input-action);\r\n height: var(--_mono-tag-input-action);\r\n margin: 0;\r\n padding: 0;\r\n border: 0;\r\n border-radius: var(--mono-tag-input-clear-radius, calc(var(--radius) - 5px));\r\n background: transparent;\r\n color: var(--_mono-tag-input-muted);\r\n font: inherit;\r\n line-height: 1;\r\n cursor: pointer;\r\n outline-style: none;\r\n transition-property: color, background-color, transform;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration);\r\n}\r\n\r\n[mono-tag-input] :is([mono-clear], [mono-arrow], [mono-scroll], [mono-ds-retry], [mono-ds-spinner]) > :is(svg, .mono-icon, [mono-icon]) {\r\n display: block;\r\n width: var(--_mono-tag-input-icon);\r\n height: var(--_mono-tag-input-icon);\r\n pointer-events: none;\r\n}\r\n\r\n[mono-tag-input] [mono-clear] > :is(svg, .mono-icon, [mono-icon]) {\r\n width: var(--_mono-tag-input-clear-glyph);\r\n height: var(--_mono-tag-input-clear-glyph);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .btn[data-variant='ghost'] — hover:bg-muted hover:text-foreground */\r\n@media (hover: hover) {\r\n [mono-tag-input] :is([mono-clear], [mono-arrow], [mono-scroll], [mono-ds-retry]):hover {\r\n background: var(--mono-mode-ghost-hover);\r\n color: var(--_mono-tag-input-text);\r\n }\r\n}\r\n\r\n/* EXTENSION — the caret turns while the panel is open */\r\n[mono-tag-input][mono-open] [mono-arrow] > :is(svg, .mono-icon, [mono-icon]) {\r\n transform: rotate(180deg);\r\n}\r\n\r\n/* EXTENSION — dataSource state glyphs: the busy arc spins, the ↻ wears the\r\n error colour so it reads as the way out of the red field */\r\n[mono-tag-input] [mono-ds-spinner] {\r\n cursor: progress;\r\n}\r\n\r\n[mono-tag-input] [mono-ds-spinner] > svg {\r\n animation: mono-tag-input-spin 0.7s linear infinite;\r\n}\r\n\r\n[mono-tag-input] [mono-ds-retry] {\r\n color: var(--mono-tag-input-ds-error-text, var(--_mono-tag-input-invalid));\r\n}\r\n\r\n@keyframes mono-tag-input-spin {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n/* At an end of the strip the pager keeps its box but disappears — hiding it with\r\n `display: none` would shrink the row and shove the strip sideways mid-click. */\r\n[mono-tag-input] [mono-scroll][mono-idle] {\r\n visibility: hidden;\r\n pointer-events: none;\r\n}\r\n\r\n/* =========================================\r\n The panel\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/popover.css [data-popover] — absolute z-50 overflow;\r\n mono: `display: none` while closed, `--mono-popup-z` from the shared stack,\r\n `--mono-popup-avail-h` from the portal controller */\r\n/* basecoat@1.0.2 styles/vega.css .combobox [data-popover] — bg-popover\r\n text-popover-foreground ring-foreground/10 max-h-72 rounded-md p-0 shadow-md ring-1 */\r\n/* basecoat@1.0.2 styles/vega.css .combobox [role='listbox'] — max-h-[min(18rem,\r\n var(--available-height,18rem))] scroll-py-1 overflow-y-auto p-1 (our panel IS\r\n the listbox: one scrolling box) */\r\n[mono-tag-input] > [mono-dropdown] {\r\n position: absolute;\r\n /* `top: auto` = the static position (under the field, before the message); the\r\n 6px offset is a transform the controller's inline `transform: none` cancels */\r\n top: auto;\r\n transform: translateY(calc(var(--mono-spacing) * 1.5));\r\n left: 0;\r\n right: 0;\r\n z-index: var(--mono-popup-z, 1000);\r\n display: none;\r\n min-width: var(--mono-tag-input-dropdown-min-width, 9rem);\r\n max-height: min(var(--_mono-tag-input-panel-max-h, 18rem), var(--mono-popup-avail-h, 100vh));\r\n padding: var(--mono-tag-input-dropdown-padding, var(--mono-spacing));\r\n overflow: auto;\r\n overscroll-behavior: contain;\r\n scroll-padding-block: var(--mono-tag-input-dropdown-padding, var(--mono-spacing));\r\n isolation: isolate;\r\n border-radius: var(--mono-tag-input-dropdown-radius, var(--mono-radius-md));\r\n background: var(--mono-tag-input-dropdown-bg, var(--popover));\r\n color: var(--mono-tag-input-dropdown-color, var(--popover-foreground));\r\n box-shadow: var(--mono-tag-input-dropdown-ring, 0 0 0 1px color-mix(in oklab, var(--foreground) 10%, transparent)), var(--mono-tag-input-dropdown-shadow, var(--mono-shadow-md));\r\n font-size: var(--mono-tag-input-option-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-option-line-height, var(--mono-text-sm--lh));\r\n outline-style: none;\r\n}\r\n\r\n[mono-tag-input][mono-open] > [mono-dropdown] {\r\n display: block;\r\n}\r\n\r\n/* =========================================\r\n Options\r\n -----------------------------------------\r\n Every rule that paints a native line lists its stamped twin (`slot=\"list\"`:\r\n `[data-mono-type='row']`, `[data-mono-active]`, `[data-mono-selected]`,\r\n `[data-mono-chrome]`) so the two can never drift. `:where()` wraps only the\r\n CONTAINER, keeping the twin at attribute weight.\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 components/select.css .select:not(select) [role='option'] — relative\r\n flex w-full cursor-default items-center outline-none select-none; disabled\r\n pointer-events-none opacity-50 */\r\n/* basecoat@1.0.2 styles/vega.css .combobox [role='option'] — gap-2 rounded-sm\r\n py-1.5 ps-2 pe-8 text-sm, svg size-4; EXTENSION: one indent step per level */\r\n[mono-tag-input] [mono-item],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row'] {\r\n --_ti-item-level: 0;\r\n position: relative;\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n gap: var(--mono-tag-input-option-gap, calc(var(--mono-spacing) * 2));\r\n margin: 0;\r\n padding-block: var(--mono-tag-input-option-padding-y, calc(var(--mono-spacing) * 1.5));\r\n padding-inline: var(--mono-tag-input-option-padding-x, calc(var(--mono-spacing) * 2)) var(--mono-tag-input-option-padding-end, calc(var(--mono-spacing) * 8));\r\n padding-inline-start: calc(var(--mono-tag-input-option-padding-x, calc(var(--mono-spacing) * 2)) + var(--_ti-item-level) * calc(var(--mono-spacing) * 3));\r\n min-height: var(--mono-tag-input-option-min-height, 0);\r\n border: 0;\r\n border-radius: var(--mono-tag-input-option-radius, var(--mono-radius-sm));\r\n /* longhands, so the selected row's check (a background-image) survives the\r\n active / hover background */\r\n background-color: transparent;\r\n background-image: none;\r\n color: var(--_mono-tag-input-text);\r\n font-family: inherit;\r\n font-size: var(--mono-tag-input-option-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-option-line-height, var(--mono-text-sm--lh));\r\n font-weight: var(--mono-tag-input-option-font-weight, var(--mono-font-weight-normal));\r\n text-align: start;\r\n outline-style: none;\r\n user-select: none;\r\n cursor: default;\r\n transition-property: color, background-color;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration-fast);\r\n}\r\n\r\n/* EXTENSION: a hair of air between rows. Upstream stacks its options flush, so an\r\n active row directly under the selected one read as ONE tall highlight; a 2px\r\n seam keeps the two rounded-sm washes apart. `--mono-tag-input-option-spacing`. */\r\n[mono-tag-input] [mono-item] + [mono-item],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row'] + [data-mono-type='row'] {\r\n margin-top: var(--mono-tag-input-option-spacing, 2px);\r\n}\r\n\r\n[mono-tag-input] [mono-item][mono-level='1'] { --_ti-item-level: 1; }\r\n[mono-tag-input] [mono-item][mono-level='2'] { --_ti-item-level: 2; }\r\n[mono-tag-input] [mono-item][mono-level='3'] { --_ti-item-level: 3; }\r\n[mono-tag-input] [mono-item][mono-level='4'] { --_ti-item-level: 4; }\r\n\r\n/* basecoat@1.0.2 styles/vega.css .select:not(select) [role='option'].active, .select:not(select) [role='option']:focus-visible\r\n — bg-muted text-foreground. The keyboard cursor and the pointer share one look. */\r\n[mono-tag-input] [mono-item][mono-active]:not([mono-disabled]):not(:disabled),\r\n[mono-tag-input] [mono-item]:focus-visible,\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-active] {\r\n background-color: var(--mono-tag-input-option-active-bg, var(--muted));\r\n color: var(--mono-tag-input-option-active-color, var(--_mono-tag-input-text));\r\n}\r\n\r\n/* basecoat@1.0.2 components/select.css .select:not(select):not([data-select-initialized]) [role='option']:not([aria-disabled='true']):not(:disabled):hover, .select:not(select) [role='option'].active */\r\n[mono-tag-input] [mono-item]:hover:not([mono-disabled]):not(:disabled),\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row']:hover {\r\n background-color: var(--mono-tag-input-option-active-bg, var(--muted));\r\n color: var(--mono-tag-input-option-active-color, var(--_mono-tag-input-text));\r\n}\r\n\r\n/* basecoat@1.0.2 components/select.css .select:not(select) [role='option'][aria-selected='true']\r\n — the --check-icon at the end. A row with its OWN checkbox says it there instead. */\r\n[mono-tag-input] [mono-item][mono-selected]:not([mono-check]),\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row'][data-mono-selected] {\r\n background-image: var(--mono-tag-input-check-icon, var(--check-icon));\r\n background-size: var(--mono-tag-input-check-size, 0.875rem);\r\n background-position: center right calc(var(--mono-spacing) * 2);\r\n background-repeat: no-repeat;\r\n}\r\n\r\n[mono-tag-input] [mono-item][mono-selected]:not([mono-check]):dir(rtl),\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row'][data-mono-selected]:dir(rtl) {\r\n background-position: center left calc(var(--mono-spacing) * 2);\r\n}\r\n\r\n[mono-tag-input] [mono-item][mono-disabled],\r\n[mono-tag-input] [mono-item]:disabled {\r\n opacity: 0.5;\r\n pointer-events: none;\r\n cursor: not-allowed;\r\n}\r\n\r\n/* the title IS the consumer's line — a custom row has no title element */\r\n[mono-tag-input] [mono-item-text] {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n}\r\n\r\n[mono-tag-input] [mono-item-title],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='row'] {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* EXTENSION — `item.description`: a muted second line */\r\n[mono-tag-input] [mono-item-sub] {\r\n margin-top: 0;\r\n font-size: var(--mono-text-xs);\r\n line-height: var(--mono-text-xs--lh);\r\n color: var(--_mono-tag-input-muted);\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* checkable rows: the box IS a mono-checkbox — the row emits the element's own\r\n markup ([mono-checkbox] > [mono-box], [mono-size=\"sm\"], the checked /\r\n indeterminate / loading states) and checkbox.css paints every pixel of it, in\r\n both builds; this sheet says only how it sits in the row: it must not shrink\r\n or take clicks (the row's button handles the toggle). A consumer's line lays\r\n out the same. */\r\n[mono-tag-input] [mono-check-box],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-chrome] {\r\n flex: 0 0 auto;\r\n gap: 0;\r\n pointer-events: none;\r\n}\r\n\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='group'] {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--mono-tag-input-option-gap, calc(var(--mono-spacing) * 2));\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .select:not(select) [role='listbox']:not(:has([data-value]:not([aria-hidden='true'])))::before\r\n — py-6 text-center text-sm */\r\n[mono-tag-input] [mono-empty-row] {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding-block: calc(var(--mono-spacing) * 6);\r\n padding-inline: calc(var(--mono-spacing) * 3);\r\n font-size: var(--mono-tag-input-option-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-option-line-height, var(--mono-text-sm--lh));\r\n color: var(--_mono-tag-input-muted);\r\n text-align: center;\r\n cursor: default;\r\n user-select: none;\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox [role='heading'] — px-2 py-1.5 text-xs\r\n text-muted-foreground; EXTENSION: one indent step per level, a <button> when the\r\n header selects its group */\r\n[mono-tag-input] [mono-group],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='group'] {\r\n --_ti-group-level: 0;\r\n width: 100%;\r\n margin: 0;\r\n padding-block: var(--mono-tag-input-group-padding-y, calc(var(--mono-spacing) * 1.5));\r\n padding-inline: var(--mono-tag-input-group-padding-x, calc(var(--mono-spacing) * 2));\r\n padding-inline-start: calc(var(--mono-tag-input-group-padding-x, calc(var(--mono-spacing) * 2)) + var(--_ti-group-level) * calc(var(--mono-spacing) * 3));\r\n border: 0;\r\n border-radius: var(--mono-tag-input-option-radius, var(--mono-radius-sm));\r\n background: transparent;\r\n font-family: inherit;\r\n font-size: var(--mono-tag-input-group-font-size, var(--mono-text-xs));\r\n line-height: var(--mono-tag-input-group-line-height, var(--mono-text-xs--lh));\r\n font-weight: var(--mono-tag-input-group-font-weight, var(--mono-font-weight-normal));\r\n text-transform: var(--mono-tag-input-group-text-transform, none);\r\n letter-spacing: var(--mono-tag-input-group-letter-spacing, normal);\r\n text-align: start;\r\n color: var(--_mono-tag-input-muted);\r\n cursor: default;\r\n user-select: none;\r\n}\r\n\r\n[mono-tag-input] [mono-group][mono-level='1'],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-level='1'] { --_ti-group-level: 1; --_ti-item-level: 1; }\r\n[mono-tag-input] [mono-group][mono-level='2'],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-level='2'] { --_ti-group-level: 2; --_ti-item-level: 2; }\r\n[mono-tag-input] [mono-group][mono-level='3'],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-level='3'] { --_ti-group-level: 3; --_ti-item-level: 3; }\r\n[mono-tag-input] [mono-group][mono-level='4'],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-level='4'] { --_ti-group-level: 4; --_ti-item-level: 4; }\r\n\r\n/* a header that selects its own group is a <button> laid out like the rows */\r\n[mono-tag-input] [mono-group][mono-toggle],\r\n[mono-tag-input] :where([mono-list-slot]) [data-mono-type='group']:has([data-mono-chrome]) {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--mono-tag-input-option-gap, calc(var(--mono-spacing) * 2));\r\n cursor: pointer;\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-tag-input] [mono-group][mono-toggle]:hover {\r\n background-color: var(--mono-tag-input-option-active-bg, var(--muted));\r\n color: var(--_mono-tag-input-text);\r\n }\r\n}\r\n\r\n/* a group carrying a selection reads at a glance while scrolling */\r\n[mono-tag-input] [mono-group][mono-toggle][mono-selected] {\r\n color: var(--_mono-tag-input-text);\r\n}\r\n\r\n[mono-tag-input] [mono-group-label] {\r\n flex: 1 1 auto;\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n/* group-sticky: pin headers while their rows scroll, on the panel's own surface */\r\n[mono-tag-input] [mono-group][mono-sticky] {\r\n position: sticky;\r\n top: calc(var(--_ti-group-level) * 1.5rem);\r\n z-index: calc(5 - var(--_ti-group-level));\r\n background: var(--mono-tag-input-dropdown-bg, var(--popover));\r\n}\r\n\r\n/* EXTENSION — the \"All\" row: always first, always sticky, on the panel surface\r\n with a hairline under it; z above the group headers (which stack from 5 down) */\r\n[mono-tag-input] [mono-select-all] {\r\n position: sticky;\r\n top: 0;\r\n z-index: 6;\r\n background-color: var(--mono-tag-input-dropdown-bg, var(--popover));\r\n box-shadow: 0 1px 0 0 var(--border);\r\n font-weight: var(--mono-font-weight-medium);\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-tag-input] [mono-select-all]:hover:not(:disabled) {\r\n background-color: var(--mono-tag-input-option-active-bg, var(--muted));\r\n }\r\n}\r\n\r\n/* while it drains the server the row is `disabled` so a second click cannot start\r\n a second drain — but it is busy, not unavailable: undo the disabled look */\r\n[mono-tag-input] [mono-select-all][mono-loading],\r\n[mono-tag-input] [mono-select-all][mono-loading]:hover {\r\n opacity: 1;\r\n cursor: progress;\r\n pointer-events: none;\r\n background-color: var(--mono-tag-input-option-active-bg, var(--muted));\r\n}\r\n\r\n/* EXTENSION — the load-more affordance: an option-shaped ghost button */\r\n[mono-tag-input] [mono-load-more] {\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n justify-content: center;\r\n gap: var(--mono-tag-input-option-gap, calc(var(--mono-spacing) * 2));\r\n margin: 0;\r\n padding-block: var(--mono-tag-input-option-padding-y, calc(var(--mono-spacing) * 1.5));\r\n padding-inline: var(--mono-tag-input-option-padding-x, calc(var(--mono-spacing) * 2));\r\n border: 0;\r\n border-radius: var(--mono-tag-input-option-radius, var(--mono-radius-sm));\r\n background: transparent;\r\n color: var(--_mono-tag-input-muted);\r\n font-family: inherit;\r\n font-size: var(--mono-tag-input-option-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-option-line-height, var(--mono-text-sm--lh));\r\n font-weight: var(--mono-font-weight-medium);\r\n cursor: pointer;\r\n transition-property: color, background-color;\r\n transition-timing-function: var(--mono-ease);\r\n transition-duration: var(--mono-duration-fast);\r\n}\r\n\r\n@media (hover: hover) {\r\n [mono-tag-input] [mono-load-more]:hover:not([mono-loading]) {\r\n background: var(--mono-tag-input-option-active-bg, var(--muted));\r\n color: var(--_mono-tag-input-text);\r\n }\r\n}\r\n\r\n[mono-tag-input] [mono-load-more][mono-loading] {\r\n cursor: default;\r\n opacity: 0.7;\r\n}\r\n\r\n/* Consumer-rendered option rows (slot=\"list\"): `display: contents` so mono's own\r\n placement wrapper generates no box. */\r\n[mono-tag-input] [mono-list-slot] {\r\n display: contents;\r\n}\r\n\r\n/* =========================================\r\n The \"+N more\" overflow panel — a popover holding the overflow chips\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .combobox [data-popover] — bg-popover ring-1\r\n ring-foreground/10 rounded-md shadow-md; EXTENSION: p-1.5 gap-1.5 flex-wrap */\r\n[mono-tag-input] > [mono-more-panel] {\r\n position: absolute;\r\n left: 0;\r\n right: 0;\r\n top: auto;\r\n transform: translateY(calc(var(--mono-spacing) * 1.5));\r\n z-index: var(--mono-popup-z, 1000);\r\n display: none;\r\n flex-wrap: wrap;\r\n align-items: flex-start;\r\n gap: var(--_mono-tag-input-gap);\r\n padding: calc(var(--mono-spacing) * 1.5);\r\n max-height: min(14rem, var(--mono-popup-avail-h, 100vh));\r\n overflow: auto;\r\n overscroll-behavior: contain;\r\n border-radius: var(--mono-tag-input-dropdown-radius, var(--mono-radius-md));\r\n background: var(--mono-tag-input-dropdown-bg, var(--popover));\r\n color: var(--mono-tag-input-dropdown-color, var(--popover-foreground));\r\n box-shadow: var(--mono-tag-input-dropdown-ring, 0 0 0 1px color-mix(in oklab, var(--foreground) 10%, transparent)), var(--mono-tag-input-dropdown-shadow, var(--mono-shadow-md));\r\n}\r\n\r\n[mono-tag-input][mono-more-open] > [mono-more-panel] {\r\n display: flex;\r\n}\r\n\r\n/* =========================================\r\n Message\r\n ========================================= */\r\n\r\n/* basecoat@1.0.2 styles/vega.css .fieldset legend + p, .field > p, .field section > p */\r\n[mono-tag-input] > [mono-message-wrap] {\r\n display: block;\r\n margin-top: var(--_mono-tag-input-gap-y);\r\n}\r\n\r\n[mono-tag-input] > [mono-message-wrap]:not(:has([mono-message]:not([mono-empty]))) {\r\n display: none;\r\n}\r\n\r\n[mono-tag-input] [mono-message] {\r\n font-size: var(--mono-tag-input-message-font-size, var(--mono-text-sm));\r\n line-height: var(--mono-tag-input-message-line-height, var(--mono-leading-normal));\r\n font-weight: var(--mono-font-weight-normal);\r\n text-align: start;\r\n color: var(--_mono-tag-input-muted);\r\n}\r\n\r\n/* basecoat@1.0.2 styles/vega.css .field [role=\"alert\"] — text-destructive text-sm */\r\n[mono-tag-input] [mono-message=\"invalid\"] {\r\n color: var(--_mono-tag-input-invalid);\r\n}\r\n\r\n[mono-tag-input] [mono-message=\"valid\"] {\r\n color: var(--_mono-tag-input-valid);\r\n}\r\n\r\n[mono-tag-input] [mono-message=\"warning\"] {\r\n color: var(--_mono-tag-input-warning);\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n [mono-tag-input] > [mono-field],\r\n [mono-tag-input] [mono-clear],\r\n [mono-tag-input] [mono-arrow],\r\n [mono-tag-input] [mono-scroll],\r\n [mono-tag-input] [mono-item],\r\n [mono-tag-input] [mono-chip-close] {\r\n transition: none;\r\n }\r\n\r\n [mono-tag-input] [mono-ds-spinner] > svg {\r\n animation-duration: 2.4s;\r\n }\r\n}\r\n";
2788
+ //#endregion
2789
+ //#region src/components/tag-input/mono-tag-input.ts
2790
+ var MonoTagInput = class MonoTagInput extends MonoTagInputCore(LitElement) {
2791
+ constructor(..._args) {
2792
+ super(..._args);
2793
+ this._slotsCaptured = false;
2794
+ this._slotLabel = [];
2795
+ this._slotHelper = [];
2796
+ this._slotList = null;
2797
+ }
2798
+ static {
2799
+ this.styles = [unsafeCSS(tag_input_default)];
2800
+ }
2801
+ createRenderRoot() {
2802
+ return this;
2803
+ }
2804
+ connectedCallback() {
2805
+ super.connectedCallback();
2806
+ this._captureSlots();
2807
+ if (this.isConnected) this.performUpdate();
2808
+ }
2809
+ updated(changed) {
2810
+ super.updated(changed);
2811
+ this._onLateListSlot();
2812
+ this._placeSlot("label", this._slotLabel);
2813
+ this._placeSlot("helper", this._slotHelper);
2814
+ this._placeListSlot();
2815
+ this._watchListChrome();
2816
+ this._syncListChrome();
2817
+ }
2818
+ /**
2819
+ * The captured wrapper, which is the truth for this build at every moment: parked out of the
2820
+ * host before the panel exists, and inside the panel after. The core's default (a light child of
2821
+ * the host) is the SHADOW build's answer and would find nothing here.
2822
+ */
2823
+ get _listSlotWrapper() {
2824
+ return this._slotList;
2825
+ }
2826
+ /** Light-DOM target for the list wrapper; the shadow build projects instead. */
2827
+ renderListSlot() {
2828
+ return html`<div class="mono-tag-input-list-slot" mono-list-slot data-mono-slot="list" @click=${this._onListSlotClick}></div>`;
2829
+ }
2830
+ /**
2831
+ * Move the wrapper into the panel, once it exists.
2832
+ *
2833
+ * The panel is relocated into a body portal while open, so the target is queried through the
2834
+ * core's portal-aware root rather than the host. Idempotent: once the wrapper is inside the
2835
+ * target it is left alone, which matters because re-appending it on every render would blow away
2836
+ * the consumer's scroll position and focus.
2837
+ */
2838
+ _placeListSlot() {
2839
+ const wrapper = this._slotList;
2840
+ if (!wrapper) return;
2841
+ const target = this._listSlotTarget;
2842
+ if (!target || wrapper.parentNode === target) return;
2843
+ target.appendChild(wrapper);
2844
+ }
2845
+ _captureSlots() {
2846
+ if (this._slotsCaptured) return;
2847
+ this._slotsCaptured = true;
2848
+ const captured = monoHostChildNodes(this);
2849
+ const capturedSlotNodes = /* @__PURE__ */ new Set();
2850
+ for (const node of captured) {
2851
+ if (!(node instanceof Element)) continue;
2852
+ const slotName = node.getAttribute("slot");
2853
+ if (slotName === "label") {
2854
+ node.removeAttribute("slot");
2855
+ this._slotLabel.push(node);
2856
+ capturedSlotNodes.add(node);
2857
+ }
2858
+ if (slotName === "helper") {
2859
+ node.removeAttribute("slot");
2860
+ this._slotHelper.push(node);
2861
+ capturedSlotNodes.add(node);
2862
+ }
2863
+ if (slotName === "list" && !this._slotList) {
2864
+ this._slotList = node;
2865
+ this._hasListSlotState = true;
2866
+ capturedSlotNodes.add(node);
2867
+ }
2868
+ }
2869
+ this._hasLabelSlotState = this._slotLabel.length > 0;
2870
+ this._hasHelperSlotState = this._slotHelper.length > 0;
2871
+ for (const node of capturedSlotNodes) if (node.parentNode === this) this.removeChild(node);
2872
+ }
2873
+ /**
2874
+ * Adopt a wrapper that appeared after `connectedCallback` — see `LateSlotWatcher`.
2875
+ *
2876
+ * Two things have to happen and the order matters. It is PARKED first, out of the host, because
2877
+ * until it is placed it would otherwise paint in the host's own flow, under the field rather
2878
+ * than inside the panel — that is the bug this exists for. Only then is the flag flipped, which
2879
+ * schedules the render that creates the target `_placeListSlot` needs.
2880
+ *
2881
+ * Parking detached is safe for the subtree inside it: the consumer's `v-for` inserts against
2882
+ * anchors that are its OWN children, and those move with it.
2883
+ */
2884
+ _onLateListSlot() {
2885
+ if (this._slotList) return;
2886
+ const wrapper = this._lateListSlot.find();
2887
+ if (!wrapper) return;
2888
+ this._slotList = wrapper;
2889
+ if (wrapper.parentNode === this) this.removeChild(wrapper);
2890
+ this._hasListSlotState = true;
2891
+ }
2892
+ _placeSlot(name, nodes) {
2893
+ if (!nodes.length) return;
2894
+ const target = this.querySelector(`[data-mono-slot="${name}"]`);
2895
+ if (!target) return;
2896
+ for (const node of nodes) placeSlotNode(target, node);
2897
+ }
2898
+ };
2899
+ MonoTagInput = __decorate([customElement("mono-tag-input")], MonoTagInput);
2900
+ //#endregion
2901
+ //#region src/components/tag-input/tag-input-utils.ts
2902
+ function validateTagInputProps(props) {
2903
+ const validSizes = [
2904
+ "xs",
2905
+ "sm",
2906
+ "md",
2907
+ "lg",
2908
+ "xl",
2909
+ "xxl"
2910
+ ];
2911
+ const validColors = [
2912
+ "primary",
2913
+ "secondary",
2914
+ "success",
2915
+ "danger",
2916
+ "warning",
2917
+ "info",
2918
+ "teal",
2919
+ "purple",
2920
+ "neutral",
2921
+ "dark"
2922
+ ];
2923
+ const validVariants = [
2924
+ "outlined",
2925
+ "filled",
2926
+ "underlined"
2927
+ ];
2928
+ const validStates = [
2929
+ "default",
2930
+ "valid",
2931
+ "invalid",
2932
+ "warning"
2933
+ ];
2934
+ if (props.size && !validSizes.includes(props.size)) return false;
2935
+ if (props.color && !validColors.includes(props.color)) return false;
2936
+ if (props.variant && !validVariants.includes(props.variant)) return false;
2937
+ if (props.validationState && !validStates.includes(props.validationState)) return false;
2938
+ return true;
2939
+ }
2940
+ function normalizeSuggestions(items) {
2941
+ return items.map((item) => ({
2942
+ ...item,
2943
+ value: item.value ?? item.label
2944
+ }));
2945
+ }
2946
+ //#endregion
2947
+ export { MonoTagInput, normalizeSuggestions, validateTagInputProps };