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