@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,142 @@
1
+ <template>
2
+ <fieldset
3
+ :id="idWithFallback"
4
+ ref="radioGroup"
5
+ :data-test="dataTest"
6
+ role="radiogroup"
7
+ class="c-radio-group"
8
+ :class="{
9
+ 'c-radio-group--column': column,
10
+ 'c-radio-group--row': !column,
11
+ 'c-radio-group--invalid': !isValidationValid,
12
+ }"
13
+ :aria-invalid="isValidationValid ? 'false' : 'true'"
14
+ :aria-labelledby="`${idWithFallback}-label`"
15
+ :aria-errormessage="`${idWithFallback}-message`"
16
+ >
17
+ <span :id="`${idWithFallback}-label`" :data-test="`${dataTest}-label`">
18
+ <slot name="label">{{ label }}</slot>
19
+ </span>
20
+
21
+ <slot />
22
+
23
+ <CValidationMessage
24
+ :id="`${idWithFallback}-message`"
25
+ :data-test="`${dataTest}-message`"
26
+ :validation-message="validationMessage"
27
+ :hide="hideDetails"
28
+ >
29
+ <slot name="message" />
30
+ </CValidationMessage>
31
+ </fieldset>
32
+ </template>
33
+
34
+ <script lang="ts">
35
+ import { type PropType, computed, defineComponent, provide, ref, toRefs, watch } from 'vue';
36
+
37
+ import CValidationMessage from '@propelinc/citrus-ui/src/components/CValidationMessage.vue';
38
+ import { useInternalValue } from '@propelinc/citrus-ui/src/composables/binding';
39
+ import { useId } from '@propelinc/citrus-ui/src/composables/id';
40
+ import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
41
+ import { useValidations } from '@propelinc/citrus-ui/src/composables/validations';
42
+ import { RADIO_STATE } from '@propelinc/citrus-ui/src/services/injections/radio';
43
+
44
+ export default defineComponent({
45
+ name: 'CRadioGroup',
46
+ components: { CValidationMessage },
47
+ props: {
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ value: { type: null as unknown as PropType<any>, default: null },
50
+ id: { type: String as PropType<string | null>, default: null },
51
+ dataTest: { type: String, default: 'radio-group' },
52
+ label: { type: String as PropType<string | null>, default: null },
53
+ column: { type: Boolean, default: true },
54
+ mandatory: { type: Boolean, default: false },
55
+ rules: { type: Array as PropType<Rules<string>>, default: () => [] },
56
+ hideDetails: { type: Boolean as PropType<boolean | 'auto'>, default: false },
57
+ },
58
+ emits: ['change', 'input'],
59
+ setup(props, { emit }) {
60
+ const { value, rules, id, mandatory } = toRefs(props);
61
+ const idWithFallback = useId(id);
62
+ const radioGroup = ref<HTMLElement | null>(null);
63
+
64
+ const internalValue = useInternalValue(value, {
65
+ onChange: (newValue) => {
66
+ emit('change', newValue);
67
+ emit('input', newValue);
68
+ },
69
+ });
70
+
71
+ const {
72
+ startValidating,
73
+ message: validationMessage,
74
+ valid: isValidationValid,
75
+ } = useValidations({
76
+ id: idWithFallback,
77
+ value: internalValue,
78
+ rules,
79
+ required: mandatory,
80
+ validateOn: 'change',
81
+ });
82
+
83
+ provide(
84
+ RADIO_STATE,
85
+ computed(() => ({
86
+ invalid: !isValidationValid.value,
87
+ value: internalValue.value,
88
+ name: idWithFallback.value,
89
+ update: (newValue: unknown): void => {
90
+ internalValue.value = newValue;
91
+ },
92
+ register: (value: unknown): void => {
93
+ if (props.mandatory && internalValue.value === null) {
94
+ internalValue.value = value;
95
+ }
96
+ },
97
+ unregister: (value: unknown): void => {
98
+ if (internalValue.value === value) {
99
+ internalValue.value = null;
100
+ }
101
+ },
102
+ }))
103
+ );
104
+
105
+ watch(internalValue, () => {
106
+ startValidating();
107
+ });
108
+
109
+ return {
110
+ idWithFallback,
111
+ isValidationValid,
112
+ radioGroup,
113
+ validationMessage,
114
+ };
115
+ },
116
+ });
117
+ </script>
118
+
119
+ <style lang="scss" scoped>
120
+ @import '@propelinc/citrus-ui/src/styles/core';
121
+ @import '@propelinc/citrus-ui/src/styles/form-fields';
122
+
123
+ .c-radio-group {
124
+ border: none;
125
+ display: flex;
126
+ flex-direction: row;
127
+ gap: 8px;
128
+ width: 100%;
129
+
130
+ &.c-radio-group--column {
131
+ flex-direction: column;
132
+ }
133
+
134
+ &--row {
135
+ align-items: center;
136
+
137
+ :deep(.c-radio) {
138
+ width: auto;
139
+ }
140
+ }
141
+ }
142
+ </style>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <div :class="{ 'w-100': fullWidth }">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ /**
9
+ * NOTE(slanden): This component is no longer used. We are keeping it around for now
10
+ * because it is used in the CMS, but other than applying the w-100 class, it has
11
+ * no effect. We will remove this component in a future PR.
12
+ */
13
+
14
+ withDefaults(
15
+ defineProps<{
16
+ fullWidth?: boolean;
17
+ }>(),
18
+ {
19
+ fullWidth: false,
20
+ }
21
+ );
22
+ </script>
23
+
24
+ <style scoped>
25
+ .w-100 {
26
+ width: 100%;
27
+ }
28
+ </style>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <div
3
+ class="c-row"
4
+ :class="{
5
+ 'c-row--dense': dense,
6
+ 'c-row--no-gutters': noGutters,
7
+ [`align-${align}`]: align,
8
+ [`align-content-${alignContent}`]: alignContent,
9
+ [`justify-${justify}`]: justify,
10
+ }"
11
+ >
12
+ <slot />
13
+ </div>
14
+ </template>
15
+
16
+ <script lang="ts">
17
+ import { type PropType, defineComponent } from 'vue';
18
+
19
+ export default defineComponent({
20
+ props: {
21
+ /** Applies the align-items css property.
22
+ * Available options are: start, center, end and stretch. */
23
+ align: {
24
+ type: String as PropType<'center' | 'start' | 'end' | 'stretch'>,
25
+ default: null,
26
+ },
27
+ /** Applies the align-content css property.
28
+ * Available options are: start, center, end, and stretch. */
29
+ alignContent: {
30
+ type: String as PropType<'center' | 'start' | 'end' | 'stretch'>,
31
+ default: null,
32
+ },
33
+ /** Reduces the gutter between c-cols. */
34
+ dense: { type: Boolean, default: false },
35
+ /** Removes the gutter between c-cols. */
36
+ noGutters: { type: Boolean, default: false },
37
+ /** Applies the justify-content css property.
38
+ * Available options are: start, center, end, space-between and space-around. */
39
+ justify: {
40
+ type: String as PropType<'center' | 'start' | 'end' | 'space-between' | 'space-around'>,
41
+ default: null,
42
+ },
43
+ },
44
+ });
45
+ </script>
46
+
47
+ <style lang="scss" scoped>
48
+ .c-row {
49
+ display: flex;
50
+ flex: 1 1 auto;
51
+ flex-wrap: wrap;
52
+ margin: 0 -12px;
53
+ }
54
+
55
+ .c-row--dense {
56
+ margin: 0 -4px;
57
+ }
58
+
59
+ .c-row--no-gutters {
60
+ margin: 0;
61
+ }
62
+ </style>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div class="c-safe-area">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <style scoped>
8
+ .c-safe-area {
9
+ --full-height: 100vh;
10
+
11
+ display: flex;
12
+ flex-direction: column;
13
+ height: calc(var(--full-height) - env(safe-area-inset-top) - env(safe-area-inset-bottom));
14
+ max-width: 100%;
15
+ overflow: scroll;
16
+ }
17
+
18
+ @supports (height: 100dvh) {
19
+ .c-safe-area {
20
+ --full-height: 100dvh;
21
+ }
22
+ }
23
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div class="c-section-header" data-test="section-header">
3
+ <component :is="tag" class="c-section-header__title" data-test="section-header-title">
4
+ {{ title }}
5
+ </component>
6
+ <slot name="append" />
7
+ </div>
8
+ </template>
9
+
10
+ <script lang="ts">
11
+ import { defineComponent, provide, ref } from 'vue';
12
+
13
+ import { TERTIARY as TERTIARY_ICON_BUTTON } from '@propelinc/citrus-ui/src/services/injections/icon-buttons';
14
+
15
+ export default defineComponent({
16
+ props: {
17
+ /** The title text to display. */
18
+ title: { type: String, default: '' },
19
+ /** The tag used for the title text. */
20
+ tag: { type: String, default: 'h2' },
21
+ },
22
+ setup(): void {
23
+ provide(TERTIARY_ICON_BUTTON, ref(true));
24
+ },
25
+ });
26
+ </script>
27
+
28
+ <style lang="scss" scoped>
29
+ @import '@propelinc/citrus-ui/src/styles/core';
30
+ @import '@propelinc/citrus-ui/src/styles/utils/typography';
31
+
32
+ .c-section-header {
33
+ align-items: center;
34
+ display: flex;
35
+ gap: 12px;
36
+ height: 48px;
37
+ justify-content: space-between;
38
+ }
39
+
40
+ .c-section-header__title {
41
+ @include headline;
42
+ @include text-overflow-ellipsis;
43
+
44
+ flex: 1 1 auto;
45
+ }
46
+
47
+ .c-card + .c-section-header {
48
+ margin-top: 16px;
49
+ }
50
+ </style>
@@ -1,90 +1,239 @@
1
1
  <template>
2
- <form-field :data-test="dataTest" :field-id="id" :disabled="disabled" :hide-label="hideLabel">
3
- <template #label>
4
- {{ label }}
5
- <slot name="label" />
6
- </template>
7
-
8
- <select-input
9
- :id="id"
10
- v-bind="$attrs"
11
- :data-test="`${dataTest}-select`"
12
- class="select__field"
13
- :class="{ 'select__field--disabled': disabled }"
14
- :aria-label="hideLabel ? label : undefined"
15
- solo
16
- flat
17
- :placeholder="placeholder"
18
- :disabled="disabled"
19
- :value="value"
20
- :rules="rules"
21
- :items="items"
22
- :hide-details="hideDetails"
23
- validate-on-blur
24
- v-on="$listeners"
2
+ <div
3
+ class="c-select"
4
+ :class="{
5
+ 'c-select--disabled': disabled,
6
+ 'c-select--invalid': !isValidationValid,
7
+ }"
8
+ :data-test="dataTest"
9
+ >
10
+ <label
11
+ :for="id"
12
+ class="c-select__label"
13
+ :class="{ 'c-select__label--hidden': hideLabel }"
14
+ :data-test="`${dataTest}-label`"
25
15
  >
26
- <template #append>
27
- <font-awesome-icon
28
- v-if="loading"
29
- :data-test="`${dataTest}-icon-loading`"
30
- class="fa-spin select__field__icon"
31
- :icon="faSpinner"
32
- />
33
- <font-awesome-icon
34
- v-else
35
- :data-test="`${dataTest}-icon-dropdown`"
36
- class="select__field__icon"
37
- :icon="faChevronDown"
38
- />
39
- </template>
40
- </select-input>
41
- </form-field>
16
+ <slot name="label">{{ label }}</slot>
17
+ </label>
18
+ <div class="c-select__input-container">
19
+ <select
20
+ :id="id"
21
+ ref="select"
22
+ class="c-select__input"
23
+ :class="{
24
+ 'c-select__input--has-value': inputValue && !disabled,
25
+ 'c-select__input--invalid': !isValidationValid,
26
+ 'c-select__input--loading': loading,
27
+ 'c-select__input--disabled': disabled,
28
+ }"
29
+ :aria-label="ariaLabel || label"
30
+ :data-test="`${dataTest}-select`"
31
+ :value="inputValue"
32
+ :disabled="disabled"
33
+ :required="required"
34
+ @input="onInput"
35
+ @focus="$emit('focus', $event)"
36
+ @blur="$emit('blur', $event)"
37
+ @keydown="$emit('keydown', $event)"
38
+ v-on="validationListeners"
39
+ >
40
+ <option v-if="placeholder" value disabled selected>{{ placeholder }}</option>
41
+ <option
42
+ v-for="item in items"
43
+ :key="item.value"
44
+ :value="item.value"
45
+ :disabled="item.disabled"
46
+ data-test="option"
47
+ >
48
+ {{ item.label }}
49
+ </option>
50
+ </select>
51
+ <CLoader v-if="loading" small class="c-select__icon" data-test="select-icon-loading" />
52
+ <FontAwesomeIcon v-else class="c-select__icon" :icon="faChevronDown" />
53
+ </div>
54
+ <CValidationMessage
55
+ class="c-select__message"
56
+ :data-test="`${dataTest}-message`"
57
+ :validation-message="validationMessage"
58
+ :hide="hideDetails"
59
+ >
60
+ <slot name="message" />
61
+ </CValidationMessage>
62
+ </div>
42
63
  </template>
43
64
 
44
65
  <script lang="ts">
45
- import { faChevronDown, faSpinner } from '@fortawesome/pro-light-svg-icons';
66
+ import { faChevronDown } from '@fortawesome/pro-regular-svg-icons';
46
67
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
47
- import { Component, Vue, Prop } from 'vue-property-decorator';
68
+ import { type PropType, defineComponent, ref, toRefs } from 'vue';
48
69
 
49
- import FormField from '@/components/helpers/FormField.vue';
50
- import SelectInput from '@/components/helpers/SelectInput.vue';
70
+ import CLoader from '@propelinc/citrus-ui/src/components/CLoader.vue';
71
+ import CValidationMessage from '@propelinc/citrus-ui/src/components/CValidationMessage.vue';
72
+ import { useInternalValue } from '@propelinc/citrus-ui/src/composables/binding';
73
+ import { useId } from '@propelinc/citrus-ui/src/composables/id';
74
+ import { useValidations } from '@propelinc/citrus-ui/src/composables/validations';
51
75
 
52
- // @ts-ignore
53
- @Component({
76
+ export default defineComponent({
54
77
  name: 'CSelect',
55
- inheritAttrs: false,
56
- components: { FormField, SelectInput, FontAwesomeIcon },
57
- })
58
- export default class CSelect extends Vue {
59
- faChevronDown = faChevronDown;
60
- faSpinner = faSpinner;
61
-
62
- @Prop(String) label?: string;
63
- @Prop(String) placeholder?: string;
64
- @Prop({ type: String, required: true }) id!: string;
65
- /** List of options like `{ label: 'Yes', value: 'yes' }` */
66
- @Prop({ type: Array, default: () => [] }) items!: { label: string; value: string }[];
67
- @Prop({ type: Boolean, default: false }) disabled!: boolean;
68
- @Prop({ type: String, default: '' }) value!: string;
69
- /** Prefix for test selectors */
70
- @Prop({ type: String, default: 'select-field' }) dataTest!: string;
71
- /** Hides the label and instead labels the field with `aria-label` */
72
- @Prop({ type: Boolean, default: false }) hideLabel!: boolean;
73
- /** Hides the validation message area. Defaults to `false` (show message area even when valid), so validations transition in gracefully. */
74
- @Prop({ type: [Boolean, String], default: false }) hideDetails!: boolean | 'auto';
75
- @Prop({ type: Boolean, default: false }) loading!: boolean;
76
- @Prop({ type: Array, default: () => [] }) rules!: ((value: string) => string | boolean)[];
77
- }
78
+ components: { CLoader, CValidationMessage, FontAwesomeIcon },
79
+ props: {
80
+ /** The select's label, both visual and screenreader-only */
81
+ label: { type: String, default: undefined },
82
+ /** Overrides label for screenreader-only */
83
+ ariaLabel: { type: String, default: undefined },
84
+ /** Set the select's placeholder text */
85
+ placeholder: { type: String, default: undefined },
86
+ /** Assigns the select input's id */
87
+ id: { type: String, default: undefined },
88
+ /** List of options like `{ label: 'Yes', value: 'yes' }` */
89
+ items: {
90
+ type: Array as PropType<{ label: string; value: string; disabled?: boolean }[]>,
91
+ default: () => [],
92
+ },
93
+ /** Controls whether the select is disabled */
94
+ disabled: { type: Boolean, default: false },
95
+ /** Controls the value of the select */
96
+ value: { type: String, default: '' },
97
+ /** Prefix for test selectors */
98
+ dataTest: { type: String, default: 'select' },
99
+ /** Hides the label and instead labels the field with `aria-label` */
100
+ hideLabel: { type: Boolean, default: false },
101
+ /**
102
+ * Hides the validation message area. Defaults to `false` (show message area even
103
+ * when valid), so validations transition in gracefully.
104
+ *
105
+ * If set to 'auto', the validation message area will only display if there is a message.
106
+ */
107
+ hideDetails: { type: [Boolean, String] as PropType<boolean | 'auto'>, default: false },
108
+ /** Controls whether the select is loading */
109
+ loading: { type: Boolean, default: false },
110
+ /**
111
+ * An array of functions that either return either true / false or a string
112
+ * containing an error message. The component passes the input value as an
113
+ * argument. The input field will enter an error state if a function does
114
+ * not return true.
115
+ * */
116
+ rules: { type: Array as PropType<((value: string) => string | boolean)[]>, default: () => [] },
117
+ /** If true, the select will be required */
118
+ required: { type: Boolean, default: false },
119
+ },
120
+ emits: ['input', 'focus', 'blur', 'keydown'],
121
+ setup(props, { emit, expose }) {
122
+ const { id, value, rules, required } = toRefs(props);
123
+ const idWithFallback = useId(id);
124
+ const inputValue = useInternalValue(value, {
125
+ onChange: (newValue) => emit('input', newValue),
126
+ });
127
+ const select = ref<HTMLSelectElement | null>(null);
128
+ const {
129
+ message: validationMessage,
130
+ valid: isValidationValid,
131
+ listeners: validationListeners,
132
+ startValidating,
133
+ clearValidations,
134
+ } = useValidations({
135
+ id: idWithFallback,
136
+ field: select,
137
+ value: inputValue,
138
+ rules,
139
+ required,
140
+ validateOn: 'blur',
141
+ });
142
+
143
+ function onInput(event: Event): void {
144
+ const target = event.target as HTMLSelectElement;
145
+ inputValue.value = target.value;
146
+ }
147
+
148
+ expose({ startValidating, clearValidations });
149
+
150
+ return {
151
+ inputValue,
152
+ validationListeners,
153
+ validationMessage,
154
+ isValidationValid,
155
+ select,
156
+ faChevronDown,
157
+
158
+ onInput,
159
+ };
160
+ },
161
+ });
78
162
  </script>
79
163
 
80
- <style lang="scss" scoped>
81
- @import '@/styles/form-fields.scss';
164
+ <style scoped lang="scss">
165
+ @import '@propelinc/citrus-ui/src/styles/core';
166
+ @import '@propelinc/citrus-ui/src/styles/form-fields';
167
+
168
+ .c-select {
169
+ display: flex;
170
+ flex-direction: column;
171
+
172
+ &--disabled {
173
+ color: $color-text-disabled;
174
+ }
175
+ }
176
+
177
+ .c-select__label {
178
+ @include body-emphasized;
179
+
180
+ margin-bottom: 8px;
181
+ transition: color $sl-field-transition-duration ease;
182
+
183
+ &--hidden {
184
+ @include sr-only;
185
+ }
186
+ }
187
+
188
+ .c-select__input-container {
189
+ align-items: center;
190
+ display: flex;
191
+ position: relative;
192
+ }
193
+
194
+ .c-select__icon {
195
+ pointer-events: none;
196
+ position: absolute;
197
+ right: 16px;
198
+ }
199
+
200
+ .c-select__input {
201
+ appearance: none;
202
+ background-color: $color-white;
203
+ border: $border-width solid $color-border;
204
+ border-radius: $border-radius-next;
205
+ color: $color-placeholder-text;
206
+ cursor: pointer;
207
+ flex-grow: 1;
208
+ letter-spacing: $letter-spacing-extend-small;
209
+ max-width: 100%;
210
+ min-height: $button-size-large;
211
+ outline: 0.5px solid transparent;
212
+ padding: 0 36px 0 16px;
213
+ text-overflow: ellipsis;
214
+ transition:
215
+ border-color ease 0.2s,
216
+ outline-color ease 0.2s;
217
+
218
+ &:focus {
219
+ border-color: $color-black;
220
+ }
221
+
222
+ &--has-value {
223
+ color: $color-black;
224
+ }
225
+
226
+ &--invalid {
227
+ border-color: $color-black;
228
+ outline-color: $color-black;
229
+ }
82
230
 
83
- .select__field {
84
- @include form-field;
231
+ &[disabled] {
232
+ background-color: $color-gray-100;
233
+ }
85
234
  }
86
235
 
87
- .select__field--disabled {
88
- @include form-field-disabled;
236
+ .c-select__message {
237
+ margin-top: 4px;
89
238
  }
90
239
  </style>
@@ -0,0 +1,65 @@
1
+ <!--
2
+ This Skeleton component is the foundation for all of our skeleton loader components.
3
+
4
+ In most cases, you will use a more specific version of this component, such as
5
+ CSkeletonLoaderCard, CSkeletonLoaderText, CSkeletonLoaderCircle, etc.
6
+
7
+ However, you can create custom skeleton loaders ad-hoc through composition. For example, a custom
8
+ loader text component could be created like this:
9
+
10
+ ```vue
11
+ <div v-for="x in 3" :key="x">
12
+ <div class="d-flex w-full" style="font-size: 42px; line-height: 130%;">
13
+ <div style="height: 16px;">
14
+ <CSkeleton />
15
+ </div>
16
+ <span>&nbsp;</span>
17
+ </div>
18
+ </div>
19
+ ```
20
+ -->
21
+
22
+ <template>
23
+ <div class="c-skeleton" data-test="skeleton">
24
+ <div class="c-skeleton__indicator" />
25
+ </div>
26
+ </template>
27
+
28
+ <style lang="scss" scoped>
29
+ @import '@propelinc/citrus-ui/src/styles/core';
30
+
31
+ .c-skeleton {
32
+ display: flex;
33
+ height: 100%;
34
+ min-height: 1rem;
35
+ position: relative;
36
+ width: 100%;
37
+ }
38
+
39
+ .c-skeleton__indicator {
40
+ --color: #{$color-gray-100};
41
+ --sheen-color: #{$color-gray-200};
42
+
43
+ animation: sheen 8s ease-in-out infinite;
44
+ background: linear-gradient(
45
+ 270deg,
46
+ var(--sheen-color),
47
+ var(--color),
48
+ var(--color),
49
+ var(--sheen-color)
50
+ );
51
+ background-size: 400% 100%;
52
+ border-radius: $border-radius-next;
53
+ flex: 1 1 auto;
54
+ }
55
+
56
+ @keyframes sheen {
57
+ 0% {
58
+ background-position: 200% 0;
59
+ }
60
+
61
+ 100% {
62
+ background-position: -200% 0;
63
+ }
64
+ }
65
+ </style>