@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,131 @@
1
+ <!--
2
+
3
+ <px-toggle-button-list
4
+ :items="fruits"
5
+ items-value-property="id"
6
+ items-label-property="name"
7
+ items-key-property="id"
8
+ >
9
+ <template v-slot:item="{ item, checked }" :style="{color: checked ? 'green' : null}">{{ item.name }}</template>
10
+ </px-toggle-button-list>
11
+
12
+
13
+ Supported variants:
14
+
15
+ - connected - draws buttons in a single connected group (no gaps between buttons)
16
+ - connected outline - same as connected but uses an outline button style
17
+ - wrap - allows the button container to wrap
18
+
19
+ -->
20
+ <template>
21
+ <px-flex
22
+ :class="bem({ readonly: readonly, ...variantsMap })"
23
+ :gap="isVariant('connected') ? 0 : gap"
24
+ :wrap="isVariant('wrap')"
25
+ :vertical="isVariant('vertical')"
26
+ :role="multiSelect ? null : 'radiogroup'"
27
+ >
28
+ <component
29
+ :is="isVariant('radio') ? 'px-radio-button' : 'px-toggle-button'"
30
+ v-for="item in items"
31
+ :key="getItemKey(item)"
32
+ :class="[bem('button'), buttonClass]"
33
+ :icon="icon"
34
+ :iconSize="iconSize"
35
+ :variant="isVariant('radio') ? 'default' : variant"
36
+ :checked="isItemSelected(item)"
37
+ :disabled="readonly"
38
+ @checked="itemCheck(item)"
39
+ @unchecked="itemUncheck(item)"
40
+ :role="multiSelect ? 'switch' : 'radio'"
41
+ >
42
+ <slot name="item" :item="item" :checked="isItemSelected(item)">
43
+ {{ getItemLabel(item) }}
44
+ </slot>
45
+ </component>
46
+ </px-flex>
47
+ </template>
48
+
49
+ <script>
50
+ import PxBase from './PxBase.vue';
51
+ import PxBaseItemsSelect from './PxBaseItemsSelect.vue';
52
+ import PxBaseVariants from './PxBaseVariants.vue';
53
+ import PxFlex from './PxFlex.vue';
54
+ import PxRadioButton from './PxRadioButton.vue';
55
+ import PxToggleButton from './PxToggleButton.vue';
56
+
57
+ export default {
58
+ name: 'px-toggle-button-list',
59
+
60
+ mixins: [PxBase, PxBaseItemsSelect, PxBaseVariants],
61
+ components: { PxToggleButton, PxRadioButton, PxFlex },
62
+ props: {
63
+ // spacing between items (see PxFlex for details)
64
+ gap: { default: 0.5 },
65
+
66
+ // name of icon to be displayed when the button is in a checked state
67
+ icon: { type: String, default: require('../assets/icons/check.svg') },
68
+
69
+ // the size of the icon
70
+ iconSize: { default: null },
71
+
72
+ // class set on the individual buttons
73
+ buttonClass: { type: String, default: null },
74
+
75
+ // display only mode
76
+ readonly: { type: Boolean, default: false },
77
+ },
78
+ computed: {
79
+ calculatedInputGroup() {
80
+ return this.inputGroup || this.getGeneratedId('group-');
81
+ },
82
+ },
83
+ methods: {
84
+ itemCheck(item) {
85
+ if (this.multiSelect) {
86
+ this.selectItems([item]);
87
+ } else {
88
+ this.selectItemOnly(item);
89
+ }
90
+ },
91
+ itemUncheck(item) {
92
+ this.unselectItems([item]);
93
+ },
94
+ },
95
+ };
96
+ </script>
97
+
98
+ <style lang="scss">
99
+ @use '../styles/px.scss' as *;
100
+ .px-toggle-button-list {
101
+ $block: get-block-name(&);
102
+
103
+ // variant: connected
104
+
105
+ &--connected & {
106
+ &__button:not(:first-child) {
107
+ border-top-left-radius: 0;
108
+ border-bottom-left-radius: 0;
109
+ }
110
+ &__button:not(:last-child) {
111
+ border-top-right-radius: 0;
112
+ border-bottom-right-radius: 0;
113
+ }
114
+ &__button {
115
+ &:not(:hover) {
116
+ box-shadow: none;
117
+ }
118
+ &:hover {
119
+ z-index: 1;
120
+ }
121
+ }
122
+ }
123
+ &--connected.#{$block}--outline & {
124
+ &__button {
125
+ &:not(:last-child) {
126
+ border-right: none;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ </style>
@@ -0,0 +1,100 @@
1
+ <template>
2
+ <transition
3
+ name="px-transition-expand"
4
+ @enter="enter"
5
+ @after-enter="afterEnter"
6
+ @leave="leave"
7
+ @before-enter="before"
8
+ @before-leave="before"
9
+ @after-leave="after"
10
+ >
11
+ <slot />
12
+ </transition>
13
+ </template>
14
+
15
+ <script>
16
+ export default {
17
+ props: {
18
+ // override the transition duration (expressed in seconds)
19
+ duration: { type: Number, default: null },
20
+ },
21
+ methods: {
22
+ before(element) {
23
+ if (this.duration) {
24
+ element.style.transitionDuration = this.duration + 's';
25
+ }
26
+ },
27
+
28
+ after(element) {
29
+ if (this.duration) {
30
+ element.style.transitionDuration = null;
31
+ }
32
+ },
33
+
34
+ enter(element) {
35
+ // cache width
36
+ const width = getComputedStyle(element).width;
37
+
38
+ // height prep
39
+ element.style.width = width;
40
+ element.style.position = 'absolute';
41
+ element.style.visibility = 'hidden';
42
+ element.style.height = 'auto';
43
+ element.style.opacity = 0;
44
+
45
+ // cache height
46
+ const height = getComputedStyle(element).height;
47
+
48
+ // restore
49
+ element.style.width = null;
50
+ element.style.position = null;
51
+ element.style.visibility = null;
52
+ element.style.height = null;
53
+ element.style.opacity = null;
54
+
55
+ // force repaint
56
+ getComputedStyle(element).height;
57
+
58
+ // trigger the animation
59
+ setTimeout(() => {
60
+ element.style.height = height;
61
+ });
62
+
63
+ this.$emit('height-computed', height);
64
+ },
65
+ afterEnter(element) {
66
+ element.style.height = null;
67
+ element.style.opacity = null;
68
+ this.after(element);
69
+ },
70
+ leave(element) {
71
+ const height = getComputedStyle(element).height;
72
+
73
+ element.style.height = height;
74
+ element.style.opacity = 0;
75
+
76
+ // force repaint
77
+ getComputedStyle(element).height;
78
+
79
+ setTimeout(() => {
80
+ element.style.height = 0;
81
+ });
82
+ },
83
+ },
84
+ };
85
+ </script>
86
+
87
+ <style lang="scss">
88
+ @use '../styles/px.scss' as *;
89
+
90
+ .px-transition-expand-enter-active,
91
+ .px-transition-expand-leave-active {
92
+ transition: height 600ms $ease-out-quart, opacity 600ms $ease-out-quart;
93
+ }
94
+
95
+ .px-transition-expand-enter,
96
+ .px-transition-expand-leave-to {
97
+ opacity: 0;
98
+ height: 0;
99
+ }
100
+ </style>
@@ -0,0 +1,431 @@
1
+ <!--
2
+
3
+ Provides general purpose data-driven validation functionality and UI. Here is some boilerplate
4
+ code that shows how you can manage multiple validations in a single page / component:
5
+
6
+ <template>
7
+ <div>
8
+ <div>Has errors: {{ hasErrors }}</div>
9
+
10
+ <px-validator
11
+ :value="fieldOne"
12
+ rules="required"
13
+ @valid-changed="validChanged"
14
+ >
15
+ <template #default="v">
16
+ <px-textbox :class="v.class" v-model="fieldOne" />
17
+ </template>
18
+ </px-validator>
19
+
20
+ <px-validator
21
+ :value="fieldTwo"
22
+ rules="{
23
+ required: true,
24
+ apples: (value) => {
25
+ if (value.indexOf('apples') == -1) {
26
+ return 'Must mention delicious apples';
27
+ }
28
+ }
29
+ }"
30
+ @valid-changed="validChanged"
31
+ >
32
+ <template #default="v">
33
+ <px-textbox :class="v.class" v-model="fieldTwo" />
34
+ </template>
35
+ </px-validator>
36
+ </div>
37
+ </template>
38
+
39
+ <script>
40
+ import PxValidator from '@thinkpixellab/px-vue/components/PxValidator.vue';
41
+ import PxTextbox from '@thinkpixellab/px-vue/components/PxTextbox.vue';
42
+
43
+ export default {
44
+ components: { PxValidator, PxTextbox },
45
+ data() {
46
+ return: {
47
+
48
+ // validation is all data driven so the components need to
49
+ // have data fields associated with them
50
+ fieldOne: null,
51
+ fieldTwo: null,
52
+
53
+ // tracks validation information for all fields on the page
54
+ validation: {}
55
+ }
56
+ },
57
+ computed: {
58
+ hasErrors() {
59
+ return !Object.values(this.validation).reduce((prev, val) => {
60
+ return prev && val;
61
+ }, true);
62
+ }
63
+ },
64
+ methods: {
65
+ validChanged(isValid, id) {
66
+ this.$set(this.validation, id, isValid);
67
+ }
68
+ }
69
+
70
+ }
71
+ </script>
72
+
73
+ -->
74
+
75
+ <template>
76
+ <div :class="bem()" @focusin="onFocusIn" @focusout="onFocusOut">
77
+ <slot name="default" v-bind="validatorData"></slot>
78
+ <slot name="errors">
79
+ <div v-if="!hideErrors" :class="[bem('error-container'), errorContainerClass]">
80
+ <span
81
+ v-for="error in validatorData.visibleErrors"
82
+ :key="error.id"
83
+ :class="[bem('error-item'), errorItemClass]"
84
+ >
85
+ <px-icon
86
+ :class="bem('error-icon')"
87
+ :src="require('../assets/icons/invalid.svg')"
88
+ />
89
+ {{ error.message }}
90
+ </span>
91
+ </div>
92
+ </slot>
93
+ </div>
94
+ </template>
95
+
96
+ <script>
97
+ import PxBase from './PxBase.vue';
98
+ import PxIcon from './PxIcon.vue';
99
+
100
+ const VALIDATORS = {
101
+ required(val) {
102
+ const isValid = val !== null && val !== undefined && val !== '';
103
+ if (!isValid) {
104
+ return 'Required. Must provide a value.';
105
+ }
106
+ return null;
107
+ },
108
+ oneof(val, allowedValues) {
109
+ const isValid = allowedValues.includes(val);
110
+ if (!isValid) {
111
+ return 'Must match one of the allowed values.';
112
+ }
113
+ return null;
114
+ },
115
+ not(val, notValue) {
116
+ const isValid = val !== notValue;
117
+ if (!isValid) {
118
+ return 'Invalid. Must provide a different value.';
119
+ }
120
+ },
121
+ minlength(val, length) {
122
+ const isValid = (val + '').length >= length;
123
+ if (!isValid) {
124
+ return `Must be at least ${length} characters.`;
125
+ }
126
+ return null;
127
+ },
128
+ maxlength(val, length) {
129
+ const isValid = (val + '').length <= length;
130
+ if (!isValid) {
131
+ return `Must not exceed ${length} characters.`;
132
+ }
133
+ return null;
134
+ },
135
+ email(val) {
136
+ const isValid = /^\w+([.-]?\w+)+@\w+([.:]?\w+)+(\.[a-zA-Z0-9]{2,3})+$/.test(val);
137
+ if (!isValid) {
138
+ return 'Must be a valid email address.';
139
+ }
140
+ return null;
141
+ },
142
+ phone(val) {
143
+ // us phone numbers only, based on comment in this post:
144
+ // https://stackoverflow.com/questions/123559/how-to-validate-phone-numbers-using-regex
145
+ const isValid =
146
+ /(?:(?:(\s*\(?([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\)?\s*(?:[.-]\s*)?)([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})/.test(
147
+ val
148
+ );
149
+ if (!isValid) {
150
+ return 'Must be a valid phone number.';
151
+ }
152
+ return null;
153
+ },
154
+
155
+ regex(val, regexStr) {
156
+ const isValid = new RegExp(regexStr).test(val);
157
+ if (!isValid) {
158
+ return 'Must match the specified format.';
159
+ }
160
+ return null;
161
+ },
162
+
163
+ // url(val) {
164
+ // // TODO
165
+ // },
166
+ // number(val) {
167
+ // // TODO
168
+ // },
169
+ // integer(val) {
170
+ // // TODO
171
+ // },
172
+ // maxvalue(val, max) {
173
+ // // TODO
174
+ // },
175
+ // minvalue(val, min) {
176
+ // // TODO
177
+ // },
178
+ };
179
+
180
+ export default {
181
+ name: 'px-validator',
182
+ components: { PxIcon },
183
+ mixins: [PxBase],
184
+ props: {
185
+ // the value to be validated
186
+ value: { default: null },
187
+
188
+ // list of validator rules, see explanation of syntax in notes above
189
+ rules: { default: null },
190
+
191
+ // Whether validation is currently active, possible values are:
192
+ // - true / false (obvious)
193
+ // - focus-in (becomes active once a child element has been focused)
194
+ // - focus-out (becomes active once a child element has lost focus)
195
+ // - focus-active (active only while a child element has focus)
196
+ active: { default: 'focus-out' },
197
+
198
+ // message overrides, can be a string (always used), object (overrides based on error id),
199
+ // or a function (rule object provided as parameter)
200
+ messageOverride: { default: null },
201
+
202
+ // optional field id that can be set to disambiguate valid-changed events
203
+ fieldId: { type: String, default: null },
204
+
205
+ // if true, the default errors slot will be hidden altogether
206
+ hideErrors: { type: Boolean, default: false },
207
+
208
+ // if true, the default messages slot will show all violation messages instead of just the first
209
+ allErrors: { type: Boolean, default: false },
210
+
211
+ // class that will be applied to the default errors container and item respectively
212
+ errorContainerClass: { type: String, default: null },
213
+ errorItemClass: { type: String, default: null },
214
+
215
+ // override class names
216
+ inactiveClass: { type: String, default: null },
217
+ validClass: { type: String, default: 'valid' },
218
+ invalidClass: { type: String, default: 'invalid' },
219
+ requiredClass: { type: String, default: 'required' },
220
+ },
221
+ data() {
222
+ return { focusActive: false, focusIn: false, focusOut: false };
223
+ },
224
+ computed: {
225
+ fieldIdInternal() {
226
+ return this.fieldId || this.uniqueId();
227
+ },
228
+
229
+ activeInternal() {
230
+ if (typeof this.active == 'string') {
231
+ if (this.active == 'focus-in') {
232
+ return this.focusIn;
233
+ }
234
+ if (this.active == 'focus-out') {
235
+ return this.focusOut;
236
+ }
237
+ if (this.active == 'focus-active') {
238
+ return this.focusActive;
239
+ }
240
+ }
241
+ return !!this.active;
242
+ },
243
+
244
+ rulesArray() {
245
+ let r = [];
246
+
247
+ if (this.rules) {
248
+ let t = typeof this.rules;
249
+
250
+ // String
251
+
252
+ // Expects a string like "rule1:param rule2 rule3" where rule ids and parameters are
253
+ // separated by colons. This format works for most rules but won't work for
254
+ // complicated parameters like those required for regex, oneof or custom callbacks.
255
+ // For those, use the object format.
256
+ if (t == 'string') {
257
+ const split = this.rules.split(/\s+/);
258
+ split.forEach(s => {
259
+ s = s.split(':');
260
+ const id = s[0];
261
+ const validator = id in VALIDATORS ? VALIDATORS[id] : null;
262
+ const param = s.length > 1 ? s[1] : null;
263
+ if (validator) {
264
+ r.push({
265
+ id,
266
+ validator,
267
+ param,
268
+ });
269
+ }
270
+ });
271
+ }
272
+
273
+ // Object
274
+
275
+ // Expects an object like {required: true, regex: '...', myvalidator:(value) => {...} }
276
+ // Use this format for more complex or customized validation rules.
277
+ else if (t == 'object') {
278
+ for (let id in this.rules) {
279
+ // custom validator
280
+ if (typeof this.rules[id] == 'function') {
281
+ r.push({
282
+ id,
283
+ validator: this.rules[id],
284
+ });
285
+ }
286
+
287
+ // built in validator
288
+ else {
289
+ const validator = id in VALIDATORS ? VALIDATORS[id] : null;
290
+ if (validator) {
291
+ r.push({
292
+ id,
293
+ validator,
294
+ param: this.rules[id],
295
+ });
296
+ }
297
+ }
298
+ }
299
+ }
300
+ }
301
+
302
+ return r;
303
+ },
304
+
305
+ validatorData() {
306
+ let errors = this.getErrors();
307
+
308
+ let visibleErrors = [];
309
+ if (this.activeInternal) {
310
+ visibleErrors = !this.allErrors && errors?.length > 0 ? [errors[0]] : errors;
311
+ }
312
+
313
+ const isValid = errors.length == 0;
314
+ const isRequired = this.rulesArray.find(r => r.id == 'required');
315
+ const validityClass = isValid ? this.validClass : this.invalidClass;
316
+
317
+ let v = {
318
+ // this will be true unless a violation is found, even if validation is not active
319
+ isValid: isValid,
320
+
321
+ // whether valdition is presently active
322
+ isActive: this.activeInternal,
323
+
324
+ // field id
325
+ fieldId: this.fieldIdInternal,
326
+
327
+ // a class which can be applied to content to style it as valid, invalid (validation not active)
328
+ class: this.activeInternal ? validityClass : this.inactiveClass,
329
+
330
+ // a class for each of the rule violations in the form of invalid--[id]
331
+ violationClasses: isValid ? [] : errors.map(e => this.invalidClass + '--' + e.id),
332
+
333
+ // a class which can be applied to content to style required fields
334
+ requiredClass: isRequired ? this.requiredClass : null,
335
+
336
+ // whether the field is required (base on the special presence of the required rule)
337
+ required: isRequired,
338
+
339
+ errors: errors,
340
+ visibleErrors: visibleErrors,
341
+ };
342
+
343
+ return v;
344
+ },
345
+
346
+ isValid() {
347
+ return this.validatorData.isValid;
348
+ },
349
+ },
350
+ watch: {
351
+ isValid: {
352
+ immediate: true,
353
+ handler() {
354
+ this.$emit('valid-changed', this.validatorData);
355
+ },
356
+ },
357
+ },
358
+ methods: {
359
+ onFocusIn() {
360
+ this.focusIn = true;
361
+ this.focusActive = true;
362
+ },
363
+ onFocusOut() {
364
+ this.focusOut = true;
365
+ this.focusActive = false;
366
+ },
367
+ getErrorMessage(validator, defaultErrorMessage) {
368
+ if (this.messageOverride) {
369
+ if (typeof this.messageOverride == 'string') {
370
+ return this.messageOverride;
371
+ }
372
+
373
+ if (
374
+ typeof this.messageOverride == 'object' &&
375
+ validator.id in this.messageOverride
376
+ ) {
377
+ return this.messageOverride[validator.id];
378
+ }
379
+
380
+ if (typeof this.messageOverride == 'function') {
381
+ return this.messageOverride(validator, defaultErrorMessage);
382
+ }
383
+ }
384
+
385
+ return defaultErrorMessage;
386
+ },
387
+ getErrors() {
388
+ let errors = [];
389
+
390
+ this.rulesArray.forEach(r => {
391
+ let error = r.validator(this.value, r.param);
392
+ if (error) {
393
+ errors.push({ id: r.id, message: this.getErrorMessage(r, error) });
394
+ }
395
+ });
396
+
397
+ return errors;
398
+ },
399
+ },
400
+ };
401
+ </script>
402
+
403
+ <style lang="scss">
404
+ @use '../styles/px.scss' as *;
405
+ .px-validator {
406
+ display: flex;
407
+ flex-direction: column;
408
+ justify-content: stretch;
409
+
410
+ $error-color: get('colors:error', #fc433e, false);
411
+
412
+ &__error-container {
413
+ display: flex;
414
+ flex-direction: column;
415
+ font-size: fs(xs);
416
+ color: $error-color;
417
+ min-height: 1.5em;
418
+ line-height: 1.1;
419
+ padding-top: 0.33em;
420
+ }
421
+
422
+ &__error-item {
423
+ display: flex;
424
+ align-items: center;
425
+ }
426
+
427
+ &__error-icon {
428
+ margin-right: 0.3em;
429
+ }
430
+ }
431
+ </style>