@schukai/monster 3.51.4 → 3.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/CHANGELOG.md +706 -0
  2. package/README.md +16 -13
  3. package/example/components/form/button.mjs +10 -0
  4. package/example/components/form/select.mjs +25 -0
  5. package/example/components/form/tree-select.mjs +27 -0
  6. package/example/components/host/host.mjs +0 -0
  7. package/example/components/notify/message.mjs +4 -0
  8. package/example/components/notify/notify.mjs +4 -0
  9. package/example/components/state/log.mjs +0 -0
  10. package/example/components/state/state.mjs +0 -0
  11. package/package.json +6 -2
  12. package/source/components/constants.mjs +132 -0
  13. package/source/components/datatable/columnbar.mjs +310 -0
  14. package/source/components/datatable/constants.mjs +121 -0
  15. package/source/components/datatable/dataset.mjs +219 -0
  16. package/source/components/datatable/datasource/dom.mjs +186 -0
  17. package/source/components/datatable/datasource/namespace.mjs +13 -0
  18. package/source/components/datatable/datasource/rest.mjs +400 -0
  19. package/source/components/datatable/datasource.mjs +102 -0
  20. package/source/components/datatable/datatable/header.mjs +268 -0
  21. package/source/components/datatable/datatable/namespace.mjs +13 -0
  22. package/source/components/datatable/datatable.mjs +789 -0
  23. package/source/components/datatable/embedded-pagination.mjs +113 -0
  24. package/source/components/datatable/filter/abstract-base.mjs +31 -0
  25. package/source/components/datatable/filter/date-range.mjs +1041 -0
  26. package/source/components/datatable/filter/input.mjs +175 -0
  27. package/source/components/datatable/filter/namespace.mjs +13 -0
  28. package/source/components/datatable/filter/range.mjs +671 -0
  29. package/source/components/datatable/filter/select.mjs +65 -0
  30. package/source/components/datatable/filter/settings.mjs +116 -0
  31. package/source/components/datatable/filter-button.mjs +98 -0
  32. package/source/components/datatable/filter.mjs +929 -0
  33. package/source/components/datatable/namespace.mjs +11 -0
  34. package/source/components/datatable/pagination.mjs +456 -0
  35. package/source/components/datatable/style/column-bar.pcss +123 -0
  36. package/source/components/datatable/style/dataset.pcss +13 -0
  37. package/source/components/datatable/style/datasource.pcss +16 -0
  38. package/source/components/datatable/style/datatable.pcss +239 -0
  39. package/source/components/datatable/style/embedded-pagination.pcss +101 -0
  40. package/source/components/datatable/style/filter-button.pcss +22 -0
  41. package/source/components/datatable/style/filter-controls-defaults.pcss +46 -0
  42. package/source/components/datatable/style/filter-date-range.pcss +9 -0
  43. package/source/components/datatable/style/filter-range.pcss +5 -0
  44. package/source/components/datatable/style/filter.pcss +156 -0
  45. package/source/components/datatable/style/pagination.pcss +59 -0
  46. package/source/components/datatable/style/select-filter.pcss +27 -0
  47. package/source/components/datatable/stylesheet/column-bar.mjs +33 -0
  48. package/source/components/datatable/stylesheet/dataset.mjs +33 -0
  49. package/source/components/datatable/stylesheet/datasource.mjs +33 -0
  50. package/source/components/datatable/stylesheet/datatable.mjs +33 -0
  51. package/source/components/datatable/stylesheet/embedded-pagination.mjs +33 -0
  52. package/source/components/datatable/stylesheet/filter-button.mjs +33 -0
  53. package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +33 -0
  54. package/source/components/datatable/stylesheet/filter-date-range.mjs +33 -0
  55. package/source/components/datatable/stylesheet/filter-range.mjs +33 -0
  56. package/source/components/datatable/stylesheet/filter.mjs +33 -0
  57. package/source/components/datatable/stylesheet/namespace.mjs +13 -0
  58. package/source/components/datatable/stylesheet/pagination.mjs +33 -0
  59. package/source/components/datatable/stylesheet/select-filter.mjs +33 -0
  60. package/source/components/datatable/util.mjs +60 -0
  61. package/source/components/form/action-button.mjs +262 -0
  62. package/source/components/form/api-button.mjs +515 -0
  63. package/source/components/form/button-bar.mjs +739 -0
  64. package/source/components/form/button.mjs +350 -0
  65. package/source/components/form/confirm-button.mjs +330 -0
  66. package/source/components/form/constants.mjs +111 -0
  67. package/source/components/form/context-help.mjs +123 -0
  68. package/source/components/form/events.mjs +84 -0
  69. package/source/components/form/form.mjs +601 -0
  70. package/source/components/form/message-state-button.mjs +396 -0
  71. package/source/components/form/namespace.mjs +13 -0
  72. package/source/components/form/popper-button.mjs +435 -0
  73. package/source/components/form/popper.mjs +487 -0
  74. package/source/components/form/reload.mjs +360 -0
  75. package/source/components/form/select.mjs +2314 -0
  76. package/source/components/form/shadow-reload.mjs +137 -0
  77. package/source/components/form/state-button.mjs +182 -0
  78. package/source/components/form/style/action-button.pcss +41 -0
  79. package/source/components/form/style/api-button.pcss +0 -0
  80. package/source/components/form/style/button-bar.pcss +51 -0
  81. package/source/components/form/style/button.pcss +8 -0
  82. package/source/components/form/style/confirm-button.pcss +17 -0
  83. package/source/components/form/style/context-help.pcss +16 -0
  84. package/source/components/form/style/form.pcss +10 -0
  85. package/source/components/form/style/message-state-button.pcss +10 -0
  86. package/source/components/form/style/popper-button.pcss +16 -0
  87. package/source/components/form/style/popper.pcss +8 -0
  88. package/source/components/form/style/select.pcss +265 -0
  89. package/source/components/form/style/state-button.pcss +116 -0
  90. package/source/components/form/style/tabs.pcss +170 -0
  91. package/source/components/form/style/tree-select.pcss +81 -0
  92. package/source/components/form/stylesheet/action-button.mjs +33 -0
  93. package/source/components/form/stylesheet/api-button.mjs +33 -0
  94. package/source/components/form/stylesheet/button-bar.mjs +33 -0
  95. package/source/components/form/stylesheet/button.mjs +33 -0
  96. package/source/components/form/stylesheet/confirm-button.mjs +33 -0
  97. package/source/components/form/stylesheet/context-help.mjs +33 -0
  98. package/source/components/form/stylesheet/form.mjs +33 -0
  99. package/source/components/form/stylesheet/message-state-button.mjs +33 -0
  100. package/source/components/form/stylesheet/namespace.mjs +13 -0
  101. package/source/components/form/stylesheet/popper-button.mjs +33 -0
  102. package/source/components/form/stylesheet/popper.mjs +33 -0
  103. package/source/components/form/stylesheet/select.mjs +33 -0
  104. package/source/components/form/stylesheet/state-button.mjs +33 -0
  105. package/source/components/form/stylesheet/tabs.mjs +33 -0
  106. package/source/components/form/stylesheet/tree-select.mjs +33 -0
  107. package/source/components/form/tabs.mjs +1011 -0
  108. package/source/components/form/template.mjs +373 -0
  109. package/source/components/form/tree-select.mjs +527 -0
  110. package/source/components/form/types/namespace.mjs +13 -0
  111. package/source/components/form/types/state.mjs +93 -0
  112. package/source/components/form/util/fetch.mjs +133 -0
  113. package/source/components/form/util/floating-ui.mjs +245 -0
  114. package/source/components/form/util/namespace.mjs +13 -0
  115. package/source/components/form/util/popper.mjs +49 -0
  116. package/source/components/host/call-button.mjs +236 -0
  117. package/source/components/host/collapse.mjs +526 -0
  118. package/source/components/host/config-manager.mjs +304 -0
  119. package/source/components/host/constants.mjs +18 -0
  120. package/source/components/host/details.mjs +268 -0
  121. package/source/components/host/events.mjs +131 -0
  122. package/source/components/host/host.mjs +420 -0
  123. package/source/components/host/namespace.mjs +13 -0
  124. package/source/components/host/overlay.mjs +339 -0
  125. package/source/components/host/style/call-button.pcss +36 -0
  126. package/source/components/host/style/collapse.pcss +67 -0
  127. package/source/components/host/style/config-manager.pcss +5 -0
  128. package/source/components/host/style/details.pcss +68 -0
  129. package/source/components/host/style/host.pcss +43 -0
  130. package/source/components/host/style/overlay.pcss +73 -0
  131. package/source/components/host/style/toggle-button.pcss +36 -0
  132. package/source/components/host/style/viewer.pcss +13 -0
  133. package/source/components/host/stylesheet/call-button.mjs +33 -0
  134. package/source/components/host/stylesheet/collapse.mjs +33 -0
  135. package/source/components/host/stylesheet/config-manager.mjs +33 -0
  136. package/source/components/host/stylesheet/details.mjs +33 -0
  137. package/source/components/host/stylesheet/host.mjs +33 -0
  138. package/source/components/host/stylesheet/namespace.mjs +13 -0
  139. package/source/components/host/stylesheet/overlay.mjs +33 -0
  140. package/source/components/host/stylesheet/toggle-button.mjs +33 -0
  141. package/source/components/host/stylesheet/viewer.mjs +33 -0
  142. package/source/components/host/toggle-button.mjs +88 -0
  143. package/source/components/host/util.mjs +23 -0
  144. package/source/components/host/viewer.mjs +309 -0
  145. package/source/components/namespace.mjs +14 -0
  146. package/source/components/notify/constants.mjs +15 -0
  147. package/source/components/notify/events.mjs +15 -0
  148. package/source/components/notify/message.mjs +374 -0
  149. package/source/components/notify/namespace.mjs +15 -0
  150. package/source/components/notify/notify.mjs +236 -0
  151. package/source/components/notify/style/message.pcss +57 -0
  152. package/source/components/notify/style/notify.pcss +118 -0
  153. package/source/components/notify/stylesheet/message.mjs +33 -0
  154. package/source/components/notify/stylesheet/namespace.mjs +15 -0
  155. package/source/components/notify/stylesheet/notify.mjs +33 -0
  156. package/source/components/state/log/entry.mjs +126 -0
  157. package/source/components/state/log/namespace.mjs +13 -0
  158. package/source/components/state/log.mjs +275 -0
  159. package/source/components/state/namespace.mjs +13 -0
  160. package/source/components/state/state.mjs +131 -0
  161. package/source/components/state/style/log.pcss +111 -0
  162. package/source/components/state/style/state.pcss +113 -0
  163. package/source/components/state/stylesheet/log.mjs +33 -0
  164. package/source/components/state/stylesheet/state.mjs +33 -0
  165. package/source/components/style/badge.pcss +92 -0
  166. package/source/components/style/border.pcss +77 -0
  167. package/source/components/style/button.pcss +105 -0
  168. package/source/components/style/card.pcss +108 -0
  169. package/source/components/style/color.pcss +257 -0
  170. package/source/components/style/common.pcss +103 -0
  171. package/source/components/style/control.pcss +11 -0
  172. package/source/components/style/data-grid.pcss +43 -0
  173. package/source/components/style/display.pcss +42 -0
  174. package/source/components/style/floating-ui.pcss +33 -0
  175. package/source/components/style/form.pcss +5 -0
  176. package/source/components/style/host.pcss +15 -0
  177. package/source/components/style/link.pcss +63 -0
  178. package/source/components/style/mixin/badge.pcss +18 -0
  179. package/source/components/style/mixin/button.pcss +54 -0
  180. package/source/components/style/mixin/form.pcss +247 -0
  181. package/source/components/style/mixin/hover.pcss +8 -0
  182. package/source/components/style/mixin/media.pcss +107 -0
  183. package/source/components/style/mixin/property.pcss +288 -0
  184. package/source/components/style/mixin/skeleton.pcss +26 -0
  185. package/source/components/style/mixin/spinner.pcss +24 -0
  186. package/source/components/style/mixin/typography.pcss +52 -0
  187. package/source/components/style/normalize.pcss +14 -0
  188. package/source/components/style/popper.pcss +78 -0
  189. package/source/components/style/property.pcss +17 -0
  190. package/source/components/style/ripple.pcss +14 -0
  191. package/source/components/style/skeleton.pcss +28 -0
  192. package/source/components/style/space.pcss +47 -0
  193. package/source/components/style/spinner.pcss +6 -0
  194. package/source/components/style/table.pcss +46 -0
  195. package/source/components/style/theme.pcss +119 -0
  196. package/source/components/style/typography.pcss +131 -0
  197. package/source/components/stylesheet/badge.mjs +33 -0
  198. package/source/components/stylesheet/border.mjs +33 -0
  199. package/source/components/stylesheet/button.mjs +33 -0
  200. package/source/components/stylesheet/card.mjs +33 -0
  201. package/source/components/stylesheet/color.mjs +33 -0
  202. package/source/components/stylesheet/common.mjs +33 -0
  203. package/source/components/stylesheet/control.mjs +33 -0
  204. package/source/components/stylesheet/data-grid.mjs +33 -0
  205. package/source/components/stylesheet/display.mjs +33 -0
  206. package/source/components/stylesheet/floating-ui.mjs +33 -0
  207. package/source/components/stylesheet/form.mjs +33 -0
  208. package/source/components/stylesheet/host.mjs +33 -0
  209. package/source/components/stylesheet/link.mjs +33 -0
  210. package/source/components/stylesheet/namespace.mjs +13 -0
  211. package/source/components/stylesheet/normalize.mjs +33 -0
  212. package/source/components/stylesheet/popper.mjs +33 -0
  213. package/source/components/stylesheet/property.mjs +33 -0
  214. package/source/components/stylesheet/ripple.mjs +33 -0
  215. package/source/components/stylesheet/skeleton.mjs +33 -0
  216. package/source/components/stylesheet/space.mjs +33 -0
  217. package/source/components/stylesheet/spinner.mjs +33 -0
  218. package/source/components/stylesheet/table.mjs +33 -0
  219. package/source/components/stylesheet/theme.mjs +33 -0
  220. package/source/components/stylesheet/tree-menu.mjs +33 -0
  221. package/source/components/stylesheet/typography.mjs +33 -0
  222. package/source/components/tree-menu/namespace.mjs +13 -0
  223. package/source/components/tree-menu/style/tree-menu.pcss +107 -0
  224. package/source/components/tree-menu/stylesheet/namespace.mjs +13 -0
  225. package/source/components/tree-menu/stylesheet/tree-menu.mjs +33 -0
  226. package/source/components/tree-menu/tree-menu.mjs +660 -0
  227. package/source/constraints/abstract.mjs +17 -24
  228. package/source/constraints/abstractoperator.mjs +27 -22
  229. package/source/constraints/andoperator.mjs +20 -17
  230. package/source/constraints/invalid.mjs +17 -17
  231. package/source/constraints/isarray.mjs +20 -20
  232. package/source/constraints/isobject.mjs +20 -20
  233. package/source/constraints/oroperator.mjs +45 -45
  234. package/source/constraints/valid.mjs +17 -17
  235. package/source/data/buildmap.mjs +108 -103
  236. package/source/data/buildtree.mjs +59 -57
  237. package/source/data/datasource/dom.mjs +80 -84
  238. package/source/data/datasource/namespace.mjs +1 -1
  239. package/source/data/datasource/server/restapi/data-fetch-error.mjs +27 -25
  240. package/source/data/datasource/server/restapi/writeerror.mjs +34 -32
  241. package/source/data/datasource/server/restapi.mjs +176 -177
  242. package/source/data/datasource/server/webconnect.mjs +150 -156
  243. package/source/data/datasource/server.mjs +58 -59
  244. package/source/data/datasource/storage/localstorage.mjs +25 -24
  245. package/source/data/datasource/storage/sessionstorage.mjs +28 -25
  246. package/source/data/datasource/storage.mjs +74 -73
  247. package/source/data/datasource.mjs +176 -167
  248. package/source/data/diff.mjs +98 -97
  249. package/source/data/extend.mjs +42 -42
  250. package/source/data/pathfinder.mjs +301 -288
  251. package/source/data/pipe.mjs +36 -36
  252. package/source/data/transformer.mjs +742 -726
  253. package/source/dom/assembler.mjs +44 -44
  254. package/source/dom/attributes.mjs +142 -122
  255. package/source/dom/constants.mjs +62 -58
  256. package/source/dom/customcontrol.mjs +299 -299
  257. package/source/dom/customelement.mjs +843 -806
  258. package/source/dom/dimension.mjs +56 -46
  259. package/source/dom/events.mjs +74 -69
  260. package/source/dom/focusmanager.mjs +175 -175
  261. package/source/dom/locale.mjs +28 -28
  262. package/source/dom/ready.mjs +13 -13
  263. package/source/dom/resource/data.mjs +117 -111
  264. package/source/dom/resource/link/stylesheet.mjs +16 -16
  265. package/source/dom/resource/link.mjs +94 -96
  266. package/source/dom/resource/script.mjs +72 -74
  267. package/source/dom/resource.mjs +174 -172
  268. package/source/dom/resourcemanager.mjs +152 -156
  269. package/source/dom/slotted.mjs +78 -80
  270. package/source/dom/template.mjs +126 -112
  271. package/source/dom/theme.mjs +35 -35
  272. package/source/dom/updater.mjs +673 -651
  273. package/source/dom/util/extract-keys.mjs +34 -22
  274. package/source/dom/util/init-options-from-attributes.mjs +46 -38
  275. package/source/dom/util/namespace.mjs +13 -0
  276. package/source/dom/util/set-option-from-attribute.mjs +35 -29
  277. package/source/dom/util.mjs +112 -81
  278. package/source/dom/worker/factory.mjs +83 -83
  279. package/source/i18n/formatter.mjs +75 -73
  280. package/source/i18n/locale.mjs +146 -144
  281. package/source/i18n/provider.mjs +70 -64
  282. package/source/i18n/providers/embed.mjs +136 -127
  283. package/source/i18n/providers/fetch.mjs +84 -76
  284. package/source/i18n/translations.mjs +205 -195
  285. package/source/logging/handler/console.mjs +36 -36
  286. package/source/logging/handler.mjs +140 -140
  287. package/source/logging/logentry.mjs +25 -25
  288. package/source/logging/logger.mjs +177 -175
  289. package/source/math/random.mjs +63 -59
  290. package/source/monster.mjs +226 -217
  291. package/source/net/webconnect/message.mjs +31 -31
  292. package/source/net/webconnect.mjs +278 -271
  293. package/source/text/bracketed-key-value-hash.mjs +182 -179
  294. package/source/text/formatter.mjs +235 -210
  295. package/source/text/generate-range-comparison-expression.mjs +56 -34
  296. package/source/text/namespace.mjs +1 -1
  297. package/source/types/base.mjs +69 -61
  298. package/source/types/basewithoptions.mjs +46 -46
  299. package/source/types/binary.mjs +20 -20
  300. package/source/types/dataurl.mjs +96 -90
  301. package/source/types/global.mjs +45 -39
  302. package/source/types/id.mjs +25 -25
  303. package/source/types/internal.mjs +115 -114
  304. package/source/types/is.mjs +56 -40
  305. package/source/types/mediatype.mjs +119 -119
  306. package/source/types/namespace.mjs +1 -1
  307. package/source/types/node.mjs +160 -150
  308. package/source/types/nodelist.mjs +94 -96
  309. package/source/types/noderecursiveiterator.mjs +50 -50
  310. package/source/types/observablequeue.mjs +73 -73
  311. package/source/types/observer.mjs +104 -104
  312. package/source/types/observerlist.mjs +66 -66
  313. package/source/types/proxyobserver.mjs +210 -210
  314. package/source/types/queue.mjs +63 -63
  315. package/source/types/randomid.mjs +13 -13
  316. package/source/types/regex.mjs +3 -1
  317. package/source/types/stack.mjs +64 -64
  318. package/source/types/tokenlist.mjs +206 -205
  319. package/source/types/typeof.mjs +12 -10
  320. package/source/types/uniquequeue.mjs +48 -48
  321. package/source/types/uuid.mjs +32 -32
  322. package/source/types/validate.mjs +67 -67
  323. package/source/types/version.mjs +115 -105
  324. package/source/util/clone.mjs +103 -91
  325. package/source/util/comparator.mjs +97 -97
  326. package/source/util/deadmansswitch.mjs +40 -44
  327. package/source/util/freeze.mjs +10 -9
  328. package/source/util/namespace.mjs +1 -1
  329. package/source/util/processing.mjs +104 -105
  330. package/source/util/runtime.mjs +56 -44
  331. package/source/util/trimspaces.mjs +24 -24
  332. package/test/cases/components/form/button.mjs +122 -0
  333. package/test/cases/components/form/confirm-button.mjs +127 -0
  334. package/test/cases/components/form/form.mjs +317 -0
  335. package/test/cases/components/form/reload.mjs +188 -0
  336. package/test/cases/components/form/select.mjs +229 -0
  337. package/test/cases/components/form/state-button.mjs +130 -0
  338. package/test/cases/components/form/tabs.mjs +98 -0
  339. package/test/cases/components/form/template.mjs +189 -0
  340. package/test/cases/components/form/tree-select.mjs +216 -0
  341. package/test/cases/components/host/details.mjs +68 -0
  342. package/test/cases/components/host/host.mjs +70 -0
  343. package/test/cases/components/host/overlay.mjs +60 -0
  344. package/test/cases/components/host/util.mjs +79 -0
  345. package/test/cases/components/notify/message.mjs +39 -0
  346. package/test/cases/components/notify/notify.mjs +89 -0
  347. package/test/cases/constraint/abstractoperator.mjs +2 -2
  348. package/test/cases/constraint/andoperator.mjs +3 -3
  349. package/test/cases/constraint/invalid.mjs +1 -1
  350. package/test/cases/constraint/isarray.mjs +1 -1
  351. package/test/cases/constraint/isobject.mjs +1 -1
  352. package/test/cases/constraint/oroperator.mjs +3 -3
  353. package/test/cases/constraint/valid.mjs +1 -1
  354. package/test/cases/data/buildmap.mjs +1 -1
  355. package/test/cases/data/buildtree.mjs +2 -2
  356. package/test/cases/data/datasource/dom.mjs +1 -1
  357. package/test/cases/data/datasource/server/restapi.mjs +2 -2
  358. package/test/cases/data/datasource/server/websocket.mjs +1 -1
  359. package/test/cases/data/datasource/server.mjs +1 -1
  360. package/test/cases/data/datasource/storage/localstorage.mjs +1 -1
  361. package/test/cases/data/datasource/storage/sessionstorage.mjs +1 -1
  362. package/test/cases/data/datasource.mjs +1 -1
  363. package/test/cases/data/diff.mjs +2 -2
  364. package/test/cases/data/extend.mjs +1 -1
  365. package/test/cases/data/pathfinder.mjs +1 -1
  366. package/test/cases/data/pipe.mjs +2 -2
  367. package/test/cases/data/transformer.mjs +3 -4
  368. package/test/cases/dom/assembler.mjs +1 -1
  369. package/test/cases/dom/attributes.mjs +1 -1
  370. package/test/cases/dom/customcontrol.mjs +8 -7
  371. package/test/cases/dom/customelement-initfromscripthost.mjs +6 -6
  372. package/test/cases/dom/customelement.mjs +7 -7
  373. package/test/cases/dom/dimension.mjs +4 -4
  374. package/test/cases/dom/events.mjs +1 -1
  375. package/test/cases/dom/find.mjs +1 -1
  376. package/test/cases/dom/focusmanager.mjs +1 -1
  377. package/test/cases/dom/locale.mjs +2 -2
  378. package/test/cases/dom/ready.mjs +1 -1
  379. package/test/cases/dom/resource/data.mjs +3 -3
  380. package/test/cases/dom/resource/link/stylesheet.mjs +3 -3
  381. package/test/cases/dom/resource/link.mjs +3 -3
  382. package/test/cases/dom/resource/script.mjs +3 -3
  383. package/test/cases/dom/resource.mjs +1 -1
  384. package/test/cases/dom/resourcemanager.mjs +1 -1
  385. package/test/cases/dom/slotted-nodes.mjs +1 -1
  386. package/test/cases/dom/template.mjs +2 -2
  387. package/test/cases/dom/theme.mjs +2 -2
  388. package/test/cases/dom/updater.mjs +4 -4
  389. package/test/cases/dom/util/extract-keys.mjs +1 -1
  390. package/test/cases/dom/util/init-options-from-attributes.mjs +1 -1
  391. package/test/cases/dom/util.mjs +2 -2
  392. package/test/cases/dom/worker/factory.mjs +2 -2
  393. package/test/cases/i18n/formatter.mjs +2 -2
  394. package/test/cases/i18n/locale.mjs +1 -1
  395. package/test/cases/i18n/provider.mjs +4 -4
  396. package/test/cases/i18n/providers/embed.mjs +3 -3
  397. package/test/cases/i18n/providers/fetch.mjs +3 -3
  398. package/test/cases/i18n/translations.mjs +3 -3
  399. package/test/cases/logging/handler/console.mjs +3 -3
  400. package/test/cases/logging/handler.mjs +3 -3
  401. package/test/cases/logging/logentry.mjs +1 -1
  402. package/test/cases/logging/logger.mjs +1 -1
  403. package/test/cases/math/random.mjs +1 -2
  404. package/test/cases/monster.mjs +2 -2
  405. package/test/cases/net/webconnect/message.mjs +1 -2
  406. package/test/cases/net/webconnect.mjs +3 -3
  407. package/test/cases/text/bracketed-key-value-hash.mjs +1 -1
  408. package/test/cases/text/formatter.mjs +1 -1
  409. package/test/cases/text/util.mjs +1 -1
  410. package/test/cases/types/base.mjs +2 -2
  411. package/test/cases/types/basewithoptions.mjs +1 -1
  412. package/test/cases/types/binary.mjs +1 -1
  413. package/test/cases/types/dataurl.mjs +1 -1
  414. package/test/cases/types/global.mjs +1 -1
  415. package/test/cases/types/id.mjs +1 -1
  416. package/test/cases/types/internal.mjs +2 -2
  417. package/test/cases/types/is.mjs +2 -2
  418. package/test/cases/types/mediatype.mjs +1 -1
  419. package/test/cases/types/node.mjs +4 -4
  420. package/test/cases/types/nodelist.mjs +2 -2
  421. package/test/cases/types/noderecursiveiterator.mjs +3 -3
  422. package/test/cases/types/observablequeue.mjs +2 -2
  423. package/test/cases/types/observer.mjs +1 -1
  424. package/test/cases/types/observerlist.mjs +2 -2
  425. package/test/cases/types/proxyobserver.mjs +4 -4
  426. package/test/cases/types/queue.mjs +1 -1
  427. package/test/cases/types/randomid.mjs +1 -1
  428. package/test/cases/types/regex.mjs +1 -1
  429. package/test/cases/types/stack.mjs +1 -1
  430. package/test/cases/types/tokenlist.mjs +1 -1
  431. package/test/cases/types/typeof.mjs +2 -2
  432. package/test/cases/types/uniquequeue.mjs +1 -1
  433. package/test/cases/types/uuid.mjs +1 -1
  434. package/test/cases/types/validate.mjs +3 -3
  435. package/test/cases/types/version.mjs +1 -1
  436. package/test/cases/util/clone.mjs +1 -1
  437. package/test/cases/util/comparator.mjs +1 -1
  438. package/test/cases/util/deadmansswitch.mjs +1 -1
  439. package/test/cases/util/freeze.mjs +1 -1
  440. package/test/cases/util/processing.mjs +1 -1
  441. package/test/cases/util/trimspaces.mjs +1 -1
  442. package/test/util/chai-dom.mjs +2 -2
  443. package/test/util/intersection-mock.mjs +69 -0
  444. package/test/util/jsdom.mjs +43 -27
  445. package/test/util/localstorage.mjs +1 -0
  446. package/test/util/resize-observer.mjs +29 -0
  447. package/test/util/websocket.mjs +5 -2
  448. package/test/web/import.js +92 -73
  449. package/test/web/test.html +28 -5
  450. package/test/web/tests.js +29430 -15209
  451. package/CHANGELOG +0 -438
@@ -0,0 +1,2314 @@
1
+ /**
2
+ * Copyright schukai GmbH and contributors 2023. All Rights Reserved.
3
+ * Node module: @schukai/monster
4
+ * This file is licensed under the AGPLv3 License.
5
+ * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
+ */
7
+ import { instanceSymbol } from "../../constants.mjs";
8
+ import { internalSymbol } from "../../constants.mjs";
9
+ import { buildMap } from "../../data/buildmap.mjs";
10
+ import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
11
+ import { positionPopper } from "./util/floating-ui.mjs";
12
+ import {
13
+ addAttributeToken,
14
+ findClosestByAttribute,
15
+ removeAttributeToken,
16
+ } from "../../dom/attributes.mjs";
17
+ import {
18
+ ATTRIBUTE_ERRORMESSAGE,
19
+ ATTRIBUTE_PREFIX,
20
+ ATTRIBUTE_ROLE,
21
+ } from "../../dom/constants.mjs";
22
+ import { CustomControl } from "../../dom/customcontrol.mjs";
23
+ import {
24
+ assembleMethodSymbol,
25
+ getSlottedElements,
26
+ registerCustomElement,
27
+ } from "../../dom/customelement.mjs";
28
+ import {
29
+ findTargetElementFromEvent,
30
+ fireCustomEvent,
31
+ fireEvent,
32
+ } from "../../dom/events.mjs";
33
+ import { getDocument } from "../../dom/util.mjs";
34
+ import { Formatter } from "../../text/formatter.mjs";
35
+ import { getGlobal } from "../../types/global.mjs";
36
+ import { ID } from "../../types/id.mjs";
37
+ import {
38
+ isArray,
39
+ isFunction,
40
+ isInteger,
41
+ isIterable,
42
+ isObject,
43
+ isPrimitive,
44
+ isString,
45
+ } from "../../types/is.mjs";
46
+ import { Observer } from "../../types/observer.mjs";
47
+ import { ProxyObserver } from "../../types/proxyobserver.mjs";
48
+ import { validateArray, validateString } from "../../types/validate.mjs";
49
+ import { Processing } from "../../util/processing.mjs";
50
+ import { STYLE_DISPLAY_MODE_BLOCK } from "./constants.mjs";
51
+ import { SelectStyleSheet } from "./stylesheet/select.mjs";
52
+ import {
53
+ getDocumentTranslations,
54
+ Translations,
55
+ } from "../../i18n/translations.mjs";
56
+
57
+ export {
58
+ Select,
59
+ popperElementSymbol,
60
+ getSummaryTemplate,
61
+ getSelectionTemplate,
62
+ };
63
+
64
+ /**
65
+ * @private
66
+ * @type {string}
67
+ */
68
+ const noOptionsAvailableMessage = "No options available.";
69
+
70
+ /**
71
+ * @private
72
+ * @type {symbol}
73
+ */
74
+ const timerCallbackSymbol = Symbol("timerCallback");
75
+
76
+ /**
77
+ * local symbol
78
+ * @private
79
+ * @type {symbol}
80
+ */
81
+ const closeEventHandler = Symbol("closeEventHandler");
82
+
83
+ /**
84
+ * local symbol
85
+ * @private
86
+ * @type {symbol}
87
+ */
88
+ const clearOptionEventHandler = Symbol("clearOptionEventHandler");
89
+
90
+ /**
91
+ * local symbol
92
+ * @private
93
+ * @type {symbol}
94
+ */
95
+ const resizeObserverSymbol = Symbol("resizeObserver");
96
+
97
+ /**
98
+ * local symbol
99
+ * @private
100
+ * @type {symbol}
101
+ */
102
+ const keyEventHandler = Symbol("keyEventHandler");
103
+ /**
104
+ * local symbol
105
+ * @private
106
+ * @type {symbol}
107
+ */
108
+ const inputEventHandler = Symbol("inputEventHandler");
109
+
110
+ /**
111
+ * local symbol
112
+ * @private
113
+ * @type {symbol}
114
+ */
115
+ const changeEventHandler = Symbol("changeEventHandler");
116
+
117
+ /**
118
+ * local symbol
119
+ * @private
120
+ * @type {symbol}
121
+ */
122
+ const controlElementSymbol = Symbol("controlElement");
123
+
124
+ /**
125
+ * local symbol
126
+ * @private
127
+ * @type {symbol}
128
+ */
129
+ const selectionElementSymbol = Symbol("selectionElement");
130
+
131
+ /**
132
+ * local symbol
133
+ * @private
134
+ * @type {symbol}
135
+ */
136
+ const containerElementSymbol = Symbol("containerElement");
137
+
138
+ /**
139
+ * local symbol
140
+ * @private
141
+ * @type {symbol}
142
+ */
143
+ const popperElementSymbol = Symbol("popperElement");
144
+
145
+ /**
146
+ * local symbol
147
+ * @private
148
+ * @type {symbol}
149
+ */
150
+ const inlineFilterElementSymbol = Symbol("inlineFilterElement");
151
+ /**
152
+ * local symbol
153
+ * @private
154
+ * @type {symbol}
155
+ */
156
+ const popperFilterElementSymbol = Symbol("popperFilterElement");
157
+ /**
158
+ * local symbol
159
+ * @private
160
+ * @type {symbol}
161
+ */
162
+ const popperFilterContainerElementSymbol = Symbol(
163
+ "popperFilterContainerElement",
164
+ );
165
+
166
+ /**
167
+ * local symbol
168
+ * @private
169
+ * @type {symbol}
170
+ */
171
+ const optionsElementSymbol = Symbol("optionsElement");
172
+
173
+ /**
174
+ * local symbol
175
+ * @private
176
+ * @type {symbol}
177
+ */
178
+ const noOptionsAvailableElementSymbol = Symbol("noOptionsAvailableElement");
179
+
180
+ /**
181
+ * local symbol
182
+ * @private
183
+ * @type {symbol}
184
+ */
185
+ const statusOrRemoveBadgesElementSymbol = Symbol("statusOrRemoveBadgesElement");
186
+
187
+ /**
188
+ * @private
189
+ * @type {symbol}
190
+ */
191
+ const areOptionsAvailableAndInitSymbol = Symbol("@@areOptionsAvailableAndInit");
192
+
193
+ /**
194
+ * @private
195
+ * @type {number}
196
+ */
197
+ const FOCUS_DIRECTION_UP = 1;
198
+ /**
199
+ * @private
200
+ * @type {number}
201
+ */
202
+ const FOCUS_DIRECTION_DOWN = 2;
203
+
204
+ /**
205
+ * @private
206
+ * @type {string}
207
+ */
208
+ const FILTER_MODE_REMOTE = "remote";
209
+
210
+ /**
211
+ * @private
212
+ * @type {string}
213
+ */
214
+ const FILTER_MODE_OPTIONS = "options";
215
+
216
+ /**
217
+ * @private
218
+ * @type {string}
219
+ */
220
+ const FILTER_MODE_DISABLED = "disabled";
221
+
222
+ /**
223
+ * @private
224
+ * @type {string}
225
+ */
226
+ const FILTER_POSITION_POPPER = "popper";
227
+ /**
228
+ * @private
229
+ * @type {string}
230
+ */
231
+ const FILTER_POSITION_INLINE = "inline";
232
+
233
+ /**
234
+ * @typedef {Object} Selection
235
+ * @property {*} value
236
+ * @property {String} label
237
+ * @memberOf Monster.Components.Form
238
+ * @since 1.2.0
239
+ */
240
+
241
+ /**
242
+ * This CustomControl creates a select element with a variety of options.
243
+ * It supports filtering, local and remote, multiple selection and has a
244
+ * template system for displaying the options.
245
+ *
246
+ * <img src="./images/select.png">
247
+ *
248
+ * Dependencies: the system uses functions of the [monsterjs](https://monsterjs.org/) library
249
+ * as well as [pooperjs](https://popper.js.org/docs/v2/).
250
+ *
251
+ * You can create this control either by specifying the HTML tag `<monster-select />` directly in the HTML or using
252
+ * Javascript via the `document.createElement('monster-select');` method.
253
+ *
254
+ * ```html
255
+ * <monster-select></monster-select>
256
+ * ```
257
+ *
258
+ * Or you can create this CustomControl directly in Javascript:
259
+ *
260
+ * ```js
261
+ * import {Select} from '@schukai/component-form/source/select.js';
262
+ * document.createElement('monster-select');
263
+ * ```
264
+ *
265
+ * ## Events
266
+ *
267
+ * The event `monster-change` is sent as soon as someone has clicked on a input control.
268
+ * `monster-changed` is sent as soon as the control has processed this input.
269
+ * The `monster-changed` event is sent when setting a selection. If the options have been set, the `monster-options-set` event is sent.
270
+ *
271
+ * The CustomEvent has the property [`detail`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail).
272
+ *
273
+ * ```
274
+ * node.addEventListener('monster-change',(e)=>console.log(e.detail))
275
+ * node.addEventListener('monster-changed',(e)=>console.log(e.detail))
276
+ * node.addEventListener('monster-selected',(e)=>console.log(e.detail))
277
+ * node.addEventListener('monster-options-set',(e)=>console.log(e.detail))
278
+ * ```
279
+ *
280
+ * @externalExample ../../../example/components/form/select.mjs
281
+ * @startuml select.png
282
+ * skinparam monochrome true
283
+ * skinparam shadowing false
284
+ * HTMLElement <|-- CustomElement
285
+ * CustomElement <|-- CustomControl
286
+ * CustomControl <|-- Select
287
+ * @enduml
288
+ *
289
+ * @since 1.0.0
290
+ * @copyright schukai GmbH
291
+ * @memberOf Monster.Components.Form
292
+ * @summary A highly configurable select control
293
+ * @fires Monster.Components.Form.event:monster-options-set
294
+ * @fires Monster.Components.Form.event:monster-selected
295
+ * @fires Monster.Components.Form.event:monster-change
296
+ * @fires Monster.Components.Form.event:monster-changed
297
+ */
298
+ class Select extends CustomControl {
299
+ /**
300
+ * @extends CustomControl
301
+ */
302
+ constructor() {
303
+ super();
304
+ initOptionObserver.call(this);
305
+ }
306
+
307
+ /**
308
+ * This method is called by the `instanceof` operator.
309
+ * @returns {symbol}
310
+ * @since 2.1.0
311
+ */
312
+ static get [instanceSymbol]() {
313
+ return Symbol.for("@schukai/component-form/select@@instance");
314
+ }
315
+
316
+ /**
317
+ * The current selection of the Select
318
+ *
319
+ * ```
320
+ * e = document.querySelector('monster-select');
321
+ * console.log(e.value)
322
+ * // ↦ 1
323
+ * // ↦ ['1','2']
324
+ * ```
325
+ *
326
+ * @property {string|array}
327
+ */
328
+ get value() {
329
+ return convertSelectionToValue.call(this, this.getOption("selection"));
330
+ }
331
+
332
+ /**
333
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals}
334
+ * @return {boolean}
335
+ */
336
+ static get formAssociated() {
337
+ return true;
338
+ }
339
+
340
+ /**
341
+ * Set selection
342
+ *
343
+ * ```
344
+ * e = document.querySelector('monster-select');
345
+ * e.value=1
346
+ * ```
347
+ *
348
+ * @property {string|array} value
349
+ * @since 1.2.0
350
+ * @throws {Error} unsupported type
351
+ */
352
+ set value(value) {;
353
+
354
+ const result = convertValueToSelection.call(this, value);
355
+ setSelection
356
+ .call(this, result.selection)
357
+ .then(() => {})
358
+ .catch((e) => {
359
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
360
+ });
361
+ }
362
+
363
+ /**
364
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
365
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
366
+ *
367
+ * The individual configuration values can be found in the table.
368
+ *
369
+ * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown
370
+ * @property {boolean} delegatesFocus=false lorem [see mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus)
371
+ * @property {Object[]} options Selection of key identifier pairs available for selection and displayed in the dropdown.
372
+ * @property {string} options[].label Label
373
+ * @property {string} options[].value Value
374
+ * @property {string} options[].visibility hidden or visible
375
+ * @property {Array} selection Selected options
376
+ * @property {Integer} showMaxOptions=10 Maximum number of visible options before a scroll bar should be displayed.
377
+ * @property {string} type=radio Multiple (checkbox) or single selection (radio)
378
+ * @property {string} name=(random id) Name of the form field
379
+ * @property {string} url Load options from server per url
380
+ * @property {Object} fetch Fetch [see Using Fetch mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
381
+ * @property {String} fetch.redirect=error
382
+ * @property {String} fetch.method=GET
383
+ * @property {String} fetch.mode=same-origin
384
+ * @property {String} fetch.credentials=same-origin
385
+ * @property {Object} fetch.headers={"accept":"application/json"}}
386
+ * @property {Object} labels
387
+ * @property {string} labels.cannot-be-loaded cannot be loaded
388
+ * @property {string} labels.no-options-available no options available
389
+ * @property {string} labels.select-an-option select an option
390
+ * @property {string} labels.no-option no option in the list, maybe you have to change the filter
391
+ * @property {Object} features List with features
392
+ * @property {Boolean} features.clearAll=true Display of a delete button to delete the entire selection
393
+ * @property {Boolean} features.clear=true Display of a delete key for deleting the specific selection
394
+ * @property {Boolean} features.loadOnOpen=false Load options when opening the dropdown
395
+ * @property {Boolean} filter.defaultValue=* Default filter value, if the filter is empty
396
+ * @property {Boolean} filter.mode=options Filter mode, values: options, remote, disabled
397
+ * @property {Object} templates Template definitions
398
+ * @property {string} templates.main Main template
399
+ * @property {string} templateMapping Mapping of the template placeholders
400
+ * @property {string} templateMapping.selected Selected Template
401
+ * @property {Object} popper [PopperJS Options](https://popper.js.org/docs/v2/)
402
+ * @property {string} popper.placement=bottom PopperJS placement
403
+ * @property {Object[]} modifiers={name:offset} PopperJS placement
404
+ * @property {Object} mapping
405
+ * @property {String} mapping.selector=* Path to select the appropriate entries
406
+ * @property {String} mapping.labelTemplate="" template with the label placeholders in the form ${name}, where name is the key (**)
407
+ * @property {String} mapping.valueTemplate="" template with the value placeholders in the form ${name}, where name is the key
408
+ * @property {Monster.Components.Form~exampleFilterCallback|undefined} mapping.filter Filtering of values via a function
409
+ * @property {Object} formatter
410
+ * @property {Monster.Components.Form~formatterSelectionCallback|undefined} formatter.selection format selection label
411
+ */
412
+ get defaults() {
413
+ return Object.assign(
414
+ {},
415
+ super.defaults,
416
+ {
417
+ toggleEventType: ["click", "touch"],
418
+ delegatesFocus: false,
419
+ options: [],
420
+ selection: [],
421
+ showMaxOptions: 10,
422
+ type: "radio",
423
+ name: new ID("s").toString(),
424
+ features: {
425
+ clearAll: true,
426
+ clear: true,
427
+ loadOnOpen: false,
428
+ },
429
+ url: null,
430
+ labels: {
431
+ "cannot-be-loaded": "Cannot be loaded",
432
+ "no-options-available": "No options available",
433
+ "select-an-option": "Select an option",
434
+ "summary-text": {
435
+ zero: "No entries were selected",
436
+ one: '<span class="monster-badge-primary-pill">1</span> entry was selected',
437
+ other:
438
+ '<span class="monster-badge-primary-pill">${count}</span> entries were selected',
439
+ },
440
+ "no-options":
441
+ "Unfortunately, there are no options available in the list.",
442
+ "no-options-found":
443
+ "No options are available in the list. Please consider modifying the filter.",
444
+ },
445
+ messages: {
446
+ control: null,
447
+ selected: null,
448
+ emptyOptions: null,
449
+ },
450
+ fetch: {
451
+ redirect: "error",
452
+ method: "GET",
453
+ mode: "same-origin",
454
+ credentials: "same-origin",
455
+ headers: {
456
+ accept: "application/json",
457
+ },
458
+ },
459
+ filter: {
460
+ defaultValue: "*",
461
+ mode: "disabled",
462
+ position: "inline",
463
+ },
464
+ classes: {
465
+ badge: "monster-badge-primary",
466
+ statusOrRemoveBadge: "empty",
467
+ },
468
+ mapping: {
469
+ selector: "*",
470
+ labelTemplate: "",
471
+ valueTemplate: "",
472
+ filter: null,
473
+ },
474
+ formatter: {
475
+ selection: buildSelectionLabel,
476
+ },
477
+ templates: {
478
+ main: getTemplate(),
479
+ },
480
+ templateMapping: {
481
+ /** with the attribute `data-monster-selected-template` the template for the selected options can be defined. */
482
+ selected: getSelectionTemplate(),
483
+ },
484
+
485
+ popper: {
486
+ placement: "bottom",
487
+ middleware: ["flip", "offset:1"],
488
+ },
489
+ },
490
+ initOptionsFromArguments.call(this),
491
+ );
492
+ }
493
+
494
+ /**
495
+ *
496
+ * @return {Monster.Components.Form.Select}
497
+ */
498
+ [assembleMethodSymbol]() {
499
+ const self = this;
500
+ super[assembleMethodSymbol]();
501
+
502
+ initControlReferences.call(self);
503
+ initEventhandler.call(self);
504
+
505
+ if (
506
+ self.getOption("url") !== null &&
507
+ self.getOption("features.loadOnOpen") !== true
508
+ ) {
509
+ self
510
+ .fetch()
511
+ .then(() => {
512
+ let result;
513
+ if (self.hasAttribute("value")) {
514
+ result = setSelection.call(self, self.getAttribute("value"));
515
+ } else {
516
+ result = setSelection.call(self, []);
517
+ }
518
+
519
+ result
520
+ .then(() => {})
521
+ .catch((e) => {
522
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
523
+ });
524
+ })
525
+ .catch((e) => {
526
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
527
+ throw e;
528
+ });
529
+ }
530
+
531
+ let lastValue = self.value;
532
+ self[internalSymbol].attachObserver(
533
+ new Observer(function () {
534
+ if (isObject(this) && this instanceof ProxyObserver) {
535
+ const n = this.getSubject()?.options?.value;
536
+
537
+ if (lastValue !== n) {
538
+ lastValue = n;
539
+ setSelection
540
+ .call(self, n)
541
+ .then(() => {})
542
+ .catch((e) => {
543
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `${e}`);
544
+ });
545
+ }
546
+ }
547
+ }),
548
+ );
549
+
550
+ areOptionsAvailableAndInit.call(self);
551
+
552
+ return this;
553
+ }
554
+
555
+ /**
556
+ * The Button.click() method simulates a click on the internal button element.
557
+ *
558
+ * @since 3.27.0
559
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click}
560
+ */
561
+ click() {;
562
+ if (this.getOption("disabled") === true) {
563
+ return;
564
+ }
565
+
566
+ toggle.call(this);
567
+ }
568
+
569
+ /**
570
+ * The Button.focus() method sets focus on the internal button element.
571
+ *
572
+ * @since 3.27.0
573
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus}
574
+ */
575
+ focus(options) {;
576
+ if (this.getOption("disabled") === true) {
577
+ return;
578
+ }
579
+
580
+ new Processing(() => {
581
+ gatherState.call(this);
582
+ focusFilter.call(this, options);
583
+ })
584
+ .run()
585
+ .catch((e) => {
586
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
587
+ });
588
+ }
589
+
590
+ /**
591
+ * The Button.blur() method removes focus from the internal button element.
592
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur
593
+ */
594
+ blur() {;
595
+ new Processing(() => {
596
+ gatherState.call(this);
597
+ blurFilter.call(this);
598
+ })
599
+ .run()
600
+ .catch((e) => {
601
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
602
+ });
603
+ }
604
+
605
+ /**
606
+ * If no url is specified, the options are taken from the Component itself.
607
+ *
608
+ * @param {string|URL} url URL to fetch the options
609
+ * @return {Promise}
610
+ */
611
+ fetch(url) {;
612
+
613
+ if (url instanceof URL) {
614
+ url = url.toString();
615
+ }
616
+
617
+ if (url !== undefined && url !== null) {
618
+ url = validateString(url);
619
+ }
620
+
621
+ return fetchData.call(this, url).then((map) => {
622
+ if (
623
+ isObject(map) ||
624
+ isArray(map) | (map instanceof Set) ||
625
+ map instanceof Map
626
+ ) {
627
+ this.importOptions(map);
628
+ }
629
+ });
630
+ }
631
+
632
+ /**
633
+ * @return {void}
634
+ */
635
+ connectedCallback() {
636
+ super.connectedCallback();
637
+ const document = getDocument();;
638
+
639
+ for (const [, type] of Object.entries(["click", "touch"])) {
640
+ // close on outside ui-events
641
+ document.addEventListener(type, this[closeEventHandler]);
642
+ }
643
+
644
+ parseSlotsToOptions.call(this);
645
+ attachResizeObserver.call(this);
646
+ updatePopper.call(this);
647
+
648
+ new Processing(() => {
649
+ gatherState.call(this);
650
+ focusFilter.call(this);
651
+ }).run();
652
+ }
653
+
654
+ /**
655
+ * @return {void}
656
+ */
657
+ disconnectedCallback() {
658
+ super.disconnectedCallback();
659
+ const document = getDocument();;
660
+
661
+ // close on outside ui-events
662
+ for (const [, type] of Object.entries(["click", "touch"])) {
663
+ document.removeEventListener(type, this[closeEventHandler]);
664
+ }
665
+
666
+ disconnectResizeObserver.call(this);
667
+ }
668
+
669
+ /**
670
+ * Import Select Options from dataset
671
+ * Not to be confused with the control defaults/options
672
+ *
673
+ * @since 0.16.0
674
+ * @param {array|object|Map|Set} data
675
+ * @return {Select}
676
+ * @throws {Error} map is not iterable
677
+ * @throws {Error} missing label configuration
678
+ */
679
+ importOptions(data) {;
680
+
681
+ const mappingOptions = this.getOption("mapping", {});
682
+ const selector = mappingOptions?.["selector"];
683
+ const labelTemplate = mappingOptions?.["labelTemplate"];
684
+ const valueTemplate = mappingOptions?.["valueTemplate"];
685
+ const filter = mappingOptions?.["filter"];
686
+
687
+ let flag = false;
688
+ if (labelTemplate === "") {
689
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty label template");
690
+ flag = true;
691
+ }
692
+
693
+ if (valueTemplate === "") {
694
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, "empty value template");
695
+ flag = true;
696
+ }
697
+
698
+ if (flag === true) {
699
+ throw new Error("missing label configuration");
700
+ }
701
+
702
+ const map = buildMap(data, selector, labelTemplate, valueTemplate, filter);
703
+
704
+ const options = [];
705
+ if (!isIterable(map)) {
706
+ throw new Error("map is not iterable");
707
+ }
708
+
709
+ const visibility = "visible";
710
+
711
+ map.forEach((label, value) => {
712
+ options.push({
713
+ value,
714
+ label,
715
+ visibility,
716
+ });
717
+ });
718
+
719
+ runAsOptionLengthChanged.call(this, map.size);
720
+ this.setOption("options", options);
721
+
722
+ fireCustomEvent(this, "monster-options-set", {
723
+ options,
724
+ });
725
+
726
+ return this;
727
+ }
728
+
729
+ /**
730
+ * @private
731
+ * @return {Monster.Components.Form.Select}
732
+ */
733
+ calcAndSetOptionsDimension() {
734
+ calcAndSetOptionsDimension.call(this);
735
+ return this;
736
+ }
737
+
738
+ /**
739
+ *
740
+ * @return {string}
741
+ */
742
+ static getTag() {
743
+ return "monster-select";
744
+ }
745
+
746
+ /**
747
+ *
748
+ * @return {CSSStyleSheet[]}
749
+ */
750
+ static getCSSStyleSheet() {
751
+ return [SelectStyleSheet];
752
+ }
753
+ }
754
+
755
+ /**
756
+ * This attribute can be used to pass a URL to this select.
757
+ *
758
+ * ```
759
+ * <monster-select data-monster-url="https://example.com/"></monster-select>
760
+ * ```
761
+ *
762
+ * @private
763
+ * @return {object}
764
+ */
765
+ function initOptionsFromArguments() {;
766
+ const options = {};
767
+
768
+ const template = this.getAttribute("data-monster-selected-template");
769
+ if (isString(template)) {
770
+ if (!options["templateMapping"]) options["templateMapping"] = {};
771
+
772
+ switch (template) {
773
+ case "summary":
774
+ case "default":
775
+ options["templateMapping"]["selected"] = getSummaryTemplate();
776
+ break;
777
+ case "selected":
778
+ options["templateMapping"]["selected"] = getSelectionTemplate();
779
+ break;
780
+ default:
781
+ addAttributeToken(
782
+ this,
783
+ ATTRIBUTE_ERRORMESSAGE,
784
+ "invalid template, use summary or selected",
785
+ );
786
+ }
787
+ }
788
+
789
+ return options;
790
+ }
791
+
792
+ /**
793
+ * @private
794
+ */
795
+ function attachResizeObserver() {;
796
+
797
+ // against flickering
798
+ this[resizeObserverSymbol] = new ResizeObserver((entries) => {
799
+ if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
800
+ try {
801
+ this[timerCallbackSymbol].touch();
802
+ return;
803
+ } catch (e) {
804
+ delete this[timerCallbackSymbol];
805
+ }
806
+ }
807
+
808
+ this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
809
+ updatePopper.call(this);
810
+ delete this[timerCallbackSymbol];
811
+ });
812
+ });
813
+
814
+ this[resizeObserverSymbol].observe(this.parentElement);
815
+ }
816
+
817
+ function disconnectResizeObserver() {;
818
+ if (this[resizeObserverSymbol] instanceof ResizeObserver) {
819
+ this[resizeObserverSymbol].disconnect();
820
+ }
821
+ }
822
+
823
+ function getSelectionTemplate() {
824
+ return `<div data-monster-role="selection"
825
+ data-monster-insert="selection path:selection" role="search"
826
+ ><input type="text" role="searchbox"
827
+ part="inline-filter" name="inline-filter"
828
+ data-monster-role="filter"
829
+ autocomplete="off"
830
+ tabindex="0"
831
+ ><div data-monster-replace="path:messages.control"></div>
832
+ </div>`;
833
+ }
834
+
835
+ function getSummaryTemplate() {
836
+ return `<div data-monster-role="selection" role="search">
837
+ <input type="text" role="searchbox"
838
+ part="inline-filter" name="inline-filter"
839
+ data-monster-role="filter"
840
+ autocomplete="off"
841
+ tabindex="0"
842
+ >
843
+ <div data-monster-replace="path:messages.selected"></div>
844
+ </div>`;
845
+ }
846
+
847
+ /**
848
+ * @return {void}
849
+ * @private
850
+ */
851
+ function parseSlotsToOptions() {;
852
+
853
+ let options = this.getOption("options");
854
+ if (!isIterable(options)) {
855
+ options = [];
856
+ }
857
+
858
+ let counter = 1;
859
+ getSlottedElements.call(this, "div").forEach((node) => {
860
+ let value = String(counter++);
861
+ let visibility = "visible";
862
+
863
+ if (node.hasAttribute("data-monster-value")) {
864
+ value = node.getAttribute("data-monster-value");
865
+ }
866
+
867
+ if (node.style.display === "none") {
868
+ visibility = "hidden";
869
+ }
870
+
871
+ const label = node.outerHTML;
872
+
873
+ options.push({
874
+ value,
875
+ label,
876
+ visibility,
877
+ });
878
+ });
879
+
880
+ runAsOptionLengthChanged.call(this, options.length);
881
+ this.setOption("options", options);
882
+ }
883
+
884
+ /**
885
+ * wait until all options are finished rendering
886
+ *
887
+ * @private
888
+ * @param {int} targetLength
889
+ */
890
+ function runAsOptionLengthChanged(targetLength) {
891
+ const self = this;
892
+
893
+ if (!self[optionsElementSymbol]) {
894
+ return;
895
+ }
896
+
897
+ const callback = function (mutationsList, observer) {
898
+ const run = false;
899
+ for (const mutation of mutationsList) {
900
+ if (mutation.type === "childList") {
901
+ const run = true;
902
+ break;
903
+ }
904
+ }
905
+
906
+ if (run === true) {
907
+ const nodes = self[optionsElementSymbol].querySelectorAll(
908
+ `div[${ATTRIBUTE_ROLE}=option]`,
909
+ );
910
+
911
+ if (nodes.length === targetLength) {
912
+ checkOptionState.call(self);
913
+ observer.disconnect();
914
+ }
915
+ }
916
+ };
917
+
918
+ const observer = new MutationObserver(callback);
919
+ observer.observe(self[optionsElementSymbol], {
920
+ attributes: false,
921
+ childList: true,
922
+ subtree: true,
923
+ });
924
+ }
925
+
926
+ /**
927
+ * @private
928
+ * @param {*} value
929
+ * @return {*}
930
+ */
931
+ function buildSelectionLabel(value) {;
932
+ const options = this.getOption("options");
933
+
934
+ for (let i = 0; i < options.length; i++) {
935
+ const o = options?.[i];
936
+ if (isObject(o) && o?.["value"] === value) {
937
+ return o?.["label"];
938
+ } else if (isPrimitive(o) && o === value) {
939
+ return o;
940
+ }
941
+ }
942
+
943
+ return undefined;
944
+ }
945
+
946
+ /**
947
+ * @private
948
+ * @param {*} value
949
+ * @return {string}
950
+ * @throws {Error} no value found
951
+ */
952
+ function getSelectionLabel(value) {;
953
+
954
+ const callback = this.getOption("formatter.selection");
955
+ if (isFunction(callback)) {
956
+ const label = callback.call(this, value);
957
+ if (isString(label)) return label;
958
+ }
959
+
960
+ if (isString(value) || isInteger(value)) {
961
+ return `${value}`;
962
+ }
963
+
964
+ return this.getOption("labels.cannot-be-loaded", value);
965
+ }
966
+
967
+ /**
968
+ * @private
969
+ * @param {Event} event
970
+ */
971
+ function handleToggleKeyboardEvents(event) {;
972
+
973
+ switch (event?.["code"]) {
974
+ case "Escape":
975
+ toggle.call(this);
976
+ event.preventDefault();
977
+ break;
978
+ case "Space":
979
+ toggle.call(this);
980
+ event.preventDefault();
981
+ break;
982
+ }
983
+ }
984
+
985
+ /**
986
+ * @license AGPLv3
987
+ * @since 1.15.0
988
+ * @private
989
+ * @this CustomElement
990
+ */
991
+ function initOptionObserver() {
992
+ const self = this;
993
+
994
+ self.attachObserver(
995
+ new Observer(function () {
996
+ new Processing(() => {
997
+ try {
998
+ self.updateI18n();
999
+ } catch (e) {}
1000
+ try {
1001
+ areOptionsAvailableAndInit.call(self);
1002
+ } catch (e) {}
1003
+
1004
+ setSummaryAndControlText.call(self);
1005
+ }).run();
1006
+ }),
1007
+ );
1008
+ }
1009
+
1010
+ function getDefaultTranslation() {;
1011
+
1012
+ const translation = new Translations("en").assignTranslations(
1013
+ this.getOption("labels", {}),
1014
+ );
1015
+
1016
+ try {
1017
+ const doc = getDocumentTranslations();
1018
+ translation.locale = doc.locale;
1019
+ } catch (e) {}
1020
+
1021
+ return translation;
1022
+ }
1023
+
1024
+ /**
1025
+ * @private
1026
+ * @returns {string|*}
1027
+ */
1028
+ function setSummaryAndControlText() {;
1029
+
1030
+ const translations = getDefaultTranslation.call(this);
1031
+ const selections = this.getOption("selection");
1032
+
1033
+ const text = translations.getPluralRuleText(
1034
+ "summary-text",
1035
+ selections.length,
1036
+ "",
1037
+ );
1038
+
1039
+ const selectedText = new Formatter({
1040
+ count: String(selections.length),
1041
+ }).format(text);
1042
+
1043
+ this.setOption("messages.selected", selectedText);
1044
+
1045
+ const current = this.getOption("messages.control");
1046
+ const msg = this.getOption("labels.select-an-option");
1047
+
1048
+ if (
1049
+ current === "" ||
1050
+ current === undefined ||
1051
+ current === msg ||
1052
+ current === null
1053
+ ) {
1054
+ if (selections === undefined || selections.length === 0) {
1055
+ this.setOption("messages.control", msg);
1056
+ } else {
1057
+ this.setOption("messages.control", "");
1058
+ }
1059
+ }
1060
+ }
1061
+
1062
+ /**
1063
+ * @private
1064
+ * @return {NodeList}
1065
+ */
1066
+ function getOptionElements() {
1067
+ return this[optionsElementSymbol].querySelectorAll(
1068
+ `[${ATTRIBUTE_ROLE}=option]`,
1069
+ );
1070
+ }
1071
+
1072
+ /**
1073
+ * With the help of this filter callback, values can be filtered out. Only if the filter function returns true, the value is taken for the map.
1074
+ *
1075
+ * @callback Monster.Components.Form~exampleFilterCallback
1076
+ * @param {*} value Value
1077
+ * @param {string} key Key
1078
+ * @memberOf Monster.Components.Form
1079
+ * @see Monster.Data.buildMap
1080
+ */
1081
+
1082
+ /**
1083
+ *
1084
+ * @callback Monster.Components.Form~formatterSelectionCallback
1085
+ * @param {*} value Value
1086
+ * @return {string|undefined}
1087
+ * @memberOf Monster.Components.Form
1088
+ * @see Monster.Data.buildMap
1089
+ */
1090
+
1091
+ /**
1092
+ * @private
1093
+ */
1094
+ function calcAndSetOptionsDimension() {;
1095
+
1096
+ const options = getOptionElements.call(this);
1097
+ const container = this[optionsElementSymbol];
1098
+ if (!(container instanceof HTMLElement && options instanceof NodeList)) {
1099
+ return;
1100
+ }
1101
+
1102
+ let visible = 0;
1103
+ let optionHeight = 0;
1104
+ const max = this.getOption("showMaxOptions", 10);
1105
+
1106
+ let scrollFlag = false;
1107
+ for (const [, option] of Object.entries(options)) {
1108
+ const computedStyle = getGlobal().getComputedStyle(option);
1109
+ if (computedStyle.display === "none") continue;
1110
+
1111
+ let h = option.getBoundingClientRect().height;
1112
+ h += parseInt(computedStyle.getPropertyValue("margin-top"), 10);
1113
+ h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10);
1114
+ optionHeight = Math.max(optionHeight, h);
1115
+
1116
+ visible++;
1117
+ if (visible > max) {
1118
+ break;
1119
+ }
1120
+ }
1121
+
1122
+ if (visible > max) {
1123
+ visible = max;
1124
+ scrollFlag = true;
1125
+ }
1126
+
1127
+ if (visible === 0) {
1128
+ if (this.getOption("options").length === 0) {
1129
+ this.setOption(
1130
+ "messages.emptyOptions",
1131
+ this.getOption("labels.no-options-available"),
1132
+ );
1133
+ } else {
1134
+ this.setOption(
1135
+ "messages.emptyOptions",
1136
+ this.getOption("labels.no-options-found"),
1137
+ );
1138
+ }
1139
+ this[noOptionsAvailableElementSymbol].classList.remove("d-none");
1140
+ } else {
1141
+ this[noOptionsAvailableElementSymbol].classList.add("d-none");
1142
+ }
1143
+
1144
+ const styles = getGlobal().getComputedStyle(this[optionsElementSymbol]);
1145
+ let padding = parseInt(styles.getPropertyValue("padding-top"), 10);
1146
+ padding += parseInt(styles.getPropertyValue("padding-bottom"), 10);
1147
+
1148
+ let margin = parseInt(styles.getPropertyValue("margin-top"), 10);
1149
+ margin += parseInt(styles.getPropertyValue("margin-bottom"), 10);
1150
+
1151
+ const containerHeight = optionHeight * visible + padding + margin;
1152
+ container.style.height = `${containerHeight}px`;
1153
+
1154
+ if (scrollFlag === true) {
1155
+ container.style.overflowY = "scroll";
1156
+ } else {
1157
+ container.style.overflowY = "auto";
1158
+ }
1159
+
1160
+ const domRect = this[controlElementSymbol].getBoundingClientRect();
1161
+
1162
+ this[popperElementSymbol].style.width = `${domRect.width}px`;
1163
+ container.style.overflowX = "auto";
1164
+ }
1165
+
1166
+ /**
1167
+ * @private
1168
+ * @param {number} direction
1169
+ * @throws {Error} no shadow-root is defined
1170
+ */
1171
+ function activateCurrentOption(direction) {;
1172
+
1173
+ if (!this.shadowRoot) {
1174
+ throw new Error("no shadow-root is defined");
1175
+ }
1176
+
1177
+ let focused = this.shadowRoot.querySelector(`[${ATTRIBUTE_PREFIX}focused]`);
1178
+
1179
+ if (
1180
+ !(focused instanceof HTMLElement) ||
1181
+ focused.matches("[data-monster-visibility=hidden]")
1182
+ ) {
1183
+ for (const [, e] of Object.entries(
1184
+ this.shadowRoot.querySelectorAll(`[${ATTRIBUTE_ROLE}=option]`),
1185
+ )) {
1186
+ if (e.matches("[data-monster-visibility=visible]")) {
1187
+ focused = e;
1188
+ break;
1189
+ }
1190
+ }
1191
+ } else {
1192
+ if (direction === FOCUS_DIRECTION_DOWN) {
1193
+ while (focused.nextSibling) {
1194
+ focused = focused.nextSibling;
1195
+
1196
+ if (
1197
+ focused instanceof HTMLElement &&
1198
+ focused.hasAttribute(ATTRIBUTE_ROLE) &&
1199
+ focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1200
+ focused.matches("[data-monster-visibility=visible]") &&
1201
+ focused.matches(":not([data-monster-filtered=true])")
1202
+ ) {
1203
+ break;
1204
+ }
1205
+ }
1206
+ } else {
1207
+ while (focused.previousSibling) {
1208
+ focused = focused.previousSibling;
1209
+
1210
+ if (
1211
+ focused instanceof HTMLElement &&
1212
+ focused.hasAttribute(ATTRIBUTE_ROLE) &&
1213
+ focused.getAttribute(ATTRIBUTE_ROLE) === "option" &&
1214
+ focused.matches("[data-monster-visibility=visible]") &&
1215
+ focused.matches(":not([data-monster-filtered=true])")
1216
+ ) {
1217
+ break;
1218
+ }
1219
+ }
1220
+ }
1221
+ }
1222
+
1223
+ new Processing(() => {
1224
+ if (focused instanceof HTMLElement) {
1225
+ this.shadowRoot
1226
+ .querySelectorAll(`[${ATTRIBUTE_PREFIX}focused]`)
1227
+ .forEach((e) => {
1228
+ e.removeAttribute(`${ATTRIBUTE_PREFIX}focused`);
1229
+ });
1230
+
1231
+ focused.focus();
1232
+ focused.setAttribute(`${ATTRIBUTE_PREFIX}focused`, true);
1233
+ }
1234
+ }).run();
1235
+ }
1236
+
1237
+ /**
1238
+ * @private
1239
+ */
1240
+ function filterOptions() {;
1241
+
1242
+ new Processing(() => {
1243
+ let filterValue;
1244
+
1245
+ switch (this.getOption("filter.position")) {
1246
+ case FILTER_POSITION_INLINE:
1247
+ if (this[inlineFilterElementSymbol] instanceof HTMLElement) {
1248
+ filterValue = this[inlineFilterElementSymbol].value.toLowerCase();
1249
+ } else {
1250
+ return;
1251
+ }
1252
+
1253
+ break;
1254
+ case FILTER_POSITION_POPPER:
1255
+ default:
1256
+ if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
1257
+ filterValue = this[popperFilterElementSymbol].value.toLowerCase();
1258
+ } else {
1259
+ return;
1260
+ }
1261
+ }
1262
+
1263
+ const options = this.getOption("options");
1264
+ for (const [i, option] of Object.entries(options)) {
1265
+ if (option.label.toLowerCase().indexOf(filterValue) === -1) {
1266
+ this.setOption(`options.${i}.filtered`, "true");
1267
+ } else {
1268
+ this.setOption(`options.${i}.filtered`, undefined);
1269
+ }
1270
+ }
1271
+ })
1272
+ .run()
1273
+ .then(() => {
1274
+ new Processing(10, () => {
1275
+ calcAndSetOptionsDimension.call(this);
1276
+ focusFilter.call(this);
1277
+ }).run();
1278
+ })
1279
+ .catch((e) => {
1280
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1281
+ });
1282
+ }
1283
+
1284
+ /**
1285
+ * @private
1286
+ * @param {Event} event
1287
+ */
1288
+ function handleFilterKeyboardEvents(event) {;
1289
+
1290
+ const shiftKey = event?.["shiftKey"];
1291
+
1292
+ switch (event?.["code"]) {
1293
+ case "Tab":
1294
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1295
+ event.preventDefault();
1296
+ break;
1297
+ case "Escape":
1298
+ toggle.call(this);
1299
+ event.preventDefault();
1300
+ break;
1301
+ case "Tab" && shiftKey === true:
1302
+ case "ArrowUp":
1303
+ activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1304
+ event.preventDefault();
1305
+ break;
1306
+ case "Tab" && !shiftKey:
1307
+ case "ArrowDown":
1308
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1309
+ event.preventDefault();
1310
+ break;
1311
+ default:
1312
+ if (this.getOption("filter.mode") !== FILTER_MODE_REMOTE) {
1313
+ filterOptions.call(this);
1314
+ } else {
1315
+ filterFromRemote.call(this).catch((e) => {
1316
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1317
+ });
1318
+ }
1319
+ }
1320
+ }
1321
+
1322
+ /**
1323
+ * @private
1324
+ */
1325
+ function filterFromRemote() {;
1326
+
1327
+ if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) {
1328
+ return;
1329
+ }
1330
+
1331
+ const optionUrl = this.getOption("url");
1332
+ if (!optionUrl) {
1333
+ addAttributeToken(
1334
+ this,
1335
+ ATTRIBUTE_ERRORMESSAGE,
1336
+ "Missing URL for Remote Filter.",
1337
+ );
1338
+ return;
1339
+ }
1340
+
1341
+ return new Processing(() => {
1342
+ const filterValue = encodeURI(
1343
+ this[inlineFilterElementSymbol].value.toLowerCase(),
1344
+ );
1345
+ let url = optionUrl;
1346
+ if (filterValue.length > 0) {
1347
+ url = new Formatter({ filter: filterValue }).format(optionUrl);
1348
+ }
1349
+
1350
+ this
1351
+ .fetch(url)
1352
+ .then(() => {
1353
+ checkOptionState.call(this);
1354
+ })
1355
+ .catch((e) => {
1356
+ throw e;
1357
+ });
1358
+ }).run();
1359
+ }
1360
+
1361
+ /**
1362
+ *
1363
+ * @param {Event} event
1364
+ * @private
1365
+ */
1366
+ function handleOptionKeyboardEvents(event) {;
1367
+
1368
+ const shiftKey = event?.["shiftKey"];
1369
+
1370
+ switch (event?.["code"]) {
1371
+ case "Escape":
1372
+ toggle.call(this);
1373
+ event.preventDefault();
1374
+ break;
1375
+ case "Enter":
1376
+ case "Space":
1377
+ const path = event.composedPath();
1378
+ const element = path?.[0];
1379
+
1380
+ fireEvent(element.getElementsByTagName("input"), "click");
1381
+ event.preventDefault();
1382
+ break;
1383
+
1384
+ case "Tab" && shiftKey === true:
1385
+ case "ArrowUp":
1386
+ activateCurrentOption.call(this, FOCUS_DIRECTION_UP);
1387
+ event.preventDefault();
1388
+ break;
1389
+
1390
+ case "Tab" && !shiftKey:
1391
+ case "ArrowLeft":
1392
+ case "ArrowRight":
1393
+ // handled by tree select
1394
+ break;
1395
+ case "ArrowDown":
1396
+ activateCurrentOption.call(this, FOCUS_DIRECTION_DOWN);
1397
+ event.preventDefault();
1398
+ break;
1399
+ default:
1400
+ const p = event.composedPath();
1401
+ if (p?.[0] instanceof HTMLInputElement) {
1402
+ return;
1403
+ }
1404
+ focusFilter.call(this);
1405
+ break;
1406
+ }
1407
+ }
1408
+
1409
+ /**
1410
+ * @private
1411
+ * @returns {string}
1412
+ */
1413
+ function getFilterMode() {;
1414
+
1415
+ switch (this.getOption("filter.mode")) {
1416
+ case FILTER_MODE_OPTIONS:
1417
+ return FILTER_MODE_OPTIONS;
1418
+ case FILTER_MODE_REMOTE:
1419
+ return FILTER_MODE_REMOTE;
1420
+ default:
1421
+ return FILTER_MODE_DISABLED;
1422
+ }
1423
+ }
1424
+
1425
+ /**
1426
+ * @private
1427
+ */
1428
+ function blurFilter() {;
1429
+
1430
+ if (!(this[inlineFilterElementSymbol] instanceof HTMLElement)) {
1431
+ return;
1432
+ }
1433
+
1434
+ if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1435
+ return;
1436
+ }
1437
+
1438
+ this[popperFilterContainerElementSymbol].classList.remove("active");
1439
+ this[popperFilterContainerElementSymbol].blur();
1440
+
1441
+ this[inlineFilterElementSymbol].classList.remove("active");
1442
+ this[inlineFilterElementSymbol].blur();
1443
+ }
1444
+
1445
+ /**
1446
+ * @private
1447
+ * @param focusOptions
1448
+ */
1449
+ function focusPopperFilter(focusOptions) {;
1450
+
1451
+ this[popperFilterContainerElementSymbol].classList.remove("d-none");
1452
+ this[popperFilterElementSymbol].classList.add("active");
1453
+ this[inlineFilterElementSymbol].classList.remove("active");
1454
+ this[inlineFilterElementSymbol].classList.add("d-none");
1455
+
1456
+ if (!(this[popperFilterElementSymbol] instanceof HTMLElement)) {
1457
+ addAttributeToken(
1458
+ this,
1459
+ ATTRIBUTE_ERRORMESSAGE,
1460
+ "Missing Popper Filter Element.",
1461
+ );
1462
+ return;
1463
+ }
1464
+
1465
+ // visibility is set to visible, because focus() does not work on invisible elements
1466
+ // and the class definition is assigned later in the processing
1467
+ setTimeout(() => {
1468
+ if (focusOptions === undefined || focusOptions === null) {
1469
+ this[popperFilterElementSymbol].focus();
1470
+ } else {
1471
+ this[popperFilterElementSymbol].focus(focusOptions);
1472
+ }
1473
+ }, 100);
1474
+ }
1475
+
1476
+ /**
1477
+ * @private
1478
+ * @param focusOptions
1479
+ */
1480
+ function focusInlineFilter(focusOptions) {;
1481
+
1482
+ const options = this.getOption("options");
1483
+ if (
1484
+ (!isArray(options) || options.length === 0) &&
1485
+ this.getOption("filter.mode") !== FILTER_MODE_REMOTE
1486
+ ) {
1487
+ return;
1488
+ }
1489
+
1490
+ this[popperFilterContainerElementSymbol].classList.add("d-none");
1491
+ this[inlineFilterElementSymbol].classList.add("active");
1492
+ this[inlineFilterElementSymbol].classList.remove("d-none");
1493
+
1494
+ // visibility is set to visible, because focus() does not work on invisible elements
1495
+ // and the class definition is assigned later in the processing
1496
+ setTimeout(() => {
1497
+ if (focusOptions === undefined || focusOptions === null) {
1498
+ this[inlineFilterElementSymbol].focus();
1499
+ } else {
1500
+ this[inlineFilterElementSymbol].focus(focusOptions);
1501
+ }
1502
+ }, 100);
1503
+ }
1504
+
1505
+ /**
1506
+ * @private
1507
+ */
1508
+ function focusFilter(focusOptions) {;
1509
+
1510
+ if (getFilterMode.call(this) === FILTER_MODE_DISABLED) {
1511
+ this[popperFilterContainerElementSymbol].classList.add("d-none");
1512
+ this[inlineFilterElementSymbol].classList.add("d-none");
1513
+ return;
1514
+ }
1515
+
1516
+ if (this.getOption("filter.position") === FILTER_POSITION_INLINE) {
1517
+ return focusInlineFilter.call(this, focusOptions);
1518
+ }
1519
+
1520
+ return focusPopperFilter.call(this, focusOptions);
1521
+ }
1522
+
1523
+ /**
1524
+ * @private
1525
+ * @return {array}
1526
+ * @throws {Error} no shadow-root is defined
1527
+ * @throws {Error} unsupported type
1528
+ */
1529
+ function gatherState() {;
1530
+
1531
+ const type = this.getOption("type");
1532
+ if (["radio", "checkbox"].indexOf(type) === -1) {
1533
+ throw new Error("unsupported type");
1534
+ }
1535
+
1536
+ if (!this.shadowRoot) {
1537
+ throw new Error("no shadow-root is defined");
1538
+ }
1539
+
1540
+ const selection = [];
1541
+ const elements = this.shadowRoot.querySelectorAll(
1542
+ `input[type=${type}]:checked`,
1543
+ );
1544
+ for (const e of elements) {
1545
+ selection.push({
1546
+ label: getSelectionLabel.call(this, e.value),
1547
+ value: e.value,
1548
+ });
1549
+ }
1550
+
1551
+ setSelection
1552
+ .call(this, selection)
1553
+ .then(() => {})
1554
+ .catch((e) => {
1555
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1556
+ });
1557
+
1558
+ return this;
1559
+ }
1560
+
1561
+ /**
1562
+ * @private
1563
+ * @throws {Error} no shadow-root is defined
1564
+ * @throws {Error} unsupported type
1565
+ */
1566
+ function clearSelection() {;
1567
+
1568
+ const type = this.getOption("type");
1569
+ if (["radio", "checkbox"].indexOf(type) === -1) {
1570
+ throw new Error("unsupported type");
1571
+ }
1572
+
1573
+ if (!this.shadowRoot) {
1574
+ throw new Error("no shadow-root is defined");
1575
+ }
1576
+
1577
+ setSelection
1578
+ .call(this, [])
1579
+ .then(() => {})
1580
+ .catch((e) => {
1581
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, `${e}`);
1582
+ });
1583
+ }
1584
+
1585
+ /**
1586
+ * @private
1587
+ */
1588
+ function areOptionsAvailableAndInit() {;
1589
+
1590
+ // prevent multiple calls
1591
+ if (this[areOptionsAvailableAndInitSymbol] === undefined) {
1592
+ this[areOptionsAvailableAndInitSymbol] = 0;
1593
+ }
1594
+
1595
+ if (this[areOptionsAvailableAndInitSymbol] > 0) {
1596
+ this[areOptionsAvailableAndInitSymbol]--;
1597
+ return true;
1598
+ }
1599
+
1600
+ this[areOptionsAvailableAndInitSymbol]++;
1601
+
1602
+ const options = this.getOption("options");
1603
+
1604
+ if (
1605
+ options === undefined ||
1606
+ options === null ||
1607
+ (isArray(options) && options.length === 0)
1608
+ ) {
1609
+ setStatusOrRemoveBadges.call(this, "empty");
1610
+
1611
+ hide.call(this);
1612
+
1613
+ this.setOption(
1614
+ "messages.control",
1615
+ this.getOption("labels.no-options-available"),
1616
+ );
1617
+ this.setOption("messages.summary", "");
1618
+ this.setOption("selection", []);
1619
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1620
+ return false;
1621
+ }
1622
+
1623
+ const selections = this.getOption("selection");
1624
+ if (
1625
+ selections === undefined ||
1626
+ selections === null ||
1627
+ selections.length === 0
1628
+ ) {
1629
+ this.setOption(
1630
+ "messages.control",
1631
+ this.getOption("labels.select-an-option"),
1632
+ );
1633
+ } else {
1634
+ this.setOption("messages.control", "");
1635
+ }
1636
+
1637
+ this.setOption("messages.summary", setSummaryAndControlText.call(this));
1638
+
1639
+ let updated = false;
1640
+ let valueCounter = 1;
1641
+ for (const option of options) {
1642
+ if (option?.visibility === undefined) {
1643
+ option.visibility = "visible";
1644
+ updated = true;
1645
+ }
1646
+
1647
+ if (option?.value === undefined && option?.label === undefined) {
1648
+ option.value = `${valueCounter++}`;
1649
+ option.label = option.value;
1650
+ updated = true;
1651
+ continue;
1652
+ }
1653
+
1654
+ if (option?.value === undefined) {
1655
+ option.value = option.label;
1656
+ updated = true;
1657
+ }
1658
+
1659
+ if (option?.label === undefined) {
1660
+ option.label = option.value;
1661
+ updated = true;
1662
+ }
1663
+ }
1664
+
1665
+ if (updated) {
1666
+ this.setOption("options", options);
1667
+ }
1668
+
1669
+ setStatusOrRemoveBadges.call(this, "status");
1670
+
1671
+ removeAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, noOptionsAvailableMessage);
1672
+ return true;
1673
+ }
1674
+
1675
+ /**
1676
+ * @private
1677
+ * @throws {Error} no shadow-root is defined
1678
+ */
1679
+ function checkOptionState() {;
1680
+
1681
+ if (!this.shadowRoot) {
1682
+ throw new Error("no shadow-root is defined");
1683
+ }
1684
+
1685
+ const elements = this.shadowRoot.querySelectorAll(
1686
+ `[${ATTRIBUTE_ROLE}=option] input`,
1687
+ );
1688
+
1689
+ let selection = this.getOption("selection");
1690
+ if (!isArray(selection)) {
1691
+ selection = [];
1692
+ }
1693
+
1694
+ const checkedValues = selection.map((a) => {
1695
+ return a.value;
1696
+ });
1697
+
1698
+ for (const e of elements) {
1699
+ if (checkedValues.indexOf(e.value) !== -1) {
1700
+ if (e.checked !== true) e.checked = true;
1701
+ } else {
1702
+ if (e.checked !== false) e.checked = false;
1703
+ }
1704
+ }
1705
+ }
1706
+
1707
+ /**
1708
+ * @private
1709
+ * @param {*} value
1710
+ * @return {Object}
1711
+ */
1712
+ function convertValueToSelection(value) {;
1713
+ const selection = [];
1714
+
1715
+ if (isString(value)) {
1716
+ value = value
1717
+ .split(",")
1718
+ .map((a) => {
1719
+ return a.trim();
1720
+ })
1721
+ .filter((a) => {
1722
+ return a !== "";
1723
+ });
1724
+ }
1725
+
1726
+ if (isString(value) || isInteger(value)) {
1727
+ selection.push({
1728
+ label: getSelectionLabel.call(this, value),
1729
+ value: value,
1730
+ });
1731
+ } else if (isArray(value)) {
1732
+ for (const v of value) {
1733
+ selection.push({
1734
+ label: getSelectionLabel.call(this, v),
1735
+ value: v,
1736
+ });
1737
+ }
1738
+
1739
+ value = value.join(",");
1740
+ } else {
1741
+ throw new Error("unsupported type");
1742
+ }
1743
+
1744
+ return {
1745
+ selection: selection,
1746
+ value: value,
1747
+ };
1748
+ }
1749
+
1750
+ /**
1751
+ * @private
1752
+ * @param {array} selection
1753
+ * @return {string}
1754
+ */
1755
+ function convertSelectionToValue(selection) {;
1756
+
1757
+ const value = [];
1758
+
1759
+ if (isArray(selection)) {
1760
+ for (const obj of selection) {
1761
+ const v = obj?.["value"];
1762
+ if (v !== undefined) value.push(v);
1763
+ }
1764
+ }
1765
+
1766
+ if (value.length === 0) {
1767
+ return "";
1768
+ } else if (value.length === 1) {
1769
+ return value.pop();
1770
+ }
1771
+
1772
+ return value.join(",");
1773
+ }
1774
+
1775
+ /**
1776
+ * @private
1777
+ * @param {array} selection
1778
+ * @return {Promise}
1779
+ * @throws {Error} no shadow-root is defined
1780
+ */
1781
+ function setSelection(selection) {;
1782
+
1783
+ if (isString(selection)) {
1784
+ const result = convertValueToSelection.call(this, selection);
1785
+ selection = result?.selection;
1786
+ } else if (selection === undefined) {
1787
+ selection = [];
1788
+ }
1789
+
1790
+ this.setOption("selection", validateArray(selection));
1791
+ checkOptionState.call(this);
1792
+
1793
+ try {
1794
+ this?.setFormValue(this.value);
1795
+ } catch (e) {
1796
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1797
+ }
1798
+
1799
+ fireCustomEvent(this, "monster-selected", {
1800
+ selection,
1801
+ });
1802
+
1803
+ return new Processing(() => {
1804
+ const CLASSNAME = "selected";
1805
+
1806
+ if (!this.shadowRoot) {
1807
+ throw new Error("no shadow-root is defined");
1808
+ }
1809
+
1810
+ const notSelected = this.shadowRoot.querySelectorAll(":not(:checked)");
1811
+
1812
+ if (notSelected) {
1813
+ notSelected.forEach((node) => {
1814
+ const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
1815
+ if (parent) {
1816
+ parent.classList.remove(CLASSNAME);
1817
+ }
1818
+ });
1819
+ }
1820
+
1821
+ const selected = this.shadowRoot.querySelectorAll(":checked");
1822
+ if (selected) {
1823
+ selected.forEach((node) => {
1824
+ const parent = node.closest(`[${ATTRIBUTE_ROLE}=option]`);
1825
+ if (parent) {
1826
+ parent.classList.add(CLASSNAME);
1827
+ }
1828
+ });
1829
+ }
1830
+ }).run();
1831
+ }
1832
+
1833
+ /**
1834
+ * @private
1835
+ * @param {string} url
1836
+ * @return {Promise}
1837
+ * @throws {TypeError} the result cannot be parsed
1838
+ * @throws {TypeError} unsupported response
1839
+ */
1840
+ function fetchData(url) {;
1841
+
1842
+ if (!url) url = this.getOption("url");
1843
+ if (!url) return Promise.resolve();
1844
+
1845
+ const fetchOptions = this.getOption("fetch", {});
1846
+
1847
+ setStatusOrRemoveBadges.call(this, "loading");
1848
+ url = new Formatter({ filter: this.getOption("filter.defaultValue") }).format(
1849
+ url,
1850
+ );
1851
+
1852
+ const global = getGlobal();
1853
+ return global
1854
+ .fetch(url, fetchOptions)
1855
+ .then((response) => {
1856
+ const contentType = response.headers.get("content-type");
1857
+ if (contentType && contentType.indexOf("application/json") !== -1) {
1858
+ return response.text();
1859
+ }
1860
+
1861
+ throw new TypeError(`unsupported response ${contentType}`);
1862
+ })
1863
+ .then((text) => {
1864
+ try {
1865
+ return Promise.resolve(JSON.parse(String(text)));
1866
+ } catch (e) {
1867
+ throw new TypeError("the result cannot be parsed");
1868
+ }
1869
+ });
1870
+ }
1871
+
1872
+ /**
1873
+ * @private
1874
+ */
1875
+ function hide() {;
1876
+
1877
+ this[popperElementSymbol].style.display = "none";
1878
+ setStatusOrRemoveBadges.call(this, "status");
1879
+ removeAttributeToken(this[controlElementSymbol], "class", "open");
1880
+ }
1881
+
1882
+ /**
1883
+ * @private
1884
+ */
1885
+ function show() {;
1886
+
1887
+ if (this.getOption("disabled", undefined) === true) {
1888
+ return;
1889
+ }
1890
+
1891
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
1892
+ return;
1893
+ }
1894
+
1895
+ focusFilter.call(this);
1896
+ const optionsAvailable = areOptionsAvailableAndInit.call(this);
1897
+ const remoteFilterFlag = this.getOption("filter.mode") === FILTER_MODE_REMOTE;
1898
+
1899
+ if (optionsAvailable === false && remoteFilterFlag !== true) {
1900
+ const loadOnOpenFlag = this.getOption("features.loadOnOpen");
1901
+ if (loadOnOpenFlag === true) {
1902
+ this.setOption("features.loadOnOpen", false);
1903
+ this.setOption("classes.statusOrRemoveBadge", "loading");
1904
+ this.fetch().then(() => {
1905
+ show.call(this);
1906
+ });
1907
+ }
1908
+
1909
+ return;
1910
+ }
1911
+
1912
+ this[popperElementSymbol].style.visibility = "hidden";
1913
+ this[popperElementSymbol].style.display = STYLE_DISPLAY_MODE_BLOCK;
1914
+ setStatusOrRemoveBadges.call(this, "open");
1915
+
1916
+ addAttributeToken(this[controlElementSymbol], "class", "open");
1917
+
1918
+ new Processing(() => {
1919
+ calcAndSetOptionsDimension.call(this);
1920
+ focusFilter.call(this);
1921
+ this[popperElementSymbol].style.removeProperty("visibility");
1922
+ updatePopper.call(this);
1923
+ })
1924
+ .run()
1925
+ .catch((e) => {
1926
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.message);
1927
+ });
1928
+ }
1929
+
1930
+ /**
1931
+ * @private
1932
+ */
1933
+ function toggle() {
1934
+ if (this[popperElementSymbol].style.display === STYLE_DISPLAY_MODE_BLOCK) {
1935
+ hide.call(this);
1936
+ } else {
1937
+ show.call(this);
1938
+ }
1939
+ }
1940
+
1941
+ /**
1942
+ * @private
1943
+ * @fires Monster.Components.Form.event:monster-selection-removed
1944
+ * @fires Monster.Components.Form.event:monster-selection-cleared
1945
+ */
1946
+ function initEventhandler() {
1947
+ const self = this;
1948
+
1949
+ /**
1950
+ * @param {Event} event
1951
+ */
1952
+ self[clearOptionEventHandler] = (event) => {
1953
+ const element = findTargetElementFromEvent(
1954
+ event,
1955
+ ATTRIBUTE_ROLE,
1956
+ "remove-badge",
1957
+ );
1958
+ if (element instanceof HTMLElement) {
1959
+ const badge = findClosestByAttribute(element, ATTRIBUTE_ROLE, "badge");
1960
+ if (badge instanceof HTMLElement) {
1961
+ const value = badge.getAttribute(`${ATTRIBUTE_PREFIX}value`);
1962
+
1963
+ let selection = self.getOption("selection");
1964
+ selection = selection.filter((b) => {
1965
+ return value !== b.value;
1966
+ });
1967
+
1968
+ setSelection
1969
+ .call(self, selection)
1970
+ .then(() => {
1971
+ fireCustomEvent(self, "monster-selection-removed", {
1972
+ value,
1973
+ });
1974
+ })
1975
+ .catch((e) => {
1976
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.message);
1977
+ });
1978
+ }
1979
+ }
1980
+ };
1981
+
1982
+ /**
1983
+ * @param {Event} event
1984
+ */
1985
+ self[closeEventHandler] = (event) => {
1986
+ const path = event.composedPath();
1987
+
1988
+ for (const [, element] of Object.entries(path)) {
1989
+ if (element === self) {
1990
+ return;
1991
+ }
1992
+ }
1993
+ hide.call(self);
1994
+ };
1995
+
1996
+ /**
1997
+ * @param {Event} event
1998
+ */
1999
+ self[inputEventHandler] = (event) => {
2000
+ const path = event.composedPath();
2001
+ const element = path?.[0];
2002
+
2003
+ if (element instanceof HTMLElement) {
2004
+ if (
2005
+ element.hasAttribute(ATTRIBUTE_ROLE) &&
2006
+ element.getAttribute(ATTRIBUTE_ROLE) === "option-control"
2007
+ ) {
2008
+ fireCustomEvent(self, "monster-change", {
2009
+ type: event.type,
2010
+ value: element.value,
2011
+ checked: element.checked,
2012
+ });
2013
+ } else if (
2014
+ element.hasAttribute(ATTRIBUTE_ROLE) &&
2015
+ element.getAttribute(ATTRIBUTE_ROLE) === "filter"
2016
+ ) {
2017
+ }
2018
+ }
2019
+ };
2020
+
2021
+ /**
2022
+ * @param {Event} event
2023
+ */
2024
+ self[changeEventHandler] = (event) => {
2025
+ gatherState.call(self);
2026
+ fireCustomEvent(self, "monster-changed", event?.detail);
2027
+ };
2028
+
2029
+ self[keyEventHandler] = (event) => {
2030
+ const path = event.composedPath();
2031
+ const element = path.shift();
2032
+
2033
+ let role;
2034
+
2035
+ if (element instanceof HTMLElement) {
2036
+ if (element.hasAttribute(ATTRIBUTE_ROLE)) {
2037
+ role = element.getAttribute(ATTRIBUTE_ROLE);
2038
+ } else if (element === this) {
2039
+ show.call(this);
2040
+ // focusFilter.call(self);
2041
+ } else {
2042
+ const e = element.closest(`[${ATTRIBUTE_ROLE}]`);
2043
+ if (e instanceof HTMLElement && e.hasAttribute(ATTRIBUTE_ROLE)) {
2044
+ role = e.getAttribute(ATTRIBUTE_ROLE);
2045
+ }
2046
+ }
2047
+ } else {
2048
+ return;
2049
+ }
2050
+
2051
+ switch (role) {
2052
+ case "filter":
2053
+ handleFilterKeyboardEvents.call(self, event);
2054
+ break;
2055
+ case "option-label":
2056
+ case "option-control":
2057
+ case "option":
2058
+ handleOptionKeyboardEvents.call(self, event);
2059
+ break;
2060
+ case "control":
2061
+ case "toggle":
2062
+ handleToggleKeyboardEvents.call(self, event);
2063
+ break;
2064
+ }
2065
+ };
2066
+
2067
+ const types = self.getOption("toggleEventType", ["click"]);
2068
+
2069
+ for (const [, type] of Object.entries(types)) {
2070
+ self[controlElementSymbol]
2071
+ .querySelector(`[${ATTRIBUTE_ROLE}="container"]`)
2072
+ .addEventListener(type, function (event) {
2073
+ const element = findTargetElementFromEvent(
2074
+ event,
2075
+ ATTRIBUTE_ROLE,
2076
+ "remove-badge",
2077
+ );
2078
+ if (element instanceof HTMLElement) {
2079
+ return;
2080
+ }
2081
+
2082
+ toggle.call(self);
2083
+ });
2084
+
2085
+ self[controlElementSymbol]
2086
+ .querySelector(`[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`)
2087
+ .addEventListener(type, function (event) {
2088
+ if (self.getOption("disabled", undefined) === true) {
2089
+ return;
2090
+ }
2091
+
2092
+ const path = event.composedPath();
2093
+ const element = path?.[0];
2094
+ if (element instanceof HTMLElement) {
2095
+ const control = element.closest(
2096
+ `[${ATTRIBUTE_ROLE}="status-or-remove-badges"]`,
2097
+ );
2098
+ if (control instanceof HTMLElement) {
2099
+ if (control.classList.contains("clear")) {
2100
+ clearSelection.call(self);
2101
+
2102
+ fireCustomEvent(self, "monster-selection-cleared", {});
2103
+ } else {
2104
+ const element = findTargetElementFromEvent(
2105
+ event,
2106
+ ATTRIBUTE_ROLE,
2107
+ "remove-badge",
2108
+ );
2109
+ if (element instanceof HTMLElement) {
2110
+ return;
2111
+ }
2112
+
2113
+ toggle.call(self);
2114
+ }
2115
+ }
2116
+ }
2117
+ });
2118
+
2119
+ // badge, selection
2120
+ self.addEventListener(type, self[clearOptionEventHandler]);
2121
+ }
2122
+
2123
+ self.addEventListener("monster-change", self[changeEventHandler]);
2124
+ self.addEventListener("input", self[inputEventHandler]);
2125
+ self.addEventListener("keydown", self[keyEventHandler]);
2126
+
2127
+ return self;
2128
+ }
2129
+
2130
+ /**
2131
+ * @private
2132
+ * @return {Select}
2133
+ */
2134
+ function setStatusOrRemoveBadges(suggestion) {;
2135
+ setTimeout(() => {
2136
+ const selection = this.getOption("selection");
2137
+ const clearAllFlag =
2138
+ isArray(selection) &&
2139
+ selection.length > 0 &&
2140
+ this.getOption("features.clearAll") === true;
2141
+
2142
+ if (clearAllFlag) {
2143
+ //this[statusOrRemoveBadgesElementSymbol].classList.remove("status");
2144
+ //this[statusOrRemoveBadgesElementSymbol].classList.add("clear");
2145
+ this.setOption("classes.statusOrRemoveBadge", "clear");
2146
+ return;
2147
+ }
2148
+
2149
+ if (suggestion === "loading") {
2150
+ this.setOption("classes.statusOrRemoveBadge", "loading");
2151
+ return;
2152
+ }
2153
+
2154
+ if (this[controlElementSymbol].classList.contains("open")) {
2155
+ this.setOption("classes.statusOrRemoveBadge", "open");
2156
+ return;
2157
+ }
2158
+
2159
+ const options = this.getOption("options");
2160
+ if (
2161
+ options === undefined ||
2162
+ options === null ||
2163
+ (isArray(options) && options.length === 0)
2164
+ ) {
2165
+ this.setOption("classes.statusOrRemoveBadge", "empty");
2166
+ return;
2167
+ }
2168
+
2169
+ if (suggestion) {
2170
+ this.setOption("classes.statusOrRemoveBadge", suggestion);
2171
+ return;
2172
+ }
2173
+ }, 2);
2174
+ }
2175
+
2176
+ /**
2177
+ * @private
2178
+ * @return {Select}
2179
+ * @throws {Error} no shadow-root is defined
2180
+ */
2181
+ function initControlReferences() {;
2182
+
2183
+ if (!this.shadowRoot) {
2184
+ throw new Error("no shadow-root is defined");
2185
+ }
2186
+
2187
+ this[controlElementSymbol] = this.shadowRoot.querySelector(
2188
+ `[${ATTRIBUTE_ROLE}=control]`,
2189
+ );
2190
+ this[selectionElementSymbol] = this.shadowRoot.querySelector(
2191
+ `[${ATTRIBUTE_ROLE}=selection]`,
2192
+ );
2193
+ this[containerElementSymbol] = this.shadowRoot.querySelector(
2194
+ `[${ATTRIBUTE_ROLE}=container]`,
2195
+ );
2196
+ this[popperElementSymbol] = this.shadowRoot.querySelector(
2197
+ `[${ATTRIBUTE_ROLE}=popper]`,
2198
+ );
2199
+ this[inlineFilterElementSymbol] = this.shadowRoot.querySelector(
2200
+ `[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`,
2201
+ );
2202
+ this[popperFilterElementSymbol] = this.shadowRoot.querySelector(
2203
+ `[${ATTRIBUTE_ROLE}=filter][name="popper-filter"]`,
2204
+ );
2205
+ this[popperFilterContainerElementSymbol] =
2206
+ this[popperFilterElementSymbol].parentElement;
2207
+ this[optionsElementSymbol] = this.shadowRoot.querySelector(
2208
+ `[${ATTRIBUTE_ROLE}=options]`,
2209
+ );
2210
+ this[noOptionsAvailableElementSymbol] = this.shadowRoot.querySelector(
2211
+ `[${ATTRIBUTE_ROLE}="no-options"]`,
2212
+ );
2213
+ this[statusOrRemoveBadgesElementSymbol] = this.shadowRoot.querySelector(
2214
+ `[${ATTRIBUTE_ROLE}=status-or-remove-badges]`,
2215
+ );
2216
+ }
2217
+
2218
+ /**
2219
+ * @private
2220
+ */
2221
+ function updatePopper() {;
2222
+
2223
+ if (this[popperElementSymbol].style.display !== STYLE_DISPLAY_MODE_BLOCK) {
2224
+ return;
2225
+ }
2226
+
2227
+ if (this.getOption("disabled", false) === true) {
2228
+ return;
2229
+ }
2230
+
2231
+ new Processing(() => {
2232
+ calcAndSetOptionsDimension.call(this);
2233
+ positionPopper.call(
2234
+ this,
2235
+ this[controlElementSymbol],
2236
+ this[popperElementSymbol],
2237
+ this.getOption("popper", {}),
2238
+ );
2239
+ }).run();
2240
+
2241
+ return this;
2242
+ }
2243
+
2244
+ /**
2245
+ * @private
2246
+ * @return {string}
2247
+ */
2248
+ function getTemplate() {
2249
+ // language=HTML
2250
+ return `
2251
+ <template id="options">
2252
+ <div data-monster-role="option" tabindex="-1"
2253
+ data-monster-attributes="
2254
+ data-monster-filtered path:options.filtered,
2255
+ data-monster-visibility path:options.visibility">
2256
+ <label part="option" role="option">
2257
+ <input data-monster-role="option-control"
2258
+ data-monster-attributes="
2259
+ type path:type,
2260
+ role path:role,
2261
+ value path:options | index:value,
2262
+ name path:name,
2263
+ part path:type | prefix:option- | suffix: form,
2264
+ class path:options.class
2265
+ " tabindex="-1">
2266
+ <div data-monster-replace="path:options | index:label" part="option-label"></div>
2267
+ </label>
2268
+ </div>
2269
+ </template>
2270
+
2271
+ <template id="selection">
2272
+ <div data-monster-role="badge"
2273
+ part="badge"
2274
+ data-monster-attributes="
2275
+ data-monster-value path:selection | index:value,
2276
+ class path:classes | index:badge,
2277
+ part path:type | suffix:-option | prefix: form-" tabindex="-1">
2278
+ <div data-monster-replace="path:selection | index:label" part="badge-label"
2279
+ data-monster-role="badge-label"></div>
2280
+ <div part="remove-badge" data-monster-select-this
2281
+ data-monster-attributes="class path:features.clear | ?::hidden "
2282
+ data-monster-role="remove-badge" tabindex="-1"></div>
2283
+ </div>
2284
+ </template>
2285
+
2286
+ <slot class="hidden"></slot>
2287
+
2288
+ <div data-monster-role="control" part="control" tabindex="0">
2289
+ <div data-monster-role="container">
2290
+ \${selected}
2291
+ </div>
2292
+
2293
+ <div data-monster-role="popper" part="popper" tabindex="-1" class="monster-color-primary-1">
2294
+ <div class="option-filter-control" role="search">
2295
+ <input type="text" role="searchbox"
2296
+ part="popper-filter" name="popper-filter"
2297
+ data-monster-role="filter"
2298
+ autocomplete="off"
2299
+ tabindex="0">
2300
+ </div>
2301
+ <div part="content" class="flex" data-monster-replace="path:content">
2302
+ <div part="options" data-monster-role="options" data-monster-insert="options path:options"
2303
+ tabindex="-1"></div>
2304
+ </div>
2305
+ <div part="no-options" data-monster-role="no-options"
2306
+ data-monster-replace="path:messages.emptyOptions"></div>
2307
+ </div>
2308
+ <div part="status-or-remove-badges" data-monster-role="status-or-remove-badges"
2309
+ data-monster-attributes="class path:classes.statusOrRemoveBadge | suffix:\\ status-or-remove-badges"></div>
2310
+ </div>
2311
+ `;
2312
+ }
2313
+
2314
+ registerCustomElement(Select);