@propelinc/citrus-ui 0.6.0 → 1.0.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 (355) hide show
  1. package/README.md +54 -60
  2. package/dist/colors/colors.d.ts +31 -0
  3. package/dist/colors/theme.d.ts +2 -11
  4. package/dist/colors/util-classes.d.ts +11 -0
  5. package/dist/components/CAccordion.vue.d.ts +21 -0
  6. package/dist/components/CAccordionItem.vue.d.ts +41 -0
  7. package/dist/components/CAppBar.vue.d.ts +156 -0
  8. package/dist/components/CBadge.vue.d.ts +52 -0
  9. package/dist/components/CBottomSheet.vue.d.ts +226 -0
  10. package/dist/components/CButton/CButton.vue.d.ts +231 -0
  11. package/dist/components/CButton/types.d.ts +5 -0
  12. package/dist/components/CButtonStack.vue.d.ts +24 -0
  13. package/dist/components/CCard.vue.d.ts +107 -0
  14. package/dist/components/CCardFooter.vue.d.ts +26 -0
  15. package/dist/components/CCardHeader.vue.d.ts +3 -0
  16. package/dist/components/CCardSection.vue.d.ts +17 -0
  17. package/dist/components/CCheckbox.vue.d.ts +145 -0
  18. package/dist/components/CCol.vue.d.ts +21 -0
  19. package/dist/components/CDivider.vue.d.ts +17 -0
  20. package/dist/components/CDobField.vue.d.ts +2109 -0
  21. package/dist/components/CDobSelect.vue.d.ts +398 -0
  22. package/dist/components/CEmailField.vue.d.ts +699 -0
  23. package/dist/components/CExpandTransition.vue.d.ts +19 -0
  24. package/dist/components/CFadeTransition.vue.d.ts +3 -0
  25. package/dist/components/CFileInput.vue.d.ts +98 -0
  26. package/dist/components/CFixedPageFooter.vue.d.ts +106 -0
  27. package/dist/components/CForm.vue.d.ts +29 -0
  28. package/dist/components/CFormFieldCounter.vue.d.ts +42 -0
  29. package/dist/components/CIconButton.vue.d.ts +390 -0
  30. package/dist/components/CLabel.vue.d.ts +32 -0
  31. package/dist/components/CListItem.vue.d.ts +208 -0
  32. package/dist/components/CListItemContent.vue.d.ts +27 -0
  33. package/dist/components/CListItemIcon.vue.d.ts +54 -0
  34. package/dist/components/CLoader.vue.d.ts +73 -0
  35. package/dist/components/CLogo.vue.d.ts +19 -0
  36. package/dist/components/CMaskedTextField.vue.d.ts +2012 -0
  37. package/dist/components/CMenu.vue.d.ts +6 -0
  38. package/dist/components/CMenuItem.vue.d.ts +170 -0
  39. package/dist/components/CMenuLabel.vue.d.ts +3 -0
  40. package/dist/components/CModal.vue.d.ts +206 -0
  41. package/dist/components/CModalLoading.vue.d.ts +230 -0
  42. package/dist/components/CNotification.vue.d.ts +589 -0
  43. package/dist/components/CPhoneField.vue.d.ts +2088 -0
  44. package/dist/components/CPill.vue.d.ts +42 -0
  45. package/dist/components/CPillGroup.vue.d.ts +70 -0
  46. package/dist/components/CPopup.vue.d.ts +21 -0
  47. package/dist/components/CProgressLinear.vue.d.ts +61 -0
  48. package/dist/components/CProgressRing.vue.d.ts +103 -0
  49. package/dist/components/CRadio.vue.d.ts +73 -0
  50. package/dist/components/CRadioGroup.vue.d.ts +123 -0
  51. package/dist/components/CRebrand.vue.d.ts +28 -0
  52. package/dist/components/CRow.vue.d.ts +67 -0
  53. package/dist/components/CSafeArea.vue.d.ts +18 -0
  54. package/dist/components/CSectionHeader.vue.d.ts +28 -0
  55. package/dist/components/CSelect.vue.d.ts +293 -0
  56. package/dist/components/CSkeleton.vue.d.ts +3 -0
  57. package/dist/components/CSkeletonLoaderCard.vue.d.ts +21 -0
  58. package/dist/components/CSkeletonLoaderCircle.vue.d.ts +5 -0
  59. package/dist/components/CSkeletonLoaderText.vue.d.ts +44 -0
  60. package/dist/components/CSlideFadeTransition.vue.d.ts +58 -0
  61. package/dist/components/CSplitInput.vue.d.ts +2131 -0
  62. package/dist/components/CSquaredIcon.vue.d.ts +47 -0
  63. package/dist/components/CSsnField.vue.d.ts +2083 -0
  64. package/dist/components/CStatusDot.vue.d.ts +27 -0
  65. package/dist/components/CSwitch.vue.d.ts +54 -0
  66. package/dist/components/CSwitchListItem.vue.d.ts +392 -0
  67. package/dist/components/CTextArea.vue.d.ts +240 -0
  68. package/dist/components/CTextField.vue.d.ts +647 -0
  69. package/dist/components/CTextLink.vue.d.ts +55 -0
  70. package/dist/components/CThirdPartyLogo.vue.d.ts +128 -0
  71. package/dist/components/CTimeago.vue.d.ts +12 -0
  72. package/dist/components/CToast.vue.d.ts +458 -0
  73. package/dist/components/CToastsList.vue.d.ts +430 -0
  74. package/dist/components/CValidationMessage.vue.d.ts +45 -0
  75. package/dist/components/CZipcodeField.vue.d.ts +2080 -0
  76. package/dist/components/index.d.ts +66 -25
  77. package/dist/components/internal/CCloseButton.vue.d.ts +14 -0
  78. package/dist/composables/accessibility.d.ts +1 -0
  79. package/dist/composables/animation.d.ts +12 -0
  80. package/dist/composables/binding.d.ts +19 -0
  81. package/dist/composables/colors.d.ts +13 -0
  82. package/dist/composables/elements.d.ts +3 -0
  83. package/dist/composables/fields.d.ts +9 -0
  84. package/dist/composables/gestures.d.ts +53 -0
  85. package/dist/composables/i18n.d.ts +3 -0
  86. package/dist/composables/id.d.ts +11 -0
  87. package/dist/composables/input-mask.d.ts +18 -0
  88. package/dist/composables/router.d.ts +30 -0
  89. package/dist/composables/slots.d.ts +2 -0
  90. package/dist/composables/toast.d.ts +21 -0
  91. package/dist/composables/validations.d.ts +77 -0
  92. package/dist/index.css +1 -0
  93. package/dist/index.d.ts +5 -4
  94. package/dist/index.mjs +11738 -0
  95. package/dist/index.mjs.map +1 -0
  96. package/dist/plugin.d.ts +2 -2
  97. package/dist/services/animation.d.ts +17 -0
  98. package/dist/services/directives/index.d.ts +2 -0
  99. package/dist/services/directives/scroll-into-view.d.ts +7 -0
  100. package/dist/services/directives/tap-animation.d.ts +6 -0
  101. package/dist/services/id.d.ts +22 -0
  102. package/dist/services/injections/accordions.d.ts +3 -0
  103. package/dist/services/injections/animations.d.ts +2 -0
  104. package/dist/services/injections/buttons.d.ts +4 -0
  105. package/dist/services/injections/forms.d.ts +6 -0
  106. package/dist/services/injections/icon-buttons.d.ts +3 -0
  107. package/dist/services/injections/pills.d.ts +4 -0
  108. package/dist/services/injections/radio.d.ts +10 -0
  109. package/dist/styles/main.css +3002 -0
  110. package/dist/styles/utils.css +2319 -0
  111. package/dist/theme/icons.d.ts +35 -2
  112. package/dist/types/CForm.d.ts +12 -0
  113. package/dist/types/font-awesome.d.ts +5 -0
  114. package/dist/types.d.ts +12 -0
  115. package/index.ts +2 -0
  116. package/package.json +60 -45
  117. package/src/assets/fonts/grenette-regular.woff2 +0 -0
  118. package/src/assets/fonts/grenette-semibold.woff2 +0 -0
  119. package/src/assets/fonts/polymath.woff2 +0 -0
  120. package/src/assets/logos/propel/icon.svg +15 -0
  121. package/src/assets/logos/propel/lockup.svg +11 -0
  122. package/src/colors/colors.ts +173 -0
  123. package/src/colors/theme.ts +8 -14
  124. package/src/colors/util-classes.ts +49 -0
  125. package/src/componentResolver.js +33 -0
  126. package/src/components/CAccordion.vue +32 -7
  127. package/src/components/CAccordionItem.vue +109 -36
  128. package/src/components/CAppBar.vue +237 -0
  129. package/src/components/CBadge.vue +74 -0
  130. package/src/components/CBottomSheet.vue +430 -0
  131. package/src/components/CButton/CButton.vue +347 -0
  132. package/src/components/CButton/types.ts +5 -0
  133. package/src/components/CButtonStack.vue +36 -0
  134. package/src/components/CCard.vue +149 -41
  135. package/src/components/CCardFooter.vue +11 -27
  136. package/src/components/CCardHeader.vue +30 -21
  137. package/src/components/CCardSection.vue +23 -12
  138. package/src/components/CCheckbox.vue +191 -21
  139. package/src/components/CCol.vue +55 -0
  140. package/src/components/CDivider.vue +46 -0
  141. package/src/components/CDobField.vue +153 -0
  142. package/src/components/CDobSelect.vue +274 -0
  143. package/src/components/CEmailField.vue +61 -0
  144. package/src/components/CExpandTransition.vue +55 -0
  145. package/src/components/CFadeTransition.vue +23 -0
  146. package/src/components/CFileInput.vue +186 -0
  147. package/src/components/CFixedPageFooter.vue +76 -0
  148. package/src/components/CForm.vue +86 -0
  149. package/src/components/CFormFieldCounter.vue +40 -0
  150. package/src/components/CIconButton.vue +175 -59
  151. package/src/components/CLabel.vue +52 -0
  152. package/src/components/CListItem.vue +149 -45
  153. package/src/components/CListItemContent.vue +60 -0
  154. package/src/components/CListItemIcon.vue +27 -31
  155. package/src/components/CLoader.vue +156 -0
  156. package/src/components/CLogo.vue +23 -0
  157. package/src/components/CMaskedTextField.vue +118 -0
  158. package/src/components/CMenu.vue +24 -0
  159. package/src/components/CMenuItem.vue +106 -0
  160. package/src/components/CMenuLabel.vue +26 -0
  161. package/src/components/CModal.vue +198 -79
  162. package/src/components/CModalLoading.vue +27 -9
  163. package/src/components/CNotification.vue +86 -53
  164. package/src/components/CPhoneField.vue +69 -0
  165. package/src/components/CPill.vue +162 -0
  166. package/src/components/CPillGroup.vue +73 -0
  167. package/src/components/CPopup.vue +66 -0
  168. package/src/components/CProgressLinear.vue +52 -0
  169. package/src/components/CProgressRing.vue +126 -0
  170. package/src/components/CRadio.vue +138 -0
  171. package/src/components/CRadioGroup.vue +142 -0
  172. package/src/components/CRebrand.vue +28 -0
  173. package/src/components/CRow.vue +62 -0
  174. package/src/components/CSafeArea.vue +23 -0
  175. package/src/components/CSectionHeader.vue +50 -0
  176. package/src/components/CSelect.vue +223 -74
  177. package/src/components/CSkeleton.vue +65 -0
  178. package/src/components/CSkeletonLoaderCard.vue +29 -0
  179. package/src/components/CSkeletonLoaderCircle.vue +18 -14
  180. package/src/components/CSkeletonLoaderText.vue +127 -17
  181. package/src/components/CSlideFadeTransition.vue +100 -0
  182. package/src/components/CSplitInput.vue +111 -0
  183. package/src/components/CSquaredIcon.vue +83 -0
  184. package/src/components/CSsnField.vue +86 -0
  185. package/src/components/CStatusDot.vue +70 -0
  186. package/src/components/CSwitch.vue +125 -0
  187. package/src/components/CSwitchListItem.vue +110 -0
  188. package/src/components/CTextArea.vue +193 -47
  189. package/src/components/CTextField.vue +450 -93
  190. package/src/components/CTextLink.vue +48 -38
  191. package/src/components/CThirdPartyLogo.vue +127 -0
  192. package/src/components/CTimeago.vue +63 -0
  193. package/src/components/CToast.vue +259 -0
  194. package/src/components/CToastsList.vue +32 -0
  195. package/src/components/CValidationMessage.vue +70 -0
  196. package/src/components/CZipcodeField.vue +69 -0
  197. package/src/components/index.ts +66 -25
  198. package/src/components/internal/CCloseButton.vue +57 -0
  199. package/src/composables/accessibility.ts +29 -0
  200. package/src/composables/animation.ts +95 -0
  201. package/src/composables/binding.ts +34 -0
  202. package/src/composables/colors.ts +59 -0
  203. package/src/composables/elements.ts +72 -0
  204. package/src/composables/fields.ts +19 -0
  205. package/src/composables/gestures.ts +197 -0
  206. package/src/composables/i18n.ts +13 -0
  207. package/src/composables/id.ts +23 -0
  208. package/src/composables/input-mask.ts +139 -0
  209. package/src/composables/router.ts +64 -0
  210. package/src/composables/slots.ts +57 -0
  211. package/src/composables/toast.ts +64 -0
  212. package/src/composables/validations.ts +214 -0
  213. package/src/index.ts +7 -7
  214. package/src/plugin.ts +13 -6
  215. package/src/services/animation.ts +101 -0
  216. package/src/services/directives/index.ts +2 -0
  217. package/src/services/directives/scroll-into-view.ts +86 -0
  218. package/src/services/directives/tap-animation.ts +71 -0
  219. package/src/services/id.ts +31 -0
  220. package/src/services/injections/accordions.ts +4 -0
  221. package/src/services/injections/animations.ts +3 -0
  222. package/src/services/injections/buttons.ts +5 -0
  223. package/src/services/injections/forms.ts +8 -0
  224. package/src/services/injections/icon-buttons.ts +4 -0
  225. package/src/services/injections/pills.ts +7 -0
  226. package/src/services/injections/radio.ts +12 -0
  227. package/src/shims-vue.d.ts +6 -3
  228. package/src/styles/_animation.scss +19 -0
  229. package/src/styles/_button.scss +61 -0
  230. package/src/styles/_colors.scss +58 -11
  231. package/src/styles/_core.scss +248 -87
  232. package/src/styles/_form-fields.scss +68 -15
  233. package/src/styles/_grenette.scss +13 -0
  234. package/src/styles/_polymath.scss +14 -0
  235. package/src/styles/_reset.scss +105 -0
  236. package/src/styles/_shoelace.scss +46 -0
  237. package/src/styles/_typography.scss +40 -10
  238. package/src/styles/main.scss +6 -3
  239. package/src/styles/utils/a11y.scss +18 -0
  240. package/src/styles/utils/typography.scss +13 -0
  241. package/src/styles/utils.scss +560 -0
  242. package/src/styles/variables.scss +27 -15
  243. package/src/theme/icons.ts +16 -5
  244. package/src/types/CForm.ts +15 -0
  245. package/src/types/font-awesome.ts +6 -0
  246. package/src/types.ts +15 -0
  247. package/.browserslistrc +0 -3
  248. package/.eslintrc.js +0 -4
  249. package/.stylelintrc.js +0 -3
  250. package/babel.config.js +0 -3
  251. package/dist/citrus-ui.common.js +0 -43434
  252. package/dist/citrus-ui.common.js.map +0 -1
  253. package/dist/citrus-ui.css +0 -1
  254. package/dist/citrus-ui.umd.js +0 -43444
  255. package/dist/citrus-ui.umd.js.map +0 -1
  256. package/dist/citrus-ui.umd.min.js +0 -27
  257. package/dist/citrus-ui.umd.min.js.map +0 -1
  258. package/dist/demo.html +0 -10
  259. package/dist/fonts/Blitz-Script.85ed9abe.woff2 +0 -0
  260. package/dist/fonts/ObjectSans-Bold.5492f3d5.woff2 +0 -0
  261. package/dist/fonts/ObjectSans-BoldSlanted.29e2a87e.woff2 +0 -0
  262. package/dist/fonts/ObjectSans-Heavy.d0b2f035.woff2 +0 -0
  263. package/dist/fonts/ObjectSans-HeavySlanted.45e9c063.woff2 +0 -0
  264. package/dist/fonts/ObjectSans-Light.f885dec3.woff2 +0 -0
  265. package/dist/fonts/ObjectSans-LightSlanted.b8eb7c12.woff2 +0 -0
  266. package/dist/fonts/ObjectSans-Regular.e4ea0b90.woff2 +0 -0
  267. package/dist/fonts/ObjectSans-Slanted.57a90be9.woff2 +0 -0
  268. package/dist/fonts/ObjectSans-Thin.86d44227.woff2 +0 -0
  269. package/dist/fonts/ObjectSans-ThinSlanted.20342160.woff2 +0 -0
  270. package/jest.config.js +0 -9
  271. package/plopfile.js +0 -67
  272. package/project.json +0 -69
  273. package/src/assets/fonts/Blitz-Script.woff2 +0 -0
  274. package/src/assets/fonts/ObjectSans-Bold.woff2 +0 -0
  275. package/src/assets/fonts/ObjectSans-BoldSlanted.woff2 +0 -0
  276. package/src/assets/fonts/ObjectSans-Heavy.woff2 +0 -0
  277. package/src/assets/fonts/ObjectSans-HeavySlanted.woff2 +0 -0
  278. package/src/assets/fonts/ObjectSans-Light.woff2 +0 -0
  279. package/src/assets/fonts/ObjectSans-LightSlanted.woff2 +0 -0
  280. package/src/assets/fonts/ObjectSans-Regular.woff2 +0 -0
  281. package/src/assets/fonts/ObjectSans-Slanted.woff2 +0 -0
  282. package/src/assets/fonts/ObjectSans-Thin.woff2 +0 -0
  283. package/src/assets/fonts/ObjectSans-ThinSlanted.woff2 +0 -0
  284. package/src/components/CAlert.vue +0 -78
  285. package/src/components/CBanner.vue +0 -47
  286. package/src/components/CButton.vue +0 -146
  287. package/src/components/CListItemAction.vue +0 -29
  288. package/src/components/CSegmentedButton.vue +0 -47
  289. package/src/components/CSegmentedButtonOption.vue +0 -42
  290. package/src/components/helpers/FormField.vue +0 -48
  291. package/src/components/helpers/SelectInput.vue +0 -115
  292. package/src/shims-scss.d.ts +0 -4
  293. package/src/shims-vuetify.d.ts +0 -4
  294. package/src/styles/_blitz.scss +0 -8
  295. package/src/styles/_object-sans.scss +0 -23
  296. package/storybook-static/0.799c368cbe88266827ba.manager.bundle.js +0 -1
  297. package/storybook-static/0.a9f0a9ad.iframe.bundle.js +0 -3
  298. package/storybook-static/0.a9f0a9ad.iframe.bundle.js.LICENSE.txt +0 -8
  299. package/storybook-static/0.a9f0a9ad.iframe.bundle.js.map +0 -1
  300. package/storybook-static/1.0438fd8d.iframe.bundle.js +0 -3
  301. package/storybook-static/1.0438fd8d.iframe.bundle.js.LICENSE.txt +0 -17
  302. package/storybook-static/1.0438fd8d.iframe.bundle.js.map +0 -1
  303. package/storybook-static/1.9ebd2fb519f6726108de.manager.bundle.js +0 -1
  304. package/storybook-static/10.348d8814.iframe.bundle.js +0 -3
  305. package/storybook-static/10.348d8814.iframe.bundle.js.LICENSE.txt +0 -30
  306. package/storybook-static/10.348d8814.iframe.bundle.js.map +0 -1
  307. package/storybook-static/10.a85ea1a67689be8e19ff.manager.bundle.js +0 -1
  308. package/storybook-static/11.f4e922583ae35da460f3.manager.bundle.js +0 -2
  309. package/storybook-static/11.f4e922583ae35da460f3.manager.bundle.js.LICENSE.txt +0 -12
  310. package/storybook-static/12.1415460941f0bdcb8fa8.manager.bundle.js +0 -1
  311. package/storybook-static/2.75a17459.iframe.bundle.js +0 -3
  312. package/storybook-static/2.75a17459.iframe.bundle.js.LICENSE.txt +0 -26
  313. package/storybook-static/2.75a17459.iframe.bundle.js.map +0 -1
  314. package/storybook-static/5.f459d151315e6780c20f.manager.bundle.js +0 -2
  315. package/storybook-static/5.f459d151315e6780c20f.manager.bundle.js.LICENSE.txt +0 -8
  316. package/storybook-static/6.3bd64d820f3745f262ff.manager.bundle.js +0 -1
  317. package/storybook-static/6.ce8d99b4.iframe.bundle.js +0 -1
  318. package/storybook-static/7.3d04765dbf3f1dcd706c.manager.bundle.js +0 -1
  319. package/storybook-static/7.6633a922.iframe.bundle.js +0 -3
  320. package/storybook-static/7.6633a922.iframe.bundle.js.LICENSE.txt +0 -12
  321. package/storybook-static/7.6633a922.iframe.bundle.js.map +0 -1
  322. package/storybook-static/8.b541eadfcb9164835dfc.manager.bundle.js +0 -1
  323. package/storybook-static/8.fc5e1ebf.iframe.bundle.js +0 -1
  324. package/storybook-static/9.411ac8e451bbb10926c7.manager.bundle.js +0 -1
  325. package/storybook-static/9.724ac3ed.iframe.bundle.js +0 -3
  326. package/storybook-static/9.724ac3ed.iframe.bundle.js.LICENSE.txt +0 -15
  327. package/storybook-static/9.724ac3ed.iframe.bundle.js.map +0 -1
  328. package/storybook-static/css/main.95216119.css +0 -1
  329. package/storybook-static/css/vendors~main.02dc89bf.css +0 -1
  330. package/storybook-static/favicon.ico +0 -0
  331. package/storybook-static/fonts/Blitz-Script.85ed9abe.woff2 +0 -0
  332. package/storybook-static/fonts/ObjectSans-Bold.5492f3d5.woff2 +0 -0
  333. package/storybook-static/fonts/ObjectSans-BoldSlanted.29e2a87e.woff2 +0 -0
  334. package/storybook-static/fonts/ObjectSans-Heavy.d0b2f035.woff2 +0 -0
  335. package/storybook-static/fonts/ObjectSans-HeavySlanted.45e9c063.woff2 +0 -0
  336. package/storybook-static/fonts/ObjectSans-Light.f885dec3.woff2 +0 -0
  337. package/storybook-static/fonts/ObjectSans-LightSlanted.b8eb7c12.woff2 +0 -0
  338. package/storybook-static/fonts/ObjectSans-Regular.e4ea0b90.woff2 +0 -0
  339. package/storybook-static/fonts/ObjectSans-Slanted.57a90be9.woff2 +0 -0
  340. package/storybook-static/fonts/ObjectSans-Thin.86d44227.woff2 +0 -0
  341. package/storybook-static/fonts/ObjectSans-ThinSlanted.20342160.woff2 +0 -0
  342. package/storybook-static/iframe.html +0 -348
  343. package/storybook-static/index.html +0 -51
  344. package/storybook-static/main.7b4aec9c4352d4bb535b.manager.bundle.js +0 -1
  345. package/storybook-static/main.9e8c64c7.iframe.bundle.js +0 -1
  346. package/storybook-static/runtime~main.91a0c7330ab317d35c4a.manager.bundle.js +0 -1
  347. package/storybook-static/runtime~main.e4da100f.iframe.bundle.js +0 -1
  348. package/storybook-static/vendors~main.6660eda6.iframe.bundle.js +0 -7
  349. package/storybook-static/vendors~main.6660eda6.iframe.bundle.js.LICENSE.txt +0 -80
  350. package/storybook-static/vendors~main.6660eda6.iframe.bundle.js.map +0 -1
  351. package/storybook-static/vendors~main.f7f16cebbf3aa96a4f89.manager.bundle.js +0 -2
  352. package/storybook-static/vendors~main.f7f16cebbf3aa96a4f89.manager.bundle.js.LICENSE.txt +0 -110
  353. package/tsconfig.dist.json +0 -7
  354. package/tsconfig.json +0 -24
  355. package/vue.config.js +0 -5
@@ -0,0 +1,347 @@
1
+ <!-- eslint-disable vue/no-deprecated-slot-attribute -->
2
+ <template>
3
+ <sl-button
4
+ v-bind="$attrs"
5
+ ref="button"
6
+ class="c-button"
7
+ :class="{
8
+ 'c-button--block': injectedOrPropBlock,
9
+ 'c-button--has-prefix-icon': hasIcon && iconPosition === 'prefix',
10
+ 'c-button--has-suffix-icon': hasIcon && iconPosition === 'suffix',
11
+ [`c-button-level--${level}`]: level,
12
+ [`c-button-variant--${computedVariant}`]: computedVariant,
13
+ [`c-button-size--${computedSize}`]: computedSize,
14
+ }"
15
+ :data-block="dataBlock"
16
+ :data-href="routerDestinationOrHref"
17
+ :data-level="level"
18
+ :data-loading="dataLoading"
19
+ :data-size="computedSize"
20
+ data-test="button"
21
+ :data-variant="computedVariant"
22
+ :disabled="disabled"
23
+ :href="routerDestinationOrHref"
24
+ :loading="loading || undefined"
25
+ :size="computedSize"
26
+ :target="target"
27
+ :variant="shoelaceVariant"
28
+ v-on="animationListeners"
29
+ @click="onClick"
30
+ @sl-focus="$emit('focus', $event)"
31
+ @sl-blur="$emit('blur', $event)"
32
+ >
33
+ <span v-if="hasIcon" :slot="iconPosition" data-test="button-icon-slot">
34
+ <slot name="icon">
35
+ <font-awesome-icon v-if="icon" :icon="icon" />
36
+ </slot>
37
+ </span>
38
+ <slot data-test="button-default-slot" />
39
+ </sl-button>
40
+ </template>
41
+
42
+ <script lang="ts">
43
+ import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
44
+ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
45
+ import '@shoelace-style/shoelace/dist/components/button/button.js';
46
+ import type { PropType } from 'vue';
47
+ import { computed, defineComponent, inject, ref, toRefs } from 'vue';
48
+ import type { RouteLocationRaw } from 'vue-router';
49
+
50
+ import type {
51
+ ButtonIconPosition,
52
+ ButtonLevel,
53
+ ButtonShoelaceVariant,
54
+ ButtonSize,
55
+ ButtonVariant,
56
+ } from '@propelinc/citrus-ui/src/components/CButton/types';
57
+ import { useTapAnimation } from '@propelinc/citrus-ui/src/composables/animation';
58
+ import { useRouterLink } from '@propelinc/citrus-ui/src/composables/router';
59
+ import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
60
+ import { BLOCK, BOUNCE_AMOUNT, LARGE } from '@propelinc/citrus-ui/src/services/injections/buttons';
61
+
62
+ /**
63
+ * Shoelace has a set of variants that don't match the variant names we would like to use.
64
+ * This mapping is used to translate the variant names to the correct Shoelace variant names
65
+ * and apply it to the underlying Shoelace button component.
66
+ */
67
+ export const VARIANT_TO_SHOELACE_VARIANT: Record<ButtonVariant, ButtonShoelaceVariant> = {
68
+ primary: 'primary',
69
+ // Shoelace `default` is an outline style
70
+ secondary: 'default',
71
+ tertiary: 'text',
72
+ };
73
+
74
+ const BLOCK_BOUNCE_AMOUNT = 0.96;
75
+ const BASE_BOUNCE_AMOUNT = 0.94;
76
+
77
+ export default defineComponent({
78
+ components: {
79
+ FontAwesomeIcon,
80
+ },
81
+ props: {
82
+ /** Controls whether button appears as full-width */
83
+ block: { type: Boolean, default: false },
84
+ /** Controls whether button is disabled */
85
+ disabled: { type: Boolean, default: false },
86
+ /** Designates the button as an anchor and applies the href attribute */
87
+ href: { type: String, default: undefined },
88
+ /** Chooses an icon to render on the left side of the button */
89
+ icon: {
90
+ type: [String, Array, Object] as PropType<string | string[] | IconDefinition>,
91
+ default: undefined,
92
+ },
93
+ /** Chooses whether to place the icon before or after the button text */
94
+ iconPosition: {
95
+ type: String as PropType<ButtonIconPosition>,
96
+ default: 'prefix',
97
+ validator: (value: string) => ['prefix', 'suffix'].includes(value),
98
+ },
99
+ /**
100
+ * @deprecated use `size` prop instead
101
+ * Controls whether button uses the large variant
102
+ */
103
+ large: { type: Boolean, default: false, deprecated: true },
104
+ /** Controls the level of the button */
105
+ level: {
106
+ type: String as PropType<ButtonLevel>,
107
+ default: 'normal',
108
+ validator: (value: string) => ['normal', 'danger'].includes(value),
109
+ },
110
+ /** Controls whether button is loading */
111
+ loading: { type: Boolean, default: false },
112
+ /**
113
+ * @deprecated use `variant` prop instead
114
+ * Controls whether button uses the secondary variant */
115
+ secondary: { type: Boolean, default: false, deprecated: true },
116
+ /**
117
+ * Controls the size of the button
118
+ * @default 'medium'
119
+ */
120
+ size: {
121
+ type: String as PropType<ButtonSize>,
122
+ default: 'medium',
123
+ validator: (value: string) => ['medium', 'large'].includes(value),
124
+ },
125
+ /** Designates the target attribute. Only use with the href prop. */
126
+ target: { type: String, default: undefined },
127
+ /**
128
+ * @deprecated use `variant` prop instead
129
+ * Controls whether button uses the tertiary variant
130
+ */
131
+ tertiary: { type: Boolean, default: false, deprecated: true },
132
+ /** Controls whether button functions as a router-link */
133
+ to: { type: [Object, String] as PropType<RouteLocationRaw>, default: undefined },
134
+ /**
135
+ * Controls the styling of the button
136
+ * @default 'primary'
137
+ */
138
+ variant: {
139
+ type: String as PropType<ButtonVariant>,
140
+ default: 'primary',
141
+ validator: (value: string) => ['primary', 'secondary', 'tertiary'].includes(value),
142
+ },
143
+ },
144
+ emits: ['click', 'focus', 'blur'],
145
+ setup(props, { emit }) {
146
+ const { block, to } = toRefs(props);
147
+ const { href: routerDestination, navigate } = useRouterLink(to);
148
+ const routerDestinationOrHref = computed(() => routerDestination.value ?? props.href);
149
+
150
+ const dataLoading = computed<true | undefined>(() => props.loading || undefined);
151
+
152
+ const injectedBlock = inject(BLOCK, undefined);
153
+ const injectedOrPropBlock = computed(() => injectedBlock?.value ?? props.block);
154
+ const dataBlock = computed<true | undefined>(() => injectedOrPropBlock.value || undefined);
155
+
156
+ const iconSlotHasContent = useSlotHasContent('icon');
157
+ const hasIcon = computed(() => iconSlotHasContent.value || !!props.icon);
158
+
159
+ /**
160
+ * Handle the deprecated `secondary` and `tertiary` props.
161
+ */
162
+ const computedVariant = computed((): ButtonVariant => {
163
+ if (props.secondary) {
164
+ return 'secondary';
165
+ }
166
+
167
+ if (props.tertiary) {
168
+ return 'tertiary';
169
+ }
170
+
171
+ return props.variant;
172
+ });
173
+
174
+ /**
175
+ * Map the computed variant to the Shoelace variant
176
+ */
177
+ const shoelaceVariant = computed(() => VARIANT_TO_SHOELACE_VARIANT[computedVariant.value]);
178
+
179
+ /**
180
+ * The deprecated `large` prop can be injected through a provider.
181
+ */
182
+ const injectedLarge = inject(LARGE, undefined);
183
+ const injectedOrPropsLarge = computed(() => injectedLarge?.value ?? props.large);
184
+ /**
185
+ * Because we want the `size` prop to have a default, it's always supplied.
186
+ * Thus, our only option to respect the deprecated `large` prop is to give it priority.
187
+ */
188
+ const computedSize = computed(() => {
189
+ if (injectedOrPropsLarge.value) {
190
+ return 'large';
191
+ }
192
+
193
+ return props.size;
194
+ });
195
+
196
+ function onClick(event: MouseEvent): void {
197
+ /**
198
+ * If the button is disabled or loading, do not take action.
199
+ * This prevents double/extra clicks when an async operation is in progress.
200
+ */
201
+ if (props.disabled || props.loading) {
202
+ return;
203
+ }
204
+
205
+ navigate(event);
206
+ emit('click', event);
207
+ }
208
+
209
+ const button = ref<HTMLElement | null>(null);
210
+ const injectedBounceAmount = inject(BOUNCE_AMOUNT, null);
211
+ const bounceAmount = computed(() => {
212
+ /**
213
+ * If the button is disabled or loading, do not animate the button.
214
+ */
215
+ if (props.disabled || props.loading) {
216
+ return 1;
217
+ }
218
+
219
+ if (injectedBounceAmount) {
220
+ return injectedBounceAmount;
221
+ }
222
+
223
+ if (block.value) {
224
+ return BLOCK_BOUNCE_AMOUNT;
225
+ }
226
+
227
+ return BASE_BOUNCE_AMOUNT;
228
+ });
229
+ const animationListeners = useTapAnimation({
230
+ el: button,
231
+ keyframes: {
232
+ default: { transform: 'scale(1)' },
233
+ pressed: { transform: `scale(${bounceAmount.value})` },
234
+ },
235
+ });
236
+
237
+ return {
238
+ animationListeners,
239
+ button,
240
+ computedSize,
241
+ computedVariant,
242
+ dataBlock,
243
+ dataLoading,
244
+ hasIcon,
245
+ injectedOrPropBlock,
246
+ injectedOrPropsLarge,
247
+ onClick,
248
+ routerDestinationOrHref,
249
+ shoelaceVariant,
250
+ };
251
+ },
252
+ });
253
+ </script>
254
+
255
+ <style lang="scss" scoped>
256
+ @import '@propelinc/citrus-ui/src/styles/core';
257
+ @import '@propelinc/citrus-ui/src/styles/button';
258
+
259
+ .c-button {
260
+ // Prevents the iOS tap highlight color from showing up on buttons
261
+ -webkit-tap-highlight-color: transparent;
262
+
263
+ &::part(base) {
264
+ // Included in all buttons so that they line up in rows, even buttons with transparent borders
265
+ border-width: $border-width;
266
+ transition: background-color 0.2s ease-in-out;
267
+ }
268
+
269
+ &::part(label) {
270
+ padding: 0 16px;
271
+ }
272
+ }
273
+
274
+ .c-button-size--medium::part(base) {
275
+ --sl-input-height-medium: #{$button-size-medium};
276
+ }
277
+
278
+ .c-button-size--large::part(base) {
279
+ --sl-input-height-large: #{$button-size-large};
280
+ }
281
+
282
+ .c-button--has-prefix-icon {
283
+ &::part(base) {
284
+ padding-inline-start: 16px;
285
+ }
286
+
287
+ &::part(label) {
288
+ padding-inline-start: 8px;
289
+ }
290
+ }
291
+
292
+ .c-button--has-suffix-icon {
293
+ &::part(base) {
294
+ padding-inline-end: 16px;
295
+ }
296
+
297
+ &::part(label) {
298
+ padding-inline-end: 8px;
299
+ }
300
+ }
301
+
302
+ .c-button--block {
303
+ min-width: 100%;
304
+ }
305
+
306
+ .c-button-variant--primary::part(base) {
307
+ @include button-theme-primary;
308
+ }
309
+
310
+ .c-button-variant--primary.c-button-level--danger::part(base) {
311
+ @include button-theme-primary-danger;
312
+ }
313
+
314
+ .c-button-variant--secondary::part(base) {
315
+ @include button-theme-secondary;
316
+ }
317
+
318
+ .c-button-variant--secondary.c-button-level--danger::part(base) {
319
+ @include button-theme-secondary-danger;
320
+ }
321
+
322
+ .c-button-variant--tertiary::part(base) {
323
+ @include button-theme-tertiary;
324
+ }
325
+
326
+ .c-button-variant--tertiary.c-button-level--danger::part(base) {
327
+ @include button-theme-tertiary-danger;
328
+ }
329
+
330
+ /**
331
+ * Override Shoelace's default disabled styles
332
+ * (The danger styles seem fine)
333
+ */
334
+ :not(.c-button-level--danger) {
335
+ &.c-button-variant--primary[disabled]::part(base) {
336
+ @include button-theme($color-gray-400, $color-gray-200, $color-gray-200);
337
+ }
338
+
339
+ &.c-button-variant--secondary[disabled]::part(base) {
340
+ @include button-theme($color-gray-300, $color-gray-300, transparent);
341
+ }
342
+
343
+ &.c-button-variant--tertiary[disabled]::part(base) {
344
+ @include button-theme($color-gray-300, transparent, transparent);
345
+ }
346
+ }
347
+ </style>
@@ -0,0 +1,5 @@
1
+ export type ButtonSize = 'medium' | 'large';
2
+ export type ButtonLevel = 'normal' | 'danger';
3
+ export type ButtonVariant = 'primary' | 'secondary' | 'tertiary';
4
+ export type ButtonShoelaceVariant = 'default' | 'primary' | 'text';
5
+ export type ButtonIconPosition = 'prefix' | 'suffix';
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <component :is="tag" class="c-button-stack" data-test="c-button-stack">
3
+ <slot />
4
+ </component>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { defineComponent, provide, ref, toRefs } from 'vue';
9
+
10
+ import { BLOCK, LARGE } from '@propelinc/citrus-ui/src/services/injections/buttons';
11
+
12
+ export default defineComponent({
13
+ props: {
14
+ tag: { type: String, default: 'div' },
15
+ large: { type: Boolean, default: null },
16
+ },
17
+ setup(props) {
18
+ const { large } = toRefs(props);
19
+
20
+ provide(BLOCK, ref(true));
21
+ provide(LARGE, large);
22
+ },
23
+ });
24
+ </script>
25
+
26
+ <style scoped>
27
+ /**
28
+ * FIXME: https://linear.app/slanden/issue/FE-37/remove-exported-margins
29
+ * These are exported margins, would be preferable to use a Flex column with gap instead
30
+ */
31
+ :deep() {
32
+ .c-button + .c-button {
33
+ margin-top: 8px;
34
+ }
35
+ }
36
+ </style>
@@ -1,64 +1,172 @@
1
1
  <template>
2
- <v-card
3
- flat
4
- :outlined="outlined"
5
- :ripple="false"
6
- class="card"
7
- :class="{ 'card--divided': divided }"
8
- :to="to"
2
+ <component
3
+ :is="config.element"
4
+ v-bind="config.attrs"
5
+ data-test="card"
6
+ class="c-card"
7
+ :class="{
8
+ 'c-card--tile': tile,
9
+ 'c-card--borderless': borderless,
10
+ 'c-card--link': config.isLink,
11
+ 'c-card--stretch': stretch,
12
+ }"
9
13
  :href="href"
10
- :color="color"
11
- v-on="$listeners"
14
+ :style="{
15
+ '--background-color': backgroundCssColor,
16
+ '--border-color': borderCssColor,
17
+ }"
18
+ :to="to"
12
19
  >
13
- <c-card-header v-if="title">
20
+ <CCardHeader v-if="title">
14
21
  {{ title }}
15
- </c-card-header>
16
-
22
+ </CCardHeader>
17
23
  <slot />
18
- </v-card>
24
+ </component>
19
25
  </template>
20
26
 
21
27
  <script lang="ts">
22
- import { Component, Vue, Prop } from 'vue-property-decorator';
23
- import { RawLocation } from 'vue-router';
24
-
25
- import CCardHeader from '@/components/CCardHeader.vue';
26
-
27
- @Component({ name: 'CCard', components: { CCardHeader } })
28
- export default class CCard extends Vue {
29
- @Prop(String) title?: string;
30
- /** Shows borders between header, sections, and footer */
31
- @Prop({ type: Boolean, default: false }) divided!: boolean;
32
- /** Sets background color */
33
- @Prop(String) color?: string;
34
- @Prop([Object, String]) to?: RawLocation;
35
- @Prop(String) href?: string;
36
- @Prop({ type: Boolean, default: true }) outlined!: boolean;
28
+ import type { PropType } from 'vue';
29
+ import { computed, defineComponent, toRefs } from 'vue';
30
+ import type { RouteLocationRaw } from 'vue-router';
31
+
32
+ import CCardHeader from '@propelinc/citrus-ui/src/components/CCardHeader.vue';
33
+ import { useCssColor } from '@propelinc/citrus-ui/src/composables/colors';
34
+
35
+ type RoutingVariant = 'none' | 'internal' | 'external';
36
+
37
+ export interface InternalCardConfig {
38
+ attrs: Record<string, unknown>;
39
+ element: string;
40
+ isLink: boolean;
37
41
  }
42
+
43
+ export default defineComponent({
44
+ components: { CCardHeader },
45
+ props: {
46
+ /** Sets the border color of the card */
47
+ borderColor: { type: String, default: undefined },
48
+
49
+ /** Removes the border of the card */
50
+ borderless: { type: Boolean, default: false },
51
+
52
+ /** Sets the background color of the entire card */
53
+ color: { type: String, default: undefined },
54
+
55
+ /** Navigates externally on click */
56
+ href: { type: String, default: undefined },
57
+
58
+ /** Stretches the card vertically to fill the height of the parent container */
59
+ stretch: { type: Boolean, default: false },
60
+
61
+ /** Toggles a squared-off card style intended to fill the width of the page */
62
+ tile: { type: Boolean, default: false },
63
+
64
+ /** Sets the title of the card */
65
+ title: { type: String, default: undefined },
66
+
67
+ /** Navigates within the app on click */
68
+ to: { type: [Object, String] as PropType<RouteLocationRaw | undefined>, default: undefined },
69
+ },
70
+ setup(props, { attrs }) {
71
+ const { href, to } = toRefs(props);
72
+
73
+ const { cssColor: backgroundCssColor } = useCssColor(() => props.color);
74
+ const { cssColor: borderCssColor } = useCssColor(() => props.borderColor);
75
+
76
+ const routingVariant = computed<RoutingVariant>(() => {
77
+ if (to.value) {
78
+ return 'internal';
79
+ }
80
+
81
+ if (href.value) {
82
+ return 'external';
83
+ }
84
+
85
+ return 'none';
86
+ });
87
+
88
+ const config = computed<InternalCardConfig>(() => {
89
+ switch (routingVariant.value) {
90
+ case 'internal':
91
+ return {
92
+ attrs,
93
+ element: 'router-link',
94
+ isLink: true,
95
+ };
96
+
97
+ case 'external':
98
+ return {
99
+ attrs: {
100
+ ...attrs,
101
+ role: 'link',
102
+ tabindex: '0',
103
+ target: '_blank',
104
+ },
105
+ element: 'a',
106
+ isLink: true,
107
+ };
108
+
109
+ case 'none':
110
+ default:
111
+ return { attrs, element: 'div', isLink: false };
112
+ }
113
+ });
114
+
115
+ return { config, backgroundCssColor, borderCssColor };
116
+ },
117
+ });
38
118
  </script>
39
119
 
40
120
  <style lang="scss" scoped>
41
- @import '~@/styles/core.scss';
121
+ @import '@propelinc/citrus-ui/src/styles/core';
42
122
 
43
- .card {
123
+ .c-card {
124
+ --background-color: #{$color-background};
125
+ --border-color: #{$color-border};
126
+ --border-radius: #{$border-radius-next};
127
+ --text-color: #{$color-text-primary};
128
+
129
+ background-color: var(--background-color);
130
+ border-color: var(--border-color);
131
+ border-radius: var(--border-radius);
132
+ border-style: solid;
133
+ border-width: $border-width;
134
+ color: var(--text-color);
135
+ display: block;
136
+ max-width: 100%;
44
137
  overflow: hidden;
45
138
 
139
+ /**
140
+ * FIXME: (kyleshevlin - https://linear.app/slanden/issue/FE-37/remove-exported-margins):
141
+ * This is an "exported margin" and we should try to remove it. They make composition difficult.
142
+ * Read more here: https://kyleshevlin.com/no-outer-margin
143
+ *
144
+ * For example, imagine we want to have multiple cards in a row. This selector will add a
145
+ * margin-top to every card except the first. That would not be desired.
146
+ *
147
+ * Ideally, layout of sibling cards is always handled by a parent element.
148
+ */
46
149
  & + & {
47
- margin-top: 12px;
150
+ margin-top: 8px;
48
151
  }
49
152
  }
50
153
 
51
- .card--divided::v-deep {
52
- :is(.card__header, .card__section, .card__footer):not(:first-child) {
53
- border-top: $border;
54
- }
154
+ .c-card--tile {
155
+ --border-radius: 0;
55
156
 
56
- .card__section {
57
- padding-top: $card-v-spacing;
58
- }
157
+ border-left: none;
158
+ border-right: none;
159
+ }
59
160
 
60
- .card__footer {
61
- padding-top: $card-v-spacing;
62
- }
161
+ .c-card--borderless {
162
+ --border-color: transparent;
163
+ }
164
+
165
+ .c-card--link {
166
+ cursor: pointer;
167
+ }
168
+
169
+ .c-card--stretch {
170
+ height: 100%;
63
171
  }
64
172
  </style>
@@ -1,39 +1,23 @@
1
1
  <template>
2
- <v-card-actions class="card__footer">
2
+ <CButtonStack v-bind="$attrs" data-test="card-footer" class="c-card-footer">
3
3
  <slot />
4
- </v-card-actions>
4
+ </CButtonStack>
5
5
  </template>
6
6
 
7
7
  <script lang="ts">
8
- import { Component, Vue } from 'vue-property-decorator';
8
+ import { defineComponent } from 'vue';
9
9
 
10
- @Component({ name: 'CCardFooter' })
11
- export default class CCardFooter extends Vue {}
10
+ import CButtonStack from '@propelinc/citrus-ui/src/components/CButtonStack.vue';
11
+
12
+ export default defineComponent({
13
+ components: { CButtonStack },
14
+ });
12
15
  </script>
13
16
 
14
17
  <style lang="scss" scoped>
15
- @import '~@/styles/core.scss';
16
-
17
- .card__footer {
18
- align-items: stretch;
19
- flex-direction: column;
20
-
21
- ::v-deep {
22
- :is(.button--primary, .button--secondary) + :is(.button--primary, .button--secondary) {
23
- margin-top: 8px;
24
- }
25
-
26
- :is(.button--primary, .button--secondary) + .button--tertiary {
27
- margin-top: 4px;
28
- }
29
-
30
- .button--tertiary + .button--tertiary {
31
- margin-top: 4px;
32
- }
18
+ @import '@propelinc/citrus-ui/src/styles/core';
33
19
 
34
- .button--tertiary {
35
- margin: -4px 0;
36
- }
37
- }
20
+ .c-card-footer {
21
+ padding: 0 16px 16px;
38
22
  }
39
23
  </style>