@shortfuse/materialdesignweb 0.5.0 → 0.7.0

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