@propelinc/citrus-ui 0.5.1 → 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 (299) hide show
  1. package/README.md +56 -86
  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 +63 -77
  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 +280 -119
  232. package/src/styles/_form-fields.scss +69 -16
  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 +39 -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 +57 -45
  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/.nvmrc +0 -1
  250. package/.stylelintrc.js +0 -3
  251. package/babel.config.js +0 -3
  252. package/dist/citrus-ui.common.js +0 -42228
  253. package/dist/citrus-ui.common.js.map +0 -1
  254. package/dist/citrus-ui.css +0 -1
  255. package/dist/citrus-ui.umd.js +0 -42238
  256. package/dist/citrus-ui.umd.js.map +0 -1
  257. package/dist/citrus-ui.umd.min.js +0 -27
  258. package/dist/citrus-ui.umd.min.js.map +0 -1
  259. package/dist/demo.html +0 -10
  260. package/dist/fonts/Blitz-Script.85ed9abe.woff2 +0 -0
  261. package/dist/fonts/ObjectSans-Bold.5492f3d5.woff2 +0 -0
  262. package/dist/fonts/ObjectSans-BoldSlanted.29e2a87e.woff2 +0 -0
  263. package/dist/fonts/ObjectSans-Heavy.d0b2f035.woff2 +0 -0
  264. package/dist/fonts/ObjectSans-HeavySlanted.45e9c063.woff2 +0 -0
  265. package/dist/fonts/ObjectSans-Light.f885dec3.woff2 +0 -0
  266. package/dist/fonts/ObjectSans-LightSlanted.b8eb7c12.woff2 +0 -0
  267. package/dist/fonts/ObjectSans-Regular.e4ea0b90.woff2 +0 -0
  268. package/dist/fonts/ObjectSans-Slanted.57a90be9.woff2 +0 -0
  269. package/dist/fonts/ObjectSans-Thin.86d44227.woff2 +0 -0
  270. package/dist/fonts/ObjectSans-ThinSlanted.20342160.woff2 +0 -0
  271. package/jest.config.js +0 -9
  272. package/plopfile.js +0 -67
  273. package/postcss.config.js +0 -5
  274. package/src/assets/fonts/Blitz-Script.woff2 +0 -0
  275. package/src/assets/fonts/ObjectSans-Bold.woff2 +0 -0
  276. package/src/assets/fonts/ObjectSans-BoldSlanted.woff2 +0 -0
  277. package/src/assets/fonts/ObjectSans-Heavy.woff2 +0 -0
  278. package/src/assets/fonts/ObjectSans-HeavySlanted.woff2 +0 -0
  279. package/src/assets/fonts/ObjectSans-Light.woff2 +0 -0
  280. package/src/assets/fonts/ObjectSans-LightSlanted.woff2 +0 -0
  281. package/src/assets/fonts/ObjectSans-Regular.woff2 +0 -0
  282. package/src/assets/fonts/ObjectSans-Slanted.woff2 +0 -0
  283. package/src/assets/fonts/ObjectSans-Thin.woff2 +0 -0
  284. package/src/assets/fonts/ObjectSans-ThinSlanted.woff2 +0 -0
  285. package/src/components/CAlert.vue +0 -73
  286. package/src/components/CBanner.vue +0 -47
  287. package/src/components/CButton.vue +0 -146
  288. package/src/components/CListItemAction.vue +0 -29
  289. package/src/components/CSegmentedButton.vue +0 -47
  290. package/src/components/CSegmentedButtonOption.vue +0 -42
  291. package/src/components/helpers/FormField.vue +0 -48
  292. package/src/components/helpers/SelectInput.vue +0 -115
  293. package/src/shims-scss.d.ts +0 -4
  294. package/src/shims-vuetify.d.ts +0 -4
  295. package/src/styles/_blitz.scss +0 -8
  296. package/src/styles/_object-sans.scss +0 -23
  297. package/tsconfig.dist.json +0 -9
  298. package/tsconfig.json +0 -42
  299. package/vue.config.js +0 -5
@@ -0,0 +1,101 @@
1
+ import type { ElementAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry.js';
2
+
3
+ export interface AnimationOptions {
4
+ /** The starting progress through the animation from 0 to 1 */
5
+ start?: number;
6
+ /** The duration of the animation in milliseconds */
7
+ duration?: number;
8
+ /** The easing function to use for the animation */
9
+ easing?: string;
10
+ /** The endimum distance to slide */
11
+ end?: number;
12
+ }
13
+
14
+ const DEFAULT_DURATION = 300;
15
+ const DEFAULT_EASING = 'ease';
16
+
17
+ export function fadeIn({
18
+ start = 0,
19
+ duration = DEFAULT_DURATION,
20
+ easing = DEFAULT_EASING,
21
+ }: AnimationOptions = {}): ElementAnimation {
22
+ return {
23
+ keyframes: [
24
+ { opacity: start, offset: 0 },
25
+ { opacity: 1, offset: 1 },
26
+ ],
27
+ options: { duration, easing },
28
+ };
29
+ }
30
+
31
+ export function fadeOut({
32
+ start = 0,
33
+ duration = DEFAULT_DURATION,
34
+ easing = DEFAULT_EASING,
35
+ }: AnimationOptions = {}): ElementAnimation {
36
+ return {
37
+ keyframes: [
38
+ { opacity: 1 - start, offset: 0 },
39
+ { opacity: 0, offset: 1 },
40
+ ],
41
+ options: { duration, easing },
42
+ };
43
+ }
44
+
45
+ export function slideUp({
46
+ start = 0,
47
+ duration = DEFAULT_DURATION,
48
+ easing = DEFAULT_EASING,
49
+ }: AnimationOptions = {}): ElementAnimation {
50
+ return {
51
+ keyframes: [
52
+ { translate: `0 ${(1 - start) * 100}%`, offset: 0 },
53
+ { translate: '0 0', offset: 1 },
54
+ ],
55
+ options: { duration, easing },
56
+ };
57
+ }
58
+
59
+ export function slideDown({
60
+ start = 0,
61
+ duration = DEFAULT_DURATION,
62
+ easing = DEFAULT_EASING,
63
+ }: AnimationOptions = {}): ElementAnimation {
64
+ return {
65
+ keyframes: [
66
+ { translate: `0 ${start * 100}%`, offset: 0 },
67
+ { translate: '0 100%', offset: 1 },
68
+ ],
69
+ options: { duration, easing },
70
+ };
71
+ }
72
+
73
+ export function slideRight({
74
+ start = 0,
75
+ duration = DEFAULT_DURATION,
76
+ easing = DEFAULT_EASING,
77
+ end = 1,
78
+ }: AnimationOptions = {}): ElementAnimation {
79
+ return {
80
+ keyframes: [
81
+ { translate: `${start * 100}% 0`, offset: 0 },
82
+ { translate: `${end * 100}% 0`, offset: 1 },
83
+ ],
84
+ options: { duration, easing },
85
+ };
86
+ }
87
+
88
+ export function slideLeft({
89
+ start = 0,
90
+ duration = DEFAULT_DURATION,
91
+ easing = DEFAULT_EASING,
92
+ end = 1,
93
+ }: AnimationOptions = {}): ElementAnimation {
94
+ return {
95
+ keyframes: [
96
+ { translate: `${-start * 100}% 0`, offset: 0 },
97
+ { translate: `${-end * 100}% 0`, offset: 1 },
98
+ ],
99
+ options: { duration, easing },
100
+ };
101
+ }
@@ -0,0 +1,2 @@
1
+ export { scrollIntoView } from './scroll-into-view';
2
+ export { tapAnimation } from './tap-animation';
@@ -0,0 +1,86 @@
1
+ import type { DebouncedFunc } from 'lodash';
2
+ import { debounce } from 'lodash';
3
+ import type { Directive } from 'vue';
4
+
5
+ interface ScrollIntoViewElement extends HTMLElement {
6
+ scrollDirective?: {
7
+ focusable: HTMLInputElement | HTMLTextAreaElement;
8
+ scrollIfNeeded: DebouncedFunc<() => void>;
9
+ focusListener: () => void;
10
+ blurListener: () => void;
11
+ };
12
+ }
13
+
14
+ // NOTE(mohan): This is to support browsers without visualViewport.
15
+ const getViewport = (): Window | VisualViewport => window.visualViewport ?? window;
16
+
17
+ const scrollToElement = (element: Element): void => {
18
+ const rect = element.getBoundingClientRect();
19
+ const windowHeight = window.innerHeight || document.documentElement.clientHeight;
20
+
21
+ // Check if element is obscured by header or footer
22
+ const appHeight = document.getElementById('app')?.clientHeight;
23
+ const estimatedHeaderHeight =
24
+ document.getElementsByClassName('app-bar c-app-bar')[0]?.clientHeight || 64;
25
+ const estimatedFooterHeight =
26
+ document.getElementsByClassName('c-fixed-page-footer')[0]?.clientHeight ||
27
+ document.getElementsByClassName('scrollable-footer')[0]?.clientHeight ||
28
+ 0;
29
+ const contentStartY = appHeight
30
+ ? windowHeight - (appHeight - estimatedHeaderHeight)
31
+ : estimatedHeaderHeight;
32
+ const contentEndY = windowHeight - estimatedFooterHeight;
33
+
34
+ const isObscuredByHeader = rect.top < contentStartY;
35
+ const isObscuredByFooter = rect.bottom > contentEndY;
36
+
37
+ if (isObscuredByHeader || isObscuredByFooter) {
38
+ element.scrollIntoView({ behavior: 'smooth', block: 'center' });
39
+ }
40
+ };
41
+
42
+ /**
43
+ * This directive scrolls the element into view when the input inside it is focused.
44
+ *
45
+ * It also listens for viewport size changes, so it can scroll again if the keyboard pops up.
46
+ */
47
+ export const scrollIntoView: Directive = {
48
+ beforeMount(el: ScrollIntoViewElement): void {
49
+ const inputEl = el.querySelector('input,textarea');
50
+ if (!inputEl) {
51
+ return;
52
+ }
53
+
54
+ el.scrollDirective = {
55
+ focusable: inputEl as HTMLInputElement | HTMLTextAreaElement,
56
+ scrollIfNeeded: debounce((): void => {
57
+ scrollToElement(el);
58
+ }, 300),
59
+ focusListener: (): void => {
60
+ if (el.scrollDirective) {
61
+ el.scrollDirective.scrollIfNeeded();
62
+ // When focused, we track the viewport size, so we can scroll again if the keyboard pops up.
63
+ getViewport().addEventListener('resize', el.scrollDirective.scrollIfNeeded);
64
+ }
65
+ },
66
+ blurListener: (): void => {
67
+ if (el.scrollDirective) {
68
+ el.scrollDirective.scrollIfNeeded.cancel();
69
+ getViewport().removeEventListener('resize', el.scrollDirective.scrollIfNeeded);
70
+ }
71
+ },
72
+ };
73
+
74
+ inputEl.addEventListener('focus', el.scrollDirective!.focusListener);
75
+ inputEl.addEventListener('blur', el.scrollDirective!.blurListener);
76
+ },
77
+
78
+ unmounted(el: ScrollIntoViewElement): void {
79
+ if (el.scrollDirective) {
80
+ el.scrollDirective.scrollIfNeeded.cancel();
81
+ el.scrollDirective.focusable.removeEventListener('focus', el.scrollDirective.focusListener);
82
+ el.scrollDirective.focusable.removeEventListener('blur', el.scrollDirective.blurListener);
83
+ getViewport().removeEventListener('resize', el.scrollDirective.scrollIfNeeded);
84
+ }
85
+ },
86
+ };
@@ -0,0 +1,71 @@
1
+ import { ref } from 'vue';
2
+ import type { Directive, DirectiveBinding } from 'vue';
3
+
4
+ import { useTapAnimation } from '../../composables/animation';
5
+
6
+ interface TapAnimationValue {
7
+ bounceAmount?: number;
8
+ }
9
+
10
+ interface TapAnimationElement extends HTMLElement {
11
+ __tapAnimationCleanup?: () => void;
12
+ }
13
+
14
+ const DEFAULT_BOUNCE_AMOUNT = 0.94;
15
+
16
+ function setupTapAnimation(el: HTMLElement, bounceAmount: number): void {
17
+ const animationListeners = useTapAnimation({
18
+ el: ref(el),
19
+ keyframes: {
20
+ default: { transform: 'scale(1)' },
21
+ pressed: { transform: `scale(${bounceAmount})` },
22
+ },
23
+ });
24
+
25
+ // Add event listeners
26
+ Object.entries(animationListeners).forEach(([event, handler]) => {
27
+ el.addEventListener(event, handler);
28
+ });
29
+
30
+ // The cleanup function is essential here to ensure that all event listeners added by the directive are removed
31
+ // when the directive is unbound. Without this cleanup, the event listeners would remain attached to the element,
32
+ // potentially causing memory leaks and unexpected behavior. This function is called in the 'unbind' hook to properly
33
+ // clean up the element.
34
+ (el as TapAnimationElement).__tapAnimationCleanup = (): void => {
35
+ Object.entries(animationListeners).forEach(([event, handler]) => {
36
+ el.removeEventListener(event, handler);
37
+ });
38
+ };
39
+ }
40
+
41
+ export const tapAnimation: Directive<HTMLElement, TapAnimationValue> = {
42
+ beforeMount(el: HTMLElement, binding: DirectiveBinding<TapAnimationValue>): void {
43
+ // Check for reduced motion preference
44
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
45
+ if (prefersReducedMotion) {
46
+ return;
47
+ }
48
+
49
+ const bounceAmount = binding.value?.bounceAmount ?? DEFAULT_BOUNCE_AMOUNT;
50
+ setupTapAnimation(el, bounceAmount);
51
+ },
52
+
53
+ updated(el: HTMLElement, binding: DirectiveBinding<TapAnimationValue>): void {
54
+ // Check for reduced motion preference
55
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
56
+ if (prefersReducedMotion) {
57
+ return;
58
+ }
59
+
60
+ // If bounce amount changes, we need to re-mount the directive
61
+ if (binding.value?.bounceAmount !== binding.oldValue?.bounceAmount) {
62
+ (el as TapAnimationElement).__tapAnimationCleanup?.();
63
+ const bounceAmount = binding.value?.bounceAmount ?? DEFAULT_BOUNCE_AMOUNT;
64
+ setupTapAnimation(el, bounceAmount);
65
+ }
66
+ },
67
+
68
+ unmounted(el: HTMLElement): void {
69
+ (el as TapAnimationElement).__tapAnimationCleanup?.();
70
+ },
71
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Generates unique IDs for components. Useful for linking labels to inputs.
3
+ */
4
+ export class ID {
5
+ private counters: Record<string, number> = {};
6
+
7
+ /**
8
+ * Generates a unique ID for a component.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * // From within a component
13
+ * id.getID(this.$options.name);
14
+ * ```
15
+ */
16
+ getID(componentName: string): string {
17
+ const counter = this.counters[componentName] || 0;
18
+ this.counters[componentName] = counter + 1;
19
+ const kebabCaseName = componentName.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase();
20
+ return `${kebabCaseName}-${counter}`;
21
+ }
22
+
23
+ reset(): void {
24
+ this.counters = {};
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @deprecated Use the `useId` composable instead.
30
+ */
31
+ export default new ID();
@@ -0,0 +1,4 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const FLUID = Symbol('fluid') as InjectionKey<Ref<boolean>>;
4
+ export const ON_TOGGLE = Symbol('on-toggle') as InjectionKey<() => void>;
@@ -0,0 +1,3 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const ANIMATIONS_DISABLED = Symbol('animations-disabled') as InjectionKey<Ref<boolean>>;
@@ -0,0 +1,5 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const BLOCK = Symbol('block') as InjectionKey<Ref<boolean>>;
4
+ export const LARGE = Symbol('large') as InjectionKey<Ref<boolean>>;
5
+ export const BOUNCE_AMOUNT = Symbol('bounce-amount') as InjectionKey<number>;
@@ -0,0 +1,8 @@
1
+ import type { InjectionKey } from 'vue';
2
+
3
+ import type { ValidationState } from '@propelinc/citrus-ui/src/types/CForm';
4
+
5
+ export const VALIDATIONS = Symbol('validations') as InjectionKey<{
6
+ register: (input: ValidationState) => void;
7
+ unregister: (id: string) => void;
8
+ }>;
@@ -0,0 +1,4 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const TERTIARY = Symbol('tertiary') as InjectionKey<Ref<boolean>>;
4
+ export const INHERIT_COLOR = Symbol('inherit-color') as InjectionKey<Ref<boolean>>;
@@ -0,0 +1,7 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export const SELECTED_VALUE = Symbol('selected-value') as InjectionKey<Ref<string>>;
4
+ export const TOGGLE_VALUE = Symbol('toggle-value') as InjectionKey<
5
+ (value: string | undefined) => void
6
+ >;
7
+ export const ROLE = Symbol('role') as InjectionKey<Ref<string>>;
@@ -0,0 +1,12 @@
1
+ import type { InjectionKey, Ref } from 'vue';
2
+
3
+ export interface RadioState {
4
+ value: unknown;
5
+ invalid: boolean;
6
+ name: string;
7
+ update: (value: unknown) => void;
8
+ register: (value: unknown) => void;
9
+ unregister: (value: unknown) => void;
10
+ }
11
+
12
+ export const RADIO_STATE = Symbol('radio-state') as InjectionKey<Ref<RadioState>>;
@@ -1,4 +1,7 @@
1
- declare module '*.vue' {
2
- import Vue from 'vue';
3
- export default Vue;
1
+ declare module 'vue' {
2
+ export interface ComponentCustomProperties {
3
+ $t: (key: string, interpolations?: Record<string, string | number>) => string;
4
+ }
4
5
  }
6
+
7
+ export {};
@@ -0,0 +1,19 @@
1
+ @keyframes skeleton-loader-animation {
2
+ 0% {
3
+ background-position: 150%;
4
+ }
5
+
6
+ 100% {
7
+ background-position: -50%;
8
+ }
9
+ }
10
+
11
+ @keyframes loader-spin-fast-slow {
12
+ from {
13
+ transform: rotate(0deg);
14
+ }
15
+
16
+ to {
17
+ transform: rotate(1080deg);
18
+ }
19
+ }
@@ -0,0 +1,61 @@
1
+ @mixin button-theme($color, $border-color, $background-color) {
2
+ background-color: $background-color;
3
+ border-color: $border-color;
4
+ color: $color;
5
+ }
6
+
7
+ @mixin button-theme-primary() {
8
+ @include button-theme($color-white, $color-black, $color-black);
9
+
10
+ &:hover {
11
+ @include button-theme($color-white, $color-black, $color-black);
12
+ }
13
+ }
14
+
15
+ @mixin button-theme-secondary() {
16
+ @include button-theme($color-black, $color-black, transparent);
17
+
18
+ &:hover {
19
+ @include button-theme($color-black, $color-black, transparent);
20
+ }
21
+ }
22
+
23
+ @mixin button-theme-tertiary() {
24
+ @include button-theme($color-black, transparent, transparent);
25
+
26
+ &:hover {
27
+ @include button-theme($color-black, transparent, transparent);
28
+ }
29
+ }
30
+
31
+ @mixin button-theme-primary-danger() {
32
+ @include button-theme($color-white, $color-status-error, $color-status-error);
33
+
34
+ &:hover {
35
+ @include button-theme($color-white, $color-status-error, $color-status-error);
36
+ }
37
+ }
38
+
39
+ @mixin button-theme-secondary-danger() {
40
+ @include button-theme($color-status-error, $color-status-error, $color-white);
41
+
42
+ &:hover {
43
+ @include button-theme($color-status-error, $color-status-error, $color-white);
44
+ }
45
+ }
46
+
47
+ @mixin button-theme-tertiary-danger() {
48
+ @include button-theme($color-status-error, transparent, transparent);
49
+
50
+ &:hover {
51
+ @include button-theme($color-status-error, transparent, transparent);
52
+ }
53
+ }
54
+
55
+ @mixin button-theme-close() {
56
+ @include button-theme($color-black, $color-white, $color-white);
57
+
58
+ &:hover {
59
+ @include button-theme($color-black, $color-white, $color-white);
60
+ }
61
+ }
@@ -1,4 +1,6 @@
1
- @import "@/styles/core.scss";
1
+ @import '@propelinc/citrus-ui/src/styles/core';
2
+
3
+ // NOTE(slanden): Be sure to update the colors.ts file when updating this file.
2
4
 
3
5
  :export {
4
6
  ACCENT_BLUE: $color-accent-blue;
@@ -7,25 +9,70 @@
7
9
  ACCENT_GREEN: $color-accent-green;
8
10
  ACCENT_GREEN_SHADE_1: $color-accent-green-shade-1;
9
11
  ACCENT_GREEN_SHADE_2: $color-accent-green-shade-2;
12
+ ACCENT_ORANGE: $color-accent-orange;
13
+ ACCENT_ORANGE_SHADE_1: $color-accent-orange-shade-1;
14
+ ACCENT_ORANGE_SHADE_2: $color-accent-orange-shade-2;
15
+ ACCENT_PINK: $color-accent-pink;
16
+ ACCENT_PINK_SHADE_1: $color-accent-pink-shade-1;
17
+ ACCENT_PINK_SHADE_2: $color-accent-pink-shade-2;
18
+ ACCENT_RED_SHADE_1: $color-accent-red-shade-1;
19
+ ACCENT_RED_SHADE_2: $color-accent-red-shade-2;
10
20
  ALERT_RED: $color-alert-red;
11
- LEMON: $color-lemon;
12
- NAVY: $color-navy;
13
- NAVY_TINT_1: $color-navy-tint-1;
14
- NAVY_TINT_2: $color-navy-tint-2;
15
- NAVY_TINT_3: $color-navy-tint-3;
16
- NAVY_TINT_4: $color-navy-tint-4;
17
- NEUTRAL: $color-neutral;
18
- NEUTRAL_SHADE: $color-neutral-shade;
21
+ BACKGROUND: $color-background;
22
+ BLACK: $color-black;
23
+ BLUE_100: $color-blue-100;
24
+ BLUE_200: $color-blue-200;
25
+ BLUE_300: $color-blue-300;
26
+ BLUE_400: $color-blue-400;
27
+ BLUE_500: $color-blue-500;
28
+ BORDER: $color-border;
29
+ BUTTON_BACKGROUND: $color-button-background;
30
+ GOLD_100: $color-gold-100;
31
+ GOLD_200: $color-gold-200;
32
+ GOLD_300: $color-gold-300;
33
+ GOLD_400: $color-gold-400;
34
+ GOLD_500: $color-gold-500;
35
+ GRAY_100: $color-gray-100;
36
+ GRAY_200: $color-gray-200;
37
+ GRAY_300: $color-gray-300;
38
+ GRAY_400: $color-gray-400;
39
+ GRAY_500: $color-gray-500;
40
+ GREEN_100: $color-green-100;
41
+ GREEN_200: $color-green-200;
42
+ GREEN_300: $color-green-300;
43
+ GREEN_400: $color-green-400;
44
+ GREEN_500: $color-green-500;
19
45
  ORANGE: $color-orange;
20
- PEACH: $color-peach;
46
+ ORANGE_TINT_1: $color-orange-tint-1;
47
+ ORANGE_TINT_2: $color-orange-tint-2;
21
48
  PINK: $color-pink;
49
+ PINK_TINT_1: $color-pink-tint-1;
50
+ PINK_TINT_2: $color-pink-tint-2;
22
51
  PROVIDERS_BLUE: $color-providers-blue;
23
52
  PROVIDERS_BLUE_TINT_1: $color-providers-blue-tint-1;
24
53
  PROVIDERS_BLUE_TINT_2: $color-providers-blue-tint-2;
25
54
  PROVIDERS_GREEN: $color-providers-green;
26
55
  PROVIDERS_GREEN_TINT_1: $color-providers-green-tint-1;
27
56
  PROVIDERS_GREEN_TINT_2: $color-providers-green-tint-2;
28
- PURPLE: $color-purple;
57
+ PURPLE_100: $color-purple-100;
58
+ PURPLE_200: $color-purple-200;
59
+ PURPLE_300: $color-purple-300;
60
+ PURPLE_400: $color-purple-400;
61
+ PURPLE_500: $color-purple-500;
62
+ RED_100: $color-red-100;
63
+ RED_200: $color-red-200;
64
+ RED_300: $color-red-300;
65
+ RED_400: $color-red-400;
66
+ RED_500: $color-red-500;
67
+ STATUS_ERROR: $color-status-error;
68
+ STATUS_SUCCESS: $color-status-success;
69
+ STATUS_WARNING: $color-status-warning;
70
+ TEXT_DISABLED: $color-text-disabled;
71
+ TEXT_PLACEHOLDER: $color-text-placeholder;
72
+ TEXT_PRIMARY: $color-text-primary;
73
+ TEXT_SECONDARY: $color-text-secondary;
29
74
  WHITE: $color-white;
30
75
  YELLOW: $color-yellow;
76
+ YELLOW_TINT_1: $color-yellow-tint-1;
77
+ YELLOW_TINT_2: $color-yellow-tint-2;
31
78
  }