@shortfuse/materialdesignweb 0.5.0 → 0.7.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 (418) hide show
  1. package/README.md +155 -77
  2. package/bin/generate-css.js +12 -0
  3. package/components/Badge.css +30 -0
  4. package/components/Badge.js +15 -0
  5. package/components/Body.css +14 -0
  6. package/components/Body.js +7 -0
  7. package/components/BottomAppBar.css +23 -0
  8. package/components/BottomAppBar.js +25 -0
  9. package/components/Box.css +31 -0
  10. package/components/Box.js +24 -0
  11. package/components/Button.css +146 -0
  12. package/components/Button.js +95 -0
  13. package/components/Button.md +61 -0
  14. package/components/Card.css +109 -0
  15. package/components/Card.js +82 -0
  16. package/components/Checkbox.css +77 -0
  17. package/components/Checkbox.js +59 -0
  18. package/components/CheckboxIcon.css +89 -0
  19. package/components/CheckboxIcon.js +41 -0
  20. package/components/Chip.css +35 -0
  21. package/components/Chip.js +22 -0
  22. package/components/Dialog.css +235 -0
  23. package/components/Dialog.js +327 -0
  24. package/components/DialogActions.js +13 -0
  25. package/components/Divider.css +41 -0
  26. package/components/Divider.js +13 -0
  27. package/components/ExtendedFab.css +24 -0
  28. package/components/ExtendedFab.js +11 -0
  29. package/components/Fab.css +23 -0
  30. package/components/Fab.js +26 -0
  31. package/components/FilterChip.css +80 -0
  32. package/components/FilterChip.js +51 -0
  33. package/components/Headline.css +14 -0
  34. package/components/Headline.js +33 -0
  35. package/components/Icon.css +76 -0
  36. package/components/Icon.js +174 -0
  37. package/components/IconButton.css +151 -0
  38. package/components/IconButton.js +65 -0
  39. package/components/Input.js +16 -0
  40. package/components/Label.css +14 -0
  41. package/components/Label.js +7 -0
  42. package/components/Layout.css +19 -0
  43. package/components/Layout.js +12 -0
  44. package/components/List.css +12 -0
  45. package/components/List.js +17 -0
  46. package/components/ListItem.css +224 -0
  47. package/components/ListItem.js +112 -0
  48. package/components/ListOption.css +34 -0
  49. package/components/ListOption.js +122 -0
  50. package/components/ListSelect.css +9 -0
  51. package/components/ListSelect.js +206 -0
  52. package/components/Menu.css +171 -0
  53. package/components/Menu.js +470 -0
  54. package/components/MenuItem.css +53 -0
  55. package/components/MenuItem.js +215 -0
  56. package/components/Nav.css +17 -0
  57. package/components/Nav.js +23 -0
  58. package/components/NavBar.css +34 -0
  59. package/components/NavBar.js +88 -0
  60. package/components/NavBarItem.css +41 -0
  61. package/components/NavBarItem.js +7 -0
  62. package/components/NavDrawer.css +31 -0
  63. package/components/NavDrawer.js +13 -0
  64. package/components/NavDrawerItem.css +42 -0
  65. package/components/NavDrawerItem.js +12 -0
  66. package/components/NavItem.css +181 -0
  67. package/components/NavItem.js +83 -0
  68. package/components/NavRail.css +47 -0
  69. package/components/NavRail.js +17 -0
  70. package/components/NavRailItem.css +25 -0
  71. package/components/NavRailItem.js +7 -0
  72. package/components/Option.js +91 -0
  73. package/components/Outline.css +138 -0
  74. package/components/Pane.css +261 -0
  75. package/components/Pane.js +21 -0
  76. package/components/Progress.css +74 -0
  77. package/components/Progress.js +67 -0
  78. package/components/ProgressCircle.css +226 -0
  79. package/components/ProgressLine.css +155 -0
  80. package/components/Radio.css +83 -0
  81. package/components/Radio.js +42 -0
  82. package/components/RadioIcon.css +73 -0
  83. package/components/RadioIcon.js +37 -0
  84. package/components/Ripple.css +74 -0
  85. package/components/Ripple.js +114 -0
  86. package/components/SegmentedButton.css +94 -0
  87. package/components/SegmentedButton.js +49 -0
  88. package/components/SegmentedButtonGroup.css +12 -0
  89. package/components/SegmentedButtonGroup.js +44 -0
  90. package/components/Select.css +52 -0
  91. package/components/Select.js +71 -0
  92. package/components/Shape.css +132 -0
  93. package/components/Shape.js +25 -0
  94. package/components/Slider.css +306 -0
  95. package/components/Slider.js +206 -0
  96. package/components/Snackbar.css +80 -0
  97. package/components/Snackbar.js +75 -0
  98. package/components/Surface.css +10 -0
  99. package/components/Surface.js +23 -0
  100. package/components/Switch.css +63 -0
  101. package/components/Switch.js +127 -0
  102. package/components/SwitchIcon.css +177 -0
  103. package/components/SwitchIcon.js +89 -0
  104. package/components/SwitchIconAnimations.css +89 -0
  105. package/components/Tab.css +85 -0
  106. package/components/Tab.js +103 -0
  107. package/components/TabContent.js +151 -0
  108. package/components/TabList.css +129 -0
  109. package/components/TabList.js +309 -0
  110. package/components/TabPanel.js +37 -0
  111. package/components/TextArea.css +93 -0
  112. package/components/TextArea.js +229 -0
  113. package/components/Title.css +14 -0
  114. package/components/Title.js +15 -0
  115. package/components/Tooltip.css +40 -0
  116. package/components/Tooltip.js +22 -0
  117. package/components/TopAppBar.css +209 -0
  118. package/components/TopAppBar.js +201 -0
  119. package/core/Composition.js +988 -0
  120. package/core/CustomElement.js +844 -0
  121. package/core/ICustomElement.d.ts +288 -0
  122. package/core/ICustomElement.js +1 -0
  123. package/core/css.js +51 -0
  124. package/core/customTypes.js +125 -0
  125. package/core/dom.js +56 -154
  126. package/core/identify.js +40 -0
  127. package/core/observe.js +410 -0
  128. package/core/template.js +121 -0
  129. package/core/typings.d.ts +135 -0
  130. package/core/typings.js +1 -0
  131. package/mixins/AriaReflectorMixin.js +42 -0
  132. package/mixins/AriaToolbarMixin.js +13 -0
  133. package/mixins/ControlMixin.css +57 -0
  134. package/mixins/ControlMixin.js +212 -0
  135. package/mixins/DensityMixin.css +40 -0
  136. package/mixins/DensityMixin.js +11 -0
  137. package/mixins/FlexableMixin.css +79 -0
  138. package/mixins/FlexableMixin.js +32 -0
  139. package/mixins/FormAssociatedMixin.js +170 -0
  140. package/mixins/InputMixin.js +335 -0
  141. package/mixins/KeyboardNavMixin.js +244 -0
  142. package/mixins/RTLObserverMixin.js +35 -0
  143. package/mixins/ResizeObserverMixin.js +38 -0
  144. package/mixins/RippleMixin.css +12 -0
  145. package/mixins/RippleMixin.js +115 -0
  146. package/mixins/ScrollListenerMixin.js +100 -0
  147. package/mixins/ShapeMixin.css +135 -0
  148. package/mixins/ShapeMixin.js +31 -0
  149. package/mixins/StateMixin.css +82 -0
  150. package/mixins/StateMixin.js +114 -0
  151. package/mixins/SurfaceMixin.css +150 -0
  152. package/mixins/SurfaceMixin.js +32 -0
  153. package/mixins/TextFieldMixin.css +657 -0
  154. package/mixins/TextFieldMixin.js +121 -0
  155. package/mixins/ThemableMixin.css +204 -0
  156. package/mixins/ThemableMixin.js +16 -0
  157. package/mixins/TooltipTriggerMixin.css +27 -0
  158. package/mixins/TooltipTriggerMixin.js +366 -0
  159. package/mixins/TouchTargetMixin.css +26 -0
  160. package/mixins/TouchTargetMixin.js +9 -0
  161. package/package.json +54 -49
  162. package/theming/index.js +594 -0
  163. package/theming/loader.js +24 -0
  164. package/utils/cli.js +11 -0
  165. package/utils/color_keywords.js +151 -0
  166. package/utils/hct/Cam16.js +298 -0
  167. package/utils/hct/CorePalette.js +84 -0
  168. package/utils/hct/Hct.js +172 -0
  169. package/utils/hct/Scheme.js +587 -0
  170. package/utils/hct/TonalPalette.js +68 -0
  171. package/utils/hct/ViewingConditions.js +136 -0
  172. package/utils/hct/blend.js +93 -0
  173. package/utils/hct/colorUtils.js +302 -0
  174. package/utils/hct/hctSolver.js +559 -0
  175. package/utils/hct/helper.js +182 -0
  176. package/utils/hct/mathUtils.js +153 -0
  177. package/utils/jsonMergePatch.js +100 -0
  178. package/utils/jsx-runtime.js +101 -0
  179. package/utils/popup.js +117 -0
  180. package/utils/svg.js +129 -0
  181. package/.browserslistrc +0 -4
  182. package/.eslintrc.json +0 -204
  183. package/.stylelintrc.json +0 -645
  184. package/.vscode/launch.json +0 -31
  185. package/.vscode/settings.json +0 -3
  186. package/.vscode/tasks.json +0 -32
  187. package/CHANGELOG.md +0 -36
  188. package/CODE_OF_CONDUCT.md +0 -46
  189. package/adapters/datatable/column.js +0 -176
  190. package/adapters/datatable/index.js +0 -960
  191. package/adapters/dom/index.js +0 -586
  192. package/adapters/list/index.js +0 -69
  193. package/adapters/search/index.js +0 -495
  194. package/components/appbar/_spec.scss +0 -165
  195. package/components/appbar/_theme.scss +0 -0
  196. package/components/appbar/index.scss +0 -2
  197. package/components/banner/_spec.scss +0 -83
  198. package/components/banner/_theme.scss +0 -0
  199. package/components/banner/index.scss +0 -2
  200. package/components/bottomnav/README.md +0 -85
  201. package/components/bottomnav/_spec.scss +0 -149
  202. package/components/bottomnav/_theme.scss +0 -0
  203. package/components/bottomnav/index.js +0 -117
  204. package/components/bottomnav/index.scss +0 -2
  205. package/components/bottomnav/item.js +0 -88
  206. package/components/button/README.md +0 -61
  207. package/components/button/_spec.scss +0 -162
  208. package/components/button/_theme.scss +0 -42
  209. package/components/button/index.eta +0 -32
  210. package/components/button/index.js +0 -43
  211. package/components/button/index.pug +0 -18
  212. package/components/button/index.scss +0 -2
  213. package/components/card/_spec.scss +0 -241
  214. package/components/card/_theme.scss +0 -0
  215. package/components/card/index.scss +0 -2
  216. package/components/chip/_spec.scss +0 -111
  217. package/components/chip/_theme.scss +0 -105
  218. package/components/chip/index.js +0 -23
  219. package/components/chip/index.scss +0 -2
  220. package/components/chip/item.js +0 -20
  221. package/components/datatable/_spec.scss +0 -225
  222. package/components/datatable/_theme.scss +0 -128
  223. package/components/datatable/cell.js +0 -44
  224. package/components/datatable/columnheader.js +0 -46
  225. package/components/datatable/index.js +0 -374
  226. package/components/datatable/index.scss +0 -2
  227. package/components/datatable/row.js +0 -48
  228. package/components/datatable/rowheader.js +0 -18
  229. package/components/dialog/_spec.scss +0 -203
  230. package/components/dialog/_theme.scss +0 -7
  231. package/components/dialog/index.js +0 -601
  232. package/components/dialog/index.scss +0 -2
  233. package/components/divider/_spec.scss +0 -11
  234. package/components/divider/_theme.scss +0 -0
  235. package/components/divider/index.scss +0 -2
  236. package/components/elevation/_spec.scss +0 -9
  237. package/components/elevation/_theme.scss +0 -0
  238. package/components/elevation/index.scss +0 -2
  239. package/components/fab/_spec.scss +0 -210
  240. package/components/fab/_theme.scss +0 -0
  241. package/components/fab/index.js +0 -99
  242. package/components/fab/index.scss +0 -2
  243. package/components/grid/_spec.scss +0 -169
  244. package/components/grid/_theme.scss +0 -0
  245. package/components/grid/index.scss +0 -2
  246. package/components/layout/_mixins.scss +0 -11
  247. package/components/layout/_spec.scss +0 -916
  248. package/components/layout/_theme.scss +0 -19
  249. package/components/layout/index.js +0 -454
  250. package/components/layout/index.scss +0 -2
  251. package/components/list/_spec.scss +0 -363
  252. package/components/list/_theme.scss +0 -102
  253. package/components/list/content.js +0 -106
  254. package/components/list/index.js +0 -256
  255. package/components/list/index.scss +0 -2
  256. package/components/list/item.js +0 -167
  257. package/components/list/secondary.js +0 -45
  258. package/components/menu/_spec.scss +0 -329
  259. package/components/menu/_theme.scss +0 -0
  260. package/components/menu/index.js +0 -705
  261. package/components/menu/index.scss +0 -2
  262. package/components/menu/item.js +0 -231
  263. package/components/progress/_spec.scss +0 -156
  264. package/components/progress/_theme.scss +0 -0
  265. package/components/progress/index.js +0 -36
  266. package/components/progress/index.scss +0 -2
  267. package/components/selection/_spec.scss +0 -376
  268. package/components/selection/_theme.scss +0 -134
  269. package/components/selection/index.eta +0 -60
  270. package/components/selection/index.js +0 -70
  271. package/components/selection/index.pug +0 -30
  272. package/components/selection/index.scss +0 -2
  273. package/components/selection/input.js +0 -54
  274. package/components/selection/radiogroup.js +0 -40
  275. package/components/slider/_spec.scss +0 -59
  276. package/components/slider/_theme.scss +0 -0
  277. package/components/slider/index.scss +0 -2
  278. package/components/snackbar/_spec.scss +0 -150
  279. package/components/snackbar/_theme.scss +0 -0
  280. package/components/snackbar/index.js +0 -338
  281. package/components/snackbar/index.scss +0 -2
  282. package/components/tab/_spec.scss +0 -220
  283. package/components/tab/_theme.scss +0 -0
  284. package/components/tab/content.js +0 -210
  285. package/components/tab/index.js +0 -257
  286. package/components/tab/index.scss +0 -2
  287. package/components/tab/item.js +0 -88
  288. package/components/tab/list.js +0 -196
  289. package/components/tab/panel.js +0 -54
  290. package/components/textfield/README.md +0 -179
  291. package/components/textfield/_spec.scss +0 -763
  292. package/components/textfield/_theme.scss +0 -264
  293. package/components/textfield/index.eta +0 -74
  294. package/components/textfield/index.js +0 -160
  295. package/components/textfield/index.pug +0 -30
  296. package/components/textfield/index.scss +0 -2
  297. package/components/tooltip/_spec.scss +0 -185
  298. package/components/tooltip/_theme.scss +0 -0
  299. package/components/tooltip/index.scss +0 -2
  300. package/components/type/_spec.scss +0 -227
  301. package/components/type/_theme.scss +0 -0
  302. package/components/type/index.scss +0 -2
  303. package/core/_breakpoint.scss +0 -189
  304. package/core/_elevation.scss +0 -78
  305. package/core/_length.scss +0 -8
  306. package/core/_motion.scss +0 -31
  307. package/core/_platform.scss +0 -12
  308. package/core/_type.scss +0 -128
  309. package/core/aria/attributes.js +0 -141
  310. package/core/aria/button.js +0 -49
  311. package/core/aria/keyboard.js +0 -92
  312. package/core/aria/rovingtabindex.js +0 -175
  313. package/core/aria/tab.js +0 -59
  314. package/core/document/index.js +0 -39
  315. package/core/overlay/_spec.scss +0 -28
  316. package/core/overlay/_theme.scss +0 -147
  317. package/core/overlay/index.js +0 -95
  318. package/core/overlay/index.scss +0 -2
  319. package/core/ripple/_spec.scss +0 -196
  320. package/core/ripple/_theme.scss +0 -20
  321. package/core/ripple/index.js +0 -286
  322. package/core/ripple/index.scss +0 -2
  323. package/core/theme/_aliases.scss +0 -15
  324. package/core/theme/_config.scss +0 -8
  325. package/core/theme/_functions.scss +0 -22
  326. package/core/theme/_palettes.scss +0 -405
  327. package/core/theme/_spec.scss +0 -0
  328. package/core/theme/_theme.scss +0 -268
  329. package/core/theme/index.js +0 -50
  330. package/core/theme/index.scss +0 -4
  331. package/core/throttler.js +0 -42
  332. package/core/transition/index.js +0 -465
  333. package/docs/_flex.scss +0 -28
  334. package/docs/_menuoptions.js +0 -183
  335. package/docs/_partials/_androidnavbar.eta +0 -5
  336. package/docs/_partials/_androidstatusbar.eta +0 -13
  337. package/docs/_partials/_appbar.eta +0 -27
  338. package/docs/_partials/_buttontest.eta +0 -31
  339. package/docs/_partials/_header.eta +0 -146
  340. package/docs/_partials/_navlistitem.eta +0 -16
  341. package/docs/_partials/_target.eta +0 -1
  342. package/docs/_sample-utils.js +0 -88
  343. package/docs/_storage.js +0 -33
  344. package/docs/docs.scss +0 -331
  345. package/docs/framework.scss +0 -26
  346. package/docs/index.eta +0 -12
  347. package/docs/index.js +0 -7
  348. package/docs/pages/appbar.eta +0 -108
  349. package/docs/pages/appbar.js +0 -0
  350. package/docs/pages/bottomnav.eta +0 -188
  351. package/docs/pages/bottomnav.js +0 -118
  352. package/docs/pages/button.eta +0 -124
  353. package/docs/pages/button.js +0 -224
  354. package/docs/pages/card.eta +0 -90
  355. package/docs/pages/card.js +0 -175
  356. package/docs/pages/chip.eta +0 -122
  357. package/docs/pages/chip.js +0 -80
  358. package/docs/pages/color.eta +0 -143
  359. package/docs/pages/color.js +0 -261
  360. package/docs/pages/datatable.eta +0 -323
  361. package/docs/pages/datatable.js +0 -160
  362. package/docs/pages/dialog.eta +0 -184
  363. package/docs/pages/dialog.js +0 -174
  364. package/docs/pages/dom.eta +0 -26
  365. package/docs/pages/dom.js +0 -140
  366. package/docs/pages/elevation.eta +0 -35
  367. package/docs/pages/elevation.js +0 -0
  368. package/docs/pages/fab.eta +0 -99
  369. package/docs/pages/fab.js +0 -43
  370. package/docs/pages/grid.eta +0 -135
  371. package/docs/pages/grid.js +0 -128
  372. package/docs/pages/layout.eta +0 -8
  373. package/docs/pages/layout.js +0 -0
  374. package/docs/pages/list.eta +0 -465
  375. package/docs/pages/list.js +0 -8
  376. package/docs/pages/menu.eta +0 -274
  377. package/docs/pages/menu.js +0 -213
  378. package/docs/pages/overlay.eta +0 -69
  379. package/docs/pages/overlay.js +0 -3
  380. package/docs/pages/progress.eta +0 -23
  381. package/docs/pages/progress.js +0 -12
  382. package/docs/pages/ripple.eta +0 -27
  383. package/docs/pages/ripple.js +0 -3
  384. package/docs/pages/search.eta +0 -242
  385. package/docs/pages/search.js +0 -226
  386. package/docs/pages/selection.eta +0 -107
  387. package/docs/pages/selection.js +0 -12
  388. package/docs/pages/slider.eta +0 -23
  389. package/docs/pages/slider.js +0 -0
  390. package/docs/pages/snackbar.eta +0 -83
  391. package/docs/pages/snackbar.js +0 -157
  392. package/docs/pages/tab.eta +0 -407
  393. package/docs/pages/tab.js +0 -152
  394. package/docs/pages/textfield.eta +0 -487
  395. package/docs/pages/textfield.js +0 -257
  396. package/docs/pages/tooltip.eta +0 -92
  397. package/docs/pages/tooltip.js +0 -0
  398. package/docs/pages/transition.eta +0 -117
  399. package/docs/pages/transition.js +0 -52
  400. package/docs/pages/type.eta +0 -31
  401. package/docs/pages/type.js +0 -0
  402. package/docs/postrender.js +0 -41
  403. package/docs/prerender.js +0 -16
  404. package/docs/pwa/_dialogs.eta +0 -143
  405. package/docs/pwa/_menus.eta +0 -16
  406. package/docs/pwa/pwa-prerender.js +0 -3
  407. package/docs/pwa/pwa.eta +0 -478
  408. package/docs/pwa/pwa.js +0 -298
  409. package/docs/pwa/pwa.scss +0 -31
  410. package/docs/themes/theme-colored.scss +0 -15
  411. package/docs/themes/theme-default.scss +0 -3
  412. package/index.scss +0 -27
  413. package/jsconfig.json +0 -16
  414. package/scripts/deploy-docs.sh +0 -9
  415. package/templates/index.eta +0 -2
  416. package/templates/index.pug +0 -3
  417. package/tsconfig.json +0 -16
  418. package/webpack.config.js +0 -304
@@ -0,0 +1,844 @@
1
+ /* eslint-disable max-classes-per-file */
2
+
3
+ import Composition from './Composition.js';
4
+ import { ICustomElement } from './ICustomElement.js';
5
+ import { attrNameFromPropName, attrValueFromDataValue } from './dom.js';
6
+ import { defineObservableProperty } from './observe.js';
7
+ import { addInlineFunction, css, html } from './template.js';
8
+
9
+ /**
10
+ * @template {abstract new (...args: any) => unknown} T
11
+ * @param {InstanceType<T>} instance
12
+ */
13
+ function superOf(instance) {
14
+ const staticContext = instance.constructor;
15
+ const superOfStatic = Object.getPrototypeOf(staticContext);
16
+ return superOfStatic.prototype;
17
+ }
18
+
19
+ const EVENT_PREFIX_REGEX = /^([*1~]+)?(.*)$/;
20
+
21
+ /**
22
+ * Web Component that can cache templates for minification or performance
23
+ */
24
+ export default class CustomElement extends ICustomElement {
25
+ /** @type {string} */
26
+ static elementName;
27
+
28
+ /** @return {Iterable<string>} */
29
+ static get observedAttributes() {
30
+ const s = new Set();
31
+ for (const config of this.propList.values()) {
32
+ if (config.reflect === true || config.reflect === 'read') {
33
+ s.add(config.attr);
34
+ }
35
+ }
36
+ return s;
37
+ }
38
+
39
+ /** @type {import('./Composition.js').Compositor<?>} */
40
+ compose() {
41
+ if (this.#composition) {
42
+ console.warn('Already composed. Generating *new* composition...');
43
+ }
44
+ this.#composition = new Composition();
45
+ return this.#composition;
46
+ }
47
+
48
+ /** @type {Composition<?>} */
49
+ static _composition = null;
50
+
51
+ /** @type {Map<string, import('./typings.js').ObserverConfiguration<?,?,?>>} */
52
+ static _props = new Map();
53
+
54
+ /** @type {Map<string, Function[]>} */
55
+ static _propChangedCallbacks = new Map();
56
+
57
+ /** @type {Map<string, Function[]>} */
58
+ static _attributeChangedCallbacks = new Map();
59
+
60
+ /** @type {typeof ICustomElement._onComposeCallbacks} */
61
+ static _onComposeCallbacks = [];
62
+
63
+ /** @type {typeof ICustomElement._onConnectedCallbacks} */
64
+ static _onConnectedCallbacks = [];
65
+
66
+ /** @type {typeof ICustomElement._onDisconnectedCallbacks} */
67
+ static _onDisconnectedCallbacks = [];
68
+
69
+ /** @type {typeof ICustomElement._onConstructedCallbacks} */
70
+ static _onConstructedCallbacks = [];
71
+
72
+ static interpolatesTemplate = true;
73
+
74
+ static supportsElementInternals = 'attachInternals' in HTMLElement.prototype;
75
+
76
+ static supportsElementInternalsRole = CustomElement.supportsElementInternals
77
+ && 'role' in ElementInternals.prototype;
78
+
79
+ /** @type {boolean} */
80
+ static templatable = null;
81
+
82
+ static defined = false;
83
+
84
+ static autoRegistration = true;
85
+
86
+ /** @type {Map<string, typeof CustomElement>} */
87
+ static registrations = new Map();
88
+
89
+ /** @type {typeof ICustomElement.expressions} */
90
+ static expressions = this.set;
91
+
92
+ /** @type {typeof ICustomElement.methods} */
93
+ static methods = this.set;
94
+
95
+ /** @type {typeof ICustomElement.overrides} */
96
+ static overrides = this.set;
97
+
98
+ /** @type {typeof ICustomElement.props} */
99
+ static props = this.observe;
100
+
101
+ /**
102
+ * @template {typeof CustomElement} T
103
+ * @this T
104
+ * @template {keyof T} K
105
+ * @param {K} collection
106
+ * @param {T[K] extends (infer R)[] ? R : never} callback
107
+ */
108
+ static _addCallback(collection, callback) {
109
+ if (!this.hasOwnProperty(collection)) {
110
+ this[collection] = [
111
+ ...this[collection],
112
+ ];
113
+ }
114
+ this[collection].push(callback);
115
+ }
116
+
117
+ /**
118
+ * Append parts to composition
119
+ * @type {typeof ICustomElement.append}
120
+ */
121
+ static append(...parts) {
122
+ this.on({
123
+ composed({ composition }) {
124
+ // console.debug('onComposed:append', ...parts);
125
+ composition.append(...parts);
126
+ },
127
+ });
128
+ // @ts-expect-error Can't cast T
129
+ return this;
130
+ }
131
+
132
+ /**
133
+ * Appends styles to composition
134
+ * @type {typeof ICustomElement.css}
135
+ */
136
+ static css(array, ...substitutions) {
137
+ if (Array.isArray(array)) {
138
+ // @ts-expect-error Complex cast
139
+ this.append(css(array, ...substitutions));
140
+ } else {
141
+ // @ts-expect-error Complex cast
142
+ this.append(array, ...substitutions);
143
+ }
144
+ // @ts-expect-error Can't cast T
145
+ return this;
146
+ }
147
+
148
+ /** @type {typeof ICustomElement['setSchema']} */
149
+ static setSchema(schema) {
150
+ this.schema = schema;
151
+ // @ts-expect-error Can't cast T
152
+ return this;
153
+ }
154
+
155
+ /**
156
+ * Registers class asynchronously at end of current event loop cycle
157
+ * via `queueMicrotask`. If class is registered before then,
158
+ * does nothing.
159
+ * @type {typeof ICustomElement['autoRegister']}
160
+ */
161
+ static autoRegister(elementName) {
162
+ if (elementName) {
163
+ this.elementName = elementName;
164
+ }
165
+ queueMicrotask(() => {
166
+ if (this.autoRegistration) {
167
+ this.register();
168
+ }
169
+ });
170
+ // @ts-expect-error Can't cast T
171
+ return this;
172
+ }
173
+
174
+ /**
175
+ * Appends DocumentFragment to composition
176
+ * @type {typeof ICustomElement.html}
177
+ */
178
+ static html(strings, ...substitutions) {
179
+ this.on({
180
+ composed({ composition }) {
181
+ // console.log('onComposed:html', strings);
182
+ composition.append(html(strings, ...substitutions));
183
+ },
184
+ });
185
+ // @ts-expect-error Can't cast T
186
+ return this;
187
+ }
188
+
189
+ /**
190
+ * Extends base class into a new class.
191
+ * Use to avoid mutating base class.
192
+ * TODO: Add constructor arguments typing
193
+ * @type {typeof ICustomElement.extend}
194
+ */
195
+ static extend() {
196
+ // @ts-expect-error Can't cast T
197
+ return class ExtendedClass extends this {};
198
+ }
199
+
200
+ /**
201
+ * Extends base class into a new class.
202
+ * Use to avoid mutating base class.
203
+ * TODO: Add constructor arguments typing
204
+ * @type {typeof ICustomElement.tsClassFix}
205
+ */
206
+ static tsClassFix() {
207
+ // @ts-expect-error Can't cast T
208
+ return this;
209
+ }
210
+
211
+ /**
212
+ * Assigns static values to class
213
+ * @type {typeof ICustomElement.setStatic}
214
+ */
215
+ static setStatic(source) {
216
+ Object.assign(this, source);
217
+ // @ts-expect-error Can't cast T
218
+ return this;
219
+ }
220
+
221
+ /**
222
+ * Assigns values directly to all instances (via prototype)
223
+ * @type {typeof ICustomElement.set}
224
+ */
225
+ static readonly(source, options) {
226
+ // @ts-expect-error Can't cast T
227
+ return this.set(source, { ...options, writable: false });
228
+ }
229
+
230
+ /**
231
+ * Assigns values directly to all instances (via prototype)
232
+ * @type {typeof ICustomElement.set}
233
+ */
234
+ static set(source, options) {
235
+ Object.defineProperties(
236
+ this.prototype,
237
+ Object.fromEntries(
238
+ Object.entries(source).map(([name, value]) => {
239
+ // Tap into .map() to avoid double iteration
240
+ // Property may be redefined observable
241
+ this.undefine(name);
242
+ return [
243
+ name,
244
+ {
245
+ enumerable: name[0] !== '_',
246
+ configurable: true,
247
+ value,
248
+ writable: true,
249
+ ...options,
250
+ },
251
+ ];
252
+ }),
253
+ ),
254
+ );
255
+ // @ts-expect-error Can't cast T
256
+ return this;
257
+ }
258
+
259
+ /**
260
+ * Returns result of calling mixin with current class
261
+ * @type {typeof ICustomElement.mixin}
262
+ */
263
+ static mixin(mixin) {
264
+ return mixin(this);
265
+ }
266
+
267
+ /**
268
+ * Registers class with window.customElements synchronously
269
+ * @type {typeof ICustomElement['register']}
270
+ */
271
+ static register(elementName, force = false) {
272
+ if (this.hasOwnProperty('defined') && this.defined && !force) {
273
+ console.warn(this.elementName, 'already registered.');
274
+ // @ts-expect-error Can't cast T
275
+ return this;
276
+ }
277
+
278
+ if (elementName) {
279
+ this.elementName = elementName;
280
+ }
281
+
282
+ customElements.define(this.elementName, this);
283
+ CustomElement.registrations.set(this.elementName, this);
284
+ this.defined = true;
285
+ // @ts-expect-error Can't cast T
286
+ return this;
287
+ }
288
+
289
+ static get propList() {
290
+ if (!this.hasOwnProperty('_props')) {
291
+ this._props = new Map(this._props);
292
+ }
293
+ return this._props;
294
+ }
295
+
296
+ static get propChangedCallbacks() {
297
+ if (!this.hasOwnProperty('_propChangedCallbacks')) {
298
+ // structuredClone()
299
+ this._propChangedCallbacks = new Map(
300
+ [
301
+ ...this._propChangedCallbacks,
302
+ ].map(([name, array]) => [name, array.slice()]),
303
+ );
304
+ }
305
+ return this._propChangedCallbacks;
306
+ }
307
+
308
+ static get attributeChangedCallbacks() {
309
+ if (!this.hasOwnProperty('_attributeChangedCallbacks')) {
310
+ this._attributeChangedCallbacks = new Map(
311
+ [
312
+ ...this._attributeChangedCallbacks,
313
+ ].map(([name, array]) => [name, array.slice()]),
314
+ );
315
+ }
316
+ return this._attributeChangedCallbacks;
317
+ }
318
+
319
+ /**
320
+ * Creates observable property on instances (via prototype)
321
+ * @template {import('./typings.js').ObserverPropertyType} [T1=null]
322
+ * @template {import('./typings.js').ObserverPropertyType} [T2=null]
323
+ * @template {any} [T3=null]
324
+ * @param {string} name
325
+ * @param {T1|import('./typings.js').ObserverOptions<T2,T3>} [typeOrOptions='string']
326
+ * @return {(
327
+ * T3 extends null ?
328
+ * T2 extends null ?
329
+ * T1 extends null ?
330
+ * string
331
+ * : import('./typings.js').ParsedObserverPropertyType<T1>
332
+ * : import('./typings.js').ParsedObserverPropertyType<T2>
333
+ * : T3
334
+ * )}
335
+ */
336
+ static prop(name, typeOrOptions) {
337
+ // TODO: Cache and save configuration for reuse (mixins)
338
+ /** @type {import('./typings.js').ObserverOptions<?,?>} */
339
+ const options = {
340
+ ...((typeof typeOrOptions === 'string') ? { type: typeOrOptions } : typeOrOptions),
341
+ };
342
+
343
+ const customCallback = options.changedCallback;
344
+
345
+ if (customCallback) {
346
+ // Move callback to later in stack for attribute-based changes as well
347
+ this.onPropChanged({ [name]: customCallback });
348
+ }
349
+
350
+ // TODO: Inspect possible closure bloat
351
+ options.changedCallback = function wrappedChangedCallback(oldValue, newValue, changes) {
352
+ this._onObserverPropertyChanged.call(this, name, oldValue, newValue, changes);
353
+ };
354
+
355
+ const config = defineObservableProperty(this.prototype, name, options);
356
+
357
+ this.propList.set(name, config);
358
+ for (const [prop, callback] of config.watchers) {
359
+ this.on(`${prop}Changed`, callback);
360
+ }
361
+
362
+ return config.INIT_SYMBOL;
363
+ }
364
+
365
+ /**
366
+ * Define properties on instances via Object.defineProperties().
367
+ * Automatically sets property non-enumerable if name begins with `_`.
368
+ * @type {typeof ICustomElement.define}
369
+ */
370
+ static define(props) {
371
+ Object.defineProperties(
372
+ this.prototype,
373
+ Object.fromEntries(
374
+ Object.entries(props).map(([name, options]) => {
375
+ // Tap into .map() to avoid double iteration
376
+ // Property may be redefined observable
377
+ this.undefine(name);
378
+ return [
379
+ name,
380
+ {
381
+ enumerable: name[0] !== '_',
382
+ configurable: true,
383
+ ...(
384
+ typeof options === 'function'
385
+ ? { get: options }
386
+ : options
387
+ ),
388
+ },
389
+ ];
390
+ }),
391
+ ),
392
+ );
393
+
394
+ // @ts-expect-error Can't cast T
395
+ return this;
396
+ }
397
+
398
+ static undefine(name) {
399
+ Reflect.deleteProperty(this.prototype, name);
400
+ const config = this.propList.get(name);
401
+ if (config && config.watchers.length) {
402
+ const propWatchers = this.propChangedCallbacks.get(name);
403
+ if (propWatchers) {
404
+ for (const watcher of config.watchers) {
405
+ const index = propWatchers.indexOf(watcher);
406
+ if (index !== -1) {
407
+ console.warn('Unwatching', name);
408
+ propWatchers.splice(index, 1);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ this.propList.delete(name);
414
+ return this;
415
+ }
416
+
417
+ /**
418
+ * Creates observable properties on instances
419
+ * @type {typeof ICustomElement.observe}
420
+ */
421
+ static observe(props) {
422
+ for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
423
+ if (typeof typeOrOptions === 'function') {
424
+ this.prop(name, {
425
+ reflect: false,
426
+ get: typeOrOptions,
427
+ });
428
+ } else {
429
+ this.prop(name, typeOrOptions);
430
+ }
431
+ }
432
+ // @ts-expect-error Can't cast T
433
+ return this;
434
+ }
435
+
436
+ /** @type {typeof ICustomElement.defineStatic} */
437
+ static defineStatic(props) {
438
+ for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
439
+ const options = (typeof typeOrOptions === 'function')
440
+ ? { get: typeOrOptions }
441
+ : (typeof typeOrOptions === 'string'
442
+ ? { type: typeOrOptions }
443
+ : typeOrOptions);
444
+ defineObservableProperty(this, name, {
445
+ reflect: false,
446
+ ...options,
447
+ });
448
+ }
449
+ // @ts-expect-error Can't cast T
450
+ return this;
451
+ }
452
+
453
+ /** @type {typeof ICustomElement.events} */
454
+ static events(listeners, options) {
455
+ this.on({
456
+ composed({ composition }) {
457
+ for (const [key, listenerOptions] of Object.entries(listeners)) {
458
+ const [, flags, type] = key.match(EVENT_PREFIX_REGEX);
459
+ composition.addCompositionEventListener({
460
+ type,
461
+ once: flags?.includes('1'),
462
+ passive: flags?.includes('~'),
463
+ capture: flags?.includes('*'),
464
+ ...(
465
+ typeof listenerOptions === 'function'
466
+ ? { handleEvent: listenerOptions }
467
+ : (typeof listenerOptions === 'string'
468
+ ? { prop: listenerOptions }
469
+ : listenerOptions)
470
+ ),
471
+ ...(
472
+ options
473
+ )
474
+ ,
475
+ });
476
+ }
477
+ },
478
+ });
479
+
480
+ // @ts-expect-error Can't cast T
481
+ return this;
482
+ }
483
+
484
+ /** @type {typeof ICustomElement.childEvents} */
485
+ static childEvents(listenerMap, options) {
486
+ for (const [id, listeners] of Object.entries(listenerMap)) {
487
+ this.events(listeners, {
488
+ id,
489
+ ...options,
490
+ });
491
+ }
492
+
493
+ // @ts-expect-error Can't cast T
494
+ return this;
495
+ }
496
+
497
+ /** @type {typeof ICustomElement['on']} */
498
+ static on(nameOrCallbacks, callback) {
499
+ const callbacks = typeof nameOrCallbacks === 'string'
500
+ ? { [nameOrCallbacks]: callback }
501
+ : nameOrCallbacks;
502
+ for (const [name, fn] of Object.entries(callbacks)) {
503
+ /** @type {keyof (typeof CustomElement)} */
504
+ let arrayPropName;
505
+ switch (name) {
506
+ case 'composed': arrayPropName = '_onComposeCallbacks'; break;
507
+ case 'constructed': arrayPropName = '_onConstructedCallbacks'; break;
508
+ case 'connected': arrayPropName = '_onConnectedCallbacks'; break;
509
+ case 'disconnected': arrayPropName = '_onDisconnectedCallbacks'; break;
510
+ case 'props':
511
+ this.onPropChanged(fn);
512
+ continue;
513
+ case 'attrs':
514
+ this.onAttributeChanged(fn);
515
+ continue;
516
+ default:
517
+ if (name.endsWith('Changed')) {
518
+ const prop = name.slice(0, name.length - 'Changed'.length);
519
+ this.onPropChanged({ [prop]: fn });
520
+ continue;
521
+ }
522
+ throw new Error('Invalid callback name');
523
+ }
524
+ this._addCallback(arrayPropName, fn);
525
+ }
526
+
527
+ // @ts-expect-error Can't cast T
528
+ return this;
529
+ }
530
+
531
+ /** @type {typeof ICustomElement['onPropChanged']} */
532
+ static onPropChanged(options) {
533
+ for (const [prop, callback] of Object.entries(options)) {
534
+ let array = this.propChangedCallbacks.get(prop);
535
+ if (!array) {
536
+ array = [];
537
+ this.propChangedCallbacks.set(prop, array);
538
+ }
539
+ array.push(callback);
540
+ }
541
+
542
+ // @ts-expect-error Can't cast T
543
+ return this;
544
+ }
545
+
546
+ /** @type {typeof ICustomElement['onAttributeChanged']} */
547
+ static onAttributeChanged(options) {
548
+ for (const [name, callback] of Object.entries(options)) {
549
+ let array = this.attributeChangedCallbacks.get(name);
550
+ if (!array) {
551
+ array = [];
552
+ this.attributeChangedCallbacks.set(name, array);
553
+ }
554
+ array.push(callback);
555
+ }
556
+
557
+ // @ts-expect-error Can't cast T
558
+ return this;
559
+ }
560
+
561
+ /** @type {Record<string, HTMLElement>}} */
562
+ #refsProxy;
563
+
564
+ /** @type {Map<string, WeakRef<HTMLElement>>}} */
565
+ #refsCache = new Map();
566
+
567
+ /** @type {Map<string, WeakRef<HTMLElement>>}} */
568
+ #refsCompositionCache = new Map();
569
+
570
+ /** @type {Composition<?>} */
571
+ #composition;
572
+
573
+ /** @type {Map<string,null|[string,any]>} */
574
+ _propAttributeCache;
575
+
576
+ /** @type {import('./ICustomElement.js').CallbackArguments} */
577
+ _callbackArguments = null;
578
+
579
+ /** @param {any[]} args */
580
+ constructor(...args) {
581
+ super();
582
+
583
+ if (CustomElement.supportsElementInternals) {
584
+ this.elementInternals = this.attachInternals();
585
+ }
586
+
587
+ this.attachShadow({ mode: 'open', delegatesFocus: this.delegatesFocus });
588
+
589
+ this.composition.initialRender(this.shadowRoot, this);
590
+
591
+ for (const callback of this.static._onConstructedCallbacks) {
592
+ callback.call(this, this.callbackArguments);
593
+ }
594
+ }
595
+
596
+ /**
597
+ * Updates nodes based on data
598
+ * Expects data in JSON Merge Patch format
599
+ * @see https://www.rfc-editor.org/rfc/rfc7386
600
+ * @param {?} data
601
+ * @param {?} [store]
602
+ * @return {void}
603
+ */
604
+ render(data, store) {
605
+ // console.log('render', data);
606
+ this.composition.render(this.shadowRoot, data, this, store ? { ...this, store } : this);
607
+ }
608
+
609
+ /** @type {InstanceType<typeof ICustomElement>['propChangedCallback']} */
610
+ propChangedCallback(name, oldValue, newValue, changes = newValue) {
611
+ const callbacks = this.static.propChangedCallbacks.get(name);
612
+ if (callbacks) {
613
+ for (const callback of callbacks) {
614
+ callback.call(this, oldValue, newValue, changes, this);
615
+ }
616
+ }
617
+
618
+ this.render({ [name]: changes });
619
+ }
620
+
621
+ /**
622
+ * @param {string} name
623
+ * @param {string|null} oldValue
624
+ * @param {string|null} newValue
625
+ */
626
+ attributeChangedCallback(name, oldValue, newValue) {
627
+ const callbacks = this.static.attributeChangedCallbacks.get(name);
628
+ if (callbacks) {
629
+ for (const callback of callbacks) {
630
+ callback.call(this, oldValue, newValue, this);
631
+ }
632
+ }
633
+
634
+ // Array.find
635
+ for (const config of this.static.propList.values()) {
636
+ if (config.attr !== name) continue;
637
+
638
+ if (config.reflect !== true && config.reflect !== 'read') return;
639
+
640
+ if (config.attributeChangedCallback) {
641
+ config.attributeChangedCallback.call(this, name, oldValue, newValue);
642
+ return;
643
+ }
644
+
645
+ const [stringValue] = this.attributeCache.get(name) ?? [null, null];
646
+ if (stringValue === newValue) {
647
+ // Attribute was changed via data change event. Ignore.
648
+ return;
649
+ }
650
+
651
+ // @ts-expect-error any
652
+ const previousDataValue = this[config.key];
653
+ const parsedValue = newValue === null
654
+ ? config.nullParser(/** @type {null} */ (newValue))
655
+ // Avoid Boolean('') === false
656
+ : (config.type === 'boolean' ? true : config.parser(newValue));
657
+
658
+ if (parsedValue === previousDataValue) {
659
+ // No internal value change
660
+ return;
661
+ }
662
+ // "Remember" that this attrValue equates to this data value
663
+ // Avoids rewriting attribute later on data change event
664
+ this.attributeCache.set(name, [newValue, parsedValue]);
665
+ // @ts-expect-error any
666
+ this[config.key] = parsedValue;
667
+ return;
668
+ }
669
+ }
670
+
671
+ get #template() {
672
+ return this.#composition?.template;
673
+ }
674
+
675
+ /**
676
+ * @param {string} name
677
+ * @param {any} oldValue
678
+ * @param {any} newValue
679
+ * @param {any} changes
680
+ */
681
+ _onObserverPropertyChanged(name, oldValue, newValue, changes) {
682
+ const { reflect, attr } = this.static.propList.get(name);
683
+ if (attr && (reflect === true || reflect === 'write')) {
684
+ const [, dataValue] = this.attributeCache.get(attr) ?? [null, null];
685
+ // Don't change attribute if data value is equivalent
686
+ // (eg: Boolean('foo') === true; Number("1.0") === 1)
687
+ if (dataValue !== newValue) {
688
+ const attrValue = attrValueFromDataValue(newValue);
689
+ // Cache attrValue to ignore attributeChangedCallback later
690
+ this.attributeCache.set(attr, [attrValue, newValue]);
691
+ if (attrValue == null) {
692
+ this.removeAttribute(attr);
693
+ } else {
694
+ this.setAttribute(attr, attrValue);
695
+ }
696
+ }
697
+ }
698
+
699
+ // Invoke change => render
700
+ this.propChangedCallback(name, oldValue, newValue, changes);
701
+ }
702
+
703
+ /**
704
+ * Proxy object that returns shadow DOM elements by ID.
705
+ * If called before interpolation (eg: on composed), returns from template
706
+ * @return {Record<string,HTMLElement>}
707
+ */
708
+ get refs() {
709
+ // eslint-disable-next-line no-return-assign
710
+ return (this.#refsProxy ??= new Proxy({}, {
711
+ /**
712
+ * @param {any} target
713
+ * @param {string} id
714
+ * @return {Element}
715
+ */
716
+ get: (target, id) => {
717
+ if (!this.#composition) {
718
+ console.warn(this.static.name, 'Attempted to access references before composing!');
719
+ }
720
+ const composition = this.composition;
721
+ if (!composition.interpolated) {
722
+ let element = this.#refsCompositionCache.get(id)?.deref();
723
+ if (element) return element;
724
+ const formattedId = attrNameFromPropName(id);
725
+ // console.warn(this.tagName, 'Returning template reference');
726
+ element = composition.template.getElementById(formattedId);
727
+ if (!element) return null;
728
+ this.#refsCompositionCache.set(id, new WeakRef(element));
729
+ return element;
730
+ }
731
+ let element = this.#refsCache.get(id)?.deref();
732
+ if (element) {
733
+ return element;
734
+ }
735
+ const formattedId = attrNameFromPropName(id);
736
+ element = composition.getElement(this.shadowRoot, formattedId);
737
+ if (!element) return null;
738
+ this.#refsCache.set(id, new WeakRef(element));
739
+ return element;
740
+ },
741
+ }));
742
+ }
743
+
744
+ get attributeCache() {
745
+ this._propAttributeCache ??= new Map();
746
+ return this._propAttributeCache;
747
+ }
748
+
749
+ get tabIndex() {
750
+ return super.tabIndex;
751
+ }
752
+
753
+ set tabIndex(value) {
754
+ if (value === super.tabIndex && value !== -1) {
755
+ // Non -1 value already set
756
+ return;
757
+ }
758
+
759
+ if (this.delegatesFocus && document.activeElement === this) {
760
+ if (this.getAttribute('tabindex') === value.toString()) {
761
+ // Skip if possible
762
+ return;
763
+ }
764
+
765
+ // Chrome blurs on tabindex changes with delegatesFocus
766
+ // Fixed in Chrome 111
767
+ // Remove this code ~June 2023
768
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=1346606
769
+ /** @type {EventListener} */
770
+ const listener = (e) => {
771
+ e.stopImmediatePropagation();
772
+ e.stopPropagation();
773
+ if (e.type === 'blur') {
774
+ console.warn('Chromium bug 1346606: Tabindex change caused blur. Giving focusing back.', this);
775
+ this.focus();
776
+ } else {
777
+ console.warn('Chromium bug 1346606: Blocking focus event.', this);
778
+ }
779
+ };
780
+ this.addEventListener('blur', listener, { capture: true, once: true });
781
+ this.addEventListener('focus', listener, { capture: true, once: true });
782
+ super.tabIndex = value;
783
+ this.removeEventListener('blur', listener, { capture: true });
784
+ this.removeEventListener('focus', listener, { capture: true });
785
+ return;
786
+ }
787
+
788
+ super.tabIndex = value;
789
+ }
790
+
791
+ get static() { return /** @type {typeof CustomElement} */ (/** @type {unknown} */ (this.constructor)); }
792
+
793
+ get unique() { return false; }
794
+
795
+ get callbackArguments() {
796
+ // eslint-disable-next-line no-return-assign
797
+ return this._callbackArguments ??= {
798
+ composition: this.#composition,
799
+ html: html.bind(this),
800
+ inline: addInlineFunction,
801
+ template: this.#template,
802
+ element: this,
803
+ };
804
+ }
805
+
806
+ /** @return {Composition<?>} */
807
+ get composition() {
808
+ if (this.#composition) return this.#composition;
809
+
810
+ if (!this.unique && this.static.hasOwnProperty('_composition')) {
811
+ this.#composition = this.static._composition;
812
+ return this.static._composition;
813
+ }
814
+
815
+ // TODO: Use Composition to track uniqueness
816
+ // console.log('composing', this.static.elementName);
817
+ this.compose();
818
+ for (const callback of this.static._onComposeCallbacks) {
819
+ // console.log(this.static.elementName, 'composition callback');
820
+ callback.call(this, this.callbackArguments);
821
+ }
822
+
823
+ if (!this.unique) {
824
+ // Cache compilation into static property
825
+ this.static._composition = this.#composition;
826
+ }
827
+
828
+ return this.#composition;
829
+ }
830
+
831
+ connectedCallback() {
832
+ for (const callbacks of this.static._onConnectedCallbacks) {
833
+ callbacks.call(this, this.callbackArguments);
834
+ }
835
+ }
836
+
837
+ disconnectedCallback() {
838
+ for (const callbacks of this.static._onDisconnectedCallbacks) {
839
+ callbacks.call(this, this.callbackArguments);
840
+ }
841
+ }
842
+ }
843
+
844
+ CustomElement.prototype.delegatesFocus = false;