@nanoporetech-digital/components 3.1.1 → 3.3.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 (461) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/cjs/dom-d7c33f11.js.map +1 -1
  3. package/dist/cjs/index-41582c2a.js +4 -4
  4. package/dist/cjs/index.cjs.js +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/{modal-f09e431f.js → modal-e4defcc3.js} +3 -3
  7. package/dist/cjs/{modal-f09e431f.js.map → modal-e4defcc3.js.map} +1 -1
  8. package/dist/cjs/nano-alert.cjs.entry.js +3 -3
  9. package/dist/cjs/nano-alert.cjs.entry.js.map +1 -1
  10. package/dist/cjs/nano-algolia.cjs.entry.js +1 -1
  11. package/dist/cjs/nano-algolia.cjs.entry.js.map +1 -1
  12. package/dist/cjs/nano-aspect-ratio.cjs.entry.js +1 -1
  13. package/dist/cjs/nano-aspect-ratio.cjs.entry.js.map +1 -1
  14. package/dist/cjs/nano-checkbox-group.cjs.entry.js +1 -1
  15. package/dist/cjs/nano-checkbox-group.cjs.entry.js.map +1 -1
  16. package/dist/cjs/nano-checkbox.cjs.entry.js +1 -1
  17. package/dist/cjs/nano-checkbox.cjs.entry.js.map +1 -1
  18. package/dist/cjs/nano-components.cjs.js +1 -1
  19. package/dist/cjs/nano-datalist_3.cjs.entry.js +2 -2
  20. package/dist/cjs/nano-datalist_3.cjs.entry.js.map +1 -1
  21. package/dist/cjs/nano-date-input.cjs.entry.js +1 -1
  22. package/dist/cjs/nano-date-input.cjs.entry.js.map +1 -1
  23. package/dist/cjs/nano-date-picker.cjs.entry.js +1 -1
  24. package/dist/cjs/nano-date-picker.cjs.entry.js.map +1 -1
  25. package/dist/cjs/nano-details.cjs.entry.js +1 -1
  26. package/dist/cjs/nano-details.cjs.entry.js.map +1 -1
  27. package/dist/cjs/nano-dialog.cjs.entry.js +3 -3
  28. package/dist/cjs/nano-dialog.cjs.entry.js.map +1 -1
  29. package/dist/cjs/nano-drawer.cjs.entry.js +3 -3
  30. package/dist/cjs/nano-drawer.cjs.entry.js.map +1 -1
  31. package/dist/cjs/nano-dropdown.cjs.entry.js +2 -2
  32. package/dist/cjs/nano-dropdown.cjs.entry.js.map +1 -1
  33. package/dist/cjs/nano-file-upload.cjs.entry.js +1 -1
  34. package/dist/cjs/nano-file-upload.cjs.entry.js.map +1 -1
  35. package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js +10 -5
  36. package/dist/cjs/nano-global-nav-user-profile_3.cjs.entry.js.map +1 -1
  37. package/dist/cjs/nano-global-nav.cjs.entry.js +41 -25
  38. package/dist/cjs/nano-global-nav.cjs.entry.js.map +1 -1
  39. package/dist/cjs/nano-global-search-results.cjs.entry.js +1 -1
  40. package/dist/cjs/nano-global-search-results.cjs.entry.js.map +1 -1
  41. package/dist/cjs/nano-grid_3.cjs.entry.js +2 -2
  42. package/dist/cjs/nano-grid_3.cjs.entry.js.map +1 -1
  43. package/dist/cjs/nano-hero.cjs.entry.js +1 -1
  44. package/dist/cjs/nano-hero.cjs.entry.js.map +1 -1
  45. package/dist/cjs/nano-icon-button.cjs.entry.js +1 -1
  46. package/dist/cjs/nano-icon-button.cjs.entry.js.map +1 -1
  47. package/dist/cjs/nano-icon.cjs.entry.js +1 -1
  48. package/dist/cjs/nano-icon.cjs.entry.js.map +1 -1
  49. package/dist/cjs/nano-input.cjs.entry.js +1 -1
  50. package/dist/cjs/nano-input.cjs.entry.js.map +1 -1
  51. package/dist/cjs/nano-menu-drawer.cjs.entry.js +1 -1
  52. package/dist/cjs/nano-menu-drawer.cjs.entry.js.map +1 -1
  53. package/dist/cjs/nano-progress-bar.cjs.entry.js +2 -2
  54. package/dist/cjs/nano-progress-bar.cjs.entry.js.map +1 -1
  55. package/dist/cjs/nano-range.cjs.entry.js +1 -1
  56. package/dist/cjs/nano-range.cjs.entry.js.map +1 -1
  57. package/dist/cjs/nano-rating.cjs.entry.js +1 -1
  58. package/dist/cjs/nano-rating.cjs.entry.js.map +1 -1
  59. package/dist/cjs/nano-resize-observe_2.cjs.entry.js +23 -12
  60. package/dist/cjs/nano-resize-observe_2.cjs.entry.js.map +1 -1
  61. package/dist/cjs/nano-slide.cjs.entry.js +1 -1
  62. package/dist/cjs/nano-slide.cjs.entry.js.map +1 -1
  63. package/dist/cjs/nano-slides.cjs.entry.js +1 -1
  64. package/dist/cjs/nano-slides.cjs.entry.js.map +1 -1
  65. package/dist/cjs/nano-spinner.cjs.entry.js +1 -1
  66. package/dist/cjs/nano-spinner.cjs.entry.js.map +1 -1
  67. package/dist/cjs/nano-split-pane.cjs.entry.js +1 -1
  68. package/dist/cjs/nano-split-pane.cjs.entry.js.map +1 -1
  69. package/dist/cjs/nano-sticker.cjs.entry.js +1 -1
  70. package/dist/cjs/nano-sticker.cjs.entry.js.map +1 -1
  71. package/dist/cjs/nano-tab-content.cjs.entry.js +1 -1
  72. package/dist/cjs/nano-tab-content.cjs.entry.js.map +1 -1
  73. package/dist/cjs/nano-tab-group.cjs.entry.js +1 -1
  74. package/dist/cjs/nano-tab-group.cjs.entry.js.map +1 -1
  75. package/dist/cjs/nano-tab.cjs.entry.js +1 -1
  76. package/dist/cjs/nano-tab.cjs.entry.js.map +1 -1
  77. package/dist/cjs/{nano-table-844394ad.js → nano-table-2ddb22be.js} +27 -26
  78. package/dist/cjs/nano-table-2ddb22be.js.map +1 -0
  79. package/dist/cjs/nano-table.cjs.entry.js +1 -1
  80. package/dist/cjs/nano-tooltip.cjs.entry.js +1 -1
  81. package/dist/cjs/nano-tooltip.cjs.entry.js.map +1 -1
  82. package/dist/cjs/{tabbable-de4c23d8.js → tabbable-bdf10c84.js} +13 -4
  83. package/dist/cjs/tabbable-bdf10c84.js.map +1 -0
  84. package/dist/cjs/{table.worker-1bc19978.js → table.worker-ec62a083.js} +2 -2
  85. package/dist/cjs/table.worker-ec62a083.js.map +1 -0
  86. package/dist/collection/components/alert/alert.css +16 -56
  87. package/dist/collection/components/algolia/algolia.css +5 -22
  88. package/dist/collection/components/aspect-ratio/aspect-ratio.css +2 -4
  89. package/dist/collection/components/checkbox/checkbox-group.css +8 -19
  90. package/dist/collection/components/checkbox/checkbox.css +24 -61
  91. package/dist/collection/components/date-input/date-input.css +8 -29
  92. package/dist/collection/components/date-picker/date-picker.css +22 -61
  93. package/dist/collection/components/details/details.css +7 -27
  94. package/dist/collection/components/dialog/dialog.css +20 -79
  95. package/dist/collection/components/drawer/drawer.css +13 -42
  96. package/dist/collection/components/dropdown/dropdown.css +5 -13
  97. package/dist/collection/components/file-upload/file-upload.css +45 -127
  98. package/dist/collection/components/global-nav/global-nav.js +40 -24
  99. package/dist/collection/components/global-nav/global-nav.js.map +1 -1
  100. package/dist/collection/components/global-nav/style/global-nav.css +147 -302
  101. package/dist/collection/components/global-search-results/global-search-results.css +81 -248
  102. package/dist/collection/components/grid/grid.css +21 -76
  103. package/dist/collection/components/hero/hero.css +22 -63
  104. package/dist/collection/components/icon/icon.css +2 -5
  105. package/dist/collection/components/icon-button/icon-button.css +4 -15
  106. package/dist/collection/components/img/img.css +9 -19
  107. package/dist/collection/components/input/input.css +34 -148
  108. package/dist/collection/components/input/input.js +2 -2
  109. package/dist/collection/components/input/input.js.map +1 -1
  110. package/dist/collection/components/menu/menu.css +1 -2
  111. package/dist/collection/components/menu-drawer/menu-drawer.css +16 -47
  112. package/dist/collection/components/nav-item/nav-item.css +73 -147
  113. package/dist/collection/components/nav-item/nav-item.js +8 -3
  114. package/dist/collection/components/nav-item/nav-item.js.map +1 -1
  115. package/dist/collection/components/option/option.css +10 -40
  116. package/dist/collection/components/progress-bar/progress-bar.css +5 -26
  117. package/dist/collection/components/progress-bar/progress-bar.js +1 -1
  118. package/dist/collection/components/progress-bar/progress-bar.js.map +1 -1
  119. package/dist/collection/components/range/range.css +20 -56
  120. package/dist/collection/components/rating/rating.css +9 -28
  121. package/dist/collection/components/resize-observe/resize-observe.js +38 -12
  122. package/dist/collection/components/resize-observe/resize-observe.js.map +1 -1
  123. package/dist/collection/components/select/select.css +56 -210
  124. package/dist/collection/components/skeleton/skeleton.css +2 -17
  125. package/dist/collection/components/slides/slide.css +4 -13
  126. package/dist/collection/components/slides/slides.css +3 -14
  127. package/dist/collection/components/spinner/spinner.css +34 -122
  128. package/dist/collection/components/split-pane/split-pane.css +4 -18
  129. package/dist/collection/components/sticker/sticker.css +8 -18
  130. package/dist/collection/components/table/table.children.js +10 -10
  131. package/dist/collection/components/table/table.children.js.map +1 -1
  132. package/dist/collection/components/table/table.css +111 -61
  133. package/dist/collection/components/table/table.js +22 -20
  134. package/dist/collection/components/table/table.js.map +1 -1
  135. package/dist/collection/components/table/table.service.js +1 -1
  136. package/dist/collection/components/table/table.service.js.map +1 -1
  137. package/dist/collection/components/tabs/tab-content.css +11 -59
  138. package/dist/collection/components/tabs/tab-group.css +20 -77
  139. package/dist/collection/components/tabs/tab.css +11 -30
  140. package/dist/collection/components/tooltip/tooltip.css +26 -56
  141. package/dist/collection/utils/dom.js.map +1 -1
  142. package/dist/collection/utils/modal.js +1 -1
  143. package/dist/collection/utils/modal.js.map +1 -1
  144. package/dist/collection/utils/tabbable.js +12 -3
  145. package/dist/collection/utils/tabbable.js.map +1 -1
  146. package/dist/components/algolia.js +1 -1
  147. package/dist/components/algolia.js.map +1 -1
  148. package/dist/components/date-picker.js +1 -1
  149. package/dist/components/date-picker.js.map +1 -1
  150. package/dist/components/dom.js.map +1 -1
  151. package/dist/components/dropdown.js +1 -1
  152. package/dist/components/dropdown.js.map +1 -1
  153. package/dist/components/grid.js +1 -1
  154. package/dist/components/grid.js.map +1 -1
  155. package/dist/components/icon-button.js +1 -1
  156. package/dist/components/icon-button.js.map +1 -1
  157. package/dist/components/icon.js +1 -1
  158. package/dist/components/icon.js.map +1 -1
  159. package/dist/components/img.js +1 -1
  160. package/dist/components/img.js.map +1 -1
  161. package/dist/components/input.js +1 -1
  162. package/dist/components/input.js.map +1 -1
  163. package/dist/components/menu.js +1 -1
  164. package/dist/components/menu.js.map +1 -1
  165. package/dist/components/modal.js +1 -1
  166. package/dist/components/modal.js.map +1 -1
  167. package/dist/components/nano-alert.js +1 -1
  168. package/dist/components/nano-alert.js.map +1 -1
  169. package/dist/components/nano-aspect-ratio.js +1 -1
  170. package/dist/components/nano-aspect-ratio.js.map +1 -1
  171. package/dist/components/nano-checkbox-group.js +1 -1
  172. package/dist/components/nano-checkbox-group.js.map +1 -1
  173. package/dist/components/nano-checkbox.js +1 -1
  174. package/dist/components/nano-checkbox.js.map +1 -1
  175. package/dist/components/nano-date-input.js +1 -1
  176. package/dist/components/nano-date-input.js.map +1 -1
  177. package/dist/components/nano-details.js +1 -1
  178. package/dist/components/nano-details.js.map +1 -1
  179. package/dist/components/nano-dialog.js +1 -1
  180. package/dist/components/nano-dialog.js.map +1 -1
  181. package/dist/components/nano-drawer.js +1 -1
  182. package/dist/components/nano-drawer.js.map +1 -1
  183. package/dist/components/nano-file-upload.js +1 -1
  184. package/dist/components/nano-file-upload.js.map +1 -1
  185. package/dist/components/nano-global-nav.js +41 -25
  186. package/dist/components/nano-global-nav.js.map +1 -1
  187. package/dist/components/nano-global-search-results.js +1 -1
  188. package/dist/components/nano-global-search-results.js.map +1 -1
  189. package/dist/components/nano-hero.js +1 -1
  190. package/dist/components/nano-hero.js.map +1 -1
  191. package/dist/components/nano-menu-drawer.js +1 -1
  192. package/dist/components/nano-menu-drawer.js.map +1 -1
  193. package/dist/components/nano-range.js +1 -1
  194. package/dist/components/nano-range.js.map +1 -1
  195. package/dist/components/nano-rating.js +1 -1
  196. package/dist/components/nano-rating.js.map +1 -1
  197. package/dist/components/nano-slide.js +1 -1
  198. package/dist/components/nano-slide.js.map +1 -1
  199. package/dist/components/nano-slides.js +1 -1
  200. package/dist/components/nano-slides.js.map +1 -1
  201. package/dist/components/nano-split-pane.js +1 -1
  202. package/dist/components/nano-split-pane.js.map +1 -1
  203. package/dist/components/nano-tab-content.js +1 -1
  204. package/dist/components/nano-tab-content.js.map +1 -1
  205. package/dist/components/nano-tab-group.js +1 -1
  206. package/dist/components/nano-tab-group.js.map +1 -1
  207. package/dist/components/nano-tab.js +1 -1
  208. package/dist/components/nano-tab.js.map +1 -1
  209. package/dist/components/nano-table.js +35 -28
  210. package/dist/components/nano-table.js.map +1 -1
  211. package/dist/components/nav-item.js +9 -4
  212. package/dist/components/nav-item.js.map +1 -1
  213. package/dist/components/option.js +1 -1
  214. package/dist/components/option.js.map +1 -1
  215. package/dist/components/progress-bar.js +2 -2
  216. package/dist/components/progress-bar.js.map +1 -1
  217. package/dist/components/resize-observe.js +23 -13
  218. package/dist/components/resize-observe.js.map +1 -1
  219. package/dist/components/select.js +1 -1
  220. package/dist/components/select.js.map +1 -1
  221. package/dist/components/skeleton.js +1 -1
  222. package/dist/components/skeleton.js.map +1 -1
  223. package/dist/components/spinner.js +1 -1
  224. package/dist/components/spinner.js.map +1 -1
  225. package/dist/components/sticker.js +1 -1
  226. package/dist/components/sticker.js.map +1 -1
  227. package/dist/components/tabbable.js +12 -3
  228. package/dist/components/tabbable.js.map +1 -1
  229. package/dist/components/tooltip.js +1 -1
  230. package/dist/components/tooltip.js.map +1 -1
  231. package/dist/custom-elements/index.js +147 -106
  232. package/dist/custom-elements/index.js.map +1 -1
  233. package/dist/esm/dom-d3ad49e2.js.map +1 -1
  234. package/dist/esm/index-3c280603.js +4 -4
  235. package/dist/esm/index.js +1 -1
  236. package/dist/esm/loader.js +1 -1
  237. package/dist/esm/{modal-215df46b.js → modal-5c9ce466.js} +3 -3
  238. package/dist/esm/{modal-215df46b.js.map → modal-5c9ce466.js.map} +1 -1
  239. package/dist/esm/nano-alert.entry.js +3 -3
  240. package/dist/esm/nano-alert.entry.js.map +1 -1
  241. package/dist/esm/nano-algolia.entry.js +1 -1
  242. package/dist/esm/nano-algolia.entry.js.map +1 -1
  243. package/dist/esm/nano-aspect-ratio.entry.js +1 -1
  244. package/dist/esm/nano-aspect-ratio.entry.js.map +1 -1
  245. package/dist/esm/nano-checkbox-group.entry.js +1 -1
  246. package/dist/esm/nano-checkbox-group.entry.js.map +1 -1
  247. package/dist/esm/nano-checkbox.entry.js +1 -1
  248. package/dist/esm/nano-checkbox.entry.js.map +1 -1
  249. package/dist/esm/nano-components.js +1 -1
  250. package/dist/esm/nano-datalist_3.entry.js +2 -2
  251. package/dist/esm/nano-datalist_3.entry.js.map +1 -1
  252. package/dist/esm/nano-date-input.entry.js +1 -1
  253. package/dist/esm/nano-date-input.entry.js.map +1 -1
  254. package/dist/esm/nano-date-picker.entry.js +1 -1
  255. package/dist/esm/nano-date-picker.entry.js.map +1 -1
  256. package/dist/esm/nano-details.entry.js +1 -1
  257. package/dist/esm/nano-details.entry.js.map +1 -1
  258. package/dist/esm/nano-dialog.entry.js +3 -3
  259. package/dist/esm/nano-dialog.entry.js.map +1 -1
  260. package/dist/esm/nano-drawer.entry.js +3 -3
  261. package/dist/esm/nano-drawer.entry.js.map +1 -1
  262. package/dist/esm/nano-dropdown.entry.js +2 -2
  263. package/dist/esm/nano-dropdown.entry.js.map +1 -1
  264. package/dist/esm/nano-file-upload.entry.js +1 -1
  265. package/dist/esm/nano-file-upload.entry.js.map +1 -1
  266. package/dist/esm/nano-global-nav-user-profile_3.entry.js +10 -5
  267. package/dist/esm/nano-global-nav-user-profile_3.entry.js.map +1 -1
  268. package/dist/esm/nano-global-nav.entry.js +41 -25
  269. package/dist/esm/nano-global-nav.entry.js.map +1 -1
  270. package/dist/esm/nano-global-search-results.entry.js +1 -1
  271. package/dist/esm/nano-global-search-results.entry.js.map +1 -1
  272. package/dist/esm/nano-grid_3.entry.js +2 -2
  273. package/dist/esm/nano-grid_3.entry.js.map +1 -1
  274. package/dist/esm/nano-hero.entry.js +1 -1
  275. package/dist/esm/nano-hero.entry.js.map +1 -1
  276. package/dist/esm/nano-icon-button.entry.js +1 -1
  277. package/dist/esm/nano-icon-button.entry.js.map +1 -1
  278. package/dist/esm/nano-icon.entry.js +1 -1
  279. package/dist/esm/nano-icon.entry.js.map +1 -1
  280. package/dist/esm/nano-input.entry.js +1 -1
  281. package/dist/esm/nano-input.entry.js.map +1 -1
  282. package/dist/esm/nano-menu-drawer.entry.js +1 -1
  283. package/dist/esm/nano-menu-drawer.entry.js.map +1 -1
  284. package/dist/esm/nano-progress-bar.entry.js +2 -2
  285. package/dist/esm/nano-progress-bar.entry.js.map +1 -1
  286. package/dist/esm/nano-range.entry.js +1 -1
  287. package/dist/esm/nano-range.entry.js.map +1 -1
  288. package/dist/esm/nano-rating.entry.js +1 -1
  289. package/dist/esm/nano-rating.entry.js.map +1 -1
  290. package/dist/esm/nano-resize-observe_2.entry.js +23 -12
  291. package/dist/esm/nano-resize-observe_2.entry.js.map +1 -1
  292. package/dist/esm/nano-slide.entry.js +1 -1
  293. package/dist/esm/nano-slide.entry.js.map +1 -1
  294. package/dist/esm/nano-slides.entry.js +1 -1
  295. package/dist/esm/nano-slides.entry.js.map +1 -1
  296. package/dist/esm/nano-spinner.entry.js +1 -1
  297. package/dist/esm/nano-spinner.entry.js.map +1 -1
  298. package/dist/esm/nano-split-pane.entry.js +1 -1
  299. package/dist/esm/nano-split-pane.entry.js.map +1 -1
  300. package/dist/esm/nano-sticker.entry.js +1 -1
  301. package/dist/esm/nano-sticker.entry.js.map +1 -1
  302. package/dist/esm/nano-tab-content.entry.js +1 -1
  303. package/dist/esm/nano-tab-content.entry.js.map +1 -1
  304. package/dist/esm/nano-tab-group.entry.js +1 -1
  305. package/dist/esm/nano-tab-group.entry.js.map +1 -1
  306. package/dist/esm/nano-tab.entry.js +1 -1
  307. package/dist/esm/nano-tab.entry.js.map +1 -1
  308. package/dist/esm/{nano-table-19d19d72.js → nano-table-9d4fbd41.js} +27 -26
  309. package/dist/esm/nano-table-9d4fbd41.js.map +1 -0
  310. package/dist/esm/nano-table.entry.js +1 -1
  311. package/dist/esm/nano-tooltip.entry.js +1 -1
  312. package/dist/esm/nano-tooltip.entry.js.map +1 -1
  313. package/dist/esm/{tabbable-614f515e.js → tabbable-31485ff7.js} +13 -4
  314. package/dist/esm/tabbable-31485ff7.js.map +1 -0
  315. package/dist/esm/{table.worker-c82cecdf.js → table.worker-1ba8ac3f.js} +2 -2
  316. package/dist/esm/table.worker-1ba8ac3f.js.map +1 -0
  317. package/dist/nano-components/index.esm.js +1 -1
  318. package/dist/nano-components/nano-components.css +1 -1
  319. package/dist/nano-components/nano-components.esm.js +1 -1
  320. package/dist/nano-components/{p-35295332.entry.js → p-151aad1e.entry.js} +5 -5
  321. package/dist/nano-components/{p-35295332.entry.js.map → p-151aad1e.entry.js.map} +1 -1
  322. package/dist/nano-components/p-15543295.entry.js +5 -0
  323. package/dist/nano-components/{p-6e3412d2.entry.js.map → p-15543295.entry.js.map} +1 -1
  324. package/dist/nano-components/p-1e709f87.entry.js +5 -0
  325. package/dist/nano-components/p-1e709f87.entry.js.map +1 -0
  326. package/dist/nano-components/p-1f347342.entry.js +5 -0
  327. package/dist/nano-components/{p-02df1f62.entry.js.map → p-1f347342.entry.js.map} +1 -1
  328. package/dist/nano-components/p-216ece9a.js +5 -0
  329. package/dist/nano-components/{p-7ade1695.js.map → p-216ece9a.js.map} +0 -0
  330. package/dist/nano-components/p-23575705.entry.js +5 -0
  331. package/dist/nano-components/{p-6958df8c.entry.js.map → p-23575705.entry.js.map} +1 -1
  332. package/dist/nano-components/p-244223f0.entry.js +5 -0
  333. package/dist/nano-components/{p-6cd59e58.entry.js.map → p-244223f0.entry.js.map} +1 -1
  334. package/dist/nano-components/p-284dd9a2.entry.js +5 -0
  335. package/dist/nano-components/{p-5107646c.entry.js.map → p-284dd9a2.entry.js.map} +1 -1
  336. package/dist/nano-components/p-2cb4615b.entry.js +5 -0
  337. package/dist/nano-components/{p-e3730878.entry.js.map → p-2cb4615b.entry.js.map} +1 -1
  338. package/dist/nano-components/p-36842a50.entry.js +5 -0
  339. package/dist/nano-components/{p-f69f93e9.entry.js.map → p-36842a50.entry.js.map} +1 -1
  340. package/dist/nano-components/p-41addb3a.entry.js +5 -0
  341. package/dist/nano-components/{p-0a5ad0ef.entry.js.map → p-41addb3a.entry.js.map} +1 -1
  342. package/dist/nano-components/{p-9a385481.js → p-45abbbdd.js} +2 -2
  343. package/dist/nano-components/p-45abbbdd.js.map +1 -0
  344. package/dist/nano-components/p-46b348b7.entry.js +5 -0
  345. package/dist/nano-components/{p-28f713fb.entry.js.map → p-46b348b7.entry.js.map} +1 -1
  346. package/dist/nano-components/p-4b69178e.entry.js +5 -0
  347. package/dist/nano-components/{p-5e33798f.entry.js.map → p-4b69178e.entry.js.map} +1 -1
  348. package/dist/nano-components/p-4f0e14b5.entry.js +5 -0
  349. package/dist/nano-components/{p-8f5e0022.entry.js.map → p-4f0e14b5.entry.js.map} +1 -1
  350. package/dist/nano-components/p-559a6492.entry.js +5 -0
  351. package/dist/nano-components/p-559a6492.entry.js.map +1 -0
  352. package/dist/nano-components/p-601e18d5.entry.js +5 -0
  353. package/dist/nano-components/p-601e18d5.entry.js.map +1 -0
  354. package/dist/nano-components/p-69e5a37d.entry.js +5 -0
  355. package/dist/nano-components/{p-282987e6.entry.js.map → p-69e5a37d.entry.js.map} +1 -1
  356. package/dist/nano-components/p-751927d1.entry.js +5 -0
  357. package/dist/nano-components/{p-5d81773d.entry.js.map → p-751927d1.entry.js.map} +1 -1
  358. package/dist/nano-components/p-845ae77e.js.map +1 -1
  359. package/dist/nano-components/p-866e7e88.js +5 -0
  360. package/dist/nano-components/p-866e7e88.js.map +1 -0
  361. package/dist/nano-components/{p-b4a045a2.entry.js → p-89b8ce4f.entry.js} +2 -2
  362. package/dist/nano-components/{p-b4a045a2.entry.js.map → p-89b8ce4f.entry.js.map} +0 -0
  363. package/dist/nano-components/p-9059c8c1.entry.js +5 -0
  364. package/dist/nano-components/{p-d8e8d7e3.entry.js.map → p-9059c8c1.entry.js.map} +1 -1
  365. package/dist/nano-components/p-92504f7f.entry.js +5 -0
  366. package/dist/nano-components/{p-50fcb11c.entry.js.map → p-92504f7f.entry.js.map} +1 -1
  367. package/dist/nano-components/p-99fbae74.entry.js +5 -0
  368. package/dist/nano-components/{p-8a52a411.entry.js.map → p-99fbae74.entry.js.map} +1 -1
  369. package/dist/nano-components/p-9eeed8f5.entry.js +5 -0
  370. package/dist/nano-components/{p-4c97f05f.entry.js.map → p-9eeed8f5.entry.js.map} +1 -1
  371. package/dist/nano-components/p-a183e3c7.entry.js +5 -0
  372. package/dist/nano-components/{p-b290a970.entry.js.map → p-a183e3c7.entry.js.map} +1 -1
  373. package/dist/nano-components/p-a2e38472.entry.js +5 -0
  374. package/dist/nano-components/p-a2e38472.entry.js.map +1 -0
  375. package/dist/nano-components/p-b87539f0.entry.js +5 -0
  376. package/dist/nano-components/{p-efa8c520.entry.js.map → p-b87539f0.entry.js.map} +1 -1
  377. package/dist/nano-components/p-b9c8b99f.entry.js +5 -0
  378. package/dist/nano-components/p-b9c8b99f.entry.js.map +1 -0
  379. package/dist/nano-components/{p-cb79d1ec.js → p-c9a7c7ea.js} +2 -2
  380. package/dist/nano-components/{p-cb79d1ec.js.map → p-c9a7c7ea.js.map} +1 -1
  381. package/dist/nano-components/{p-c45851c3.entry.js → p-d1c8eca4.entry.js} +2 -2
  382. package/dist/nano-components/{p-c45851c3.entry.js.map → p-d1c8eca4.entry.js.map} +1 -1
  383. package/dist/nano-components/p-d8678bdc.entry.js +5 -0
  384. package/dist/nano-components/p-d8678bdc.entry.js.map +1 -0
  385. package/dist/nano-components/p-db4b6602.entry.js +5 -0
  386. package/dist/nano-components/{p-716064b6.entry.js.map → p-db4b6602.entry.js.map} +1 -1
  387. package/dist/nano-components/{p-916e4b6b.entry.js → p-dba8a88d.entry.js} +2 -2
  388. package/dist/nano-components/{p-916e4b6b.entry.js.map → p-dba8a88d.entry.js.map} +1 -1
  389. package/dist/nano-components/p-e4e41e06.entry.js +5 -0
  390. package/dist/nano-components/p-e4e41e06.entry.js.map +1 -0
  391. package/dist/nano-components/p-e5408bc8.entry.js +5 -0
  392. package/dist/nano-components/{p-c5bb5540.entry.js.map → p-e5408bc8.entry.js.map} +1 -1
  393. package/dist/nano-components/p-f43d1d8e.entry.js +5 -0
  394. package/dist/nano-components/p-f43d1d8e.entry.js.map +1 -0
  395. package/dist/nano-components/p-f7471cca.entry.js +5 -0
  396. package/dist/nano-components/{p-66ad1418.entry.js.map → p-f7471cca.entry.js.map} +1 -1
  397. package/dist/nano-components/p-fe94eeff.entry.js +5 -0
  398. package/dist/nano-components/{p-701e8ebf.entry.js.map → p-fe94eeff.entry.js.map} +1 -1
  399. package/dist/nano-components/p-feb9f164.entry.js +5 -0
  400. package/dist/nano-components/{p-81136f24.entry.js.map → p-feb9f164.entry.js.map} +1 -1
  401. package/dist/themes/nanopore.css +1 -1
  402. package/dist/themes/nanopore.css.map +1 -1
  403. package/dist/types/components/global-nav/global-nav.d.ts +8 -3
  404. package/dist/types/components/input/input.d.ts +2 -2
  405. package/dist/types/components/resize-observe/resize-observe.d.ts +5 -2
  406. package/dist/types/components/table/table.d.ts +8 -7
  407. package/dist/types/components.d.ts +4 -0
  408. package/dist/types/utils/dom.d.ts +1 -1
  409. package/docs-json.json +175 -9
  410. package/docs-vscode.json +2 -2
  411. package/package.json +2 -2
  412. package/dist/cjs/nano-table-844394ad.js.map +0 -1
  413. package/dist/cjs/tabbable-de4c23d8.js.map +0 -1
  414. package/dist/cjs/table.worker-1bc19978.js.map +0 -1
  415. package/dist/esm/nano-table-19d19d72.js.map +0 -1
  416. package/dist/esm/tabbable-614f515e.js.map +0 -1
  417. package/dist/esm/table.worker-c82cecdf.js.map +0 -1
  418. package/dist/nano-components/p-02df1f62.entry.js +0 -5
  419. package/dist/nano-components/p-0a5ad0ef.entry.js +0 -5
  420. package/dist/nano-components/p-1ae8c03e.entry.js +0 -5
  421. package/dist/nano-components/p-1ae8c03e.entry.js.map +0 -1
  422. package/dist/nano-components/p-282987e6.entry.js +0 -5
  423. package/dist/nano-components/p-28b43ee9.entry.js +0 -5
  424. package/dist/nano-components/p-28b43ee9.entry.js.map +0 -1
  425. package/dist/nano-components/p-28f713fb.entry.js +0 -5
  426. package/dist/nano-components/p-37553477.entry.js +0 -5
  427. package/dist/nano-components/p-37553477.entry.js.map +0 -1
  428. package/dist/nano-components/p-4c97f05f.entry.js +0 -5
  429. package/dist/nano-components/p-50fcb11c.entry.js +0 -5
  430. package/dist/nano-components/p-5107646c.entry.js +0 -5
  431. package/dist/nano-components/p-5d81773d.entry.js +0 -5
  432. package/dist/nano-components/p-5e33798f.entry.js +0 -5
  433. package/dist/nano-components/p-66ad1418.entry.js +0 -5
  434. package/dist/nano-components/p-6958df8c.entry.js +0 -5
  435. package/dist/nano-components/p-6cd59e58.entry.js +0 -5
  436. package/dist/nano-components/p-6e3412d2.entry.js +0 -5
  437. package/dist/nano-components/p-701e8ebf.entry.js +0 -5
  438. package/dist/nano-components/p-716064b6.entry.js +0 -5
  439. package/dist/nano-components/p-7ade1695.js +0 -5
  440. package/dist/nano-components/p-81136f24.entry.js +0 -5
  441. package/dist/nano-components/p-8a52a411.entry.js +0 -5
  442. package/dist/nano-components/p-8f5e0022.entry.js +0 -5
  443. package/dist/nano-components/p-9a385481.js.map +0 -1
  444. package/dist/nano-components/p-a151dea5.entry.js +0 -5
  445. package/dist/nano-components/p-a151dea5.entry.js.map +0 -1
  446. package/dist/nano-components/p-b290a970.entry.js +0 -5
  447. package/dist/nano-components/p-b7901427.entry.js +0 -5
  448. package/dist/nano-components/p-b7901427.entry.js.map +0 -1
  449. package/dist/nano-components/p-b83a8320.js +0 -5
  450. package/dist/nano-components/p-b83a8320.js.map +0 -1
  451. package/dist/nano-components/p-c5bb5540.entry.js +0 -5
  452. package/dist/nano-components/p-d8e8d7e3.entry.js +0 -5
  453. package/dist/nano-components/p-e3730878.entry.js +0 -5
  454. package/dist/nano-components/p-efa8c520.entry.js +0 -5
  455. package/dist/nano-components/p-f69f93e9.entry.js +0 -5
  456. package/dist/nano-components/p-f71f69c9.entry.js +0 -5
  457. package/dist/nano-components/p-f71f69c9.entry.js.map +0 -1
  458. package/dist/nano-components/p-f95a263c.entry.js +0 -5
  459. package/dist/nano-components/p-f95a263c.entry.js.map +0 -1
  460. package/dist/nano-components/p-fa2a6733.entry.js +0 -5
  461. package/dist/nano-components/p-fa2a6733.entry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["src/utils/drag.ts","src/components/split-pane/split-pane.scss?tag=nano-split-pane&encapsulation=shadow","src/components/split-pane/split-pane.tsx"],"names":["drag","container","onMove","move","pointerEvent","dims","getBoundingClientRect","defaultView","ownerDocument","offsetX","left","pageXOffset","offsetY","top","pageYOffset","x","pageX","y","pageY","stop","document","removeEventListener","addEventListener","passive","splitPaneCss","SplitPane","[object Object]","hostRef","this","isAnimating","didLoad","_shouldAnimate","handleDrag","e","disabled","preventDefault","host","newPositionInPixels","vertical","nanoDragging","emit","primary","size","snap","snaps","split","forEach","value","snapPoint","endsWith","parseFloat","snapThreshold","shouldAnimate","position","clamp","pixelsToPercentage","requestAnimationFrame","handleKeyDown","event","includes","key","newPosition","incr","shiftKey","handleResize","cachedPositionInPixels","handlePositionChange","debounce","bind","width","height","sa","_position","pos","Math","min","max","isNaN","animationDuration","animatePosition","percentageToPixels","positionInPixels","nanoReposition","end","duration","fps","start","distance","time","easeInOutQuad","t","s","d","go","detachRO","ro","ResizeObserver","observe","unobserve","undefined","handlePositionInPixelsChange","setTimeout","attachRO","styles","gridTemplate","secondary","h","Host","style","part","class","name","tabindex","role","aria-label","onKeyDown","onMouseDown","onTouchStart","slot"],"mappings":"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","sourcesContent":["export function drag(\n container: HTMLElement,\n onMove: (x: number, y: number) => void\n) {\n function move(pointerEvent: PointerEvent) {\n const dims = container.getBoundingClientRect();\n const defaultView = container.ownerDocument.defaultView!;\n const offsetX = dims.left + defaultView.pageXOffset;\n const offsetY = dims.top + defaultView.pageYOffset;\n const x = pointerEvent.pageX - offsetX;\n const y = pointerEvent.pageY - offsetY;\n\n onMove(x, y);\n }\n\n function stop() {\n document.removeEventListener('pointermove', move);\n document.removeEventListener('pointerup', stop);\n }\n\n document.addEventListener('pointermove', move, { passive: true });\n document.addEventListener('pointerup', stop);\n}\n","@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/components';\n@import '../../global/style/nano-theme/form';\n\n:host {\n /**\n * @prop --divider-width: The width of the visible divider. Default 4px.\n * @prop --divider-hit-area: The invisible region around the divider where dragging can occur. This is\n * usually wider than the divider to facilitate easier dragging. Default 12px.\n * @prop --min: The minimum allowed size of the primary panel. Default 0.\n * @prop --max: The maximum allowed size of the primary panel. Default 100%.\n * @prop --background-color: Handle background. Default #{map.get($colors, lightgrey)}.\n * @prop --content-color: Handle color. Default #{map.get($colors, dimgrey)}.\n */\n --divider-width: 12px;\n --divider-hit-area: 14px;\n --min: 0%;\n --max: 100%;\n --background-color: #{map.get($colors, lightgrey)};\n --content-color: #{map.get($colors, dimgrey)};\n\n display: grid;\n}\n\n.start,\n.end {\n overflow: hidden;\n}\n\n.divider {\n flex: 0 0 var(--divider-width);\n display: flex;\n position: relative;\n align-items: center;\n justify-content: center;\n background-color: var(--background-color);\n color: var(--content-color);\n z-index: 1;\n font-size: 0.8rem;\n}\n\n.divider:focus {\n outline: none;\n}\n\n:host(:not([disabled])) .divider:focus-visible {\n background-color: #{$control-focus-color};\n}\n\n:host([disabled]) .divider {\n cursor: not-allowed;\n}\n\n/* Horizontal */\n:host(:not([vertical], [disabled])) .divider {\n cursor: col-resize;\n}\n\n:host(:not([vertical])) .divider::after {\n display: flex;\n content: '';\n position: absolute;\n block-size: 100%;\n inset-inline-start: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2);\n inline-size: var(--divider-hit-area);\n}\n\n/* Vertical */\n:host([vertical]) {\n flex-direction: column;\n}\n\n:host([vertical]:not([disabled])) .divider {\n cursor: row-resize;\n}\n\n:host([vertical]) .divider::after {\n content: '';\n position: absolute;\n inline-size: 100%;\n inset-block-start: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2);\n block-size: var(--divider-hit-area);\n}\n","import {\n Prop,\n Component,\n Watch,\n Event,\n EventEmitter,\n ComponentInterface,\n Element,\n Host,\n h,\n Method,\n} from '@stencil/core';\nimport { drag } from '../../utils/drag';\nimport { clamp } from '../../utils/math';\nimport { debounce } from '../../utils/throttle';\n\n/**\n * Split panes display two adjacent panels, allowing the user to reposition them.\n *\n * @part start - The start panel.\n * @part end - The end panel.\n * @part panel - Targets both the start and end panels.\n * @part divider - The divider that separates the start and end panels.\n *\n * @slot start - The start panel.\n * @slot end - The end panel.\n * @slot handle - An optional handle to render at the center of the divider.\n */\n@Component({\n tag: 'nano-split-pane',\n styleUrl: 'split-pane.scss',\n shadow: true,\n})\nexport class SplitPane implements ComponentInterface {\n @Element() host: HTMLNanoSplitPaneElement;\n private cachedPositionInPixels: number;\n private ro: ResizeObserver;\n private isAnimating = false;\n private didLoad = false;\n\n private get size() {\n const { width, height } = this.host.getBoundingClientRect();\n return this.vertical ? height : width;\n }\n\n private get shouldAnimate() {\n return this.didLoad && this._shouldAnimate;\n }\n private set shouldAnimate(sa: boolean) {\n this._shouldAnimate = sa;\n }\n private _shouldAnimate: boolean = true;\n\n constructor() {\n this.handlePositionChange = debounce(\n this.handlePositionChange.bind(this),\n 100\n );\n }\n\n /**\n * The current position of the divider from the primary panel's edge\n * as a percentage 0-100. Defaults to 50% of the container's initial size.\n */\n @Prop()\n get position() {\n return this._position;\n }\n set position(pos: number) {\n // override too high / low\n pos = Math.min(Math.max(pos, 0), 100);\n if (isNaN(pos) || pos === this._position) return;\n\n if (\n this.shouldAnimate &&\n this.animationDuration > 0 &&\n !isNaN(this.position)\n ) {\n this.animatePosition(pos);\n return;\n }\n this._position = pos;\n }\n private _position: number;\n\n // eslint-disable-next-line @stencil/no-unused-watch\n @Watch('position')\n handlePositionChange() {\n this.cachedPositionInPixels = this.percentageToPixels(this.position);\n this.positionInPixels = this.percentageToPixels(this.position);\n this.nanoReposition.emit();\n }\n\n /**\n * The current position of the divider from the primary panel's edge in pixels.\n */\n @Prop({ mutable: true }) positionInPixels: number;\n\n @Watch('positionInPixels')\n handlePositionInPixelsChange() {\n this.position = this.pixelsToPercentage(this.positionInPixels);\n }\n\n /** Draws the split panel in a vertical orientation with the start and end panels stacked. */\n @Prop({ reflect: true }) vertical = false;\n\n /** Disables resizing. Note that the position may still change as a result of resizing the host element. */\n @Prop({ reflect: true }) disabled = false;\n\n /**\n * If no primary panel is designated, both panels will resize proportionally when the host element is resized. If a\n * primary panel is designated, it will maintain its size and the other panel will grow or shrink as needed when the\n * host element is resized.\n */\n @Prop() primary?: 'start' | 'end';\n\n /**\n * One or more space-separated values at which the divider should snap. Values can be in pixels or percentages, e.g.\n * `\"100px 50%\"`.\n */\n @Prop() snap?: string;\n\n /** How close the divider must be to a snap point until snapping occurs. */\n @Prop() snapThreshold = 12;\n\n /** When changing `position` via property, the pane will animate into position. Make `animationDuration` 0 to disable. */\n @Prop() animationDuration = 0.6;\n\n /** Emitted when the divider's position changes. */\n @Event() nanoReposition: EventEmitter;\n\n /** Emitted when the divider is being dragged. */\n @Event() nanoDragging: EventEmitter<number>;\n\n /** Utility to convert % to pixels */\n @Method()\n async getPercentageToPixels(value: number) {\n return this.percentageToPixels(value);\n }\n\n /** Utility to convert pixels to % (`position`) */\n @Method()\n async getPixelsToPercentage(value: number) {\n return this.pixelsToPercentage(value);\n }\n\n // Private logic\n\n private animatePosition(end: number) {\n if (this.isAnimating) return;\n\n const duration = this.animationDuration; // seconds\n const fps = 60;\n const start = this.position;\n const distance = end - start;\n\n let position = start;\n let time = 0;\n\n function easeInOutQuad(t: number, s: number, e: number, d: number) {\n if ((t /= d / 2) < 1) return (e / 2) * t * t + s;\n else return (-e / 2) * (--t * (t - 2) - 1) + s;\n }\n\n const go = () => {\n time += 1 / fps;\n position = easeInOutQuad(time, start, distance, duration);\n\n if (\n (end > start && position >= end) ||\n (end < start && position <= end)\n ) {\n this.position = end;\n this.shouldAnimate = true;\n this.isAnimating = false;\n return;\n }\n this.position = position;\n requestAnimationFrame(go);\n };\n\n this.shouldAnimate = false;\n this.isAnimating = true;\n requestAnimationFrame(go);\n }\n\n private percentageToPixels(value: number) {\n return this.size * (value / 100);\n }\n\n private pixelsToPercentage(value: number) {\n return (value / this.size) * 100;\n }\n\n private attachRO() {\n this.detachRO();\n this.ro = new ResizeObserver(() => this.handleResize());\n this.ro.observe(this.host);\n }\n\n private detachRO() {\n if (!this.ro) return;\n this.ro.unobserve(this.host);\n this.ro = undefined;\n }\n\n // Event handlers\n\n private handleDrag = (e: Event) => {\n if (this.disabled) {\n return;\n }\n\n // Prevent text selection when dragging\n e.preventDefault();\n\n drag(this.host, (x, y) => {\n let newPositionInPixels = this.vertical ? y : x;\n\n this.nanoDragging.emit(newPositionInPixels);\n\n // Flip for end panels\n if (this.primary === 'end') {\n newPositionInPixels = this.size - newPositionInPixels;\n }\n\n // Check snap points\n if (this.snap) {\n const snaps = this.snap.split(' ');\n\n snaps.forEach((value) => {\n let snapPoint: number;\n\n if (value.endsWith('%')) {\n snapPoint = this.size * (parseFloat(value) / 100);\n } else {\n snapPoint = parseFloat(value);\n }\n\n if (\n newPositionInPixels >= snapPoint - this.snapThreshold &&\n newPositionInPixels <= snapPoint + this.snapThreshold\n ) {\n newPositionInPixels = snapPoint;\n }\n });\n }\n this.shouldAnimate = false;\n this.position = clamp(\n this.pixelsToPercentage(newPositionInPixels),\n 0,\n 100\n );\n requestAnimationFrame(() => (this.shouldAnimate = true));\n });\n };\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (this.disabled) {\n return;\n }\n\n if (\n [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n let newPosition = this.position;\n const incr =\n (event.shiftKey ? 10 : 1) * (this.primary === 'end' ? -1 : 1);\n\n event.preventDefault();\n\n if (\n (event.key === 'ArrowLeft' && !this.vertical) ||\n (event.key === 'ArrowUp' && this.vertical)\n ) {\n newPosition -= incr;\n }\n\n if (\n (event.key === 'ArrowRight' && !this.vertical) ||\n (event.key === 'ArrowDown' && this.vertical)\n ) {\n newPosition += incr;\n }\n\n if (event.key === 'Home') {\n newPosition = this.primary === 'end' ? 100 : 0;\n }\n\n if (event.key === 'End') {\n newPosition = this.primary === 'end' ? 0 : 100;\n }\n\n this.shouldAnimate = false;\n\n this.position = clamp(newPosition, 0, 100);\n requestAnimationFrame(() => (this.shouldAnimate = true));\n }\n };\n\n private handleResize = () => {\n if (!this.didLoad || this.isAnimating) return;\n\n // Resize when a primary panel is set\n if (this.primary) {\n this.shouldAnimate = false;\n this.position = this.pixelsToPercentage(this.cachedPositionInPixels);\n requestAnimationFrame(() => (this.shouldAnimate = true));\n }\n };\n\n componentDidLoad(): void {\n if (this.positionInPixels) this.handlePositionInPixelsChange();\n setTimeout(() => (this.didLoad = true));\n }\n\n connectedCallback() {\n this.cachedPositionInPixels = this.percentageToPixels(this.position);\n this.attachRO();\n }\n\n disconnectedCallback() {\n this.detachRO();\n }\n\n componentDidRender(): void {\n // bit hacky ... because we use getter / setter for position, there's a render *before* `position` is passed in via attribute\n // if we set a default position in the class, this causes the divider to jump (from default to user set position)\n // so - wait a render, see if there's a position passed in via attribute, *then* set default if not\n requestAnimationFrame(() => {\n if (typeof this.position === 'undefined') {\n this.position = 50;\n }\n });\n }\n\n render() {\n if (typeof this.position === 'undefined') return;\n const styles: { gridTemplateRows?: string; gridTemplateColumns?: string } =\n {};\n const gridTemplate = this.vertical\n ? 'gridTemplateRows'\n : 'gridTemplateColumns';\n const primary = `\n clamp(\n 0%,\n clamp(\n var(--min),\n ${this.position}% - var(--divider-width) / 2,\n var(--max)\n ),\n calc(100% - var(--divider-width))\n )\n `;\n const secondary = 'auto';\n\n if (this.primary === 'end') {\n styles[gridTemplate] = `${secondary} var(--divider-width) ${primary}`;\n } else {\n styles[gridTemplate] = `${primary} var(--divider-width) ${secondary}`;\n }\n\n return (\n <Host style={styles}>\n <div part=\"panel start\" class=\"start\">\n <slot name=\"start\"></slot>\n </div>\n <div\n part=\"divider\"\n class=\"divider\"\n tabindex={this.disabled ? undefined : '0'}\n role=\"separator\"\n aria-label=\"Resize\"\n onKeyDown={this.handleKeyDown}\n onMouseDown={this.handleDrag}\n onTouchStart={this.handleDrag}\n >\n <slot name=\"handle\">\n {!this.disabled && this.vertical ? (\n <nano-icon slot=\"handle\" name=\"solid/grip-lines\" />\n ) : (\n <nano-icon slot=\"handle\" name=\"solid/grip-lines-vertical\" />\n )}\n </slot>\n </div>\n <div part=\"panel end\" class=\"end\">\n <slot name=\"end\"></slot>\n </div>\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["src/utils/drag.ts","src/components/split-pane/split-pane.scss?tag=nano-split-pane&encapsulation=shadow","src/components/split-pane/split-pane.tsx"],"names":["drag","container","onMove","move","pointerEvent","dims","getBoundingClientRect","defaultView","ownerDocument","offsetX","left","pageXOffset","offsetY","top","pageYOffset","x","pageX","y","pageY","stop","document","removeEventListener","addEventListener","passive","splitPaneCss","SplitPane","[object Object]","hostRef","this","isAnimating","didLoad","_shouldAnimate","handleDrag","e","disabled","preventDefault","host","newPositionInPixels","vertical","nanoDragging","emit","primary","size","snap","snaps","split","forEach","value","snapPoint","endsWith","parseFloat","snapThreshold","shouldAnimate","position","clamp","pixelsToPercentage","requestAnimationFrame","handleKeyDown","event","includes","key","newPosition","incr","shiftKey","handleResize","cachedPositionInPixels","handlePositionChange","debounce","bind","width","height","sa","_position","pos","Math","min","max","isNaN","animationDuration","animatePosition","percentageToPixels","positionInPixels","nanoReposition","end","duration","fps","start","distance","time","easeInOutQuad","t","s","d","go","detachRO","ro","ResizeObserver","observe","unobserve","undefined","handlePositionInPixelsChange","setTimeout","attachRO","styles","gridTemplate","secondary","h","Host","style","part","class","name","tabindex","role","aria-label","onKeyDown","onMouseDown","onTouchStart","slot"],"mappings":"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","sourcesContent":["export function drag(\n container: HTMLElement,\n onMove: (x: number, y: number) => void\n) {\n function move(pointerEvent: PointerEvent) {\n const dims = container.getBoundingClientRect();\n const defaultView = container.ownerDocument.defaultView!;\n const offsetX = dims.left + defaultView.pageXOffset;\n const offsetY = dims.top + defaultView.pageYOffset;\n const x = pointerEvent.pageX - offsetX;\n const y = pointerEvent.pageY - offsetY;\n\n onMove(x, y);\n }\n\n function stop() {\n document.removeEventListener('pointermove', move);\n document.removeEventListener('pointerup', stop);\n }\n\n document.addEventListener('pointermove', move, { passive: true });\n document.addEventListener('pointerup', stop);\n}\n","@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/components';\n@import '../../global/style/nano-theme/form';\n\n:host {\n /**\n * @prop --divider-width: The width of the visible divider. Default 4px.\n * @prop --divider-hit-area: The invisible region around the divider where dragging can occur. This is\n * usually wider than the divider to facilitate easier dragging. Default 12px.\n * @prop --min: The minimum allowed size of the primary panel. Default 0.\n * @prop --max: The maximum allowed size of the primary panel. Default 100%.\n * @prop --background-color: Handle background. Default #{map.get($colors, lightgrey)}.\n * @prop --content-color: Handle color. Default #{map.get($colors, dimgrey)}.\n */\n --divider-width: 12px;\n --divider-hit-area: 14px;\n --min: 0%;\n --max: 100%;\n --background-color: #{map.get($colors, lightgrey)};\n --content-color: #{map.get($colors, dimgrey)};\n\n display: grid;\n}\n\n.start,\n.end {\n overflow: hidden;\n}\n\n.divider {\n flex: 0 0 var(--divider-width);\n display: flex;\n position: relative;\n align-items: center;\n justify-content: center;\n background-color: var(--background-color);\n color: var(--content-color);\n z-index: 1;\n font-size: 0.8rem;\n}\n\n.divider:focus {\n outline: none;\n}\n\n:host(:not([disabled])) .divider:focus-visible {\n background-color: #{$control-focus-color};\n}\n\n:host([disabled]) .divider {\n cursor: not-allowed;\n}\n\n/* Horizontal */\n:host(:not([vertical], [disabled])) .divider {\n cursor: col-resize;\n}\n\n:host(:not([vertical])) .divider::after {\n display: flex;\n content: '';\n position: absolute;\n block-size: 100%;\n inset-inline-start: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2);\n inline-size: var(--divider-hit-area);\n}\n\n/* Vertical */\n:host([vertical]) {\n flex-direction: column;\n}\n\n:host([vertical]:not([disabled])) .divider {\n cursor: row-resize;\n}\n\n:host([vertical]) .divider::after {\n content: '';\n position: absolute;\n inline-size: 100%;\n inset-block-start: calc(var(--divider-hit-area) / -2 + var(--divider-width) / 2);\n block-size: var(--divider-hit-area);\n}\n","import {\n Prop,\n Component,\n Watch,\n Event,\n EventEmitter,\n ComponentInterface,\n Element,\n Host,\n h,\n Method,\n} from '@stencil/core';\nimport { drag } from '../../utils/drag';\nimport { clamp } from '../../utils/math';\nimport { debounce } from '../../utils/throttle';\n\n/**\n * Split panes display two adjacent panels, allowing the user to reposition them.\n *\n * @part start - The start panel.\n * @part end - The end panel.\n * @part panel - Targets both the start and end panels.\n * @part divider - The divider that separates the start and end panels.\n *\n * @slot start - The start panel.\n * @slot end - The end panel.\n * @slot handle - An optional handle to render at the center of the divider.\n */\n@Component({\n tag: 'nano-split-pane',\n styleUrl: 'split-pane.scss',\n shadow: true,\n})\nexport class SplitPane implements ComponentInterface {\n @Element() host: HTMLNanoSplitPaneElement;\n private cachedPositionInPixels: number;\n private ro: ResizeObserver;\n private isAnimating = false;\n private didLoad = false;\n\n private get size() {\n const { width, height } = this.host.getBoundingClientRect();\n return this.vertical ? height : width;\n }\n\n private get shouldAnimate() {\n return this.didLoad && this._shouldAnimate;\n }\n private set shouldAnimate(sa: boolean) {\n this._shouldAnimate = sa;\n }\n private _shouldAnimate: boolean = true;\n\n constructor() {\n this.handlePositionChange = debounce(\n this.handlePositionChange.bind(this),\n 100\n );\n }\n\n /**\n * The current position of the divider from the primary panel's edge\n * as a percentage 0-100. Defaults to 50% of the container's initial size.\n */\n @Prop()\n get position() {\n return this._position;\n }\n set position(pos: number) {\n // override too high / low\n pos = Math.min(Math.max(pos, 0), 100);\n if (isNaN(pos) || pos === this._position) return;\n\n if (\n this.shouldAnimate &&\n this.animationDuration > 0 &&\n !isNaN(this.position)\n ) {\n this.animatePosition(pos);\n return;\n }\n this._position = pos;\n }\n private _position: number;\n\n // eslint-disable-next-line @stencil/no-unused-watch\n @Watch('position')\n handlePositionChange() {\n this.cachedPositionInPixels = this.percentageToPixels(this.position);\n this.positionInPixels = this.percentageToPixels(this.position);\n this.nanoReposition.emit();\n }\n\n /**\n * The current position of the divider from the primary panel's edge in pixels.\n */\n @Prop({ mutable: true }) positionInPixels: number;\n\n @Watch('positionInPixels')\n handlePositionInPixelsChange() {\n this.position = this.pixelsToPercentage(this.positionInPixels);\n }\n\n /** Draws the split panel in a vertical orientation with the start and end panels stacked. */\n @Prop({ reflect: true }) vertical = false;\n\n /** Disables resizing. Note that the position may still change as a result of resizing the host element. */\n @Prop({ reflect: true }) disabled = false;\n\n /**\n * If no primary panel is designated, both panels will resize proportionally when the host element is resized. If a\n * primary panel is designated, it will maintain its size and the other panel will grow or shrink as needed when the\n * host element is resized.\n */\n @Prop() primary?: 'start' | 'end';\n\n /**\n * One or more space-separated values at which the divider should snap. Values can be in pixels or percentages, e.g.\n * `\"100px 50%\"`.\n */\n @Prop() snap?: string;\n\n /** How close the divider must be to a snap point until snapping occurs. */\n @Prop() snapThreshold = 12;\n\n /** When changing `position` via property, the pane will animate into position. Make `animationDuration` 0 to disable. */\n @Prop() animationDuration = 0.6;\n\n /** Emitted when the divider's position changes. */\n @Event() nanoReposition: EventEmitter;\n\n /** Emitted when the divider is being dragged. */\n @Event() nanoDragging: EventEmitter<number>;\n\n /** Utility to convert % to pixels */\n @Method()\n async getPercentageToPixels(value: number) {\n return this.percentageToPixels(value);\n }\n\n /** Utility to convert pixels to % (`position`) */\n @Method()\n async getPixelsToPercentage(value: number) {\n return this.pixelsToPercentage(value);\n }\n\n // Private logic\n\n private animatePosition(end: number) {\n if (this.isAnimating) return;\n\n const duration = this.animationDuration; // seconds\n const fps = 60;\n const start = this.position;\n const distance = end - start;\n\n let position = start;\n let time = 0;\n\n function easeInOutQuad(t: number, s: number, e: number, d: number) {\n if ((t /= d / 2) < 1) return (e / 2) * t * t + s;\n else return (-e / 2) * (--t * (t - 2) - 1) + s;\n }\n\n const go = () => {\n time += 1 / fps;\n position = easeInOutQuad(time, start, distance, duration);\n\n if (\n (end > start && position >= end) ||\n (end < start && position <= end)\n ) {\n this.position = end;\n this.shouldAnimate = true;\n this.isAnimating = false;\n return;\n }\n this.position = position;\n requestAnimationFrame(go);\n };\n\n this.shouldAnimate = false;\n this.isAnimating = true;\n requestAnimationFrame(go);\n }\n\n private percentageToPixels(value: number) {\n return this.size * (value / 100);\n }\n\n private pixelsToPercentage(value: number) {\n return (value / this.size) * 100;\n }\n\n private attachRO() {\n this.detachRO();\n this.ro = new ResizeObserver(() => this.handleResize());\n this.ro.observe(this.host);\n }\n\n private detachRO() {\n if (!this.ro) return;\n this.ro.unobserve(this.host);\n this.ro = undefined;\n }\n\n // Event handlers\n\n private handleDrag = (e: Event) => {\n if (this.disabled) {\n return;\n }\n\n // Prevent text selection when dragging\n e.preventDefault();\n\n drag(this.host, (x, y) => {\n let newPositionInPixels = this.vertical ? y : x;\n\n this.nanoDragging.emit(newPositionInPixels);\n\n // Flip for end panels\n if (this.primary === 'end') {\n newPositionInPixels = this.size - newPositionInPixels;\n }\n\n // Check snap points\n if (this.snap) {\n const snaps = this.snap.split(' ');\n\n snaps.forEach((value) => {\n let snapPoint: number;\n\n if (value.endsWith('%')) {\n snapPoint = this.size * (parseFloat(value) / 100);\n } else {\n snapPoint = parseFloat(value);\n }\n\n if (\n newPositionInPixels >= snapPoint - this.snapThreshold &&\n newPositionInPixels <= snapPoint + this.snapThreshold\n ) {\n newPositionInPixels = snapPoint;\n }\n });\n }\n this.shouldAnimate = false;\n this.position = clamp(\n this.pixelsToPercentage(newPositionInPixels),\n 0,\n 100\n );\n requestAnimationFrame(() => (this.shouldAnimate = true));\n });\n };\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (this.disabled) {\n return;\n }\n\n if (\n [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n let newPosition = this.position;\n const incr =\n (event.shiftKey ? 10 : 1) * (this.primary === 'end' ? -1 : 1);\n\n event.preventDefault();\n\n if (\n (event.key === 'ArrowLeft' && !this.vertical) ||\n (event.key === 'ArrowUp' && this.vertical)\n ) {\n newPosition -= incr;\n }\n\n if (\n (event.key === 'ArrowRight' && !this.vertical) ||\n (event.key === 'ArrowDown' && this.vertical)\n ) {\n newPosition += incr;\n }\n\n if (event.key === 'Home') {\n newPosition = this.primary === 'end' ? 100 : 0;\n }\n\n if (event.key === 'End') {\n newPosition = this.primary === 'end' ? 0 : 100;\n }\n\n this.shouldAnimate = false;\n\n this.position = clamp(newPosition, 0, 100);\n requestAnimationFrame(() => (this.shouldAnimate = true));\n }\n };\n\n private handleResize = () => {\n if (!this.didLoad || this.isAnimating) return;\n\n // Resize when a primary panel is set\n if (this.primary) {\n this.shouldAnimate = false;\n this.position = this.pixelsToPercentage(this.cachedPositionInPixels);\n requestAnimationFrame(() => (this.shouldAnimate = true));\n }\n };\n\n componentDidLoad(): void {\n if (this.positionInPixels) this.handlePositionInPixelsChange();\n setTimeout(() => (this.didLoad = true));\n }\n\n connectedCallback() {\n this.cachedPositionInPixels = this.percentageToPixels(this.position);\n this.attachRO();\n }\n\n disconnectedCallback() {\n this.detachRO();\n }\n\n componentDidRender(): void {\n // bit hacky ... because we use getter / setter for position, there's a render *before* `position` is passed in via attribute\n // if we set a default position in the class, this causes the divider to jump (from default to user set position)\n // so - wait a render, see if there's a position passed in via attribute, *then* set default if not\n requestAnimationFrame(() => {\n if (typeof this.position === 'undefined') {\n this.position = 50;\n }\n });\n }\n\n render() {\n if (typeof this.position === 'undefined') return;\n const styles: { gridTemplateRows?: string; gridTemplateColumns?: string } =\n {};\n const gridTemplate = this.vertical\n ? 'gridTemplateRows'\n : 'gridTemplateColumns';\n const primary = `\n clamp(\n 0%,\n clamp(\n var(--min),\n ${this.position}% - var(--divider-width) / 2,\n var(--max)\n ),\n calc(100% - var(--divider-width))\n )\n `;\n const secondary = 'auto';\n\n if (this.primary === 'end') {\n styles[gridTemplate] = `${secondary} var(--divider-width) ${primary}`;\n } else {\n styles[gridTemplate] = `${primary} var(--divider-width) ${secondary}`;\n }\n\n return (\n <Host style={styles}>\n <div part=\"panel start\" class=\"start\">\n <slot name=\"start\"></slot>\n </div>\n <div\n part=\"divider\"\n class=\"divider\"\n tabindex={this.disabled ? undefined : '0'}\n role=\"separator\"\n aria-label=\"Resize\"\n onKeyDown={this.handleKeyDown}\n onMouseDown={this.handleDrag}\n onTouchStart={this.handleDrag}\n >\n <slot name=\"handle\">\n {!this.disabled && this.vertical ? (\n <nano-icon slot=\"handle\" name=\"solid/grip-lines\" />\n ) : (\n <nano-icon slot=\"handle\" name=\"solid/grip-lines-vertical\" />\n )}\n </slot>\n </div>\n <div part=\"panel end\" class=\"end\">\n <slot name=\"end\"></slot>\n </div>\n </Host>\n );\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /*!
2
+ * Web Components for Nanopore digital Web Apps
3
+ */
4
+ import{r as t,c as i,h as e,a as s,g as n}from"./p-1fe12320.js";import{p as a,a as o,c as h}from"./p-15a60f7e.js";import{c as d}from"./p-7b3638b7.js";const r=".sc-nano-date-input-h{box-sizing:border-box}*.sc-nano-date-input,*.sc-nano-date-input::before,*.sc-nano-date-input::after{box-sizing:border-box}[hidden].sc-nano-date-input{display:none !important}.sc-nano-date-input-h{display:inline-block;inline-size:100%;--focus-shadow:var(--nano-control-focus-shadow, 0 0 0 0.1875rem var(--nano-control-focus-color, rgba(144, 198, 231, 0.8)));--open-btn-color:var(--nano-button-color, #f0efed);--open-btn-border:none;--close-btn-color:var(--nano-button-color, #f0efed);--picker-base-size:16px}.nano-color.sc-nano-date-input-h{--focus-shadow:0 0 0 0.1875rem rgba(var(--nano-color-tint-rgb), 0.56)}nano-icon.sc-nano-date-input{pointer-events:none}.date-field.sc-nano-date-input{display:flex;flex-direction:column;position:relative}.date-field__dropdown.sc-nano-date-input{--padding:0;--overflow:visible;padding:0 !important;inline-size:0 !important;inline-size:100%;z-index:var(--nano-layer-index-dropdown, 300) !important}.date-field__close-bar.sc-nano-date-input{align-items:center;display:flex;justify-content:space-between;text-overflow:ellipsis;white-space:nowrap;border:0;margin:0;overflow:visible;padding:0;position:absolute;inset-inline-end:-8px;inset-block-start:-8px;inline-size:auto;z-index:1}.date-field__open.sc-nano-date-input{background:var(--open-btn-color);border:var(--open-btn-border);margin:0;-webkit-appearance:none;appearance:none}.date-field__open.sc-nano-date-input:focus{box-shadow:var(--focus-shadow);outline:none}.date-field__close.sc-nano-date-input{-webkit-appearance:none;align-items:center;appearance:none;background:var(--close-btn-color);border:0;border-radius:50%;cursor:pointer;display:flex;block-size:24px;justify-content:center;padding:0;inline-size:24px}@media (min-width: 36em){.date-field__close.sc-nano-date-input{opacity:0}}.date-field__close.sc-nano-date-input:focus{box-shadow:var(--focus-shadow);outline:none}@media (min-width: 36em){.date-field__close.sc-nano-date-input:focus{opacity:1}}.date-field__close.sc-nano-date-input nano-icon.sc-nano-date-input{margin-block:0;margin-inline:auto}.date-field.sc-nano-date-input nano-date-picker.sc-nano-date-input{font-size:var(--picker-base-size)}.vhidden.sc-nano-date-input{clip:rect(1px, 1px, 1px, 1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);block-size:1px;inline-size:1px;margin:-1px;overflow:hidden;padding:0;position:absolute}";const l={d:"(\\d{1,2})",m:"(\\d{1,2})",y:"(\\d{4})"};let c=0;const u=class{constructor(e){t(this,e);this.nanoChange=i(this,"nanoChange",7);this.nanoValidate=i(this,"nanoValidate",7);this.directInput=false;this.dateOrderIndeces={d:0,m:1,y:3};this.inputId=`nano-input-${c++}`;this.locale=window.navigator.languages||window.navigator.language||undefined;this._dropDownConfig={};this.onInputChange=t=>{t.stopPropagation();this.setValue(t.target.value)};this.onInputValidate=t=>{t.stopPropagation();this._invalid=!t.detail.isValid;this.nanoValidate.emit({isValid:t.detail.isValid,errorMessage:t.detail.errorMessage,originalEvent:t.detail.originalEvent})};this.onInputKey=()=>{this.directInput=true};this.onDatePicked=t=>{this.directInput=false;this.value=t.detail.value;if(this.closeAfterPicked)this.pickerOpen=false};this.onDropdownHide=()=>{setTimeout((t=>this.pickerOpen=false),200);setTimeout((t=>this.trigger.focus()),50)};this.onDropdownShow=()=>{setTimeout((t=>{this.pickerEle.setFocus(false,this.pickerOpenSource==="key");this.pickerOpenSource=null}),200)};this.onTriggerClick=()=>{if(!this.pickerOpen){this.pickerOpen=true;this.pickerOpenSource="mouse"}};this.onTriggerKey=t=>{if([" ","Enter"].includes(t.key)){if(!this.pickerOpen){this.pickerOpen=true;this.pickerOpenSource="key"}}};this.onCloseClick=()=>{if(this.pickerOpen)this.pickerOpen=false};this.onCloseKeyDown=t=>{if(t.key==="Tab"&&t.shiftKey){this.pickerEle.setFocus(true);t.preventDefault()}if(t.key===" "||t.key==="Enter"){if(this.pickerOpen)this.pickerOpen=false}};this.pattern=undefined;this.inputValue=undefined;this._invalid=false;this.helperText=true;this.helperTextFormat={year:"numeric",month:"long",day:"numeric"};this.floatLabel=false;this.name=this.inputId;this.readonly=false;this.size=undefined;this.form=undefined;this.firstDayOfWeek=undefined;this.localization=undefined;this.disabled=false;this.color=undefined;this.autofocus=false;this.clearInput=false;this.label=undefined;this.placeholder=undefined;this.value="";this.validateOn="submitThenDirty";this.showInlineError=true;this.dateOrder="dmy";this.required=false;this.min=undefined;this.max=undefined;this.hideLabel=false;this.picker=true;this.initialPickerDate=undefined;this.pickerOpen=false;this.closeAfterPicked=true;this.isDateDisabled=()=>false}get invalid(){return this._invalid}get validityMessage(){if(!this.input)return"";return this.input.validityMessage}handleValueChange(){if(!this.directInput)this.inputValue=this.formatIsoDate(this.value);setTimeout((()=>{this.nanoChange.emit({value:this.value,date:a(this.value)})}),20);this.directInput=false}handleDateOrderChange(){this.setDatePattern()}testDateValidity(){const t=a(this.value);let i,e,s="";if(this.value&&t){if(this.min&&(i=a(this.min))&&t<i){s="Date below the minimum: "+i.toLocaleDateString(this.locale,this.helperTextFormat)}if(this.max&&(e=a(this.max))&&t>e){s="Date above the maximum: "+e.toLocaleDateString(this.locale,this.helperTextFormat)}if(this.isDateDisabled(t)){s="Date selected is disabled."}}requestAnimationFrame((async i=>{if(!this.input)return;const e=await this.input.getInputElement();if(this.value.length&&!t)s="Please enter a valid date";e.setCustomValidity(s);if(this.input.validateOn==="dirty"){this.input.showError(s)}}))}handlePickerOpenChange(){this.dropdown.open=this.pickerOpen}get dropDownConfig(){return this._dropDownConfig}set dropDownConfig(t){this._dropDownConfig={...this._dropDownConfig,...t}}get dateValue(){return a(this.value)}async reportValidity(t){const i=await this.input.reportValidity(t);if(i.isValid&&t)this.testDateValidity();return await this.input.reportValidity(t)}async setFocus(){if(this.input)this.input.setFocus()}async getInputElement(){return await this.input.getInputElement()}async showError(t){if(!this.input)return;this.input.showError(t)}setDatePattern(){const t=[];const i=[];Array.from(this.dateOrder).map(((e,s)=>{t.push(l[e]);this.dateOrderIndeces[e]=s;i.push(e==="y"?"yyyy":e+e)}));this.pattern=t.join("\\W+");if(!this.placeholder&&this.placeholder!=="false")this.placeholder=i.join(" ")}formatIsoDate(t){const i=[];Array.from("ymd").map((t=>i.push(l[t])));const e=t.match(new RegExp(i.join("\\W+")));if(!e)return"";const s=[];s[this.dateOrderIndeces.d]=e[3];s[this.dateOrderIndeces.m]=e[2];s[this.dateOrderIndeces.y]=e[1];return s.join(" ")}setValue(t){const i=t.match(new RegExp(this.pattern));if(!i){this.value=t;return}let e=h(i[this.dateOrderIndeces.y+1],i[this.dateOrderIndeces.m+1],i[this.dateOrderIndeces.d+1]);if(!e){e=new Date(t);if(!e){this.value=t;return}}const s=o(e);this.value=s;return s}connectedCallback(){this.setDatePattern();this.handleValueChange()}componentDidLoad(){if(!this.pickerCloseBtn||!this.picker)return;this.pickerEle.firstFocusEle=this.pickerCloseBtn;this.dropdown.tetherTo=this.trigger;setTimeout((t=>this.handlePickerOpenChange()),300)}render(){this.locale=navigator.languages||navigator.language||undefined;this.dropDownConfig.placement=this.dropDownConfig.placement||"bottom-end";if(this.host.ownerDocument.dir==="rtl"){this.dropDownConfig.placement.replace("start","end")}if(this.trigger)this.dropDownConfig.tetherTo=this.trigger;const t=a(this.value);const i=!!this.host.querySelector('[slot="helper"]');return e(s,{class:{...d(this.color)}},e("div",{class:"date-field"},e("nano-input",{class:"date-field__input",slot:"trigger",required:this.required||undefined,showInlineError:this.showInlineError,validateOn:this.validateOn,placeholder:this.placeholder!=="false"?this.placeholder:undefined,pattern:this.pattern,label:this.label,disabled:this.disabled||undefined,color:this.color||undefined,autofocus:this.autofocus||undefined,clearInput:this.clearInput||undefined,onNanoChange:this.onInputChange,onNanoInput:this.onInputKey,onNanoValidate:this.onInputValidate,name:"",form:this.form||undefined,size:this.size||undefined,readonly:this.readonly,value:this.inputValue,ref:t=>this.input=t,floatLabel:this.floatLabel,hideLabel:this.hideLabel,inputmode:"numeric",part:"input"},e("slot",{name:"start",slot:"start"}),e("slot",{name:"label"}),e("slot",{name:"end",slot:"end"}),this.picker&&[e("button",{slot:"end",class:"date-field__open",type:"button",onKeyDown:this.onTriggerKey,onClick:this.onTriggerClick,ref:t=>this.trigger=t,disabled:this.disabled||this.readonly},e("nano-icon",{name:"light/calendar-alt"})),e("nano-dropdown",{slot:"end",onNanoHide:this.onDropdownHide,onNanoShow:this.onDropdownShow,dialogTitle:"Choose a date",class:"date-field__dropdown",ref:t=>this.dropdown=t,...this.dropDownConfig,part:"dropdown"},e("div",null,e("div",{class:"date-field__close-bar"},e("button",{class:"date-field__close",type:"button",onMouseDown:this.onCloseClick,onKeyDown:this.onCloseKeyDown,ref:t=>this.pickerCloseBtn=t},e("nano-icon",{name:"light/times"}),e("span",{class:"vhidden"},"Close window"))),e("nano-date-picker",{isDateDisabled:this.isDateDisabled,onNanoDatePicked:this.onDatePicked,min:this.min||undefined,max:this.max||undefined,"is-modal":true,ref:t=>this.pickerEle=t,localization:this.localization,selectedDate:this.value||this.initialPickerDate,firstDayOfWeek:this.firstDayOfWeek,color:this.color||undefined,part:"date-picker"})))],(i||this.helperText||this.showInlineError)&&e("span",{slot:"helper"},e("span",{class:{vhidden:!!this.value.length}},e("slot",{name:"helper"})),this.helperText&&!!t&&e("span",null,t.toLocaleDateString(this.locale,this.helperTextFormat)))),e("input",{type:"hidden",value:this.value,name:this.name})))}get host(){return n(this)}static get watchers(){return{value:["handleValueChange","testDateValidity"],dateOrder:["handleDateOrderChange"],min:["testDateValidity"],max:["testDateValidity"],pickerOpen:["handlePickerOpenChange"]}}};u.style=r;export{u as nano_date_input};
5
+ //# sourceMappingURL=p-2cb4615b.entry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["src/components/date-input/date-input.scss?tag=nano-date-input&encapsulation=scoped","src/components/date-input/date-input.tsx"],"names":["dateInputCss","DateRegxps","d","m","y","inputIds","DateInput","this","directInput","dateOrderIndeces","inputId","locale","window","navigator","languages","language","undefined","_dropDownConfig","onInputChange","e","stopPropagation","setValue","target","value","onInputValidate","_invalid","detail","isValid","nanoValidate","emit","errorMessage","originalEvent","onInputKey","onDatePicked","closeAfterPicked","pickerOpen","onDropdownHide","setTimeout","_","trigger","focus","onDropdownShow","pickerEle","setFocus","pickerOpenSource","onTriggerClick","onTriggerKey","includes","key","onCloseClick","onCloseKeyDown","shiftKey","preventDefault","year","month","day","invalid","validityMessage","input","[object Object]","inputValue","formatIsoDate","nanoChange","date","parseISODate","setDatePattern","valueDate","min","max","error","toLocaleDateString","helperTextFormat","isDateDisabled","requestAnimationFrame","async","getInputElement","length","setCustomValidity","validateOn","showError","dropdown","open","dropDownConfig","ddc","dateValue","validateFirst","initValidity","reportValidity","testDateValidity","message","dateRegexOrdered","dateStrOrd","Array","from","dateOrder","map","datepart","i","push","pattern","join","placeholder","isoDate","matches","match","RegExp","formatted","createDate","Date","dateStr","printISODate","handleValueChange","pickerCloseBtn","picker","firstFocusEle","tetherTo","handlePickerOpenChange","placement","host","ownerDocument","dir","replace","hasHelperSlot","querySelector","h","Host","class","createColorClasses","color","slot","required","showInlineError","label","disabled","autofocus","clearInput","onNanoChange","onNanoInput","onNanoValidate","name","form","size","readonly","ref","floatLabel","hideLabel","inputmode","part","type","onKeyDown","onClick","onNanoHide","onNanoShow","dialogTitle","onMouseDown","pickerClose","onNanoDatePicked","is-modal","localization","selectedDate","initialPickerDate","firstDayOfWeek","helperText","vhidden"],"mappings":"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","sourcesContent":["@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/form';\n@import '../../global/style/nano-theme/layers';\n@import '../../global/style/utilities/globals';\n\n:host {\n /**\n * @prop --focus-shadow: defaults to #{$control-focus-style};\n * @prop --open-btn-color: defaults to #{$button-bg-color};\n * @prop --open-btn-border: defaults to none;\n * @prop --close-btn-color: defaults to #{map.get($colors, celsius)};\n * @prop --picker-base-size: Base font size of the date picker component. Defaults to 16px;\n */\n\n display: inline-block;\n inline-size: 100%;\n\n --focus-shadow: #{$control-focus-style};\n --open-btn-color: #{$button-bg-color};\n --open-btn-border: none;\n --close-btn-color: #{$button-bg-color};\n --picker-base-size: 16px;\n}\n\n:host(.nano-color) {\n --focus-shadow: #{$control-focus-size current-color(tint, 0.56)};\n}\n\nnano-icon {\n pointer-events: none;\n}\n\n.date-field {\n display: flex;\n flex-direction: column;\n position: relative;\n\n &__dropdown {\n --padding: 0;\n --overflow: visible;\n\n padding: 0 !important;\n inline-size: 0 !important;\n inline-size: 100%;\n z-index: $layer-index-dropdown !important;\n }\n\n &__close-bar {\n align-items: center;\n display: flex;\n justify-content: space-between;\n text-overflow: ellipsis;\n white-space: nowrap;\n border: 0;\n margin: 0;\n overflow: visible;\n padding: 0;\n position: absolute;\n inset-inline-end: -8px;\n inset-block-start: -8px;\n inline-size: auto;\n z-index: 1;\n }\n\n &__open {\n background: var(--open-btn-color);\n border: var(--open-btn-border);\n margin: 0;\n appearance: none;\n\n &:focus {\n box-shadow: var(--focus-shadow);\n outline: none;\n }\n }\n\n &__close {\n -webkit-appearance: none;\n align-items: center;\n appearance: none;\n background: var(--close-btn-color);\n border: 0;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n block-size: 24px;\n justify-content: center;\n padding: 0;\n inline-size: 24px;\n\n @media (min-width: 36em) {\n opacity: 0;\n }\n\n &:focus {\n box-shadow: var(--focus-shadow);\n outline: none;\n\n @media (min-width: 36em) {\n opacity: 1;\n }\n }\n\n nano-icon {\n margin-block: 0;\n margin-inline: auto;\n }\n }\n\n nano-date-picker {\n font-size: var(--picker-base-size);\n }\n}\n\n.vhidden {\n @include visually-hide();\n}\n","import {\n Component,\n ComponentInterface,\n Element,\n h,\n Prop,\n Watch,\n State,\n Event,\n EventEmitter,\n Host,\n Method,\n} from '@stencil/core';\nimport {\n createDate,\n DaysOfWeek,\n printISODate,\n parseISODate,\n} from '../../utils/date-utils';\n\nimport { createColorClasses } from '../../utils/theme';\nimport type {\n PickerChangeEvent,\n DateInputChangeEventDetail,\n Color,\n LocalDateOpts,\n DuetLocalizedText,\n ControlValidity,\n ControlValidityEventDetail,\n DateDisabledPredicate,\n NanoInputCustomEvent,\n InputChangeEventDetail,\n} from '../../interface';\nimport type { Dropdown } from '../dropdown/dropdown';\n\nconst DateRegxps = {\n d: '(\\\\d{1,2})',\n m: '(\\\\d{1,2})',\n y: '(\\\\d{4})',\n};\n\nlet inputIds = 0;\n\n/**\n * The date-input component combines `nano-dropdown`, `nano-input` and `nano-date-picker` components to make a fully featured date form field. It has specific options for localisation, date formatting and validation.\n *\n * @slot label - if you do not set a label attribute, you can use this slot for more complex markup\n * @slot helper - helper text to accompany the form field underneath.\n * @slot start - input start slot\n * @slot end - input end slot\n */\n@Component({\n tag: 'nano-date-input',\n styleUrl: 'date-input.scss',\n scoped: true,\n})\nexport class DateInput implements ComponentInterface {\n private pickerEle!: HTMLNanoDatePickerElement;\n private trigger!: HTMLButtonElement;\n private pickerCloseBtn!: HTMLButtonElement;\n private dropdown!: HTMLNanoDropdownElement;\n private input: HTMLNanoInputElement;\n private pickerOpenSource: 'key' | 'mouse';\n\n private directInput = false;\n private dateOrderIndeces = { d: 0, m: 1, y: 3 };\n private inputId = `nano-input-${inputIds++}`;\n private locale =\n (window.navigator.languages as string[]) ||\n window.navigator.language ||\n undefined;\n\n @Element() host: HTMLNanoDateInputElement;\n\n // Private state\n\n @State() pattern!: string;\n @State() inputValue: string;\n\n // Public Api / Prop\n\n /**\n * This will be true when the control is in an invalid state.\n * Validity is determined by the `required` prop. Or if custom validity message is set. @readonly\n */\n @Prop({ reflect: true })\n get invalid() {\n return this._invalid;\n }\n @State() _invalid = false;\n\n /**\n * Current validation message - if any. @readonly\n */\n @Prop()\n get validityMessage() {\n if (!this.input) return '';\n return this.input.validityMessage;\n }\n\n /**\n * Whether to show a long form, confirmation date string of the one currently entered\n */\n @Prop() helperText: boolean = true;\n\n /**\n * Options for the date string display. Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString.\n */\n @Prop() helperTextFormat: LocalDateOpts = {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n };\n\n /**\n * Enable floating label behaviour. Will disable placeholder if set.\n */\n @Prop() floatLabel: boolean = false;\n\n /**\n * The name of the control, which is submitted with the form data.\n */\n @Prop() name: string = this.inputId;\n\n /**\n * If `true`, the user cannot modify the value.\n */\n @Prop() readonly = false;\n\n /**\n * The initial size (number of characters) of the control.\n */\n @Prop() size?: number;\n\n /**\n * The form element to associate the select with (its form owner). Must be the id of a form.\n */\n @Prop() form?: string | null;\n\n /**\n * Which day is considered first day of the week? `0` for Sunday, `1` for Monday, etc.\n * Default is Monday.\n */\n @Prop() firstDayOfWeek?: DaysOfWeek;\n\n /**\n * Button labels, day names, month names, etc, used for localization.\n * Default is English.\n */\n @Prop() localization?: DuetLocalizedText;\n\n /**\n * If `true`, the user cannot interact with the input.\n */\n @Prop() disabled = false;\n\n /**\n * The color to use from the application's color palette.\n */\n @Prop() color?: Color;\n\n /**\n * This Boolean attribute lets you specify that a form control should have input focus when the page loads.\n */\n @Prop() autofocus = false;\n\n /**\n * If `true`, a clear icon will appear in the input when there is a value. Clicking it clears the input.\n */\n @Prop() clearInput = false;\n\n /**\n * String to place within a label element. Alternatively you may use a label slot.\n */\n @Prop() label?: string;\n\n /**\n * Instructional text that shows before the input has a value.\n * The pattern prop will be used to create a placeholder automatically if unused.\n */\n @Prop({ mutable: true }) placeholder: string;\n\n /**\n * Current value. Must be in IS0-8601 format: YYYY-MM-DD.\n */\n @Prop({ reflect: true, mutable: true }) value: string = '';\n\n @Watch('value')\n handleValueChange() {\n if (!this.directInput) this.inputValue = this.formatIsoDate(this.value);\n setTimeout(() => {\n this.nanoChange.emit({\n value: this.value,\n date: parseISODate(this.value),\n });\n }, 20);\n this.directInput = false;\n }\n\n /**\n * When should the field perform validation\n */\n @Prop() validateOn?: 'dirty' | 'submit' | 'submitThenDirty' =\n 'submitThenDirty';\n\n /**\n * Whether to show validation errors underneath input\n */\n @Prop({ reflect: true }) showInlineError = true;\n\n /**\n * The order of the date parts for entry and display.\n * e.g. dmy = dd mm yyyy\n */\n @Prop() dateOrder: 'dmy' | 'mdy' | 'ymd' | 'dym' = 'dmy';\n\n @Watch('dateOrder')\n handleDateOrderChange() {\n this.setDatePattern();\n }\n\n /**\n * If `true`, the user must fill in a value before submitting a form.\n */\n @Prop() required = false;\n\n /**\n * Minimum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD.\n * This setting can be used alone or together with the max property.\n */\n @Prop() min?: string;\n\n /**\n * Maximum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD.\n * This setting can be used alone or together with the min property.\n */\n @Prop() max?: string;\n\n /**\n * Visually hide the label - but make it accessible.\n */\n @Prop() hideLabel?: boolean = false;\n\n @Watch('min')\n @Watch('max')\n @Watch('value')\n testDateValidity() {\n const valueDate = parseISODate(this.value);\n\n let min: Date,\n max: Date,\n error: string = '';\n\n if (this.value && valueDate) {\n if (this.min && (min = parseISODate(this.min)) && valueDate < min) {\n error =\n 'Date below the minimum: ' +\n min.toLocaleDateString(this.locale, this.helperTextFormat);\n }\n if (this.max && (max = parseISODate(this.max)) && valueDate > max) {\n error =\n 'Date above the maximum: ' +\n max.toLocaleDateString(this.locale, this.helperTextFormat);\n }\n if (this.isDateDisabled(valueDate)) {\n error = 'Date selected is disabled.';\n }\n }\n\n requestAnimationFrame(async (_) => {\n if (!this.input) return;\n const input = await this.input.getInputElement();\n if (this.value.length && !valueDate) error = 'Please enter a valid date';\n\n input.setCustomValidity(error);\n if (this.input.validateOn === 'dirty') {\n this.input.showError(error);\n }\n });\n }\n\n /**\n * Show a date picker. Date pickers are not very useful\n * if the potential input is too far in the distance or past\n * e.g. Birthdays\n */\n @Prop() picker: boolean = true;\n\n /**\n * Initial picker date. Will be to `value` if set. Will be today's date if nothing set.\n * Must be in IS0-8601 format: YYYY-MM-DD.\n */\n @Prop() initialPickerDate?: string;\n\n /**\n * Set / read whether the picker is currently open.\n */\n @Prop({ reflect: true, mutable: true }) pickerOpen: boolean = false;\n\n @Watch('pickerOpen')\n handlePickerOpenChange() {\n this.dropdown.open = this.pickerOpen;\n }\n\n /**\n * Close the picker after a date is selected\n */\n @Prop() closeAfterPicked: boolean = true;\n\n /** nano-dropdown config options you can pass to the nested dropdown component */\n @Prop()\n get dropDownConfig() {\n return this._dropDownConfig;\n }\n set dropDownConfig(ddc: Partial<Dropdown>) {\n this._dropDownConfig = { ...this._dropDownConfig, ...ddc };\n }\n private _dropDownConfig: Partial<Dropdown> = {};\n\n /** @readonly get the value as a `Date` */\n @Prop()\n get dateValue() {\n return parseISODate(this.value);\n }\n\n /** Controls which days are disabled and therefore disallowed.\n * For example, this can be used to disallow selection of weekends.\n * @returns `false` for not disabled and `true` for disabled */\n @Prop() isDateDisabled: DateDisabledPredicate = () => false;\n\n // Event emitters\n\n /**\n * Event emitted when a date is selected.\n */\n @Event() nanoChange: EventEmitter<DateInputChangeEventDetail>;\n\n /**\n * Called when validation is performed (which depends on `validateOn`).\n * @returns event.detail: `{ isValid: boolean, errorMessage: string, originalEvent: Event }`.\n */\n @Event() nanoValidate: EventEmitter<ControlValidityEventDetail>;\n\n // Methods\n\n /**\n * Get the current state of the control.\n * @param validateFirst - perform validation first before reporting\n * @returns `{ isValid: boolean, errorMessage: string }`\n */\n @Method()\n async reportValidity(validateFirst: boolean): Promise<ControlValidity> {\n const initValidity = await this.input.reportValidity(validateFirst);\n if (initValidity.isValid && validateFirst) this.testDateValidity();\n return await this.input.reportValidity(validateFirst);\n }\n\n /**\n * Sets focus on the child `nano-input`.\n */\n @Method()\n async setFocus() {\n if (this.input) this.input.setFocus();\n }\n\n /**\n * Returns the native `<input>` element used under the hood.\n */\n @Method()\n async getInputElement() {\n return await this.input.getInputElement();\n }\n\n /**\n * Invalidate the field and show a custom error message. To clear the error you will need to re-call this method with an empty string.\n */\n @Method()\n async showError(message: string) {\n if (!this.input) return;\n this.input.showError(message);\n }\n\n // Event handlers\n\n private onInputChange = (e: NanoInputCustomEvent<InputChangeEventDetail>) => {\n e.stopPropagation();\n this.setValue(e.target.value);\n };\n\n private onInputValidate = (e: CustomEvent<ControlValidityEventDetail>) => {\n e.stopPropagation();\n this._invalid = !e.detail.isValid;\n\n this.nanoValidate.emit({\n isValid: e.detail.isValid,\n errorMessage: e.detail.errorMessage,\n originalEvent: e.detail.originalEvent,\n });\n };\n\n private onInputKey = () => {\n this.directInput = true;\n };\n\n private onDatePicked = (e: { detail: PickerChangeEvent }) => {\n this.directInput = false;\n this.value = e.detail.value;\n if (this.closeAfterPicked) this.pickerOpen = false;\n };\n\n private onDropdownHide = () => {\n setTimeout((_) => (this.pickerOpen = false), 200);\n setTimeout((_) => this.trigger.focus(), 50);\n };\n\n private onDropdownShow = () => {\n setTimeout((_) => {\n this.pickerEle.setFocus(false, this.pickerOpenSource === 'key');\n this.pickerOpenSource = null;\n }, 200);\n };\n\n private onTriggerClick = () => {\n if (!this.pickerOpen) {\n this.pickerOpen = true;\n this.pickerOpenSource = 'mouse';\n }\n };\n\n private onTriggerKey = (e: KeyboardEvent) => {\n if ([' ', 'Enter'].includes(e.key)) {\n if (!this.pickerOpen) {\n this.pickerOpen = true;\n this.pickerOpenSource = 'key';\n }\n }\n };\n\n private onCloseClick = () => {\n if (this.pickerOpen) this.pickerOpen = false;\n };\n\n private onCloseKeyDown = (e: KeyboardEvent) => {\n // this ensures focus is trapped inside the picker\n if (e.key === 'Tab' && e.shiftKey) {\n this.pickerEle.setFocus(true);\n e.preventDefault();\n }\n if (e.key === ' ' || e.key === 'Enter') {\n if (this.pickerOpen) this.pickerOpen = false;\n }\n };\n\n // Private logic\n\n // set the regexp input pattern and placeholder (if necessary)\n private setDatePattern() {\n const dateRegexOrdered = [];\n const dateStrOrd = [];\n Array.from(this.dateOrder).map((datepart, i) => {\n dateRegexOrdered.push(DateRegxps[datepart]);\n this.dateOrderIndeces[datepart] = i;\n dateStrOrd.push(datepart === 'y' ? 'yyyy' : datepart + datepart);\n });\n this.pattern = dateRegexOrdered.join('\\\\W+');\n\n if (!this.placeholder && this.placeholder !== 'false')\n this.placeholder = dateStrOrd.join(' ');\n }\n\n // set the public facing date string\n private formatIsoDate(isoDate: string) {\n const dateRegexOrdered = [];\n Array.from('ymd').map((datepart) =>\n dateRegexOrdered.push(DateRegxps[datepart])\n );\n const matches = isoDate.match(new RegExp(dateRegexOrdered.join('\\\\W+')));\n if (!matches) return '';\n\n const formatted = [];\n formatted[this.dateOrderIndeces.d] = matches[3];\n formatted[this.dateOrderIndeces.m] = matches[2];\n formatted[this.dateOrderIndeces.y] = matches[1];\n\n return formatted.join(' ');\n }\n\n // on manual user entry, set the value that will be sent with the form field\n private setValue(inputValue: string) {\n const matches = inputValue.match(new RegExp(this.pattern));\n\n // it's an invalid date, but we still need to set it\n if (!matches) {\n this.value = inputValue;\n return;\n }\n\n let date = createDate(\n matches[this.dateOrderIndeces.y + 1],\n matches[this.dateOrderIndeces.m + 1],\n matches[this.dateOrderIndeces.d + 1]\n );\n\n if (!date) {\n // last ditch attempt - see if the browser can get something\n date = new Date(inputValue);\n\n // it's definitely an invalid date, but set it anyway for validation messages\n if (!date) {\n this.value = inputValue;\n return;\n }\n }\n\n const dateStr = printISODate(date);\n this.value = dateStr;\n return dateStr;\n }\n\n connectedCallback() {\n this.setDatePattern();\n this.handleValueChange();\n }\n\n componentDidLoad() {\n if (!this.pickerCloseBtn || !this.picker) return;\n this.pickerEle.firstFocusEle = this.pickerCloseBtn;\n this.dropdown.tetherTo = this.trigger;\n setTimeout((_) => this.handlePickerOpenChange(), 300);\n }\n\n render() {\n this.locale =\n (navigator.languages as string[]) || navigator.language || undefined;\n\n this.dropDownConfig.placement =\n this.dropDownConfig.placement || 'bottom-end';\n\n if ((this.host.ownerDocument as Document).dir === 'rtl') {\n this.dropDownConfig.placement.replace('start', 'end');\n }\n if (this.trigger) this.dropDownConfig.tetherTo = this.trigger;\n\n const valueDate = parseISODate(this.value);\n const hasHelperSlot = !!this.host.querySelector('[slot=\"helper\"]');\n\n return (\n <Host class={{ ...createColorClasses(this.color) }}>\n <div class=\"date-field\">\n <nano-input\n class=\"date-field__input\"\n slot=\"trigger\"\n required={this.required || undefined}\n showInlineError={this.showInlineError}\n validateOn={this.validateOn}\n placeholder={\n this.placeholder !== 'false' ? this.placeholder : undefined\n }\n pattern={this.pattern}\n label={this.label}\n disabled={this.disabled || undefined}\n color={this.color || undefined}\n autofocus={this.autofocus || undefined}\n clearInput={this.clearInput || undefined}\n onNanoChange={this.onInputChange}\n onNanoInput={this.onInputKey}\n onNanoValidate={this.onInputValidate}\n name=\"\"\n form={this.form || undefined}\n size={this.size || undefined}\n readonly={this.readonly}\n value={this.inputValue}\n ref={(input) => (this.input = input)}\n floatLabel={this.floatLabel}\n hideLabel={this.hideLabel}\n inputmode={'numeric'}\n part=\"input\"\n >\n <slot name=\"start\" slot=\"start\" />\n <slot name=\"label\" />\n <slot name=\"end\" slot=\"end\" />\n {this.picker && [\n <button\n slot=\"end\"\n class=\"date-field__open\"\n type=\"button\"\n onKeyDown={this.onTriggerKey}\n onClick={this.onTriggerClick}\n ref={(trigger) => (this.trigger = trigger)}\n disabled={this.disabled || this.readonly}\n >\n <nano-icon name=\"light/calendar-alt\"></nano-icon>\n </button>,\n\n <nano-dropdown\n slot=\"end\"\n onNanoHide={this.onDropdownHide}\n onNanoShow={this.onDropdownShow}\n dialogTitle=\"Choose a date\"\n class=\"date-field__dropdown\"\n ref={(dropdown) => (this.dropdown = dropdown)}\n {...this.dropDownConfig}\n part=\"dropdown\"\n >\n <div>\n <div class=\"date-field__close-bar\">\n <button\n class=\"date-field__close\"\n type=\"button\"\n onMouseDown={this.onCloseClick}\n onKeyDown={this.onCloseKeyDown}\n ref={(pickerClose) => (this.pickerCloseBtn = pickerClose)}\n >\n <nano-icon name=\"light/times\"></nano-icon>\n <span class=\"vhidden\">Close window</span>\n </button>\n </div>\n <nano-date-picker\n isDateDisabled={this.isDateDisabled}\n onNanoDatePicked={this.onDatePicked}\n min={this.min || undefined}\n max={this.max || undefined}\n is-modal={true}\n ref={(picker) => (this.pickerEle = picker)}\n localization={this.localization}\n selectedDate={this.value || this.initialPickerDate}\n firstDayOfWeek={this.firstDayOfWeek}\n color={this.color || undefined}\n part=\"date-picker\"\n ></nano-date-picker>\n </div>\n </nano-dropdown>,\n ]}\n {(hasHelperSlot || this.helperText || this.showInlineError) && (\n <span slot=\"helper\">\n <span class={{ vhidden: !!this.value.length }}>\n <slot name=\"helper\" />\n </span>\n {this.helperText && !!valueDate && (\n <span>\n {valueDate.toLocaleDateString(\n this.locale,\n this.helperTextFormat\n )}\n </span>\n )}\n </span>\n )}\n </nano-input>\n <input type=\"hidden\" value={this.value} name={this.name} />\n </div>\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["src/components/date-input/date-input.scss?tag=nano-date-input&encapsulation=scoped","src/components/date-input/date-input.tsx"],"names":["dateInputCss","DateRegxps","d","m","y","inputIds","DateInput","this","directInput","dateOrderIndeces","inputId","locale","window","navigator","languages","language","undefined","_dropDownConfig","onInputChange","e","stopPropagation","setValue","target","value","onInputValidate","_invalid","detail","isValid","nanoValidate","emit","errorMessage","originalEvent","onInputKey","onDatePicked","closeAfterPicked","pickerOpen","onDropdownHide","setTimeout","_","trigger","focus","onDropdownShow","pickerEle","setFocus","pickerOpenSource","onTriggerClick","onTriggerKey","includes","key","onCloseClick","onCloseKeyDown","shiftKey","preventDefault","year","month","day","invalid","validityMessage","input","[object Object]","inputValue","formatIsoDate","nanoChange","date","parseISODate","setDatePattern","valueDate","min","max","error","toLocaleDateString","helperTextFormat","isDateDisabled","requestAnimationFrame","async","getInputElement","length","setCustomValidity","validateOn","showError","dropdown","open","dropDownConfig","ddc","dateValue","validateFirst","initValidity","reportValidity","testDateValidity","message","dateRegexOrdered","dateStrOrd","Array","from","dateOrder","map","datepart","i","push","pattern","join","placeholder","isoDate","matches","match","RegExp","formatted","createDate","Date","dateStr","printISODate","handleValueChange","pickerCloseBtn","picker","firstFocusEle","tetherTo","handlePickerOpenChange","placement","host","ownerDocument","dir","replace","hasHelperSlot","querySelector","h","Host","class","createColorClasses","color","slot","required","showInlineError","label","disabled","autofocus","clearInput","onNanoChange","onNanoInput","onNanoValidate","name","form","size","readonly","ref","floatLabel","hideLabel","inputmode","part","type","onKeyDown","onClick","onNanoHide","onNanoShow","dialogTitle","onMouseDown","pickerClose","onNanoDatePicked","is-modal","localization","selectedDate","initialPickerDate","firstDayOfWeek","helperText","vhidden"],"mappings":";;;sJAAA,MAAMA,EAAe,i0ECmCrB,MAAMC,EAAa,CACjBC,EAAG,aACHC,EAAG,aACHC,EAAG,YAGL,IAAIC,EAAW,QAeFC,EAAS,iHAQZC,KAAAC,YAAc,MACdD,KAAAE,iBAAmB,CAAEP,EAAG,EAAGC,EAAG,EAAGC,EAAG,GACpCG,KAAAG,QAAU,cAAcL,MACxBE,KAAAI,OACLC,OAAOC,UAAUC,WAClBF,OAAOC,UAAUE,UACjBC,UAuPMT,KAAAU,gBAAqC,GAmErCV,KAAAW,cAAiBC,IACvBA,EAAEC,kBACFb,KAAKc,SAASF,EAAEG,OAAOC,QAGjBhB,KAAAiB,gBAAmBL,IACzBA,EAAEC,kBACFb,KAAKkB,UAAYN,EAAEO,OAAOC,QAE1BpB,KAAKqB,aAAaC,KAAK,CACrBF,QAASR,EAAEO,OAAOC,QAClBG,aAAcX,EAAEO,OAAOI,aACvBC,cAAeZ,EAAEO,OAAOK,iBAIpBxB,KAAAyB,WAAa,KACnBzB,KAAKC,YAAc,MAGbD,KAAA0B,aAAgBd,IACtBZ,KAAKC,YAAc,MACnBD,KAAKgB,MAAQJ,EAAEO,OAAOH,MACtB,GAAIhB,KAAK2B,iBAAkB3B,KAAK4B,WAAa,OAGvC5B,KAAA6B,eAAiB,KACvBC,YAAYC,GAAO/B,KAAK4B,WAAa,OAAQ,KAC7CE,YAAYC,GAAM/B,KAAKgC,QAAQC,SAAS,KAGlCjC,KAAAkC,eAAiB,KACvBJ,YAAYC,IACV/B,KAAKmC,UAAUC,SAAS,MAAOpC,KAAKqC,mBAAqB,OACzDrC,KAAKqC,iBAAmB,OACvB,MAGGrC,KAAAsC,eAAiB,KACvB,IAAKtC,KAAK4B,WAAY,CACpB5B,KAAK4B,WAAa,KAClB5B,KAAKqC,iBAAmB,UAIpBrC,KAAAuC,aAAgB3B,IACtB,GAAI,CAAC,IAAK,SAAS4B,SAAS5B,EAAE6B,KAAM,CAClC,IAAKzC,KAAK4B,WAAY,CACpB5B,KAAK4B,WAAa,KAClB5B,KAAKqC,iBAAmB,SAKtBrC,KAAA0C,aAAe,KACrB,GAAI1C,KAAK4B,WAAY5B,KAAK4B,WAAa,OAGjC5B,KAAA2C,eAAkB/B,IAExB,GAAIA,EAAE6B,MAAQ,OAAS7B,EAAEgC,SAAU,CACjC5C,KAAKmC,UAAUC,SAAS,MACxBxB,EAAEiC,iBAEJ,GAAIjC,EAAE6B,MAAQ,KAAO7B,EAAE6B,MAAQ,QAAS,CACtC,GAAIzC,KAAK4B,WAAY5B,KAAK4B,WAAa,uEAxWvB,sBAcU,2BAKY,CACxCkB,KAAM,UACNC,MAAO,OACPC,IAAK,2BAMuB,gBAKPhD,KAAKG,sBAKT,sHA2BA,0CAUC,sBAKC,iEAgBmC,mBAkBtD,uCAKyC,oBAMQ,oBAUhC,2DAiBW,kBA6CJ,sDAWoC,4BAU1B,yBAqBY,IAAM,MAnPtD8C,cAEE,OAAOjD,KAAKkB,SAOdgC,sBAEE,IAAKlD,KAAKmD,MAAO,MAAO,GACxB,OAAOnD,KAAKmD,MAAMD,gBA2FpBE,oBACE,IAAKpD,KAAKC,YAAaD,KAAKqD,WAAarD,KAAKsD,cAActD,KAAKgB,OACjEc,YAAW,KACT9B,KAAKuD,WAAWjC,KAAK,CACnBN,MAAOhB,KAAKgB,MACZwC,KAAMC,EAAazD,KAAKgB,WAEzB,IACHhB,KAAKC,YAAc,MAqBrBmD,wBACEpD,KAAK0D,iBA4BPN,mBACE,MAAMO,EAAYF,EAAazD,KAAKgB,OAEpC,IAAI4C,EACFC,EACAC,EAAgB,GAElB,GAAI9D,KAAKgB,OAAS2C,EAAW,CAC3B,GAAI3D,KAAK4D,MAAQA,EAAMH,EAAazD,KAAK4D,OAASD,EAAYC,EAAK,CACjEE,EACE,2BACAF,EAAIG,mBAAmB/D,KAAKI,OAAQJ,KAAKgE,kBAE7C,GAAIhE,KAAK6D,MAAQA,EAAMJ,EAAazD,KAAK6D,OAASF,EAAYE,EAAK,CACjEC,EACE,2BACAD,EAAIE,mBAAmB/D,KAAKI,OAAQJ,KAAKgE,kBAE7C,GAAIhE,KAAKiE,eAAeN,GAAY,CAClCG,EAAQ,8BAIZI,uBAAsBC,MAAOpC,IAC3B,IAAK/B,KAAKmD,MAAO,OACjB,MAAMA,QAAcnD,KAAKmD,MAAMiB,kBAC/B,GAAIpE,KAAKgB,MAAMqD,SAAWV,EAAWG,EAAQ,4BAE7CX,EAAMmB,kBAAkBR,GACxB,GAAI9D,KAAKmD,MAAMoB,aAAe,QAAS,CACrCvE,KAAKmD,MAAMqB,UAAUV,OAwB3BV,yBACEpD,KAAKyE,SAASC,KAAO1E,KAAK4B,WAS5B+C,qBAEE,OAAO3E,KAAKU,gBAEdiE,mBAAmBC,GACjB5E,KAAKU,gBAAkB,IAAKV,KAAKU,mBAAoBkE,GAKvDC,gBAEE,OAAOpB,EAAazD,KAAKgB,OA6B3BoC,qBAAqB0B,GACnB,MAAMC,QAAqB/E,KAAKmD,MAAM6B,eAAeF,GACrD,GAAIC,EAAa3D,SAAW0D,EAAe9E,KAAKiF,mBAChD,aAAajF,KAAKmD,MAAM6B,eAAeF,GAOzC1B,iBACE,GAAIpD,KAAKmD,MAAOnD,KAAKmD,MAAMf,WAO7BgB,wBACE,aAAapD,KAAKmD,MAAMiB,kBAO1BhB,gBAAgB8B,GACd,IAAKlF,KAAKmD,MAAO,OACjBnD,KAAKmD,MAAMqB,UAAUU,GA6Ef9B,iBACN,MAAM+B,EAAmB,GACzB,MAAMC,EAAa,GACnBC,MAAMC,KAAKtF,KAAKuF,WAAWC,KAAI,CAACC,EAAUC,KACxCP,EAAiBQ,KAAKjG,EAAW+F,IACjCzF,KAAKE,iBAAiBuF,GAAYC,EAClCN,EAAWO,KAAKF,IAAa,IAAM,OAASA,EAAWA,MAEzDzF,KAAK4F,QAAUT,EAAiBU,KAAK,QAErC,IAAK7F,KAAK8F,aAAe9F,KAAK8F,cAAgB,QAC5C9F,KAAK8F,YAAcV,EAAWS,KAAK,KAI/BzC,cAAc2C,GACpB,MAAMZ,EAAmB,GACzBE,MAAMC,KAAK,OAAOE,KAAKC,GACrBN,EAAiBQ,KAAKjG,EAAW+F,MAEnC,MAAMO,EAAUD,EAAQE,MAAM,IAAIC,OAAOf,EAAiBU,KAAK,UAC/D,IAAKG,EAAS,MAAO,GAErB,MAAMG,EAAY,GAClBA,EAAUnG,KAAKE,iBAAiBP,GAAKqG,EAAQ,GAC7CG,EAAUnG,KAAKE,iBAAiBN,GAAKoG,EAAQ,GAC7CG,EAAUnG,KAAKE,iBAAiBL,GAAKmG,EAAQ,GAE7C,OAAOG,EAAUN,KAAK,KAIhBzC,SAASC,GACf,MAAM2C,EAAU3C,EAAW4C,MAAM,IAAIC,OAAOlG,KAAK4F,UAGjD,IAAKI,EAAS,CACZhG,KAAKgB,MAAQqC,EACb,OAGF,IAAIG,EAAO4C,EACTJ,EAAQhG,KAAKE,iBAAiBL,EAAI,GAClCmG,EAAQhG,KAAKE,iBAAiBN,EAAI,GAClCoG,EAAQhG,KAAKE,iBAAiBP,EAAI,IAGpC,IAAK6D,EAAM,CAETA,EAAO,IAAI6C,KAAKhD,GAGhB,IAAKG,EAAM,CACTxD,KAAKgB,MAAQqC,EACb,QAIJ,MAAMiD,EAAUC,EAAa/C,GAC7BxD,KAAKgB,MAAQsF,EACb,OAAOA,EAGTlD,oBACEpD,KAAK0D,iBACL1D,KAAKwG,oBAGPpD,mBACE,IAAKpD,KAAKyG,iBAAmBzG,KAAK0G,OAAQ,OAC1C1G,KAAKmC,UAAUwE,cAAgB3G,KAAKyG,eACpCzG,KAAKyE,SAASmC,SAAW5G,KAAKgC,QAC9BF,YAAYC,GAAM/B,KAAK6G,0BAA0B,KAGnDzD,SACEpD,KAAKI,OACFE,UAAUC,WAA0BD,UAAUE,UAAYC,UAE7DT,KAAK2E,eAAemC,UAClB9G,KAAK2E,eAAemC,WAAa,aAEnC,GAAK9G,KAAK+G,KAAKC,cAA2BC,MAAQ,MAAO,CACvDjH,KAAK2E,eAAemC,UAAUI,QAAQ,QAAS,OAEjD,GAAIlH,KAAKgC,QAAShC,KAAK2E,eAAeiC,SAAW5G,KAAKgC,QAEtD,MAAM2B,EAAYF,EAAazD,KAAKgB,OACpC,MAAMmG,IAAkBnH,KAAK+G,KAAKK,cAAc,mBAEhD,OACEC,EAACC,EAAI,CAACC,MAAO,IAAKC,EAAmBxH,KAAKyH,SACxCJ,EAAA,MAAA,CAAKE,MAAM,cACTF,EAAA,aAAA,CACEE,MAAM,oBACNG,KAAK,UACLC,SAAU3H,KAAK2H,UAAYlH,UAC3BmH,gBAAiB5H,KAAK4H,gBACtBrD,WAAYvE,KAAKuE,WACjBuB,YACE9F,KAAK8F,cAAgB,QAAU9F,KAAK8F,YAAcrF,UAEpDmF,QAAS5F,KAAK4F,QACdiC,MAAO7H,KAAK6H,MACZC,SAAU9H,KAAK8H,UAAYrH,UAC3BgH,MAAOzH,KAAKyH,OAAShH,UACrBsH,UAAW/H,KAAK+H,WAAatH,UAC7BuH,WAAYhI,KAAKgI,YAAcvH,UAC/BwH,aAAcjI,KAAKW,cACnBuH,YAAalI,KAAKyB,WAClB0G,eAAgBnI,KAAKiB,gBACrBmH,KAAK,GACLC,KAAMrI,KAAKqI,MAAQ5H,UACnB6H,KAAMtI,KAAKsI,MAAQ7H,UACnB8H,SAAUvI,KAAKuI,SACfvH,MAAOhB,KAAKqD,WACZmF,IAAMrF,GAAWnD,KAAKmD,MAAQA,EAC9BsF,WAAYzI,KAAKyI,WACjBC,UAAW1I,KAAK0I,UAChBC,UAAW,UACXC,KAAK,SAELvB,EAAA,OAAA,CAAMe,KAAK,QAAQV,KAAK,UACxBL,EAAA,OAAA,CAAMe,KAAK,UACXf,EAAA,OAAA,CAAMe,KAAK,MAAMV,KAAK,QACrB1H,KAAK0G,QAAU,CACdW,EAAA,SAAA,CACEK,KAAK,MACLH,MAAM,mBACNsB,KAAK,SACLC,UAAW9I,KAAKuC,aAChBwG,QAAS/I,KAAKsC,eACdkG,IAAMxG,GAAahC,KAAKgC,QAAUA,EAClC8F,SAAU9H,KAAK8H,UAAY9H,KAAKuI,UAEhClB,EAAA,YAAA,CAAWe,KAAK,wBAGlBf,EAAA,gBAAA,CACEK,KAAK,MACLsB,WAAYhJ,KAAK6B,eACjBoH,WAAYjJ,KAAKkC,eACjBgH,YAAY,gBACZ3B,MAAM,uBACNiB,IAAM/D,GAAczE,KAAKyE,SAAWA,KAChCzE,KAAK2E,eACTiE,KAAK,YAELvB,EAAA,MAAA,KACEA,EAAA,MAAA,CAAKE,MAAM,yBACTF,EAAA,SAAA,CACEE,MAAM,oBACNsB,KAAK,SACLM,YAAanJ,KAAK0C,aAClBoG,UAAW9I,KAAK2C,eAChB6F,IAAMY,GAAiBpJ,KAAKyG,eAAiB2C,GAE7C/B,EAAA,YAAA,CAAWe,KAAK,gBAChBf,EAAA,OAAA,CAAME,MAAM,WAAS,kBAGzBF,EAAA,mBAAA,CACEpD,eAAgBjE,KAAKiE,eACrBoF,iBAAkBrJ,KAAK0B,aACvBkC,IAAK5D,KAAK4D,KAAOnD,UACjBoD,IAAK7D,KAAK6D,KAAOpD,UAAS6I,WAChB,KACVd,IAAM9B,GAAY1G,KAAKmC,UAAYuE,EACnC6C,aAAcvJ,KAAKuJ,aACnBC,aAAcxJ,KAAKgB,OAAShB,KAAKyJ,kBACjCC,eAAgB1J,KAAK0J,eACrBjC,MAAOzH,KAAKyH,OAAShH,UACrBmI,KAAK,oBAKXzB,GAAiBnH,KAAK2J,YAAc3J,KAAK4H,kBACzCP,EAAA,OAAA,CAAMK,KAAK,UACTL,EAAA,OAAA,CAAME,MAAO,CAAEqC,UAAW5J,KAAKgB,MAAMqD,SACnCgD,EAAA,OAAA,CAAMe,KAAK,YAEZpI,KAAK2J,cAAgBhG,GACpB0D,EAAA,OAAA,KACG1D,EAAUI,mBACT/D,KAAKI,OACLJ,KAAKgE,qBAOjBqD,EAAA,QAAA,CAAOwB,KAAK,SAAS7H,MAAOhB,KAAKgB,MAAOoH,KAAMpI,KAAKoI","sourcesContent":["@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/form';\n@import '../../global/style/nano-theme/layers';\n@import '../../global/style/utilities/globals';\n\n:host {\n /**\n * @prop --focus-shadow: defaults to #{$control-focus-style};\n * @prop --open-btn-color: defaults to #{$button-bg-color};\n * @prop --open-btn-border: defaults to none;\n * @prop --close-btn-color: defaults to #{map.get($colors, celsius)};\n * @prop --picker-base-size: Base font size of the date picker component. Defaults to 16px;\n */\n\n display: inline-block;\n inline-size: 100%;\n\n --focus-shadow: #{$control-focus-style};\n --open-btn-color: #{$button-bg-color};\n --open-btn-border: none;\n --close-btn-color: #{$button-bg-color};\n --picker-base-size: 16px;\n}\n\n:host(.nano-color) {\n --focus-shadow: #{$control-focus-size current-color(tint, 0.56)};\n}\n\nnano-icon {\n pointer-events: none;\n}\n\n.date-field {\n display: flex;\n flex-direction: column;\n position: relative;\n\n &__dropdown {\n --padding: 0;\n --overflow: visible;\n\n padding: 0 !important;\n inline-size: 0 !important;\n inline-size: 100%;\n z-index: $layer-index-dropdown !important;\n }\n\n &__close-bar {\n align-items: center;\n display: flex;\n justify-content: space-between;\n text-overflow: ellipsis;\n white-space: nowrap;\n border: 0;\n margin: 0;\n overflow: visible;\n padding: 0;\n position: absolute;\n inset-inline-end: -8px;\n inset-block-start: -8px;\n inline-size: auto;\n z-index: 1;\n }\n\n &__open {\n background: var(--open-btn-color);\n border: var(--open-btn-border);\n margin: 0;\n appearance: none;\n\n &:focus {\n box-shadow: var(--focus-shadow);\n outline: none;\n }\n }\n\n &__close {\n -webkit-appearance: none;\n align-items: center;\n appearance: none;\n background: var(--close-btn-color);\n border: 0;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n block-size: 24px;\n justify-content: center;\n padding: 0;\n inline-size: 24px;\n\n @media (min-width: 36em) {\n opacity: 0;\n }\n\n &:focus {\n box-shadow: var(--focus-shadow);\n outline: none;\n\n @media (min-width: 36em) {\n opacity: 1;\n }\n }\n\n nano-icon {\n margin-block: 0;\n margin-inline: auto;\n }\n }\n\n nano-date-picker {\n font-size: var(--picker-base-size);\n }\n}\n\n.vhidden {\n @include visually-hide();\n}\n","import {\n Component,\n ComponentInterface,\n Element,\n h,\n Prop,\n Watch,\n State,\n Event,\n EventEmitter,\n Host,\n Method,\n} from '@stencil/core';\nimport {\n createDate,\n DaysOfWeek,\n printISODate,\n parseISODate,\n} from '../../utils/date-utils';\n\nimport { createColorClasses } from '../../utils/theme';\nimport type {\n PickerChangeEvent,\n DateInputChangeEventDetail,\n Color,\n LocalDateOpts,\n DuetLocalizedText,\n ControlValidity,\n ControlValidityEventDetail,\n DateDisabledPredicate,\n NanoInputCustomEvent,\n InputChangeEventDetail,\n} from '../../interface';\nimport type { Dropdown } from '../dropdown/dropdown';\n\nconst DateRegxps = {\n d: '(\\\\d{1,2})',\n m: '(\\\\d{1,2})',\n y: '(\\\\d{4})',\n};\n\nlet inputIds = 0;\n\n/**\n * The date-input component combines `nano-dropdown`, `nano-input` and `nano-date-picker` components to make a fully featured date form field. It has specific options for localisation, date formatting and validation.\n *\n * @slot label - if you do not set a label attribute, you can use this slot for more complex markup\n * @slot helper - helper text to accompany the form field underneath.\n * @slot start - input start slot\n * @slot end - input end slot\n */\n@Component({\n tag: 'nano-date-input',\n styleUrl: 'date-input.scss',\n scoped: true,\n})\nexport class DateInput implements ComponentInterface {\n private pickerEle!: HTMLNanoDatePickerElement;\n private trigger!: HTMLButtonElement;\n private pickerCloseBtn!: HTMLButtonElement;\n private dropdown!: HTMLNanoDropdownElement;\n private input: HTMLNanoInputElement;\n private pickerOpenSource: 'key' | 'mouse';\n\n private directInput = false;\n private dateOrderIndeces = { d: 0, m: 1, y: 3 };\n private inputId = `nano-input-${inputIds++}`;\n private locale =\n (window.navigator.languages as string[]) ||\n window.navigator.language ||\n undefined;\n\n @Element() host: HTMLNanoDateInputElement;\n\n // Private state\n\n @State() pattern!: string;\n @State() inputValue: string;\n\n // Public Api / Prop\n\n /**\n * This will be true when the control is in an invalid state.\n * Validity is determined by the `required` prop. Or if custom validity message is set. @readonly\n */\n @Prop({ reflect: true })\n get invalid() {\n return this._invalid;\n }\n @State() _invalid = false;\n\n /**\n * Current validation message - if any. @readonly\n */\n @Prop()\n get validityMessage() {\n if (!this.input) return '';\n return this.input.validityMessage;\n }\n\n /**\n * Whether to show a long form, confirmation date string of the one currently entered\n */\n @Prop() helperText: boolean = true;\n\n /**\n * Options for the date string display. Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString.\n */\n @Prop() helperTextFormat: LocalDateOpts = {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n };\n\n /**\n * Enable floating label behaviour. Will disable placeholder if set.\n */\n @Prop() floatLabel: boolean = false;\n\n /**\n * The name of the control, which is submitted with the form data.\n */\n @Prop() name: string = this.inputId;\n\n /**\n * If `true`, the user cannot modify the value.\n */\n @Prop() readonly = false;\n\n /**\n * The initial size (number of characters) of the control.\n */\n @Prop() size?: number;\n\n /**\n * The form element to associate the select with (its form owner). Must be the id of a form.\n */\n @Prop() form?: string | null;\n\n /**\n * Which day is considered first day of the week? `0` for Sunday, `1` for Monday, etc.\n * Default is Monday.\n */\n @Prop() firstDayOfWeek?: DaysOfWeek;\n\n /**\n * Button labels, day names, month names, etc, used for localization.\n * Default is English.\n */\n @Prop() localization?: DuetLocalizedText;\n\n /**\n * If `true`, the user cannot interact with the input.\n */\n @Prop() disabled = false;\n\n /**\n * The color to use from the application's color palette.\n */\n @Prop() color?: Color;\n\n /**\n * This Boolean attribute lets you specify that a form control should have input focus when the page loads.\n */\n @Prop() autofocus = false;\n\n /**\n * If `true`, a clear icon will appear in the input when there is a value. Clicking it clears the input.\n */\n @Prop() clearInput = false;\n\n /**\n * String to place within a label element. Alternatively you may use a label slot.\n */\n @Prop() label?: string;\n\n /**\n * Instructional text that shows before the input has a value.\n * The pattern prop will be used to create a placeholder automatically if unused.\n */\n @Prop({ mutable: true }) placeholder: string;\n\n /**\n * Current value. Must be in IS0-8601 format: YYYY-MM-DD.\n */\n @Prop({ reflect: true, mutable: true }) value: string = '';\n\n @Watch('value')\n handleValueChange() {\n if (!this.directInput) this.inputValue = this.formatIsoDate(this.value);\n setTimeout(() => {\n this.nanoChange.emit({\n value: this.value,\n date: parseISODate(this.value),\n });\n }, 20);\n this.directInput = false;\n }\n\n /**\n * When should the field perform validation\n */\n @Prop() validateOn?: 'dirty' | 'submit' | 'submitThenDirty' =\n 'submitThenDirty';\n\n /**\n * Whether to show validation errors underneath input\n */\n @Prop({ reflect: true }) showInlineError = true;\n\n /**\n * The order of the date parts for entry and display.\n * e.g. dmy = dd mm yyyy\n */\n @Prop() dateOrder: 'dmy' | 'mdy' | 'ymd' | 'dym' = 'dmy';\n\n @Watch('dateOrder')\n handleDateOrderChange() {\n this.setDatePattern();\n }\n\n /**\n * If `true`, the user must fill in a value before submitting a form.\n */\n @Prop() required = false;\n\n /**\n * Minimum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD.\n * This setting can be used alone or together with the max property.\n */\n @Prop() min?: string;\n\n /**\n * Maximum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD.\n * This setting can be used alone or together with the min property.\n */\n @Prop() max?: string;\n\n /**\n * Visually hide the label - but make it accessible.\n */\n @Prop() hideLabel?: boolean = false;\n\n @Watch('min')\n @Watch('max')\n @Watch('value')\n testDateValidity() {\n const valueDate = parseISODate(this.value);\n\n let min: Date,\n max: Date,\n error: string = '';\n\n if (this.value && valueDate) {\n if (this.min && (min = parseISODate(this.min)) && valueDate < min) {\n error =\n 'Date below the minimum: ' +\n min.toLocaleDateString(this.locale, this.helperTextFormat);\n }\n if (this.max && (max = parseISODate(this.max)) && valueDate > max) {\n error =\n 'Date above the maximum: ' +\n max.toLocaleDateString(this.locale, this.helperTextFormat);\n }\n if (this.isDateDisabled(valueDate)) {\n error = 'Date selected is disabled.';\n }\n }\n\n requestAnimationFrame(async (_) => {\n if (!this.input) return;\n const input = await this.input.getInputElement();\n if (this.value.length && !valueDate) error = 'Please enter a valid date';\n\n input.setCustomValidity(error);\n if (this.input.validateOn === 'dirty') {\n this.input.showError(error);\n }\n });\n }\n\n /**\n * Show a date picker. Date pickers are not very useful\n * if the potential input is too far in the distance or past\n * e.g. Birthdays\n */\n @Prop() picker: boolean = true;\n\n /**\n * Initial picker date. Will be to `value` if set. Will be today's date if nothing set.\n * Must be in IS0-8601 format: YYYY-MM-DD.\n */\n @Prop() initialPickerDate?: string;\n\n /**\n * Set / read whether the picker is currently open.\n */\n @Prop({ reflect: true, mutable: true }) pickerOpen: boolean = false;\n\n @Watch('pickerOpen')\n handlePickerOpenChange() {\n this.dropdown.open = this.pickerOpen;\n }\n\n /**\n * Close the picker after a date is selected\n */\n @Prop() closeAfterPicked: boolean = true;\n\n /** nano-dropdown config options you can pass to the nested dropdown component */\n @Prop()\n get dropDownConfig() {\n return this._dropDownConfig;\n }\n set dropDownConfig(ddc: Partial<Dropdown>) {\n this._dropDownConfig = { ...this._dropDownConfig, ...ddc };\n }\n private _dropDownConfig: Partial<Dropdown> = {};\n\n /** @readonly get the value as a `Date` */\n @Prop()\n get dateValue() {\n return parseISODate(this.value);\n }\n\n /** Controls which days are disabled and therefore disallowed.\n * For example, this can be used to disallow selection of weekends.\n * @returns `false` for not disabled and `true` for disabled */\n @Prop() isDateDisabled: DateDisabledPredicate = () => false;\n\n // Event emitters\n\n /**\n * Event emitted when a date is selected.\n */\n @Event() nanoChange: EventEmitter<DateInputChangeEventDetail>;\n\n /**\n * Called when validation is performed (which depends on `validateOn`).\n * @returns event.detail: `{ isValid: boolean, errorMessage: string, originalEvent: Event }`.\n */\n @Event() nanoValidate: EventEmitter<ControlValidityEventDetail>;\n\n // Methods\n\n /**\n * Get the current state of the control.\n * @param validateFirst - perform validation first before reporting\n * @returns `{ isValid: boolean, errorMessage: string }`\n */\n @Method()\n async reportValidity(validateFirst: boolean): Promise<ControlValidity> {\n const initValidity = await this.input.reportValidity(validateFirst);\n if (initValidity.isValid && validateFirst) this.testDateValidity();\n return await this.input.reportValidity(validateFirst);\n }\n\n /**\n * Sets focus on the child `nano-input`.\n */\n @Method()\n async setFocus() {\n if (this.input) this.input.setFocus();\n }\n\n /**\n * Returns the native `<input>` element used under the hood.\n */\n @Method()\n async getInputElement() {\n return await this.input.getInputElement();\n }\n\n /**\n * Invalidate the field and show a custom error message. To clear the error you will need to re-call this method with an empty string.\n */\n @Method()\n async showError(message: string) {\n if (!this.input) return;\n this.input.showError(message);\n }\n\n // Event handlers\n\n private onInputChange = (e: NanoInputCustomEvent<InputChangeEventDetail>) => {\n e.stopPropagation();\n this.setValue(e.target.value);\n };\n\n private onInputValidate = (e: CustomEvent<ControlValidityEventDetail>) => {\n e.stopPropagation();\n this._invalid = !e.detail.isValid;\n\n this.nanoValidate.emit({\n isValid: e.detail.isValid,\n errorMessage: e.detail.errorMessage,\n originalEvent: e.detail.originalEvent,\n });\n };\n\n private onInputKey = () => {\n this.directInput = true;\n };\n\n private onDatePicked = (e: { detail: PickerChangeEvent }) => {\n this.directInput = false;\n this.value = e.detail.value;\n if (this.closeAfterPicked) this.pickerOpen = false;\n };\n\n private onDropdownHide = () => {\n setTimeout((_) => (this.pickerOpen = false), 200);\n setTimeout((_) => this.trigger.focus(), 50);\n };\n\n private onDropdownShow = () => {\n setTimeout((_) => {\n this.pickerEle.setFocus(false, this.pickerOpenSource === 'key');\n this.pickerOpenSource = null;\n }, 200);\n };\n\n private onTriggerClick = () => {\n if (!this.pickerOpen) {\n this.pickerOpen = true;\n this.pickerOpenSource = 'mouse';\n }\n };\n\n private onTriggerKey = (e: KeyboardEvent) => {\n if ([' ', 'Enter'].includes(e.key)) {\n if (!this.pickerOpen) {\n this.pickerOpen = true;\n this.pickerOpenSource = 'key';\n }\n }\n };\n\n private onCloseClick = () => {\n if (this.pickerOpen) this.pickerOpen = false;\n };\n\n private onCloseKeyDown = (e: KeyboardEvent) => {\n // this ensures focus is trapped inside the picker\n if (e.key === 'Tab' && e.shiftKey) {\n this.pickerEle.setFocus(true);\n e.preventDefault();\n }\n if (e.key === ' ' || e.key === 'Enter') {\n if (this.pickerOpen) this.pickerOpen = false;\n }\n };\n\n // Private logic\n\n // set the regexp input pattern and placeholder (if necessary)\n private setDatePattern() {\n const dateRegexOrdered = [];\n const dateStrOrd = [];\n Array.from(this.dateOrder).map((datepart, i) => {\n dateRegexOrdered.push(DateRegxps[datepart]);\n this.dateOrderIndeces[datepart] = i;\n dateStrOrd.push(datepart === 'y' ? 'yyyy' : datepart + datepart);\n });\n this.pattern = dateRegexOrdered.join('\\\\W+');\n\n if (!this.placeholder && this.placeholder !== 'false')\n this.placeholder = dateStrOrd.join(' ');\n }\n\n // set the public facing date string\n private formatIsoDate(isoDate: string) {\n const dateRegexOrdered = [];\n Array.from('ymd').map((datepart) =>\n dateRegexOrdered.push(DateRegxps[datepart])\n );\n const matches = isoDate.match(new RegExp(dateRegexOrdered.join('\\\\W+')));\n if (!matches) return '';\n\n const formatted = [];\n formatted[this.dateOrderIndeces.d] = matches[3];\n formatted[this.dateOrderIndeces.m] = matches[2];\n formatted[this.dateOrderIndeces.y] = matches[1];\n\n return formatted.join(' ');\n }\n\n // on manual user entry, set the value that will be sent with the form field\n private setValue(inputValue: string) {\n const matches = inputValue.match(new RegExp(this.pattern));\n\n // it's an invalid date, but we still need to set it\n if (!matches) {\n this.value = inputValue;\n return;\n }\n\n let date = createDate(\n matches[this.dateOrderIndeces.y + 1],\n matches[this.dateOrderIndeces.m + 1],\n matches[this.dateOrderIndeces.d + 1]\n );\n\n if (!date) {\n // last ditch attempt - see if the browser can get something\n date = new Date(inputValue);\n\n // it's definitely an invalid date, but set it anyway for validation messages\n if (!date) {\n this.value = inputValue;\n return;\n }\n }\n\n const dateStr = printISODate(date);\n this.value = dateStr;\n return dateStr;\n }\n\n connectedCallback() {\n this.setDatePattern();\n this.handleValueChange();\n }\n\n componentDidLoad() {\n if (!this.pickerCloseBtn || !this.picker) return;\n this.pickerEle.firstFocusEle = this.pickerCloseBtn;\n this.dropdown.tetherTo = this.trigger;\n setTimeout((_) => this.handlePickerOpenChange(), 300);\n }\n\n render() {\n this.locale =\n (navigator.languages as string[]) || navigator.language || undefined;\n\n this.dropDownConfig.placement =\n this.dropDownConfig.placement || 'bottom-end';\n\n if ((this.host.ownerDocument as Document).dir === 'rtl') {\n this.dropDownConfig.placement.replace('start', 'end');\n }\n if (this.trigger) this.dropDownConfig.tetherTo = this.trigger;\n\n const valueDate = parseISODate(this.value);\n const hasHelperSlot = !!this.host.querySelector('[slot=\"helper\"]');\n\n return (\n <Host class={{ ...createColorClasses(this.color) }}>\n <div class=\"date-field\">\n <nano-input\n class=\"date-field__input\"\n slot=\"trigger\"\n required={this.required || undefined}\n showInlineError={this.showInlineError}\n validateOn={this.validateOn}\n placeholder={\n this.placeholder !== 'false' ? this.placeholder : undefined\n }\n pattern={this.pattern}\n label={this.label}\n disabled={this.disabled || undefined}\n color={this.color || undefined}\n autofocus={this.autofocus || undefined}\n clearInput={this.clearInput || undefined}\n onNanoChange={this.onInputChange}\n onNanoInput={this.onInputKey}\n onNanoValidate={this.onInputValidate}\n name=\"\"\n form={this.form || undefined}\n size={this.size || undefined}\n readonly={this.readonly}\n value={this.inputValue}\n ref={(input) => (this.input = input)}\n floatLabel={this.floatLabel}\n hideLabel={this.hideLabel}\n inputmode={'numeric'}\n part=\"input\"\n >\n <slot name=\"start\" slot=\"start\" />\n <slot name=\"label\" />\n <slot name=\"end\" slot=\"end\" />\n {this.picker && [\n <button\n slot=\"end\"\n class=\"date-field__open\"\n type=\"button\"\n onKeyDown={this.onTriggerKey}\n onClick={this.onTriggerClick}\n ref={(trigger) => (this.trigger = trigger)}\n disabled={this.disabled || this.readonly}\n >\n <nano-icon name=\"light/calendar-alt\"></nano-icon>\n </button>,\n\n <nano-dropdown\n slot=\"end\"\n onNanoHide={this.onDropdownHide}\n onNanoShow={this.onDropdownShow}\n dialogTitle=\"Choose a date\"\n class=\"date-field__dropdown\"\n ref={(dropdown) => (this.dropdown = dropdown)}\n {...this.dropDownConfig}\n part=\"dropdown\"\n >\n <div>\n <div class=\"date-field__close-bar\">\n <button\n class=\"date-field__close\"\n type=\"button\"\n onMouseDown={this.onCloseClick}\n onKeyDown={this.onCloseKeyDown}\n ref={(pickerClose) => (this.pickerCloseBtn = pickerClose)}\n >\n <nano-icon name=\"light/times\"></nano-icon>\n <span class=\"vhidden\">Close window</span>\n </button>\n </div>\n <nano-date-picker\n isDateDisabled={this.isDateDisabled}\n onNanoDatePicked={this.onDatePicked}\n min={this.min || undefined}\n max={this.max || undefined}\n is-modal={true}\n ref={(picker) => (this.pickerEle = picker)}\n localization={this.localization}\n selectedDate={this.value || this.initialPickerDate}\n firstDayOfWeek={this.firstDayOfWeek}\n color={this.color || undefined}\n part=\"date-picker\"\n ></nano-date-picker>\n </div>\n </nano-dropdown>,\n ]}\n {(hasHelperSlot || this.helperText || this.showInlineError) && (\n <span slot=\"helper\">\n <span class={{ vhidden: !!this.value.length }}>\n <slot name=\"helper\" />\n </span>\n {this.helperText && !!valueDate && (\n <span>\n {valueDate.toLocaleDateString(\n this.locale,\n this.helperTextFormat\n )}\n </span>\n )}\n </span>\n )}\n </nano-input>\n <input type=\"hidden\" value={this.value} name={this.name} />\n </div>\n </Host>\n );\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /*!
2
+ * Web Components for Nanopore digital Web Apps
3
+ */
4
+ import{r as t,c as i,h as a,a as e,g as s}from"./p-1fe12320.js";import{M as n}from"./p-c9a7c7ea.js";import{l as r,u as o}from"./p-885b6950.js";import{c as l}from"./p-7b3638b7.js";import"./p-45abbbdd.js";import"./p-845ae77e.js";const h=":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}:host{--border-radius:var(--nano-layer-border-radius, var(--nano-border-radius-medium, 4px));--border-color:var(--nano-layer-border-color, rgba(0, 0, 0, 0.1));--border-width:var(--nano-layer-border-width, 1px);--background:var(--nano-layer-bg, #fff);--tint-color:var(--nano-color-base, var(--nano-color-primary, #007495));--icon-size:2rem;--scrim-color:var(--nano-layer-overlay-dark, rgba(74, 74, 74, .5));--close-button-color:#b5aea7;display:block}:host(.nano-color){--tint-color:var(--nano-color-base, var(--nano-color-primary, #007495))}.alert{position:relative;background-color:var(--background);border:solid var(--border-width) var(--border-color);border-block-start-width:4px;border-block-start-color:var(--tint-color);border-radius:var(--border-radius);opacity:0;transform:scale(0.9);transition:var(--nano-transition-medium, 0.5s) opacity ease, var(--nano-transition-fast, 0.3s) transform ease}.alert:focus{outline:none}.alert:not(.alert--showing){position:absolute;inline-size:1px;block-size:1px;clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);overflow:hidden;pointer-events:none;visibility:hidden}.alert--open{opacity:1;transform:none}.alert--toasty,.alert--modal{box-shadow:var(--nano-layer-shadow-large, 0 2px 8px rgba(0, 0, 0, 0.2));margin:var(--nano-spacing-medium, 16px)}.alert__content{display:flex;align-items:stretch}.alert__modal-wrap{position:fixed;display:flex;align-items:center;justify-content:center;inset:0;z-index:var(--nano-layer-index-alert, 800)}.alert__message{flex:1 1 auto;padding:var(--nano-spacing-medium, 16px);overflow:hidden;line-height:1.6}.alert__close{--color:var(--close-button-color);flex:0 0 auto;display:flex;align-items:center;font-size:1.1em;padding-inline:0 var(--nano-spacing-medium, 16px);padding-block:0}.alert__footer{padding:0 var(--nano-spacing-small, 8px) 0;display:flex;flex-direction:row;justify-content:space-around;align-items:center}.alert__footer ::slotted(*){flex:1;margin:0 var(--nano-spacing-small, 8px) var(--nano-spacing-medium, 16px) !important}.alert__overlay{position:fixed;inset:0;background-color:var(--scrim-color);opacity:0;transition:var(--nano-transition-fast, 0.3s) opacity;z-index:var(--nano-layer-index-alert, 800);-webkit-backdrop-filter:blur(var(--nano-layer-overlay-blur, 3px));backdrop-filter:blur(var(--nano-layer-overlay-blur, 3px))}.alert__overlay--open{opacity:1}.alert__icon{flex:0 0 auto;display:flex;align-items:center;font-size:var(--icon-size)}.alert__icon ::slotted(*){color:var(--tint-color);margin-inline-start:var(--nano-spacing-medium, 16px)}";const c=Object.assign(document.createElement("div"),{className:"nano-toast-stack nano-toast-stack--tr"});const d=Object.assign(document.createElement("div"),{className:"nano-toast-stack nano-toast-stack--tl"});const u=Object.assign(document.createElement("div"),{className:"nano-toast-stack nano-toast-stack--bl"});const f=Object.assign(document.createElement("div"),{className:"nano-toast-stack nano-toast-stack--br"});const m=class{constructor(e){t(this,e);this.nanoShow=i(this,"nanoShow",7);this.nanoAfterShow=i(this,"nanoAfterShow",7);this.nanoHide=i(this,"nanoHide",7);this.nanoAfterHide=i(this,"nanoAfterHide",7);this.addedTransEnd=false;this.goingToHide=false;this.goingToShow=false;this.handleMouseMove=()=>{this.restartAutoHide()};this.handleCloseClick=()=>{this.hide()};this.handleTransitionEnd=t=>{if(t.propertyName==="opacity"&&(t.target===this.panel||t.target===this.overlay)){this.host.hidden=!this.open;this.isShowing=this.open;this.open?this.nanoAfterShow.emit():this.nanoAfterHide.emit()}};this.handleButtonClick=t=>{if(t.defaultPrevented)return;if(t.target.tagName&&t.target.tagName.toLowerCase()==="button")this.hide()};this.restartAutoHide=()=>{clearTimeout(this.autoHideTimeout);if(this.open&&this.duration<Infinity){this.autoHideTimeout=setTimeout((()=>this.hide()),this.duration)}};this.Panel=()=>a("div",{ref:t=>this.panel=t,part:"panel",class:{alert:true,"alert--open":this.open,"alert--toasty":this.isToast,"alert--modal":!!this.isModal,"alert--showing":this.isShowing},role:!!this.isModal?"alertdialog":"alert","aria-live":"assertive","aria-atomic":"true","aria-hidden":this.open?"false":"true","aria-modal":!!this.isModal?"true":undefined,"aria-label":this.label?this.label:undefined,onMouseMove:this.handleMouseMove,tabIndex:!!this.isModal?0:undefined},a("div",{class:"alert__content"},a("div",{part:"icon",class:"alert__icon"},a("slot",{name:"icon"})),a("div",{part:"message",class:"alert__message"},a("slot",null)),this.closable&&a("div",{class:"alert__close"},a("nano-icon-button",{class:"alert__close",iconName:"light/times",label:"close menu",onClick:this.handleCloseClick}))),a("div",{class:"alert__footer"},a("slot",{name:"footer"})));this.isModal=false;this.isToast=false;this.isShowing=false;this.label=undefined;this.open=false;this.closable=false;this.color=undefined;this.duration=Infinity}handleOpenChange(){this.open?this.show():this.hide()}handleDurationChange(){this.restartAutoHide()}async show(){if(this.goingToShow){return}const t=this.nanoShow.emit();if(t.defaultPrevented){this.open=false;return false}this.host.hidden=false;this.goingToShow=true;this.open=true;requestAnimationFrame((()=>{this.isShowing=true;this.goingToShow=false}));if(this.duration<Infinity){clearTimeout(this.autoHideTimeout);this.autoHideTimeout=setTimeout((()=>this.hide()),this.duration)}}async hide(){if(this.goingToHide){return}const t=this.nanoHide.emit();if(t.defaultPrevented){this.open=true;return false}this.goingToHide=true;this.open=false;requestAnimationFrame((()=>this.goingToHide=false));clearTimeout(this.autoHideTimeout)}async toast(t="tr"){this.isToast=true;return new Promise((i=>{let a;switch(t){case"tl":a=d;break;case"bl":a=u;break;case"br":a=f;break;default:a=c;break}if(!a.parentElement){document.body.appendChild(a)}a.appendChild(this.host);this.connectedCallback();this.show();const e=()=>{this.host.remove();this.isToast=false;i();if(!a.querySelector("nano-alert")){a.remove()}};this.host.addEventListener("nanoAfterHide",e,{once:true});this.host.addEventListener("nanoafterhide",e,{once:true})}))}async alert(t){this.isModal=true;this.label=t;return new Promise((t=>{if(!document.body.contains(this.host)){document.body.appendChild(this.host)}this.modal.activate();r(this.host);this.originalTrigger=document.activeElement;requestAnimationFrame((()=>{this.show()}));const i=()=>requestAnimationFrame((()=>this.panel.focus({preventScroll:true})));const a=()=>{this.modal.deactivate();this.host.remove();this.label=undefined;this.isModal=false;t();if(this.originalTrigger&&typeof this.originalTrigger.focus==="function"){setTimeout((()=>this.originalTrigger.focus()))}};this.host.addEventListener("nanoAfterShow",i,{once:true});this.host.addEventListener("nanoaftershow",i,{once:true});this.host.addEventListener("nanoAfterHide",a,{once:true});this.host.addEventListener("nanoafterhide",a,{once:true})}))}connectedCallback(){this.modal=new n(this.host);this.host.addEventListener("click",this.handleButtonClick);if(this.panel){this.addedTransEnd=true;this.panel.addEventListener("transitionend",this.handleTransitionEnd)}}disconnectedCallback(){o(this.host);this.host.removeEventListener("click",this.handleButtonClick);this.addedTransEnd=false;this.panel.removeEventListener("transitionend",this.handleTransitionEnd)}componentDidLoad(){if(this.open){this.show()}if(!this.addedTransEnd){this.panel.addEventListener("transitionend",this.handleTransitionEnd)}}render(){return a(e,{class:{...l(this.color)},showing:this.isShowing},this.isModal&&[a("div",{part:"overlay",class:{alert__overlay:true,"alert__overlay--open":this.open},ref:t=>this.overlay=t}),a("div",{class:"alert__modal-wrap"},a(this.Panel,null))],!this.isModal&&a(this.Panel,null))}get host(){return s(this)}static get watchers(){return{open:["handleOpenChange"],duration:["handleDurationChange"]}}};m.style=h;export{m as nano_alert};
5
+ //# sourceMappingURL=p-36842a50.entry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["src/components/alert/alert.scss?tag=nano-alert&encapsulation=shadow","src/components/alert/alert.tsx"],"names":["alertCss","toastStackTr","Object","assign","document","createElement","className","toastStackTl","toastStackBl","toastStackBr","Alert","this","addedTransEnd","goingToHide","goingToShow","handleMouseMove","restartAutoHide","handleCloseClick","hide","handleTransitionEnd","event","propertyName","target","panel","overlay","host","hidden","open","isShowing","nanoAfterShow","emit","nanoAfterHide","handleButtonClick","e","defaultPrevented","tagName","toLowerCase","clearTimeout","autoHideTimeout","duration","Infinity","setTimeout","Panel","h","ref","el","part","class","alert","alert--open","alert--toasty","isToast","alert--modal","isModal","alert--showing","role","aria-live","aria-atomic","aria-hidden","aria-modal","undefined","aria-label","label","onMouseMove","tabIndex","name","closable","iconName","onClick","[object Object]","show","nanoShow","requestAnimationFrame","nanoHide","position","Promise","resolve","toastStack","parentElement","body","appendChild","connectedCallback","onClose","remove","querySelector","addEventListener","once","contains","modal","activate","lockBodyScrolling","originalTrigger","activeElement","onOpen","focus","preventScroll","deactivate","Modal","unlockBodyScrolling","removeEventListener","Host","createColorClasses","color","showing","alert__overlay","alert__overlay--open","div"],"mappings":"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","sourcesContent":["@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/base';\n@import '../../global/style/nano-theme/colours';\n@import '../../global/style/nano-theme/layers';\n\n:host {\n /**\n * @prop --border-radius: defaults to #{$layer-border-radius};\n * @prop --border-color: defaults to #{$layer-border-color};\n * @prop --border-width: defaults to #{$layer-border-width};\n * @prop --background: defaults to #{$layer-bg-color};\n * @prop --tint-color: defaults to var(--nano-color-base, #{nano-color(primary, base)});\n * @prop --icon-size: defaults to 1.5rem;\n * @prop --scrim-color: overlay colour of alert display. Defaults to #{$layer-overlay-dark};\n * @prop --close-button-color: defaults to #{map.get($colors, mediumgrey)} ;\n */\n\n --border-radius: #{$layer-border-radius};\n --border-color: #{$layer-border-color};\n --border-width: #{$layer-border-width};\n --background: #{$layer-bg-color};\n --tint-color: var(--nano-color-base, #{nano-color(primary, base)});\n --icon-size: 2rem;\n --scrim-color: #{$layer-overlay-dark};\n --close-button-color: #{map.get($colors, palegrey)};\n\n display: block;\n}\n\n:host(.nano-color) {\n --tint-color: var(--nano-color-base, #{nano-color(primary, base)});\n}\n\n.alert {\n position: relative;\n background-color: var(--background);\n border: solid var(--border-width) var(--border-color);\n border-block-start-width: 4px;\n border-block-start-color: var(--tint-color);\n border-radius: var(--border-radius);\n opacity: 0;\n transform: scale(0.9);\n transition:\n #{$transition-medium} opacity ease,\n #{$transition-fast} transform ease;\n\n &:focus {\n outline: none;\n }\n\n &:not(.alert--showing) {\n @include hidden;\n }\n\n &--open {\n opacity: 1;\n transform: none;\n }\n\n &--toasty,\n &--modal {\n box-shadow: #{$layer-shadow-large};\n margin: #{$spacing-medium};\n }\n}\n\n.alert__content {\n display: flex;\n align-items: stretch;\n}\n\n.alert__modal-wrap {\n position: fixed;\n display: flex;\n align-items: center;\n justify-content: center;\n inset: 0;\n z-index: #{$layer-index-alert};\n}\n\n.alert__message {\n flex: 1 1 auto;\n padding: #{$spacing-medium};\n overflow: hidden;\n line-height: 1.6;\n}\n\n.alert__close {\n --color: var(--close-button-color);\n\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: 1.1em;\n padding-inline: 0 #{$spacing-medium};\n padding-block: 0;\n}\n\n.alert__footer {\n padding: 0 #{$spacing-small} 0;\n display: flex;\n flex-direction: row;\n justify-content: space-around;\n align-items: center;\n\n ::slotted(*) {\n flex: 1;\n margin: 0 #{$spacing-small} #{$spacing-medium} !important;\n }\n}\n\n.alert__overlay {\n position: fixed;\n inset: 0;\n background-color: var(--scrim-color);\n opacity: 0;\n transition: #{$transition-fast} opacity;\n z-index: #{$layer-index-alert};\n backdrop-filter: blur(#{$layer-overlay-blur});\n\n &--open {\n opacity: 1;\n }\n}\n\n.alert__icon {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: var(--icon-size);\n\n ::slotted(*) {\n color: var(--tint-color);\n margin-inline-start: #{$spacing-medium};\n }\n}\n","import {\n Component,\n ComponentInterface,\n Element,\n Event,\n EventEmitter,\n Method,\n Prop,\n State,\n Watch,\n h,\n Host,\n VNode,\n} from '@stencil/core';\nimport Modal from '../../utils/modal';\nimport { lockBodyScrolling, unlockBodyScrolling } from '../../utils/scroll';\nimport { createColorClasses } from '../../utils/theme';\nimport type { Color } from '../../interface';\n\nconst toastStackTr = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--tr',\n});\nconst toastStackTl = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--tl',\n});\nconst toastStackBl = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--bl',\n});\nconst toastStackBr = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--br',\n});\n\n/**\n * Alerts are used to display important messages either inline, as toast notifications or as modals requiring action.\n * @slot - The alert's content.\n * @slot icon - An icon to show in the alert.\n * @slot footer - Place items at the bottom of the alert. Best used with `button` elements - esp when used as with the `alert()` method.\n */\n@Component({\n tag: 'nano-alert',\n styleUrl: 'alert.scss',\n shadow: true,\n})\nexport class Alert implements ComponentInterface {\n private autoHideTimeout: ReturnType<typeof setTimeout>;\n private panel: HTMLElement;\n private overlay: HTMLElement;\n private modal: Modal;\n private originalTrigger: HTMLElement | null;\n private addedTransEnd = false;\n private goingToHide = false;\n private goingToShow = false;\n\n @State() isModal = false;\n @State() isToast = false;\n @State() isShowing = false;\n @State() label: string;\n\n @Element() host: HTMLNanoAlertElement;\n\n /** Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods. */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n @Watch('open')\n handleOpenChange() {\n this.open ? this.show() : this.hide();\n }\n\n /** Set to true to make the alert closable. */\n @Prop({ reflect: true }) closable = false;\n\n /** The color to use from the application's color palette. */\n @Prop({ reflect: true }) color?: Color;\n\n /**\n * The length of time, in milliseconds, the alert will show before closing itself. If the user interacts with the\n * alert before it closes (e.g. moves the mouse over it), the timer will restart.\n */\n @Prop() duration = Infinity;\n\n @Watch('duration')\n handleDurationChange() {\n this.restartAutoHide();\n }\n\n /** Emitted when the alert opens. Calling `event.preventDefault()` will prevent it from being opened. */\n @Event() nanoShow: EventEmitter;\n\n /** Emitted after the alert opens and all transitions are complete. */\n @Event() nanoAfterShow: EventEmitter;\n\n /** Emitted when the alert closes. Calling `event.preventDefault()` will prevent it from being closed. */\n @Event() nanoHide: EventEmitter;\n\n /** Emitted after the alert closes and all transitions are complete. */\n @Event() nanoAfterHide: EventEmitter;\n\n /** Shows the alert. */\n @Method()\n async show() {\n if (this.goingToShow) {\n return;\n }\n const nanoShow = this.nanoShow.emit();\n if (nanoShow.defaultPrevented) {\n this.open = false;\n return false;\n }\n\n this.host.hidden = false;\n this.goingToShow = true;\n this.open = true;\n requestAnimationFrame(() => {\n this.isShowing = true;\n this.goingToShow = false;\n });\n\n if (this.duration < Infinity) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);\n }\n }\n\n /** Hides the alert */\n @Method()\n async hide() {\n if (this.goingToHide) {\n return;\n }\n const nanoHide = this.nanoHide.emit();\n\n if (nanoHide.defaultPrevented) {\n this.open = true;\n return false;\n }\n this.goingToHide = true;\n this.open = false;\n\n requestAnimationFrame(() => (this.goingToHide = false));\n clearTimeout(this.autoHideTimeout);\n }\n\n /**\n * Displays the alert as a toast notification. This will move the alert out of its position in the DOM and, when\n * dismissed, it will be removed from the DOM completely. By storing a reference to the alert, you can reuse it by\n * calling this method again. The returned promise will resolve after the alert is hidden.\n *\n * @param position options are tr (top-right - default), tl (top-left), br (bottom-right), bl (bottom-left)\n * @returns a promise which will resolve after the alert has hidden\n */\n @Method()\n async toast(position: 'tr' | 'tl' | 'bl' | 'br' = 'tr') {\n this.isToast = true;\n return new Promise<void>((resolve) => {\n let toastStack: HTMLElement;\n switch (position) {\n case 'tl':\n toastStack = toastStackTl;\n break;\n case 'bl':\n toastStack = toastStackBl;\n break;\n case 'br':\n toastStack = toastStackBr;\n break;\n default:\n toastStack = toastStackTr;\n break;\n }\n\n if (!toastStack.parentElement) {\n document.body.appendChild(toastStack);\n }\n\n toastStack.appendChild(this.host);\n this.connectedCallback();\n this.show();\n\n const onClose = () => {\n this.host.remove();\n this.isToast = false;\n resolve();\n\n // Remove the toast stack from the DOM when there are no more alerts\n if (!toastStack.querySelector('nano-alert')) {\n toastStack.remove();\n }\n };\n\n this.host.addEventListener('nanoAfterHide', onClose, { once: true });\n this.host.addEventListener('nanoafterhide', onClose, { once: true });\n });\n }\n\n /**\n * Displays the alert as a dialog / modal - more akin to a traditional js alert().\n * @param label a label for assistive technology\n */\n @Method()\n async alert(label: string) {\n this.isModal = true;\n this.label = label;\n\n return new Promise<void>((resolve) => {\n if (!document.body.contains(this.host)) {\n document.body.appendChild(this.host);\n }\n\n this.modal.activate();\n lockBodyScrolling(this.host);\n this.originalTrigger = document.activeElement as HTMLElement;\n\n requestAnimationFrame(() => {\n this.show();\n });\n\n const onOpen = () =>\n requestAnimationFrame(() => this.panel.focus({ preventScroll: true }));\n\n const onClose = () => {\n this.modal.deactivate();\n this.host.remove();\n this.label = undefined;\n this.isModal = false;\n resolve();\n\n // Restore focus to the original trigger\n if (\n this.originalTrigger &&\n typeof this.originalTrigger.focus === 'function'\n ) {\n setTimeout(() => this.originalTrigger.focus());\n }\n };\n\n this.host.addEventListener('nanoAfterShow', onOpen, { once: true });\n this.host.addEventListener('nanoaftershow', onOpen, { once: true });\n\n this.host.addEventListener('nanoAfterHide', onClose, {\n once: true,\n });\n this.host.addEventListener('nanoafterhide', onClose, {\n once: true,\n });\n });\n }\n\n private handleMouseMove = () => {\n this.restartAutoHide();\n };\n\n private handleCloseClick = () => {\n this.hide();\n };\n\n private handleTransitionEnd = (event: TransitionEvent) => {\n if (\n event.propertyName === 'opacity' &&\n (event.target === this.panel || event.target === this.overlay)\n ) {\n this.host.hidden = !this.open;\n this.isShowing = this.open;\n this.open ? this.nanoAfterShow.emit() : this.nanoAfterHide.emit();\n }\n };\n\n private handleButtonClick = (e: PointerEvent & { target: HTMLElement }) => {\n if (e.defaultPrevented) return;\n if (e.target.tagName && e.target.tagName.toLowerCase() === 'button')\n this.hide();\n };\n\n private restartAutoHide = () => {\n clearTimeout(this.autoHideTimeout);\n if (this.open && this.duration < Infinity) {\n this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);\n }\n };\n\n connectedCallback() {\n this.modal = new Modal(this.host);\n this.host.addEventListener('click', this.handleButtonClick);\n\n if (this.panel) {\n this.addedTransEnd = true;\n this.panel.addEventListener('transitionend', this.handleTransitionEnd);\n }\n }\n\n disconnectedCallback() {\n unlockBodyScrolling(this.host);\n this.host.removeEventListener('click', this.handleButtonClick);\n\n this.addedTransEnd = false;\n this.panel.removeEventListener('transitionend', this.handleTransitionEnd);\n }\n\n componentDidLoad() {\n // Show on init if open\n if (this.open) {\n this.show();\n }\n if (!this.addedTransEnd) {\n this.panel.addEventListener('transitionend', this.handleTransitionEnd);\n }\n }\n\n private Panel = (): VNode => {\n return (\n <div\n ref={(el) => (this.panel = el)}\n part=\"panel\"\n class={{\n alert: true,\n 'alert--open': this.open,\n 'alert--toasty': this.isToast,\n 'alert--modal': !!this.isModal,\n 'alert--showing': this.isShowing,\n }}\n role={!!this.isModal ? 'alertdialog' : 'alert'}\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n aria-hidden={this.open ? 'false' : 'true'}\n aria-modal={!!this.isModal ? 'true' : undefined}\n aria-label={this.label ? this.label : undefined}\n onMouseMove={this.handleMouseMove}\n tabIndex={!!this.isModal ? 0 : undefined}\n >\n <div class=\"alert__content\">\n <div part=\"icon\" class=\"alert__icon\">\n <slot name=\"icon\" />\n </div>\n <div part=\"message\" class=\"alert__message\">\n <slot />\n </div>\n {this.closable && (\n <div class=\"alert__close\">\n <nano-icon-button\n class=\"alert__close\"\n iconName=\"light/times\"\n label=\"close menu\"\n onClick={this.handleCloseClick}\n ></nano-icon-button>\n </div>\n )}\n </div>\n <div class=\"alert__footer\">\n <slot name=\"footer\" />\n </div>\n </div>\n );\n };\n\n render() {\n return (\n <Host\n class={{ ...createColorClasses(this.color) }}\n showing={this.isShowing}\n >\n {this.isModal && [\n <div\n part=\"overlay\"\n class={{\n alert__overlay: true,\n 'alert__overlay--open': this.open,\n }}\n ref={(div) => (this.overlay = div)}\n />,\n <div class=\"alert__modal-wrap\">\n <this.Panel />\n </div>,\n ]}\n {!this.isModal && <this.Panel />}\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["src/components/alert/alert.scss?tag=nano-alert&encapsulation=shadow","src/components/alert/alert.tsx"],"names":["alertCss","toastStackTr","Object","assign","document","createElement","className","toastStackTl","toastStackBl","toastStackBr","Alert","this","addedTransEnd","goingToHide","goingToShow","handleMouseMove","restartAutoHide","handleCloseClick","hide","handleTransitionEnd","event","propertyName","target","panel","overlay","host","hidden","open","isShowing","nanoAfterShow","emit","nanoAfterHide","handleButtonClick","e","defaultPrevented","tagName","toLowerCase","clearTimeout","autoHideTimeout","duration","Infinity","setTimeout","Panel","h","ref","el","part","class","alert","alert--open","alert--toasty","isToast","alert--modal","isModal","alert--showing","role","aria-live","aria-atomic","aria-hidden","aria-modal","undefined","aria-label","label","onMouseMove","tabIndex","name","closable","iconName","onClick","[object Object]","show","nanoShow","requestAnimationFrame","nanoHide","position","Promise","resolve","toastStack","parentElement","body","appendChild","connectedCallback","onClose","remove","querySelector","addEventListener","once","contains","modal","activate","lockBodyScrolling","originalTrigger","activeElement","onOpen","focus","preventScroll","deactivate","Modal","unlockBodyScrolling","removeEventListener","Host","createColorClasses","color","showing","alert__overlay","alert__overlay--open","div"],"mappings":"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","sourcesContent":["@use 'sass:map';\n@use 'sass:list';\n\n@import '../../global/style/nano-theme/base';\n@import '../../global/style/nano-theme/colours';\n@import '../../global/style/nano-theme/layers';\n\n:host {\n /**\n * @prop --border-radius: defaults to #{$layer-border-radius};\n * @prop --border-color: defaults to #{$layer-border-color};\n * @prop --border-width: defaults to #{$layer-border-width};\n * @prop --background: defaults to #{$layer-bg-color};\n * @prop --tint-color: defaults to var(--nano-color-base, #{nano-color(primary, base)});\n * @prop --icon-size: defaults to 1.5rem;\n * @prop --scrim-color: overlay colour of alert display. Defaults to #{$layer-overlay-dark};\n * @prop --close-button-color: defaults to #{map.get($colors, mediumgrey)} ;\n */\n\n --border-radius: #{$layer-border-radius};\n --border-color: #{$layer-border-color};\n --border-width: #{$layer-border-width};\n --background: #{$layer-bg-color};\n --tint-color: var(--nano-color-base, #{nano-color(primary, base)});\n --icon-size: 2rem;\n --scrim-color: #{$layer-overlay-dark};\n --close-button-color: #{map.get($colors, palegrey)};\n\n display: block;\n}\n\n:host(.nano-color) {\n --tint-color: var(--nano-color-base, #{nano-color(primary, base)});\n}\n\n.alert {\n position: relative;\n background-color: var(--background);\n border: solid var(--border-width) var(--border-color);\n border-block-start-width: 4px;\n border-block-start-color: var(--tint-color);\n border-radius: var(--border-radius);\n opacity: 0;\n transform: scale(0.9);\n transition:\n #{$transition-medium} opacity ease,\n #{$transition-fast} transform ease;\n\n &:focus {\n outline: none;\n }\n\n &:not(.alert--showing) {\n @include hidden;\n }\n\n &--open {\n opacity: 1;\n transform: none;\n }\n\n &--toasty,\n &--modal {\n box-shadow: #{$layer-shadow-large};\n margin: #{$spacing-medium};\n }\n}\n\n.alert__content {\n display: flex;\n align-items: stretch;\n}\n\n.alert__modal-wrap {\n position: fixed;\n display: flex;\n align-items: center;\n justify-content: center;\n inset: 0;\n z-index: #{$layer-index-alert};\n}\n\n.alert__message {\n flex: 1 1 auto;\n padding: #{$spacing-medium};\n overflow: hidden;\n line-height: 1.6;\n}\n\n.alert__close {\n --color: var(--close-button-color);\n\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: 1.1em;\n padding-inline: 0 #{$spacing-medium};\n padding-block: 0;\n}\n\n.alert__footer {\n padding: 0 #{$spacing-small} 0;\n display: flex;\n flex-direction: row;\n justify-content: space-around;\n align-items: center;\n\n ::slotted(*) {\n flex: 1;\n margin: 0 #{$spacing-small} #{$spacing-medium} !important;\n }\n}\n\n.alert__overlay {\n position: fixed;\n inset: 0;\n background-color: var(--scrim-color);\n opacity: 0;\n transition: #{$transition-fast} opacity;\n z-index: #{$layer-index-alert};\n backdrop-filter: blur(#{$layer-overlay-blur});\n\n &--open {\n opacity: 1;\n }\n}\n\n.alert__icon {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: var(--icon-size);\n\n ::slotted(*) {\n color: var(--tint-color);\n margin-inline-start: #{$spacing-medium};\n }\n}\n","import {\n Component,\n ComponentInterface,\n Element,\n Event,\n EventEmitter,\n Method,\n Prop,\n State,\n Watch,\n h,\n Host,\n VNode,\n} from '@stencil/core';\nimport Modal from '../../utils/modal';\nimport { lockBodyScrolling, unlockBodyScrolling } from '../../utils/scroll';\nimport { createColorClasses } from '../../utils/theme';\nimport type { Color } from '../../interface';\n\nconst toastStackTr = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--tr',\n});\nconst toastStackTl = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--tl',\n});\nconst toastStackBl = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--bl',\n});\nconst toastStackBr = Object.assign(document.createElement('div'), {\n className: 'nano-toast-stack nano-toast-stack--br',\n});\n\n/**\n * Alerts are used to display important messages either inline, as toast notifications or as modals requiring action.\n * @slot - The alert's content.\n * @slot icon - An icon to show in the alert.\n * @slot footer - Place items at the bottom of the alert. Best used with `button` elements - esp when used as with the `alert()` method.\n */\n@Component({\n tag: 'nano-alert',\n styleUrl: 'alert.scss',\n shadow: true,\n})\nexport class Alert implements ComponentInterface {\n private autoHideTimeout: ReturnType<typeof setTimeout>;\n private panel: HTMLElement;\n private overlay: HTMLElement;\n private modal: Modal;\n private originalTrigger: HTMLElement | null;\n private addedTransEnd = false;\n private goingToHide = false;\n private goingToShow = false;\n\n @State() isModal = false;\n @State() isToast = false;\n @State() isShowing = false;\n @State() label: string;\n\n @Element() host: HTMLNanoAlertElement;\n\n /** Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods. */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n @Watch('open')\n handleOpenChange() {\n this.open ? this.show() : this.hide();\n }\n\n /** Set to true to make the alert closable. */\n @Prop({ reflect: true }) closable = false;\n\n /** The color to use from the application's color palette. */\n @Prop({ reflect: true }) color?: Color;\n\n /**\n * The length of time, in milliseconds, the alert will show before closing itself. If the user interacts with the\n * alert before it closes (e.g. moves the mouse over it), the timer will restart.\n */\n @Prop() duration = Infinity;\n\n @Watch('duration')\n handleDurationChange() {\n this.restartAutoHide();\n }\n\n /** Emitted when the alert opens. Calling `event.preventDefault()` will prevent it from being opened. */\n @Event() nanoShow: EventEmitter;\n\n /** Emitted after the alert opens and all transitions are complete. */\n @Event() nanoAfterShow: EventEmitter;\n\n /** Emitted when the alert closes. Calling `event.preventDefault()` will prevent it from being closed. */\n @Event() nanoHide: EventEmitter;\n\n /** Emitted after the alert closes and all transitions are complete. */\n @Event() nanoAfterHide: EventEmitter;\n\n /** Shows the alert. */\n @Method()\n async show() {\n if (this.goingToShow) {\n return;\n }\n const nanoShow = this.nanoShow.emit();\n if (nanoShow.defaultPrevented) {\n this.open = false;\n return false;\n }\n\n this.host.hidden = false;\n this.goingToShow = true;\n this.open = true;\n requestAnimationFrame(() => {\n this.isShowing = true;\n this.goingToShow = false;\n });\n\n if (this.duration < Infinity) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);\n }\n }\n\n /** Hides the alert */\n @Method()\n async hide() {\n if (this.goingToHide) {\n return;\n }\n const nanoHide = this.nanoHide.emit();\n\n if (nanoHide.defaultPrevented) {\n this.open = true;\n return false;\n }\n this.goingToHide = true;\n this.open = false;\n\n requestAnimationFrame(() => (this.goingToHide = false));\n clearTimeout(this.autoHideTimeout);\n }\n\n /**\n * Displays the alert as a toast notification. This will move the alert out of its position in the DOM and, when\n * dismissed, it will be removed from the DOM completely. By storing a reference to the alert, you can reuse it by\n * calling this method again. The returned promise will resolve after the alert is hidden.\n *\n * @param position options are tr (top-right - default), tl (top-left), br (bottom-right), bl (bottom-left)\n * @returns a promise which will resolve after the alert has hidden\n */\n @Method()\n async toast(position: 'tr' | 'tl' | 'bl' | 'br' = 'tr') {\n this.isToast = true;\n return new Promise<void>((resolve) => {\n let toastStack: HTMLElement;\n switch (position) {\n case 'tl':\n toastStack = toastStackTl;\n break;\n case 'bl':\n toastStack = toastStackBl;\n break;\n case 'br':\n toastStack = toastStackBr;\n break;\n default:\n toastStack = toastStackTr;\n break;\n }\n\n if (!toastStack.parentElement) {\n document.body.appendChild(toastStack);\n }\n\n toastStack.appendChild(this.host);\n this.connectedCallback();\n this.show();\n\n const onClose = () => {\n this.host.remove();\n this.isToast = false;\n resolve();\n\n // Remove the toast stack from the DOM when there are no more alerts\n if (!toastStack.querySelector('nano-alert')) {\n toastStack.remove();\n }\n };\n\n this.host.addEventListener('nanoAfterHide', onClose, { once: true });\n this.host.addEventListener('nanoafterhide', onClose, { once: true });\n });\n }\n\n /**\n * Displays the alert as a dialog / modal - more akin to a traditional js alert().\n * @param label a label for assistive technology\n */\n @Method()\n async alert(label: string) {\n this.isModal = true;\n this.label = label;\n\n return new Promise<void>((resolve) => {\n if (!document.body.contains(this.host)) {\n document.body.appendChild(this.host);\n }\n\n this.modal.activate();\n lockBodyScrolling(this.host);\n this.originalTrigger = document.activeElement as HTMLElement;\n\n requestAnimationFrame(() => {\n this.show();\n });\n\n const onOpen = () =>\n requestAnimationFrame(() => this.panel.focus({ preventScroll: true }));\n\n const onClose = () => {\n this.modal.deactivate();\n this.host.remove();\n this.label = undefined;\n this.isModal = false;\n resolve();\n\n // Restore focus to the original trigger\n if (\n this.originalTrigger &&\n typeof this.originalTrigger.focus === 'function'\n ) {\n setTimeout(() => this.originalTrigger.focus());\n }\n };\n\n this.host.addEventListener('nanoAfterShow', onOpen, { once: true });\n this.host.addEventListener('nanoaftershow', onOpen, { once: true });\n\n this.host.addEventListener('nanoAfterHide', onClose, {\n once: true,\n });\n this.host.addEventListener('nanoafterhide', onClose, {\n once: true,\n });\n });\n }\n\n private handleMouseMove = () => {\n this.restartAutoHide();\n };\n\n private handleCloseClick = () => {\n this.hide();\n };\n\n private handleTransitionEnd = (event: TransitionEvent) => {\n if (\n event.propertyName === 'opacity' &&\n (event.target === this.panel || event.target === this.overlay)\n ) {\n this.host.hidden = !this.open;\n this.isShowing = this.open;\n this.open ? this.nanoAfterShow.emit() : this.nanoAfterHide.emit();\n }\n };\n\n private handleButtonClick = (e: PointerEvent & { target: HTMLElement }) => {\n if (e.defaultPrevented) return;\n if (e.target.tagName && e.target.tagName.toLowerCase() === 'button')\n this.hide();\n };\n\n private restartAutoHide = () => {\n clearTimeout(this.autoHideTimeout);\n if (this.open && this.duration < Infinity) {\n this.autoHideTimeout = setTimeout(() => this.hide(), this.duration);\n }\n };\n\n connectedCallback() {\n this.modal = new Modal(this.host);\n this.host.addEventListener('click', this.handleButtonClick);\n\n if (this.panel) {\n this.addedTransEnd = true;\n this.panel.addEventListener('transitionend', this.handleTransitionEnd);\n }\n }\n\n disconnectedCallback() {\n unlockBodyScrolling(this.host);\n this.host.removeEventListener('click', this.handleButtonClick);\n\n this.addedTransEnd = false;\n this.panel.removeEventListener('transitionend', this.handleTransitionEnd);\n }\n\n componentDidLoad() {\n // Show on init if open\n if (this.open) {\n this.show();\n }\n if (!this.addedTransEnd) {\n this.panel.addEventListener('transitionend', this.handleTransitionEnd);\n }\n }\n\n private Panel = (): VNode => {\n return (\n <div\n ref={(el) => (this.panel = el)}\n part=\"panel\"\n class={{\n alert: true,\n 'alert--open': this.open,\n 'alert--toasty': this.isToast,\n 'alert--modal': !!this.isModal,\n 'alert--showing': this.isShowing,\n }}\n role={!!this.isModal ? 'alertdialog' : 'alert'}\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n aria-hidden={this.open ? 'false' : 'true'}\n aria-modal={!!this.isModal ? 'true' : undefined}\n aria-label={this.label ? this.label : undefined}\n onMouseMove={this.handleMouseMove}\n tabIndex={!!this.isModal ? 0 : undefined}\n >\n <div class=\"alert__content\">\n <div part=\"icon\" class=\"alert__icon\">\n <slot name=\"icon\" />\n </div>\n <div part=\"message\" class=\"alert__message\">\n <slot />\n </div>\n {this.closable && (\n <div class=\"alert__close\">\n <nano-icon-button\n class=\"alert__close\"\n iconName=\"light/times\"\n label=\"close menu\"\n onClick={this.handleCloseClick}\n ></nano-icon-button>\n </div>\n )}\n </div>\n <div class=\"alert__footer\">\n <slot name=\"footer\" />\n </div>\n </div>\n );\n };\n\n render() {\n return (\n <Host\n class={{ ...createColorClasses(this.color) }}\n showing={this.isShowing}\n >\n {this.isModal && [\n <div\n part=\"overlay\"\n class={{\n alert__overlay: true,\n 'alert__overlay--open': this.open,\n }}\n ref={(div) => (this.overlay = div)}\n />,\n <div class=\"alert__modal-wrap\">\n <this.Panel />\n </div>,\n ]}\n {!this.isModal && <this.Panel />}\n </Host>\n );\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ /*!
2
+ * Web Components for Nanopore digital Web Apps
3
+ */
4
+ import{r as t,c as e,h as i,a as r,g as s}from"./p-1fe12320.js";import{M as a}from"./p-c9a7c7ea.js";import{u as n,l as o}from"./p-885b6950.js";import"./p-45abbbdd.js";import"./p-845ae77e.js";const l=":host{box-sizing:border-box}*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}:host{position:relative;display:block;--size:25rem;--panel-background-color:white;--panel-shadow:0 4px 16px rgba(0, 0, 0, 0.1);--overlay-color:hsla(203, 10%, 20%, 0.5)}.drawer{inset-block-start:0;inset-inline-start:0;width:100%;height:100%;pointer-events:none;overflow:hidden}.drawer:not(.drawer--visible){position:absolute;inline-size:1px;block-size:1px;clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);overflow:hidden;pointer-events:none;visibility:hidden}.drawer--contained{position:absolute;z-index:initial}.drawer--fixed{position:fixed;z-index:2000}.drawer__panel{position:absolute;display:flex;flex-direction:column;z-index:2;max-width:100%;max-height:100%;background-color:var(--panel-background-color);box-shadow:var(--panel-shadow);transition:250ms transform;overflow:auto;pointer-events:all}.drawer__panel:focus{outline:none}.drawer--start .drawer__panel{transform:translate3d(-100%, 0, 0);inset-block:0 auto;width:var(--size);height:100%}.drawer--start .drawer__panel[dir=rtl]{transform:translate3d(calc(-1 * -100%), 0, 0)}.drawer--end .drawer__panel{transform:translate3d(100%, 0, 0);inset-block:0 auto;width:var(--size);height:100%}.drawer--end .drawer__panel[dir=rtl]{transform:translate3d(calc(-1 * 100%), 0, 0)}.drawer--top .drawer__panel{inset-inline:auto 0;inset-block:0 auto;width:100%;height:var(--size);transform:translate(0, -100%)}.drawer--bottom .drawer__panel{inset-inline:auto 0;inset-block:auto 0;width:100%;height:var(--size);transform:translate(0, 100%)}.drawer--open .drawer__panel{transform:translate(0, 0)}.drawer__header{display:flex}.drawer__title{flex:1 1 auto;padding:20px}.drawer__close{flex:0 0 auto;display:flex;align-items:center}.drawer__body{flex:1 1 auto;overflow:auto;-webkit-overflow-scrolling:touch}.drawer__footer{text-align:end}.drawer:not(.drawer--has-footer) .drawer__footer{display:none}.drawer__overlay{display:block;position:fixed;inset:0;background-color:var(--overlay-color);opacity:0;transition:250ms opacity;pointer-events:all}.drawer--contained .drawer__overlay{position:absolute}.drawer--open .drawer__overlay{opacity:1}";let h=0;const d=class{constructor(i){t(this,i);this.nanoShow=e(this,"nanoShow",7);this.nanoAfterShow=e(this,"nanoAfterShow",7);this.nanoHide=e(this,"nanoHide",7);this.nanoAfterHide=e(this,"nanoAfterHide",7);this.nanoOverlayDismiss=e(this,"nanoOverlayDismiss",7);this.componentId=`drawer-${++h}`;this.hasFooter=false;this.isVisible=false;this.open=false;this.label="";this.placement="end";this.contained=false;this.noHeader=false;this.type="overlay";this.contentSelector=undefined}handleOpenChange(){this.open?this.show():this.hide()}handleTypeChange(){if(this.type!=="push"&&this.type!=="reveal")return;if(!this.contentEle){this.type="overlay";console.warn("a valid contentSelector must be set");return}}handleContentSelector(){if(!this.contentSelector)this.contentEle=null;else this.contentEle=this.host.ownerDocument.querySelector(this.contentSelector)}connectedCallback(){this.handleCloseClick=this.handleCloseClick.bind(this);this.handleTransitionEnd=this.handleTransitionEnd.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);this.handleOverlayClick=this.handleOverlayClick.bind(this);this.handleSlotChange=this.handleSlotChange.bind(this);this.modal=new a(this.host)}componentWillLoad(){if(this.open){this.show()}this.handleContentSelector()}disconnectedCallback(){n(this.host)}async show(){if(this.isVisible){return}const t=this.nanoShow.emit();if(t.defaultPrevented){this.open=false;return}this.isVisible=true;this.open=true;if(!this.contained){this.modal.activate();o(this.host)}if(!this.contentEle||this.type!=="push"&&this.type!=="reveal")return;this.contentEle.style.right="0";this.contentEle.style.transition="all ease 250ms";this.contentEle.style.position="relative";this.contentEle.style.overflow="hidden";setTimeout((t=>this.contentEle.style.right="25rem"),0)}async hide(){if(!this.isVisible){return}const t=this.nanoHide.emit();if(t.defaultPrevented){this.open=true;return}this.open=false;this.modal.deactivate();n(this.host);if(!this.contentEle)return;this.contentEle.style.transition="";this.contentEle.style.position="";this.contentEle.style.overflow="";this.contentEle.style.right=""}handleCloseClick(){this.hide()}handleKeyDown(t){if(t.key==="Escape"){this.hide()}}handleOverlayClick(){const t=this.nanoOverlayDismiss.emit();if(!t.defaultPrevented){this.hide()}}handleSlotChange(){this.hasFooter=!!this.host.querySelector('[slot="footer"]')}handleTransitionEnd(t){const e=t.target;if(t.propertyName==="transform"&&e.classList.contains("drawer__panel")){this.isVisible=this.open;this.open?this.nanoAfterShow.emit():this.nanoAfterHide.emit();if(this.open){this.panel.focus()}}}render(){const t="drawer--"+this.placement;const e="drawer--"+this.type;return i(r,null,i("div",{part:"base",class:{drawer:true,"drawer--open":this.open,"drawer--visible":this.isVisible,[e]:true,[t]:true,"drawer--contained":this.contained,"drawer--fixed":!this.contained,"drawer--has-footer":this.hasFooter},onKeyDown:this.handleKeyDown,onTransitionEnd:this.handleTransitionEnd},i("div",{part:"overlay",class:"drawer__overlay",onClick:this.handleOverlayClick}),i("div",{ref:t=>this.panel=t,part:"panel",class:"drawer__panel",role:"dialog","aria-modal":"true","aria-hidden":this.open?"false":"true","aria-label":this.noHeader?this.label:null,"aria-labelledby":!this.noHeader?`${this.componentId}-title`:null,tabIndex:0},!this.noHeader&&i("header",{part:"header",class:"drawer__header"},i("span",{part:"title",class:"drawer__title",id:`${this.componentId}-title`},i("slot",{name:"label"},this.label||String.fromCharCode(65279)))),i("div",{part:"body",class:"drawer__body"},i("slot",null)),i("footer",{part:"footer",class:"drawer__footer"},i("slot",{name:"footer",onSlotchange:this.handleSlotChange})))))}get host(){return s(this)}static get watchers(){return{open:["handleOpenChange"],type:["handleTypeChange"],contentSelector:["handleContentSelector"]}}};d.style=l;export{d as nano_drawer};
5
+ //# sourceMappingURL=p-41addb3a.entry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["src/components/drawer/drawer.scss?tag=nano-drawer&encapsulation=shadow","src/components/drawer/drawer.tsx"],"names":["drawerCss","id","Drawer","this","componentId","[object Object]","open","show","hide","type","contentEle","console","warn","contentSelector","host","ownerDocument","querySelector","handleCloseClick","bind","handleTransitionEnd","handleKeyDown","handleOverlayClick","handleSlotChange","modal","Modal","handleContentSelector","unlockBodyScrolling","isVisible","nanoShow","emit","defaultPrevented","contained","activate","lockBodyScrolling","style","right","transition","position","overflow","setTimeout","_","nanoHide","deactivate","event","key","slOverlayDismiss","nanoOverlayDismiss","hasFooter","target","propertyName","classList","contains","nanoAfterShow","nanoAfterHide","panel","focus","placementClass","placement","typeClass","h","Host","part","class","drawer","drawer--open","drawer--visible","drawer--contained","drawer--fixed","drawer--has-footer","onKeyDown","onTransitionEnd","onClick","ref","el","role","aria-modal","aria-hidden","aria-label","noHeader","label","aria-labelledby","tabIndex","name","String","fromCharCode","onSlotchange"],"mappings":"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","sourcesContent":["@import '../../global/style/utilities/globals';\n@import '../../global/style/utilities/css-patterns/visually_hidden';\n\n:host {\n /**\n * @prop --size: The preferred size of the drawer; width or height depending on placement. Note that the drawer will shrink to accommodate smaller screens. Defaults to 25rem\n * @prop --panel-background-color: background color of panel. Default to 'white'\n * @prop --panel-shadow: Defaults to '0 4px 16px rgba(0, 0, 0, 0.1)';\n * @prop --overlay-color: Defaults to 'hsla(203, 10%, 20%, 0.5)';\n */\n\n position: relative;\n display: block;\n\n --size: 25rem;\n --panel-background-color: white;\n --panel-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n --overlay-color: hsla(203, 10%, 20%, 0.5);\n}\n\n.drawer {\n inset-block-start: 0;\n inset-inline-start: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n overflow: hidden;\n\n &:not(.drawer--visible) {\n @include hidden;\n }\n}\n\n.drawer--contained {\n position: absolute;\n z-index: initial;\n}\n\n.drawer--fixed {\n position: fixed;\n z-index: 2000;\n}\n\n.drawer__panel {\n position: absolute;\n display: flex;\n flex-direction: column;\n z-index: 2;\n max-width: 100%;\n max-height: 100%;\n background-color: var(--panel-background-color);\n box-shadow: var(--panel-shadow);\n transition: 250ms transform;\n overflow: auto;\n pointer-events: all;\n\n &:focus {\n outline: none;\n }\n}\n\n.drawer--start .drawer__panel {\n @include transform(translate3d(-100%, 0, 0));\n\n inset-block: 0 auto;\n width: var(--size);\n height: 100%;\n}\n\n.drawer--end .drawer__panel {\n @include transform(translate3d(100%, 0, 0));\n\n inset-block: 0 auto;\n width: var(--size);\n height: 100%;\n}\n\n.drawer--top .drawer__panel {\n inset-inline: auto 0;\n inset-block: 0 auto;\n width: 100%;\n height: var(--size);\n transform: translate(0, -100%);\n}\n\n.drawer--bottom .drawer__panel {\n inset-inline: auto 0;\n inset-block: auto 0;\n width: 100%;\n height: var(--size);\n transform: translate(0, 100%);\n}\n\n.drawer--open .drawer__panel {\n transform: translate(0, 0);\n}\n\n.drawer__header {\n display: flex;\n}\n\n.drawer__title {\n flex: 1 1 auto;\n // font-size: var(--sl-font-size-large);\n // line-height: var(--sl-line-height-dense);\n padding: 20px;\n}\n\n.drawer__close {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n // font-size: var(--sl-font-size-x-large);\n // padding: 0 var(--sl-spacing-large);\n}\n\n.drawer__body {\n flex: 1 1 auto;\n // padding: var(--sl-spacing-large);\n overflow: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.drawer__footer {\n text-align: end;\n // padding: var(--sl-spacing-large);\n\n // ::slotted(sl-button:not(:last-of-type)) {\n // margin-right: var(--sl-spacing-x-small);\n // }\n}\n\n.drawer:not(.drawer--has-footer) .drawer__footer {\n display: none;\n}\n\n.drawer__overlay {\n display: block;\n position: fixed;\n inset: 0;\n background-color: var(--overlay-color);\n opacity: 0;\n transition: 250ms opacity;\n pointer-events: all;\n}\n\n.drawer--contained .drawer__overlay {\n position: absolute;\n}\n\n.drawer--open .drawer__overlay {\n opacity: 1;\n}\n","import {\n Component,\n Element,\n Event,\n EventEmitter,\n Method,\n Prop,\n State,\n Watch,\n h,\n Host,\n} from '@stencil/core';\nimport Modal from '../../utils/modal';\nimport { lockBodyScrolling, unlockBodyScrolling } from '../../utils/scroll';\n\nlet id = 0;\n\n/**\n * WIP / TODO. https://git.oxfordnanolabs.local/Digital/nano-components/-/issues/24\n * @slot - The drawer's content.\n * @slot label - The dialog's label. Alternatively, you can use the label prop.\n * @slot footer - The drawer's footer, usually one or more buttons representing various options.\n */\n@Component({\n tag: 'nano-drawer',\n styleUrl: 'drawer.scss',\n shadow: true,\n})\nexport class Drawer {\n private componentId = `drawer-${++id}`;\n private modal: Modal;\n private panel: HTMLElement;\n private contentEle: HTMLElement;\n\n @Element() host: HTMLNanoDrawerElement;\n\n @State() hasFooter = false;\n @State() isVisible = false;\n\n /**\n * Indicates whether or not the drawer is open. You can use this in lieu of the show/hide methods.\n */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n /**\n * The drawer's label as displayed in the header. You should always include a relevant label even when using\n * `no-header`, as it is required for proper accessibility.\n */\n @Prop() label = '';\n\n /** The direction from which the drawer will open. */\n @Prop() placement: 'top' | 'end' | 'bottom' | 'start' = 'end';\n\n /**\n * By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of\n * its parent element, set this prop and add `position: relative` to the parent.\n */\n @Prop() contained = false;\n\n /**\n * Removes the header. This will also remove the default close button, so please ensure you provide an easy,\n * accessible way for users to dismiss the drawer.\n */\n @Prop() noHeader = false;\n\n /**\n * The display type of the drawer\n */\n @Prop() type: 'overlay' | 'reveal' | 'push' = 'overlay';\n\n /**\n * Required for 'reveal' and 'push' types\n * A valid DOM selector of the content element that this drawer will push or reveal underneath\n * Please remember - elements wrapping the content element must be 'overflow: hidden'\n * otherwise menus will be shown when closed\n */\n @Prop() contentSelector: string;\n\n @Watch('open')\n handleOpenChange() {\n this.open ? this.show() : this.hide();\n }\n\n @Watch('type')\n handleTypeChange() {\n if (this.type !== 'push' && this.type !== 'reveal') return;\n if (!this.contentEle) {\n this.type = 'overlay';\n console.warn('a valid contentSelector must be set');\n return;\n }\n }\n\n @Watch('contentSelector')\n handleContentSelector() {\n if (!this.contentSelector) this.contentEle = null;\n else\n this.contentEle = (this.host.ownerDocument as Document).querySelector(\n this.contentSelector\n );\n }\n\n /**\n * Emitted when the drawer opens. Calling `event.preventDefault()` will prevent it from being opened.\n */\n @Event() nanoShow: EventEmitter;\n\n /**\n * Emitted after the drawer opens and all transitions are complete.\n */\n @Event() nanoAfterShow: EventEmitter;\n\n /**\n * Emitted when the drawer closes. Calling `event.preventDefault()` will prevent it from being closed.\n */\n @Event() nanoHide: EventEmitter;\n\n /**\n * Emitted after the drawer closes and all transitions are complete.\n */\n @Event() nanoAfterHide: EventEmitter;\n\n /**\n * Emitted when the overlay is clicked. Calling `event.preventDefault()` will prevent the drawer from closing.\n */\n @Event() nanoOverlayDismiss: EventEmitter;\n\n connectedCallback() {\n this.handleCloseClick = this.handleCloseClick.bind(this);\n this.handleTransitionEnd = this.handleTransitionEnd.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleOverlayClick = this.handleOverlayClick.bind(this);\n this.handleSlotChange = this.handleSlotChange.bind(this);\n\n this.modal = new Modal(this.host);\n }\n\n componentWillLoad() {\n // Show on init if open\n if (this.open) {\n this.show();\n }\n this.handleContentSelector();\n }\n\n disconnectedCallback() {\n unlockBodyScrolling(this.host);\n }\n\n /** Shows the drawer */\n @Method()\n async show() {\n // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher\n if (this.isVisible) {\n return;\n }\n\n const nanoShow = this.nanoShow.emit();\n if (nanoShow.defaultPrevented) {\n this.open = false;\n return;\n }\n\n this.isVisible = true;\n this.open = true;\n\n // Lock body scrolling only if the drawer isn't contained\n if (!this.contained) {\n this.modal.activate();\n lockBodyScrolling(this.host);\n }\n\n if (!this.contentEle || (this.type !== 'push' && this.type !== 'reveal'))\n return;\n this.contentEle.style.right = '0';\n this.contentEle.style.transition = 'all ease 250ms';\n this.contentEle.style.position = 'relative';\n this.contentEle.style.overflow = 'hidden';\n setTimeout((_) => (this.contentEle.style.right = '25rem'), 0);\n }\n\n /** Hides the drawer */\n @Method()\n async hide() {\n // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher\n if (!this.isVisible) {\n return;\n }\n\n const nanoHide = this.nanoHide.emit();\n if (nanoHide.defaultPrevented) {\n this.open = true;\n return;\n }\n\n this.open = false;\n this.modal.deactivate();\n\n unlockBodyScrolling(this.host);\n\n if (!this.contentEle) return;\n this.contentEle.style.transition = '';\n this.contentEle.style.position = '';\n this.contentEle.style.overflow = '';\n this.contentEle.style.right = '';\n }\n\n private handleCloseClick() {\n this.hide();\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n this.hide();\n }\n }\n\n private handleOverlayClick() {\n const slOverlayDismiss = this.nanoOverlayDismiss.emit();\n\n if (!slOverlayDismiss.defaultPrevented) {\n this.hide();\n }\n }\n\n private handleSlotChange() {\n this.hasFooter = !!this.host.querySelector('[slot=\"footer\"]');\n }\n\n private handleTransitionEnd(event: TransitionEvent) {\n const target = event.target as HTMLElement;\n\n // Ensure we only emit one event when the target element is no longer visible\n if (\n event.propertyName === 'transform' &&\n target.classList.contains('drawer__panel')\n ) {\n this.isVisible = this.open;\n this.open ? this.nanoAfterShow.emit() : this.nanoAfterHide.emit();\n\n if (this.open) {\n this.panel.focus();\n }\n }\n }\n\n render() {\n const placementClass = 'drawer--' + this.placement;\n const typeClass = 'drawer--' + this.type;\n\n return (\n <Host>\n <div\n part=\"base\"\n class={{\n drawer: true,\n 'drawer--open': this.open,\n 'drawer--visible': this.isVisible,\n [typeClass]: true,\n [placementClass]: true,\n 'drawer--contained': this.contained,\n 'drawer--fixed': !this.contained,\n 'drawer--has-footer': this.hasFooter,\n }}\n onKeyDown={this.handleKeyDown}\n onTransitionEnd={this.handleTransitionEnd}\n >\n <div\n part=\"overlay\"\n class=\"drawer__overlay\"\n onClick={this.handleOverlayClick}\n />\n\n <div\n ref={(el) => (this.panel = el)}\n part=\"panel\"\n class=\"drawer__panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-hidden={this.open ? 'false' : 'true'}\n aria-label={this.noHeader ? this.label : null}\n aria-labelledby={\n !this.noHeader ? `${this.componentId}-title` : null\n }\n tabIndex={0}\n >\n {!this.noHeader && (\n <header part=\"header\" class=\"drawer__header\">\n <span\n part=\"title\"\n class=\"drawer__title\"\n id={`${this.componentId}-title`}\n >\n <slot name=\"label\">\n {/* If there's no label, use an invisible character to prevent the heading from collapsing */}\n {this.label || String.fromCharCode(65279)}\n </slot>\n </span>\n {/* <sl-icon-button part=\"close-button\" class=\"drawer__close\" name=\"x\" onClick={this.handleCloseClick} /> */}\n </header>\n )}\n\n <div part=\"body\" class=\"drawer__body\">\n <slot />\n </div>\n\n <footer part=\"footer\" class=\"drawer__footer\">\n <slot name=\"footer\" onSlotchange={this.handleSlotChange} />\n </footer>\n </div>\n </div>\n </Host>\n );\n }\n}\n"]}
1
+ {"version":3,"sources":["src/components/drawer/drawer.scss?tag=nano-drawer&encapsulation=shadow","src/components/drawer/drawer.tsx"],"names":["drawerCss","id","Drawer","this","componentId","[object Object]","open","show","hide","type","contentEle","console","warn","contentSelector","host","ownerDocument","querySelector","handleCloseClick","bind","handleTransitionEnd","handleKeyDown","handleOverlayClick","handleSlotChange","modal","Modal","handleContentSelector","unlockBodyScrolling","isVisible","nanoShow","emit","defaultPrevented","contained","activate","lockBodyScrolling","style","right","transition","position","overflow","setTimeout","_","nanoHide","deactivate","event","key","slOverlayDismiss","nanoOverlayDismiss","hasFooter","target","propertyName","classList","contains","nanoAfterShow","nanoAfterHide","panel","focus","placementClass","placement","typeClass","h","Host","part","class","drawer","drawer--open","drawer--visible","drawer--contained","drawer--fixed","drawer--has-footer","onKeyDown","onTransitionEnd","onClick","ref","el","role","aria-modal","aria-hidden","aria-label","noHeader","label","aria-labelledby","tabIndex","name","String","fromCharCode","onSlotchange"],"mappings":"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","sourcesContent":["@import '../../global/style/utilities/globals';\n@import '../../global/style/utilities/css-patterns/visually_hidden';\n\n:host {\n /**\n * @prop --size: The preferred size of the drawer; width or height depending on placement. Note that the drawer will shrink to accommodate smaller screens. Defaults to 25rem\n * @prop --panel-background-color: background color of panel. Default to 'white'\n * @prop --panel-shadow: Defaults to '0 4px 16px rgba(0, 0, 0, 0.1)';\n * @prop --overlay-color: Defaults to 'hsla(203, 10%, 20%, 0.5)';\n */\n\n position: relative;\n display: block;\n\n --size: 25rem;\n --panel-background-color: white;\n --panel-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n --overlay-color: hsla(203, 10%, 20%, 0.5);\n}\n\n.drawer {\n inset-block-start: 0;\n inset-inline-start: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n overflow: hidden;\n\n &:not(.drawer--visible) {\n @include hidden;\n }\n}\n\n.drawer--contained {\n position: absolute;\n z-index: initial;\n}\n\n.drawer--fixed {\n position: fixed;\n z-index: 2000;\n}\n\n.drawer__panel {\n position: absolute;\n display: flex;\n flex-direction: column;\n z-index: 2;\n max-width: 100%;\n max-height: 100%;\n background-color: var(--panel-background-color);\n box-shadow: var(--panel-shadow);\n transition: 250ms transform;\n overflow: auto;\n pointer-events: all;\n\n &:focus {\n outline: none;\n }\n}\n\n.drawer--start .drawer__panel {\n @include transform(translate3d(-100%, 0, 0));\n\n inset-block: 0 auto;\n width: var(--size);\n height: 100%;\n}\n\n.drawer--end .drawer__panel {\n @include transform(translate3d(100%, 0, 0));\n\n inset-block: 0 auto;\n width: var(--size);\n height: 100%;\n}\n\n.drawer--top .drawer__panel {\n inset-inline: auto 0;\n inset-block: 0 auto;\n width: 100%;\n height: var(--size);\n transform: translate(0, -100%);\n}\n\n.drawer--bottom .drawer__panel {\n inset-inline: auto 0;\n inset-block: auto 0;\n width: 100%;\n height: var(--size);\n transform: translate(0, 100%);\n}\n\n.drawer--open .drawer__panel {\n transform: translate(0, 0);\n}\n\n.drawer__header {\n display: flex;\n}\n\n.drawer__title {\n flex: 1 1 auto;\n // font-size: var(--sl-font-size-large);\n // line-height: var(--sl-line-height-dense);\n padding: 20px;\n}\n\n.drawer__close {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n // font-size: var(--sl-font-size-x-large);\n // padding: 0 var(--sl-spacing-large);\n}\n\n.drawer__body {\n flex: 1 1 auto;\n // padding: var(--sl-spacing-large);\n overflow: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.drawer__footer {\n text-align: end;\n // padding: var(--sl-spacing-large);\n\n // ::slotted(sl-button:not(:last-of-type)) {\n // margin-right: var(--sl-spacing-x-small);\n // }\n}\n\n.drawer:not(.drawer--has-footer) .drawer__footer {\n display: none;\n}\n\n.drawer__overlay {\n display: block;\n position: fixed;\n inset: 0;\n background-color: var(--overlay-color);\n opacity: 0;\n transition: 250ms opacity;\n pointer-events: all;\n}\n\n.drawer--contained .drawer__overlay {\n position: absolute;\n}\n\n.drawer--open .drawer__overlay {\n opacity: 1;\n}\n","import {\n Component,\n Element,\n Event,\n EventEmitter,\n Method,\n Prop,\n State,\n Watch,\n h,\n Host,\n} from '@stencil/core';\nimport Modal from '../../utils/modal';\nimport { lockBodyScrolling, unlockBodyScrolling } from '../../utils/scroll';\n\nlet id = 0;\n\n/**\n * WIP / TODO. https://git.oxfordnanolabs.local/Digital/nano-components/-/issues/24\n * @slot - The drawer's content.\n * @slot label - The dialog's label. Alternatively, you can use the label prop.\n * @slot footer - The drawer's footer, usually one or more buttons representing various options.\n */\n@Component({\n tag: 'nano-drawer',\n styleUrl: 'drawer.scss',\n shadow: true,\n})\nexport class Drawer {\n private componentId = `drawer-${++id}`;\n private modal: Modal;\n private panel: HTMLElement;\n private contentEle: HTMLElement;\n\n @Element() host: HTMLNanoDrawerElement;\n\n @State() hasFooter = false;\n @State() isVisible = false;\n\n /**\n * Indicates whether or not the drawer is open. You can use this in lieu of the show/hide methods.\n */\n @Prop({ mutable: true, reflect: true }) open = false;\n\n /**\n * The drawer's label as displayed in the header. You should always include a relevant label even when using\n * `no-header`, as it is required for proper accessibility.\n */\n @Prop() label = '';\n\n /** The direction from which the drawer will open. */\n @Prop() placement: 'top' | 'end' | 'bottom' | 'start' = 'end';\n\n /**\n * By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of\n * its parent element, set this prop and add `position: relative` to the parent.\n */\n @Prop() contained = false;\n\n /**\n * Removes the header. This will also remove the default close button, so please ensure you provide an easy,\n * accessible way for users to dismiss the drawer.\n */\n @Prop() noHeader = false;\n\n /**\n * The display type of the drawer\n */\n @Prop() type: 'overlay' | 'reveal' | 'push' = 'overlay';\n\n /**\n * Required for 'reveal' and 'push' types\n * A valid DOM selector of the content element that this drawer will push or reveal underneath\n * Please remember - elements wrapping the content element must be 'overflow: hidden'\n * otherwise menus will be shown when closed\n */\n @Prop() contentSelector: string;\n\n @Watch('open')\n handleOpenChange() {\n this.open ? this.show() : this.hide();\n }\n\n @Watch('type')\n handleTypeChange() {\n if (this.type !== 'push' && this.type !== 'reveal') return;\n if (!this.contentEle) {\n this.type = 'overlay';\n console.warn('a valid contentSelector must be set');\n return;\n }\n }\n\n @Watch('contentSelector')\n handleContentSelector() {\n if (!this.contentSelector) this.contentEle = null;\n else\n this.contentEle = (this.host.ownerDocument as Document).querySelector(\n this.contentSelector\n );\n }\n\n /**\n * Emitted when the drawer opens. Calling `event.preventDefault()` will prevent it from being opened.\n */\n @Event() nanoShow: EventEmitter;\n\n /**\n * Emitted after the drawer opens and all transitions are complete.\n */\n @Event() nanoAfterShow: EventEmitter;\n\n /**\n * Emitted when the drawer closes. Calling `event.preventDefault()` will prevent it from being closed.\n */\n @Event() nanoHide: EventEmitter;\n\n /**\n * Emitted after the drawer closes and all transitions are complete.\n */\n @Event() nanoAfterHide: EventEmitter;\n\n /**\n * Emitted when the overlay is clicked. Calling `event.preventDefault()` will prevent the drawer from closing.\n */\n @Event() nanoOverlayDismiss: EventEmitter;\n\n connectedCallback() {\n this.handleCloseClick = this.handleCloseClick.bind(this);\n this.handleTransitionEnd = this.handleTransitionEnd.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleOverlayClick = this.handleOverlayClick.bind(this);\n this.handleSlotChange = this.handleSlotChange.bind(this);\n\n this.modal = new Modal(this.host);\n }\n\n componentWillLoad() {\n // Show on init if open\n if (this.open) {\n this.show();\n }\n this.handleContentSelector();\n }\n\n disconnectedCallback() {\n unlockBodyScrolling(this.host);\n }\n\n /** Shows the drawer */\n @Method()\n async show() {\n // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher\n if (this.isVisible) {\n return;\n }\n\n const nanoShow = this.nanoShow.emit();\n if (nanoShow.defaultPrevented) {\n this.open = false;\n return;\n }\n\n this.isVisible = true;\n this.open = true;\n\n // Lock body scrolling only if the drawer isn't contained\n if (!this.contained) {\n this.modal.activate();\n lockBodyScrolling(this.host);\n }\n\n if (!this.contentEle || (this.type !== 'push' && this.type !== 'reveal'))\n return;\n this.contentEle.style.right = '0';\n this.contentEle.style.transition = 'all ease 250ms';\n this.contentEle.style.position = 'relative';\n this.contentEle.style.overflow = 'hidden';\n setTimeout((_) => (this.contentEle.style.right = '25rem'), 0);\n }\n\n /** Hides the drawer */\n @Method()\n async hide() {\n // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher\n if (!this.isVisible) {\n return;\n }\n\n const nanoHide = this.nanoHide.emit();\n if (nanoHide.defaultPrevented) {\n this.open = true;\n return;\n }\n\n this.open = false;\n this.modal.deactivate();\n\n unlockBodyScrolling(this.host);\n\n if (!this.contentEle) return;\n this.contentEle.style.transition = '';\n this.contentEle.style.position = '';\n this.contentEle.style.overflow = '';\n this.contentEle.style.right = '';\n }\n\n private handleCloseClick() {\n this.hide();\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n this.hide();\n }\n }\n\n private handleOverlayClick() {\n const slOverlayDismiss = this.nanoOverlayDismiss.emit();\n\n if (!slOverlayDismiss.defaultPrevented) {\n this.hide();\n }\n }\n\n private handleSlotChange() {\n this.hasFooter = !!this.host.querySelector('[slot=\"footer\"]');\n }\n\n private handleTransitionEnd(event: TransitionEvent) {\n const target = event.target as HTMLElement;\n\n // Ensure we only emit one event when the target element is no longer visible\n if (\n event.propertyName === 'transform' &&\n target.classList.contains('drawer__panel')\n ) {\n this.isVisible = this.open;\n this.open ? this.nanoAfterShow.emit() : this.nanoAfterHide.emit();\n\n if (this.open) {\n this.panel.focus();\n }\n }\n }\n\n render() {\n const placementClass = 'drawer--' + this.placement;\n const typeClass = 'drawer--' + this.type;\n\n return (\n <Host>\n <div\n part=\"base\"\n class={{\n drawer: true,\n 'drawer--open': this.open,\n 'drawer--visible': this.isVisible,\n [typeClass]: true,\n [placementClass]: true,\n 'drawer--contained': this.contained,\n 'drawer--fixed': !this.contained,\n 'drawer--has-footer': this.hasFooter,\n }}\n onKeyDown={this.handleKeyDown}\n onTransitionEnd={this.handleTransitionEnd}\n >\n <div\n part=\"overlay\"\n class=\"drawer__overlay\"\n onClick={this.handleOverlayClick}\n />\n\n <div\n ref={(el) => (this.panel = el)}\n part=\"panel\"\n class=\"drawer__panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-hidden={this.open ? 'false' : 'true'}\n aria-label={this.noHeader ? this.label : null}\n aria-labelledby={\n !this.noHeader ? `${this.componentId}-title` : null\n }\n tabIndex={0}\n >\n {!this.noHeader && (\n <header part=\"header\" class=\"drawer__header\">\n <span\n part=\"title\"\n class=\"drawer__title\"\n id={`${this.componentId}-title`}\n >\n <slot name=\"label\">\n {/* If there's no label, use an invisible character to prevent the heading from collapsing */}\n {this.label || String.fromCharCode(65279)}\n </slot>\n </span>\n {/* <sl-icon-button part=\"close-button\" class=\"drawer__close\" name=\"x\" onClick={this.handleCloseClick} /> */}\n </header>\n )}\n\n <div part=\"body\" class=\"drawer__body\">\n <slot />\n </div>\n\n <footer part=\"footer\" class=\"drawer__footer\">\n <slot name=\"footer\" onSlotchange={this.handleSlotChange} />\n </footer>\n </div>\n </div>\n </Host>\n );\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /*!
2
2
  * Web Components for Nanopore digital Web Apps
3
3
  */
4
- function e(e){const t=e.tagName.toLowerCase();if(e.getAttribute("tabindex")==="-1"){return false}if(e.hasAttribute("disabled")){return false}if(e.hasAttribute("aria-disabled")&&e.getAttribute("aria-disabled")!=="false"){return false}if(e.hasAttribute("tabindex")){return true}if(e.hasAttribute("contenteditable")&&e.getAttribute("contenteditable")!=="false"){return true}if((t==="audio"||t==="video")&&e.hasAttribute("controls")){return true}if(t==="input"&&e.getAttribute("type")==="radio"&&!e.hasAttribute("checked")){return false}if(!e.offsetParent){return false}if(window.getComputedStyle(e).visibility==="hidden"){return false}return["button","input","select","textarea","a","audio","video","summary"].includes(t)}function t(n,r=false){const i=[];if(n instanceof HTMLElement){if(e(n)){i.push(n);if(r)return i}if(n.shadowRoot&&n.shadowRoot.mode==="open"){t(n.shadowRoot,r).map((e=>i.push(e)))}if(HTMLSlotElement&&n instanceof HTMLSlotElement){n.assignedElements().map((e=>{t(e,r).map((e=>i.push(e)))}))}}Array.from(n.querySelectorAll("*")).map((e=>{t(e,r).map((e=>i.push(e)))}));return i}function n(e){const n=t(e,true);return n.length?n[0]:null}export{n as a,t as g};
5
- //# sourceMappingURL=p-9a385481.js.map
4
+ function e(e){const t=e.tagName.toLowerCase();if(e.getAttribute("tabindex")==="-1"){return false}if(e.hasAttribute("disabled")){return false}if(e.hasAttribute("aria-disabled")&&e.getAttribute("aria-disabled")!=="false"){return false}if(e.hasAttribute("tabindex")){return true}if(e.hasAttribute("contenteditable")&&e.getAttribute("contenteditable")!=="false"){return true}if((t==="audio"||t==="video")&&e.hasAttribute("controls")){return true}if(t==="input"&&e.getAttribute("type")==="radio"&&!e.hasAttribute("checked")){return false}if(!e.offsetParent){return false}if(window.getComputedStyle(e).visibility==="hidden"){return false}return["button","input","select","textarea","a","audio","video","summary"].includes(t)}function t(n,i=false){const r=[];if(n instanceof HTMLElement){if(e(n)){r.push(n);if(i)return r}if(n.shadowRoot&&n.shadowRoot.mode==="open"){t(n.shadowRoot,i).map((e=>{if(!r.includes(e))r.push(e)}))}if(HTMLSlotElement&&n instanceof HTMLSlotElement){n.assignedElements().map((e=>{t(e,i).map((e=>{if(!r.includes(e))r.push(e)}))}))}}Array.from(n.querySelectorAll("*")).map((e=>{t(e,i).map((e=>{if(!r.includes(e))r.push(e)}))}));return r}function n(e){const n=t(e,true);return n.length?n[0]:null}export{n as a,t as g};
5
+ //# sourceMappingURL=p-45abbbdd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["src/utils/tabbable.ts"],"names":["isTabbable","el","tag","tagName","toLowerCase","getAttribute","hasAttribute","offsetParent","window","getComputedStyle","visibility","includes","getTabbableElements","root","first","tabbableElements","HTMLElement","push","shadowRoot","mode","map","HTMLSlotElement","assignedElements","slottedEl","Array","from","querySelectorAll","getNearestTabbableElement","length"],"mappings":";;;AACA,SAASA,EAAWC,GAClB,MAAMC,EAAMD,EAAGE,QAAQC,cAGvB,GAAIH,EAAGI,aAAa,cAAgB,KAAM,CACxC,OAAO,MAIT,GAAIJ,EAAGK,aAAa,YAAa,CAC/B,OAAO,MAIT,GACEL,EAAGK,aAAa,kBAChBL,EAAGI,aAAa,mBAAqB,QACrC,CACA,OAAO,MAIT,GAAIJ,EAAGK,aAAa,YAAa,CAC/B,OAAO,KAIT,GACEL,EAAGK,aAAa,oBAChBL,EAAGI,aAAa,qBAAuB,QACvC,CACA,OAAO,KAIT,IAAKH,IAAQ,SAAWA,IAAQ,UAAYD,EAAGK,aAAa,YAAa,CACvE,OAAO,KAIT,GACEJ,IAAQ,SACRD,EAAGI,aAAa,UAAY,UAC3BJ,EAAGK,aAAa,WACjB,CACA,OAAO,MAIT,IAAKL,EAAGM,aAAc,CACpB,OAAO,MAIT,GAAIC,OAAOC,iBAAiBR,GAAIS,aAAe,SAAU,CACvD,OAAO,MAIT,MAAO,CACL,SACA,QACA,SACA,WACA,IACA,QACA,QACA,WACAC,SAAST,YAKGU,EACdC,EACAC,EAAiB,OAEjB,MAAMC,EAAkC,GAExC,GAAIF,aAAgBG,YAAa,CAE/B,GAAIhB,EAAWa,GAAO,CACpBE,EAAiBE,KAAKJ,GAEtB,GAAIC,EAAO,OAAOC,EAIpB,GAAIF,EAAKK,YAAcL,EAAKK,WAAWC,OAAS,OAAQ,CACtDP,EAAoBC,EAAKK,WAAYJ,GAAOM,KAAKnB,IAC/C,IAAKc,EAAiBJ,SAASV,GAAKc,EAAiBE,KAAKhB,MAK9D,GAAIoB,iBAAmBR,aAAgBQ,gBAAiB,CACtDR,EAAKS,mBAAmBF,KAAKG,IAC3BX,EAAoBW,EAAWT,GAAOM,KAAKnB,IACzC,IAAKc,EAAiBJ,SAASV,GAAKc,EAAiBE,KAAKhB,UAOlEuB,MAAMC,KAAKZ,EAAKa,iBAAiB,MAAMN,KAAKnB,IAC1CW,EAAoBX,EAAIa,GAAOM,KAAKnB,IAClC,IAAKc,EAAiBJ,SAASV,GAAKc,EAAiBE,KAAKhB,SAI9D,OAAOc,WAGOY,EAA0B1B,GACxC,MAAMc,EAAmBH,EAAoBX,EAAmB,MAChE,OAAOc,EAAiBa,OAASb,EAAiB,GAAK","sourcesContent":["// Determines if the specified element is tabbable using heuristics inspired by https://github.com/focus-trap/tabbable\nfunction isTabbable(el: HTMLElement) {\n const tag = el.tagName.toLowerCase();\n\n // Elements with a -1 tab index are not tabbable\n if (el.getAttribute('tabindex') === '-1') {\n return false;\n }\n\n // Elements with a disabled attribute are not tabbable\n if (el.hasAttribute('disabled')) {\n return false;\n }\n\n // Elements with aria-disabled are not tabbable\n if (\n el.hasAttribute('aria-disabled') &&\n el.getAttribute('aria-disabled') !== 'false'\n ) {\n return false;\n }\n\n // Elements with a tabindex other than -1 are tabbable\n if (el.hasAttribute('tabindex')) {\n return true;\n }\n\n // Elements with a contenteditable attribute are tabbable\n if (\n el.hasAttribute('contenteditable') &&\n el.getAttribute('contenteditable') !== 'false'\n ) {\n return true;\n }\n\n // Audio and video elements with the controls attribute are tabbable\n if ((tag === 'audio' || tag === 'video') && el.hasAttribute('controls')) {\n return true;\n }\n\n // Radios without a checked attribute are not tabbable\n if (\n tag === 'input' &&\n el.getAttribute('type') === 'radio' &&\n !el.hasAttribute('checked')\n ) {\n return false;\n }\n\n // Elements that are hidden have no offsetParent and are not tabbable\n if (!el.offsetParent) {\n return false;\n }\n\n // Elements without visibility are not tabbable (calculated last due to performance)\n if (window.getComputedStyle(el).visibility === 'hidden') {\n return false;\n }\n\n // At this point, the following elements are considered tabbable\n return [\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'a',\n 'audio',\n 'video',\n 'summary',\n ].includes(tag);\n}\n\n// Locates all tabbable elements within an element. If the target element is tabbable, it will be included in the\n// resulting array. This function will also look in open shadow roots.\nexport function getTabbableElements(\n root: HTMLElement | ShadowRoot,\n first: boolean = false\n) {\n const tabbableElements: HTMLElement[] = [];\n\n if (root instanceof HTMLElement) {\n // Is the root element tabbable?\n if (isTabbable(root)) {\n tabbableElements.push(root);\n\n if (first) return tabbableElements;\n }\n\n // Look for tabbable elements in the shadow root\n if (root.shadowRoot && root.shadowRoot.mode === 'open') {\n getTabbableElements(root.shadowRoot, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n }\n\n // Look at slotted elements\n if (HTMLSlotElement && root instanceof HTMLSlotElement) {\n root.assignedElements().map((slottedEl: HTMLElement) => {\n getTabbableElements(slottedEl, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n }\n }\n\n // Look for tabbable elements in children\n Array.from(root.querySelectorAll('*')).map((el: HTMLElement) => {\n getTabbableElements(el, first).map((el) => {\n if (!tabbableElements.includes(el)) tabbableElements.push(el);\n });\n });\n\n return tabbableElements;\n}\n\nexport function getNearestTabbableElement(el: Element): HTMLElement | null {\n const tabbableElements = getTabbableElements(el as HTMLElement, true);\n return tabbableElements.length ? tabbableElements[0] : null;\n}\n"]}