@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,23 +1,23 @@
1
1
  // https://www.w3.org/TR/wai-aria-practices/#menu
2
2
 
3
3
  import {
4
+ cancelTick,
4
5
  dispatchDomEvent,
5
6
  isRtl,
6
7
  iterateArrayLike,
7
8
  iterateSomeOfArrayLike,
8
9
  nextTick,
9
- cancelTick,
10
- } from '../../core/dom';
10
+ } from '../../core/dom.js';
11
11
 
12
- import * as MenuItem from './item';
12
+ import * as MenuItem from './item.js';
13
13
 
14
14
  class MenuStack {
15
15
  /**
16
16
  * @param {Element} element
17
17
  * @param {Element} previousFocus
18
- * @param {Object=} state
19
- * @param {Object=} previousState
20
- * @param {MouseEvent=} originalEvent
18
+ * @param {Object} [state]
19
+ * @param {Object} [previousState]
20
+ * @param {MouseEvent|PointerEvent} [originalEvent]
21
21
  */
22
22
  constructor(element, previousFocus, state, previousState, originalEvent) {
23
23
  this.element = element;
@@ -36,16 +36,42 @@ export const HIDE_EVENT = 'mdw:menu-hide';
36
36
 
37
37
  /**
38
38
  * @param {Element} menuElement
39
- * @return {void}
39
+ * @return {boolean} handled
40
40
  */
41
- export function attach(menuElement) {
42
- menuElement.setAttribute('mdw-menu-js', '');
43
- menuElement.addEventListener('click', onMenuClick);
44
- menuElement.addEventListener('scroll', onMenuScroll);
45
- menuElement.addEventListener('touchmove', onMenuScroll);
46
- menuElement.addEventListener('wheel', onMenuScroll);
47
- menuElement.addEventListener('keydown', onKeyDown);
48
- setupARIA(menuElement);
41
+ export function hide(menuElement) {
42
+ if (menuElement.getAttribute('aria-hidden') === 'true') {
43
+ return false;
44
+ }
45
+ menuElement.setAttribute('aria-hidden', 'true');
46
+ let stackIndex = -1;
47
+ OPEN_MENUS.some((stack, index) => {
48
+ if (stack.element === menuElement) {
49
+ stackIndex = index;
50
+ return true;
51
+ }
52
+ return false;
53
+ });
54
+ if (stackIndex !== -1) {
55
+ const menuStack = OPEN_MENUS[stackIndex];
56
+ if (menuStack.previousFocus && menuStack.previousFocus instanceof HTMLElement) {
57
+ menuStack.previousFocus.focus();
58
+ }
59
+ OPEN_MENUS.splice(stackIndex, 1);
60
+ if (menuStack.state && window.history && window.history.state) {
61
+ // IE11 returns a cloned state object, not the original
62
+ if (menuStack.state.hash === window.history.state.hash) {
63
+ window.history.back();
64
+ }
65
+ }
66
+ }
67
+ if (!OPEN_MENUS.length) {
68
+ // eslint-disable-next-line no-use-before-define
69
+ window.removeEventListener('popstate', onPopState);
70
+ // eslint-disable-next-line no-use-before-define
71
+ window.removeEventListener('resize', onWindowResize);
72
+ }
73
+ dispatchDomEvent(menuElement, HIDE_EVENT);
74
+ return true;
49
75
  }
50
76
 
51
77
  /**
@@ -60,7 +86,7 @@ export function setupARIA(menuElement) {
60
86
  menuElement.setAttribute('aria-hidden', 'true');
61
87
  }
62
88
  iterateArrayLike(menuElement.getElementsByClassName('mdw-divider'),
63
- el => el.setAttribute('role', 'separator'));
89
+ (el) => el.setAttribute('role', 'separator'));
64
90
  menuElement.setAttribute('role', 'menu');
65
91
  const popupElement = menuElement.getElementsByClassName('mdw-menu__popup')[0];
66
92
  if (popupElement) {
@@ -74,199 +100,39 @@ export function setupARIA(menuElement) {
74
100
  */
75
101
  export function onMenuScroll(event) {
76
102
  // JS needed for Safari
77
- event.preventDefault();
78
- event.stopPropagation();
103
+ if (event.target === event.currentTarget) {
104
+ event.preventDefault();
105
+ event.stopPropagation();
106
+ }
79
107
  if (event.type !== 'scroll') {
80
108
  return;
81
109
  }
82
110
  /** @type {HTMLElement} */
83
111
  const element = (event.currentTarget);
84
- if (element.scrollTop !== element.scrollHeight / 4) {
85
- element.scrollTop = element.scrollHeight / 4;
112
+ if (element.scrollTop !== 0) {
113
+ element.scrollTop = 0;
86
114
  }
87
- if (element.scrollLeft !== element.scrollWidth / 4) {
88
- element.scrollLeft = element.scrollWidth / 4;
89
- }
90
- }
91
-
92
- export function onMenuClick(event) {
93
- if (event.currentTarget === event.target) {
94
- event.stopPropagation();
95
- hide(event.currentTarget);
115
+ if (element.scrollLeft !== 0) {
116
+ element.scrollLeft = 0;
96
117
  }
97
118
  }
98
119
 
99
120
  /**
121
+ * @param {MouseEvent|PointerEvent} event
100
122
  * @return {void}
101
123
  */
102
- export function onWindowResize() {
103
- const lastOpenMenu = OPEN_MENUS[OPEN_MENUS.length - 1];
104
- if (!lastOpenMenu || !lastOpenMenu.originalEvent) {
105
- return;
106
- }
107
- if (lastOpenMenu.pendingResizeOperation) {
108
- cancelTick(lastOpenMenu.pendingResizeOperation);
109
- }
110
- lastOpenMenu.pendingResizeOperation = nextTick(() => {
111
- updateMenuPosition(
112
- lastOpenMenu.element,
113
- lastOpenMenu.element.getElementsByClassName('mdw-menu__popup')[0],
114
- lastOpenMenu.originalEvent
115
- );
116
- lastOpenMenu.pendingResizeOperation = null;
117
- });
118
- }
119
-
120
- /**
121
- * @param {PopStateEvent} event
122
- * @return {void}
123
- */
124
- export function onPopState(event) {
125
- if (!event.state) {
126
- return;
127
- }
128
- const lastOpenMenu = OPEN_MENUS[OPEN_MENUS.length - 1];
129
- if (!lastOpenMenu || !lastOpenMenu.previousState) {
130
- return;
131
- }
132
- if ((lastOpenMenu.previousState === event.state) || Object.keys(event.state)
133
- .every(key => event.state[key] === lastOpenMenu.previousState[key])) {
134
- hide(lastOpenMenu.element);
135
- }
136
- }
137
-
138
- /**
139
- * @param {KeyboardEvent} event
140
- * @return {void}
141
- */
142
- export function onKeyDown(event) {
143
- /** @type {HTMLElement} */
144
- const menuElement = (event.currentTarget);
145
- if (!menuElement || menuElement.getAttribute('aria-hidden') === 'true') {
146
- return;
147
- }
148
-
149
- if (event.key === 'ArrowDown' || (event.key === 'Down')) {
150
- event.stopPropagation();
151
- event.preventDefault();
152
- selectNextMenuItem(menuElement, false);
153
- return;
154
- }
155
- if (event.key === 'ArrowUp' || (event.key === 'Up')) {
156
- event.stopPropagation();
157
- event.preventDefault();
158
- selectNextMenuItem(menuElement, true);
159
- return;
160
- }
161
- if (event.key === 'Tab') {
162
- // Hide menu allowing focus to revert to calling element
163
- // To then allow browser default Tab interaction
164
- // Unless menu hiding is cancelled
165
- if (!hide(menuElement)) {
166
- event.stopPropagation();
167
- event.preventDefault();
168
- }
169
- return;
170
- }
171
- if (event.key === 'Escape' || event.key === 'Esc') {
124
+ export function onMenuClick(event) {
125
+ if (event.currentTarget === event.target && event.target instanceof HTMLElement) {
172
126
  event.stopPropagation();
173
- event.preventDefault();
174
- hide(menuElement);
175
- }
176
- }
177
-
178
- /**
179
- * @param {Element} menuElement
180
- * @return {void}
181
- */
182
- export function detach(menuElement) {
183
- hide(menuElement);
184
- menuElement.removeEventListener('click', onMenuClick);
185
- menuElement.removeEventListener('scroll', onMenuScroll);
186
- menuElement.removeEventListener('touchmove', onMenuScroll);
187
- menuElement.removeEventListener('wheel', onMenuScroll);
188
- menuElement.addEventListener('keydown', onKeyDown);
189
- menuElement.removeAttribute('mdw-menu-js');
190
- const popupElement = menuElement.getElementsByClassName('mdw-menu__popup')[0];
191
- if (popupElement) {
192
- popupElement.style.removeProperty('top');
193
- popupElement.style.removeProperty('left');
194
- popupElement.style.removeProperty('right');
195
- popupElement.style.removeProperty('bottom');
196
- popupElement.style.removeProperty('margin');
197
- popupElement.style.removeProperty('transform-origin');
198
- popupElement.style.removeProperty('position');
199
- if (popupElement.hasAttribute('style') && !popupElement.getAttribute('style')) {
200
- popupElement.removeAttribute('style');
201
- }
202
- }
203
- iterateArrayLike(menuElement.getElementsByClassName('mdw-menu__item'), MenuItem.detach);
204
- }
205
-
206
- /**
207
- * @param {Element} menu
208
- * @param {boolean} [backwards=false]
209
- * @return {void}
210
- */
211
- export function selectNextMenuItem(menu, backwards) {
212
- const menuItems = menu.getElementsByClassName('mdw-menu__item');
213
- let foundTarget = false;
214
- let candidate = null;
215
- let firstFocusableItem = null;
216
- let lastFocusableElement = null;
217
- const target = document.activeElement;
218
-
219
- // Hidden elements cannot be focused
220
- // Disabled elements cannot be focused on IE11
221
- // Skip elements that fail to receive focus
222
- iterateSomeOfArrayLike(menuItems, (el) => {
223
- el.focus();
224
- const focusable = (document.activeElement === el);
225
- if (focusable) {
226
- if (!firstFocusableItem) {
227
- firstFocusableItem = el;
228
- }
229
- lastFocusableElement = el;
230
- }
231
- if (el === target) {
232
- foundTarget = true;
233
- if (backwards && candidate) {
234
- return true;
235
- }
236
- return false;
237
- }
238
- if (backwards) {
239
- if (focusable) {
240
- candidate = el;
241
- }
242
- return false;
243
- }
244
- if (foundTarget) {
245
- if (focusable) {
246
- candidate = el;
247
- return true;
248
- }
249
- return false;
250
- }
251
- return false;
252
- });
253
- if (!candidate) {
254
- if (backwards) {
255
- candidate = lastFocusableElement;
256
- } else {
257
- candidate = firstFocusableItem;
258
- }
259
- }
260
- if (candidate && document.activeElement !== candidate) {
261
- candidate.focus();
127
+ hide(event.target);
262
128
  }
263
129
  }
264
130
 
265
131
  /**
266
132
  * @param {Element} menuElement
267
- * @param {Element} popupElement
268
- * @param {MouseEvent=} event
269
- * @param {boolean=} [alignTarget=true]
133
+ * @param {HTMLElement} popupElement
134
+ * @param {MouseEvent|PointerEvent} [event]
135
+ * @param {boolean} [alignTarget=true]
270
136
  * @return {void}
271
137
  */
272
138
  export function updateMenuPosition(menuElement, popupElement, event, alignTarget) {
@@ -446,7 +312,7 @@ export function updateMenuPosition(menuElement, popupElement, event, alignTarget
446
312
  return index + 1;
447
313
  }
448
314
  return 0;
449
- }).filter(value => value !== 0);
315
+ }).filter((value) => value !== 0);
450
316
  if (candidates.length) {
451
317
  let candidateNumber;
452
318
  if (isPageRTL === null) {
@@ -454,10 +320,10 @@ export function updateMenuPosition(menuElement, popupElement, event, alignTarget
454
320
  }
455
321
  if (isPageRTL) {
456
322
  candidateNumber = [2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 15]
457
- .filter(number => candidates.indexOf(number) !== -1)[0];
323
+ .filter((number) => candidates.indexOf(number) !== -1)[0];
458
324
  } else {
459
325
  candidateNumber = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
460
- .filter(number => candidates.indexOf(number) !== -1)[0];
326
+ .filter((number) => candidates.indexOf(number) !== -1)[0];
461
327
  }
462
328
  if (candidateNumber == null) {
463
329
  candidateNumber = isPageRTL ? 2 : 1;
@@ -595,6 +461,147 @@ export function updateMenuPosition(menuElement, popupElement, event, alignTarget
595
461
  popupElement.style.setProperty('transform-origin', transformOrigin);
596
462
  }
597
463
 
464
+ /**
465
+ * @return {void}
466
+ */
467
+ export function onWindowResize() {
468
+ const lastOpenMenu = OPEN_MENUS[OPEN_MENUS.length - 1];
469
+ if (!lastOpenMenu || !lastOpenMenu.originalEvent) {
470
+ return;
471
+ }
472
+ if (lastOpenMenu.pendingResizeOperation) {
473
+ cancelTick(lastOpenMenu.pendingResizeOperation);
474
+ }
475
+ lastOpenMenu.pendingResizeOperation = nextTick(() => {
476
+ updateMenuPosition(
477
+ lastOpenMenu.element,
478
+ /** @type {HTMLElement} */ (lastOpenMenu.element.getElementsByClassName('mdw-menu__popup')[0]),
479
+ lastOpenMenu.originalEvent,
480
+ );
481
+ lastOpenMenu.pendingResizeOperation = null;
482
+ });
483
+ }
484
+
485
+ /**
486
+ * @param {PopStateEvent} event
487
+ * @return {void}
488
+ */
489
+ export function onPopState(event) {
490
+ if (!event.state) {
491
+ return;
492
+ }
493
+ const lastOpenMenu = OPEN_MENUS[OPEN_MENUS.length - 1];
494
+ if (!lastOpenMenu || !lastOpenMenu.previousState) {
495
+ return;
496
+ }
497
+ if ((lastOpenMenu.previousState === event.state) || Object.keys(event.state)
498
+ .every((key) => event.state[key] === lastOpenMenu.previousState[key])) {
499
+ hide(lastOpenMenu.element);
500
+ }
501
+ }
502
+
503
+ /**
504
+ * @param {Element} menu
505
+ * @param {boolean} [backwards=false]
506
+ * @return {void}
507
+ */
508
+ export function selectNextMenuItem(menu, backwards) {
509
+ /** @type {HTMLCollectionOf<HTMLElement>} */
510
+ const menuItems = (menu.getElementsByClassName('mdw-menu__item'));
511
+ let foundTarget = false;
512
+ /** @type {HTMLElement} */
513
+ let candidate = null;
514
+ /** @type {HTMLElement} */
515
+ let firstFocusableItem = null;
516
+ let lastFocusableElement = null;
517
+ const target = document.activeElement;
518
+
519
+ // Hidden elements cannot be focused
520
+ // Disabled elements cannot be focused on IE11
521
+ // Skip elements that fail to receive focus
522
+ iterateSomeOfArrayLike(menuItems, (el) => {
523
+ el.focus();
524
+ const focusable = (document.activeElement === el);
525
+ if (focusable) {
526
+ if (!firstFocusableItem) {
527
+ firstFocusableItem = el;
528
+ }
529
+ lastFocusableElement = el;
530
+ }
531
+ if (el === target) {
532
+ foundTarget = true;
533
+ if (backwards && candidate) {
534
+ return true;
535
+ }
536
+ return false;
537
+ }
538
+ if (backwards) {
539
+ if (focusable) {
540
+ candidate = el;
541
+ }
542
+ return false;
543
+ }
544
+ if (foundTarget) {
545
+ if (focusable) {
546
+ candidate = el;
547
+ return true;
548
+ }
549
+ return false;
550
+ }
551
+ return false;
552
+ });
553
+ if (!candidate) {
554
+ if (backwards) {
555
+ candidate = lastFocusableElement;
556
+ } else {
557
+ candidate = firstFocusableItem;
558
+ }
559
+ }
560
+ if (candidate && document.activeElement !== candidate) {
561
+ candidate.focus();
562
+ }
563
+ }
564
+
565
+ /**
566
+ * @param {KeyboardEvent} event
567
+ * @return {void}
568
+ */
569
+ export function onKeyDown(event) {
570
+ /** @type {HTMLElement} */
571
+ const menuElement = (event.currentTarget);
572
+ if (!menuElement || menuElement.getAttribute('aria-hidden') === 'true') {
573
+ return;
574
+ }
575
+
576
+ if (event.key === 'ArrowDown' || (event.key === 'Down')) {
577
+ event.stopPropagation();
578
+ event.preventDefault();
579
+ selectNextMenuItem(menuElement, false);
580
+ return;
581
+ }
582
+ if (event.key === 'ArrowUp' || (event.key === 'Up')) {
583
+ event.stopPropagation();
584
+ event.preventDefault();
585
+ selectNextMenuItem(menuElement, true);
586
+ return;
587
+ }
588
+ if (event.key === 'Tab') {
589
+ // Hide menu allowing focus to revert to calling element
590
+ // To then allow browser default Tab interaction
591
+ // Unless menu hiding is cancelled
592
+ if (!hide(menuElement)) {
593
+ event.stopPropagation();
594
+ event.preventDefault();
595
+ }
596
+ return;
597
+ }
598
+ if (event.key === 'Escape' || event.key === 'Esc') {
599
+ event.stopPropagation();
600
+ event.preventDefault();
601
+ hide(menuElement);
602
+ }
603
+ }
604
+
598
605
  /**
599
606
  * @param {Element} menuElement
600
607
  * @return {void}
@@ -610,8 +617,22 @@ export function refreshMenuItems(menuElement) {
610
617
 
611
618
  /**
612
619
  * @param {Element} menuElement
613
- * @param {MouseEvent=} event
614
- * @param {boolean=} [alignTarget=true]
620
+ * @return {void}
621
+ */
622
+ export function attach(menuElement) {
623
+ menuElement.setAttribute('mdw-menu-js', '');
624
+ menuElement.addEventListener('click', onMenuClick);
625
+ menuElement.addEventListener('scroll', onMenuScroll);
626
+ menuElement.addEventListener('touchmove', onMenuScroll);
627
+ menuElement.addEventListener('wheel', onMenuScroll);
628
+ menuElement.addEventListener('keydown', onKeyDown);
629
+ setupARIA(menuElement);
630
+ }
631
+
632
+ /**
633
+ * @param {Element} menuElement
634
+ * @param {MouseEvent|PointerEvent} [event]
635
+ * @param {boolean} [alignTarget=true]
615
636
  * @return {boolean} handled
616
637
  */
617
638
  export function show(menuElement, event, alignTarget) {
@@ -619,7 +640,8 @@ export function show(menuElement, event, alignTarget) {
619
640
  // Prevent anchor link
620
641
  event.preventDefault();
621
642
  }
622
- const popupElement = menuElement.getElementsByClassName('mdw-menu__popup')[0];
643
+ /** @type {HTMLElement} */
644
+ const popupElement = (menuElement.getElementsByClassName('mdw-menu__popup')[0]);
623
645
  let changed = false;
624
646
  if (event) {
625
647
  updateMenuPosition(menuElement, popupElement, event, alignTarget);
@@ -659,7 +681,7 @@ export function show(menuElement, event, alignTarget) {
659
681
  const menuStack = new MenuStack(menuElement, previousFocus, newState, previousState, event);
660
682
  OPEN_MENUS.push(menuStack);
661
683
  refreshMenuItems(menuElement);
662
- if (event && !event.pointerType && !event.detail) {
684
+ if (event && !event.detail && ('pointerType' in event) && !event.pointerType) {
663
685
  // Triggered with keyboard event
664
686
  selectNextMenuItem(menuElement);
665
687
  } else {
@@ -671,38 +693,29 @@ export function show(menuElement, event, alignTarget) {
671
693
 
672
694
  /**
673
695
  * @param {Element} menuElement
674
- * @return {boolean} handled
696
+ * @return {void}
675
697
  */
676
- export function hide(menuElement) {
677
- if (menuElement.getAttribute('aria-hidden') === 'true') {
678
- return false;
679
- }
680
- menuElement.setAttribute('aria-hidden', 'true');
681
- let stackIndex = -1;
682
- OPEN_MENUS.some((stack, index) => {
683
- if (stack.element === menuElement) {
684
- stackIndex = index;
685
- return true;
686
- }
687
- return false;
688
- });
689
- if (stackIndex !== -1) {
690
- const menuStack = OPEN_MENUS[stackIndex];
691
- if (menuStack.previousFocus) {
692
- menuStack.previousFocus.focus();
693
- }
694
- OPEN_MENUS.splice(stackIndex, 1);
695
- if (menuStack.state && window.history && window.history.state) {
696
- // IE11 returns a cloned state object, not the original
697
- if (menuStack.state.hash === window.history.state.hash) {
698
- window.history.back();
699
- }
698
+ export function detach(menuElement) {
699
+ hide(menuElement);
700
+ menuElement.removeEventListener('click', onMenuClick);
701
+ menuElement.removeEventListener('scroll', onMenuScroll);
702
+ menuElement.removeEventListener('touchmove', onMenuScroll);
703
+ menuElement.removeEventListener('wheel', onMenuScroll);
704
+ menuElement.addEventListener('keydown', onKeyDown);
705
+ menuElement.removeAttribute('mdw-menu-js');
706
+ /** @type {HTMLElement} */
707
+ const popupElement = (menuElement.getElementsByClassName('mdw-menu__popup')[0]);
708
+ if (popupElement) {
709
+ popupElement.style.removeProperty('top');
710
+ popupElement.style.removeProperty('left');
711
+ popupElement.style.removeProperty('right');
712
+ popupElement.style.removeProperty('bottom');
713
+ popupElement.style.removeProperty('margin');
714
+ popupElement.style.removeProperty('transform-origin');
715
+ popupElement.style.removeProperty('position');
716
+ if (popupElement.hasAttribute('style') && !popupElement.getAttribute('style')) {
717
+ popupElement.removeAttribute('style');
700
718
  }
701
719
  }
702
- if (!OPEN_MENUS.length) {
703
- window.removeEventListener('popstate', onPopState);
704
- window.removeEventListener('resize', onWindowResize);
705
- }
706
- dispatchDomEvent(menuElement, HIDE_EVENT);
707
- return true;
720
+ iterateArrayLike(menuElement.getElementsByClassName('mdw-menu__item'), MenuItem.detach);
708
721
  }
@@ -1,2 +1,2 @@
1
- @import './_spec.scss';
2
- @import './_theme.scss';
1
+ @forward './_spec.scss';
2
+ @forward './_theme.scss';