@thinkpixellab-public/px-vue 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/.eslintrc.js +14 -0
  2. package/.prettierrc.js +10 -0
  3. package/LICENSE.md +9 -0
  4. package/README.md +83 -0
  5. package/assets/feather/activity.svg +1 -0
  6. package/assets/feather/airplay.svg +1 -0
  7. package/assets/feather/alert-circle.svg +1 -0
  8. package/assets/feather/alert-octagon.svg +1 -0
  9. package/assets/feather/alert-triangle.svg +1 -0
  10. package/assets/feather/align-center.svg +1 -0
  11. package/assets/feather/align-justify.svg +1 -0
  12. package/assets/feather/align-left.svg +1 -0
  13. package/assets/feather/align-right.svg +1 -0
  14. package/assets/feather/anchor.svg +1 -0
  15. package/assets/feather/aperture.svg +1 -0
  16. package/assets/feather/archive.svg +1 -0
  17. package/assets/feather/arrow-down-circle.svg +1 -0
  18. package/assets/feather/arrow-down-left.svg +1 -0
  19. package/assets/feather/arrow-down-right.svg +1 -0
  20. package/assets/feather/arrow-down.svg +1 -0
  21. package/assets/feather/arrow-left-circle.svg +1 -0
  22. package/assets/feather/arrow-left.svg +1 -0
  23. package/assets/feather/arrow-right-circle.svg +1 -0
  24. package/assets/feather/arrow-right.svg +1 -0
  25. package/assets/feather/arrow-up-circle.svg +1 -0
  26. package/assets/feather/arrow-up-left.svg +1 -0
  27. package/assets/feather/arrow-up-right.svg +1 -0
  28. package/assets/feather/arrow-up.svg +1 -0
  29. package/assets/feather/at-sign.svg +1 -0
  30. package/assets/feather/award.svg +1 -0
  31. package/assets/feather/bar-chart-2.svg +1 -0
  32. package/assets/feather/bar-chart.svg +1 -0
  33. package/assets/feather/battery-charging.svg +1 -0
  34. package/assets/feather/battery.svg +1 -0
  35. package/assets/feather/bell-off.svg +1 -0
  36. package/assets/feather/bell.svg +1 -0
  37. package/assets/feather/bluetooth.svg +1 -0
  38. package/assets/feather/bold.svg +1 -0
  39. package/assets/feather/book-open.svg +1 -0
  40. package/assets/feather/book.svg +1 -0
  41. package/assets/feather/bookmark.svg +1 -0
  42. package/assets/feather/box.svg +1 -0
  43. package/assets/feather/briefcase.svg +1 -0
  44. package/assets/feather/calendar.svg +1 -0
  45. package/assets/feather/camera-off.svg +1 -0
  46. package/assets/feather/camera.svg +1 -0
  47. package/assets/feather/cast.svg +1 -0
  48. package/assets/feather/check-circle.svg +1 -0
  49. package/assets/feather/check-square.svg +1 -0
  50. package/assets/feather/check.svg +1 -0
  51. package/assets/feather/chevron-down.svg +1 -0
  52. package/assets/feather/chevron-left.svg +1 -0
  53. package/assets/feather/chevron-right.svg +1 -0
  54. package/assets/feather/chevron-up.svg +1 -0
  55. package/assets/feather/chevrons-down.svg +1 -0
  56. package/assets/feather/chevrons-left.svg +1 -0
  57. package/assets/feather/chevrons-right.svg +1 -0
  58. package/assets/feather/chevrons-up.svg +1 -0
  59. package/assets/feather/chrome.svg +1 -0
  60. package/assets/feather/circle.svg +1 -0
  61. package/assets/feather/clipboard.svg +1 -0
  62. package/assets/feather/clock.svg +1 -0
  63. package/assets/feather/cloud-drizzle.svg +1 -0
  64. package/assets/feather/cloud-lightning.svg +1 -0
  65. package/assets/feather/cloud-off.svg +1 -0
  66. package/assets/feather/cloud-rain.svg +1 -0
  67. package/assets/feather/cloud-snow.svg +1 -0
  68. package/assets/feather/cloud.svg +1 -0
  69. package/assets/feather/code.svg +1 -0
  70. package/assets/feather/codepen.svg +1 -0
  71. package/assets/feather/codesandbox.svg +1 -0
  72. package/assets/feather/coffee.svg +1 -0
  73. package/assets/feather/columns.svg +1 -0
  74. package/assets/feather/command.svg +1 -0
  75. package/assets/feather/compass.svg +1 -0
  76. package/assets/feather/copy.svg +1 -0
  77. package/assets/feather/corner-down-left.svg +1 -0
  78. package/assets/feather/corner-down-right.svg +1 -0
  79. package/assets/feather/corner-left-down.svg +1 -0
  80. package/assets/feather/corner-left-up.svg +1 -0
  81. package/assets/feather/corner-right-down.svg +1 -0
  82. package/assets/feather/corner-right-up.svg +1 -0
  83. package/assets/feather/corner-up-left.svg +1 -0
  84. package/assets/feather/corner-up-right.svg +1 -0
  85. package/assets/feather/cpu.svg +1 -0
  86. package/assets/feather/credit-card.svg +1 -0
  87. package/assets/feather/crop.svg +1 -0
  88. package/assets/feather/crosshair.svg +1 -0
  89. package/assets/feather/database.svg +1 -0
  90. package/assets/feather/delete.svg +1 -0
  91. package/assets/feather/disc.svg +1 -0
  92. package/assets/feather/divide-circle.svg +1 -0
  93. package/assets/feather/divide-square.svg +1 -0
  94. package/assets/feather/divide.svg +1 -0
  95. package/assets/feather/dollar-sign.svg +1 -0
  96. package/assets/feather/download-cloud.svg +1 -0
  97. package/assets/feather/download.svg +1 -0
  98. package/assets/feather/dribbble.svg +1 -0
  99. package/assets/feather/droplet.svg +1 -0
  100. package/assets/feather/edit-2.svg +1 -0
  101. package/assets/feather/edit-3.svg +1 -0
  102. package/assets/feather/edit.svg +1 -0
  103. package/assets/feather/external-link.svg +1 -0
  104. package/assets/feather/eye-off.svg +1 -0
  105. package/assets/feather/eye.svg +1 -0
  106. package/assets/feather/facebook.svg +1 -0
  107. package/assets/feather/fast-forward.svg +1 -0
  108. package/assets/feather/feather.svg +1 -0
  109. package/assets/feather/figma.svg +1 -0
  110. package/assets/feather/file-minus.svg +1 -0
  111. package/assets/feather/file-plus.svg +1 -0
  112. package/assets/feather/file-text.svg +1 -0
  113. package/assets/feather/file.svg +1 -0
  114. package/assets/feather/film.svg +1 -0
  115. package/assets/feather/filter.svg +1 -0
  116. package/assets/feather/flag.svg +1 -0
  117. package/assets/feather/folder-minus.svg +1 -0
  118. package/assets/feather/folder-plus.svg +1 -0
  119. package/assets/feather/folder.svg +1 -0
  120. package/assets/feather/framer.svg +1 -0
  121. package/assets/feather/frown.svg +1 -0
  122. package/assets/feather/gift.svg +1 -0
  123. package/assets/feather/git-branch.svg +1 -0
  124. package/assets/feather/git-commit.svg +1 -0
  125. package/assets/feather/git-merge.svg +1 -0
  126. package/assets/feather/git-pull-request.svg +1 -0
  127. package/assets/feather/github.svg +1 -0
  128. package/assets/feather/gitlab.svg +1 -0
  129. package/assets/feather/globe.svg +1 -0
  130. package/assets/feather/grid.svg +1 -0
  131. package/assets/feather/hard-drive.svg +1 -0
  132. package/assets/feather/hash.svg +1 -0
  133. package/assets/feather/headphones.svg +1 -0
  134. package/assets/feather/heart.svg +1 -0
  135. package/assets/feather/help-circle.svg +1 -0
  136. package/assets/feather/hexagon.svg +1 -0
  137. package/assets/feather/home.svg +1 -0
  138. package/assets/feather/image.svg +1 -0
  139. package/assets/feather/inbox.svg +1 -0
  140. package/assets/feather/info.svg +1 -0
  141. package/assets/feather/instagram.svg +1 -0
  142. package/assets/feather/italic.svg +1 -0
  143. package/assets/feather/key.svg +1 -0
  144. package/assets/feather/layers.svg +1 -0
  145. package/assets/feather/layout.svg +1 -0
  146. package/assets/feather/life-buoy.svg +1 -0
  147. package/assets/feather/link-2.svg +1 -0
  148. package/assets/feather/link.svg +1 -0
  149. package/assets/feather/linkedin.svg +1 -0
  150. package/assets/feather/list.svg +1 -0
  151. package/assets/feather/loader.svg +1 -0
  152. package/assets/feather/lock.svg +1 -0
  153. package/assets/feather/log-in.svg +1 -0
  154. package/assets/feather/log-out.svg +1 -0
  155. package/assets/feather/mail.svg +1 -0
  156. package/assets/feather/map-pin.svg +1 -0
  157. package/assets/feather/map.svg +1 -0
  158. package/assets/feather/maximize-2.svg +1 -0
  159. package/assets/feather/maximize.svg +1 -0
  160. package/assets/feather/meh.svg +1 -0
  161. package/assets/feather/menu.svg +1 -0
  162. package/assets/feather/message-circle.svg +1 -0
  163. package/assets/feather/message-square.svg +1 -0
  164. package/assets/feather/mic-off.svg +1 -0
  165. package/assets/feather/mic.svg +1 -0
  166. package/assets/feather/minimize-2.svg +1 -0
  167. package/assets/feather/minimize.svg +1 -0
  168. package/assets/feather/minus-circle.svg +1 -0
  169. package/assets/feather/minus-square.svg +1 -0
  170. package/assets/feather/minus.svg +1 -0
  171. package/assets/feather/monitor.svg +1 -0
  172. package/assets/feather/moon.svg +1 -0
  173. package/assets/feather/more-horizontal.svg +1 -0
  174. package/assets/feather/more-vertical.svg +1 -0
  175. package/assets/feather/mouse-pointer.svg +1 -0
  176. package/assets/feather/move.svg +1 -0
  177. package/assets/feather/music.svg +1 -0
  178. package/assets/feather/navigation-2.svg +1 -0
  179. package/assets/feather/navigation.svg +1 -0
  180. package/assets/feather/octagon.svg +1 -0
  181. package/assets/feather/package.svg +1 -0
  182. package/assets/feather/paperclip.svg +1 -0
  183. package/assets/feather/pause-circle.svg +1 -0
  184. package/assets/feather/pause.svg +1 -0
  185. package/assets/feather/pen-tool.svg +1 -0
  186. package/assets/feather/percent.svg +1 -0
  187. package/assets/feather/phone-call.svg +1 -0
  188. package/assets/feather/phone-forwarded.svg +1 -0
  189. package/assets/feather/phone-incoming.svg +1 -0
  190. package/assets/feather/phone-missed.svg +1 -0
  191. package/assets/feather/phone-off.svg +1 -0
  192. package/assets/feather/phone-outgoing.svg +1 -0
  193. package/assets/feather/phone.svg +1 -0
  194. package/assets/feather/pie-chart.svg +1 -0
  195. package/assets/feather/play-circle.svg +1 -0
  196. package/assets/feather/play.svg +1 -0
  197. package/assets/feather/plus-circle.svg +1 -0
  198. package/assets/feather/plus-square.svg +1 -0
  199. package/assets/feather/plus.svg +1 -0
  200. package/assets/feather/pocket.svg +1 -0
  201. package/assets/feather/power.svg +1 -0
  202. package/assets/feather/printer.svg +1 -0
  203. package/assets/feather/radio.svg +1 -0
  204. package/assets/feather/refresh-ccw.svg +1 -0
  205. package/assets/feather/refresh-cw.svg +1 -0
  206. package/assets/feather/repeat.svg +1 -0
  207. package/assets/feather/rewind.svg +1 -0
  208. package/assets/feather/rotate-ccw.svg +1 -0
  209. package/assets/feather/rotate-cw.svg +1 -0
  210. package/assets/feather/rss.svg +1 -0
  211. package/assets/feather/save.svg +1 -0
  212. package/assets/feather/scissors.svg +1 -0
  213. package/assets/feather/search.svg +1 -0
  214. package/assets/feather/send.svg +1 -0
  215. package/assets/feather/server.svg +1 -0
  216. package/assets/feather/settings.svg +1 -0
  217. package/assets/feather/share-2.svg +1 -0
  218. package/assets/feather/share.svg +1 -0
  219. package/assets/feather/shield-off.svg +1 -0
  220. package/assets/feather/shield.svg +1 -0
  221. package/assets/feather/shopping-bag.svg +1 -0
  222. package/assets/feather/shopping-cart.svg +1 -0
  223. package/assets/feather/shuffle.svg +1 -0
  224. package/assets/feather/sidebar.svg +1 -0
  225. package/assets/feather/skip-back.svg +1 -0
  226. package/assets/feather/skip-forward.svg +1 -0
  227. package/assets/feather/slack.svg +1 -0
  228. package/assets/feather/slash.svg +1 -0
  229. package/assets/feather/sliders.svg +1 -0
  230. package/assets/feather/smartphone.svg +1 -0
  231. package/assets/feather/smile.svg +1 -0
  232. package/assets/feather/speaker.svg +1 -0
  233. package/assets/feather/square.svg +1 -0
  234. package/assets/feather/star.svg +1 -0
  235. package/assets/feather/stop-circle.svg +1 -0
  236. package/assets/feather/sun.svg +1 -0
  237. package/assets/feather/sunrise.svg +1 -0
  238. package/assets/feather/sunset.svg +1 -0
  239. package/assets/feather/table.svg +1 -0
  240. package/assets/feather/tablet.svg +1 -0
  241. package/assets/feather/tag.svg +1 -0
  242. package/assets/feather/target.svg +1 -0
  243. package/assets/feather/terminal.svg +1 -0
  244. package/assets/feather/thermometer.svg +1 -0
  245. package/assets/feather/thumbs-down.svg +1 -0
  246. package/assets/feather/thumbs-up.svg +1 -0
  247. package/assets/feather/toggle-left.svg +1 -0
  248. package/assets/feather/toggle-right.svg +1 -0
  249. package/assets/feather/tool.svg +1 -0
  250. package/assets/feather/trash-2.svg +1 -0
  251. package/assets/feather/trash.svg +1 -0
  252. package/assets/feather/trello.svg +1 -0
  253. package/assets/feather/trending-down.svg +1 -0
  254. package/assets/feather/trending-up.svg +1 -0
  255. package/assets/feather/triangle.svg +1 -0
  256. package/assets/feather/truck.svg +1 -0
  257. package/assets/feather/tv.svg +1 -0
  258. package/assets/feather/twitch.svg +1 -0
  259. package/assets/feather/twitter.svg +1 -0
  260. package/assets/feather/type.svg +1 -0
  261. package/assets/feather/umbrella.svg +1 -0
  262. package/assets/feather/underline.svg +1 -0
  263. package/assets/feather/unlock.svg +1 -0
  264. package/assets/feather/upload-cloud.svg +1 -0
  265. package/assets/feather/upload.svg +1 -0
  266. package/assets/feather/user-check.svg +1 -0
  267. package/assets/feather/user-minus.svg +1 -0
  268. package/assets/feather/user-plus.svg +1 -0
  269. package/assets/feather/user-x.svg +1 -0
  270. package/assets/feather/user.svg +1 -0
  271. package/assets/feather/users.svg +1 -0
  272. package/assets/feather/video-off.svg +1 -0
  273. package/assets/feather/video.svg +1 -0
  274. package/assets/feather/voicemail.svg +1 -0
  275. package/assets/feather/volume-1.svg +1 -0
  276. package/assets/feather/volume-2.svg +1 -0
  277. package/assets/feather/volume-x.svg +1 -0
  278. package/assets/feather/volume.svg +1 -0
  279. package/assets/feather/watch.svg +1 -0
  280. package/assets/feather/wifi-off.svg +1 -0
  281. package/assets/feather/wifi.svg +1 -0
  282. package/assets/feather/wind.svg +1 -0
  283. package/assets/feather/x-circle.svg +1 -0
  284. package/assets/feather/x-octagon.svg +1 -0
  285. package/assets/feather/x-square.svg +1 -0
  286. package/assets/feather/x.svg +1 -0
  287. package/assets/feather/youtube.svg +1 -0
  288. package/assets/feather/zap-off.svg +1 -0
  289. package/assets/feather/zap.svg +1 -0
  290. package/assets/feather/zoom-in.svg +1 -0
  291. package/assets/feather/zoom-out.svg +1 -0
  292. package/assets/icons/calendar.svg +6 -0
  293. package/assets/icons/check.svg +1 -0
  294. package/assets/icons/close-sm.svg +1 -0
  295. package/assets/icons/close.svg +1 -0
  296. package/assets/icons/copy.svg +1 -0
  297. package/assets/icons/dropdown.svg +8 -0
  298. package/assets/icons/invalid.svg +1 -0
  299. package/assets/icons/menu.svg +1 -0
  300. package/assets/icons/nav-next.svg +1 -0
  301. package/assets/icons/nav-prev.svg +1 -0
  302. package/assets/icons/sort-asc.svg +1 -0
  303. package/assets/icons/sort-desc.svg +1 -0
  304. package/assets/test/README.md +1 -0
  305. package/assets/test/trash.svg +8 -0
  306. package/babel.config.js +16 -0
  307. package/components/PxAspect.vue +127 -0
  308. package/components/PxAutoClamp.vue +75 -0
  309. package/components/PxBalancedText.vue +118 -0
  310. package/components/PxBase.vue +15 -0
  311. package/components/PxBaseDate.vue +27 -0
  312. package/components/PxBaseItems.vue +72 -0
  313. package/components/PxBaseItemsSelect.vue +230 -0
  314. package/components/PxBaseResize.vue +60 -0
  315. package/components/PxBaseToggle.vue +56 -0
  316. package/components/PxBaseVariants.vue +62 -0
  317. package/components/PxBaseVisible.vue +40 -0
  318. package/components/PxCalendar.vue +385 -0
  319. package/components/PxCard.vue +47 -0
  320. package/components/PxCardGrid.vue +386 -0
  321. package/components/PxClock.vue +510 -0
  322. package/components/PxCopyText.vue +78 -0
  323. package/components/PxDatePicker.vue +249 -0
  324. package/components/PxDropdown.vue +181 -0
  325. package/components/PxExpander.vue +46 -0
  326. package/components/PxFeatherIcon.vue +29 -0
  327. package/components/PxFeatherIconButton.vue +19 -0
  328. package/components/PxFit.vue +274 -0
  329. package/components/PxFlex.vue +93 -0
  330. package/components/PxFloat.vue +32 -0
  331. package/components/PxIcon.vue +43 -0
  332. package/components/PxIconButton.vue +115 -0
  333. package/components/PxIdUniquer.vue +59 -0
  334. package/components/PxModal.vue +365 -0
  335. package/components/PxNineGrid.vue +94 -0
  336. package/components/PxPivot.vue +207 -0
  337. package/components/PxPopup.vue +230 -0
  338. package/components/PxPortal.vue +138 -0
  339. package/components/PxPortalTarget.vue +25 -0
  340. package/components/PxProgressCircle.vue +73 -0
  341. package/components/PxRadioButton.vue +83 -0
  342. package/components/PxSideDrawer.vue +164 -0
  343. package/components/PxSlideTransition.vue +116 -0
  344. package/components/PxSlides.vue +217 -0
  345. package/components/PxStylesPreview.vue +129 -0
  346. package/components/PxSvg.vue +157 -0
  347. package/components/PxSwiper.vue +271 -0
  348. package/components/PxSwiperSlide.vue +42 -0
  349. package/components/PxSyncHeight.vue +137 -0
  350. package/components/PxTable.vue +323 -0
  351. package/components/PxTabs.vue +1 -0
  352. package/components/PxTextbox.vue +90 -0
  353. package/components/PxToggle.vue +125 -0
  354. package/components/PxToggleButton.vue +139 -0
  355. package/components/PxToggleButtonList.vue +131 -0
  356. package/components/PxTransitionExpand.vue +100 -0
  357. package/components/PxValidator.vue +431 -0
  358. package/components/PxVueTest.vue +761 -0
  359. package/components/README.md +0 -0
  360. package/dev/data/fruits.js +59 -0
  361. package/dev/data/random.js +13 -0
  362. package/dev/demos/Demo-PxBaseDrag.vue +94 -0
  363. package/dev/demos/Demo-PxCardGrid.vue +53 -0
  364. package/dev/demos/Demo-PxPivot.vue +58 -0
  365. package/dev/demos/Demo-PxSideDrawer.vue +72 -0
  366. package/dev/demos/Demo-PxSlideTransition.vue +86 -0
  367. package/dev/demos/Demo-PxSlides.vue +142 -0
  368. package/dev/demos/Demo-PxStylesPreview.vue +46 -0
  369. package/dev/demos/Demo-PxSwiper.vue +44 -0
  370. package/dev/demos/DemoPicker.vue +79 -0
  371. package/dev/dev.vue +56 -0
  372. package/dev/serve.js +17 -0
  373. package/package.json +45 -0
  374. package/plugins/common-client.js +13 -0
  375. package/plugins/common-lib.js +4 -0
  376. package/plugins/common.js +39 -0
  377. package/plugins/filters/aspect.js +14 -0
  378. package/plugins/filters/date.js +26 -0
  379. package/plugins/filters/kebab.js +9 -0
  380. package/plugins/filters/phone.js +7 -0
  381. package/plugins/filters/slug.js +26 -0
  382. package/plugins/filters/spacenator.js +11 -0
  383. package/plugins/filters/stringToItems.js +28 -0
  384. package/plugins/filters/striphtml.js +10 -0
  385. package/plugins/mixins/eventBus.js +23 -0
  386. package/px-styles.config.scss +12 -0
  387. package/styles/helpers.scss +14 -0
  388. package/styles/px.scss +6 -0
  389. package/utils/balanceText.js +123 -0
  390. package/utils/bem.js +99 -0
  391. package/utils/cardGrid.js +383 -0
  392. package/utils/cssStr.js +45 -0
  393. package/utils/drag.js +363 -0
  394. package/utils/fit.js +73 -0
  395. package/utils/tween.js +129 -0
  396. package/utils/utils.js +167 -0
  397. package/utils/variants.js +33 -0
  398. package/vue.config.js +12 -0
@@ -0,0 +1,365 @@
1
+ <!--
2
+
3
+ Usage:
4
+
5
+ <px-modal :visible.sync="modalVisible" labelled-by="#dlg-msg">
6
+ <div class="my-dialog">
7
+ <p id="dlg-msg">This is a message</p>
8
+ <button @click="modalVisible = false">Hide</button>
9
+ </div>
10
+ </px-modal>
11
+
12
+ <style>
13
+ // up to you to style the dialog element
14
+ .my-dialog { ... }
15
+ </style>
16
+
17
+ Resources:
18
+
19
+ - https://www.w3.org/TR/wai-aria-practices/#dialog_modal
20
+ - http://web-accessibility.carnegiemuseums.org/code/dialogs/
21
+ - https://github.com/GoogleChrome/dialog-polyfill
22
+ - https://vuejs.org/v2/examples/modal.html
23
+ - https://hiddedevries.nl/en/blog/2017-01-29-using-javascript-to-trap-focus-in-an-element
24
+ - https://github.com/edenspiekermann/a11y-dialog/blob/master/a11y-dialog.js
25
+ - https://github.com/willmcpo/body-scroll-lock
26
+
27
+ Check list (of what this component does):
28
+
29
+ [x] Add accessible properties (role="dialog", aria-modal, aria-labelledby)
30
+ [x] Place focus on first focusable element within the modal on opening
31
+ [x] Trap keyboard focus (e.g. focus cycles within the modal)
32
+ [x] Track element that was used to show the dialog and return focus when closing
33
+ [x] Support the "autofocus" attribute
34
+ [x] Escape key closes
35
+ [x] Disable scrolling on the body when the dialog is shown (uses body-scroll-lock)
36
+
37
+ Todo:
38
+
39
+ [ ] Add element attributes that can automatically wire up labelledby and describedby
40
+ [ ] Fix issue with returning focus to previous focused element in Firefox
41
+ [ ] Should we add some way to return a value when closing?
42
+
43
+ Implementation notes:
44
+
45
+ - We use v-show instead of v-if so that the dialog element is always in the
46
+ element tree, making it possible to keep references to the dialog element
47
+ from the parent component.
48
+
49
+
50
+
51
+ -->
52
+
53
+ <template>
54
+ <px-portal :disabled="!portalEnabled">
55
+ <transition :name="transitionName">
56
+ <div
57
+ v-show="visibleSync"
58
+ :class="['px-modal', modalClass]"
59
+ ref="modal"
60
+ :style="{ zIndex: zStart + currentLayerIndex }"
61
+ >
62
+ <div
63
+ v-if="hasOverlay"
64
+ ref="overlay"
65
+ :class="['px-modal__overlay', overlayClass]"
66
+ @click="onOverlayClick"
67
+ role="region"
68
+ >
69
+ <slot name="overlay-content" />
70
+ </div>
71
+ <div
72
+ ref="dialog"
73
+ :class="['px-modal__dialog', dialogClass]"
74
+ :aria-labelledby="labelledBy"
75
+ aria-modal="true"
76
+ role="dialog"
77
+ >
78
+ <slot />
79
+ </div>
80
+ </div>
81
+ </transition>
82
+ </px-portal>
83
+ </template>
84
+
85
+ <script>
86
+ import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
87
+ import PxPortal from './PxPortal.vue';
88
+
89
+ const TABABLE_ELEMENTS = [
90
+ 'button',
91
+ '[href]:not(.disabled)',
92
+ 'input',
93
+ 'select',
94
+ 'textarea',
95
+ '[tabindex]',
96
+ '[contenteditable]',
97
+ ];
98
+
99
+ // // Query the DOM for nodes matching the given selector, scoped to context (or
100
+ // // the whole document)
101
+ // function $$(selector, context) {
102
+ // if (!process.server) {
103
+ // return Array.prototype.slice.call((context || document).querySelectorAll(selector));
104
+ // }
105
+ // }
106
+
107
+ let globalLayerIndex = 0;
108
+
109
+ export default {
110
+ name: 'PxModal',
111
+ components: {
112
+ PxPortal,
113
+ },
114
+ props: {
115
+ // Controls whether the dialog is visible
116
+ visible: { type: Boolean, default: false },
117
+
118
+ // A class set on the popup itself (equivalent to just class on most components)
119
+ modalClass: { type: String, default: '' },
120
+
121
+ // A class set on the dialog element
122
+ dialogClass: { type: String, default: '' },
123
+
124
+ // A class set on the overlay element
125
+ overlayClass: { type: String, default: '' },
126
+
127
+ // Whether to enable the portal (foces element end of DOM)
128
+ portalEnabled: { type: Boolean, default: true },
129
+
130
+ // sets the aria-labelledby property on the dialog element
131
+ labelledBy: { type: String, default: '' },
132
+
133
+ // Controls whether the dialog is visible
134
+ hasOverlay: { type: Boolean, default: true },
135
+
136
+ // When true, click the overlay will close the popup
137
+ overlayClose: { type: Boolean, default: true },
138
+
139
+ // Name for a transition on the dialog element (the use of the portal
140
+ // means that the transition element needs to be internal to the component)
141
+ transitionName: { type: String, default: null },
142
+
143
+ // Selector to find the first element that gets focus when focus is set on the dialog
144
+ autoFocusSelector: { type: String, default: '[autofocus]' },
145
+
146
+ // automatically move focus to the contents of the modal when opened
147
+ autoFocusEnabled: { type: Boolean, default: true },
148
+
149
+ // automatically restore focus with then modal closes
150
+ restoreFocusEnabled: { type: Boolean, default: true },
151
+
152
+ // whether to disable scrolling when the modal is open
153
+ disablesScroll: { type: Boolean, default: true },
154
+
155
+ // if ture, esc key will close the popup
156
+ escCloses: { type: Boolean, default: true },
157
+
158
+ // The starting point for the z-index (note: incremented as more layers of popups are opened
159
+ // to ensure that the last opened from the same starting z will be on top of each other)
160
+ zStart: { type: Number, default: 999999 },
161
+ },
162
+
163
+ data() {
164
+ return {
165
+ visibleSync: false,
166
+ hideSource: null,
167
+ currentLayerIndex: 0,
168
+ };
169
+ },
170
+
171
+ watch: {
172
+ visible: {
173
+ immediate: true,
174
+ handler(nv) {
175
+ this.visibleSync = nv;
176
+ },
177
+ },
178
+
179
+ visibleSync: {
180
+ immediate: true,
181
+ handler(nv, ov) {
182
+ if (!process.server) {
183
+ // show
184
+ if (ov === false && nv === true) {
185
+ globalLayerIndex++;
186
+ this.currentLayerIndex = globalLayerIndex;
187
+ }
188
+
189
+ // hide
190
+ if (ov === true && nv === false) {
191
+ setTimeout(() => {
192
+ globalLayerIndex--;
193
+ }, 30);
194
+ }
195
+
196
+ if (this.visibleTimeout) {
197
+ clearTimeout(this.visibleTimeout);
198
+ }
199
+
200
+ if (nv) {
201
+ this.visibleTimeout = setTimeout(() => {
202
+ // disable scrolling on the body
203
+ if (this.disablesScroll) {
204
+ disableBodyScroll(this.$refs.modal, { reserveScrollBarGap: true });
205
+ }
206
+
207
+ // handle key events at the document level
208
+ document.addEventListener('keydown', this.onKey);
209
+
210
+ // track the element that was focused before the modal became visible
211
+ this.previousActiveElement = document.activeElement;
212
+
213
+ // focus the first focusable element (or autofocus element if set)
214
+ if (this.autoFocusEnabled) {
215
+ let focusables = this.getFocusableChildren();
216
+ let dialogFocusable = this.$refs.modal
217
+ ? this.$refs.modal.querySelector(this.autoFocusSelector)
218
+ : null;
219
+ let focused = dialogFocusable || focusables[0];
220
+ if (focused) {
221
+ focused.focus();
222
+ }
223
+ }
224
+
225
+ clearTimeout(this.visibleTimeout);
226
+ this.$emit('show');
227
+ }, 0);
228
+
229
+ // event
230
+ this.$emit('update:visible', true);
231
+ } else {
232
+ // restore previous state
233
+ this.restoreNonModalState();
234
+
235
+ // event
236
+ this.$emit('update:visible', false);
237
+ }
238
+ }
239
+
240
+ if (!nv) {
241
+ this.$emit('hide', this.hideSource);
242
+ }
243
+ },
244
+ },
245
+ },
246
+
247
+ beforeDestroy() {
248
+ this.restoreNonModalState();
249
+ },
250
+
251
+ methods: {
252
+ restoreNonModalState() {
253
+ if (this.visibleTimeout) {
254
+ clearTimeout(this.visibleTimeout);
255
+ }
256
+
257
+ // reenable body scrolling
258
+ setTimeout(() => {
259
+ // TODO should we do this based on currentLayer?
260
+ clearAllBodyScrollLocks();
261
+ }, 0);
262
+
263
+ // remove the event handler
264
+ document.removeEventListener('keydown', this.onKey);
265
+
266
+ // restore focus
267
+ if (this.previousActiveElement && this.restoreFocusEnabled) {
268
+ this.previousActiveElement.focus();
269
+ this.previousActiveElement = null;
270
+ }
271
+ },
272
+ getFocusableChildren(onlyVisible) {
273
+ let f = [...this.$refs.modal.querySelectorAll(TABABLE_ELEMENTS.join(','))];
274
+ ///let f = $$(TABABLE_ELEMENTS.join(','), this.$refs.modal);
275
+
276
+ if (onlyVisible) {
277
+ f = f.filter(child => {
278
+ return (
279
+ child.tabIndex >= 0 &&
280
+ !!(child.offsetWidth || child.offsetHeight || child.getClientRects().length)
281
+ );
282
+ });
283
+ }
284
+
285
+ return f.sort((a, b) => {
286
+ if (a.tabIndex > b.tabIndex) {
287
+ return 1;
288
+ }
289
+ if (a.tabIndex < b.tabIndex) {
290
+ return -1;
291
+ }
292
+ return 0;
293
+ });
294
+ },
295
+ onKey(e) {
296
+ if (this.visibleSync) {
297
+ if (e.keyCode === 27 && this.escCloses) {
298
+ this.onEsc(e);
299
+ } else if (e.keyCode === 9) {
300
+ this.onTab(e);
301
+ }
302
+ }
303
+ },
304
+
305
+ onTab(e) {
306
+ // Refresh this on every tab press in case visibility of something has changed
307
+ let focusables = this.getFocusableChildren();
308
+ let focusedIndex = focusables.indexOf(document.activeElement);
309
+
310
+ // Trap tab focus
311
+ if (e.shiftKey && focusedIndex <= 0) {
312
+ focusables[focusables.length - 1].focus();
313
+ e.preventDefault();
314
+ } else if (!e.shiftKey && focusedIndex === focusables.length - 1) {
315
+ focusables[0].focus();
316
+ event.preventDefault();
317
+ }
318
+ },
319
+ onOverlayClick() {
320
+ if (this.overlayClose) {
321
+ this.hide('overlay');
322
+ this.$emit('overlay-click');
323
+ }
324
+ },
325
+ onEsc() {
326
+ if (this.currentLayerIndex == globalLayerIndex) {
327
+ this.hide('esc');
328
+ this.$emit('cancel');
329
+ }
330
+ },
331
+ show() {
332
+ this.hideSource = null;
333
+ this.visibleSync = true;
334
+ },
335
+ hide(hideSource) {
336
+ this.hideSource = hideSource;
337
+ this.visibleSync = false;
338
+ },
339
+
340
+ getDialogElement() {
341
+ return this.$refs.dialog;
342
+ },
343
+ },
344
+ };
345
+ </script>
346
+ <style lang="scss">
347
+ @use '../styles/px.scss' as *;
348
+
349
+ .px-modal {
350
+ position: relative;
351
+
352
+ //z-index: 9999999;
353
+
354
+ // default overlay
355
+ &__overlay {
356
+ z-index: 1;
357
+ @include fixed;
358
+ }
359
+
360
+ &__dialog {
361
+ z-index: 2;
362
+ position: relative;
363
+ }
364
+ }
365
+ </style>
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <div :class="bem({ debug: debug })" :style="borderStyle">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'nine-grid',
10
+ props: {
11
+ // the image source for the ninegrid border
12
+ src: { type: String, default: null },
13
+
14
+ // original width and height of the source
15
+ srcWidth: { type: Number, default: 100 },
16
+ srcHeight: { type: Number, default: 100 },
17
+
18
+ // a number, an array of 1-4 (top,right,bottom,left) numbers or a space separated string of 1-4
19
+ // numbers that represent the border-image-slices values expressed in px
20
+ slice: { default: () => [20] },
21
+
22
+ // scale for border image (does not affect the slot content)
23
+ scale: { type: Number, default: 1 },
24
+
25
+ // when true, the ninegrid image will behave like a background instead of a border (this is
26
+ // accomplished by creating an additional element behind the content)
27
+ backgroundMode: { type: Boolean, default: true },
28
+
29
+ // flag to indicate debug features are active
30
+ debug: { type: Boolean, default: false },
31
+ },
32
+ computed: {
33
+ sliceArray() {
34
+ if (!isNaN(this.slice)) {
35
+ return [this.slice, this.slice, this.slice, this.slice];
36
+ }
37
+
38
+ let arr = Array.isArray(this.slice)
39
+ ? this.slice
40
+ : this.slice.split(' ').map(v => parseInt(v));
41
+
42
+ if (arr.length == 1) {
43
+ return [arr[0], arr[0], arr[0], arr[0]];
44
+ }
45
+
46
+ if (arr.length == 2) {
47
+ return [arr[0], arr[1], arr[0], arr[1]];
48
+ }
49
+
50
+ if (arr.length == 3) {
51
+ return [arr[0], arr[1], arr[2], arr[1]];
52
+ }
53
+
54
+ return arr;
55
+ },
56
+
57
+ borderStyle() {
58
+ //console.log(`this.slice: 👉 ${JSON.stringify(this.slice, null, 4)}`);
59
+
60
+ let borderImageSlice = this.sliceArray
61
+ .map((v, idx) => {
62
+ return (v / (idx % 2 ? this.srcWidth : this.srcHeight)) * 100 + '%';
63
+ })
64
+ .join(' ');
65
+
66
+ return {
67
+ borderStyle: 'solid',
68
+ borderWidth: this.sliceArray.map(v => v * this.scale + 'px').join(' '),
69
+ borderImageSource: `url('${this.src}')`,
70
+ borderImageSlice: borderImageSlice + 'fill',
71
+ };
72
+ },
73
+ },
74
+ methods: {},
75
+ };
76
+ </script>
77
+
78
+ <style lang="scss">
79
+ @use '../styles/px.scss' as *;
80
+
81
+ .nine-grid {
82
+ position: relative;
83
+ box-sizing: border-box;
84
+ border: 2px solid white;
85
+
86
+ &--debug {
87
+ @include after() {
88
+ @include abs();
89
+ border: 2px dashed red;
90
+ pointer-events: none;
91
+ }
92
+ }
93
+ }
94
+ </style>
@@ -0,0 +1,207 @@
1
+ <!--
2
+ Simple pivot component (basically tabs but uses an underline to show selection). Uses
3
+ BaseItemsSelect so it can easily be paired with other BaseItemSelect components.
4
+
5
+
6
+ -->
7
+ <template>
8
+ <div :class="bem({ scrolls: scrolls, animated: animated })">
9
+ <div :class="bem('tabs-align', { justify: justify })">
10
+ <div ref="tabs" :class="bem('tabs')">
11
+ <button
12
+ :class="[bem('tab-base', { selected: isItemSelected(item) }), tabClass]"
13
+ v-for="item in items"
14
+ :key="getItemKey(item)"
15
+ :disabled="getItemDisabled(item)"
16
+ @click="itemClick(item)"
17
+ >
18
+ <span :ref="getTabContentRefName(item)">
19
+ <slot :item="item">
20
+ {{ getItemLabel(item) }}
21
+ </slot>
22
+ </span>
23
+ </button>
24
+
25
+ <div
26
+ :class="[bem('selector-base'), selectorClass]"
27
+ :style="{
28
+ left: cssPx(selectorOffset),
29
+ width: cssPx(selectorWidth),
30
+ }"
31
+ ></div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </template>
36
+
37
+ <script>
38
+ import PxBaseItemsSelect from './PxBaseItemsSelect.vue';
39
+ import PxBaseResize from './PxBaseResize.vue';
40
+ import utils from '../utils/utils.js';
41
+
42
+ export default {
43
+ name: 'px-pivot',
44
+ components: {},
45
+ mixins: [PxBaseResize, PxBaseItemsSelect],
46
+ props: {
47
+ tabClass: { type: String, default: 'px-pivot__tab' },
48
+ selectorClass: { type: String, default: 'px-pivot__selector' },
49
+
50
+ // if true scrolls horizontally when no more room
51
+ scrolls: { type: Boolean, default: true },
52
+
53
+ // how to justify the tabs within the container (start | center | end)
54
+ justify: { type: String, default: 'center' },
55
+
56
+ // overwrite default
57
+ autoSelectFirst: { type: Boolean, default: true },
58
+ },
59
+ data() {
60
+ return {
61
+ selectorVisible: false,
62
+ selectorOffset: 0,
63
+ selectorWidth: 0,
64
+ animated: false,
65
+ };
66
+ },
67
+ // computed: {},
68
+ watch: {
69
+ syncSelected(nv) {
70
+ if (nv) {
71
+ this.updateSelector();
72
+ }
73
+ },
74
+ items: {
75
+ deep: true,
76
+ handler() {
77
+ this.$nextTick(() => {
78
+ this.updateSelector();
79
+ });
80
+ },
81
+ },
82
+ },
83
+
84
+ methods: {
85
+ resize() {
86
+ this.updateSelector();
87
+ },
88
+ updateSelector() {
89
+ // don't update if 0 size
90
+ if (this.$el?.offsetWidth === 0) {
91
+ return;
92
+ }
93
+
94
+ if (!this.selectedItem) {
95
+ return;
96
+ }
97
+
98
+ const selected = this.$refs[this.getTabContentRefName(this.selectedItem)][0];
99
+ const selectedRect = utils.getClientRect(selected, this.$refs.tabs);
100
+
101
+ if (selected) {
102
+ this.selectorVisible = true;
103
+ this.selectorOffset = selectedRect.left;
104
+ this.selectorWidth = selectedRect.width;
105
+ } else {
106
+ this.selectorVisible = false;
107
+ }
108
+
109
+ if (this.scrolls) {
110
+ selected.scrollIntoView({ behavior: 'smooth', inline: 'center' });
111
+ }
112
+ },
113
+
114
+ getTabContentRefName(item) {
115
+ if (!item) {
116
+ return null;
117
+ }
118
+ return 'tab' + this.getItemKey(item);
119
+ },
120
+
121
+ itemClick(item) {
122
+ this.animated = true;
123
+ this.selectItemOnly(item);
124
+ setTimeout(() => {
125
+ this.animated = false;
126
+ }, 100);
127
+ },
128
+ },
129
+ };
130
+ </script>
131
+
132
+ <style lang="scss">
133
+ @use '../styles/px.scss' as *;
134
+ .px-pivot {
135
+ display: grid;
136
+ grid-template-columns: minmax(min-content, 100%);
137
+
138
+ // disable animation until loaded
139
+ &--loading {
140
+ * {
141
+ transition: none !important;
142
+ }
143
+ }
144
+
145
+ --px-pivot-tab-padding: 0.5em;
146
+ --px-pivot-tab-offset: -0.5em;
147
+
148
+ &--scrolls {
149
+ max-width: 100%;
150
+ overflow-x: auto;
151
+ -webkit-overflow-scrolling: touch;
152
+ @include invisible-scrollbar();
153
+ }
154
+
155
+ &__tabs-align {
156
+ min-width: 100%;
157
+ display: flex;
158
+ position: relative;
159
+ &--justify-center {
160
+ justify-content: center;
161
+ }
162
+ &--justify-start {
163
+ justify-content: flex-start;
164
+ left: var(--px-pivot-tab-offset);
165
+ }
166
+
167
+ &--justify-end {
168
+ justify-content: flex-end;
169
+ right: var(--px-pivot-tab-offset);
170
+ }
171
+ }
172
+
173
+ &__tabs {
174
+ position: relative;
175
+ display: flex;
176
+ flex: none;
177
+ }
178
+ &__tab-base {
179
+ @include control-reset();
180
+ background-color: transparent;
181
+ }
182
+
183
+ &__tab {
184
+ flex: none;
185
+ padding: var(--px-pivot-tab-padding);
186
+ cursor: pointer;
187
+ &:disabled {
188
+ opacity: 0.5;
189
+ cursor: not-allowed;
190
+ }
191
+ }
192
+
193
+ &__selector-base {
194
+ position: absolute;
195
+ bottom: 0;
196
+ left: 0;
197
+ height: 2px;
198
+ background-color: currentColor;
199
+ }
200
+
201
+ &--animated & {
202
+ &__selector {
203
+ @include transition(width left);
204
+ }
205
+ }
206
+ }
207
+ </style>