@shortfuse/materialdesignweb 0.4.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (452) hide show
  1. package/README.md +155 -79
  2. package/bin/generate-css.js +12 -0
  3. package/components/Badge.css +30 -0
  4. package/components/Badge.js +15 -0
  5. package/components/Body.css +14 -0
  6. package/components/Body.js +7 -0
  7. package/components/BottomAppBar.css +23 -0
  8. package/components/BottomAppBar.js +25 -0
  9. package/components/Box.css +31 -0
  10. package/components/Box.js +24 -0
  11. package/components/Button.css +146 -0
  12. package/components/Button.js +95 -0
  13. package/components/Button.md +61 -0
  14. package/components/Card.css +109 -0
  15. package/components/Card.js +82 -0
  16. package/components/Checkbox.css +77 -0
  17. package/components/Checkbox.js +59 -0
  18. package/components/CheckboxIcon.css +89 -0
  19. package/components/CheckboxIcon.js +41 -0
  20. package/components/Chip.css +35 -0
  21. package/components/Chip.js +22 -0
  22. package/components/Dialog.css +235 -0
  23. package/components/Dialog.js +327 -0
  24. package/components/DialogActions.js +13 -0
  25. package/components/Divider.css +41 -0
  26. package/components/Divider.js +13 -0
  27. package/components/ExtendedFab.css +24 -0
  28. package/components/ExtendedFab.js +11 -0
  29. package/components/Fab.css +23 -0
  30. package/components/Fab.js +26 -0
  31. package/components/FilterChip.css +80 -0
  32. package/components/FilterChip.js +51 -0
  33. package/components/Headline.css +14 -0
  34. package/components/Headline.js +33 -0
  35. package/components/Icon.css +76 -0
  36. package/components/Icon.js +174 -0
  37. package/components/IconButton.css +151 -0
  38. package/components/IconButton.js +65 -0
  39. package/components/Input.js +16 -0
  40. package/components/Label.css +14 -0
  41. package/components/Label.js +7 -0
  42. package/components/Layout.css +19 -0
  43. package/components/Layout.js +12 -0
  44. package/components/List.css +12 -0
  45. package/components/List.js +17 -0
  46. package/components/ListItem.css +224 -0
  47. package/components/ListItem.js +112 -0
  48. package/components/ListOption.css +34 -0
  49. package/components/ListOption.js +122 -0
  50. package/components/ListSelect.css +9 -0
  51. package/components/ListSelect.js +206 -0
  52. package/components/Menu.css +171 -0
  53. package/components/Menu.js +470 -0
  54. package/components/MenuItem.css +53 -0
  55. package/components/MenuItem.js +215 -0
  56. package/components/Nav.css +17 -0
  57. package/components/Nav.js +23 -0
  58. package/components/NavBar.css +34 -0
  59. package/components/NavBar.js +88 -0
  60. package/components/NavBarItem.css +41 -0
  61. package/components/NavBarItem.js +7 -0
  62. package/components/NavDrawer.css +31 -0
  63. package/components/NavDrawer.js +13 -0
  64. package/components/NavDrawerItem.css +42 -0
  65. package/components/NavDrawerItem.js +12 -0
  66. package/components/NavItem.css +181 -0
  67. package/components/NavItem.js +83 -0
  68. package/components/NavRail.css +47 -0
  69. package/components/NavRail.js +17 -0
  70. package/components/NavRailItem.css +25 -0
  71. package/components/NavRailItem.js +7 -0
  72. package/components/Option.js +91 -0
  73. package/components/Outline.css +138 -0
  74. package/components/Pane.css +261 -0
  75. package/components/Pane.js +21 -0
  76. package/components/Progress.css +74 -0
  77. package/components/Progress.js +67 -0
  78. package/components/ProgressCircle.css +226 -0
  79. package/components/ProgressLine.css +155 -0
  80. package/components/Radio.css +83 -0
  81. package/components/Radio.js +42 -0
  82. package/components/RadioIcon.css +73 -0
  83. package/components/RadioIcon.js +37 -0
  84. package/components/Ripple.css +74 -0
  85. package/components/Ripple.js +114 -0
  86. package/components/SegmentedButton.css +94 -0
  87. package/components/SegmentedButton.js +49 -0
  88. package/components/SegmentedButtonGroup.css +12 -0
  89. package/components/SegmentedButtonGroup.js +44 -0
  90. package/components/Select.css +52 -0
  91. package/components/Select.js +71 -0
  92. package/components/Shape.css +132 -0
  93. package/components/Shape.js +25 -0
  94. package/components/Slider.css +306 -0
  95. package/components/Slider.js +206 -0
  96. package/components/Snackbar.css +80 -0
  97. package/components/Snackbar.js +75 -0
  98. package/components/Surface.css +10 -0
  99. package/components/Surface.js +23 -0
  100. package/components/Switch.css +63 -0
  101. package/components/Switch.js +127 -0
  102. package/components/SwitchIcon.css +177 -0
  103. package/components/SwitchIcon.js +89 -0
  104. package/components/SwitchIconAnimations.css +89 -0
  105. package/components/Tab.css +85 -0
  106. package/components/Tab.js +103 -0
  107. package/components/TabContent.js +151 -0
  108. package/components/TabList.css +129 -0
  109. package/components/TabList.js +309 -0
  110. package/components/TabPanel.js +37 -0
  111. package/components/TextArea.css +93 -0
  112. package/components/TextArea.js +229 -0
  113. package/components/Title.css +14 -0
  114. package/components/Title.js +15 -0
  115. package/components/Tooltip.css +40 -0
  116. package/components/Tooltip.js +22 -0
  117. package/components/TopAppBar.css +209 -0
  118. package/components/TopAppBar.js +201 -0
  119. package/core/Composition.js +988 -0
  120. package/core/CustomElement.js +844 -0
  121. package/core/ICustomElement.d.ts +288 -0
  122. package/core/ICustomElement.js +1 -0
  123. package/core/css.js +51 -0
  124. package/core/customTypes.js +125 -0
  125. package/core/dom.js +56 -245
  126. package/core/identify.js +40 -0
  127. package/core/observe.js +410 -0
  128. package/core/template.js +121 -0
  129. package/core/typings.d.ts +135 -0
  130. package/core/typings.js +1 -0
  131. package/mixins/AriaReflectorMixin.js +42 -0
  132. package/mixins/AriaToolbarMixin.js +13 -0
  133. package/mixins/ControlMixin.css +57 -0
  134. package/mixins/ControlMixin.js +212 -0
  135. package/mixins/DensityMixin.css +40 -0
  136. package/mixins/DensityMixin.js +11 -0
  137. package/mixins/FlexableMixin.css +79 -0
  138. package/mixins/FlexableMixin.js +32 -0
  139. package/mixins/FormAssociatedMixin.js +170 -0
  140. package/mixins/InputMixin.js +335 -0
  141. package/mixins/KeyboardNavMixin.js +244 -0
  142. package/mixins/RTLObserverMixin.js +35 -0
  143. package/mixins/ResizeObserverMixin.js +38 -0
  144. package/mixins/RippleMixin.css +12 -0
  145. package/mixins/RippleMixin.js +115 -0
  146. package/mixins/ScrollListenerMixin.js +100 -0
  147. package/mixins/ShapeMixin.css +135 -0
  148. package/mixins/ShapeMixin.js +31 -0
  149. package/mixins/StateMixin.css +82 -0
  150. package/mixins/StateMixin.js +114 -0
  151. package/mixins/SurfaceMixin.css +150 -0
  152. package/mixins/SurfaceMixin.js +32 -0
  153. package/mixins/TextFieldMixin.css +657 -0
  154. package/mixins/TextFieldMixin.js +121 -0
  155. package/mixins/ThemableMixin.css +204 -0
  156. package/mixins/ThemableMixin.js +16 -0
  157. package/mixins/TooltipTriggerMixin.css +27 -0
  158. package/mixins/TooltipTriggerMixin.js +366 -0
  159. package/mixins/TouchTargetMixin.css +26 -0
  160. package/mixins/TouchTargetMixin.js +9 -0
  161. package/package.json +57 -41
  162. package/theming/index.js +594 -0
  163. package/theming/loader.js +24 -0
  164. package/utils/cli.js +11 -0
  165. package/utils/color_keywords.js +151 -0
  166. package/utils/hct/Cam16.js +298 -0
  167. package/utils/hct/CorePalette.js +84 -0
  168. package/utils/hct/Hct.js +172 -0
  169. package/utils/hct/Scheme.js +587 -0
  170. package/utils/hct/TonalPalette.js +68 -0
  171. package/utils/hct/ViewingConditions.js +136 -0
  172. package/utils/hct/blend.js +93 -0
  173. package/utils/hct/colorUtils.js +302 -0
  174. package/utils/hct/hctSolver.js +559 -0
  175. package/utils/hct/helper.js +182 -0
  176. package/utils/hct/mathUtils.js +153 -0
  177. package/utils/jsonMergePatch.js +100 -0
  178. package/utils/jsx-runtime.js +101 -0
  179. package/utils/popup.js +117 -0
  180. package/utils/svg.js +129 -0
  181. package/.browserslistrc +0 -3
  182. package/.eslintrc.json +0 -153
  183. package/.stylelintrc.json +0 -600
  184. package/.vscode/launch.json +0 -31
  185. package/.vscode/settings.json +0 -3
  186. package/.vscode/tasks.json +0 -32
  187. package/CHANGELOG.md +0 -24
  188. package/CODE_OF_CONDUCT.md +0 -46
  189. package/adapters/datatable/column.js +0 -203
  190. package/adapters/datatable/index.js +0 -972
  191. package/adapters/dom/index.js +0 -601
  192. package/adapters/list/index.js +0 -69
  193. package/adapters/search/index.js +0 -521
  194. package/components/appbar/_spec.scss +0 -225
  195. package/components/appbar/_theme.scss +0 -0
  196. package/components/appbar/index.scss +0 -2
  197. package/components/banner/_spec.scss +0 -118
  198. package/components/banner/_theme.scss +0 -0
  199. package/components/banner/index.scss +0 -2
  200. package/components/bottomnav/README.md +0 -85
  201. package/components/bottomnav/_spec.scss +0 -157
  202. package/components/bottomnav/_theme.scss +0 -0
  203. package/components/bottomnav/index.js +0 -122
  204. package/components/bottomnav/index.scss +0 -2
  205. package/components/bottomnav/item.js +0 -89
  206. package/components/button/README.md +0 -61
  207. package/components/button/_spec.scss +0 -161
  208. package/components/button/_theme.scss +0 -65
  209. package/components/button/index.eta +0 -32
  210. package/components/button/index.js +0 -43
  211. package/components/button/index.pug +0 -18
  212. package/components/button/index.scss +0 -2
  213. package/components/card/_spec.scss +0 -249
  214. package/components/card/_theme.scss +0 -0
  215. package/components/card/index.scss +0 -2
  216. package/components/chip/_spec.scss +0 -134
  217. package/components/chip/_theme.scss +0 -177
  218. package/components/chip/index.js +0 -21
  219. package/components/chip/index.scss +0 -2
  220. package/components/chip/item.js +0 -20
  221. package/components/datatable/_spec.scss +0 -288
  222. package/components/datatable/_theme.scss +0 -154
  223. package/components/datatable/cell.js +0 -45
  224. package/components/datatable/columnheader.js +0 -47
  225. package/components/datatable/index.js +0 -388
  226. package/components/datatable/index.scss +0 -2
  227. package/components/datatable/row.js +0 -49
  228. package/components/datatable/rowheader.js +0 -18
  229. package/components/dialog/_spec.scss +0 -213
  230. package/components/dialog/_theme.scss +0 -0
  231. package/components/dialog/index.js +0 -627
  232. package/components/dialog/index.scss +0 -2
  233. package/components/divider/_spec.scss +0 -13
  234. package/components/divider/_theme.scss +0 -0
  235. package/components/divider/index.scss +0 -2
  236. package/components/elevation/_spec.scss +0 -9
  237. package/components/elevation/_theme.scss +0 -0
  238. package/components/elevation/index.scss +0 -2
  239. package/components/fab/_spec.scss +0 -222
  240. package/components/fab/_theme.scss +0 -0
  241. package/components/fab/index.js +0 -103
  242. package/components/fab/index.scss +0 -2
  243. package/components/grid/_spec.scss +0 -312
  244. package/components/grid/_theme.scss +0 -0
  245. package/components/grid/index.scss +0 -2
  246. package/components/layout/_mixins.scss +0 -33
  247. package/components/layout/_spec.scss +0 -1012
  248. package/components/layout/_theme.scss +0 -44
  249. package/components/layout/index.js +0 -464
  250. package/components/layout/index.scss +0 -2
  251. package/components/list/_spec.scss +0 -397
  252. package/components/list/_theme.scss +0 -111
  253. package/components/list/content.js +0 -110
  254. package/components/list/index.js +0 -260
  255. package/components/list/index.scss +0 -2
  256. package/components/list/item.js +0 -170
  257. package/components/list/secondary.js +0 -46
  258. package/components/menu/_spec.scss +0 -362
  259. package/components/menu/_theme.scss +0 -0
  260. package/components/menu/index.js +0 -721
  261. package/components/menu/index.scss +0 -2
  262. package/components/menu/item.js +0 -239
  263. package/components/progress/_spec.scss +0 -147
  264. package/components/progress/_theme.scss +0 -0
  265. package/components/progress/index.js +0 -36
  266. package/components/progress/index.scss +0 -2
  267. package/components/selection/_spec.scss +0 -386
  268. package/components/selection/_theme.scss +0 -166
  269. package/components/selection/index.eta +0 -60
  270. package/components/selection/index.js +0 -76
  271. package/components/selection/index.pug +0 -30
  272. package/components/selection/index.scss +0 -2
  273. package/components/selection/input.js +0 -56
  274. package/components/selection/radiogroup.js +0 -47
  275. package/components/slider/_spec.scss +0 -64
  276. package/components/slider/_theme.scss +0 -0
  277. package/components/slider/index.scss +0 -2
  278. package/components/snackbar/_spec.scss +0 -195
  279. package/components/snackbar/_theme.scss +0 -0
  280. package/components/snackbar/index.js +0 -344
  281. package/components/snackbar/index.scss +0 -2
  282. package/components/tab/_spec.scss +0 -235
  283. package/components/tab/_theme.scss +0 -0
  284. package/components/tab/content.js +0 -205
  285. package/components/tab/index.js +0 -260
  286. package/components/tab/index.scss +0 -2
  287. package/components/tab/item.js +0 -89
  288. package/components/tab/list.js +0 -210
  289. package/components/tab/panel.js +0 -54
  290. package/components/template/_theme.scss +0 -27
  291. package/components/textfield/README.md +0 -179
  292. package/components/textfield/_mixins.scss +0 -52
  293. package/components/textfield/_spec.scss +0 -809
  294. package/components/textfield/_theme.scss +0 -299
  295. package/components/textfield/index.eta +0 -74
  296. package/components/textfield/index.js +0 -168
  297. package/components/textfield/index.pug +0 -30
  298. package/components/textfield/index.scss +0 -2
  299. package/components/tooltip/_spec.scss +0 -188
  300. package/components/tooltip/_theme.scss +0 -0
  301. package/components/tooltip/index.scss +0 -2
  302. package/components/type/_spec.scss +0 -224
  303. package/components/type/_theme.scss +0 -0
  304. package/components/type/index.scss +0 -2
  305. package/core/_breakpoint.scss +0 -189
  306. package/core/_elevation.scss +0 -38
  307. package/core/_length.scss +0 -9
  308. package/core/_motion.scss +0 -31
  309. package/core/_platform.scss +0 -34
  310. package/core/_type.scss +0 -127
  311. package/core/aria/attributes.js +0 -141
  312. package/core/aria/button.js +0 -50
  313. package/core/aria/keyboard.js +0 -93
  314. package/core/aria/rovingtabindex.js +0 -178
  315. package/core/aria/tab.js +0 -60
  316. package/core/color/_spec.scss +0 -0
  317. package/core/color/_theme.scss +0 -390
  318. package/core/color/index.scss +0 -2
  319. package/core/document/index.js +0 -39
  320. package/core/overlay/_spec.scss +0 -31
  321. package/core/overlay/_theme.scss +0 -171
  322. package/core/overlay/index.js +0 -108
  323. package/core/overlay/index.scss +0 -2
  324. package/core/ripple/_spec.scss +0 -197
  325. package/core/ripple/_theme.scss +0 -40
  326. package/core/ripple/index.js +0 -294
  327. package/core/ripple/index.scss +0 -2
  328. package/core/theme/_config.scss +0 -2
  329. package/core/theme/_mixins.scss +0 -172
  330. package/core/theme/_palettes.scss +0 -406
  331. package/core/theme/_variables.scss +0 -24
  332. package/core/theme/index.js +0 -50
  333. package/core/throttler.js +0 -42
  334. package/core/transition/index.js +0 -468
  335. package/docs/_flex.scss +0 -22
  336. package/docs/_menuoptions.js +0 -183
  337. package/docs/_mixins.pug +0 -155
  338. package/docs/_partials/_androidnavbar.eta +0 -5
  339. package/docs/_partials/_androidstatusbar.eta +0 -13
  340. package/docs/_partials/_appbar.eta +0 -29
  341. package/docs/_partials/_buttontest.eta +0 -31
  342. package/docs/_partials/_header.eta +0 -149
  343. package/docs/_partials/_navlistitem.eta +0 -16
  344. package/docs/_partials/_target.eta +0 -1
  345. package/docs/_sample-utils.js +0 -93
  346. package/docs/_storage.js +0 -33
  347. package/docs/docs.scss +0 -295
  348. package/docs/index.eta +0 -16
  349. package/docs/index.js +0 -0
  350. package/docs/pages/appbar.eta +0 -114
  351. package/docs/pages/appbar.js +0 -0
  352. package/docs/pages/appbar.pug +0 -78
  353. package/docs/pages/bottomnav.eta +0 -188
  354. package/docs/pages/bottomnav.js +0 -115
  355. package/docs/pages/bottomnav.pug +0 -137
  356. package/docs/pages/button.eta +0 -124
  357. package/docs/pages/button.js +0 -224
  358. package/docs/pages/button.pug +0 -121
  359. package/docs/pages/card.eta +0 -90
  360. package/docs/pages/card.js +0 -177
  361. package/docs/pages/card.pug +0 -74
  362. package/docs/pages/chip.eta +0 -122
  363. package/docs/pages/chip.js +0 -82
  364. package/docs/pages/chip.pug +0 -91
  365. package/docs/pages/color.eta +0 -143
  366. package/docs/pages/color.js +0 -262
  367. package/docs/pages/color.pug +0 -121
  368. package/docs/pages/datatable.eta +0 -323
  369. package/docs/pages/datatable.js +0 -164
  370. package/docs/pages/datatable.pug +0 -283
  371. package/docs/pages/dialog.eta +0 -186
  372. package/docs/pages/dialog.js +0 -177
  373. package/docs/pages/dialog.pug +0 -132
  374. package/docs/pages/dom.eta +0 -26
  375. package/docs/pages/dom.js +0 -143
  376. package/docs/pages/dom.pug +0 -22
  377. package/docs/pages/elevation.eta +0 -35
  378. package/docs/pages/elevation.js +0 -0
  379. package/docs/pages/elevation.pug +0 -25
  380. package/docs/pages/fab.eta +0 -99
  381. package/docs/pages/fab.js +0 -44
  382. package/docs/pages/fab.pug +0 -66
  383. package/docs/pages/grid.eta +0 -135
  384. package/docs/pages/grid.js +0 -128
  385. package/docs/pages/grid.pug +0 -95
  386. package/docs/pages/layout.eta +0 -8
  387. package/docs/pages/layout.js +0 -0
  388. package/docs/pages/layout.pug +0 -7
  389. package/docs/pages/list.eta +0 -465
  390. package/docs/pages/list.js +0 -9
  391. package/docs/pages/list.pug +0 -326
  392. package/docs/pages/menu.eta +0 -276
  393. package/docs/pages/menu.js +0 -217
  394. package/docs/pages/menu.pug +0 -205
  395. package/docs/pages/overlay.eta +0 -69
  396. package/docs/pages/overlay.js +0 -4
  397. package/docs/pages/overlay.pug +0 -55
  398. package/docs/pages/progress.eta +0 -23
  399. package/docs/pages/progress.js +0 -12
  400. package/docs/pages/progress.pug +0 -16
  401. package/docs/pages/ripple.eta +0 -27
  402. package/docs/pages/ripple.js +0 -4
  403. package/docs/pages/ripple.pug +0 -21
  404. package/docs/pages/search.eta +0 -246
  405. package/docs/pages/search.js +0 -243
  406. package/docs/pages/search.pug +0 -165
  407. package/docs/pages/selection.eta +0 -111
  408. package/docs/pages/selection.js +0 -13
  409. package/docs/pages/selection.pug +0 -74
  410. package/docs/pages/slider.eta +0 -23
  411. package/docs/pages/slider.js +0 -0
  412. package/docs/pages/slider.pug +0 -17
  413. package/docs/pages/snackbar.eta +0 -83
  414. package/docs/pages/snackbar.js +0 -158
  415. package/docs/pages/snackbar.pug +0 -60
  416. package/docs/pages/tab.eta +0 -421
  417. package/docs/pages/tab.js +0 -151
  418. package/docs/pages/tab.pug +0 -304
  419. package/docs/pages/textfield.eta +0 -486
  420. package/docs/pages/textfield.js +0 -254
  421. package/docs/pages/textfield.pug +0 -360
  422. package/docs/pages/tooltip.eta +0 -94
  423. package/docs/pages/tooltip.js +0 -0
  424. package/docs/pages/tooltip.pug +0 -78
  425. package/docs/pages/transition.eta +0 -117
  426. package/docs/pages/transition.js +0 -54
  427. package/docs/pages/transition.pug +0 -76
  428. package/docs/pages/type.eta +0 -31
  429. package/docs/pages/type.js +0 -0
  430. package/docs/pages/type.pug +0 -29
  431. package/docs/postrender.js +0 -39
  432. package/docs/prerender.js +0 -16
  433. package/docs/pwa/_dialogs.eta +0 -143
  434. package/docs/pwa/_dialogs.pug +0 -96
  435. package/docs/pwa/_menus.eta +0 -16
  436. package/docs/pwa/_menus.pug +0 -11
  437. package/docs/pwa/pwa-prerender.js +0 -3
  438. package/docs/pwa/pwa.eta +0 -480
  439. package/docs/pwa/pwa.js +0 -306
  440. package/docs/pwa/pwa.pug +0 -325
  441. package/docs/pwa/pwa.scss +0 -26
  442. package/docs/spec.scss +0 -26
  443. package/docs/themes/_component-themes.scss +0 -26
  444. package/docs/themes/theme-colored-fallbacks.scss +0 -17
  445. package/docs/themes/theme-colored.scss +0 -17
  446. package/docs/themes/theme-default-fallbacks.scss +0 -17
  447. package/docs/themes/theme-default.scss +0 -17
  448. package/jsconfig.json +0 -12
  449. package/scripts/deploy-docs.sh +0 -9
  450. package/templates/index.eta +0 -2
  451. package/templates/index.pug +0 -3
  452. package/webpack.config.cjs +0 -257
@@ -1,972 +0,0 @@
1
- import * as Button from '../../components/button/index.js';
2
- import * as DataTableCell from '../../components/datatable/cell.js';
3
- import * as DataTableColumnHeader from '../../components/datatable/columnheader.js';
4
- import * as DataTable from '../../components/datatable/index.js';
5
- import * as DataTableRow from '../../components/datatable/row.js';
6
- import * as DataTableRowHeader from '../../components/datatable/rowheader.js';
7
- import * as Selection from '../../components/selection/index.js';
8
- import * as RovingTabIndex from '../../core/aria/rovingtabindex.js';
9
- import { getPassiveEventListenerOption, iterateArrayLike, iterateSomeOfArrayLike } from '../../core/dom.js';
10
- import { noop } from '../../utils/function.js';
11
-
12
- import DataTableAdapterColumn from './column.js';
13
-
14
- /**
15
- * @template {Record<string, any>} T
16
- * @template {keyof T & string} K
17
- * @typedef {import('./column').DataTableAdapterColumnOptions<T,K>} DataTableAdapterColumnOptions<T,K>
18
- */
19
-
20
- /**
21
- * Callback fired when value change is requested
22
- * Return truthy value to cancel updating object
23
- * @template {Record<string, any>} T
24
- * @template {keyof T & string} K
25
- * @callback DataTableAdapterOnValueChangeRequestedCallback<T>
26
- * @param {T} object
27
- * @param {K} key
28
- * @param {T[K]} value
29
- * @return {boolean} cancel
30
- */
31
-
32
- /**
33
- * Callback fired when value is changed
34
- * @template {Record<string, any>} T
35
- * @template {keyof T & string} K
36
- * @callback DataTableAdapterOnValueChangedCallback<T>
37
- * @param {T} object
38
- * @param {K} key
39
- * @param {T[K]} value
40
- * @return {void}
41
- */
42
-
43
- /**
44
- * @template {Record<string, any>} T
45
- * @callback DataTableAdapterFilter<T>
46
- * @param {T} element
47
- * @param {number} [index]
48
- * @param {T[]} array
49
- * @return {any}
50
- */
51
-
52
- /**
53
- * @template {Record<string, any>} T
54
- * @callback DataTableAdapterSorter<T>
55
- * @param {T} a
56
- * @param {T} b
57
- * @return {number}
58
- */
59
-
60
- /**
61
- * Constructor options for DataTableAdapter
62
- * @template T
63
- * @typedef DataTableAdapterOptions<T>
64
- * @prop {HTMLElement} datatable
65
- * @prop {T[]} datasource Object array
66
- * @prop {DataTableAdapterFilter<T>} [filter]
67
- * @prop {DataTableAdapterOnValueChangeRequestedCallback<T,keyof T & string>} [onValueChangeRequested]
68
- * @prop {DataTableAdapterOnValueChangedCallback<T,keyof T & string>} [onValueChanged]
69
- * @prop {DataTableAdapterSorter<T>} [sorter]
70
- */
71
-
72
- /** @template {Record<string, any>} T */
73
- export default class DataTableAdapter {
74
- /** @param {DataTableAdapterOptions<T>} options */
75
- constructor(options) {
76
- this.element = options.datatable;
77
- this.datasource = options.datasource;
78
- this.filter = options.filter;
79
- this.sorter = options.sorter;
80
- this.onValueChangeRequested = options.onValueChangeRequested || (() => false);
81
- this.onValueChanged = options.onValueChanged || noop;
82
- DataTable.attach(this.element);
83
-
84
- this.onElementScrollListener = () => this.onElementScroll();
85
-
86
- /**
87
- * @param {CustomEvent} event
88
- * @return {void}
89
- */
90
- this.onDataTableColumnHeaderSortListener = (event) => this.onDataTableColumnHeaderSort(event);
91
- /**
92
- * @param {CustomEvent} event
93
- * @return {void}
94
- */
95
- this.onCheckedChangeEventListener = (event) => this.onCheckedChangeEvent(event);
96
-
97
- this.element.addEventListener(
98
- DataTableColumnHeader.SORT_EVENT,
99
- this.onDataTableColumnHeaderSortListener,
100
- );
101
- this.element.addEventListener(
102
- Selection.CHECKED_CHANGE_EVENT,
103
- this.onCheckedChangeEventListener,
104
- );
105
- this.element.addEventListener(
106
- DataTableRow.SELECTED_CHANGE_EVENT,
107
- DataTableAdapter.onRowSelectedChangeEvent,
108
- );
109
-
110
- this.scroller = DataTable.getScroller(this.element);
111
- this.element.setAttribute('mdw-datatable-adapter', '');
112
- /** @type {DataTableAdapterColumn<T,any>[]} */
113
- this.columns = [];
114
- this.page = 0;
115
- this.pageLimit = 0;
116
- this.debounceTimeMs = 0;
117
- this.throttleTimeMs = 0;
118
- this.useLazyRendering = false;
119
- }
120
-
121
- /**
122
- * @param {CustomEvent} event
123
- * @return {void}
124
- */
125
- onDataTableColumnHeaderSort(event) {
126
- /** @type {HTMLTableHeaderCellElement} */
127
- const cell = (event.target);
128
- const ascending = event.detail.sort === 'ascending';
129
- this.updateSortIcons(cell, ascending);
130
- if (this.updateSortColumn) {
131
- this.updateSortColumn(cell, ascending);
132
- }
133
- }
134
-
135
- detach() {
136
- this.element.removeAttribute('mdw-datatable-adapter');
137
- this.element = null;
138
- this.datasource = null;
139
- this.filteredDatasource = null;
140
- }
141
-
142
- /**
143
- * @param {boolean} [forceRefresh=false]
144
- * @return {void}
145
- */
146
- performThrottledRender(forceRefresh = false) {
147
- this.performLazyRender(forceRefresh);
148
- if (this.throttledRenderPending) {
149
- this.throttledRenderPending = false;
150
- this.scheduleThrottledRender();
151
- }
152
- }
153
-
154
- /**
155
- * @param {boolean} [forceRefresh=false]
156
- * @return {void}
157
- */
158
- scheduleThrottledRender(forceRefresh = false) {
159
- if (this.throttleTimeMs < 17) {
160
- window.requestAnimationFrame(() => this.performThrottledRender(forceRefresh));
161
- } else {
162
- setTimeout(() => this.performThrottledRender(forceRefresh), this.throttleTimeMs);
163
- }
164
- }
165
-
166
- /**
167
- * @param {CustomEvent} event
168
- * @return {void}
169
- */
170
- static onRowSelectedChangeEvent(event) {
171
- /** @type {HTMLTableRowElement} */
172
- const row = (event.target);
173
- const selectionElement = row.querySelector('[mdw-selector] .mdw-selection[aria-checked]');
174
- if (!selectionElement) {
175
- return;
176
- }
177
- Selection.setChecked(selectionElement, event.detail.value, true);
178
- }
179
-
180
- onElementScroll() {
181
- if (this.debounceTimeout) {
182
- clearTimeout(this.debounceTimeout);
183
- this.debounceTimeout = null;
184
- }
185
- if (this.throttledRenderPending) {
186
- // Will perform in the future
187
- return;
188
- }
189
- if (this.debounceTimeMs) {
190
- this.debounceTimeout = setTimeout(() => {
191
- this.scheduleThrottledRender();
192
- this.throttledRenderPending = true;
193
- }, this.debounceTimeMs);
194
- } else {
195
- this.scheduleThrottledRender();
196
- this.throttledRenderPending = true;
197
- }
198
- }
199
-
200
- buildScrollListener() {
201
- this.scroller.addEventListener('scroll', this.onElementScrollListener, getPassiveEventListenerOption());
202
- }
203
-
204
- destroyScrollListener() {
205
- this.scroller.removeEventListener('scroll', this.onElementScrollListener);
206
- }
207
-
208
- /**
209
- * @param {CustomEvent} event
210
- * @return {void}
211
- */
212
- onCheckedChangeEvent(event) {
213
- /** @type {HTMLElement} */
214
- const selectionElement = (event.target);
215
- const checked = event.detail.value === 'true';
216
- const currentCell = this.getTableCell(selectionElement);
217
- if (currentCell.getAttribute('role') === 'columnheader') {
218
- this.setCheckOnAllRows(checked, currentCell.cellIndex);
219
- this.setHasSelection(checked);
220
- return;
221
- }
222
- const currentRow = this.getTableRow(selectionElement);
223
- const object = this.getDataForTableRow(currentRow);
224
- /** @type {keyof T & string} */
225
- // eslint-disable-next-line prefer-destructuring
226
- const key = (currentCell.dataset.key);
227
- if (this.onValueChangeRequested(object, key, checked)) {
228
- event.preventDefault();
229
- return;
230
- }
231
- object[key] = checked;
232
- this.onValueChanged(object, key, checked);
233
- if (currentCell.hasAttribute('mdw-selector')) {
234
- DataTableRow.setSelected(currentRow, event.detail.value, true);
235
- }
236
- }
237
-
238
- /**
239
- * Overridable sorting method
240
- * @param {HTMLTableHeaderCellElement} [tableHeaderCell] null if none
241
- * @param {boolean} [ascending=false]
242
- * @return {void}
243
- */
244
- updateSortColumn(tableHeaderCell, ascending) {
245
- if (!tableHeaderCell) {
246
- this.sorter = null;
247
- this.refresh();
248
- return;
249
- }
250
- if (tableHeaderCell.cellIndex === -1) {
251
- // Header not attached to row!
252
- return;
253
- }
254
- const index = tableHeaderCell.cellIndex;
255
- const tableColumn = this.columns[index];
256
- const direction = ascending ? 1 : -1;
257
- this.sorter = ((/** @type {T} */ a, /** @type {T} */ b) => {
258
- const valueA = a[tableColumn.key];
259
- const valueB = b[tableColumn.key];
260
- if (tableColumn.sorter) {
261
- return tableColumn.sorter(a, b) * direction;
262
- }
263
- if (valueA == null) {
264
- if (valueB == null) {
265
- return 0;
266
- }
267
- return -1 * direction;
268
- }
269
- if (valueB == null) {
270
- return direction;
271
- }
272
- if (tableColumn.type === 'number') {
273
- return (parseFloat(valueA) - parseFloat(valueB)) * direction;
274
- }
275
- if (tableColumn.type === 'checkbox') {
276
- return ((valueA ? 1 : 0) - (valueB ? 1 : 0)) * direction;
277
- }
278
- if ('localeCompare' in valueA) {
279
- return valueA.localeCompare(valueB) * direction;
280
- }
281
- // eslint-disable-next-line eqeqeq
282
- if (valueA == valueB) {
283
- return 0;
284
- }
285
- return (valueA - valueB) * direction;
286
- });
287
- this.refresh();
288
- }
289
-
290
- /**
291
- * @param {HTMLTableHeaderCellElement} [sortedTableHeaderCell] null if none
292
- * @param {boolean} [ascending=false]
293
- * @return {void}
294
- */
295
- updateSortIcons(sortedTableHeaderCell, ascending) {
296
- if (sortedTableHeaderCell) {
297
- if (ascending) {
298
- sortedTableHeaderCell.setAttribute('aria-sort', 'ascending');
299
- } else {
300
- sortedTableHeaderCell.setAttribute('aria-sort', 'descending');
301
- }
302
- }
303
- iterateArrayLike(this.getHeaderRow().getElementsByTagName('th'), (otherTableHeader) => {
304
- if (otherTableHeader !== sortedTableHeaderCell && otherTableHeader.hasAttribute('aria-sort')) {
305
- otherTableHeader.setAttribute('aria-sort', 'none');
306
- }
307
- });
308
- }
309
-
310
- /**
311
- * @param {boolean} value
312
- * @param {number} columnIndex
313
- * @return {void}
314
- */
315
- setCheckOnAllRows(value, columnIndex) {
316
- const column = this.columns[columnIndex];
317
- this.datasource.forEach((object) => {
318
- object[column.key] = value; // eslint-disable-line no-param-reassign
319
- });
320
- this.refresh();
321
- }
322
-
323
- /**
324
- * @param {HTMLElement} element
325
- * @return {HTMLTableRowElement}
326
- */
327
- getTableRow(element) {
328
- if (element === this.element) {
329
- return null;
330
- }
331
- if (element instanceof HTMLTableRowElement) {
332
- return element;
333
- }
334
- if (!element.parentElement) {
335
- return null;
336
- }
337
- return this.getTableRow(element.parentElement);
338
- }
339
-
340
- /**
341
- * @param {HTMLElement} element
342
- * @return {HTMLTableCellElement}
343
- */
344
- getTableCell(element) {
345
- if (element === this.element) {
346
- return null;
347
- }
348
- if (element instanceof HTMLTableCellElement) {
349
- return element;
350
- }
351
- if (!element.parentElement) {
352
- return null;
353
- }
354
- return this.getTableCell(element.parentElement);
355
- }
356
-
357
- /** @return {T[]} */
358
- getSelectedRows() {
359
- const selectorColumn = this.columns.filter((column) => column.rowSelector)[0];
360
- if (!selectorColumn) {
361
- return [];
362
- }
363
- return this.getDatasource().filter((row) => row[selectorColumn.key]);
364
- }
365
-
366
- /**
367
- * @param {boolean} value
368
- * @return {void}
369
- */
370
- setHasSelection(value) {
371
- if (value) {
372
- this.element.setAttribute('mdw-has-selection', '');
373
- return;
374
- }
375
- this.element.removeAttribute('mdw-has-selection');
376
- }
377
-
378
- /**
379
- * @param {T[]} datasource Object array
380
- * @return {void}
381
- */
382
- setDatasource(datasource) {
383
- this.datasource = datasource;
384
- }
385
-
386
- /**
387
- * Toggle lazy rending for datasources
388
- * @param {boolean} value
389
- * @return {void}
390
- */
391
- setUseLazyRendering(value) {
392
- this.useLazyRendering = value;
393
- if (value) {
394
- this.buildScrollListener();
395
- } else {
396
- this.destroyScrollListener();
397
- }
398
- }
399
-
400
- /**
401
- * @template {keyof T & string} K
402
- * @param {DataTableAdapterColumnOptions<T,K>} options
403
- * @return {DataTableAdapterColumn<T,K>}
404
- */
405
- addColumn(options) {
406
- const tableColumn = new DataTableAdapterColumn(options);
407
- const headerRow = this.getHeaderRow();
408
- headerRow.appendChild(tableColumn.element);
409
- this.columns.push(tableColumn);
410
- return tableColumn;
411
- }
412
-
413
- updatePaginator() {
414
- if (!this.pageLimit) {
415
- return;
416
- }
417
- const min = this.page * this.pageLimit;
418
- const total = this.getDatasource().length;
419
- let max = this.pageLimit + min;
420
- if (max > total) {
421
- max = total;
422
- }
423
- this.paginationDetailsElement.textContent = `${min + 1}-${max} of ${total}`;
424
- this.previousPageButton.setAttribute('aria-disabled', (min === 0 ? 'true' : 'false'));
425
- this.nextPageButton.setAttribute('aria-disabled', (max === total ? 'true' : 'false'));
426
- }
427
-
428
- /**
429
- * @param {Object} options
430
- * @param {boolean} [options.disabled=false]
431
- * @param {number} [options.limit=10]
432
- * @param {number[]} [options.limits=[10,25,50,100]]
433
- * @return {void}
434
- */
435
- setPagination(options = {}) {
436
- const footer = this.getFooter(!options.disabled);
437
- if (options.disabled) {
438
- this.pageLimit = 0;
439
- this.page = 0;
440
- if (footer) {
441
- footer.style.setProperty('display', 'none');
442
- }
443
- this.needsDraw = true;
444
- return;
445
- }
446
- footer.style.removeProperty('display');
447
- let optionsElement = footer.getElementsByClassName('mdw-datatable__footer-options')[0];
448
- if (!optionsElement) {
449
- optionsElement = document.createElement('div');
450
- optionsElement.classList.add('mdw-datatable__footer-options');
451
- const rowsPerPageText = document.createElement('span');
452
- rowsPerPageText.textContent = 'Rows per page';
453
- const limits = options.limits || [10, 25, 50, 100];
454
- const limitsElement = document.createElement('label');
455
- limitsElement.classList.add('mdw-textfield');
456
- limitsElement.setAttribute('mdw-solo', '');
457
- const select = document.createElement('select');
458
- select.classList.add('mdw-textfield__input');
459
- limits.forEach((limit) => {
460
- const option = document.createElement('option');
461
- option.value = limit.toString();
462
- option.textContent = limit.toString();
463
- option.className = 'mdw-theme';
464
- option.setAttribute('mdw-surface', 'card');
465
- select.appendChild(option);
466
- });
467
- select.value = (options.limit && options.limit.toString()) || '10';
468
- const dropdownIcon = document.createElement('div');
469
- dropdownIcon.classList.add('mdw-textfield__icon');
470
- dropdownIcon.setAttribute('mdw-dropdown', '');
471
- limitsElement.appendChild(select);
472
- limitsElement.appendChild(dropdownIcon);
473
- optionsElement.appendChild(rowsPerPageText);
474
- optionsElement.appendChild(limitsElement);
475
- footer.appendChild(optionsElement);
476
- select.addEventListener('input', () => {
477
- this.pageLimit = parseInt(select.value, 10);
478
- this.updateRowCount(false);
479
- this.updatePaginator();
480
- this.refreshRows();
481
- });
482
- }
483
- if (!this.paginationDetailsElement) {
484
- this.paginationDetailsElement = footer.getElementsByClassName('mdw-datatable__footer-details')[0];
485
- }
486
- if (!this.paginationDetailsElement) {
487
- this.paginationDetailsElement = document.createElement('div');
488
- this.paginationDetailsElement.classList.add('mdw-datatable__footer-details');
489
- footer.appendChild(this.paginationDetailsElement);
490
- }
491
- if (!this.paginationControls) {
492
- this.paginationControls = footer.getElementsByClassName('mdw-datatable__footer-controls')[0];
493
- }
494
- if (!this.paginationControls) {
495
- this.paginationControls = document.createElement('div');
496
- this.paginationControls.classList.add('mdw-datatable__footer-controls');
497
- footer.appendChild(this.paginationControls);
498
- }
499
- if (!this.previousPageButton || !this.nextPageButton) {
500
- const buttons = this.paginationControls.getElementsByClassName('mdw-button');
501
- if (buttons.length !== 2) {
502
- this.previousPageButton = document.createElement('a');
503
- this.previousPageButton.classList.add('mdw-button');
504
- this.previousPageButton.classList.add('material-icons');
505
- this.previousPageButton.setAttribute('mdw-icon', '');
506
- this.previousPageButton.textContent = 'chevron_left';
507
- this.paginationControls.appendChild(this.previousPageButton);
508
- Button.attach(this.previousPageButton);
509
-
510
- this.nextPageButton = document.createElement('a');
511
- this.nextPageButton.classList.add('mdw-button');
512
- this.nextPageButton.classList.add('material-icons');
513
- this.nextPageButton.setAttribute('mdw-icon', '');
514
- this.nextPageButton.textContent = 'chevron_right';
515
- this.paginationControls.appendChild(this.nextPageButton);
516
- Button.attach(this.nextPageButton);
517
- } else {
518
- this.previousPageButton = buttons[0];
519
- this.nextPageButton = buttons[1];
520
- }
521
- this.previousPageButton.addEventListener('click', () => {
522
- if (this.previousPageButton.getAttribute('aria-disabled') === 'true') {
523
- return;
524
- }
525
- this.page -= 1;
526
- this.updateRowCount(false);
527
- this.updatePaginator();
528
- this.refreshRows();
529
- });
530
- this.nextPageButton.addEventListener('click', () => {
531
- if (this.nextPageButton.getAttribute('aria-disabled') === 'true') {
532
- return;
533
- }
534
- this.page += 1;
535
- this.updateRowCount(false);
536
- this.updatePaginator();
537
- this.refreshRows();
538
- });
539
- }
540
- this.pageLimit = options.limit || 10;
541
- this.updateRowCount(false);
542
- this.updatePaginator();
543
- this.refreshRows();
544
- }
545
-
546
- /**
547
- * @param {boolean} create
548
- * @return {HTMLElement}
549
- */
550
- getFooter(create) {
551
- /** @type {HTMLElement} */
552
- let footer = (this.element.getElementsByClassName('mdw-datatable__footer')[0]);
553
- if (!footer && create) {
554
- footer = document.createElement('div');
555
- footer.classList.add('mdw-datatable__footer');
556
- this.element.appendChild(footer);
557
- }
558
- return footer;
559
- }
560
-
561
- /**
562
- * @param {HTMLTableRowElement} el
563
- * @param {?number} viewportTop
564
- * @param {?number} viewportBottom
565
- * @return {boolean}
566
- */
567
- isRowVisible(
568
- el,
569
- viewportTop = this.scroller.scrollTop,
570
- viewportBottom = this.scroller.scrollTop + this.scroller.offsetHeight,
571
- ) {
572
- const rowTop = el.offsetTop;
573
- const rowBottom = rowTop + el.offsetHeight;
574
- if (rowTop > viewportTop && rowTop < viewportBottom) {
575
- // Top of row is visible
576
- return true;
577
- }
578
- if (rowBottom > viewportTop && rowBottom < viewportBottom) {
579
- // Bottom of row is visible
580
- return true;
581
- }
582
- return false;
583
- }
584
-
585
- /**
586
- * @param {(HTMLTableRowElement[])} visibleRows
587
- * @return {void}
588
- */
589
- clearNonvisibleRows(visibleRows) {
590
- const tbody = this.getTableBody();
591
- if (visibleRows.length === tbody.rows.length) {
592
- return;
593
- }
594
- let firstRowIndex = Infinity;
595
- let lastRowIndex = -Infinity;
596
- if (visibleRows.length) {
597
- firstRowIndex = visibleRows[0].sectionRowIndex;
598
- lastRowIndex = visibleRows[visibleRows.length - 1].sectionRowIndex;
599
- }
600
- iterateArrayLike(tbody.rows, (row, index) => {
601
- if (index >= firstRowIndex && index <= lastRowIndex) {
602
- return;
603
- }
604
- if (row.lastChild) {
605
- // Store row height to prevent layout shifting
606
- row.style.setProperty('height', `${row.offsetHeight || 0}px`);
607
- }
608
- while (row.lastChild) {
609
- row.removeChild(row.lastChild);
610
- }
611
- });
612
- }
613
-
614
- /**
615
- * @return {HTMLTableRowElement[]}
616
- */
617
- getLazyRenderRows() {
618
- const tbody = this.getTableBody();
619
- const len = tbody.rows.length;
620
- /** @type {HTMLTableRowElement[]} */
621
- const rows = [];
622
- const minRowCount = window.screen.height / 48;
623
- if (len <= minRowCount) {
624
- iterateArrayLike(tbody.rows, (row) => {
625
- rows.push(row);
626
- });
627
- return rows;
628
- }
629
- let foundFirstVisibleRow = false;
630
- let startIndex = 0;
631
- let endIndex = 0;
632
- const viewportTop = this.scroller.scrollTop;
633
- const viewportBottom = viewportTop + this.scroller.offsetHeight;
634
- iterateSomeOfArrayLike(tbody.rows, (row, index) => {
635
- if (this.isRowVisible(row, viewportTop, viewportBottom)) {
636
- if (!foundFirstVisibleRow) {
637
- foundFirstVisibleRow = true;
638
- startIndex = index;
639
- }
640
- endIndex = index;
641
- } else if (foundFirstVisibleRow) {
642
- return true;
643
- }
644
- return false;
645
- });
646
-
647
- while ((endIndex - startIndex) + 1 < minRowCount) {
648
- if (startIndex === 0) {
649
- endIndex += 1;
650
- } else if (endIndex === len - 1) {
651
- startIndex -= 1;
652
- } else {
653
- startIndex -= 1;
654
- endIndex += 1;
655
- }
656
- }
657
- for (let i = startIndex; i <= endIndex; i += 1) {
658
- rows.push(tbody.rows.item(i));
659
- }
660
-
661
- return rows;
662
- }
663
-
664
- /**
665
- * @param {boolean} forceRefresh
666
- * @return {void}
667
- */
668
- performLazyRender(forceRefresh = false) {
669
- const visibleRows = this.getLazyRenderRows();
670
- visibleRows.forEach((row) => {
671
- if (forceRefresh || !row.cells.length) {
672
- this.refreshRow(row.sectionRowIndex);
673
- }
674
- });
675
- this.clearNonvisibleRows(visibleRows);
676
- }
677
-
678
- /**
679
- * @param {DataTableAdapterFilter<T>} filter
680
- * @return {void}
681
- */
682
- setFilter(filter) {
683
- this.filter = filter;
684
- this.refreshFilter();
685
- }
686
-
687
- /**
688
- * @param {DataTableAdapterSorter<T>} sorter
689
- * @return {void}
690
- */
691
- setSorter(sorter) {
692
- this.sorter = sorter;
693
- this.refreshFilter();
694
- }
695
-
696
- refreshFilter() {
697
- if (this.filter && this.sorter) {
698
- this.filteredDatasource = this.datasource.filter(this.filter).sort(this.sorter);
699
- } else if (this.filter) {
700
- this.filteredDatasource = this.datasource.filter(this.filter);
701
- } else if (this.sorter) {
702
- this.filteredDatasource = this.datasource.slice(0).sort(this.sorter);
703
- } else {
704
- this.filteredDatasource = null;
705
- }
706
- }
707
-
708
- /**
709
- * Get filtered datasource
710
- * @return {T[]}
711
- */
712
- getDatasource() {
713
- if (this.filter || this.sorter) {
714
- if (this.filteredDatasource == null) {
715
- this.refreshFilter();
716
- }
717
- return this.filteredDatasource;
718
- }
719
- return this.datasource;
720
- }
721
-
722
- /**
723
- * Update number of rows in table
724
- * @param {boolean} [refresh=false] Refresh new rows
725
- * @return {void}
726
- */
727
- updateRowCount(refresh) {
728
- const tbody = this.getTableBody();
729
- const rowLength = tbody.rows.length;
730
-
731
- const datasource = this.getDatasource();
732
- let rowsToDisplay = datasource.length;
733
- if (this.pageLimit) {
734
- let offset = this.page * this.pageLimit;
735
- if (offset > rowsToDisplay) {
736
- // Datasource or filter likely changed
737
- // Reset to page 0
738
- this.page = 0;
739
- offset = 0;
740
- }
741
- rowsToDisplay -= offset;
742
- if (rowsToDisplay > this.pageLimit) {
743
- rowsToDisplay = this.pageLimit;
744
- }
745
- }
746
-
747
- const rowDifference = rowsToDisplay - rowLength;
748
- const newRows = [];
749
-
750
- if (rowDifference < 0) {
751
- // too many rows
752
- for (let i = rowLength - 1; i >= rowsToDisplay; i -= 1) {
753
- const row = tbody.rows.item(i);
754
- tbody.removeChild(row);
755
- }
756
- }
757
- if (rowDifference > 0) {
758
- const fragment = document.createDocumentFragment();
759
- for (let i = 0; i < rowDifference; i += 1) {
760
- const row = document.createElement('tr');
761
- DataTableRow.attach(row);
762
- newRows.push(row);
763
- fragment.appendChild(row);
764
- }
765
- if (this.element.hasAttribute('mdw-row-focusable')) {
766
- RovingTabIndex.setupTabIndexes(newRows);
767
- }
768
- tbody.appendChild(fragment);
769
- }
770
- if (refresh && rowDifference !== 0) {
771
- if (this.useLazyRendering) {
772
- this.scheduleThrottledRender(true);
773
- } else {
774
- newRows.forEach((row) => {
775
- this.refreshRow(row.sectionRowIndex);
776
- });
777
- }
778
- }
779
- }
780
-
781
- /** @return {void} */
782
- refreshRows() {
783
- if (this.useLazyRendering) {
784
- this.performLazyRender(true);
785
- } else {
786
- const tbody = this.getTableBody();
787
- iterateArrayLike(tbody.rows, (row, index) => {
788
- this.refreshRow(index);
789
- });
790
- }
791
- if (this.useLazyRendering) {
792
- this.scheduleThrottledRender();
793
- }
794
- }
795
-
796
- /** @return {void} */
797
- refresh() {
798
- this.refreshFilter();
799
- this.updateRowCount(false);
800
- this.updatePaginator();
801
- this.refreshRows();
802
- }
803
-
804
- /**
805
- * @param {HTMLTableRowElement} row
806
- * @return {T}
807
- */
808
- getDataForTableRow(row) {
809
- const index = (row.sectionRowIndex) + (this.page * this.pageLimit);
810
- return this.getDatasource()[index];
811
- }
812
-
813
- /**
814
- * @param {T} data
815
- * @return {HTMLTableRowElement} row
816
- */
817
- getTableRowForData(data) {
818
- const datasourceIndex = this.getDatasource().indexOf(data);
819
- if (datasourceIndex === -1) {
820
- return null;
821
- }
822
- const minIndex = this.page * this.pageLimit;
823
- return this.getTableBody().rows.item(datasourceIndex - minIndex);
824
- }
825
-
826
- /**
827
- * @param {number} rowIndex
828
- * @return {void}
829
- */
830
- refreshRow(rowIndex) {
831
- const row = this.getTableBody().rows.item(rowIndex);
832
- row.style.removeProperty('height');
833
- this.columns.forEach((column, columnIndex) => {
834
- this.refreshCell(columnIndex, rowIndex);
835
- });
836
- }
837
-
838
- /**
839
- * @param {number} columnIndex
840
- * @param {number} rowIndex
841
- * @return {void}
842
- */
843
- refreshCell(columnIndex, rowIndex) {
844
- const tableColumn = this.columns[columnIndex];
845
- const row = this.getTableBody().rows.item(rowIndex);
846
- let len = row.cells.length;
847
- let createdCells = false;
848
- while (len <= columnIndex) {
849
- createdCells = true;
850
- // Generate cells
851
- const missingColumn = this.columns[len];
852
- let missingCell;
853
- if (missingColumn.rowSelector) {
854
- missingCell = document.createElement('th');
855
- row.appendChild(missingCell);
856
- DataTableRowHeader.attach(missingCell);
857
- } else {
858
- missingCell = row.insertCell();
859
- DataTableCell.attach(missingCell);
860
- }
861
- switch (missingColumn.type) {
862
- case 'checkbox':
863
- missingCell.setAttribute('mdw-checkbox', '');
864
- break;
865
- case 'number':
866
- missingCell.setAttribute('mdw-number', '');
867
- break;
868
- case 'text':
869
- missingCell.setAttribute('mdw-text', '');
870
- break;
871
- default:
872
- }
873
- missingCell.dataset.key = missingColumn.key;
874
- if (missingColumn.rowSelector) {
875
- missingCell.setAttribute('mdw-selector', '');
876
- }
877
- if (missingColumn.primaryColumn) {
878
- missingCell.setAttribute('mdw-primary-column', '');
879
- }
880
- len += 1;
881
- }
882
- if (createdCells) {
883
- if (this.element.hasAttribute('mdw-cell-focusable')) {
884
- RovingTabIndex.setupTabIndexes(row.querySelectorAll(DataTable.CELL_TABINDEX_QUERIES.join(',')));
885
- }
886
- }
887
- const cell = row.cells.item(columnIndex);
888
- const data = this.getDataForTableRow(row);
889
- const value = data[tableColumn.key];
890
- if (tableColumn.rowSelector) {
891
- if (row.getAttribute('aria-selected') !== (value ? 'true' : 'false')) {
892
- row.setAttribute('aria-selected', (value ? 'true' : 'false'));
893
- }
894
- }
895
- const formattedValue = tableColumn.formatter(value, data);
896
- tableColumn.renderer(cell, formattedValue, data);
897
- }
898
-
899
- /**
900
- * @template {keyof T & string} K
901
- * @param {HTMLTableCellElement|DataTableAdapterColumn<T,K>|number|string} search
902
- * @return {DataTableAdapterColumn<T,K>}
903
- */
904
- getColumn(search) {
905
- if (search instanceof DataTableAdapterColumn) {
906
- return search;
907
- }
908
- if (search instanceof HTMLTableCellElement) {
909
- return this.columns.filter((column) => column.element === search)[0];
910
- }
911
- if (typeof search === 'string') {
912
- return this.columns.filter((column) => column.element.dataset.key === search)[0];
913
- }
914
- return this.columns[search];
915
- }
916
-
917
- /** @return {HTMLTableElement} */
918
- getTable() {
919
- let table = this.element.getElementsByTagName('table')[0];
920
- if (!table) {
921
- table = document.createElement('table');
922
- const footer = this.element.getElementsByClassName('mdw-datatable__footer')[0];
923
- if (footer) {
924
- this.element.insertBefore(table, footer);
925
- } else {
926
- this.element.appendChild(table);
927
- }
928
- }
929
- return table;
930
- }
931
-
932
- /** @return {HTMLTableRowElement} */
933
- getHeaderRow() {
934
- let thead = this.element.getElementsByTagName('thead')[0];
935
- if (!thead) {
936
- const table = this.getTable();
937
- thead = document.createElement('thead');
938
- table.appendChild(thead);
939
- }
940
- let headerRow = thead.getElementsByTagName('tr')[0];
941
- if (!headerRow) {
942
- headerRow = document.createElement('tr');
943
- thead.appendChild(headerRow);
944
- }
945
- return headerRow;
946
- }
947
-
948
- /** @return {HTMLTableSectionElement} */
949
- getTableBody() {
950
- if (this.tbody) {
951
- return this.tbody;
952
- }
953
- this.tbody = this.element.getElementsByTagName('tbody')[0];
954
- if (!this.tbody) {
955
- const table = this.getTable();
956
- this.tbody = document.createElement('tbody');
957
- table.appendChild(this.tbody);
958
- }
959
- return this.tbody;
960
- }
961
-
962
- /**
963
- * @param {number} columnIndex
964
- * @return {void}
965
- */
966
- refreshColumn(columnIndex) {
967
- const tbody = this.getTableBody();
968
- iterateArrayLike(tbody.rows, (row, rowIndex) => {
969
- this.refreshCell(columnIndex, rowIndex);
970
- });
971
- }
972
- }