@shortfuse/materialdesignweb 0.3.0 → 0.4.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 (398) hide show
  1. package/.eslintrc.json +136 -30
  2. package/.stylelintrc.json +6 -40
  3. package/.vscode/launch.json +20 -5
  4. package/CHANGELOG.md +24 -0
  5. package/README.md +12 -9
  6. package/adapters/datatable/column.js +82 -74
  7. package/adapters/datatable/index.js +173 -131
  8. package/adapters/dom/index.js +529 -75
  9. package/adapters/list/index.js +25 -12
  10. package/adapters/search/index.js +13 -13
  11. package/components/appbar/_spec.scss +87 -64
  12. package/components/appbar/index.scss +2 -2
  13. package/components/banner/_spec.scss +8 -8
  14. package/components/banner/index.scss +2 -2
  15. package/components/bottomnav/_spec.scss +22 -17
  16. package/components/bottomnav/index.js +61 -52
  17. package/components/bottomnav/index.scss +2 -2
  18. package/components/bottomnav/item.js +44 -25
  19. package/components/button/README.md +14 -14
  20. package/components/button/_spec.scss +23 -22
  21. package/components/button/_theme.scss +37 -21
  22. package/components/button/index.eta +32 -0
  23. package/components/button/index.js +12 -12
  24. package/components/button/index.scss +2 -2
  25. package/components/card/_spec.scss +40 -36
  26. package/components/card/index.scss +2 -2
  27. package/components/chip/_spec.scss +7 -8
  28. package/components/chip/_theme.scss +31 -31
  29. package/components/chip/index.js +3 -2
  30. package/components/chip/index.scss +2 -2
  31. package/components/chip/item.js +1 -16
  32. package/components/datatable/_spec.scss +71 -85
  33. package/components/datatable/_theme.scss +61 -156
  34. package/components/datatable/cell.js +45 -0
  35. package/components/datatable/columnheader.js +47 -0
  36. package/components/datatable/index.js +279 -366
  37. package/components/datatable/index.scss +2 -2
  38. package/components/datatable/row.js +49 -0
  39. package/components/datatable/rowheader.js +18 -0
  40. package/components/dialog/_spec.scss +61 -41
  41. package/components/dialog/index.js +325 -297
  42. package/components/dialog/index.scss +2 -2
  43. package/components/divider/_spec.scss +8 -6
  44. package/components/divider/index.scss +2 -2
  45. package/components/elevation/_spec.scss +2 -2
  46. package/components/elevation/index.scss +2 -2
  47. package/components/fab/_spec.scss +23 -24
  48. package/components/fab/index.js +50 -50
  49. package/components/fab/index.scss +2 -2
  50. package/components/grid/_spec.scss +33 -31
  51. package/components/grid/index.scss +2 -2
  52. package/components/layout/_mixins.scss +5 -5
  53. package/components/layout/_spec.scss +206 -176
  54. package/components/layout/_theme.scss +14 -16
  55. package/components/layout/index.js +181 -153
  56. package/components/layout/index.scss +2 -2
  57. package/components/list/_spec.scss +117 -104
  58. package/components/list/_theme.scss +31 -34
  59. package/components/list/content.js +68 -52
  60. package/components/list/index.js +194 -61
  61. package/components/list/index.scss +2 -2
  62. package/components/list/item.js +136 -12
  63. package/components/list/secondary.js +46 -0
  64. package/components/menu/_spec.scss +32 -19
  65. package/components/menu/index.js +242 -229
  66. package/components/menu/index.scss +2 -2
  67. package/components/menu/item.js +95 -110
  68. package/components/progress/_spec.scss +35 -27
  69. package/components/progress/index.js +21 -0
  70. package/components/progress/index.scss +2 -1
  71. package/components/selection/_spec.scss +242 -224
  72. package/components/selection/_theme.scss +100 -95
  73. package/components/selection/index.eta +60 -0
  74. package/components/selection/index.js +76 -0
  75. package/components/selection/index.pug +15 -8
  76. package/components/selection/index.scss +2 -2
  77. package/components/selection/input.js +56 -0
  78. package/components/selection/radiogroup.js +47 -0
  79. package/components/slider/_spec.scss +10 -8
  80. package/components/slider/index.scss +2 -2
  81. package/components/snackbar/_spec.scss +22 -21
  82. package/components/snackbar/index.js +102 -111
  83. package/components/snackbar/index.scss +2 -2
  84. package/components/tab/_spec.scss +20 -19
  85. package/components/tab/content.js +41 -40
  86. package/components/tab/index.js +192 -99
  87. package/components/tab/index.scss +2 -2
  88. package/components/tab/item.js +38 -55
  89. package/components/tab/list.js +96 -72
  90. package/components/tab/panel.js +12 -13
  91. package/components/template/_theme.scss +11 -11
  92. package/components/textfield/_mixins.scss +52 -0
  93. package/components/textfield/_spec.scss +215 -266
  94. package/components/textfield/_theme.scss +95 -72
  95. package/components/textfield/index.eta +74 -0
  96. package/components/textfield/index.js +63 -57
  97. package/components/textfield/index.scss +2 -2
  98. package/components/tooltip/_spec.scss +27 -25
  99. package/components/tooltip/index.scss +2 -2
  100. package/components/type/_spec.scss +51 -38
  101. package/components/type/index.scss +2 -2
  102. package/core/_breakpoint.scss +75 -91
  103. package/core/_elevation.scss +10 -10
  104. package/core/_length.scss +9 -0
  105. package/core/_motion.scss +14 -14
  106. package/core/_platform.scss +9 -15
  107. package/core/_type.scss +33 -32
  108. package/core/aria/attributes.js +125 -25
  109. package/core/aria/button.js +23 -23
  110. package/core/aria/keyboard.js +93 -0
  111. package/core/aria/rovingtabindex.js +69 -154
  112. package/core/aria/tab.js +31 -28
  113. package/core/color/_theme.scss +240 -280
  114. package/core/color/index.scss +2 -2
  115. package/core/document/index.js +39 -0
  116. package/core/dom.js +12 -12
  117. package/core/overlay/_spec.scss +0 -3
  118. package/core/overlay/_theme.scss +56 -74
  119. package/core/overlay/index.js +49 -18
  120. package/core/overlay/index.scss +2 -2
  121. package/core/ripple/_spec.scss +22 -39
  122. package/core/ripple/_theme.scss +13 -13
  123. package/core/ripple/index.js +137 -134
  124. package/core/ripple/index.scss +2 -2
  125. package/core/theme/_config.scss +2 -0
  126. package/core/theme/_mixins.scss +172 -0
  127. package/core/theme/_palettes.scss +155 -135
  128. package/core/theme/_variables.scss +24 -15
  129. package/core/theme/index.js +50 -0
  130. package/core/throttler.js +1 -1
  131. package/core/transition/index.js +36 -20
  132. package/{docs-src → docs}/_flex.scss +0 -0
  133. package/{docs-src → docs}/_menuoptions.js +21 -34
  134. package/{docs-src → docs}/_mixins.pug +39 -26
  135. package/docs/_partials/_androidnavbar.eta +5 -0
  136. package/docs/_partials/_androidstatusbar.eta +13 -0
  137. package/docs/_partials/_appbar.eta +29 -0
  138. package/docs/_partials/_buttontest.eta +31 -0
  139. package/docs/_partials/_header.eta +149 -0
  140. package/docs/_partials/_navlistitem.eta +16 -0
  141. package/docs/_partials/_target.eta +1 -0
  142. package/{docs-src → docs}/_sample-utils.js +8 -6
  143. package/{docs-src → docs}/_storage.js +0 -0
  144. package/{docs-src → docs}/docs.scss +5 -2
  145. package/docs/index.eta +16 -0
  146. package/{docs-src → docs}/index.js +0 -0
  147. package/docs/pages/appbar.eta +114 -0
  148. package/{docs-src/components → docs/pages}/appbar.js +0 -0
  149. package/{docs-src/components → docs/pages}/appbar.pug +15 -18
  150. package/docs/pages/bottomnav.eta +188 -0
  151. package/{docs-src/components → docs/pages}/bottomnav.js +23 -24
  152. package/{docs-src/components → docs/pages}/bottomnav.pug +4 -4
  153. package/docs/pages/button.eta +124 -0
  154. package/{docs-src/components → docs/pages}/button.js +19 -19
  155. package/{docs-src/components → docs/pages}/button.pug +15 -15
  156. package/docs/pages/card.eta +90 -0
  157. package/{docs-src/components → docs/pages}/card.js +3 -3
  158. package/{docs-src/components → docs/pages}/card.pug +7 -7
  159. package/docs/pages/chip.eta +122 -0
  160. package/{docs-src/components → docs/pages}/chip.js +3 -6
  161. package/{docs-src/components → docs/pages}/chip.pug +2 -2
  162. package/docs/pages/color.eta +143 -0
  163. package/{docs-src/core → docs/pages}/color.js +95 -20
  164. package/docs/pages/color.pug +121 -0
  165. package/docs/pages/datatable.eta +323 -0
  166. package/{docs-src/components → docs/pages}/datatable.js +26 -13
  167. package/docs/pages/datatable.pug +283 -0
  168. package/docs/pages/dialog.eta +186 -0
  169. package/{docs-src/components → docs/pages}/dialog.js +26 -13
  170. package/{docs-src/components → docs/pages}/dialog.pug +46 -28
  171. package/docs/pages/dom.eta +26 -0
  172. package/docs/pages/dom.js +143 -0
  173. package/docs/pages/dom.pug +22 -0
  174. package/docs/pages/elevation.eta +35 -0
  175. package/{docs-src/components → docs/pages}/elevation.js +0 -0
  176. package/{docs-src/components → docs/pages}/elevation.pug +0 -0
  177. package/docs/pages/fab.eta +99 -0
  178. package/{docs-src/components → docs/pages}/fab.js +3 -3
  179. package/{docs-src/components → docs/pages}/fab.pug +2 -2
  180. package/docs/pages/grid.eta +135 -0
  181. package/{docs-src/components → docs/pages}/grid.js +1 -1
  182. package/{docs-src/components → docs/pages}/grid.pug +3 -3
  183. package/docs/pages/layout.eta +8 -0
  184. package/{docs-src/components → docs/pages}/layout.js +0 -0
  185. package/{docs-src/components → docs/pages}/layout.pug +0 -0
  186. package/docs/pages/list.eta +465 -0
  187. package/{docs-src/components → docs/pages}/list.js +2 -2
  188. package/{docs-src/components → docs/pages}/list.pug +7 -14
  189. package/docs/pages/menu.eta +276 -0
  190. package/{docs-src/components → docs/pages}/menu.js +14 -10
  191. package/{docs-src/components → docs/pages}/menu.pug +0 -0
  192. package/docs/pages/overlay.eta +69 -0
  193. package/docs/pages/overlay.js +4 -0
  194. package/{docs-src/core → docs/pages}/overlay.pug +14 -11
  195. package/docs/pages/progress.eta +23 -0
  196. package/{docs-src/components → docs/pages}/progress.js +1 -1
  197. package/{docs-src/components → docs/pages}/progress.pug +1 -1
  198. package/docs/pages/ripple.eta +27 -0
  199. package/docs/pages/ripple.js +4 -0
  200. package/{docs-src/core → docs/pages}/ripple.pug +4 -4
  201. package/docs/pages/search.eta +246 -0
  202. package/{docs-src/components → docs/pages}/search.js +59 -42
  203. package/{docs-src/components → docs/pages}/search.pug +50 -51
  204. package/docs/pages/selection.eta +111 -0
  205. package/docs/pages/selection.js +13 -0
  206. package/docs/pages/selection.pug +74 -0
  207. package/docs/pages/slider.eta +23 -0
  208. package/{docs-src/components → docs/pages}/slider.js +0 -0
  209. package/{docs-src/components → docs/pages}/slider.pug +0 -0
  210. package/docs/pages/snackbar.eta +83 -0
  211. package/{docs-src/components → docs/pages}/snackbar.js +3 -3
  212. package/{docs-src/components → docs/pages}/snackbar.pug +0 -0
  213. package/docs/pages/tab.eta +421 -0
  214. package/{docs-src/components → docs/pages}/tab.js +18 -35
  215. package/{docs-src/components → docs/pages}/tab.pug +4 -4
  216. package/docs/pages/textfield.eta +486 -0
  217. package/{docs-src/components → docs/pages}/textfield.js +3 -4
  218. package/{docs-src/components → docs/pages}/textfield.pug +87 -35
  219. package/docs/pages/tooltip.eta +94 -0
  220. package/{docs-src/components → docs/pages}/tooltip.js +0 -0
  221. package/{docs-src/components → docs/pages}/tooltip.pug +0 -1
  222. package/docs/pages/transition.eta +117 -0
  223. package/{docs-src/core → docs/pages}/transition.js +7 -8
  224. package/{docs-src/core → docs/pages}/transition.pug +0 -0
  225. package/docs/pages/type.eta +31 -0
  226. package/{docs-src/components → docs/pages}/type.js +0 -0
  227. package/{docs-src/components → docs/pages}/type.pug +0 -1
  228. package/docs/postrender.js +39 -0
  229. package/{docs-src → docs}/prerender.js +3 -9
  230. package/docs/pwa/_dialogs.eta +143 -0
  231. package/docs/pwa/_dialogs.pug +96 -0
  232. package/docs/pwa/_menus.eta +16 -0
  233. package/{docs-src → docs}/pwa/_menus.pug +0 -0
  234. package/docs/pwa/pwa-prerender.js +3 -0
  235. package/docs/pwa/pwa.eta +480 -0
  236. package/docs/pwa/pwa.js +306 -0
  237. package/{docs-src → docs}/pwa/pwa.pug +166 -263
  238. package/docs/pwa/pwa.scss +26 -0
  239. package/docs/spec.scss +26 -0
  240. package/docs/themes/_component-themes.scss +26 -0
  241. package/docs/themes/theme-colored-fallbacks.scss +17 -0
  242. package/docs/themes/theme-colored.scss +17 -0
  243. package/docs/themes/theme-default-fallbacks.scss +17 -0
  244. package/docs/themes/theme-default.scss +17 -0
  245. package/jsconfig.json +4 -2
  246. package/package.json +40 -27
  247. package/scripts/deploy-docs.sh +9 -0
  248. package/templates/index.eta +2 -0
  249. package/utils/function.js +3 -0
  250. package/webpack.config.cjs +257 -0
  251. package/_spec.scss +0 -27
  252. package/_theme.scss +0 -27
  253. package/components/list/expander.js +0 -142
  254. package/components/list/itemgroup.js +0 -22
  255. package/core/theme/_builder.scss +0 -116
  256. package/core/theme/index.scss +0 -68
  257. package/docs/appbar.html +0 -1
  258. package/docs/appbar.min.js +0 -2
  259. package/docs/appbar.min.js.map +0 -1
  260. package/docs/bottomnav.html +0 -1
  261. package/docs/bottomnav.min.js +0 -2
  262. package/docs/bottomnav.min.js.map +0 -1
  263. package/docs/button.html +0 -1
  264. package/docs/button.min.js +0 -2
  265. package/docs/button.min.js.map +0 -1
  266. package/docs/card.html +0 -1
  267. package/docs/card.min.js +0 -2
  268. package/docs/card.min.js.map +0 -1
  269. package/docs/chip.html +0 -1
  270. package/docs/chip.min.js +0 -2
  271. package/docs/chip.min.js.map +0 -1
  272. package/docs/color.html +0 -1
  273. package/docs/color.min.js +0 -2
  274. package/docs/color.min.js.map +0 -1
  275. package/docs/datatable.html +0 -1
  276. package/docs/datatable.min.js +0 -2
  277. package/docs/datatable.min.js.map +0 -1
  278. package/docs/default.common.min.js +0 -2
  279. package/docs/default.common.min.js.map +0 -1
  280. package/docs/dialog.html +0 -1
  281. package/docs/dialog.min.js +0 -2
  282. package/docs/dialog.min.js.map +0 -1
  283. package/docs/docs.min.css +0 -1
  284. package/docs/docs.min.js +0 -2
  285. package/docs/docs.min.js.map +0 -1
  286. package/docs/elevation.html +0 -1
  287. package/docs/elevation.min.js +0 -2
  288. package/docs/elevation.min.js.map +0 -1
  289. package/docs/fab.html +0 -1
  290. package/docs/fab.min.js +0 -2
  291. package/docs/fab.min.js.map +0 -1
  292. package/docs/grid.html +0 -1
  293. package/docs/grid.min.js +0 -2
  294. package/docs/grid.min.js.map +0 -1
  295. package/docs/index.html +0 -1
  296. package/docs/index.min.js +0 -2
  297. package/docs/index.min.js.map +0 -1
  298. package/docs/ink.html +0 -1
  299. package/docs/ink.min.js +0 -2
  300. package/docs/ink.min.js.map +0 -1
  301. package/docs/layout.html +0 -1
  302. package/docs/layout.min.js +0 -2
  303. package/docs/layout.min.js.map +0 -1
  304. package/docs/list.html +0 -1
  305. package/docs/list.min.js +0 -2
  306. package/docs/list.min.js.map +0 -1
  307. package/docs/menu.html +0 -1
  308. package/docs/menu.min.js +0 -2
  309. package/docs/menu.min.js.map +0 -1
  310. package/docs/overlay.html +0 -1
  311. package/docs/overlay.min.js +0 -2
  312. package/docs/overlay.min.js.map +0 -1
  313. package/docs/prerender.common.min.js +0 -2
  314. package/docs/prerender.common.min.js.map +0 -1
  315. package/docs/prerender.min.js +0 -2
  316. package/docs/prerender.min.js.map +0 -1
  317. package/docs/progress.html +0 -1
  318. package/docs/progress.min.js +0 -2
  319. package/docs/progress.min.js.map +0 -1
  320. package/docs/pwa-prerender.min.js +0 -2
  321. package/docs/pwa-prerender.min.js.map +0 -1
  322. package/docs/pwa.html +0 -11
  323. package/docs/pwa.min.css +0 -1
  324. package/docs/pwa.min.js +0 -2
  325. package/docs/pwa.min.js.map +0 -1
  326. package/docs/ripple.html +0 -1
  327. package/docs/ripple.min.js +0 -2
  328. package/docs/ripple.min.js.map +0 -1
  329. package/docs/search.html +0 -1
  330. package/docs/search.min.js +0 -2
  331. package/docs/search.min.js.map +0 -1
  332. package/docs/selection.html +0 -1
  333. package/docs/selection.min.js +0 -2
  334. package/docs/selection.min.js.map +0 -1
  335. package/docs/slider.html +0 -1
  336. package/docs/slider.min.js +0 -2
  337. package/docs/slider.min.js.map +0 -1
  338. package/docs/snackbar.html +0 -1
  339. package/docs/snackbar.min.js +0 -2
  340. package/docs/snackbar.min.js.map +0 -1
  341. package/docs/spec.min.css +0 -1
  342. package/docs/spec.min.js +0 -2
  343. package/docs/spec.min.js.map +0 -1
  344. package/docs/surface.html +0 -1
  345. package/docs/surface.min.js +0 -2
  346. package/docs/surface.min.js.map +0 -1
  347. package/docs/tab.html +0 -1
  348. package/docs/tab.min.js +0 -2
  349. package/docs/tab.min.js.map +0 -1
  350. package/docs/textfield.html +0 -2
  351. package/docs/textfield.min.js +0 -2
  352. package/docs/textfield.min.js.map +0 -1
  353. package/docs/theme-colored-fallbacks.min.css +0 -1
  354. package/docs/theme-colored-fallbacks.min.js +0 -2
  355. package/docs/theme-colored-fallbacks.min.js.map +0 -1
  356. package/docs/theme-colored.min.css +0 -1
  357. package/docs/theme-colored.min.js +0 -2
  358. package/docs/theme-colored.min.js.map +0 -1
  359. package/docs/theme-default-fallbacks.min.css +0 -1
  360. package/docs/theme-default-fallbacks.min.js +0 -2
  361. package/docs/theme-default-fallbacks.min.js.map +0 -1
  362. package/docs/theme-default.min.css +0 -1
  363. package/docs/theme-default.min.js +0 -2
  364. package/docs/theme-default.min.js.map +0 -1
  365. package/docs/themes-fallbacks.min.css +0 -1
  366. package/docs/themes-fallbacks.min.js +0 -2
  367. package/docs/themes-fallbacks.min.js.map +0 -1
  368. package/docs/themes.min.css +0 -1
  369. package/docs/themes.min.js +0 -2
  370. package/docs/themes.min.js.map +0 -1
  371. package/docs/tooltip.html +0 -1
  372. package/docs/tooltip.min.js +0 -2
  373. package/docs/tooltip.min.js.map +0 -1
  374. package/docs/transition.html +0 -1
  375. package/docs/transition.min.js +0 -2
  376. package/docs/transition.min.js.map +0 -1
  377. package/docs/type.html +0 -1
  378. package/docs/type.min.js +0 -2
  379. package/docs/type.min.js.map +0 -1
  380. package/docs-src/components/datatable.pug +0 -327
  381. package/docs-src/components/selection.js +0 -9
  382. package/docs-src/components/selection.pug +0 -77
  383. package/docs-src/core/color.pug +0 -201
  384. package/docs-src/core/overlay.js +0 -4
  385. package/docs-src/core/ripple.js +0 -4
  386. package/docs-src/index.pug +0 -9
  387. package/docs-src/pwa/_dialogs.pug +0 -15
  388. package/docs-src/pwa/pwa-prerender.js +0 -3
  389. package/docs-src/pwa/pwa.js +0 -182
  390. package/docs-src/pwa/pwa.scss +0 -25
  391. package/docs-src/spec.scss +0 -1
  392. package/docs-src/themes/theme-colored-fallbacks.scss +0 -14
  393. package/docs-src/themes/theme-colored.scss +0 -14
  394. package/docs-src/themes/theme-default-fallbacks.scss +0 -14
  395. package/docs-src/themes/theme-default.scss +0 -14
  396. package/index.js +0 -51
  397. package/index.scss +0 -2
  398. package/webpack.config.js +0 -187
@@ -1,97 +1,115 @@
1
- import { iterateArrayLike, iterateSomeOfArrayLike } from '../../core/dom';
2
-
3
- import * as Button from '../../components/button/index';
4
- import * as DataTable from '../../components/datatable/index';
5
- import DataTableAdapterColumn from './column';
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';
6
13
 
7
14
  /**
8
- * @typedef {import('./column').DataTableAdapterColumnOptions<T>} DataTableAdapterColumnOptions<T>
9
- * @template T
15
+ * @template {Record<string, any>} T
16
+ * @template {keyof T & string} K
17
+ * @typedef {import('./column').DataTableAdapterColumnOptions<T,K>} DataTableAdapterColumnOptions<T,K>
10
18
  */
11
19
 
12
20
  /**
13
21
  * Callback fired when value change is requested
14
22
  * Return truthy value to cancel updating object
23
+ * @template {Record<string, any>} T
24
+ * @template {keyof T & string} K
15
25
  * @callback DataTableAdapterOnValueChangeRequestedCallback<T>
16
26
  * @param {T} object
17
- * @param {string} key
18
- * @param {any} value
27
+ * @param {K} key
28
+ * @param {T[K]} value
19
29
  * @return {boolean} cancel
20
- * @template T
21
30
  */
22
31
 
23
32
  /**
24
33
  * Callback fired when value is changed
34
+ * @template {Record<string, any>} T
35
+ * @template {keyof T & string} K
25
36
  * @callback DataTableAdapterOnValueChangedCallback<T>
26
37
  * @param {T} object
27
- * @param {string} key
28
- * @param {any} value
38
+ * @param {K} key
39
+ * @param {T[K]} value
29
40
  * @return {void}
30
- * @template T
31
41
  */
32
42
 
33
43
  /**
44
+ * @template {Record<string, any>} T
34
45
  * @callback DataTableAdapterFilter<T>
35
46
  * @param {T} element
36
47
  * @param {number} [index]
37
48
  * @param {T[]} array
38
49
  * @return {any}
39
- * @template T
40
50
  */
41
51
 
42
52
  /**
53
+ * @template {Record<string, any>} T
43
54
  * @callback DataTableAdapterSorter<T>
44
55
  * @param {T} a
45
56
  * @param {T} b
46
57
  * @return {number}
47
- * @template T
48
58
  */
49
59
 
50
60
  /**
61
+ * Constructor options for DataTableAdapter
51
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]
52
70
  */
71
+
72
+ /** @template {Record<string, any>} T */
53
73
  export default class DataTableAdapter {
54
- /**
55
- * @param {Object} options
56
- * @param {HTMLElement} options.datatable
57
- * @param {T[]} options.datasource Object array
58
- * @param {DataTableAdapterFilter<T>} [options.filter]
59
- * @param {DataTableAdapterOnValueChangeRequestedCallback<T>} [options.onValueChangeRequested]
60
- * @param {DataTableAdapterOnValueChangedCallback<T>} [options.onValueChanged]
61
- * @param {DataTableAdapterSorter<T>} [options.sorter]
62
- */
74
+ /** @param {DataTableAdapterOptions<T>} options */
63
75
  constructor(options) {
64
76
  this.element = options.datatable;
65
77
  this.datasource = options.datasource;
66
78
  this.filter = options.filter;
67
79
  this.sorter = options.sorter;
68
80
  this.onValueChangeRequested = options.onValueChangeRequested || (() => false);
69
- this.onValueChanged = options.onValueChanged || (() => {});
70
-
71
- this.onElementClickListener = (event) => {
72
- this.handleClickInteraction(event);
73
- };
74
- // Use one click event listener to reduce overhead and allow dynamic content
75
- this.element.addEventListener('click', this.onElementClickListener);
81
+ this.onValueChanged = options.onValueChanged || noop;
82
+ DataTable.attach(this.element);
76
83
 
77
- this.onElementScrollListener = () => {
78
- this.onElementScroll();
79
- };
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
+ );
80
109
 
81
- /** @type {HTMLTableRowElement} */
82
- this.tabindexRow = null;
83
- /** @type {Object} */
84
- this.tabindexRowData = null;
85
- this.element.addEventListener('mdw:tabindexchanged', (event) => {
86
- if (this.element.hasAttribute('mdw-row-focusable')) {
87
- this.tabindexRow = /** @type {HTMLTableRowElement} */ (event.target);
88
- this.tabindexRowData = this.getDataForTableRow(this.tabindexRow);
89
- }
90
- });
91
- DataTable.attach(this.element);
92
110
  this.scroller = DataTable.getScroller(this.element);
93
111
  this.element.setAttribute('mdw-datatable-adapter', '');
94
- /** @type {DataTableAdapterColumn<T>[]} */
112
+ /** @type {DataTableAdapterColumn<T,any>[]} */
95
113
  this.columns = [];
96
114
  this.page = 0;
97
115
  this.pageLimit = 0;
@@ -100,6 +118,20 @@ export default class DataTableAdapter {
100
118
  this.useLazyRendering = false;
101
119
  }
102
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
+
103
135
  detach() {
104
136
  this.element.removeAttribute('mdw-datatable-adapter');
105
137
  this.element = null;
@@ -131,6 +163,20 @@ export default class DataTableAdapter {
131
163
  }
132
164
  }
133
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
+
134
180
  onElementScroll() {
135
181
  if (this.debounceTimeout) {
136
182
  clearTimeout(this.debounceTimeout);
@@ -152,7 +198,7 @@ export default class DataTableAdapter {
152
198
  }
153
199
 
154
200
  buildScrollListener() {
155
- this.scroller.addEventListener('scroll', this.onElementScrollListener);
201
+ this.scroller.addEventListener('scroll', this.onElementScrollListener, getPassiveEventListenerOption());
156
202
  }
157
203
 
158
204
  destroyScrollListener() {
@@ -160,54 +206,32 @@ export default class DataTableAdapter {
160
206
  }
161
207
 
162
208
  /**
163
- * @param {PointerEvent|MouseEvent} event
209
+ * @param {CustomEvent} event
164
210
  * @return {void}
165
211
  */
166
- handleClickInteraction(event) {
167
- const { target } = event;
168
- if (target instanceof HTMLInputElement) {
169
- if (target.hasAttribute('type') && target.getAttribute('type') === 'checkbox') {
170
- event.stopPropagation();
171
- const currentCell = this.getTableCell(target);
172
- if (currentCell.tagName.toLowerCase() === 'th') {
173
- this.setCheckOnAllRows(target.checked, currentCell.cellIndex);
174
- this.setHasSelection(target.checked);
175
- return;
176
- }
177
- const currentRow = this.getTableRow(target);
178
- const object = this.getDataForTableRow(currentRow);
179
- if (this.onValueChangeRequested(object, currentCell.dataset.key, target.checked)) {
180
- event.preventDefault();
181
- return;
182
- }
183
- object[currentCell.dataset.key] = target.checked;
184
- this.onValueChanged(object, currentCell.dataset.key, target.checked);
185
- if (currentCell.hasAttribute('mdw-selector')) {
186
- if (target.checked) {
187
- currentRow.setAttribute('aria-selected', 'true');
188
- this.setHasSelection(true);
189
- } else {
190
- currentRow.removeAttribute('aria-selected');
191
- const selectedRows = this.getSelectedRows();
192
- this.setHasSelection(selectedRows.length !== 0);
193
- }
194
- }
195
- }
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);
196
220
  return;
197
221
  }
198
- const currentCell = this.getTableCell(/** @type {HTMLElement} */ (target));
199
- if (currentCell) {
200
- if (currentCell.tagName.toLowerCase() === 'th' && currentCell.hasAttribute('mdw-sortable')) {
201
- event.stopPropagation();
202
- let ascending = true;
203
- if (currentCell.hasAttribute('mdw-sorted') && !currentCell.getAttribute('mdw-sorted')) {
204
- ascending = false;
205
- }
206
- this.updateSortIcons(currentCell, ascending);
207
- if (this.updateSortColumn) {
208
- this.updateSortColumn(currentCell, ascending);
209
- }
210
- }
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);
211
235
  }
212
236
  }
213
237
 
@@ -230,9 +254,12 @@ export default class DataTableAdapter {
230
254
  const index = tableHeaderCell.cellIndex;
231
255
  const tableColumn = this.columns[index];
232
256
  const direction = ascending ? 1 : -1;
233
- this.sorter = ((a, b) => {
257
+ this.sorter = ((/** @type {T} */ a, /** @type {T} */ b) => {
234
258
  const valueA = a[tableColumn.key];
235
259
  const valueB = b[tableColumn.key];
260
+ if (tableColumn.sorter) {
261
+ return tableColumn.sorter(a, b) * direction;
262
+ }
236
263
  if (valueA == null) {
237
264
  if (valueB == null) {
238
265
  return 0;
@@ -248,7 +275,7 @@ export default class DataTableAdapter {
248
275
  if (tableColumn.type === 'checkbox') {
249
276
  return ((valueA ? 1 : 0) - (valueB ? 1 : 0)) * direction;
250
277
  }
251
- if (valueA.localeCompare) {
278
+ if ('localeCompare' in valueA) {
252
279
  return valueA.localeCompare(valueB) * direction;
253
280
  }
254
281
  // eslint-disable-next-line eqeqeq
@@ -268,14 +295,14 @@ export default class DataTableAdapter {
268
295
  updateSortIcons(sortedTableHeaderCell, ascending) {
269
296
  if (sortedTableHeaderCell) {
270
297
  if (ascending) {
271
- sortedTableHeaderCell.setAttribute('mdw-sorted', '');
298
+ sortedTableHeaderCell.setAttribute('aria-sort', 'ascending');
272
299
  } else {
273
- sortedTableHeaderCell.setAttribute('mdw-sorted', 'desc');
300
+ sortedTableHeaderCell.setAttribute('aria-sort', 'descending');
274
301
  }
275
302
  }
276
- iterateArrayLike(this.element.getElementsByTagName('th'), (otherTableHeader) => {
277
- if (otherTableHeader !== sortedTableHeaderCell) {
278
- otherTableHeader.removeAttribute('mdw-sorted');
303
+ iterateArrayLike(this.getHeaderRow().getElementsByTagName('th'), (otherTableHeader) => {
304
+ if (otherTableHeader !== sortedTableHeaderCell && otherTableHeader.hasAttribute('aria-sort')) {
305
+ otherTableHeader.setAttribute('aria-sort', 'none');
279
306
  }
280
307
  });
281
308
  }
@@ -329,11 +356,11 @@ export default class DataTableAdapter {
329
356
 
330
357
  /** @return {T[]} */
331
358
  getSelectedRows() {
332
- const selectorColumn = this.columns.filter(column => column.rowSelector)[0];
359
+ const selectorColumn = this.columns.filter((column) => column.rowSelector)[0];
333
360
  if (!selectorColumn) {
334
361
  return [];
335
362
  }
336
- return this.getDatasource().filter(row => row[selectorColumn.key]);
363
+ return this.getDatasource().filter((row) => row[selectorColumn.key]);
337
364
  }
338
365
 
339
366
  /**
@@ -371,8 +398,9 @@ export default class DataTableAdapter {
371
398
  }
372
399
 
373
400
  /**
374
- * @param {DataTableAdapterColumnOptions<T>} options
375
- * @return {DataTableAdapterColumn<T>}
401
+ * @template {keyof T & string} K
402
+ * @param {DataTableAdapterColumnOptions<T,K>} options
403
+ * @return {DataTableAdapterColumn<T,K>}
376
404
  */
377
405
  addColumn(options) {
378
406
  const tableColumn = new DataTableAdapterColumn(options);
@@ -410,12 +438,12 @@ export default class DataTableAdapter {
410
438
  this.pageLimit = 0;
411
439
  this.page = 0;
412
440
  if (footer) {
413
- footer.style.display = 'none';
441
+ footer.style.setProperty('display', 'none');
414
442
  }
415
443
  this.needsDraw = true;
416
444
  return;
417
445
  }
418
- footer.style.display = '';
446
+ footer.style.removeProperty('display');
419
447
  let optionsElement = footer.getElementsByClassName('mdw-datatable__footer-options')[0];
420
448
  if (!optionsElement) {
421
449
  optionsElement = document.createElement('div');
@@ -432,9 +460,11 @@ export default class DataTableAdapter {
432
460
  const option = document.createElement('option');
433
461
  option.value = limit.toString();
434
462
  option.textContent = limit.toString();
463
+ option.className = 'mdw-theme';
464
+ option.setAttribute('mdw-surface', 'card');
435
465
  select.appendChild(option);
436
466
  });
437
- select.setAttribute('value', (options.limit && options.limit.toString()) || '10');
467
+ select.value = (options.limit && options.limit.toString()) || '10';
438
468
  const dropdownIcon = document.createElement('div');
439
469
  dropdownIcon.classList.add('mdw-textfield__icon');
440
470
  dropdownIcon.setAttribute('mdw-dropdown', '');
@@ -537,7 +567,7 @@ export default class DataTableAdapter {
537
567
  isRowVisible(
538
568
  el,
539
569
  viewportTop = this.scroller.scrollTop,
540
- viewportBottom = this.scroller.scrollTop + this.scroller.offsetHeight
570
+ viewportBottom = this.scroller.scrollTop + this.scroller.offsetHeight,
541
571
  ) {
542
572
  const rowTop = el.offsetTop;
543
573
  const rowBottom = rowTop + el.offsetHeight;
@@ -587,6 +617,7 @@ export default class DataTableAdapter {
587
617
  getLazyRenderRows() {
588
618
  const tbody = this.getTableBody();
589
619
  const len = tbody.rows.length;
620
+ /** @type {HTMLTableRowElement[]} */
590
621
  const rows = [];
591
622
  const minRowCount = window.screen.height / 48;
592
623
  if (len <= minRowCount) {
@@ -727,12 +758,13 @@ export default class DataTableAdapter {
727
758
  const fragment = document.createDocumentFragment();
728
759
  for (let i = 0; i < rowDifference; i += 1) {
729
760
  const row = document.createElement('tr');
730
- if (this.element.hasAttribute('mdw-row-focusable')) {
731
- row.setAttribute('tabindex', '-1');
732
- }
761
+ DataTableRow.attach(row);
733
762
  newRows.push(row);
734
763
  fragment.appendChild(row);
735
764
  }
765
+ if (this.element.hasAttribute('mdw-row-focusable')) {
766
+ RovingTabIndex.setupTabIndexes(newRows);
767
+ }
736
768
  tbody.appendChild(fragment);
737
769
  }
738
770
  if (refresh && rowDifference !== 0) {
@@ -756,21 +788,6 @@ export default class DataTableAdapter {
756
788
  this.refreshRow(index);
757
789
  });
758
790
  }
759
- if (this.tabindexRowData) {
760
- const row = this.getTableRowForData(this.tabindexRowData);
761
- if (row !== this.tabindexRow) {
762
- if (this.tabindexRow) {
763
- this.tabindexRow.setAttribute('tabindex', '-1');
764
- }
765
- if (row) {
766
- if (document.activeElement === this.tabindexRow) {
767
- row.focus();
768
- }
769
- DataTable.updateTabIndex(row, false);
770
- }
771
- this.tabindexRow = row;
772
- }
773
- }
774
791
  if (this.useLazyRendering) {
775
792
  this.scheduleThrottledRender();
776
793
  }
@@ -827,12 +844,31 @@ export default class DataTableAdapter {
827
844
  const tableColumn = this.columns[columnIndex];
828
845
  const row = this.getTableBody().rows.item(rowIndex);
829
846
  let len = row.cells.length;
847
+ let createdCells = false;
830
848
  while (len <= columnIndex) {
849
+ createdCells = true;
831
850
  // Generate cells
832
851
  const missingColumn = this.columns[len];
833
- const missingCell = row.insertCell();
834
- if (missingColumn.type) {
835
- missingCell.dataset.type = missingColumn.type;
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:
836
872
  }
837
873
  missingCell.dataset.key = missingColumn.key;
838
874
  if (missingColumn.rowSelector) {
@@ -843,6 +879,11 @@ export default class DataTableAdapter {
843
879
  }
844
880
  len += 1;
845
881
  }
882
+ if (createdCells) {
883
+ if (this.element.hasAttribute('mdw-cell-focusable')) {
884
+ RovingTabIndex.setupTabIndexes(row.querySelectorAll(DataTable.CELL_TABINDEX_QUERIES.join(',')));
885
+ }
886
+ }
846
887
  const cell = row.cells.item(columnIndex);
847
888
  const data = this.getDataForTableRow(row);
848
889
  const value = data[tableColumn.key];
@@ -856,18 +897,19 @@ export default class DataTableAdapter {
856
897
  }
857
898
 
858
899
  /**
859
- * @param {HTMLTableCellElement|DataTableAdapterColumn|number|string} search
860
- * @return {DataTableAdapterColumn<T>}
900
+ * @template {keyof T & string} K
901
+ * @param {HTMLTableCellElement|DataTableAdapterColumn<T,K>|number|string} search
902
+ * @return {DataTableAdapterColumn<T,K>}
861
903
  */
862
904
  getColumn(search) {
863
905
  if (search instanceof DataTableAdapterColumn) {
864
906
  return search;
865
907
  }
866
908
  if (search instanceof HTMLTableCellElement) {
867
- return this.columns.filter(column => column.element === search)[0];
909
+ return this.columns.filter((column) => column.element === search)[0];
868
910
  }
869
911
  if (typeof search === 'string') {
870
- return this.columns.filter(column => column.element.dataset.key === search)[0];
912
+ return this.columns.filter((column) => column.element.dataset.key === search)[0];
871
913
  }
872
914
  return this.columns[search];
873
915
  }