@shortfuse/materialdesignweb 0.8.0 → 0.9.1

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 (405) hide show
  1. package/README.md +50 -198
  2. package/bin/mdw-css.js +1 -1
  3. package/components/Badge.js +15 -5
  4. package/components/Body.js +7 -0
  5. package/components/BottomAppBar.js +7 -10
  6. package/components/BottomSheet.js +472 -0
  7. package/components/Box.js +11 -49
  8. package/components/Button.js +81 -82
  9. package/components/Card.js +74 -62
  10. package/components/Checkbox.js +15 -25
  11. package/components/CheckboxIcon.js +19 -31
  12. package/components/Chip.js +18 -13
  13. package/components/Dialog.js +70 -100
  14. package/components/DialogActions.js +4 -0
  15. package/components/Display.js +64 -0
  16. package/components/Divider.js +5 -0
  17. package/components/Fab.js +94 -17
  18. package/components/FabContainer.js +57 -0
  19. package/components/FilterChip.js +43 -32
  20. package/components/Grid.js +187 -0
  21. package/components/Headline.js +9 -28
  22. package/components/Icon.js +80 -71
  23. package/components/IconButton.js +77 -120
  24. package/components/Input.js +745 -86
  25. package/components/InputChip.js +193 -0
  26. package/components/Label.js +7 -0
  27. package/components/List.js +11 -5
  28. package/components/ListItem.js +92 -23
  29. package/components/ListOption.js +143 -65
  30. package/components/Listbox.js +57 -17
  31. package/components/Menu.js +39 -27
  32. package/components/MenuItem.js +49 -36
  33. package/components/NavBar.js +66 -21
  34. package/components/NavBarItem.js +5 -0
  35. package/components/NavDrawer.js +33 -16
  36. package/components/NavDrawerItem.js +7 -4
  37. package/components/NavItem.js +61 -34
  38. package/components/NavRail.js +32 -21
  39. package/components/NavRailItem.js +10 -2
  40. package/components/Page.js +119 -0
  41. package/components/Pane.js +24 -0
  42. package/components/Popup.js +23 -8
  43. package/components/Progress.js +25 -5
  44. package/components/Radio.js +8 -7
  45. package/components/RadioIcon.js +24 -15
  46. package/components/Ripple.js +25 -7
  47. package/components/Root.js +225 -0
  48. package/components/Scrim.js +95 -0
  49. package/components/Search.js +30 -25
  50. package/components/SegmentedButton.js +53 -40
  51. package/components/SegmentedButtonGroup.js +15 -12
  52. package/components/Select.js +19 -10
  53. package/components/Shape.js +10 -66
  54. package/components/SideSheet.js +337 -0
  55. package/components/Slider.js +93 -36
  56. package/components/Snackbar.js +52 -20
  57. package/components/SnackbarContainer.js +51 -0
  58. package/components/Surface.js +20 -10
  59. package/components/Switch.js +21 -18
  60. package/components/SwitchIcon.js +62 -33
  61. package/components/Tab.js +78 -38
  62. package/components/TabContent.js +33 -12
  63. package/components/TabList.js +95 -34
  64. package/components/TabPanel.js +10 -1
  65. package/components/Table.js +151 -0
  66. package/components/TextArea.js +48 -16
  67. package/components/Title.js +8 -9
  68. package/components/Tooltip.js +51 -22
  69. package/components/TopAppBar.js +71 -78
  70. package/constants/shapes.js +36 -0
  71. package/constants/typography.js +127 -0
  72. package/core/Composition.js +391 -201
  73. package/core/CompositionAdapter.js +35 -18
  74. package/core/CustomElement.js +634 -254
  75. package/core/css.js +117 -12
  76. package/core/customTypes.js +161 -49
  77. package/core/dom.js +18 -11
  78. package/core/jsonMergePatch.js +27 -11
  79. package/core/observe.js +308 -256
  80. package/core/optimizations.js +9 -9
  81. package/core/template.js +14 -57
  82. package/dist/CustomElement.min.js +2 -0
  83. package/dist/CustomElement.min.js.map +7 -0
  84. package/dist/core/CustomElement.min.js +2 -0
  85. package/dist/core/CustomElement.min.js.map +7 -0
  86. package/dist/index.min.js +85 -115
  87. package/dist/index.min.js.map +4 -4
  88. package/dist/meta.json +1 -1
  89. package/dom/HTMLOptionsCollectionProxy.js +108 -0
  90. package/{theming/themableMixinLoader.js → loaders/palette.js} +4 -3
  91. package/loaders/theme.js +12 -0
  92. package/mixins/AriaReflectorMixin.js +64 -15
  93. package/mixins/AriaToolbarMixin.js +6 -0
  94. package/mixins/ControlMixin.js +79 -33
  95. package/mixins/DelegatesFocusMixin.js +62 -0
  96. package/mixins/DensityMixin.js +7 -3
  97. package/mixins/ElevationMixin.js +61 -0
  98. package/mixins/FlexableMixin.js +87 -39
  99. package/mixins/FormAssociatedMixin.js +76 -10
  100. package/mixins/HyperlinkMixin.js +76 -0
  101. package/mixins/InputMixin.js +227 -32
  102. package/mixins/KeyboardNavMixin.js +11 -7
  103. package/mixins/NavigationListenerMixin.js +33 -0
  104. package/mixins/PopupMixin.js +216 -219
  105. package/mixins/RTLObserverMixin.js +2 -0
  106. package/mixins/ResizeObserverMixin.js +18 -4
  107. package/mixins/RippleMixin.js +11 -7
  108. package/mixins/ScrollListenerMixin.js +14 -2
  109. package/mixins/SemiStickyMixin.js +51 -98
  110. package/mixins/ShapeMaskedMixin.js +125 -0
  111. package/mixins/ShapeMixin.js +30 -203
  112. package/mixins/StateMixin.js +74 -34
  113. package/mixins/TextFieldMixin.js +128 -145
  114. package/mixins/ThemableMixin.js +57 -56
  115. package/mixins/TooltipTriggerMixin.js +305 -359
  116. package/mixins/TouchTargetMixin.js +5 -2
  117. package/mixins/TypographyMixin.js +128 -0
  118. package/package.json +125 -81
  119. package/services/rtl.js +10 -0
  120. package/services/svgAlias.js +17 -0
  121. package/{theming/index.js → services/theme.js} +25 -176
  122. package/types/bin/mdw-css.d.ts +3 -0
  123. package/types/bin/mdw-css.d.ts.map +1 -0
  124. package/types/components/Badge.d.ts +39 -0
  125. package/types/components/Badge.d.ts.map +1 -0
  126. package/types/components/Body.d.ts +29 -0
  127. package/types/components/Body.d.ts.map +1 -0
  128. package/types/components/BottomAppBar.d.ts +72 -0
  129. package/types/components/BottomAppBar.d.ts.map +1 -0
  130. package/types/components/BottomSheet.d.ts +135 -0
  131. package/types/components/BottomSheet.d.ts.map +1 -0
  132. package/types/components/Box.d.ts +16 -0
  133. package/types/components/Box.d.ts.map +1 -0
  134. package/types/components/Button.d.ts +245 -0
  135. package/types/components/Button.d.ts.map +1 -0
  136. package/types/components/Card.d.ts +147 -0
  137. package/types/components/Card.d.ts.map +1 -0
  138. package/types/components/Checkbox.d.ts +207 -0
  139. package/types/components/Checkbox.d.ts.map +1 -0
  140. package/types/components/CheckboxIcon.d.ts +44 -0
  141. package/types/components/CheckboxIcon.d.ts.map +1 -0
  142. package/types/components/Chip.d.ts +248 -0
  143. package/types/components/Chip.d.ts.map +1 -0
  144. package/types/components/Dialog.d.ts +103 -0
  145. package/types/components/Dialog.d.ts.map +1 -0
  146. package/types/components/DialogActions.d.ts +4 -0
  147. package/types/components/DialogActions.d.ts.map +1 -0
  148. package/types/components/Display.d.ts +46 -0
  149. package/types/components/Display.d.ts.map +1 -0
  150. package/types/components/Divider.d.ts +10 -0
  151. package/types/components/Divider.d.ts.map +1 -0
  152. package/types/components/Fab.d.ts +273 -0
  153. package/types/components/Fab.d.ts.map +1 -0
  154. package/types/components/FabContainer.d.ts +10 -0
  155. package/types/components/FabContainer.d.ts.map +1 -0
  156. package/types/components/FilterChip.d.ts +256 -0
  157. package/types/components/FilterChip.d.ts.map +1 -0
  158. package/types/components/Grid.d.ts +38 -0
  159. package/types/components/Grid.d.ts.map +1 -0
  160. package/types/components/Headline.d.ts +46 -0
  161. package/types/components/Headline.d.ts.map +1 -0
  162. package/types/components/Icon.d.ts +55 -0
  163. package/types/components/Icon.d.ts.map +1 -0
  164. package/types/components/IconButton.d.ts +284 -0
  165. package/types/components/IconButton.d.ts.map +1 -0
  166. package/types/components/Input.d.ts +2528 -0
  167. package/types/components/Input.d.ts.map +1 -0
  168. package/types/components/InputChip.d.ts +85 -0
  169. package/types/components/InputChip.d.ts.map +1 -0
  170. package/types/components/Label.d.ts +29 -0
  171. package/types/components/Label.d.ts.map +1 -0
  172. package/types/components/List.d.ts +35 -0
  173. package/types/components/List.d.ts.map +1 -0
  174. package/types/components/ListItem.d.ts +124 -0
  175. package/types/components/ListItem.d.ts.map +1 -0
  176. package/types/components/ListOption.d.ts +158 -0
  177. package/types/components/ListOption.d.ts.map +1 -0
  178. package/types/components/Listbox.d.ts +763 -0
  179. package/types/components/Listbox.d.ts.map +1 -0
  180. package/types/components/Menu.d.ts +130 -0
  181. package/types/components/Menu.d.ts.map +1 -0
  182. package/types/components/MenuItem.d.ts +232 -0
  183. package/types/components/MenuItem.d.ts.map +1 -0
  184. package/types/components/NavBar.d.ts +20 -0
  185. package/types/components/NavBar.d.ts.map +1 -0
  186. package/types/components/NavBarItem.d.ts +97 -0
  187. package/types/components/NavBarItem.d.ts.map +1 -0
  188. package/types/components/NavDrawer.d.ts +107 -0
  189. package/types/components/NavDrawer.d.ts.map +1 -0
  190. package/types/components/NavDrawerItem.d.ts +97 -0
  191. package/types/components/NavDrawerItem.d.ts.map +1 -0
  192. package/types/components/NavItem.d.ts +99 -0
  193. package/types/components/NavItem.d.ts.map +1 -0
  194. package/types/components/NavRail.d.ts +108 -0
  195. package/types/components/NavRail.d.ts.map +1 -0
  196. package/types/components/NavRailItem.d.ts +97 -0
  197. package/types/components/NavRailItem.d.ts.map +1 -0
  198. package/types/components/Page.d.ts +25 -0
  199. package/types/components/Page.d.ts.map +1 -0
  200. package/types/components/Pane.d.ts +44 -0
  201. package/types/components/Pane.d.ts.map +1 -0
  202. package/types/components/Popup.d.ts +78 -0
  203. package/types/components/Popup.d.ts.map +1 -0
  204. package/types/components/Progress.d.ts +21 -0
  205. package/types/components/Progress.d.ts.map +1 -0
  206. package/types/components/Radio.d.ts +201 -0
  207. package/types/components/Radio.d.ts.map +1 -0
  208. package/types/components/RadioIcon.d.ts +46 -0
  209. package/types/components/RadioIcon.d.ts.map +1 -0
  210. package/types/components/Ripple.d.ts +35 -0
  211. package/types/components/Ripple.d.ts.map +1 -0
  212. package/types/components/Root.d.ts +68 -0
  213. package/types/components/Root.d.ts.map +1 -0
  214. package/types/components/Scrim.d.ts +6 -0
  215. package/types/components/Scrim.d.ts.map +1 -0
  216. package/types/components/Search.d.ts +516 -0
  217. package/types/components/Search.d.ts.map +1 -0
  218. package/types/components/SegmentedButton.d.ts +252 -0
  219. package/types/components/SegmentedButton.d.ts.map +1 -0
  220. package/types/components/SegmentedButtonGroup.d.ts +43 -0
  221. package/types/components/SegmentedButtonGroup.d.ts.map +1 -0
  222. package/types/components/Select.d.ts +158 -0
  223. package/types/components/Select.d.ts.map +1 -0
  224. package/types/components/Shape.d.ts +10 -0
  225. package/types/components/Shape.d.ts.map +1 -0
  226. package/types/components/SideSheet.d.ts +111 -0
  227. package/types/components/SideSheet.d.ts.map +1 -0
  228. package/types/components/Slider.d.ts +203 -0
  229. package/types/components/Slider.d.ts.map +1 -0
  230. package/types/components/Snackbar.d.ts +73 -0
  231. package/types/components/Snackbar.d.ts.map +1 -0
  232. package/types/components/SnackbarContainer.d.ts +6 -0
  233. package/types/components/SnackbarContainer.d.ts.map +1 -0
  234. package/types/components/Surface.d.ts +45 -0
  235. package/types/components/Surface.d.ts.map +1 -0
  236. package/types/components/Switch.d.ts +187 -0
  237. package/types/components/Switch.d.ts.map +1 -0
  238. package/types/components/SwitchIcon.d.ts +61 -0
  239. package/types/components/SwitchIcon.d.ts.map +1 -0
  240. package/types/components/Tab.d.ts +139 -0
  241. package/types/components/Tab.d.ts.map +1 -0
  242. package/types/components/TabContent.d.ts +124 -0
  243. package/types/components/TabContent.d.ts.map +1 -0
  244. package/types/components/TabList.d.ts +1111 -0
  245. package/types/components/TabList.d.ts.map +1 -0
  246. package/types/components/TabPanel.d.ts +28 -0
  247. package/types/components/TabPanel.d.ts.map +1 -0
  248. package/types/components/Table.d.ts +25 -0
  249. package/types/components/Table.d.ts.map +1 -0
  250. package/types/components/TextArea.d.ts +201 -0
  251. package/types/components/TextArea.d.ts.map +1 -0
  252. package/types/components/Title.d.ts +46 -0
  253. package/types/components/Title.d.ts.map +1 -0
  254. package/types/components/Tooltip.d.ts +49 -0
  255. package/types/components/Tooltip.d.ts.map +1 -0
  256. package/types/components/TopAppBar.d.ts +129 -0
  257. package/types/components/TopAppBar.d.ts.map +1 -0
  258. package/types/constants/colorKeywords.d.ts +2 -0
  259. package/types/constants/colorKeywords.d.ts.map +1 -0
  260. package/types/constants/shapes.d.ts +38 -0
  261. package/types/constants/shapes.d.ts.map +1 -0
  262. package/types/constants/typography.d.ts +212 -0
  263. package/types/constants/typography.d.ts.map +1 -0
  264. package/types/core/Composition.d.ts +260 -0
  265. package/types/core/Composition.d.ts.map +1 -0
  266. package/types/core/CompositionAdapter.d.ts +114 -0
  267. package/types/core/CompositionAdapter.d.ts.map +1 -0
  268. package/types/core/CustomElement.d.ts +304 -0
  269. package/types/core/CustomElement.d.ts.map +1 -0
  270. package/types/core/css.d.ts +44 -0
  271. package/types/core/css.d.ts.map +1 -0
  272. package/types/core/customTypes.d.ts +22 -0
  273. package/types/core/customTypes.d.ts.map +1 -0
  274. package/types/core/dom.d.ts +32 -0
  275. package/types/core/dom.d.ts.map +1 -0
  276. package/types/core/jsonMergePatch.d.ts +31 -0
  277. package/types/core/jsonMergePatch.d.ts.map +1 -0
  278. package/types/core/observe.d.ts +114 -0
  279. package/types/core/observe.d.ts.map +1 -0
  280. package/types/core/optimizations.d.ts +7 -0
  281. package/types/core/optimizations.d.ts.map +1 -0
  282. package/types/core/template.d.ts +47 -0
  283. package/types/core/template.d.ts.map +1 -0
  284. package/types/core/uid.d.ts +6 -0
  285. package/types/core/uid.d.ts.map +1 -0
  286. package/types/dom/HTMLOptionsCollectionProxy.d.ts +18 -0
  287. package/types/dom/HTMLOptionsCollectionProxy.d.ts.map +1 -0
  288. package/types/index.d.ts +88 -0
  289. package/types/index.d.ts.map +1 -0
  290. package/types/loaders/palette.d.ts +2 -0
  291. package/types/loaders/palette.d.ts.map +1 -0
  292. package/types/loaders/theme.d.ts +2 -0
  293. package/types/loaders/theme.d.ts.map +1 -0
  294. package/types/mixins/AriaReflectorMixin.d.ts +31 -0
  295. package/types/mixins/AriaReflectorMixin.d.ts.map +1 -0
  296. package/types/mixins/AriaToolbarMixin.d.ts +34 -0
  297. package/types/mixins/AriaToolbarMixin.d.ts.map +1 -0
  298. package/types/mixins/ControlMixin.d.ts +124 -0
  299. package/types/mixins/ControlMixin.d.ts.map +1 -0
  300. package/types/mixins/DelegatesFocusMixin.d.ts +13 -0
  301. package/types/mixins/DelegatesFocusMixin.d.ts.map +1 -0
  302. package/types/mixins/DensityMixin.d.ts +8 -0
  303. package/types/mixins/DensityMixin.d.ts.map +1 -0
  304. package/types/mixins/ElevationMixin.d.ts +32 -0
  305. package/types/mixins/ElevationMixin.d.ts.map +1 -0
  306. package/types/mixins/FlexableMixin.d.ts +14 -0
  307. package/types/mixins/FlexableMixin.d.ts.map +1 -0
  308. package/types/mixins/FormAssociatedMixin.d.ts +123 -0
  309. package/types/mixins/FormAssociatedMixin.d.ts.map +1 -0
  310. package/types/mixins/HyperlinkMixin.d.ts +25 -0
  311. package/types/mixins/HyperlinkMixin.d.ts.map +1 -0
  312. package/types/mixins/InputMixin.d.ts +173 -0
  313. package/types/mixins/InputMixin.d.ts.map +1 -0
  314. package/types/mixins/KeyboardNavMixin.d.ts +46 -0
  315. package/types/mixins/KeyboardNavMixin.d.ts.map +1 -0
  316. package/types/mixins/NavigationListenerMixin.d.ts +8 -0
  317. package/types/mixins/NavigationListenerMixin.d.ts.map +1 -0
  318. package/types/mixins/PopupMixin.d.ts +98 -0
  319. package/types/mixins/PopupMixin.d.ts.map +1 -0
  320. package/types/mixins/RTLObserverMixin.d.ts +8 -0
  321. package/types/mixins/RTLObserverMixin.d.ts.map +1 -0
  322. package/types/mixins/ResizeObserverMixin.d.ts +13 -0
  323. package/types/mixins/ResizeObserverMixin.d.ts.map +1 -0
  324. package/types/mixins/RippleMixin.d.ts +94 -0
  325. package/types/mixins/RippleMixin.d.ts.map +1 -0
  326. package/types/mixins/ScrollListenerMixin.d.ts +46 -0
  327. package/types/mixins/ScrollListenerMixin.d.ts.map +1 -0
  328. package/types/mixins/SemiStickyMixin.d.ts +50 -0
  329. package/types/mixins/SemiStickyMixin.d.ts.map +1 -0
  330. package/types/mixins/ShapeMaskedMixin.d.ts +12 -0
  331. package/types/mixins/ShapeMaskedMixin.d.ts.map +1 -0
  332. package/types/mixins/ShapeMixin.d.ts +39 -0
  333. package/types/mixins/ShapeMixin.d.ts.map +1 -0
  334. package/types/mixins/StateMixin.d.ts +29 -0
  335. package/types/mixins/StateMixin.d.ts.map +1 -0
  336. package/types/mixins/TextFieldMixin.d.ts +153 -0
  337. package/types/mixins/TextFieldMixin.d.ts.map +1 -0
  338. package/types/mixins/ThemableMixin.d.ts +10 -0
  339. package/types/mixins/ThemableMixin.d.ts.map +1 -0
  340. package/types/mixins/TooltipTriggerMixin.d.ts +114 -0
  341. package/types/mixins/TooltipTriggerMixin.d.ts.map +1 -0
  342. package/types/mixins/TouchTargetMixin.d.ts +6 -0
  343. package/types/mixins/TouchTargetMixin.d.ts.map +1 -0
  344. package/types/mixins/TypographyMixin.d.ts +20 -0
  345. package/types/mixins/TypographyMixin.d.ts.map +1 -0
  346. package/types/services/rtl.d.ts +3 -0
  347. package/types/services/rtl.d.ts.map +1 -0
  348. package/types/services/svgAlias.d.ts +13 -0
  349. package/types/services/svgAlias.d.ts.map +1 -0
  350. package/types/services/theme.d.ts +45 -0
  351. package/types/services/theme.d.ts.map +1 -0
  352. package/types/utils/cli.d.ts +3 -0
  353. package/types/utils/cli.d.ts.map +1 -0
  354. package/types/utils/function.d.ts +3 -0
  355. package/types/utils/function.d.ts.map +1 -0
  356. package/types/utils/jsx-runtime.d.ts +20 -0
  357. package/types/utils/jsx-runtime.d.ts.map +1 -0
  358. package/types/utils/material-color/blend.d.ts +34 -0
  359. package/types/utils/material-color/blend.d.ts.map +1 -0
  360. package/types/utils/material-color/hct/Cam16.d.ts +142 -0
  361. package/types/utils/material-color/hct/Cam16.d.ts.map +1 -0
  362. package/types/utils/material-color/hct/Hct.d.ts +93 -0
  363. package/types/utils/material-color/hct/Hct.d.ts.map +1 -0
  364. package/types/utils/material-color/hct/ViewingConditions.d.ts +69 -0
  365. package/types/utils/material-color/hct/ViewingConditions.d.ts.map +1 -0
  366. package/types/utils/material-color/hct/hctSolver.d.ts +30 -0
  367. package/types/utils/material-color/hct/hctSolver.d.ts.map +1 -0
  368. package/types/utils/material-color/helper.d.ts +8 -0
  369. package/types/utils/material-color/helper.d.ts.map +1 -0
  370. package/types/utils/material-color/palettes/CorePalette.d.ts +75 -0
  371. package/types/utils/material-color/palettes/CorePalette.d.ts.map +1 -0
  372. package/types/utils/material-color/palettes/TonalPalette.d.ts +38 -0
  373. package/types/utils/material-color/palettes/TonalPalette.d.ts.map +1 -0
  374. package/types/utils/material-color/scheme/Scheme.d.ts +264 -0
  375. package/types/utils/material-color/scheme/Scheme.d.ts.map +1 -0
  376. package/types/utils/material-color/utils/color.d.ts +172 -0
  377. package/types/utils/material-color/utils/color.d.ts.map +1 -0
  378. package/types/utils/material-color/utils/math.d.ts +94 -0
  379. package/types/utils/material-color/utils/math.d.ts.map +1 -0
  380. package/types/utils/pixelmatch.d.ts +22 -0
  381. package/types/utils/pixelmatch.d.ts.map +1 -0
  382. package/types/utils/popup.d.ts +106 -0
  383. package/types/utils/popup.d.ts.map +1 -0
  384. package/types/utils/searchParams.d.ts +3 -0
  385. package/types/utils/searchParams.d.ts.map +1 -0
  386. package/types/utils/svg.d.ts +7 -0
  387. package/types/utils/svg.d.ts.map +1 -0
  388. package/utils/jsx-runtime.js +9 -4
  389. package/utils/material-color/scheme/Scheme.js +1 -1
  390. package/utils/pixelmatch.js +363 -0
  391. package/utils/popup.js +86 -10
  392. package/utils/searchParams.js +22 -0
  393. package/components/Button.md +0 -61
  394. package/components/ExtendedFab.js +0 -32
  395. package/components/Layout.js +0 -504
  396. package/components/Nav.js +0 -38
  397. package/core/DomAdapter.js +0 -586
  398. package/core/ICustomElement.d.ts +0 -291
  399. package/core/ICustomElement.js +0 -1
  400. package/core/test.js +0 -126
  401. package/core/typings.d.ts +0 -142
  402. package/core/typings.js +0 -1
  403. package/mixins/SurfaceMixin.js +0 -127
  404. package/theming/loader.js +0 -22
  405. /package/{utils/color_keywords.js → constants/colorKeywords.js} +0 -0
@@ -1,11 +1,117 @@
1
1
  /* eslint-disable max-classes-per-file */
2
2
 
3
3
  import Composition from './Composition.js';
4
- import { ICustomElement } from './ICustomElement.js';
4
+ import { css } from './css.js';
5
5
  import { attrNameFromPropName, attrValueFromDataValue } from './dom.js';
6
6
  import { applyMergePatch } from './jsonMergePatch.js';
7
7
  import { defineObservableProperty } from './observe.js';
8
- import { addInlineFunction, css, html } from './template.js';
8
+ import { addInlineFunction, html } from './template.js';
9
+
10
+ /** @typedef {import('./observe.js').ObserverPropertyType} ObserverPropertyType */
11
+
12
+ /**
13
+ * @template {any} T
14
+ * @typedef {{
15
+ * [P in keyof T]:
16
+ * T[P] extends (...args:any[]) => infer T2 ? T2
17
+ * : T[P] extends ObserverPropertyType
18
+ * ? import('./observe.js').ParsedObserverPropertyType<T[P]>
19
+ * : T[P] extends {type: ObserverPropertyType}
20
+ * ? import('./observe.js').ParsedObserverPropertyType<T[P]['type']>
21
+ * : T[P] extends ObserverOptions<null, infer T2>
22
+ * ? unknown extends T2 ? string : T2
23
+ * : never
24
+ * }} ParsedProps
25
+ */
26
+
27
+ /**
28
+ * @template {ObserverPropertyType} T1
29
+ * @template {any} T2
30
+ * @template {Object} [C=any]
31
+ * @typedef {import('./observe.js').ObserverOptions<T1,T2,C>} ObserverOptions
32
+ */
33
+
34
+ /**
35
+ * @template {{ prototype: unknown; }} T
36
+ * @typedef {T} ClassOf<T>
37
+ */
38
+
39
+ /**
40
+ * @template {any} [T=any]
41
+ * @template {any[]} [A=any[]]
42
+ * @typedef {abstract new (...args: A) => T} Class
43
+ */
44
+
45
+ /**
46
+ * @template {any} T1
47
+ * @template {any} [T2=T1]
48
+ * @callback HTMLTemplater
49
+ * @param {TemplateStringsArray} string
50
+ * @param {...(string|DocumentFragment|Element|((this:T1, data:T2) => any))} substitutions
51
+ * @return {DocumentFragment}
52
+ */
53
+
54
+ /**
55
+ * @template {any} [T1=any]
56
+ * @template {any} [T2=T1]
57
+ * @typedef {Object} CallbackArguments
58
+ * @prop {Composition<T1>} composition
59
+ * @prop {Record<string, HTMLElement>} refs
60
+ * @prop {HTMLTemplater<T1, Partial<T2>>} html
61
+ * @prop {(fn: (this:T1, data: T2) => any) => string} inline
62
+ * @prop {DocumentFragment} template
63
+ * @prop {T1} element
64
+ */
65
+
66
+ /**
67
+ * @template {any} T1
68
+ * @template {any} [T2=T1]
69
+ * @typedef {{
70
+ * composed?: (this: T1, options: CallbackArguments<T1, T2>) => any,
71
+ * constructed?: (this: T1, options: CallbackArguments<T1, T2>) => any,
72
+ * connected?: (this: T1, options: CallbackArguments<T1, T2>) => any,
73
+ * disconnected?: (this: T1, options: CallbackArguments<T1, T2>) => any,
74
+ * props?: {
75
+ * [P in keyof T1] : (
76
+ * this: T1,
77
+ * oldValue: T1[P],
78
+ * newValue: T1[P],
79
+ * changes:any,
80
+ * element: T1
81
+ * ) => any
82
+ * },
83
+ * attrs?: {[K in keyof any]: (
84
+ * this: T1,
85
+ * oldValue: string,
86
+ * newValue: string,
87
+ * element: T1
88
+ * ) => unknown
89
+ * },
90
+ * } & {
91
+ * [P in keyof T1 & string as `${P}Changed`]?: (
92
+ * this: T1,
93
+ * oldValue: T1[P],
94
+ * newValue: T1[P],
95
+ * changes:any,
96
+ * element: T1
97
+ * ) => any
98
+ * }} CompositionCallback
99
+ */
100
+
101
+ /**
102
+ * @template {Object} C
103
+ * @typedef {{
104
+ * [P in string] :
105
+ * ObserverPropertyType
106
+ * | ObserverOptions<ObserverPropertyType, unknown, C>
107
+ * | ((this:C, data:Partial<C>, fn?: () => any) => any)
108
+ * }} IDLParameter
109
+ */
110
+
111
+ /**
112
+ * @template T
113
+ * @typedef {(T | Array<[keyof T & string, T[keyof T]]>)} ObjectOrObjectEntries
114
+ */
9
115
 
10
116
  /**
11
117
  * @template {abstract new (...args: any) => unknown} T
@@ -33,57 +139,49 @@ export function cloneAttributeCallback(name, target) {
33
139
  };
34
140
  }
35
141
 
36
- const EVENT_PREFIX_REGEX = /^([*1~]+)?(.*)$/;
37
-
38
142
  /**
39
143
  * Web Component that can cache templates for minification or performance
40
144
  */
41
- export default class CustomElement extends ICustomElement {
145
+ export default class CustomElement extends HTMLElement {
42
146
  /** @type {string} */
43
147
  static elementName;
44
148
 
45
149
  /** @return {Iterable<string>} */
46
150
  static get observedAttributes() {
47
- const s = new Set();
48
- for (const config of this.propList.values()) {
49
- if (config.reflect === true || config.reflect === 'read') {
50
- s.add(config.attr);
51
- }
52
- }
53
- return s;
151
+ return this.attrList.keys();
54
152
  }
55
153
 
56
154
  /** @type {import('./Composition.js').Compositor<?>} */
57
155
  compose() {
58
- if (this.#composition) {
59
- console.warn('Already composed. Generating *new* composition...');
60
- }
61
- this.#composition = new Composition();
62
- return this.#composition;
156
+ // eslint-disable-next-line no-return-assign
157
+ return (this.#composition ??= new Composition());
63
158
  }
64
159
 
65
160
  /** @type {Composition<?>} */
66
161
  static _composition = null;
67
162
 
68
- /** @type {Map<string, import('./typings.js').ObserverConfiguration<?,?,?>>} */
163
+ /** @type {Map<string, import('./observe.js').ObserverConfiguration<?,?,?>>} */
69
164
  static _props = new Map();
70
165
 
71
- /** @type {Map<string, Function[]>} */
166
+ /** @type {Map<string, import('./observe.js').ObserverConfiguration<?,?,?>>} */
167
+ static _attrs = new Map();
168
+
169
+ /** @type {Map<string, Array<(this: any, ...args: any[]) => any>>} */
72
170
  static _propChangedCallbacks = new Map();
73
171
 
74
- /** @type {Map<string, Function[]>} */
172
+ /** @type {Map<string, Array<(this: any, ...args: any[]) => any>>} */
75
173
  static _attributeChangedCallbacks = new Map();
76
174
 
77
- /** @type {typeof ICustomElement._onComposeCallbacks} */
175
+ /** @type {Array<(callback: CallbackArguments) => any>} */
78
176
  static _onComposeCallbacks = [];
79
177
 
80
- /** @type {typeof ICustomElement._onConnectedCallbacks} */
178
+ /** @type {Array<(callback: CallbackArguments) => any>} */
81
179
  static _onConnectedCallbacks = [];
82
180
 
83
- /** @type {typeof ICustomElement._onDisconnectedCallbacks} */
181
+ /** @type {Array<(callback: CallbackArguments) => any>} */
84
182
  static _onDisconnectedCallbacks = [];
85
183
 
86
- /** @type {typeof ICustomElement._onConstructedCallbacks} */
184
+ /** @type {Array<(callback: CallbackArguments) => any>} */
87
185
  static _onConstructedCallbacks = [];
88
186
 
89
187
  static interpolatesTemplate = true;
@@ -103,127 +201,256 @@ export default class CustomElement extends ICustomElement {
103
201
  /** @type {Map<string, typeof CustomElement>} */
104
202
  static registrations = new Map();
105
203
 
106
- /** @type {typeof ICustomElement.expressions} */
107
- static expressions = this.set;
204
+ /**
205
+ * Expressions are idempotent functions that are selectively called whenever
206
+ * a render is requested.
207
+ * Expressions are constructed exactly as methods though differ in expected
208
+ * arguments. The first argument should be destructured to ensure each used
209
+ * property is accessed at least once in order to inspect used properties.
210
+ *
211
+ * The Composition API will inspect this function with a proxy for `this` to
212
+ * catalog what observables are used by the expression. This allows the
213
+ * Composition API to build a cache as well as selective invoke the expression
214
+ * only when needed.
215
+ *
216
+ * When used with in element templates, the element itself will be passed as
217
+ * its first argument.
218
+ * ````js
219
+ * Button
220
+ * .prop('filled', 'boolean')
221
+ * .prop('outlined', 'boolean')
222
+ * .expresssions({
223
+ * _isFilledOrOutlined({filled, outlined}) {
224
+ * return (filled || outlined)
225
+ * },
226
+ * })
227
+ * .html`<div custom={_isFilledOrOutlined}></div>`;
228
+ * ````
229
+ *
230
+ * When used with external data source, that data source
231
+ * will be passed to the expression with all properties being `null` at first
232
+ * inspection.
233
+ * ````js
234
+ * const externalData = {first: 'John', last: 'Doe'};
235
+ * ContactCard
236
+ * .expresssions({
237
+ * _fullName({first, last}) {
238
+ * return [first, last].filter(Boolean).join(' ');
239
+ * },
240
+ * })
241
+ * myButton.render(externalData);
242
+ * ````
243
+ *
244
+ * Expressions may be support argumentless calls by using default
245
+ * parameters with `this`.
246
+ * ````js
247
+ * Button
248
+ * .expresssions({
249
+ * isFilledOrOutlined({filled, outlined} = this) {
250
+ * return (filled || outlined)
251
+ * },
252
+ * });
253
+ * myButton.isFilledorOutlined();
254
+ * ````
255
+ * @type {{
256
+ * <
257
+ * CLASS extends typeof CustomElement,
258
+ * ARGS extends ConstructorParameters<CLASS>,
259
+ * INSTANCE extends InstanceType<CLASS>,
260
+ * PROPS extends {
261
+ * [K in keyof any]: K extends `_${any}` ? ((data: INSTANCE, state?: Record<string, any>) => string|boolean|null)
262
+ * : ((data?: INSTANCE, state?: Record<string, any>) => string|boolean|null)
263
+ * } & ThisType<INSTANCE>
264
+ * >(this: CLASS, expressions: PROPS & ThisType<INSTANCE & PROPS>):
265
+ * CLASS & Class<{
266
+ * [K in keyof PROPS]: K extends `_${any}` ? never : () => ReturnType<PROPS[K]> }
267
+ * ,ARGS>
268
+ * }}
269
+ */
270
+ static expressions = /** @type {any} */ (this.set);
108
271
 
109
- /** @type {typeof ICustomElement.methods} */
110
272
  static methods = this.set;
111
273
 
112
- /** @type {typeof ICustomElement.overrides} */
113
- static overrides = this.set;
274
+ /**
275
+ * @type {{
276
+ * <
277
+ * CLASS extends typeof CustomElement,
278
+ * ARGS extends ConstructorParameters<CLASS>,
279
+ * INSTANCE extends InstanceType<CLASS>,
280
+ * PROPS extends Partial<INSTANCE>>
281
+ * (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
282
+ * : CLASS & Class<PROPS,ARGS>
283
+ * }}
284
+ */
285
+ static overrides = /** @type {any} */ (this.set);
286
+
287
+ /**
288
+ * @type {{
289
+ * <
290
+ * CLASS extends typeof CustomElement,
291
+ * ARGS extends ConstructorParameters<CLASS>,
292
+ * INSTANCE extends InstanceType<CLASS>,
293
+ * KEY extends string,
294
+ * OPTIONS extends ObserverPropertyType
295
+ * | ObserverOptions<ObserverPropertyType, unknown, INSTANCE>
296
+ * | ((this:INSTANCE, data:Partial<INSTANCE>, fn?: () => any) => any),
297
+ * VALUE extends Record<KEY, OPTIONS extends (...args2:any[]) => infer R ? R
298
+ * : OPTIONS extends ObserverPropertyType ? import('./observe.js').ParsedObserverPropertyType<OPTIONS>
299
+ * : OPTIONS extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
300
+ * : OPTIONS extends {type: ObserverPropertyType} ? import('./observe.js').ParsedObserverPropertyType<OPTIONS['type']>
301
+ * : OPTIONS extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
302
+ * : never
303
+ * >
304
+ * > (this: CLASS, name: KEY, options: OPTIONS)
305
+ * : CLASS & Class<VALUE,ARGS>;
306
+ * }}
307
+ */
308
+ static props = /** @type {any} */ (this.observe);
114
309
 
115
- /** @type {typeof ICustomElement.props} */
116
- static props = this.observe;
310
+ static idl = this.prop;
117
311
 
118
312
  /**
119
- * @template {typeof CustomElement} T
120
313
  * @this T
314
+ * @template {typeof CustomElement} T
121
315
  * @template {keyof T} K
122
316
  * @param {K} collection
123
- * @param {T[K] extends (infer R)[] ? R : never} callback
317
+ * @param {Function} callback
124
318
  */
125
319
  static _addCallback(collection, callback) {
126
320
  if (!this.hasOwnProperty(collection)) {
127
- this[collection] = [
128
- ...this[collection],
129
- ];
321
+ // @ts-expect-error not typed
322
+ this[collection] = [...this[collection], callback];
323
+ return;
130
324
  }
325
+ // @ts-expect-error any
131
326
  this[collection].push(callback);
132
327
  }
133
328
 
134
329
  /**
135
330
  * Append parts to composition
136
- * @type {typeof ICustomElement.append}
331
+ * @type {{
332
+ * <
333
+ * T extends typeof CustomElement,
334
+ * >
335
+ * (this: T, ...parts: ConstructorParameters<typeof Composition<InstanceType<T>>>): T;
336
+ * }}
137
337
  */
138
338
  static append(...parts) {
139
- this.on({
140
- composed({ composition }) {
141
- // console.debug('onComposed:append', ...parts);
142
- composition.append(...parts);
143
- },
339
+ this._onComposeCallbacks.push(({ composition }) => {
340
+ composition.append(...parts);
144
341
  });
145
- // @ts-expect-error Can't cast T
342
+
343
+ this._addCallback('_onComposeCallbacks', /** @type {(opts: CallbackArguments) => unknown} */ ((opts) => {
344
+ const { composition } = opts;
345
+ composition.append(...parts);
346
+ }));
146
347
  return this;
147
348
  }
148
349
 
149
350
  /**
150
- * Appends styles to composition
151
- * @type {typeof ICustomElement.css}
351
+ * After composition, invokes callback.
352
+ * May be called multiple times.
353
+ * @type {{
354
+ * <
355
+ * T1 extends (typeof CustomElement),
356
+ * T2 extends InstanceType<T1>,
357
+ * T3 extends CompositionCallback<T2, T2>['composed'],
358
+ * >
359
+ * (this: T1, callback: T3): T1
360
+ * }}
152
361
  */
153
- static css(array, ...substitutions) {
154
- if (Array.isArray(array)) {
155
- // @ts-expect-error Complex cast
156
- this.append(css(array, ...substitutions));
157
- } else {
158
- // @ts-expect-error Complex cast
159
- this.append(array, ...substitutions);
160
- }
161
- // @ts-expect-error Can't cast T
362
+ static recompose(callback) {
363
+ this._addCallback('_onComposeCallbacks', callback);
162
364
  return this;
163
365
  }
164
366
 
165
- /** @type {typeof ICustomElement['setSchema']} */
166
- static setSchema(schema) {
167
- this.schema = schema;
168
- // @ts-expect-error Can't cast T
367
+ /**
368
+ * Appends styles to composition
369
+ * @type {{
370
+ * <
371
+ * T1 extends (typeof CustomElement),
372
+ * T2 extends TemplateStringsArray|HTMLStyleElement|CSSStyleSheet|string>(
373
+ * this: T1,
374
+ * array: T2,
375
+ * ...rest: T2 extends string ? any : T2 extends TemplateStringsArray ? any[] : (HTMLStyleElement|CSSStyleSheet)[]
376
+ * ): T1
377
+ * }}
378
+ */
379
+ static css(array, ...substitutions) {
380
+ this._addCallback('_onComposeCallbacks', /** @type {(opts: CallbackArguments) => unknown} */ ((opts) => {
381
+ const { composition } = opts;
382
+ if (typeof array === 'string' || Array.isArray(array)) {
383
+ // @ts-expect-error Complex cast
384
+ composition.append(css(array, ...substitutions));
385
+ } else {
386
+ // @ts-expect-error Complex cast
387
+ composition.append(array, ...substitutions);
388
+ }
389
+ }));
390
+
169
391
  return this;
170
392
  }
171
393
 
172
394
  /**
173
- * Registers class asynchronously at end of current event loop cycle
174
- * via `queueMicrotask`. If class is registered before then,
395
+ * Registers class with customElements. If class is registered before then,
175
396
  * does nothing.
176
- * @type {typeof ICustomElement['autoRegister']}
397
+ * @type {{
398
+ * <T extends typeof CustomElement>(this: T, elementName: string): T;
399
+ * }}
177
400
  */
178
401
  static autoRegister(elementName) {
179
402
  if (this.hasOwnProperty('defined') && this.defined) {
180
403
  console.warn(this.elementName, 'already registered.');
181
- // @ts-expect-error Can't cast T
182
404
  return this;
183
405
  }
184
406
  this.register(elementName);
185
- // @ts-expect-error Can't cast T
186
407
  return this;
187
408
  }
188
409
 
189
410
  /**
190
411
  * Appends DocumentFragment to composition
191
- * @type {typeof ICustomElement.html}
412
+ * @type {{
413
+ * <T extends typeof CustomElement>(
414
+ * this: T,
415
+ * string: TemplateStringsArray,
416
+ * ...substitutions: (string|Element|((this:InstanceType<T>, data:InstanceType<T>, injections?:any) => any))[]
417
+ * ): T
418
+ * }}
192
419
  */
193
420
  static html(strings, ...substitutions) {
194
- this.on({
195
- composed({ composition }) {
421
+ this._addCallback('_onComposeCallbacks', /** @type {(opts: CallbackArguments) => unknown} */ ((opts) => {
422
+ const { composition } = opts;
196
423
  // console.log('onComposed:html', strings);
197
- composition.append(html(strings, ...substitutions));
198
- },
199
- });
200
- // @ts-expect-error Can't cast T
424
+ composition.append(html(strings, ...substitutions));
425
+ }));
201
426
  return this;
202
427
  }
203
428
 
204
429
  /**
205
430
  * Extends base class into a new class.
206
431
  * Use to avoid mutating base class.
207
- * TODO: Add constructor arguments typing
208
- * @type {typeof ICustomElement.extend}
432
+ * @type {{
433
+ * <T1 extends typeof CustomElement, T2 extends T1, T3 extends (Base:T1) => T2>
434
+ * (this: T1,customExtender?: T3|null): T3 extends null ? T1 : T2;
435
+ * }}
209
436
  */
210
- static extend() {
437
+ static extend(customExtender) {
211
438
  // @ts-expect-error Can't cast T
212
- return class extends this {};
213
- }
214
-
215
- /**
216
- * Fix for Typescript not parsing constructor params
217
- * @type {typeof ICustomElement.tsClassFix}
218
- */
219
- static tsClassFix() {
220
- // @ts-expect-error Can't cast T
221
- return this;
439
+ return customExtender ? customExtender(this) : class extends this {};
222
440
  }
223
441
 
224
442
  /**
225
443
  * Assigns static values to class
226
- * @type {typeof ICustomElement.setStatic}
444
+ * @type {{
445
+ * <
446
+ * T1 extends typeof CustomElement,
447
+ * T2 extends {
448
+ * [K in keyof any]: (
449
+ * ((this:T1, ...args:any[]) => any)
450
+ * |string|number|boolean|any[]|object)}
451
+ * >
452
+ * (this: T1, source: T2 & ThisType<T1 & T2>):T1 & T2;
453
+ * }}
227
454
  */
228
455
  static setStatic(source) {
229
456
  Object.assign(this, source);
@@ -233,16 +460,31 @@ export default class CustomElement extends ICustomElement {
233
460
 
234
461
  /**
235
462
  * Assigns values directly to all instances (via prototype)
236
- * @type {typeof ICustomElement.set}
463
+ * @type {{
464
+ * <
465
+ * CLASS extends typeof CustomElement,
466
+ * ARGS extends ConstructorParameters<CLASS>,
467
+ * INSTANCE extends InstanceType<CLASS>,
468
+ * PROPS extends object>
469
+ * (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
470
+ * : CLASS & Class<PROPS,ARGS>
471
+ * }}
237
472
  */
238
473
  static readonly(source, options) {
239
- // @ts-expect-error Can't cast T
240
474
  return this.set(source, { ...options, writable: false });
241
475
  }
242
476
 
243
477
  /**
244
478
  * Assigns values directly to all instances (via prototype)
245
- * @type {typeof ICustomElement.set}
479
+ * @type {{
480
+ * <
481
+ * CLASS extends typeof CustomElement,
482
+ * ARGS extends ConstructorParameters<CLASS>,
483
+ * INSTANCE extends InstanceType<CLASS>,
484
+ * PROPS extends object>
485
+ * (this: CLASS, source: PROPS & ThisType<PROPS & INSTANCE>, options?: Partial<PropertyDescriptor>)
486
+ * : CLASS & Class<PROPS,ARGS>
487
+ * }}
246
488
  */
247
489
  static set(source, options) {
248
490
  Object.defineProperties(
@@ -268,6 +510,7 @@ export default class CustomElement extends ICustomElement {
268
510
  {
269
511
  enumerable: false,
270
512
  configurable: true,
513
+ // @ts-expect-error Can't index by symbol
271
514
  value: source[symbol],
272
515
  writable: true,
273
516
  ...options,
@@ -281,7 +524,14 @@ export default class CustomElement extends ICustomElement {
281
524
 
282
525
  /**
283
526
  * Returns result of calling mixin with current class
284
- * @type {typeof ICustomElement.mixin}
527
+ * @type {{
528
+ * <
529
+ * BASE extends typeof CustomElement,
530
+ * FN extends (...args:any[]) => any,
531
+ * RETURN extends ReturnType<FN>,
532
+ * SUBCLASS extends ClassOf<RETURN>,
533
+ * >(this: BASE, mixin: FN): SUBCLASS & BASE
534
+ * }}
285
535
  */
286
536
  static mixin(mixin) {
287
537
  return mixin(this);
@@ -289,7 +539,9 @@ export default class CustomElement extends ICustomElement {
289
539
 
290
540
  /**
291
541
  * Registers class with window.customElements synchronously
292
- * @type {typeof ICustomElement['register']}
542
+ * @type {{
543
+ * <T extends typeof CustomElement>(this: T, elementName?: string, force?: boolean): T;
544
+ * }}
293
545
  */
294
546
  static register(elementName) {
295
547
  if (elementName) {
@@ -299,7 +551,6 @@ export default class CustomElement extends ICustomElement {
299
551
  customElements.define(this.elementName, this);
300
552
  CustomElement.registrations.set(this.elementName, this);
301
553
  this.defined = true;
302
- // @ts-expect-error Can't cast T
303
554
  return this;
304
555
  }
305
556
 
@@ -310,6 +561,13 @@ export default class CustomElement extends ICustomElement {
310
561
  return this._props;
311
562
  }
312
563
 
564
+ static get attrList() {
565
+ if (!this.hasOwnProperty('_attrs')) {
566
+ this._attrs = new Map(this._attrs);
567
+ }
568
+ return this._attrs;
569
+ }
570
+
313
571
  static get propChangedCallbacks() {
314
572
  if (!this.hasOwnProperty('_propChangedCallbacks')) {
315
573
  // structuredClone()
@@ -335,55 +593,84 @@ export default class CustomElement extends ICustomElement {
335
593
 
336
594
  /**
337
595
  * Creates observable property on instances (via prototype)
338
- * @template {import('./typings.js').ObserverPropertyType} [T1=null]
339
- * @template {import('./typings.js').ObserverPropertyType} [T2=null]
340
- * @template {any} [T3=null]
341
- * @param {string} name
342
- * @param {T1|import('./typings.js').ObserverOptions<T2,T3>} [typeOrOptions='string']
343
- * @return {(
344
- * T3 extends null ?
345
- * T2 extends null ?
346
- * T1 extends null ?
347
- * string
348
- * : import('./typings.js').ParsedObserverPropertyType<T1>
349
- * : import('./typings.js').ParsedObserverPropertyType<T2>
350
- * : T3
351
- * )}
596
+ * @type {{
597
+ * <
598
+ * CLASS extends typeof CustomElement,
599
+ * ARGS extends ConstructorParameters<CLASS>,
600
+ * INSTANCE extends InstanceType<CLASS>,
601
+ * KEY extends string,
602
+ * OPTIONS extends ObserverPropertyType
603
+ * | ObserverOptions<ObserverPropertyType, unknown, INSTANCE>
604
+ * | ((this:INSTANCE, data:Partial<INSTANCE>, fn?: () => any) => any),
605
+ * VALUE extends Record<KEY, OPTIONS extends (...args2:any[]) => infer R ? R
606
+ * : OPTIONS extends ObserverPropertyType ? import('./observe').ParsedObserverPropertyType<OPTIONS>
607
+ * : OPTIONS extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
608
+ * : OPTIONS extends {type: ObserverPropertyType} ? import('./observe').ParsedObserverPropertyType<OPTIONS['type']>
609
+ * : OPTIONS extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
610
+ * : never
611
+ * >
612
+ * > (this: CLASS, name: KEY, options: OPTIONS)
613
+ * : CLASS & Class<VALUE,ARGS>
614
+ * }}
352
615
  */
353
616
  static prop(name, typeOrOptions) {
354
617
  // TODO: Cache and save configuration for reuse (mixins)
355
- /** @type {import('./typings.js').ObserverOptions<?,?>} */
356
- const options = {
357
- ...((typeof typeOrOptions === 'string') ? { type: typeOrOptions } : typeOrOptions),
358
- };
359
-
360
- const customCallback = options.changedCallback;
618
+ const config = defineObservableProperty(
619
+ /** @type {any} */ (this.prototype),
620
+ name,
621
+ /** @type {any} */ (typeOrOptions),
622
+ );
361
623
 
362
- if (customCallback) {
363
- // Move callback to later in stack for attribute-based changes as well
364
- this.onPropChanged({ [name]: customCallback });
624
+ const { changedCallback, attr, reflect, watchers } = config;
625
+ if (changedCallback) {
626
+ watchers.push([name, changedCallback]);
365
627
  }
366
-
367
628
  // TODO: Inspect possible closure bloat
368
- options.changedCallback = function wrappedChangedCallback(oldValue, newValue, changes) {
629
+ config.changedCallback = function wrappedChangedCallback(oldValue, newValue, changes) {
369
630
  this._onObserverPropertyChanged.call(this, name, oldValue, newValue, changes);
370
631
  };
371
632
 
372
- const config = defineObservableProperty(this.prototype, name, options);
373
-
374
633
  this.propList.set(name, config);
375
- for (const [prop, callback] of config.watchers) {
376
- this.on(`${prop}Changed`, callback);
634
+
635
+ if (attr
636
+ && (reflect === true || reflect === 'read')
637
+ && (config.enumerable || !this.attrList.has(attr) || !this.attrList.get(attr).enumerable)) {
638
+ this.attrList.set(attr, config);
377
639
  }
378
640
 
379
- return config.INIT_SYMBOL;
641
+ this.onPropChanged(watchers);
642
+
643
+ // @ts-expect-error Can't cast T
644
+ return this;
380
645
  }
381
646
 
382
647
  /**
383
648
  * Define properties on instances via Object.defineProperties().
384
649
  * Automatically sets property non-enumerable if name begins with `_`.
385
650
  * Functions will be remapped as getters
386
- * @type {typeof ICustomElement.define}
651
+ * @type {{
652
+ * <
653
+ * CLASS extends typeof CustomElement,
654
+ * ARGS extends ConstructorParameters<CLASS>,
655
+ * INSTANCE extends InstanceType<CLASS>,
656
+ * PROPS extends {
657
+ * [P in keyof any] :
658
+ * {
659
+ * enumerable?: boolean;
660
+ * configurable?: boolean;
661
+ * writable?: boolean;
662
+ * value?: any;
663
+ * get?: ((this: INSTANCE) => any);
664
+ * set?: (this: INSTANCE, value: any) => void;
665
+ * } | ((this: INSTANCE, ...args:any[]) => any)
666
+ * },
667
+ * VALUE extends {
668
+ * [KEY in keyof PROPS]: PROPS[KEY] extends (...args2:any[]) => infer R ? R
669
+ * : PROPS[KEY] extends TypedPropertyDescriptor<infer R> ? R : never
670
+ * }>
671
+ * (this: CLASS, props: PROPS & ThisType<PROPS & INSTANCE>): CLASS
672
+ * & Class<VALUE,ARGS>
673
+ * }}
387
674
  */
388
675
  static define(props) {
389
676
  Object.defineProperties(
@@ -413,13 +700,26 @@ export default class CustomElement extends ICustomElement {
413
700
  return this;
414
701
  }
415
702
 
703
+ /**
704
+ * Assigns values directly to all instances (via prototype)
705
+ * @type {{
706
+ * <
707
+ * CLASS extends typeof CustomElement,
708
+ * ARGS extends ConstructorParameters<CLASS>,
709
+ * INSTANCE extends InstanceType<CLASS>,
710
+ * PROP extends string,
711
+ * PROPS extends INSTANCE & Record<PROP, never>
712
+ * >(this: CLASS, name: PROP):
713
+ * CLASS & Class<PROPS,ARGS>
714
+ * }}
715
+ */
416
716
  static undefine(name) {
417
717
  Reflect.deleteProperty(this.prototype, name);
418
718
  if (this.propList.has(name)) {
419
- const config = this.propList.get(name);
420
- if (config.watchers.length && this.propChangedCallbacks.has(name)) {
719
+ const { watchers, attr, reflect } = this.propList.get(name);
720
+ if (watchers.length && this.propChangedCallbacks.has(name)) {
421
721
  const propWatchers = this.propChangedCallbacks.get(name);
422
- for (const watcher of config.watchers) {
722
+ for (const [prop, watcher] of watchers) {
423
723
  const index = propWatchers.indexOf(watcher);
424
724
  if (index !== -1) {
425
725
  console.warn('Unwatching', name);
@@ -427,31 +727,58 @@ export default class CustomElement extends ICustomElement {
427
727
  }
428
728
  }
429
729
  }
730
+ if (attr && (reflect === true || reflect === 'read')) {
731
+ this.attrList.delete(attr);
732
+ }
733
+ this.propList.delete(name);
430
734
  }
431
- this.propList.delete(name);
735
+
736
+ // @ts-expect-error Can't cast T
432
737
  return this;
433
738
  }
434
739
 
435
740
  /**
436
741
  * Creates observable properties on instances
437
- * @type {typeof ICustomElement.observe}
742
+ * @type {{
743
+ * <
744
+ * CLASS extends typeof CustomElement,
745
+ * ARGS extends ConstructorParameters<CLASS>,
746
+ * INSTANCE extends InstanceType<CLASS>,
747
+ * PROPS extends IDLParameter<INSTANCE & VALUE>,
748
+ * VALUE extends {
749
+ * [KEY in keyof PROPS]:
750
+ * PROPS[KEY] extends (...args2:any[]) => infer R ? R
751
+ * : PROPS[KEY] extends ObserverPropertyType ? import('./observe').ParsedObserverPropertyType<PROPS[KEY]>
752
+ * : PROPS[KEY] extends {type: 'object'} & ObserverOptions<any, infer R> ? (unknown extends R ? object : R)
753
+ * : PROPS[KEY] extends {type: ObserverPropertyType} ? import('./observe').ParsedObserverPropertyType<PROPS[KEY]['type']>
754
+ * : PROPS[KEY] extends ObserverOptions<any, infer R> ? (unknown extends R ? string : R)
755
+ * : never
756
+ * },
757
+ * > (this: CLASS, props: PROPS)
758
+ * : CLASS & Class<VALUE,ARGS>
759
+ * }}
438
760
  */
439
761
  static observe(props) {
440
762
  for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
441
- if (typeof typeOrOptions === 'function') {
442
- this.prop(name, {
443
- reflect: false,
444
- get: typeOrOptions,
445
- });
446
- } else {
447
- this.prop(name, typeOrOptions);
448
- }
763
+ /** @type {any} */
764
+ const options = (typeof typeOrOptions === 'function')
765
+ ? { reflect: false, get: typeOrOptions }
766
+ : typeOrOptions;
767
+
768
+ this.prop(name, options);
449
769
  }
450
770
  // @ts-expect-error Can't cast T
451
771
  return this;
452
772
  }
453
773
 
454
- /** @type {typeof ICustomElement.defineStatic} */
774
+ /**
775
+ * @type {{
776
+ * <
777
+ * T1 extends typeof CustomElement,
778
+ * T2 extends IDLParameter<T1>>
779
+ * (this: T1, props: T2):T1 & ParsedProps<T2>
780
+ * }}
781
+ */
455
782
  static defineStatic(props) {
456
783
  for (const [name, typeOrOptions] of Object.entries(props ?? {})) {
457
784
  const options = (typeof typeOrOptions === 'function')
@@ -459,6 +786,7 @@ export default class CustomElement extends ICustomElement {
459
786
  : (typeof typeOrOptions === 'string'
460
787
  ? { type: typeOrOptions }
461
788
  : typeOrOptions);
789
+ // @ts-expect-error Adding property to this
462
790
  defineObservableProperty(this, name, {
463
791
  reflect: false,
464
792
  ...options,
@@ -468,12 +796,21 @@ export default class CustomElement extends ICustomElement {
468
796
  return this;
469
797
  }
470
798
 
471
- /** @type {typeof ICustomElement.events} */
799
+ /**
800
+ * @type {{
801
+ * <T extends typeof CustomElement>
802
+ * (
803
+ * this: T,
804
+ * listeners?: import('./Composition').CompositionEventListenerObject<InstanceType<T>>,
805
+ * options?: Partial<import('./Composition').CompositionEventListener<InstanceType<T>>>,
806
+ * ): T;
807
+ * }}
808
+ */
472
809
  static events(listeners, options) {
473
810
  this.on({
474
811
  composed({ composition }) {
475
812
  for (const [key, listenerOptions] of Object.entries(listeners)) {
476
- const [, flags, type] = key.match(EVENT_PREFIX_REGEX);
813
+ const [, flags, type] = key.match(/^([*1~]+)?(.*)$/);
477
814
  // TODO: Make abstract
478
815
  let prop;
479
816
  /** @type {string[]} */
@@ -509,34 +846,51 @@ export default class CustomElement extends ICustomElement {
509
846
  },
510
847
  });
511
848
 
512
- // @ts-expect-error Can't cast T
513
849
  return this;
514
850
  }
515
851
 
516
- /** @type {typeof ICustomElement.childEvents} */
852
+ /**
853
+ * @type {{
854
+ * <T extends typeof CustomElement>
855
+ * (
856
+ * this: T,
857
+ * listenerMap: {
858
+ * [P in keyof any]: import('./Composition').CompositionEventListenerObject<InstanceType<T>>
859
+ * },
860
+ * options?: Partial<import('./Composition').CompositionEventListener<InstanceType<T>>>,
861
+ * ): T;
862
+ * }}
863
+ */
517
864
  static childEvents(listenerMap, options) {
518
865
  for (const [tag, listeners] of Object.entries(listenerMap)) {
519
- // @ts-expect-error Can't cast T
520
866
  this.events(listeners, {
521
867
  tag: attrNameFromPropName(tag),
522
868
  ...options,
523
869
  });
524
870
  }
525
871
 
526
- // @ts-expect-error Can't cast T
527
872
  return this;
528
873
  }
529
874
 
530
- /** @type {typeof ICustomElement.events} */
875
+ /** @type {typeof CustomElement['events']} */
531
876
  static rootEvents(listeners, options) {
532
- // @ts-expect-error Can't cast T
533
877
  return this.events(listeners, {
534
878
  tag: Composition.shadowRootTag,
535
879
  ...options,
536
880
  });
537
881
  }
538
882
 
539
- /** @type {typeof ICustomElement['on']} */
883
+ /**
884
+ * @type {{
885
+ * <
886
+ * T1 extends typeof CustomElement,
887
+ * T2 extends InstanceType<T1>,
888
+ * T3 extends CompositionCallback<T2, T2>,
889
+ * T4 extends keyof T3,
890
+ * >
891
+ * (this: T1, name: T3|T4, callbacks?: T3[T4] & ThisType<T2>): T1
892
+ * }}
893
+ */
540
894
  static on(nameOrCallbacks, callback) {
541
895
  const callbacks = typeof nameOrCallbacks === 'string'
542
896
  ? { [nameOrCallbacks]: callback }
@@ -558,6 +912,7 @@ export default class CustomElement extends ICustomElement {
558
912
  default:
559
913
  if (name.endsWith('Changed')) {
560
914
  const prop = name.slice(0, name.length - 'Changed'.length);
915
+ // @ts-expect-error Computed key
561
916
  this.onPropChanged({ [prop]: fn });
562
917
  continue;
563
918
  }
@@ -566,36 +921,73 @@ export default class CustomElement extends ICustomElement {
566
921
  this._addCallback(arrayPropName, fn);
567
922
  }
568
923
 
569
- // @ts-expect-error Can't cast T
570
924
  return this;
571
925
  }
572
926
 
573
- /** @type {typeof ICustomElement['onPropChanged']} */
927
+ /**
928
+ * @type {{
929
+ * <
930
+ * T1 extends typeof CustomElement,
931
+ * T2 extends InstanceType<T1>
932
+ * >
933
+ * (
934
+ * this: T1,
935
+ * options: ObjectOrObjectEntries<{
936
+ * [P in keyof T2]? : (
937
+ * this: T2,
938
+ * oldValue: T2[P],
939
+ * newValue: T2[P],
940
+ * changes:any,
941
+ * element: T2
942
+ * ) => void
943
+ * }>,
944
+ * ): T1;
945
+ * }}
946
+ */
574
947
  static onPropChanged(options) {
575
- for (const [prop, callback] of Object.entries(options)) {
576
- if (this.propChangedCallbacks.has(prop)) {
577
- this.propChangedCallbacks.get(prop).push(callback);
948
+ const entries = Array.isArray(options) ? options : Object.entries(options);
949
+ const { propChangedCallbacks } = this;
950
+ for (const [prop, callback] of entries) {
951
+ if (propChangedCallbacks.has(prop)) {
952
+ propChangedCallbacks.get(prop).push(callback);
578
953
  } else {
579
- this.propChangedCallbacks.set(prop, [callback]);
954
+ propChangedCallbacks.set(prop, [callback]);
580
955
  }
581
956
  }
582
957
 
583
- // @ts-expect-error Can't cast T
584
958
  return this;
585
959
  }
586
960
 
587
- /** @type {typeof ICustomElement['onAttributeChanged']} */
961
+ /**
962
+ * @type {{
963
+ * <
964
+ * T1 extends typeof CustomElement,
965
+ * T2 extends InstanceType<T1>
966
+ * >
967
+ * (
968
+ * this: T1,
969
+ * options: {
970
+ * [x:string]: (
971
+ * this: T2,
972
+ * oldValue: string,
973
+ * newValue: string,
974
+ * element: T2
975
+ * ) => void
976
+ * },
977
+ * ): T1;
978
+ * }}
979
+ */
588
980
  static onAttributeChanged(options) {
589
- for (const [name, callback] of Object.entries(options)) {
590
- const lcName = name.toLowerCase();
591
- if (this.attributeChangedCallbacks.has(lcName)) {
592
- this.attributeChangedCallbacks.get(lcName).push(callback);
981
+ const entries = Array.isArray(options) ? options : Object.entries(options);
982
+ const { attributeChangedCallbacks } = this;
983
+ for (const [name, callback] of entries) {
984
+ if (attributeChangedCallbacks.has(name)) {
985
+ attributeChangedCallbacks.get(name).push(callback);
593
986
  } else {
594
- this.attributeChangedCallbacks.set(lcName, [callback]);
987
+ attributeChangedCallbacks.set(name, [callback]);
595
988
  }
596
989
  }
597
990
 
598
- // @ts-expect-error Can't cast T
599
991
  return this;
600
992
  }
601
993
 
@@ -611,10 +1003,15 @@ export default class CustomElement extends ICustomElement {
611
1003
  /** @type {Composition<?>} */
612
1004
  #composition;
613
1005
 
1006
+ #patching = false;
1007
+
1008
+ /** @type {Array<[string, any, CustomElement]>} */
1009
+ #pendingPatchRenders = [];
1010
+
614
1011
  /** @type {Map<string,{stringValue:string, parsedValue:any}>} */
615
1012
  _propAttributeCache;
616
1013
 
617
- /** @type {import('./ICustomElement.js').CallbackArguments} */
1014
+ /** @type {CallbackArguments} */
618
1015
  _callbackArguments = null;
619
1016
 
620
1017
  /** @param {any[]} args */
@@ -636,11 +1033,12 @@ export default class CustomElement extends ICustomElement {
636
1033
  * @return {void}
637
1034
  */
638
1035
  this.render = this.composition.render(
639
- this,
1036
+ this.constructor.prototype,
640
1037
  this,
641
1038
  {
1039
+ defaults: this.constructor.prototype,
642
1040
  store: this,
643
- target: this.shadowRoot,
1041
+ shadowRoot: this.shadowRoot,
644
1042
  context: this,
645
1043
  },
646
1044
  );
@@ -650,15 +1048,29 @@ export default class CustomElement extends ICustomElement {
650
1048
  }
651
1049
  }
652
1050
 
653
- /** @type {InstanceType<typeof ICustomElement>['propChangedCallback']} */
1051
+ /**
1052
+ * @type {{
1053
+ * <
1054
+ * T extends CustomElement,
1055
+ * K extends string = string,
1056
+ * >(this:T,
1057
+ * name: K,
1058
+ * oldValue: K extends keyof T ? T[K] : unknown,
1059
+ * newValue: K extends keyof T ? T[K] : unknown,
1060
+ * changes?: K extends keyof T ? T[K] extends object ? Partial<T[K]> : T[K] : unknown): void;
1061
+ * }}
1062
+ */
654
1063
  propChangedCallback(name, oldValue, newValue, changes = newValue) {
655
- if (!this.patching) {
1064
+ if (this.#patching) {
1065
+ this.#pendingPatchRenders.push([name, changes, this]);
1066
+ } else {
656
1067
  this.render.byProp(name, changes, this);
657
1068
  // this.render({ [name]: changes });
658
1069
  }
659
1070
 
660
- if (this.static._propChangedCallbacks.has(name)) {
661
- for (const callback of this.static.propChangedCallbacks.get(name)) {
1071
+ const { _propChangedCallbacks } = this.static;
1072
+ if (_propChangedCallbacks.has(name)) {
1073
+ for (const callback of _propChangedCallbacks.get(name)) {
662
1074
  callback.call(this, oldValue, newValue, changes, this);
663
1075
  }
664
1076
  }
@@ -670,55 +1082,53 @@ export default class CustomElement extends ICustomElement {
670
1082
  * @param {string|null} newValue
671
1083
  */
672
1084
  attributeChangedCallback(name, oldValue, newValue) {
673
- const lcName = name.toLowerCase();
674
- if (this.static.attributeChangedCallbacks.has(lcName)) {
675
- for (const callback of this.static.attributeChangedCallbacks.get(lcName)) {
1085
+ const { attributeChangedCallbacks } = this.static;
1086
+ if (attributeChangedCallbacks.has(name)) {
1087
+ for (const callback of attributeChangedCallbacks.get(name)) {
676
1088
  callback.call(this, oldValue, newValue, this);
677
1089
  }
678
1090
  }
679
1091
 
680
1092
  // Array.find
681
- for (const config of this.static.propList.values()) {
682
- if (config.attr !== name) continue;
1093
+ const { attrList } = this.static;
1094
+ if (!attrList.has(name)) return;
683
1095
 
684
- if (config.reflect !== true && config.reflect !== 'read') return;
1096
+ const config = attrList.get(name);
685
1097
 
686
- if (config.attributeChangedCallback) {
687
- config.attributeChangedCallback.call(this, name, oldValue, newValue);
688
- return;
689
- }
1098
+ if (config.attributeChangedCallback) {
1099
+ config.attributeChangedCallback.call(this, name, oldValue, newValue);
1100
+ return;
1101
+ }
690
1102
 
691
- let cacheEntry;
692
- if (this.attributeCache.has(lcName)) {
693
- cacheEntry = this.attributeCache.get(lcName);
694
- if (cacheEntry.stringValue === newValue) return;
695
- }
1103
+ let cacheEntry;
1104
+ if (this.attributeCache.has(name)) {
1105
+ cacheEntry = this.attributeCache.get(name);
1106
+ if (cacheEntry.stringValue === newValue) return;
1107
+ }
696
1108
 
697
- // @ts-expect-error any
698
- const previousDataValue = this[config.key];
699
- const parsedValue = newValue === null
700
- ? config.nullParser(/** @type {null} */ (newValue))
701
- // Avoid Boolean('') === false
702
- : (config.type === 'boolean' ? true : config.parser(newValue));
1109
+ // @ts-expect-error any
1110
+ const previousDataValue = this[config.key];
1111
+ const parsedValue = newValue === null
1112
+ ? config.nullParser(/** @type {null} */ (newValue))
1113
+ // Avoid Boolean('') === false
1114
+ : (config.type === 'boolean' ? true : config.parser(newValue));
703
1115
 
704
- if (parsedValue === previousDataValue) {
705
- // No internal value change
706
- return;
707
- }
708
- // "Remember" that this attrValue equates to this data value
709
- // Avoids rewriting attribute later on data change event
710
- if (cacheEntry) {
711
- cacheEntry.stringValue = newValue;
712
- cacheEntry.parsedValue = parsedValue;
713
- } else {
714
- this.attributeCache.set(lcName, {
715
- stringValue: newValue, parsedValue,
716
- });
717
- }
718
- // @ts-expect-error any
719
- this[config.key] = parsedValue;
1116
+ if (parsedValue === previousDataValue) {
1117
+ // No internal value change
720
1118
  return;
721
1119
  }
1120
+ // "Remember" that this attrValue equates to this data value
1121
+ // Avoids rewriting attribute later on data change event
1122
+ if (cacheEntry) {
1123
+ cacheEntry.stringValue = newValue;
1124
+ cacheEntry.parsedValue = parsedValue;
1125
+ } else {
1126
+ this.attributeCache.set(name, {
1127
+ stringValue: newValue, parsedValue,
1128
+ });
1129
+ }
1130
+ // @ts-expect-error any
1131
+ this[config.key] = parsedValue;
722
1132
  }
723
1133
 
724
1134
  get #template() {
@@ -732,20 +1142,21 @@ export default class CustomElement extends ICustomElement {
732
1142
  * @param {any} changes
733
1143
  */
734
1144
  _onObserverPropertyChanged(name, oldValue, newValue, changes) {
735
- if (this.static.propList.has(name)) {
736
- const { reflect, attr } = this.static.propList.get(name);
1145
+ const { propList } = this.static;
1146
+ if (propList.has(name)) {
1147
+ const { reflect, attr } = propList.get(name);
737
1148
  if (attr && (reflect === true || reflect === 'write')) {
738
- const lcName = attr.toLowerCase();
739
1149
  /** @type {{stringValue:string, parsedValue:any}} */
740
1150
  let cacheEntry;
741
1151
  let needsWrite = false;
742
- if (this.attributeCache.has(lcName)) {
743
- cacheEntry = this.attributeCache.get(lcName);
1152
+ const { attributeCache } = this;
1153
+ if (attributeCache.has(attr)) {
1154
+ cacheEntry = attributeCache.get(attr);
744
1155
  needsWrite = (cacheEntry.parsedValue !== newValue);
745
1156
  } else {
746
1157
  // @ts-ignore skip cast
747
1158
  cacheEntry = {};
748
- this.attributeCache.set(lcName, cacheEntry);
1159
+ attributeCache.set(attr, cacheEntry);
749
1160
  needsWrite = true;
750
1161
  }
751
1162
  if (needsWrite) {
@@ -766,11 +1177,17 @@ export default class CustomElement extends ICustomElement {
766
1177
  this.propChangedCallback(name, oldValue, newValue, changes);
767
1178
  }
768
1179
 
1180
+ /** @param {any} patch */
769
1181
  patch(patch) {
770
- this.patching = true;
1182
+ this.#patching = true;
771
1183
  applyMergePatch(this, patch);
1184
+ for (const [name, changes, state] of this.#pendingPatchRenders) {
1185
+ if (name in patch) continue;
1186
+ this.render.byProp(name, changes, state);
1187
+ }
1188
+ this.#pendingPatchRenders.slice(0, this.#pendingPatchRenders.length);
772
1189
  this.render(patch);
773
- this.patching = false;
1190
+ this.#patching = false;
774
1191
  }
775
1192
 
776
1193
  /**
@@ -823,60 +1240,23 @@ export default class CustomElement extends ICustomElement {
823
1240
  }
824
1241
 
825
1242
  get attributeCache() {
826
- this._propAttributeCache ??= new Map();
827
- return this._propAttributeCache;
828
- }
829
-
830
- get tabIndex() {
831
- return super.tabIndex;
832
- }
833
-
834
- set tabIndex(value) {
835
- if (value === super.tabIndex && value !== -1) {
836
- // Non -1 value already set
837
- return;
838
- }
839
-
840
- if (this.delegatesFocus && document.activeElement === this) {
841
- if (this.getAttribute('tabindex') === value.toString()) {
842
- // Skip if possible
843
- return;
844
- }
845
-
846
- // Chrome blurs on tabindex changes with delegatesFocus
847
- // Fixed in Chrome 111
848
- // Remove this code ~June 2023
849
- // https://bugs.chromium.org/p/chromium/issues/detail?id=1346606
850
- /** @type {EventListener} */
851
- const listener = (e) => {
852
- e.stopImmediatePropagation();
853
- e.stopPropagation();
854
- if (e.type === 'blur') {
855
- console.warn('Chromium bug 1346606: Tabindex change caused blur. Giving focusing back.', this);
856
- this.focus();
857
- } else {
858
- console.warn('Chromium bug 1346606: Blocking focus event.', this);
859
- }
860
- };
861
- this.addEventListener('blur', listener, { capture: true, once: true });
862
- this.addEventListener('focus', listener, { capture: true, once: true });
863
- super.tabIndex = value;
864
- this.removeEventListener('blur', listener, { capture: true });
865
- this.removeEventListener('focus', listener, { capture: true });
866
- return;
867
- }
868
-
869
- super.tabIndex = value;
1243
+ // eslint-disable-next-line no-return-assign
1244
+ return (this._propAttributeCache ??= new Map());
870
1245
  }
871
1246
 
872
1247
  get static() { return /** @type {typeof CustomElement} */ (/** @type {unknown} */ (this.constructor)); }
873
1248
 
874
1249
  get unique() { return false; }
875
1250
 
1251
+ /**
1252
+ * @template {CustomElement} T
1253
+ * @this {T}
1254
+ */
876
1255
  get callbackArguments() {
877
1256
  // eslint-disable-next-line no-return-assign
878
1257
  return this._callbackArguments ??= {
879
1258
  composition: this.#composition,
1259
+ refs: this.refs,
880
1260
  html: html.bind(this),
881
1261
  inline: addInlineFunction,
882
1262
  template: this.#template,