@schukai/monster 3.51.5 → 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 (360) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +15 -12
  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 +223 -103
  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/dom/customcontrol.mjs +5 -4
  348. package/test/cases/math/random.mjs +0 -1
  349. package/test/cases/monster.mjs +1 -1
  350. package/test/cases/net/webconnect/message.mjs +0 -1
  351. package/test/cases/types/node.mjs +1 -1
  352. package/test/util/chai-dom.mjs +2 -2
  353. package/test/util/intersection-mock.mjs +69 -0
  354. package/test/util/jsdom.mjs +41 -25
  355. package/test/util/localstorage.mjs +1 -0
  356. package/test/util/resize-observer.mjs +29 -0
  357. package/test/util/websocket.mjs +4 -1
  358. package/test/web/import.js +16 -1
  359. package/test/web/test.html +28 -5
  360. package/test/web/tests.js +30398 -17879
@@ -13,37 +13,55 @@ import { Formatter } from "../text/formatter.mjs";
13
13
 
14
14
  import { parseDataURL } from "../types/dataurl.mjs";
15
15
  import { getGlobalObject } from "../types/global.mjs";
16
- import { isArray, isFunction, isIterable, isObject, isString } from "../types/is.mjs";
16
+ import {
17
+ isArray,
18
+ isFunction,
19
+ isIterable,
20
+ isObject,
21
+ isString,
22
+ } from "../types/is.mjs";
17
23
  import { Observer } from "../types/observer.mjs";
18
24
  import { ProxyObserver } from "../types/proxyobserver.mjs";
19
- import { validateFunction, validateInstance, validateObject, validateString } from "../types/validate.mjs";
25
+ import {
26
+ validateFunction,
27
+ validateInstance,
28
+ validateObject,
29
+ validateString,
30
+ } from "../types/validate.mjs";
20
31
  import { clone } from "../util/clone.mjs";
21
- import { addAttributeToken, getLinkedObjects, hasObjectLink } from "./attributes.mjs";
22
32
  import {
23
- ATTRIBUTE_DISABLED,
24
- ATTRIBUTE_ERRORMESSAGE,
25
- ATTRIBUTE_OPTIONS,
26
- ATTRIBUTE_INIT_CALLBACK,
27
- ATTRIBUTE_OPTIONS_SELECTOR,
28
- ATTRIBUTE_SCRIPT_HOST,
29
- customElementUpdaterLinkSymbol,
30
- initControlCallbackName,
33
+ addAttributeToken,
34
+ getLinkedObjects,
35
+ hasObjectLink,
36
+ } from "./attributes.mjs";
37
+ import {
38
+ ATTRIBUTE_DISABLED,
39
+ ATTRIBUTE_ERRORMESSAGE,
40
+ ATTRIBUTE_OPTIONS,
41
+ ATTRIBUTE_INIT_CALLBACK,
42
+ ATTRIBUTE_OPTIONS_SELECTOR,
43
+ ATTRIBUTE_SCRIPT_HOST,
44
+ customElementUpdaterLinkSymbol,
45
+ initControlCallbackName,
31
46
  } from "./constants.mjs";
32
47
  import { findDocumentTemplate, Template } from "./template.mjs";
33
48
  import { addObjectWithUpdaterToElement } from "./updater.mjs";
34
49
  import { instanceSymbol } from "../constants.mjs";
35
- import { getDocumentTranslations, Translations } from "../i18n/translations.mjs";
50
+ import {
51
+ getDocumentTranslations,
52
+ Translations,
53
+ } from "../i18n/translations.mjs";
36
54
  import { getSlottedElements } from "./slotted.mjs";
37
55
  import { initOptionsFromAttributes } from "./util/init-options-from-attributes.mjs";
38
56
  import { setOptionFromAttribute } from "./util/set-option-from-attribute.mjs";
39
57
 
40
58
  export {
41
- CustomElement,
42
- initMethodSymbol,
43
- assembleMethodSymbol,
44
- attributeObserverSymbol,
45
- registerCustomElement,
46
- getSlottedElements,
59
+ CustomElement,
60
+ initMethodSymbol,
61
+ assembleMethodSymbol,
62
+ attributeObserverSymbol,
63
+ registerCustomElement,
64
+ getSlottedElements,
47
65
  };
48
66
 
49
67
  /**
@@ -56,20 +74,26 @@ const initMethodSymbol = Symbol.for("@schukai/monster/dom/@@initMethodSymbol");
56
74
  * @memberOf Monster.DOM
57
75
  * @type {symbol}
58
76
  */
59
- const assembleMethodSymbol = Symbol.for("@schukai/monster/dom/@@assembleMethodSymbol");
77
+ const assembleMethodSymbol = Symbol.for(
78
+ "@schukai/monster/dom/@@assembleMethodSymbol",
79
+ );
60
80
 
61
81
  /**
62
82
  * this symbol holds the attribute observer callbacks. The key is the attribute name.
63
83
  * @memberOf Monster.DOM
64
84
  * @type {symbol}
65
85
  */
66
- const attributeObserverSymbol = Symbol.for("@schukai/monster/dom/@@attributeObserver");
86
+ const attributeObserverSymbol = Symbol.for(
87
+ "@schukai/monster/dom/@@attributeObserver",
88
+ );
67
89
 
68
90
  /**
69
91
  * @private
70
92
  * @type {symbol}
71
93
  */
72
- const attributeMutationObserverSymbol = Symbol("@schukai/monster/dom/@@mutationObserver");
94
+ const attributeMutationObserverSymbol = Symbol(
95
+ "@schukai/monster/dom/@@mutationObserver",
96
+ );
73
97
 
74
98
  /**
75
99
  * @private
@@ -201,458 +225,466 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
201
225
  * @summary A base class for HTML5 custom controls.
202
226
  */
203
227
  class CustomElement extends HTMLElement {
204
- /**
205
- * A new object is created. First the `initOptions` method is called. Here the
206
- * options can be defined in derived classes. Subsequently, the shadowRoot is initialized.
207
- *
208
- * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
209
- *
210
- * @throws {Error} the options attribute does not contain a valid json definition.
211
- * @since 1.7.0
212
- */
213
- constructor() {
214
- super();
215
-
216
- this[attributeObserverSymbol] = {};
217
- this[internalSymbol] = new ProxyObserver({
218
- options: initOptionsFromAttributes(this, extend({}, this.defaults)),
219
- });
220
- this[initMethodSymbol]();
221
- initOptionObserver.call(this);
222
- this[scriptHostElementSymbol] = [];
223
- }
224
-
225
- /**
226
- * This method is called by the `instanceof` operator.
227
- * @returns {symbol}
228
- * @since 2.1.0
229
- */
230
- static get [instanceSymbol]() {
231
- return Symbol.for("@schukai/monster/dom/custom-element@@instance");
232
- }
233
-
234
- /**
235
- * This method determines which attributes are to be
236
- * monitored by `attributeChangedCallback()`. Unfortunately, this method is static.
237
- * Therefore, the `observedAttributes` property cannot be changed during runtime.
238
- *
239
- * @return {string[]}
240
- * @since 1.15.0
241
- */
242
- static get observedAttributes() {
243
- return [];
244
- }
245
-
246
- /**
247
- *
248
- * @param attribute
249
- * @param callback
250
- * @returns {Monster.DOM.CustomElement}
251
- */
252
- addAttributeObserver(attribute, callback) {
253
- validateFunction(callback);
254
- this[attributeObserverSymbol][attribute] = callback;
255
- return this;
256
- }
257
-
258
- /**
259
- *
260
- * @param attribute
261
- * @returns {Monster.DOM.CustomElement}
262
- */
263
- removeAttributeObserver(attribute) {
264
- delete this[attributeObserverSymbol][attribute];
265
- return this;
266
- }
267
-
268
- /**
269
- * The `defaults` property defines the default values for a control. If you want to override these,
270
- * you can use various methods, which are described in the documentation available at
271
- * {@link https://monsterjs.orgendocconfigurate-a-monster-control}.
272
- *
273
- * The individual configuration values are listed below:
274
- *
275
- * More information about the shadowRoot can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow),
276
- * in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
277
- *
278
- * More information about the template element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
279
- *
280
- * More information about the slot element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot).
281
- *
282
- * @property {boolean} disabled=false Specifies whether the control is disabled. When present, it makes the element non-mutable, non-focusable, and non-submittable with the form.
283
- * @property {string} shadowMode=open Specifies the mode of the shadow root. When set to `open`, elements in the shadow root are accessible from JavaScript outside the root, while setting it to `closed` denies access to the root's nodes from JavaScript outside it.
284
- * @property {Boolean} delegatesFocus=true Specifies the behavior of the control with respect to focusability. When set to `true`, it mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
285
- * @property {Object} templates Specifies the templates used by the control.
286
- * @property {string} templates.main=undefined Specifies the main template used by the control.
287
- * @property {Object} templateMapping Specifies the mapping of templates.
288
- * @since 1.8.0
289
- */
290
- get defaults() {
291
- return {
292
- disabled: false,
293
- shadowMode: "open",
294
- delegatesFocus: true,
295
- templates: {
296
- main: undefined,
297
- },
298
- templateMapping: {},
299
- };
300
- }
301
-
302
- /**
303
- * This method updates the labels of the element.
304
- * The labels are defined in the options object.
305
- * The key of the label is used to retrieve the translation from the document.
306
- * If the translation is different from the label, the label is updated.
307
- *
308
- * Before you can use this method, you must have loaded the translations.
309
- *
310
- * @returns {Monster.DOM.CustomElement}
311
- * @throws {Error} Cannot find element with translations. Add a translations object to the document.
312
- */
313
- updateI18n() {
314
- const translations = getDocumentTranslations();
315
- if (!translations) {
316
- return this;
317
- }
318
-
319
- let labels = this.getOption("labels");
320
- if (!(isObject(labels) || isIterable(labels))) {
321
- return this;
322
- }
323
-
324
- for (const key in labels) {
325
- const def = labels[key];
326
-
327
- if (isString(def)) {
328
- const text = translations.getText(key, def);
329
- if (text !== def) {
330
- this.setOption(`labels.${key}`, text);
331
- }
332
- continue;
333
- } else if (isObject(def)) {
334
- for (const k in def) {
335
- const d = def[k];
336
-
337
- const text = translations.getPluralRuleText(key, k, d);
338
- if (!isString(text)) {
339
- throw new Error("Invalid labels definition");
340
- }
341
- if (text !== d) {
342
- this.setOption(`labels.${key}.${k}`, text);
343
- }
344
- }
345
- continue;
346
- }
347
-
348
- throw new Error("Invalid labels definition");
349
- }
350
- return this;
351
- }
352
-
353
- /**
354
- * The `getTag()` method returns the tag name associated with the custom element. This method should be overwritten
355
- * by the derived class.
356
- *
357
- * Note that there is no check on the name of the tag in this class. It is the responsibility of
358
- * the developer to assign an appropriate tag name. If the name is not valid, the
359
- * `registerCustomElement()` method will issue an error.
360
- *
361
- * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
362
- * @throws {Error} This method must be overridden by the derived class.
363
- * @return {string} The tag name associated with the custom element.
364
- * @since 1.7.0
365
- */
366
- static getTag() {
367
- throw new Error("The method `getTag()` must be overridden by the derived class.");
368
- }
369
-
370
- /**
371
- * The `getCSSStyleSheet()` method returns a `CSSStyleSheet` object that defines the styles for the custom element.
372
- * If the environment does not support the `CSSStyleSheet` constructor, then an object can be built using the provided detour.
373
- *
374
- * If `undefined` is returned, then the shadow root does not receive a stylesheet.
375
- *
376
- * Example usage:
377
- *
378
- * ```js
379
- * static getCSSStyleSheet() {
380
- * const sheet = new CSSStyleSheet();
381
- * sheet.replaceSync("p { color: red; }");
382
- * return sheet;
383
- * }
384
- * ```
385
- *
386
- * If the environment does not support the `CSSStyleSheet` constructor,
387
- * you can use the following workaround to create the stylesheet:
388
- *
389
- * ```js
390
- * const doc = document.implementation.createHTMLDocument('title');
391
- * let style = doc.createElement("style");
392
- * style.innerHTML = "p { color: red; }";
393
- * style.appendChild(document.createTextNode(""));
394
- * doc.head.appendChild(style);
395
- * return doc.styleSheets[0];
396
- * ```
397
- *
398
- * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined} A `CSSStyleSheet` object or an array of such objects that define the styles for the custom element, or `undefined` if no stylesheet should be applied.
399
- */
400
- static getCSSStyleSheet() {
401
- return undefined;
402
- }
403
-
404
- /**
405
- * attach a new observer
406
- *
407
- * @param {Observer} observer
408
- * @returns {CustomElement}
409
- */
410
- attachObserver(observer) {
411
- this[internalSymbol].attachObserver(observer);
412
- return this;
413
- }
414
-
415
- /**
416
- * detach a observer
417
- *
418
- * @param {Observer} observer
419
- * @returns {CustomElement}
420
- */
421
- detachObserver(observer) {
422
- this[internalSymbol].detachObserver(observer);
423
- return this;
424
- }
425
-
426
- /**
427
- * @param {Observer} observer
428
- * @returns {ProxyObserver}
429
- */
430
- containsObserver(observer) {
431
- return this[internalSymbol].containsObserver(observer);
432
- }
433
-
434
- /**
435
- * nested options can be specified by path `a.b.c`
436
- *
437
- * @param {string} path
438
- * @param {*} defaultValue
439
- * @return {*}
440
- * @since 1.10.0
441
- */
442
- getOption(path, defaultValue) {
443
- let value;
444
-
445
- try {
446
- value = new Pathfinder(this[internalSymbol].getRealSubject()["options"]).getVia(path);
447
- } catch (e) {}
448
-
449
- if (value === undefined) return defaultValue;
450
- return value;
451
- }
452
-
453
- /**
454
- * Set option and inform elements
455
- *
456
- * @param {string} path
457
- * @param {*} value
458
- * @return {CustomElement}
459
- * @since 1.14.0
460
- */
461
- setOption(path, value) {
462
- new Pathfinder(this[internalSymbol].getSubject()["options"]).setVia(path, value);
463
- return this;
464
- }
465
-
466
- /**
467
- * @since 1.15.0
468
- * @param {string|object} options
469
- * @return {CustomElement}
470
- */
471
- setOptions(options) {
472
- if (isString(options)) {
473
- options = parseOptionsJSON.call(this, options);
474
- }
475
-
476
- const self = this;
477
- extend(self[internalSymbol].getSubject()["options"], self.defaults, options);
478
-
479
- return self;
480
- }
481
-
482
- /**
483
- * Is called once via the constructor
484
- *
485
- * @return {CustomElement}
486
- * @since 1.8.0
487
- */
488
- [initMethodSymbol]() {
489
- return this;
490
- }
491
-
492
- /**
493
- * This method is called once when the object is included in the DOM for the first time. It performs the following actions:
494
- * 1. Extracts the options from the attributes and the script tag of the element and sets them.
495
- * 2. Initializes the shadow root and its CSS stylesheet (if specified).
496
- * 3. Initializes the HTML content of the element.
497
- * 4. Initializes the custom elements inside the shadow root and the slotted elements.
498
- * 5. Attaches a mutation observer to observe changes to the attributes of the element.
499
- *
500
- * @return {CustomElement} - The updated custom element.
501
- * @since 1.8.0
502
- */
503
- [assembleMethodSymbol]() {
504
- const self = this;
505
- let elements;
506
- let nodeList;
507
-
508
- // Extract options from attributes and set them
509
- const AttributeOptions = getOptionsFromAttributes.call(self);
510
- if (isObject(AttributeOptions) && Object.keys(AttributeOptions).length > 0) {
511
- self.setOptions(AttributeOptions);
512
- }
513
-
514
- // Extract options from script tag and set them
515
- const ScriptOptions = getOptionsFromScriptTag.call(self);
516
- if (isObject(ScriptOptions) && Object.keys(ScriptOptions).length > 0) {
517
- self.setOptions(ScriptOptions);
518
- }
519
-
520
- // Initialize the shadow root and its CSS stylesheet
521
- if (self.getOption("shadowMode", false) !== false) {
522
- try {
523
- initShadowRoot.call(self);
524
- elements = self.shadowRoot.childNodes;
525
- } catch (e) {
526
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
527
- }
528
-
529
- try {
530
- initCSSStylesheet.call(this);
531
- } catch (e) {
532
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
533
- }
534
- }
535
-
536
- // If the elements are not found inside the shadow root, initialize the HTML content of the element
537
- if (!(elements instanceof NodeList)) {
538
- initHtmlContent.call(this);
539
- elements = this.childNodes;
540
- }
541
-
542
- // Initialize the custom elements inside the shadow root and the slotted elements
543
- initFromCallbackHost.call(this);
544
- try {
545
- nodeList = new Set([...elements, ...getSlottedElements.call(self)]);
546
- } catch (e) {
547
- nodeList = elements;
548
- }
549
- addObjectWithUpdaterToElement.call(
550
- self,
551
- nodeList,
552
- customElementUpdaterLinkSymbol,
553
- clone(self[internalSymbol].getRealSubject()["options"]),
554
- );
555
-
556
- // Attach a mutation observer to observe changes to the attributes of the element
557
- attachAttributeChangeMutationObserver.call(this);
558
-
559
- return self;
560
- }
561
-
562
- /**
563
- * This method is called every time the element is inserted into the DOM. It checks if the custom element
564
- * has already been initialized and if not, calls the assembleMethod to initialize it.
565
- *
566
- * @return {void}
567
- * @since 1.7.0
568
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/connectedCallback
569
- */
570
- connectedCallback() {
571
- const self = this;
572
-
573
- // Check if the object has already been initialized
574
- if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
575
- // If not, call the assembleMethod to initialize the object
576
- self[assembleMethodSymbol]();
577
- }
578
- }
579
-
580
- /**
581
- * Called every time the element is removed from the DOM. Useful for running clean up code.
582
- *
583
- * @return {void}
584
- * @since 1.7.0
585
- */
586
- disconnectedCallback() {}
587
-
588
- /**
589
- * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
590
- *
591
- * @return {void}
592
- * @since 1.7.0
593
- */
594
- adoptedCallback() {}
595
-
596
- /**
597
- * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
598
- * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
599
- * property will receive this callback.
600
- *
601
- * @param {string} attrName
602
- * @param {string} oldVal
603
- * @param {string} newVal
604
- * @return {void}
605
- * @since 1.15.0
606
- */
607
- attributeChangedCallback(attrName, oldVal, newVal) {
608
- const self = this;
609
-
610
- if (attrName.startsWith("data-monster-option-")) {
611
- setOptionFromAttribute(self, attrName, this[internalSymbol].getSubject()["options"]);
612
- }
613
-
614
- const callback = self[attributeObserverSymbol]?.[attrName];
615
- if (isFunction(callback)) {
616
- try {
617
- callback.call(self, newVal, oldVal);
618
- } catch (e) {
619
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
620
- }
621
- }
622
- }
623
-
624
- /**
625
- *
626
- * @param {Node} node
627
- * @return {boolean}
628
- * @throws {TypeError} value is not an instance of
629
- * @since 1.19.0
630
- */
631
- hasNode(node) {
632
- const self = this;
633
-
634
- if (containChildNode.call(self, validateInstance(node, Node))) {
635
- return true;
636
- }
637
-
638
- if (!(self.shadowRoot instanceof ShadowRoot)) {
639
- return false;
640
- }
641
-
642
- return containChildNode.call(self.shadowRoot, node);
643
- }
644
-
645
- /**
646
- * Calls a callback function if it exists.
647
- *
648
- * @param {string} name
649
- * @param {*} args
650
- * @returns {*}
651
- */
652
- callCallback(name, args) {
653
- const self = this;
654
- return callControlCallback.call(self, name, ...args);
655
- }
228
+ /**
229
+ * A new object is created. First the `initOptions` method is called. Here the
230
+ * options can be defined in derived classes. Subsequently, the shadowRoot is initialized.
231
+ *
232
+ * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
233
+ *
234
+ * @throws {Error} the options attribute does not contain a valid json definition.
235
+ * @since 1.7.0
236
+ */
237
+ constructor() {
238
+ super();
239
+
240
+ this[attributeObserverSymbol] = {};
241
+ this[internalSymbol] = new ProxyObserver({
242
+ options: initOptionsFromAttributes(this, extend({}, this.defaults)),
243
+ });
244
+ this[initMethodSymbol]();
245
+ initOptionObserver.call(this);
246
+ this[scriptHostElementSymbol] = [];
247
+ }
248
+
249
+ /**
250
+ * This method is called by the `instanceof` operator.
251
+ * @returns {symbol}
252
+ * @since 2.1.0
253
+ */
254
+ static get [instanceSymbol]() {
255
+ return Symbol.for("@schukai/monster/dom/custom-element@@instance");
256
+ }
257
+
258
+ /**
259
+ * This method determines which attributes are to be
260
+ * monitored by `attributeChangedCallback()`. Unfortunately, this method is static.
261
+ * Therefore, the `observedAttributes` property cannot be changed during runtime.
262
+ *
263
+ * @return {string[]}
264
+ * @since 1.15.0
265
+ */
266
+ static get observedAttributes() {
267
+ return [];
268
+ }
269
+
270
+ /**
271
+ *
272
+ * @param attribute
273
+ * @param callback
274
+ * @returns {Monster.DOM.CustomElement}
275
+ */
276
+ addAttributeObserver(attribute, callback) {
277
+ validateFunction(callback);
278
+ this[attributeObserverSymbol][attribute] = callback;
279
+ return this;
280
+ }
281
+
282
+ /**
283
+ *
284
+ * @param attribute
285
+ * @returns {Monster.DOM.CustomElement}
286
+ */
287
+ removeAttributeObserver(attribute) {
288
+ delete this[attributeObserverSymbol][attribute];
289
+ return this;
290
+ }
291
+
292
+ /**
293
+ * The `defaults` property defines the default values for a control. If you want to override these,
294
+ * you can use various methods, which are described in the documentation available at
295
+ * {@link https://monsterjs.orgendocconfigurate-a-monster-control}.
296
+ *
297
+ * The individual configuration values are listed below:
298
+ *
299
+ * More information about the shadowRoot can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow),
300
+ * in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
301
+ *
302
+ * More information about the template element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
303
+ *
304
+ * More information about the slot element can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot).
305
+ *
306
+ * @property {boolean} disabled=false Specifies whether the control is disabled. When present, it makes the element non-mutable, non-focusable, and non-submittable with the form.
307
+ * @property {string} shadowMode=open Specifies the mode of the shadow root. When set to `open`, elements in the shadow root are accessible from JavaScript outside the root, while setting it to `closed` denies access to the root's nodes from JavaScript outside it.
308
+ * @property {Boolean} delegatesFocus=true Specifies the behavior of the control with respect to focusability. When set to `true`, it mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling.
309
+ * @property {Object} templates Specifies the templates used by the control.
310
+ * @property {string} templates.main=undefined Specifies the main template used by the control.
311
+ * @property {Object} templateMapping Specifies the mapping of templates.
312
+ * @since 1.8.0
313
+ */
314
+ get defaults() {
315
+ return {
316
+ disabled: false,
317
+ shadowMode: "open",
318
+ delegatesFocus: true,
319
+ templates: {
320
+ main: undefined,
321
+ },
322
+ templateMapping: {},
323
+ };
324
+ }
325
+
326
+ /**
327
+ * This method updates the labels of the element.
328
+ * The labels are defined in the options object.
329
+ * The key of the label is used to retrieve the translation from the document.
330
+ * If the translation is different from the label, the label is updated.
331
+ *
332
+ * Before you can use this method, you must have loaded the translations.
333
+ *
334
+ * @returns {Monster.DOM.CustomElement}
335
+ * @throws {Error} Cannot find element with translations. Add a translations object to the document.
336
+ */
337
+ updateI18n() {
338
+ const translations = getDocumentTranslations();
339
+ if (!translations) {
340
+ return this;
341
+ }
342
+
343
+ const labels = this.getOption("labels");
344
+ if (!(isObject(labels) || isIterable(labels))) {
345
+ return this;
346
+ }
347
+
348
+ for (const key in labels) {
349
+ const def = labels[key];
350
+
351
+ if (isString(def)) {
352
+ const text = translations.getText(key, def);
353
+ if (text !== def) {
354
+ this.setOption(`labels.${key}`, text);
355
+ }
356
+ continue;
357
+ } else if (isObject(def)) {
358
+ for (const k in def) {
359
+ const d = def[k];
360
+
361
+ const text = translations.getPluralRuleText(key, k, d);
362
+ if (!isString(text)) {
363
+ throw new Error("Invalid labels definition");
364
+ }
365
+ if (text !== d) {
366
+ this.setOption(`labels.${key}.${k}`, text);
367
+ }
368
+ }
369
+ continue;
370
+ }
371
+
372
+ throw new Error("Invalid labels definition");
373
+ }
374
+ return this;
375
+ }
376
+
377
+ /**
378
+ * The `getTag()` method returns the tag name associated with the custom element. This method should be overwritten
379
+ * by the derived class.
380
+ *
381
+ * Note that there is no check on the name of the tag in this class. It is the responsibility of
382
+ * the developer to assign an appropriate tag name. If the name is not valid, the
383
+ * `registerCustomElement()` method will issue an error.
384
+ *
385
+ * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
386
+ * @throws {Error} This method must be overridden by the derived class.
387
+ * @return {string} The tag name associated with the custom element.
388
+ * @since 1.7.0
389
+ */
390
+ static getTag() {
391
+ throw new Error(
392
+ "The method `getTag()` must be overridden by the derived class.",
393
+ );
394
+ }
395
+
396
+ /**
397
+ * The `getCSSStyleSheet()` method returns a `CSSStyleSheet` object that defines the styles for the custom element.
398
+ * If the environment does not support the `CSSStyleSheet` constructor, then an object can be built using the provided detour.
399
+ *
400
+ * If `undefined` is returned, then the shadow root does not receive a stylesheet.
401
+ *
402
+ * Example usage:
403
+ *
404
+ * ```js
405
+ * static getCSSStyleSheet() {
406
+ * const sheet = new CSSStyleSheet();
407
+ * sheet.replaceSync("p { color: red; }");
408
+ * return sheet;
409
+ * }
410
+ * ```
411
+ *
412
+ * If the environment does not support the `CSSStyleSheet` constructor,
413
+ * you can use the following workaround to create the stylesheet:
414
+ *
415
+ * ```js
416
+ * const doc = document.implementation.createHTMLDocument('title');
417
+ * let style = doc.createElement("style");
418
+ * style.innerHTML = "p { color: red; }";
419
+ * style.appendChild(document.createTextNode(""));
420
+ * doc.head.appendChild(style);
421
+ * return doc.styleSheets[0];
422
+ * ```
423
+ *
424
+ * @return {CSSStyleSheet|CSSStyleSheet[]|string|undefined} A `CSSStyleSheet` object or an array of such objects that define the styles for the custom element, or `undefined` if no stylesheet should be applied.
425
+ */
426
+ static getCSSStyleSheet() {
427
+ return undefined;
428
+ }
429
+
430
+ /**
431
+ * attach a new observer
432
+ *
433
+ * @param {Observer} observer
434
+ * @returns {CustomElement}
435
+ */
436
+ attachObserver(observer) {
437
+ this[internalSymbol].attachObserver(observer);
438
+ return this;
439
+ }
440
+
441
+ /**
442
+ * detach a observer
443
+ *
444
+ * @param {Observer} observer
445
+ * @returns {CustomElement}
446
+ */
447
+ detachObserver(observer) {
448
+ this[internalSymbol].detachObserver(observer);
449
+ return this;
450
+ }
451
+
452
+ /**
453
+ * @param {Observer} observer
454
+ * @returns {ProxyObserver}
455
+ */
456
+ containsObserver(observer) {
457
+ return this[internalSymbol].containsObserver(observer);
458
+ }
459
+
460
+ /**
461
+ * nested options can be specified by path `a.b.c`
462
+ *
463
+ * @param {string} path
464
+ * @param {*} defaultValue
465
+ * @return {*}
466
+ * @since 1.10.0
467
+ */
468
+ getOption(path, defaultValue) {
469
+ let value;
470
+
471
+ try {
472
+ value = new Pathfinder(
473
+ this[internalSymbol].getRealSubject()["options"],
474
+ ).getVia(path);
475
+ } catch (e) {}
476
+
477
+ if (value === undefined) return defaultValue;
478
+ return value;
479
+ }
480
+
481
+ /**
482
+ * Set option and inform elements
483
+ *
484
+ * @param {string} path
485
+ * @param {*} value
486
+ * @return {CustomElement}
487
+ * @since 1.14.0
488
+ */
489
+ setOption(path, value) {
490
+ new Pathfinder(this[internalSymbol].getSubject()["options"]).setVia(
491
+ path,
492
+ value,
493
+ );
494
+ return this;
495
+ }
496
+
497
+ /**
498
+ * @since 1.15.0
499
+ * @param {string|object} options
500
+ * @return {CustomElement}
501
+ */
502
+ setOptions(options) {
503
+ if (isString(options)) {
504
+ options = parseOptionsJSON.call(this, options);
505
+ }
506
+ extend(
507
+ this[internalSymbol].getSubject()["options"],
508
+ this.defaults,
509
+ options,
510
+ );
511
+
512
+ return this;
513
+ }
514
+
515
+ /**
516
+ * Is called once via the constructor
517
+ *
518
+ * @return {CustomElement}
519
+ * @since 1.8.0
520
+ */
521
+ [initMethodSymbol]() {
522
+ return this;
523
+ }
524
+
525
+ /**
526
+ * This method is called once when the object is included in the DOM for the first time. It performs the following actions:
527
+ * 1. Extracts the options from the attributes and the script tag of the element and sets them.
528
+ * 2. Initializes the shadow root and its CSS stylesheet (if specified).
529
+ * 3. Initializes the HTML content of the element.
530
+ * 4. Initializes the custom elements inside the shadow root and the slotted elements.
531
+ * 5. Attaches a mutation observer to observe changes to the attributes of the element.
532
+ *
533
+ * @return {CustomElement} - The updated custom element.
534
+ * @since 1.8.0
535
+ */
536
+ [assembleMethodSymbol]() {
537
+ let elements;
538
+ let nodeList;
539
+
540
+ // Extract options from attributes and set them
541
+ const AttributeOptions = getOptionsFromAttributes.call(this);
542
+ if (
543
+ isObject(AttributeOptions) &&
544
+ Object.keys(AttributeOptions).length > 0
545
+ ) {
546
+ this.setOptions(AttributeOptions);
547
+ }
548
+
549
+ // Extract options from script tag and set them
550
+ const ScriptOptions = getOptionsFromScriptTag.call(this);
551
+ if (isObject(ScriptOptions) && Object.keys(ScriptOptions).length > 0) {
552
+ this.setOptions(ScriptOptions);
553
+ }
554
+
555
+ // Initialize the shadow root and its CSS stylesheet
556
+ if (this.getOption("shadowMode", false) !== false) {
557
+ try {
558
+ initShadowRoot.call(this);
559
+ elements = this.shadowRoot.childNodes;
560
+ } catch (e) {
561
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.toString());
562
+ }
563
+
564
+ try {
565
+ initCSSStylesheet.call(this);
566
+ } catch (e) {
567
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.toString());
568
+ }
569
+ }
570
+
571
+ // If the elements are not found inside the shadow root, initialize the HTML content of the element
572
+ if (!(elements instanceof NodeList)) {
573
+ initHtmlContent.call(this);
574
+ elements = this.childNodes;
575
+ }
576
+
577
+ // Initialize the custom elements inside the shadow root and the slotted elements
578
+ initFromCallbackHost.call(this);
579
+ try {
580
+ nodeList = new Set([...elements, ...getSlottedElements.call(this)]);
581
+ } catch (e) {
582
+ nodeList = elements;
583
+ }
584
+ addObjectWithUpdaterToElement.call(
585
+ this,
586
+ nodeList,
587
+ customElementUpdaterLinkSymbol,
588
+ clone(this[internalSymbol].getRealSubject()["options"]),
589
+ );
590
+
591
+ // Attach a mutation observer to observe changes to the attributes of the element
592
+ attachAttributeChangeMutationObserver.call(this);
593
+
594
+ return this;
595
+ }
596
+
597
+ /**
598
+ * This method is called every time the element is inserted into the DOM. It checks if the custom element
599
+ * has already been initialized and if not, calls the assembleMethod to initialize it.
600
+ *
601
+ * @return {void}
602
+ * @since 1.7.0
603
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/connectedCallback
604
+ */
605
+ connectedCallback() {
606
+ // Check if the object has already been initialized
607
+ if (!hasObjectLink(this, customElementUpdaterLinkSymbol)) {
608
+ // If not, call the assembleMethod to initialize the object
609
+ this[assembleMethodSymbol]();
610
+ }
611
+ }
612
+
613
+ /**
614
+ * Called every time the element is removed from the DOM. Useful for running clean up code.
615
+ *
616
+ * @return {void}
617
+ * @since 1.7.0
618
+ */
619
+ disconnectedCallback() {}
620
+
621
+ /**
622
+ * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
623
+ *
624
+ * @return {void}
625
+ * @since 1.7.0
626
+ */
627
+ adoptedCallback() {}
628
+
629
+ /**
630
+ * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
631
+ * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes
632
+ * property will receive this callback.
633
+ *
634
+ * @param {string} attrName
635
+ * @param {string} oldVal
636
+ * @param {string} newVal
637
+ * @return {void}
638
+ * @since 1.15.0
639
+ */
640
+ attributeChangedCallback(attrName, oldVal, newVal) {
641
+ if (attrName.startsWith("data-monster-option-")) {
642
+ setOptionFromAttribute(
643
+ this,
644
+ attrName,
645
+ this[internalSymbol].getSubject()["options"],
646
+ );
647
+ }
648
+
649
+ const callback = this[attributeObserverSymbol]?.[attrName];
650
+ if (isFunction(callback)) {
651
+ try {
652
+ callback.call(this, newVal, oldVal);
653
+ } catch (e) {
654
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.toString());
655
+ }
656
+ }
657
+ }
658
+
659
+ /**
660
+ *
661
+ * @param {Node} node
662
+ * @return {boolean}
663
+ * @throws {TypeError} value is not an instance of
664
+ * @since 1.19.0
665
+ */
666
+ hasNode(node) {
667
+ if (containChildNode.call(this, validateInstance(node, Node))) {
668
+ return true;
669
+ }
670
+
671
+ if (!(this.shadowRoot instanceof ShadowRoot)) {
672
+ return false;
673
+ }
674
+
675
+ return containChildNode.call(this.shadowRoot, node);
676
+ }
677
+
678
+ /**
679
+ * Calls a callback function if it exists.
680
+ *
681
+ * @param {string} name
682
+ * @param {*} args
683
+ * @returns {*}
684
+ */
685
+ callCallback(name, args) {
686
+ return callControlCallback.call(this, name, ...args);
687
+ }
656
688
  }
657
689
 
658
690
  /**
@@ -661,48 +693,50 @@ class CustomElement extends HTMLElement {
661
693
  * @return {any}
662
694
  */
663
695
  function callControlCallback(callBackFunctionName, ...args) {
664
- const self = this;
665
-
666
- if (!isString(callBackFunctionName) || callBackFunctionName === "") {
667
- return;
668
- }
669
-
670
- if (callBackFunctionName in self) {
671
- return self[callBackFunctionName](self, ...args);
672
- }
673
-
674
- if (!self.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
675
- return;
676
- }
677
-
678
- if (self[scriptHostElementSymbol].length === 0) {
679
- const targetId = self.getAttribute(ATTRIBUTE_SCRIPT_HOST);
680
- if (!targetId) {
681
- return;
682
- }
683
-
684
- const list = targetId.split(",");
685
- for (const id of list) {
686
- const host = findElementWithIdUpwards(self, targetId);
687
- if (!(host instanceof HTMLElement)) {
688
- continue;
689
- }
690
-
691
- self[scriptHostElementSymbol].push(host);
692
- }
693
- }
694
-
695
- for (const host of self[scriptHostElementSymbol]) {
696
- if (callBackFunctionName in host) {
697
- try {
698
- return host[callBackFunctionName](self, ...args);
699
- } catch (e) {
700
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
701
- }
702
- }
703
- }
704
-
705
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, `callback ${callBackFunctionName} not found`);
696
+ if (!isString(callBackFunctionName) || callBackFunctionName === "") {
697
+ return;
698
+ }
699
+
700
+ if (callBackFunctionName in this) {
701
+ return this[callBackFunctionName](this, ...args);
702
+ }
703
+
704
+ if (!this.hasAttribute(ATTRIBUTE_SCRIPT_HOST)) {
705
+ return;
706
+ }
707
+
708
+ if (this[scriptHostElementSymbol].length === 0) {
709
+ const targetId = this.getAttribute(ATTRIBUTE_SCRIPT_HOST);
710
+ if (!targetId) {
711
+ return;
712
+ }
713
+
714
+ const list = targetId.split(",");
715
+ for (const id of list) {
716
+ const host = findElementWithIdUpwards(this, targetId);
717
+ if (!(host instanceof HTMLElement)) {
718
+ continue;
719
+ }
720
+
721
+ this[scriptHostElementSymbol].push(host);
722
+ }
723
+ }
724
+
725
+ for (const host of this[scriptHostElementSymbol]) {
726
+ if (callBackFunctionName in host) {
727
+ try {
728
+ return host[callBackFunctionName](this, ...args);
729
+ } catch (e) {
730
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e.toString());
731
+ }
732
+ }
733
+ }
734
+
735
+ addAttributeToken(
736
+ this,
737
+ ATTRIBUTE_ERRORMESSAGE,
738
+ `callback ${callBackFunctionName} not found`,
739
+ );
706
740
  }
707
741
 
708
742
  /**
@@ -719,18 +753,16 @@ function callControlCallback(callBackFunctionName, ...args) {
719
753
  * @since 1.8.0
720
754
  */
721
755
  function initFromCallbackHost() {
722
- const self = this;
756
+ // Set the default callback function name
757
+ let callBackFunctionName = initControlCallbackName;
723
758
 
724
- // Set the default callback function name
725
- let callBackFunctionName = initControlCallbackName;
759
+ // If the `data-monster-option-callback` attribute is set, use its value as the callback function name
760
+ if (this.hasAttribute(ATTRIBUTE_INIT_CALLBACK)) {
761
+ callBackFunctionName = this.getAttribute(ATTRIBUTE_INIT_CALLBACK);
762
+ }
726
763
 
727
- // If the `data-monster-option-callback` attribute is set, use its value as the callback function name
728
- if (self.hasAttribute(ATTRIBUTE_INIT_CALLBACK)) {
729
- callBackFunctionName = self.getAttribute(ATTRIBUTE_INIT_CALLBACK);
730
- }
731
-
732
- // Call the callback function with the element as a parameter if it exists
733
- callControlCallback.call(self, callBackFunctionName);
764
+ // Call the callback function with the element as a parameter if it exists
765
+ callControlCallback.call(this, callBackFunctionName);
734
766
  }
735
767
 
736
768
  /**
@@ -740,32 +772,35 @@ function initFromCallbackHost() {
740
772
  * @this CustomElement
741
773
  */
742
774
  function attachAttributeChangeMutationObserver() {
743
- const self = this;
744
-
745
- if (typeof self[attributeMutationObserverSymbol] !== "undefined") {
746
- return;
747
- }
748
-
749
- self[attributeMutationObserverSymbol] = new MutationObserver(function (mutations, observer) {
750
- for (const mutation of mutations) {
751
- if (mutation.type === "attributes") {
752
- self.attributeChangedCallback(
753
- mutation.attributeName,
754
- mutation.oldValue,
755
- mutation.target.getAttribute(mutation.attributeName),
756
- );
757
- }
758
- }
759
- });
760
-
761
- try {
762
- self[attributeMutationObserverSymbol].observe(self, {
763
- attributes: true,
764
- attributeOldValue: true,
765
- });
766
- } catch (e) {
767
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
768
- }
775
+ const self = this;
776
+
777
+ if (typeof self[attributeMutationObserverSymbol] !== "undefined") {
778
+ return;
779
+ }
780
+
781
+ self[attributeMutationObserverSymbol] = new MutationObserver(function (
782
+ mutations,
783
+ observer,
784
+ ) {
785
+ for (const mutation of mutations) {
786
+ if (mutation.type === "attributes") {
787
+ self.attributeChangedCallback(
788
+ mutation.attributeName,
789
+ mutation.oldValue,
790
+ mutation.target.getAttribute(mutation.attributeName),
791
+ );
792
+ }
793
+ }
794
+ });
795
+
796
+ try {
797
+ self[attributeMutationObserverSymbol].observe(self, {
798
+ attributes: true,
799
+ attributeOldValue: true,
800
+ });
801
+ } catch (e) {
802
+ addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
803
+ }
769
804
  }
770
805
 
771
806
  /**
@@ -775,21 +810,19 @@ function attachAttributeChangeMutationObserver() {
775
810
  * @return {boolean}
776
811
  */
777
812
  function containChildNode(node) {
778
- const self = this;
779
-
780
- if (self.contains(node)) {
781
- return true;
782
- }
813
+ if (this.contains(node)) {
814
+ return true;
815
+ }
783
816
 
784
- for (const [, e] of Object.entries(self.childNodes)) {
785
- if (e.contains(node)) {
786
- return true;
787
- }
817
+ for (const [, e] of Object.entries(this.childNodes)) {
818
+ if (e.contains(node)) {
819
+ return true;
820
+ }
788
821
 
789
- containChildNode.call(e, node);
790
- }
822
+ containChildNode.call(e, node);
823
+ }
791
824
 
792
- return false;
825
+ return false;
793
826
  }
794
827
 
795
828
  /**
@@ -799,86 +832,89 @@ function containChildNode(node) {
799
832
  * @this CustomElement
800
833
  */
801
834
  function initOptionObserver() {
802
- const self = this;
803
-
804
- let lastDisabledValue = undefined;
805
- self.attachObserver(
806
- new Observer(function () {
807
- const flag = self.getOption("disabled");
808
-
809
- if (flag === lastDisabledValue) {
810
- return;
811
- }
812
-
813
- lastDisabledValue = flag;
814
-
815
- if (!(self.shadowRoot instanceof ShadowRoot)) {
816
- return;
817
- }
818
-
819
- const query =
820
- "button, command, fieldset, keygen, optgroup, option, select, textarea, input, [data-monster-objectlink]";
821
- const elements = self.shadowRoot.querySelectorAll(query);
822
-
823
- let nodeList;
824
- try {
825
- nodeList = new Set([...elements, ...getSlottedElements.call(self, query)]);
826
- } catch (e) {
827
- nodeList = elements;
828
- }
829
-
830
- for (const element of [...nodeList]) {
831
- if (flag === true) {
832
- element.setAttribute(ATTRIBUTE_DISABLED, "");
833
- } else {
834
- element.removeAttribute(ATTRIBUTE_DISABLED);
835
- }
836
- }
837
- }),
838
- );
839
-
840
- self.attachObserver(
841
- new Observer(function () {
842
- // not initialised
843
- if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
844
- return;
845
- }
846
- // inform every element
847
- const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
848
-
849
- for (const list of updaters) {
850
- for (const updater of list) {
851
- let d = clone(self[internalSymbol].getRealSubject()["options"]);
852
- Object.assign(updater.getSubject(), d);
853
- }
854
- }
855
- }),
856
- );
857
-
858
- // disabled
859
- self[attributeObserverSymbol][ATTRIBUTE_DISABLED] = () => {
860
- if (self.hasAttribute(ATTRIBUTE_DISABLED)) {
861
- self.setOption(ATTRIBUTE_DISABLED, true);
862
- } else {
863
- self.setOption(ATTRIBUTE_DISABLED, undefined);
864
- }
865
- };
866
-
867
- // data-monster-options
868
- self[attributeObserverSymbol][ATTRIBUTE_OPTIONS] = () => {
869
- const options = getOptionsFromAttributes.call(self);
870
- if (isObject(options) && Object.keys(options).length > 0) {
871
- self.setOptions(options);
872
- }
873
- };
874
-
875
- // data-monster-options-selector
876
- self[attributeObserverSymbol][ATTRIBUTE_OPTIONS_SELECTOR] = () => {
877
- const options = getOptionsFromScriptTag.call(self);
878
- if (isObject(options) && Object.keys(options).length > 0) {
879
- self.setOptions(options);
880
- }
881
- };
835
+ const self = this;
836
+
837
+ let lastDisabledValue = undefined;
838
+ self.attachObserver(
839
+ new Observer(function () {
840
+ const flag = self.getOption("disabled");
841
+
842
+ if (flag === lastDisabledValue) {
843
+ return;
844
+ }
845
+
846
+ lastDisabledValue = flag;
847
+
848
+ if (!(self.shadowRoot instanceof ShadowRoot)) {
849
+ return;
850
+ }
851
+
852
+ const query =
853
+ "button, command, fieldset, keygen, optgroup, option, select, textarea, input, [data-monster-objectlink]";
854
+ const elements = self.shadowRoot.querySelectorAll(query);
855
+
856
+ let nodeList;
857
+ try {
858
+ nodeList = new Set([
859
+ ...elements,
860
+ ...getSlottedElements.call(self, query),
861
+ ]);
862
+ } catch (e) {
863
+ nodeList = elements;
864
+ }
865
+
866
+ for (const element of [...nodeList]) {
867
+ if (flag === true) {
868
+ element.setAttribute(ATTRIBUTE_DISABLED, "");
869
+ } else {
870
+ element.removeAttribute(ATTRIBUTE_DISABLED);
871
+ }
872
+ }
873
+ }),
874
+ );
875
+
876
+ self.attachObserver(
877
+ new Observer(function () {
878
+ // not initialised
879
+ if (!hasObjectLink(self, customElementUpdaterLinkSymbol)) {
880
+ return;
881
+ }
882
+ // inform every element
883
+ const updaters = getLinkedObjects(self, customElementUpdaterLinkSymbol);
884
+
885
+ for (const list of updaters) {
886
+ for (const updater of list) {
887
+ const d = clone(self[internalSymbol].getRealSubject()["options"]);
888
+ Object.assign(updater.getSubject(), d);
889
+ }
890
+ }
891
+ }),
892
+ );
893
+
894
+ // disabled
895
+ self[attributeObserverSymbol][ATTRIBUTE_DISABLED] = () => {
896
+ if (self.hasAttribute(ATTRIBUTE_DISABLED)) {
897
+ self.setOption(ATTRIBUTE_DISABLED, true);
898
+ } else {
899
+ self.setOption(ATTRIBUTE_DISABLED, undefined);
900
+ }
901
+ };
902
+
903
+ // data-monster-options
904
+ self[attributeObserverSymbol][ATTRIBUTE_OPTIONS] = () => {
905
+ const options = getOptionsFromAttributes.call(self);
906
+ if (isObject(options) && Object.keys(options).length > 0) {
907
+ self.setOptions(options);
908
+ }
909
+ };
910
+
911
+ // data-monster-options-selector
912
+ self[attributeObserverSymbol][ATTRIBUTE_OPTIONS_SELECTOR] = () => {
913
+ const options = getOptionsFromScriptTag.call(self);
914
+ if (isObject(options) && Object.keys(options).length > 0) {
915
+ self.setOptions(options);
916
+ }
917
+ };
882
918
  }
883
919
 
884
920
  /**
@@ -887,37 +923,37 @@ function initOptionObserver() {
887
923
  * @throws {TypeError} value is not a object
888
924
  */
889
925
  function getOptionsFromScriptTag() {
890
- const self = this;
891
-
892
- if (!self.hasAttribute(ATTRIBUTE_OPTIONS_SELECTOR)) {
893
- return {};
894
- }
895
-
896
- const node = document.querySelector(self.getAttribute(ATTRIBUTE_OPTIONS_SELECTOR));
897
- if (!(node instanceof HTMLScriptElement)) {
898
- addAttributeToken(
899
- self,
900
- ATTRIBUTE_ERRORMESSAGE,
901
- `the selector ${ATTRIBUTE_OPTIONS_SELECTOR} for options was specified (${self.getAttribute(
902
- ATTRIBUTE_OPTIONS_SELECTOR,
903
- )}) but not found.`,
904
- );
905
- return {};
906
- }
907
-
908
- let obj = {};
909
-
910
- try {
911
- obj = parseOptionsJSON.call(this, node.textContent.trim());
912
- } catch (e) {
913
- addAttributeToken(
914
- self,
915
- ATTRIBUTE_ERRORMESSAGE,
916
- `when analyzing the configuration from the script tag there was an error. ${e}`,
917
- );
918
- }
919
-
920
- return obj;
926
+ if (!this.hasAttribute(ATTRIBUTE_OPTIONS_SELECTOR)) {
927
+ return {};
928
+ }
929
+
930
+ const node = document.querySelector(
931
+ this.getAttribute(ATTRIBUTE_OPTIONS_SELECTOR),
932
+ );
933
+ if (!(node instanceof HTMLScriptElement)) {
934
+ addAttributeToken(
935
+ this,
936
+ ATTRIBUTE_ERRORMESSAGE,
937
+ `the selector ${ATTRIBUTE_OPTIONS_SELECTOR} for options was specified (${this.getAttribute(
938
+ ATTRIBUTE_OPTIONS_SELECTOR,
939
+ )}) but not found.`,
940
+ );
941
+ return {};
942
+ }
943
+
944
+ let obj = {};
945
+
946
+ try {
947
+ obj = parseOptionsJSON.call(this, node.textContent.trim());
948
+ } catch (e) {
949
+ addAttributeToken(
950
+ this,
951
+ ATTRIBUTE_ERRORMESSAGE,
952
+ `when analyzing the configuration from the script tag there was an error. ${e}`,
953
+ );
954
+ }
955
+
956
+ return obj;
921
957
  }
922
958
 
923
959
  /**
@@ -925,23 +961,21 @@ function getOptionsFromScriptTag() {
925
961
  * @return {object}
926
962
  */
927
963
  function getOptionsFromAttributes() {
928
- const self = this;
929
-
930
- if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
931
- try {
932
- return parseOptionsJSON.call(self, this.getAttribute(ATTRIBUTE_OPTIONS));
933
- } catch (e) {
934
- addAttributeToken(
935
- self,
936
- ATTRIBUTE_ERRORMESSAGE,
937
- `the options attribute ${ATTRIBUTE_OPTIONS} does not contain a valid json definition (actual: ${this.getAttribute(
938
- ATTRIBUTE_OPTIONS,
939
- )}).${e}`,
940
- );
941
- }
942
- }
943
-
944
- return {};
964
+ if (this.hasAttribute(ATTRIBUTE_OPTIONS)) {
965
+ try {
966
+ return parseOptionsJSON.call(this, this.getAttribute(ATTRIBUTE_OPTIONS));
967
+ } catch (e) {
968
+ addAttributeToken(
969
+ this,
970
+ ATTRIBUTE_ERRORMESSAGE,
971
+ `the options attribute ${ATTRIBUTE_OPTIONS} does not contain a valid json definition (actual: ${this.getAttribute(
972
+ ATTRIBUTE_OPTIONS,
973
+ )}).${e}`,
974
+ );
975
+ }
976
+ }
977
+
978
+ return {};
945
979
  }
946
980
 
947
981
  /**
@@ -950,25 +984,25 @@ function getOptionsFromAttributes() {
950
984
  * @return {Object}
951
985
  */
952
986
  function parseOptionsJSON(data) {
953
- let obj = {};
987
+ let obj = {};
954
988
 
955
- if (!isString(data)) {
956
- return obj;
957
- }
989
+ if (!isString(data)) {
990
+ return obj;
991
+ }
958
992
 
959
- // the configuration can be specified as a data url.
960
- try {
961
- let dataUrl = parseDataURL(data);
962
- data = dataUrl.content;
963
- } catch (e) {}
993
+ // the configuration can be specified as a data url.
994
+ try {
995
+ const dataUrl = parseDataURL(data);
996
+ data = dataUrl.content;
997
+ } catch (e) {}
964
998
 
965
- try {
966
- obj = JSON.parse(data);
967
- } catch (e) {
968
- throw e;
969
- }
999
+ try {
1000
+ obj = JSON.parse(data);
1001
+ } catch (e) {
1002
+ throw e;
1003
+ }
970
1004
 
971
- return validateObject(obj);
1005
+ return validateObject(obj);
972
1006
  }
973
1007
 
974
1008
  /**
@@ -976,21 +1010,21 @@ function parseOptionsJSON(data) {
976
1010
  * @return {initHtmlContent}
977
1011
  */
978
1012
  function initHtmlContent() {
979
- try {
980
- let template = findDocumentTemplate(this.constructor.getTag());
981
- this.appendChild(template.createDocumentFragment());
982
- } catch (e) {
983
- let html = this.getOption("templates.main", "");
984
- if (isString(html) && html.length > 0) {
985
- const mapping = this.getOption("templateMapping", {});
986
- if (isObject(mapping)) {
987
- html = new Formatter(mapping).format(html);
988
- }
989
- this.innerHTML = html;
990
- }
991
- }
992
-
993
- return this;
1013
+ try {
1014
+ const template = findDocumentTemplate(this.constructor.getTag());
1015
+ this.appendChild(template.createDocumentFragment());
1016
+ } catch (e) {
1017
+ let html = this.getOption("templates.main", "");
1018
+ if (isString(html) && html.length > 0) {
1019
+ const mapping = this.getOption("templateMapping", {});
1020
+ if (isObject(mapping)) {
1021
+ html = new Formatter(mapping).format(html);
1022
+ }
1023
+ this.innerHTML = html;
1024
+ }
1025
+ }
1026
+
1027
+ return this;
994
1028
  }
995
1029
 
996
1030
  /**
@@ -1003,51 +1037,49 @@ function initHtmlContent() {
1003
1037
  * @throws {TypeError} value is not an instance of
1004
1038
  */
1005
1039
  function initCSSStylesheet() {
1006
- const self = this;
1007
-
1008
- if (!(this.shadowRoot instanceof ShadowRoot)) {
1009
- return self;
1010
- }
1011
-
1012
- const styleSheet = this.constructor.getCSSStyleSheet();
1013
-
1014
- if (styleSheet instanceof CSSStyleSheet) {
1015
- if (styleSheet.cssRules.length > 0) {
1016
- this.shadowRoot.adoptedStyleSheets = [styleSheet];
1017
- }
1018
- } else if (isArray(styleSheet)) {
1019
- const assign = [];
1020
- for (let s of styleSheet) {
1021
- if (isString(s)) {
1022
- let trimedStyleSheet = s.trim();
1023
- if (trimedStyleSheet !== "") {
1024
- const style = document.createElement("style");
1025
- style.innerHTML = trimedStyleSheet;
1026
- self.shadowRoot.prepend(style);
1027
- }
1028
- continue;
1029
- }
1030
-
1031
- validateInstance(s, CSSStyleSheet);
1032
-
1033
- if (s.cssRules.length > 0) {
1034
- assign.push(s);
1035
- }
1036
- }
1037
-
1038
- if (assign.length > 0) {
1039
- this.shadowRoot.adoptedStyleSheets = assign;
1040
- }
1041
- } else if (isString(styleSheet)) {
1042
- let trimedStyleSheet = styleSheet.trim();
1043
- if (trimedStyleSheet !== "") {
1044
- const style = document.createElement("style");
1045
- style.innerHTML = styleSheet;
1046
- self.shadowRoot.prepend(style);
1047
- }
1048
- }
1049
-
1050
- return self;
1040
+ if (!(this.shadowRoot instanceof ShadowRoot)) {
1041
+ return this;
1042
+ }
1043
+
1044
+ const styleSheet = this.constructor.getCSSStyleSheet();
1045
+
1046
+ if (styleSheet instanceof CSSStyleSheet) {
1047
+ if (styleSheet.cssRules.length > 0) {
1048
+ this.shadowRoot.adoptedStyleSheets = [styleSheet];
1049
+ }
1050
+ } else if (isArray(styleSheet)) {
1051
+ const assign = [];
1052
+ for (const s of styleSheet) {
1053
+ if (isString(s)) {
1054
+ const trimedStyleSheet = s.trim();
1055
+ if (trimedStyleSheet !== "") {
1056
+ const style = document.createElement("style");
1057
+ style.innerHTML = trimedStyleSheet;
1058
+ this.shadowRoot.prepend(style);
1059
+ }
1060
+ continue;
1061
+ }
1062
+
1063
+ validateInstance(s, CSSStyleSheet);
1064
+
1065
+ if (s.cssRules.length > 0) {
1066
+ assign.push(s);
1067
+ }
1068
+ }
1069
+
1070
+ if (assign.length > 0) {
1071
+ this.shadowRoot.adoptedStyleSheets = assign;
1072
+ }
1073
+ } else if (isString(styleSheet)) {
1074
+ const trimedStyleSheet = styleSheet.trim();
1075
+ if (trimedStyleSheet !== "") {
1076
+ const style = document.createElement("style");
1077
+ style.innerHTML = styleSheet;
1078
+ this.shadowRoot.prepend(style);
1079
+ }
1080
+ }
1081
+
1082
+ return this;
1051
1083
  }
1052
1084
 
1053
1085
  /**
@@ -1060,35 +1092,35 @@ function initCSSStylesheet() {
1060
1092
  * @since 1.8.0
1061
1093
  */
1062
1094
  function initShadowRoot() {
1063
- let template;
1064
- let html;
1065
-
1066
- try {
1067
- template = findDocumentTemplate(this.constructor.getTag());
1068
- } catch (e) {
1069
- html = this.getOption("templates.main", "");
1070
- if (!isString(html) || html === undefined || html === "") {
1071
- throw new Error("html is not set.");
1072
- }
1073
- }
1074
-
1075
- this.attachShadow({
1076
- mode: this.getOption("shadowMode", "open"),
1077
- delegatesFocus: this.getOption("delegatesFocus", true),
1078
- });
1079
-
1080
- if (template instanceof Template) {
1081
- this.shadowRoot.appendChild(template.createDocumentFragment());
1082
- return this;
1083
- }
1084
-
1085
- const mapping = this.getOption("templateMapping", {});
1086
- if (isObject(mapping)) {
1087
- html = new Formatter(mapping).format(html);
1088
- }
1089
-
1090
- this.shadowRoot.innerHTML = html;
1091
- return this;
1095
+ let template;
1096
+ let html;
1097
+
1098
+ try {
1099
+ template = findDocumentTemplate(this.constructor.getTag());
1100
+ } catch (e) {
1101
+ html = this.getOption("templates.main", "");
1102
+ if (!isString(html) || html === undefined || html === "") {
1103
+ throw new Error("html is not set.");
1104
+ }
1105
+ }
1106
+
1107
+ this.attachShadow({
1108
+ mode: this.getOption("shadowMode", "open"),
1109
+ delegatesFocus: this.getOption("delegatesFocus", true),
1110
+ });
1111
+
1112
+ if (template instanceof Template) {
1113
+ this.shadowRoot.appendChild(template.createDocumentFragment());
1114
+ return this;
1115
+ }
1116
+
1117
+ const mapping = this.getOption("templateMapping", {});
1118
+ if (isObject(mapping)) {
1119
+ html = new Formatter(mapping).format(html);
1120
+ }
1121
+
1122
+ this.shadowRoot.innerHTML = html;
1123
+ return this;
1092
1124
  }
1093
1125
 
1094
1126
  /**
@@ -1103,15 +1135,20 @@ function initShadowRoot() {
1103
1135
  * @throws {DOMException} Failed to execute 'define' on 'CustomElementRegistry': is not a valid custom element name
1104
1136
  */
1105
1137
  function registerCustomElement(element) {
1106
- validateFunction(element);
1107
- const customElements = getGlobalObject("customElements");
1108
- if (customElements === undefined) {
1109
- throw new Error("customElements is not supported.");
1110
- }
1111
-
1112
- if (customElements.get(element.getTag()) !== undefined) {
1113
- return;
1114
- }
1115
-
1116
- customElements.define(element.getTag(), element);
1138
+ validateFunction(element);
1139
+ const customElements = getGlobalObject("customElements");
1140
+ if (customElements === undefined) {
1141
+ throw new Error("customElements is not supported.");
1142
+ }
1143
+
1144
+ const tag = element?.getTag();
1145
+ if (!isString(tag) || tag === "") {
1146
+ throw new Error("tag is not set.");
1147
+ }
1148
+
1149
+ if (customElements.get(tag) !== undefined) {
1150
+ return;
1151
+ }
1152
+
1153
+ customElements.define(tag, element);
1117
1154
  }