@shortfuse/materialdesignweb 0.8.0 → 0.9.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 (394) hide show
  1. package/README.md +32 -24
  2. package/bin/mdw-css.js +1 -1
  3. package/components/Badge.js +12 -5
  4. package/components/Body.js +3 -0
  5. package/components/BottomAppBar.js +1 -8
  6. package/components/BottomSheet.js +424 -0
  7. package/components/Box.js +11 -49
  8. package/components/Button.js +61 -82
  9. package/components/Card.js +56 -61
  10. package/components/Checkbox.js +7 -25
  11. package/components/CheckboxIcon.js +10 -28
  12. package/components/Chip.js +13 -11
  13. package/components/Dialog.js +49 -98
  14. package/components/Display.js +55 -0
  15. package/components/Fab.js +83 -17
  16. package/components/FabContainer.js +48 -0
  17. package/components/FilterChip.js +34 -32
  18. package/components/Grid.js +176 -0
  19. package/components/Headline.js +5 -28
  20. package/components/Icon.js +54 -69
  21. package/components/IconButton.js +71 -120
  22. package/components/Input.js +669 -83
  23. package/components/InputChip.js +161 -0
  24. package/components/Label.js +3 -0
  25. package/components/List.js +1 -5
  26. package/components/ListItem.js +39 -23
  27. package/components/ListOption.js +79 -62
  28. package/components/Listbox.js +19 -10
  29. package/components/Menu.js +8 -18
  30. package/components/MenuItem.js +25 -26
  31. package/components/NavBar.js +53 -19
  32. package/components/NavDrawer.js +15 -15
  33. package/components/NavDrawerItem.js +2 -4
  34. package/components/NavItem.js +40 -33
  35. package/components/NavRail.js +23 -21
  36. package/components/NavRailItem.js +5 -2
  37. package/components/Page.js +105 -0
  38. package/components/Pane.js +18 -0
  39. package/components/Popup.js +17 -8
  40. package/components/Radio.js +2 -5
  41. package/components/RadioIcon.js +10 -14
  42. package/components/Ripple.js +11 -7
  43. package/components/Root.js +209 -0
  44. package/components/Scrim.js +87 -0
  45. package/components/Search.js +12 -20
  46. package/components/SegmentedButton.js +33 -36
  47. package/components/SegmentedButtonGroup.js +9 -3
  48. package/components/Select.js +6 -7
  49. package/components/Shape.js +5 -65
  50. package/components/SideSheet.js +308 -0
  51. package/components/Slider.js +71 -34
  52. package/components/Snackbar.js +22 -16
  53. package/components/SnackbarContainer.js +42 -0
  54. package/components/Surface.js +15 -10
  55. package/components/Switch.js +3 -16
  56. package/components/SwitchIcon.js +40 -32
  57. package/components/Tab.js +57 -38
  58. package/components/TabContent.js +1 -0
  59. package/components/TabList.js +60 -32
  60. package/components/TabPanel.js +1 -1
  61. package/components/Table.js +116 -0
  62. package/components/TextArea.js +16 -15
  63. package/components/Title.js +4 -9
  64. package/components/Tooltip.js +43 -21
  65. package/components/TopAppBar.js +56 -78
  66. package/constants/shapes.js +36 -0
  67. package/constants/typography.js +127 -0
  68. package/core/Composition.js +354 -192
  69. package/core/CompositionAdapter.js +11 -12
  70. package/core/CustomElement.js +588 -236
  71. package/core/css.js +117 -12
  72. package/core/customTypes.js +120 -25
  73. package/core/dom.js +17 -11
  74. package/core/jsonMergePatch.js +12 -10
  75. package/core/observe.js +298 -253
  76. package/core/optimizations.js +9 -9
  77. package/core/template.js +14 -57
  78. package/dist/index.min.js +85 -115
  79. package/dist/index.min.js.map +4 -4
  80. package/dist/meta.json +1 -1
  81. package/dom/HTMLOptionsCollectionProxy.js +106 -0
  82. package/{theming/themableMixinLoader.js → loaders/palette.js} +4 -3
  83. package/loaders/theme.js +12 -0
  84. package/mixins/AriaReflectorMixin.js +53 -13
  85. package/mixins/AriaToolbarMixin.js +3 -0
  86. package/mixins/ControlMixin.js +76 -33
  87. package/mixins/DelegatesFocusMixin.js +54 -0
  88. package/mixins/DensityMixin.js +2 -2
  89. package/mixins/ElevationMixin.js +62 -0
  90. package/mixins/FlexableMixin.js +66 -37
  91. package/mixins/FormAssociatedMixin.js +60 -8
  92. package/mixins/HyperlinkMixin.js +66 -0
  93. package/mixins/InputMixin.js +205 -32
  94. package/mixins/KeyboardNavMixin.js +8 -6
  95. package/mixins/NavigationListenerMixin.js +33 -0
  96. package/mixins/PopupMixin.js +176 -208
  97. package/mixins/ResizeObserverMixin.js +16 -4
  98. package/mixins/RippleMixin.js +8 -6
  99. package/mixins/ScrollListenerMixin.js +1 -1
  100. package/mixins/SemiStickyMixin.js +44 -98
  101. package/mixins/ShapeMaskedMixin.js +117 -0
  102. package/mixins/ShapeMixin.js +22 -204
  103. package/mixins/StateMixin.js +70 -34
  104. package/mixins/TextFieldMixin.js +107 -143
  105. package/mixins/ThemableMixin.js +44 -56
  106. package/mixins/TooltipTriggerMixin.js +291 -359
  107. package/mixins/TouchTargetMixin.js +1 -1
  108. package/mixins/TypographyMixin.js +121 -0
  109. package/package.json +110 -74
  110. package/services/rtl.js +10 -0
  111. package/services/svgAlias.js +17 -0
  112. package/{theming/index.js → services/theme.js} +24 -174
  113. package/types/bin/mdw-css.d.ts +3 -0
  114. package/types/bin/mdw-css.d.ts.map +1 -0
  115. package/types/components/Badge.d.ts +39 -0
  116. package/types/components/Badge.d.ts.map +1 -0
  117. package/types/components/Body.d.ts +29 -0
  118. package/types/components/Body.d.ts.map +1 -0
  119. package/types/components/BottomAppBar.d.ts +73 -0
  120. package/types/components/BottomAppBar.d.ts.map +1 -0
  121. package/types/components/BottomSheet.d.ts +109 -0
  122. package/types/components/BottomSheet.d.ts.map +1 -0
  123. package/types/components/Box.d.ts +16 -0
  124. package/types/components/Box.d.ts.map +1 -0
  125. package/types/components/Button.d.ts +714 -0
  126. package/types/components/Button.d.ts.map +1 -0
  127. package/types/components/Card.d.ts +412 -0
  128. package/types/components/Card.d.ts.map +1 -0
  129. package/types/components/Checkbox.d.ts +205 -0
  130. package/types/components/Checkbox.d.ts.map +1 -0
  131. package/types/components/CheckboxIcon.d.ts +44 -0
  132. package/types/components/CheckboxIcon.d.ts.map +1 -0
  133. package/types/components/Chip.d.ts +1425 -0
  134. package/types/components/Chip.d.ts.map +1 -0
  135. package/types/components/Dialog.d.ts +286 -0
  136. package/types/components/Dialog.d.ts.map +1 -0
  137. package/types/components/DialogActions.d.ts +4 -0
  138. package/types/components/DialogActions.d.ts.map +1 -0
  139. package/types/components/Display.d.ts +45 -0
  140. package/types/components/Display.d.ts.map +1 -0
  141. package/types/components/Divider.d.ts +10 -0
  142. package/types/components/Divider.d.ts.map +1 -0
  143. package/types/components/Fab.d.ts +741 -0
  144. package/types/components/Fab.d.ts.map +1 -0
  145. package/types/components/FabContainer.d.ts +10 -0
  146. package/types/components/FabContainer.d.ts.map +1 -0
  147. package/types/components/FilterChip.d.ts +4283 -0
  148. package/types/components/FilterChip.d.ts.map +1 -0
  149. package/types/components/Grid.d.ts +37 -0
  150. package/types/components/Grid.d.ts.map +1 -0
  151. package/types/components/Headline.d.ts +47 -0
  152. package/types/components/Headline.d.ts.map +1 -0
  153. package/types/components/Icon.d.ts +103 -0
  154. package/types/components/Icon.d.ts.map +1 -0
  155. package/types/components/IconButton.d.ts +1486 -0
  156. package/types/components/IconButton.d.ts.map +1 -0
  157. package/types/components/Input.d.ts +51288 -0
  158. package/types/components/Input.d.ts.map +1 -0
  159. package/types/components/InputChip.d.ts +243 -0
  160. package/types/components/InputChip.d.ts.map +1 -0
  161. package/types/components/Label.d.ts +29 -0
  162. package/types/components/Label.d.ts.map +1 -0
  163. package/types/components/List.d.ts +31 -0
  164. package/types/components/List.d.ts.map +1 -0
  165. package/types/components/ListItem.d.ts +349 -0
  166. package/types/components/ListItem.d.ts.map +1 -0
  167. package/types/components/ListOption.d.ts +1493 -0
  168. package/types/components/ListOption.d.ts.map +1 -0
  169. package/types/components/Listbox.d.ts +12012 -0
  170. package/types/components/Listbox.d.ts.map +1 -0
  171. package/types/components/Menu.d.ts +119 -0
  172. package/types/components/Menu.d.ts.map +1 -0
  173. package/types/components/MenuItem.d.ts +3109 -0
  174. package/types/components/MenuItem.d.ts.map +1 -0
  175. package/types/components/NavBar.d.ts +18 -0
  176. package/types/components/NavBar.d.ts.map +1 -0
  177. package/types/components/NavBarItem.d.ts +186 -0
  178. package/types/components/NavBarItem.d.ts.map +1 -0
  179. package/types/components/NavDrawer.d.ts +108 -0
  180. package/types/components/NavDrawer.d.ts.map +1 -0
  181. package/types/components/NavDrawerItem.d.ts +186 -0
  182. package/types/components/NavDrawerItem.d.ts.map +1 -0
  183. package/types/components/NavItem.d.ts +190 -0
  184. package/types/components/NavItem.d.ts.map +1 -0
  185. package/types/components/NavRail.d.ts +109 -0
  186. package/types/components/NavRail.d.ts.map +1 -0
  187. package/types/components/NavRailItem.d.ts +186 -0
  188. package/types/components/NavRailItem.d.ts.map +1 -0
  189. package/types/components/Page.d.ts +24 -0
  190. package/types/components/Page.d.ts.map +1 -0
  191. package/types/components/Pane.d.ts +44 -0
  192. package/types/components/Pane.d.ts.map +1 -0
  193. package/types/components/Popup.d.ts +76 -0
  194. package/types/components/Popup.d.ts.map +1 -0
  195. package/types/components/Progress.d.ts +19 -0
  196. package/types/components/Progress.d.ts.map +1 -0
  197. package/types/components/Radio.d.ts +199 -0
  198. package/types/components/Radio.d.ts.map +1 -0
  199. package/types/components/RadioIcon.d.ts +46 -0
  200. package/types/components/RadioIcon.d.ts.map +1 -0
  201. package/types/components/Ripple.d.ts +34 -0
  202. package/types/components/Ripple.d.ts.map +1 -0
  203. package/types/components/Root.d.ts +68 -0
  204. package/types/components/Root.d.ts.map +1 -0
  205. package/types/components/Scrim.d.ts +6 -0
  206. package/types/components/Scrim.d.ts.map +1 -0
  207. package/types/components/Search.d.ts +16 -0
  208. package/types/components/Search.d.ts.map +1 -0
  209. package/types/components/SegmentedButton.d.ts +718 -0
  210. package/types/components/SegmentedButton.d.ts.map +1 -0
  211. package/types/components/SegmentedButtonGroup.d.ts +44 -0
  212. package/types/components/SegmentedButtonGroup.d.ts.map +1 -0
  213. package/types/components/Select.d.ts +1361 -0
  214. package/types/components/Select.d.ts.map +1 -0
  215. package/types/components/Shape.d.ts +10 -0
  216. package/types/components/Shape.d.ts.map +1 -0
  217. package/types/components/SideSheet.d.ts +106 -0
  218. package/types/components/SideSheet.d.ts.map +1 -0
  219. package/types/components/Slider.d.ts +382 -0
  220. package/types/components/Slider.d.ts.map +1 -0
  221. package/types/components/Snackbar.d.ts +65 -0
  222. package/types/components/Snackbar.d.ts.map +1 -0
  223. package/types/components/SnackbarContainer.d.ts +6 -0
  224. package/types/components/SnackbarContainer.d.ts.map +1 -0
  225. package/types/components/Surface.d.ts +45 -0
  226. package/types/components/Surface.d.ts.map +1 -0
  227. package/types/components/Switch.d.ts +183 -0
  228. package/types/components/Switch.d.ts.map +1 -0
  229. package/types/components/SwitchIcon.d.ts +169 -0
  230. package/types/components/SwitchIcon.d.ts.map +1 -0
  231. package/types/components/Tab.d.ts +879 -0
  232. package/types/components/Tab.d.ts.map +1 -0
  233. package/types/components/TabContent.d.ts +122 -0
  234. package/types/components/TabContent.d.ts.map +1 -0
  235. package/types/components/TabList.d.ts +6266 -0
  236. package/types/components/TabList.d.ts.map +1 -0
  237. package/types/components/TabPanel.d.ts +28 -0
  238. package/types/components/TabPanel.d.ts.map +1 -0
  239. package/types/components/Table.d.ts +2 -0
  240. package/types/components/Table.d.ts.map +1 -0
  241. package/types/components/TextArea.d.ts +1394 -0
  242. package/types/components/TextArea.d.ts.map +1 -0
  243. package/types/components/Title.d.ts +47 -0
  244. package/types/components/Title.d.ts.map +1 -0
  245. package/types/components/Tooltip.d.ts +49 -0
  246. package/types/components/Tooltip.d.ts.map +1 -0
  247. package/types/components/TopAppBar.d.ts +130 -0
  248. package/types/components/TopAppBar.d.ts.map +1 -0
  249. package/types/constants/colorKeywords.d.ts +2 -0
  250. package/types/constants/colorKeywords.d.ts.map +1 -0
  251. package/types/constants/shapes.d.ts +38 -0
  252. package/types/constants/shapes.d.ts.map +1 -0
  253. package/types/constants/typography.d.ts +212 -0
  254. package/types/constants/typography.d.ts.map +1 -0
  255. package/types/core/Composition.d.ts +252 -0
  256. package/types/core/Composition.d.ts.map +1 -0
  257. package/types/core/CompositionAdapter.d.ts +92 -0
  258. package/types/core/CompositionAdapter.d.ts.map +1 -0
  259. package/types/core/CustomElement.d.ts +302 -0
  260. package/types/core/CustomElement.d.ts.map +1 -0
  261. package/types/core/css.d.ts +44 -0
  262. package/types/core/css.d.ts.map +1 -0
  263. package/types/core/customTypes.d.ts +26 -0
  264. package/types/core/customTypes.d.ts.map +1 -0
  265. package/types/core/dom.d.ts +32 -0
  266. package/types/core/dom.d.ts.map +1 -0
  267. package/types/core/jsonMergePatch.d.ts +31 -0
  268. package/types/core/jsonMergePatch.d.ts.map +1 -0
  269. package/types/core/observe.d.ts +113 -0
  270. package/types/core/observe.d.ts.map +1 -0
  271. package/types/core/optimizations.d.ts +7 -0
  272. package/types/core/optimizations.d.ts.map +1 -0
  273. package/types/core/template.d.ts +47 -0
  274. package/types/core/template.d.ts.map +1 -0
  275. package/types/core/uid.d.ts +6 -0
  276. package/types/core/uid.d.ts.map +1 -0
  277. package/types/dom/HTMLOptionsCollectionProxy.d.ts +18 -0
  278. package/types/dom/HTMLOptionsCollectionProxy.d.ts.map +1 -0
  279. package/types/index.d.ts +88 -0
  280. package/types/index.d.ts.map +1 -0
  281. package/types/loaders/palette.d.ts +2 -0
  282. package/types/loaders/palette.d.ts.map +1 -0
  283. package/types/loaders/theme.d.ts +2 -0
  284. package/types/loaders/theme.d.ts.map +1 -0
  285. package/types/mixins/AriaReflectorMixin.d.ts +23 -0
  286. package/types/mixins/AriaReflectorMixin.d.ts.map +1 -0
  287. package/types/mixins/AriaToolbarMixin.d.ts +32 -0
  288. package/types/mixins/AriaToolbarMixin.d.ts.map +1 -0
  289. package/types/mixins/ControlMixin.d.ts +124 -0
  290. package/types/mixins/ControlMixin.d.ts.map +1 -0
  291. package/types/mixins/DelegatesFocusMixin.d.ts +5 -0
  292. package/types/mixins/DelegatesFocusMixin.d.ts.map +1 -0
  293. package/types/mixins/DensityMixin.d.ts +5 -0
  294. package/types/mixins/DensityMixin.d.ts.map +1 -0
  295. package/types/mixins/ElevationMixin.d.ts +33 -0
  296. package/types/mixins/ElevationMixin.d.ts.map +1 -0
  297. package/types/mixins/FlexableMixin.d.ts +13 -0
  298. package/types/mixins/FlexableMixin.d.ts.map +1 -0
  299. package/types/mixins/FormAssociatedMixin.d.ts +122 -0
  300. package/types/mixins/FormAssociatedMixin.d.ts.map +1 -0
  301. package/types/mixins/HyperlinkMixin.d.ts +22 -0
  302. package/types/mixins/HyperlinkMixin.d.ts.map +1 -0
  303. package/types/mixins/InputMixin.d.ts +179 -0
  304. package/types/mixins/InputMixin.d.ts.map +1 -0
  305. package/types/mixins/KeyboardNavMixin.d.ts +47 -0
  306. package/types/mixins/KeyboardNavMixin.d.ts.map +1 -0
  307. package/types/mixins/NavigationListenerMixin.d.ts +8 -0
  308. package/types/mixins/NavigationListenerMixin.d.ts.map +1 -0
  309. package/types/mixins/PopupMixin.d.ts +82 -0
  310. package/types/mixins/PopupMixin.d.ts.map +1 -0
  311. package/types/mixins/RTLObserverMixin.d.ts +7 -0
  312. package/types/mixins/RTLObserverMixin.d.ts.map +1 -0
  313. package/types/mixins/ResizeObserverMixin.d.ts +12 -0
  314. package/types/mixins/ResizeObserverMixin.d.ts.map +1 -0
  315. package/types/mixins/RippleMixin.d.ts +92 -0
  316. package/types/mixins/RippleMixin.d.ts.map +1 -0
  317. package/types/mixins/ScrollListenerMixin.d.ts +41 -0
  318. package/types/mixins/ScrollListenerMixin.d.ts.map +1 -0
  319. package/types/mixins/SemiStickyMixin.d.ts +50 -0
  320. package/types/mixins/SemiStickyMixin.d.ts.map +1 -0
  321. package/types/mixins/ShapeMaskedMixin.d.ts +9 -0
  322. package/types/mixins/ShapeMaskedMixin.d.ts.map +1 -0
  323. package/types/mixins/ShapeMixin.d.ts +38 -0
  324. package/types/mixins/ShapeMixin.d.ts.map +1 -0
  325. package/types/mixins/StateMixin.d.ts +27 -0
  326. package/types/mixins/StateMixin.d.ts.map +1 -0
  327. package/types/mixins/TextFieldMixin.d.ts +1354 -0
  328. package/types/mixins/TextFieldMixin.d.ts.map +1 -0
  329. package/types/mixins/ThemableMixin.d.ts +9 -0
  330. package/types/mixins/ThemableMixin.d.ts.map +1 -0
  331. package/types/mixins/TooltipTriggerMixin.d.ts +106 -0
  332. package/types/mixins/TooltipTriggerMixin.d.ts.map +1 -0
  333. package/types/mixins/TouchTargetMixin.d.ts +3 -0
  334. package/types/mixins/TouchTargetMixin.d.ts.map +1 -0
  335. package/types/mixins/TypographyMixin.d.ts +17 -0
  336. package/types/mixins/TypographyMixin.d.ts.map +1 -0
  337. package/types/services/rtl.d.ts +3 -0
  338. package/types/services/rtl.d.ts.map +1 -0
  339. package/types/services/svgAlias.d.ts +13 -0
  340. package/types/services/svgAlias.d.ts.map +1 -0
  341. package/types/services/theme.d.ts +45 -0
  342. package/types/services/theme.d.ts.map +1 -0
  343. package/types/utils/cli.d.ts +3 -0
  344. package/types/utils/cli.d.ts.map +1 -0
  345. package/types/utils/function.d.ts +3 -0
  346. package/types/utils/function.d.ts.map +1 -0
  347. package/types/utils/jsx-runtime.d.ts +20 -0
  348. package/types/utils/jsx-runtime.d.ts.map +1 -0
  349. package/types/utils/material-color/blend.d.ts +34 -0
  350. package/types/utils/material-color/blend.d.ts.map +1 -0
  351. package/types/utils/material-color/hct/Cam16.d.ts +142 -0
  352. package/types/utils/material-color/hct/Cam16.d.ts.map +1 -0
  353. package/types/utils/material-color/hct/Hct.d.ts +93 -0
  354. package/types/utils/material-color/hct/Hct.d.ts.map +1 -0
  355. package/types/utils/material-color/hct/ViewingConditions.d.ts +69 -0
  356. package/types/utils/material-color/hct/ViewingConditions.d.ts.map +1 -0
  357. package/types/utils/material-color/hct/hctSolver.d.ts +30 -0
  358. package/types/utils/material-color/hct/hctSolver.d.ts.map +1 -0
  359. package/types/utils/material-color/helper.d.ts +8 -0
  360. package/types/utils/material-color/helper.d.ts.map +1 -0
  361. package/types/utils/material-color/palettes/CorePalette.d.ts +75 -0
  362. package/types/utils/material-color/palettes/CorePalette.d.ts.map +1 -0
  363. package/types/utils/material-color/palettes/TonalPalette.d.ts +38 -0
  364. package/types/utils/material-color/palettes/TonalPalette.d.ts.map +1 -0
  365. package/types/utils/material-color/scheme/Scheme.d.ts +264 -0
  366. package/types/utils/material-color/scheme/Scheme.d.ts.map +1 -0
  367. package/types/utils/material-color/utils/color.d.ts +172 -0
  368. package/types/utils/material-color/utils/color.d.ts.map +1 -0
  369. package/types/utils/material-color/utils/math.d.ts +94 -0
  370. package/types/utils/material-color/utils/math.d.ts.map +1 -0
  371. package/types/utils/pixelmatch.d.ts +22 -0
  372. package/types/utils/pixelmatch.d.ts.map +1 -0
  373. package/types/utils/popup.d.ts +106 -0
  374. package/types/utils/popup.d.ts.map +1 -0
  375. package/types/utils/searchParams.d.ts +3 -0
  376. package/types/utils/searchParams.d.ts.map +1 -0
  377. package/types/utils/svg.d.ts +7 -0
  378. package/types/utils/svg.d.ts.map +1 -0
  379. package/utils/material-color/scheme/Scheme.js +1 -1
  380. package/utils/pixelmatch.js +360 -0
  381. package/utils/popup.js +86 -10
  382. package/utils/searchParams.js +19 -0
  383. package/components/ExtendedFab.js +0 -32
  384. package/components/Layout.js +0 -504
  385. package/components/Nav.js +0 -38
  386. package/core/DomAdapter.js +0 -586
  387. package/core/ICustomElement.d.ts +0 -291
  388. package/core/ICustomElement.js +0 -1
  389. package/core/test.js +0 -126
  390. package/core/typings.d.ts +0 -142
  391. package/core/typings.js +0 -1
  392. package/mixins/SurfaceMixin.js +0 -127
  393. package/theming/loader.js +0 -22
  394. /package/{utils/color_keywords.js → constants/colorKeywords.js} +0 -0
package/core/observe.js CHANGED
@@ -1,65 +1,63 @@
1
1
  import { attrNameFromPropName } from './dom.js';
2
2
  import { buildMergePatch, hasMergePatch } from './jsonMergePatch.js';
3
3
 
4
- /** @typedef {import('./typings.js').ObserverPropertyType} ObserverPropertyType */
5
-
6
- /** @return {null} */
7
- const DEFAULT_NULL_PARSER = () => null;
8
-
9
- /**
10
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean#boolean_coercion
11
- * @param {any} v
12
- * @return {boolean}
13
- */
14
- const DEFAULT_BOOLEAN_PARSER = (v) => !!v;
15
-
16
- /**
17
- * Doesn't support `BigInt` types
18
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion
19
- * @param {any} v
20
- * @return {number}
21
- */
22
- const DEFAULT_NUMBER_PARSER = (v) => +v;
4
+ /** @typedef {'string' | 'boolean' | 'map' | 'set' | 'float' | 'integer' | 'object' | 'function' | 'array'} ObserverPropertyType */
23
5
 
24
6
  /**
25
- * Doesn't support `Symbol` types
26
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion
27
- * @param {any} v
28
- * @return {string}
7
+ * @template {ObserverPropertyType} T
8
+ * @typedef {(
9
+ * T extends 'boolean' ? boolean
10
+ * : T extends 'string' ? string
11
+ * : T extends 'float' | 'integer' ? number
12
+ * : T extends 'array' ? any[]
13
+ * : T extends 'object' ? any
14
+ * : T extends 'function' ? (...args:any) => any
15
+ * : unknown
16
+ * )} ParsedObserverPropertyType
29
17
  */
30
- const DEFAULT_STRING_PARSER = (v) => `${v}`;
31
18
 
32
19
  /**
33
- * @template T
34
- * @param {T} o
35
- * @return {T}
36
- */
37
- const DEFAULT_OBJECT_PARSER = (o) => o;
38
-
39
- /**
40
- * @template T
41
- * @param {T} a
42
- * @param {T} b
43
- * @return {boolean} true if equal
44
- */
45
- const DEFAULT_OBJECT_COMPARATOR = (a, b) => !hasMergePatch(a, b);
46
-
47
- /**
48
- * Always invoke change on set
49
- * @template T
50
- * @param {T} a
51
- * @param {T} b
52
- * @return {boolean} true if equal
20
+ * @template {ObserverPropertyType} T1
21
+ * @template {any} T2
22
+ * @template {Object} [C=any]
23
+ * @typedef {Object} ObserverOptions
24
+ * @prop {T1} [type]
25
+ * @prop {string} [attr]
26
+ * @prop {boolean} [readonly]
27
+ * @prop {boolean} [enumerable]
28
+ * Defaults to false if type is boolean
29
+ * @prop {boolean} [nullable]
30
+ * @prop {T2} [empty]
31
+ * @prop {T2} [value]
32
+ * @prop {WeakMap<C,T2>} [values]
33
+ * @prop {boolean|'write'|'read'} [reflect]
34
+ * Function used when null passed
35
+ * @prop {(this:C, value:null|undefined)=>T2} [nullParser]
36
+ * @prop {(this:C, value:any)=>T2} [parser]
37
+ * Function used when comparing
38
+ * @prop {(this:C, a:T2, b:T2)=> any} [diff]
39
+ * @prop {(this:C, a:T2, b:T2)=>boolean} [is]
40
+ * @prop {(this:C, data:Partial<C>, fn?: () => T2) => T2} [get]
41
+ * @prop {(this:C, value: T2, fn?:(value2: T2) => any) => any} [set]
42
+ * Simple callback
43
+ * @prop {(this:C, oldValue:T2, newValue:T2, changes:any)=>any} [changedCallback]
44
+ * Named callback
45
+ * @prop {(this:C, name:string, oldValue: T2, newValue: T2, changes:any) => any} [propChangedCallback]
46
+ * Attribute callback
47
+ * @prop {(this:C, name:string, oldValue: string, newValue: string) => any} [attributeChangedCallback]
48
+ * @prop {WeakMap<C, T2>} [computedValues]
49
+ * @prop {[keyof C, (this:C, ...args:any[]) => any][]} [watchers]
50
+ * @prop {WeakSet<C>} [needsSelfInvalidation]
51
+ * @prop {Set<keyof C>} [props]
53
52
  */
54
- const DEFAULT_ARRAY_COMPARATOR = (a, b) => false;
55
53
 
56
54
  /**
57
- * @template T
58
- * @param {T} a
59
- * @param {T} b
60
- * @return {boolean} true if equal
55
+ * @template {ObserverPropertyType} T1
56
+ * @template {any} [T2=any]
57
+ * @template {string} [K=string]
58
+ * @template {Object} [C=any]
59
+ * @typedef {ObserverOptions<T1, T2, C> & { key: K, values?: WeakMap<C, T2>; attrValues?: WeakMap<C, string> }} ObserverConfiguration
61
60
  */
62
- const DEFAULT_OBJECT_DIFF = (a, b) => buildMergePatch(a, b, 'reference');
63
61
 
64
62
  /**
65
63
  * @param {ObserverPropertyType} type
@@ -95,9 +93,11 @@ function emptyFromType(type) {
95
93
  * @return {T}
96
94
  */
97
95
  function buildProxy(proxyTarget, set, deepSet, prefix) {
96
+ // @ts-ignore
98
97
  proxyTarget ??= {};
99
98
  return new Proxy(proxyTarget, {
100
99
  get(target, p) {
100
+ // @ts-ignore
101
101
  const value = target[p];
102
102
  if (typeof p !== 'symbol') {
103
103
  const arg = prefix ? `${prefix}.${p}` : p;
@@ -135,127 +135,218 @@ function buildProxy(proxyTarget, set, deepSet, prefix) {
135
135
  function defaultParserFromType(type) {
136
136
  switch (type) {
137
137
  case 'boolean':
138
- return DEFAULT_BOOLEAN_PARSER;
138
+ /**
139
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean#boolean_coercion
140
+ * @param {any} v
141
+ * @return {boolean}
142
+ */
143
+ return (v) => !!v;
139
144
  case 'integer':
140
145
  // Calls ToNumber(x)
141
146
  return Math.round;
142
147
  case 'float':
143
- return DEFAULT_NUMBER_PARSER;
148
+ /**
149
+ * Doesn't support `BigInt` types
150
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_coercion
151
+ * @param {any} v
152
+ * @return {number}
153
+ */
154
+ return (v) => +v;
144
155
  case 'map':
145
156
  return Map;
146
157
  case 'set':
147
158
  return Set;
148
159
  case 'object':
149
- return DEFAULT_OBJECT_PARSER;
150
160
  case 'array':
151
- return DEFAULT_OBJECT_PARSER;
161
+ /**
162
+ * Reflect self
163
+ * @template T
164
+ * @param {T} o
165
+ * @return {T}
166
+ */
167
+ return (o) => o;
152
168
  default:
153
169
  case 'string':
154
- return DEFAULT_STRING_PARSER;
170
+ /**
171
+ * Doesn't support `Symbol` types
172
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion
173
+ * @param {any} v
174
+ * @return {string}
175
+ */
176
+ return (v) => `${v}`;
155
177
  }
156
178
  }
157
179
 
180
+ /**
181
+ * @param {(data: Partial<any>) => any} fn
182
+ * @param {...any} args
183
+ * @this {any}
184
+ * @return {{
185
+ * props: {
186
+ * this: string[],
187
+ * args: string[][],
188
+ * },
189
+ * deepPropStrings: {
190
+ * this: string[],
191
+ * args: string[][],
192
+ * },
193
+ * deepProps: {
194
+ * this: string[][],
195
+ * args: string[][][],
196
+ * },
197
+ * defaultValue: any,
198
+ * reusable: boolean,
199
+ * }}
200
+ */
201
+ export function observeFunction(fn, ...args) {
202
+ /** @type {Set<string>} */
203
+ const thisPoked = new Set();
204
+ /** @type {Set<string>} */
205
+ const thisPokedDeep = new Set();
206
+
207
+ const argWatchers = args.map((arg) => {
208
+ const poked = new Set();
209
+ const pokedDeep = new Set();
210
+ const proxy = buildProxy(arg, poked, pokedDeep);
211
+ return { poked, pokedDeep, proxy };
212
+ });
213
+
214
+ const thisProxy = buildProxy(this ?? {}, thisPoked, thisPokedDeep);
215
+ const defaultValue = fn.apply(thisProxy, argWatchers.map((watcher) => watcher.proxy));
216
+ /* Arrow functions can reused if they don't poke `this` */
217
+ const reusable = fn.name ? true : !thisPoked.size;
218
+
219
+ return {
220
+ props: {
221
+ this: [...thisPoked],
222
+ args: argWatchers.map((watcher) => [...watcher.poked]),
223
+ },
224
+ deepPropStrings: {
225
+ this: [...thisPokedDeep],
226
+ args: argWatchers.map((watcher) => [...watcher.pokedDeep]),
227
+ },
228
+ deepProps: {
229
+ this: [...thisPokedDeep].map((deepPropString) => deepPropString.split('.')),
230
+ args: argWatchers.map((watcher) => [...watcher.pokedDeep].map((deepPropString) => deepPropString.split('.'))),
231
+ },
232
+ defaultValue,
233
+ reusable,
234
+ };
235
+ }
236
+
158
237
  /**
159
238
  * @template {string} K
160
239
  * @template {ObserverPropertyType} [T1=any]
161
- * @template {any} [T2=import('./typings.js').ParsedObserverPropertyType<T1>]
240
+ * @template {any} [T2=ParsedObserverPropertyType<T1>]
162
241
  * @param {K} name
163
- * @param {T1|import('./typings.js').ObserverOptions<T1,T2>} [typeOrOptions='string']
164
- * @param {any} object
165
- * @return {import('./typings.js').ObserverConfiguration<T1,T2,K> & import('./typings.js').ObserverOptions<T1,T2>}
242
+ * @param {T1|ObserverOptions<T1,T2>} [typeOrOptions='string']
243
+ * @param {any} [object]
244
+ * @return {ObserverConfiguration<T1,T2,K> & ObserverOptions<T1,T2>}
166
245
  */
167
246
  export function parseObserverOptions(name, typeOrOptions, object) {
168
- /** @type {Partial<import('./typings.js').ObserverOptions<T1,T2>>} */
169
- const options = {
170
- ...((typeof typeOrOptions === 'string') ? { type: typeOrOptions } : typeOrOptions),
171
- };
247
+ /** @type {Partial<ObserverOptions<T1,T2>>} */
248
+ const options = (typeof typeOrOptions === 'string')
249
+ ? { type: typeOrOptions }
250
+ : typeOrOptions;
251
+
252
+ let {
253
+ watchers, value, readonly,
254
+ empty, type,
255
+ enumerable, reflect, attr,
256
+ nullable, parser, nullParser,
257
+ get,
258
+ is, diff,
259
+ props,
260
+ } = options;
261
+
262
+ watchers ??= [];
263
+ readonly ??= false;
264
+
265
+ if (empty === undefined) {
266
+ empty = null;
267
+ }
172
268
 
173
- let { enumerable, attr, reflect } = options;
174
- const { type, empty, changedCallback } = options;
269
+ value ??= empty;
270
+
271
+ if (get && !props) {
272
+ // Custom `get` uses computed values.
273
+ // Invalidate computed value when dependent `prop` changes
274
+ const observeResult = observeFunction(get.bind(object), object, () => value);
275
+ value ??= observeResult.defaultValue;
276
+ const uniqueProps = new Set([
277
+ ...observeResult.props.this,
278
+ ...observeResult.props.args[0],
279
+ ]);
280
+ props = uniqueProps;
281
+ }
175
282
 
176
283
  /** @type {ObserverPropertyType} */
177
- let parsedType = type;
178
- if (parsedType == null) {
179
- // Use .value or .get() to parse type
180
- const value = options.value ?? empty ?? options.get?.call(object ?? {}, object ?? {});
284
+ if (!type) {
181
285
  if (value == null) {
182
- parsedType = 'string';
286
+ // @ts-ignore
287
+ type = 'string';
183
288
  } else {
184
289
  const parsed = typeof value;
185
- parsedType = (parsed === 'number')
290
+ // @ts-ignore
291
+ type = (parsed === 'number')
186
292
  ? (Number.isInteger(value) ? 'integer' : 'number')
187
293
  : parsed;
188
294
  }
189
295
  }
190
296
 
191
297
  enumerable ??= name[0] !== '_';
192
- reflect ??= enumerable ? parsedType !== 'object' : (attr ? 'write' : false);
298
+ reflect ??= enumerable ? type !== 'object' : (attr ? 'write' : false);
193
299
  attr ??= (reflect ? attrNameFromPropName(name) : null);
300
+ nullable ??= (type === 'boolean') ? false : (empty == null);
301
+ if (!nullable) {
302
+ empty ??= emptyFromType(type);
303
+ value ??= empty;
304
+ }
194
305
 
195
306
  // if defined ? value
196
307
  // else if boolean ? false
197
308
  // else if onNullish ? false
198
309
  // else if empty == null
199
- const parser = options.parser ?? defaultParserFromType(parsedType);
200
- let nullParser = options.nullParser;
201
- let parsedEmpty = empty ?? null;
310
+ parser ??= defaultParserFromType(type);
202
311
  if (!nullParser) {
203
- const nullable = options.nullable ?? (
204
- parsedType === 'boolean'
205
- ? false
206
- : (empty == null));
207
312
  if (nullable) {
208
- nullParser = DEFAULT_NULL_PARSER;
313
+ nullParser = () => null;
209
314
  } else {
210
- parsedEmpty ??= emptyFromType(parsedType);
211
- nullParser = parsedEmpty === null ? () => emptyFromType(parsedType) : () => parsedEmpty;
315
+ nullParser = (empty === null)
316
+ ? () => emptyFromType(type)
317
+ : () => empty;
212
318
  }
213
319
  }
214
320
 
215
- let isFn = options.is;
216
- if (!isFn) {
217
- isFn = parsedType === 'object'
218
- ? DEFAULT_OBJECT_COMPARATOR
219
- : ((parsedType === 'array') ? DEFAULT_ARRAY_COMPARATOR : Object.is);
220
- }
321
+ is ??= (type === 'object')
322
+ ? (a, b) => !hasMergePatch(a, b)
323
+ : ((type === 'array') ? () => false : Object.is);
221
324
 
222
- const diff = 'diff' in options
223
- ? options.diff
224
- : ((parsedType === 'object') ? DEFAULT_OBJECT_DIFF : null);
325
+ if (diff === undefined) {
326
+ // @ts-ignore
327
+ diff = ((type === 'object') ? (a, b) => buildMergePatch(a, b, 'reference') : null);
328
+ }
225
329
 
226
330
  return {
227
331
  ...options,
228
- type: parsedType,
229
- is: isFn,
332
+ type,
333
+ is,
230
334
  diff,
231
335
  attr,
232
336
  reflect,
233
- readonly: options.readonly ?? false,
337
+ readonly,
234
338
  enumerable,
235
- value: options.value ?? parsedEmpty,
339
+ value,
236
340
  parser,
237
341
  nullParser,
238
342
  key: name,
239
- changedCallback,
240
- watchers: options.watchers ?? [],
241
- values: options.values ?? new WeakMap(),
242
- computedValues: options.computedValues ?? new WeakMap(),
243
- attributeChangedCallback: options.attributeChangedCallback,
244
- needsSelfInvalidation: options.needsSelfInvalidation ?? new WeakSet(),
343
+ props,
344
+ watchers,
245
345
  };
246
346
  }
247
347
 
248
- const INIT_SYMBOL = Symbol('PROP_INIT');
249
-
250
- /** @type {Partial<import('./typings.js').ObserverConfiguration<?,?,?>>} */
251
- const DEFAULT_OBSERVER_CONFIGURATION = {
252
- nullParser: DEFAULT_NULL_PARSER,
253
- is: Object.is,
254
- INIT_SYMBOL,
255
- };
256
-
257
348
  /**
258
- * @this {import('./typings.js').ObserverConfiguration<?,?,?>}
349
+ * @this {ObserverConfiguration<?,?,?>}
259
350
  * @param {*} value
260
351
  */
261
352
  export function parsePropertyValue(value) {
@@ -266,60 +357,58 @@ export function parsePropertyValue(value) {
266
357
  }
267
358
 
268
359
  /**
269
- * @param {(data: Partial<any>) => any} fn
270
- * @param {...any} args
271
- * @this {any}
272
- * @return {{
273
- * props: {
274
- * this: string[],
275
- * args: string[][],
276
- * },
277
- * deepPropStrings: {
278
- * this: string[],
279
- * args: string[][],
280
- * },
281
- * deepProps: {
282
- * this: string[][],
283
- * args: string[][][],
284
- * },
285
- * defaultValue: any,
286
- * reusable: boolean,
287
- * }}
360
+ * @param {ObserverConfiguration<?,?,?,?>} config
361
+ * @param {any} oldValue
362
+ * @param {any} value
363
+ * @return {boolean} changed
288
364
  */
289
- export function observeFunction(fn, ...args) {
290
- /** @type {Set<string>} */
291
- const thisPoked = new Set();
292
- /** @type {Set<string>} */
293
- const thisPokedDeep = new Set();
365
+ function detectChange(config, oldValue, value) {
366
+ if (config.get) {
367
+ // TODO: Custom getter vs parser
368
+ }
294
369
 
295
- const argWatchers = args.map((arg) => {
296
- const poked = new Set();
297
- const pokedDeep = new Set();
298
- const proxy = buildProxy(arg, poked, pokedDeep);
299
- return { poked, pokedDeep, proxy };
300
- });
370
+ // Compute real new value after parsing
371
+ const newValue = (value == null)
372
+ ? config.nullParser.call(this, value)
373
+ : config.parser.call(this, value);
301
374
 
302
- const thisProxy = buildProxy(this ?? {}, thisPoked, thisPokedDeep);
303
- const defaultValue = fn.apply(thisProxy, argWatchers.map((watcher) => watcher.proxy));
304
- /* Arrow functions can reused if they don't poke `this` */
305
- const reusable = fn.name ? true : !thisPoked.size;
375
+ // Default change is the newValue
376
+ let changes = newValue;
306
377
 
307
- return {
308
- props: {
309
- this: [...thisPoked],
310
- args: argWatchers.map((watcher) => [...watcher.poked]),
311
- },
312
- deepPropStrings: {
313
- this: [...thisPokedDeep],
314
- args: argWatchers.map((watcher) => [...watcher.pokedDeep]),
315
- },
316
- deepProps: {
317
- this: [...thisPokedDeep].map((deepPropString) => deepPropString.split('.')),
318
- args: argWatchers.map((watcher) => [...watcher.pokedDeep].map((deepPropString) => deepPropString.split('.'))),
319
- },
320
- defaultValue,
321
- reusable,
322
- };
378
+ // Null check
379
+ if (oldValue == null) {
380
+ if (newValue == null) {
381
+ // Both nullish
382
+ return false;
383
+ }
384
+ } else if (newValue != null) {
385
+ // Both non-null, compare
386
+ if (config.diff) {
387
+ // Custom change diff
388
+ changes = config.diff.call(this, oldValue, newValue);
389
+ if (changes == null) {
390
+ // No difference
391
+ return false;
392
+ }
393
+ } else if (config.is.call(this, oldValue, newValue)) {
394
+ // Non-equal
395
+ return false;
396
+ }
397
+ }
398
+
399
+ // Commit value
400
+ if (config.values) {
401
+ config.values.set(this, newValue);
402
+ } else {
403
+ config.values = new WeakMap([[this, newValue]]);
404
+ }
405
+
406
+ // Emit change
407
+
408
+ config.propChangedCallback?.call(this, config.key, oldValue, newValue, changes);
409
+ config.changedCallback?.call(this, oldValue, newValue, changes);
410
+
411
+ return true;
323
412
  }
324
413
 
325
414
  /**
@@ -329,54 +418,20 @@ export function observeFunction(fn, ...args) {
329
418
  * @template [C=any]
330
419
  * @param {C} object
331
420
  * @param {K} key
332
- * @param {import('./typings.js').ObserverOptions<T1, T2, C>} options
333
- * @return {import('./typings.js').ObserverConfiguration<T1,T2,K,C>}
421
+ * @param {ObserverOptions<T1, T2, C>} options
422
+ * @return {ObserverConfiguration<T1,T2,K,C>}
334
423
  */
335
424
  export function defineObservableProperty(object, key, options) {
336
- /** @type {import('./typings.js').ObserverConfiguration<T1,T2,K,C>} */
337
- const config = {
338
- ...DEFAULT_OBSERVER_CONFIGURATION,
339
- ...parseObserverOptions(key, options, object),
340
- changedCallback: options.changedCallback,
341
- };
342
-
343
- /**
344
- * @param {T2} oldValue
345
- * @param {T2} value
346
- * @return {boolean} changed
347
- */
348
- function detectChange(oldValue, value) {
349
- if (config.get) {
350
- // TODO: Custom getter vs parser
351
- }
352
- let newValue = value;
353
- newValue = (value == null)
354
- ? config.nullParser.call(this, value)
355
- : config.parser.call(this, newValue);
356
-
357
- let changes = newValue;
358
- if (oldValue == null) {
359
- if (newValue == null) return false; // Both nullish
360
- } else if (newValue != null) {
361
- // if (oldValue === newValue) return false;
362
- if (config.diff) {
363
- changes = config.diff.call(this, oldValue, newValue);
364
- if (changes == null) return false;
365
- } else if (config.is.call(this, oldValue, newValue)) return false;
366
- }
425
+ /** @type {ObserverConfiguration<T1,T2,K,C>} */
426
+ // @ts-ignore
427
+ const config = parseObserverOptions(key, options, object);
367
428
 
368
- config.values.set(this, newValue);
369
- // console.log(key, 'value.set', newValue);
370
- config.propChangedCallback?.call(this, key, oldValue, newValue, changes);
371
- config.changedCallback?.call(this, oldValue, newValue, changes);
372
- return true;
373
- }
374
429
  /**
375
430
  * @this {C}
376
431
  * @return {T2}
377
432
  */
378
433
  function internalGet() {
379
- return config.values.has(this) ? config.values.get(this) : config.value;
434
+ return config.values?.has(this) ? config.values.get(this) : config.value;
380
435
  }
381
436
 
382
437
  /**
@@ -385,75 +440,65 @@ export function defineObservableProperty(object, key, options) {
385
440
  * @return {void}
386
441
  */
387
442
  function internalSet(value) {
443
+ // @ts-ignore
388
444
  const oldValue = this[key];
389
- // console.log(key, 'internalSet', oldValue, '=>', value);
390
- detectChange.call(this, oldValue, value);
445
+ detectChange.call(this, config, oldValue, value);
391
446
  }
392
447
 
393
448
  /** @return {void} */
394
449
  function onInvalidate() {
395
450
  // Current value is now invalidated. Recompute and check if changed
396
- const oldValue = config.computedValues.get(this);
451
+ // eslint-disable-next-line no-multi-assign
452
+
453
+ const oldValue = config.computedValues?.get(this);
397
454
  const newValue = this[key];
398
- // console.debug('observe: onInvalidate called for', key, oldValue, '=>', newValue, this);
399
- config.needsSelfInvalidation.delete(this);
400
- detectChange.call(this, oldValue, newValue);
455
+ config.needsSelfInvalidation?.delete(this);
456
+ detectChange.call(this, config, oldValue, newValue);
401
457
  }
402
458
 
403
- if (config.get) {
404
- // Custom `get` uses computed values.
405
- // Invalidate computed value when dependent `prop` changes
406
- const observeResult = observeFunction(config.get.bind(object), object, internalGet.bind(object));
407
- const uniqueProps = new Set([
408
- ...observeResult.props.this,
409
- ...observeResult.props.args[0],
410
- ]);
411
- for (const prop of uniqueProps) {
412
- // @ts-ignore keyof C
459
+ if (config.props) {
460
+ for (const prop of config.props) {
413
461
  config.watchers.push([prop, onInvalidate]);
414
462
  }
463
+ }
464
+
465
+ /**
466
+ * @this {C}
467
+ * @return {T2}
468
+ */
469
+ function cachedGet() {
470
+ const newValue = config.get.call(this, this, internalGet.bind(this));
471
+ // Store computed value internally. Used by onInvalidate to get previous value
472
+ const computedValues = (config.computedValues ??= new WeakMap());
473
+ computedValues.set(this, newValue);
474
+ return newValue;
475
+ }
415
476
 
416
- // TODO: May be able to cache value if props are present
477
+ /**
478
+ * @this {C}
479
+ * @param {T2} value
480
+ * @return {void}
481
+ */
482
+ function cachedSet(value) {
483
+ if (config.needsSelfInvalidation) {
484
+ config.needsSelfInvalidation.add(this);
485
+ } else {
486
+ config.needsSelfInvalidation = new WeakSet([this]);
487
+ }
488
+ const oldValue = this[key];
489
+ config.set.call(this, value, internalSet.bind(this));
490
+ const newValue = this[key];
491
+ if (!config.needsSelfInvalidation.has(this)) return;
492
+ config.needsSelfInvalidation.delete(this);
493
+ detectChange.call(this, config, oldValue, newValue);
417
494
  }
495
+
418
496
  /** @type {Partial<PropertyDescriptor>} */
419
497
  const descriptor = {
420
498
  enumerable: config.enumerable,
421
499
  configurable: true,
422
- /**
423
- * @this {C}
424
- * @return {T2}
425
- */
426
- get() {
427
- if (config.get) {
428
- const newValue = config.get.call(this, this, internalGet.bind(this));
429
- // Store computed value internally. Used by onInvalidate to get previous value
430
- config.computedValues.set(this, newValue);
431
- return newValue;
432
- }
433
- return internalGet.call(this);
434
- },
435
- /**
436
- * @this {C}
437
- * @param {T2} value
438
- * @return {void}
439
- */
440
- set(value) {
441
- if (value === INIT_SYMBOL) {
442
- // console.log(key, 'returning due to INIT');
443
- return;
444
- }
445
- if (config.set) {
446
- config.needsSelfInvalidation.add(this);
447
- const oldValue = this[key];
448
- config.set.call(this, value, internalSet.bind(this));
449
- const newValue = this[key];
450
- if (!config.needsSelfInvalidation.has(this)) return;
451
- config.needsSelfInvalidation.delete(this);
452
- detectChange.call(this, oldValue, newValue);
453
- } else {
454
- internalSet.call(this, value);
455
- }
456
- },
500
+ get: config.get ? cachedGet : internalGet,
501
+ set: config.set ? cachedSet : internalSet,
457
502
  };
458
503
 
459
504
  Object.defineProperty(object, key, descriptor);