@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,125 @@
1
+ <template>
2
+ <sl-switch
3
+ class="c-switch"
4
+ :class="{
5
+ 'c-switch--label-first': labelFirst,
6
+ 'c-switch--disabled': disabled,
7
+ 'c-switch--checked': internalValue,
8
+ 'c-switch--aria-labelled': ariaLabel,
9
+ }"
10
+ :checked="internalValue || undefined"
11
+ :disabled="disabled || undefined"
12
+ @sl-change="internalValue = !internalValue"
13
+ >
14
+ <slot />
15
+ <span v-if="ariaLabel" class="c-switch__sr-label">
16
+ {{ ariaLabel }}
17
+ </span>
18
+ </sl-switch>
19
+ </template>
20
+
21
+ <script lang="ts">
22
+ import '@shoelace-style/shoelace/dist/components/switch/switch.js';
23
+ import { defineComponent, toRefs } from 'vue';
24
+
25
+ import { useInternalValue } from '@propelinc/citrus-ui/src/composables/binding';
26
+
27
+ export default defineComponent({
28
+ props: {
29
+ /** When true, the slot label is visually rendered before the control (label left, switch right) */
30
+ labelFirst: { type: Boolean, default: false },
31
+ /** Whether the switch is in an "on" or "off" state */
32
+ value: { type: Boolean, default: false },
33
+ /** Prevents the user from interacting with the switch */
34
+ disabled: { type: Boolean, default: false },
35
+ /** Label for screen-readers. This hides and overrides the normal label. */
36
+ ariaLabel: { type: String, default: '' },
37
+ },
38
+ emits: ['input'],
39
+ setup(props, { emit }) {
40
+ const { value } = toRefs(props);
41
+ const internalValue = useInternalValue(value, {
42
+ onChange: (newValue) => emit('input', newValue),
43
+ });
44
+
45
+ return {
46
+ internalValue,
47
+ };
48
+ },
49
+ });
50
+ </script>
51
+
52
+ <style lang="scss" scoped>
53
+ @import '@propelinc/citrus-ui/src/styles/core';
54
+ @import '@propelinc/citrus-ui/src/styles/utils/a11y';
55
+
56
+ @mixin switch-theme($control-color, $thumb-color, $thumb-indicator-color) {
57
+ &::part(control) {
58
+ background-color: $control-color;
59
+ }
60
+
61
+ &::part(thumb) {
62
+ background-color: $thumb-color;
63
+ }
64
+
65
+ &::part(thumb)::after {
66
+ background-color: $thumb-indicator-color;
67
+ }
68
+ }
69
+
70
+ .c-switch {
71
+ --width: 44px;
72
+ --height: 24px;
73
+ --thumb-size: 20px;
74
+
75
+ &::part(control) {
76
+ border: none;
77
+ }
78
+
79
+ &::part(thumb) {
80
+ align-items: center;
81
+ border: none;
82
+ display: flex;
83
+ justify-content: center;
84
+ }
85
+
86
+ &::part(thumb)::after {
87
+ border-radius: 1px;
88
+ content: '';
89
+ height: 8px;
90
+ transition: background-color var(--sl-transition-fast) ease-in-out;
91
+ width: 2px;
92
+ }
93
+
94
+ @include switch-theme($color-gray-400, $color-white, transparent);
95
+ }
96
+
97
+ .c-switch--label-first {
98
+ &::part(base) {
99
+ flex-direction: row-reverse;
100
+ gap: 12px;
101
+ width: 100%;
102
+ }
103
+
104
+ &::part(label) {
105
+ flex: 1;
106
+ margin: 0;
107
+ }
108
+ }
109
+
110
+ .c-switch--checked {
111
+ @include switch-theme($color-green-400, $color-white, $color-green-400);
112
+ }
113
+
114
+ .c-switch--disabled {
115
+ @include switch-theme($color-gray-300, $color-gray-200, transparent);
116
+ }
117
+
118
+ .c-switch--disabled.c-switch--checked {
119
+ @include switch-theme($color-gray-300, $color-gray-200, $color-gray-300);
120
+ }
121
+
122
+ .c-switch__sr-label {
123
+ @include sr-only;
124
+ }
125
+ </style>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <CListItem>
3
+ <CSwitch
4
+ data-test="list-item-switch"
5
+ class="c-switch-list-item__switch"
6
+ :value="value"
7
+ :disabled="disabled"
8
+ @input="$emit('input', $event)"
9
+ >
10
+ <div
11
+ class="d-flex flex-row gap-3"
12
+ :class="{
13
+ 'align-start': align === 'top',
14
+ 'align-center': align !== 'top',
15
+ }"
16
+ >
17
+ <slot name="prepend">
18
+ <CListItemIcon v-if="icon || iconSlotHasContent" :icon="icon" :icon-color="iconColor">
19
+ <template #icon>
20
+ <slot name="icon" />
21
+ </template>
22
+ </CListItemIcon>
23
+ </slot>
24
+
25
+ <CListItemContent :title="title" :label="label">
26
+ <template v-for="slotName of ['title', 'label', 'default']" #[slotName]>
27
+ <slot :name="slotName" />
28
+ </template>
29
+ </CListItemContent>
30
+ </div>
31
+ </CSwitch>
32
+ </CListItem>
33
+ </template>
34
+
35
+ <script lang="ts">
36
+ import { type PropType, defineComponent } from 'vue';
37
+
38
+ import CListItem from '@propelinc/citrus-ui/src/components/CListItem.vue';
39
+ import CListItemContent from '@propelinc/citrus-ui/src/components/CListItemContent.vue';
40
+ import CListItemIcon from '@propelinc/citrus-ui/src/components/CListItemIcon.vue';
41
+ import CSwitch from '@propelinc/citrus-ui/src/components/CSwitch.vue';
42
+ import type { FaPropType } from '@propelinc/citrus-ui/src/types/font-awesome';
43
+
44
+ import { useSlotHasContent } from '../composables/slots';
45
+
46
+ export default defineComponent({
47
+ name: 'CSwitchListItem',
48
+ components: {
49
+ CSwitch,
50
+ CListItem,
51
+ CListItemContent,
52
+ CListItemIcon,
53
+ },
54
+ props: {
55
+ /** Alignment of the content */
56
+ align: { type: String as PropType<'top' | 'center'>, default: 'center' },
57
+ /** Prevents the user from interacting with the switch */
58
+ disabled: { type: Boolean, default: false },
59
+ /** Font Awesome icon to render on the left side of the component */
60
+ icon: { type: [String, Array, Object] as FaPropType, default: null },
61
+ /** Color of the icon background */
62
+ iconColor: { type: String, default: 'gray-100' },
63
+ /** Plain body copy. Overridden by the default slot. */
64
+ label: { type: String, default: undefined },
65
+ /** Emphasized text above body text. Overridden by the default slot. */
66
+ title: { type: String, default: undefined },
67
+ /** Whether the switch is in an "on" or "off" state */
68
+ value: { type: Boolean, default: false },
69
+ },
70
+ emits: ['input'],
71
+ setup() {
72
+ const iconSlotHasContent = useSlotHasContent('icon');
73
+
74
+ return {
75
+ iconSlotHasContent,
76
+ };
77
+ },
78
+ });
79
+ </script>
80
+
81
+ <style lang="scss" scoped>
82
+ .c-switch-list-item__switch {
83
+ width: 100%;
84
+
85
+ &::part(base) {
86
+ align-items: center;
87
+ display: inline-flex;
88
+
89
+ // Using row-reverse allows us to move the slot content to the left
90
+ // and the switch to the right
91
+ flex-direction: row-reverse;
92
+ gap: 12px;
93
+
94
+ // The padding from CListItem is sufficient
95
+ padding: 0;
96
+ width: 100%;
97
+ }
98
+
99
+ &::part(label) {
100
+ align-items: center;
101
+ display: flex;
102
+ flex: 1;
103
+ gap: 12px;
104
+ justify-content: space-between;
105
+
106
+ // Removes the margin-inline-start supplied by the Shoelace styles
107
+ margin: 0;
108
+ }
109
+ }
110
+ </style>
@@ -1,61 +1,207 @@
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
- <v-textarea
9
- :id="id"
10
- v-bind="$attrs"
11
- :data-test="`${dataTest}-input`"
12
- class="text-area__input"
13
- :class="{ 'text-area__input--disabled': disabled }"
14
- :aria-label="hideLabel ? label : undefined"
15
- auto-grow
16
- solo
17
- flat
18
- :placeholder="placeholder"
2
+ <div
3
+ class="d-flex flex-column gap-1"
4
+ :class="{
5
+ 'c-text-area--disabled': disabled,
6
+ 'c-text-area--invalid': !isValidationValid,
7
+ 'c-text-area--hide-label': hideLabel,
8
+ }"
9
+ :data-test="dataTest"
10
+ >
11
+ <label class="c-text-area__label" :for="idWithFallback" :data-test="`${dataTest}-label`">
12
+ <slot name="label">
13
+ {{ label }}
14
+ </slot>
15
+ </label>
16
+
17
+ <textarea
18
+ :id="idWithFallback"
19
+ ref="textarea"
20
+ class="c-text-area__input"
21
+ rows="4"
22
+ :aria-label="label || undefined"
23
+ :aria-describedby="`${idWithFallback}-message ${idWithFallback}-validation-message`"
24
+ :aria-invalid="isValidationValid ? 'false' : 'true'"
25
+ :data-test="`${dataTest}-textarea`"
19
26
  :disabled="disabled"
20
- :hide-details="hideDetails"
21
- :value="value"
22
- :rules="rules"
23
- validate-on-blur
24
- v-on="$listeners"
27
+ :placeholder="placeholder"
28
+ :maxlength="maxlength"
29
+ :required="required"
30
+ :value="internalValue"
31
+ @input="onInput"
32
+ @blur="$emit('blur')"
33
+ @focus="$emit('focus')"
34
+ @change="$emit('change', internalValue)"
35
+ v-on="validationListeners"
25
36
  />
26
- </form-field>
37
+
38
+ <CValidationMessage
39
+ :data-test="`${dataTest}-validation-message`"
40
+ :validation-message="validationMessage"
41
+ :hide="hideDetails"
42
+ >
43
+ <template #append>
44
+ <CFormFieldCounter
45
+ v-if="counter"
46
+ :data-test="`${dataTest}-counter`"
47
+ :counter="counter"
48
+ :counter-value="counterValue"
49
+ :value="internalValue"
50
+ />
51
+ </template>
52
+ </CValidationMessage>
53
+
54
+ <div
55
+ v-if="messageSlotHasContent"
56
+ :id="`${idWithFallback}-message`"
57
+ class="c-text-area__message"
58
+ :data-test="`${dataTest}-message`"
59
+ >
60
+ <slot name="message" />
61
+ </div>
62
+ </div>
27
63
  </template>
28
64
 
29
65
  <script lang="ts">
30
- import { Component, Vue, Prop } from 'vue-property-decorator';
31
-
32
- import FormField from '@/components/helpers/FormField.vue';
33
-
34
- @Component({ name: 'CTextArea', inheritAttrs: false, components: { FormField } })
35
- export default class CTextArea extends Vue {
36
- @Prop(String) label?: string;
37
- @Prop(String) placeholder?: string;
38
- @Prop({ type: String, required: true }) id!: string;
39
- @Prop({ type: Boolean, default: false }) disabled!: boolean;
40
- @Prop({ type: String, default: '' }) value!: string;
41
- /** Hides the label and instead labels the field with `aria-label` */
42
- @Prop({ type: Boolean, default: false }) hideLabel!: boolean;
43
- /** Hides the validation message area. Defaults to `false` (show message area even when valid), so validations transition in gracefully. */
44
- @Prop({ type: [Boolean, String], default: false }) hideDetails!: boolean | 'auto';
45
- @Prop({ type: String, default: 'text-area' }) dataTest!: string;
46
- @Prop({ type: Array, default: () => [] }) rules!: ((value: string) => string | boolean)[];
47
- }
66
+ import type { PropType } from 'vue';
67
+ import { defineComponent, ref, toRefs } from 'vue';
68
+
69
+ import CFormFieldCounter from '@propelinc/citrus-ui/src/components/CFormFieldCounter.vue';
70
+ import CValidationMessage from '@propelinc/citrus-ui/src/components/CValidationMessage.vue';
71
+ import { useInternalValue } from '@propelinc/citrus-ui/src/composables/binding';
72
+ import { useId } from '@propelinc/citrus-ui/src/composables/id';
73
+ import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
74
+ import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
75
+ import { useValidations } from '@propelinc/citrus-ui/src/composables/validations';
76
+
77
+ export default defineComponent({
78
+ name: 'CTextArea',
79
+ components: { CValidationMessage, CFormFieldCounter },
80
+ props: {
81
+ /** The textarea's label, both visual and screenreader-only */
82
+ label: { type: String as PropType<string | null>, default: null },
83
+ /** The textarea's placeholder */
84
+ placeholder: { type: String, default: '' },
85
+ /** The textarea element's id */
86
+ id: { type: String as PropType<string | null>, default: null },
87
+ /** Controls whether the input is disabled */
88
+ disabled: { type: Boolean, default: false },
89
+ /** The textarea's value */
90
+ value: { type: String, default: '' },
91
+ /** Hides the label and instead labels the field with `aria-label` */
92
+ hideLabel: { type: Boolean, default: false },
93
+ /** Hides the validation message area. Defaults to `false` (show message area even when valid), so validations transition in gracefully. */
94
+ hideDetails: { type: [Boolean, String] as PropType<boolean | 'auto'>, default: false },
95
+ /** Adds a custom data test string to the form field and textarea elements */
96
+ dataTest: { type: String, default: 'text-area' },
97
+ /** Shows a character counter and sets its denominator. */
98
+ counter: { type: Number as PropType<number | null>, default: null },
99
+ /** Function or number that determines the numerator of the counter. If not
100
+ * set, the counter will be the length of the input value. */
101
+ counterValue: {
102
+ type: [Number, Function] as PropType<number | (() => number | null)>,
103
+ default: null,
104
+ },
105
+ maxlength: { type: Number, default: undefined },
106
+ /** Accepts a mixed array of types function, boolean and string.
107
+ * Functions pass an input value as an argument and must return either true / false or
108
+ * a string containing an error message. The input field will enter an error state if a
109
+ * function returns (or any value in the array contains) false or is a string */
110
+ rules: { type: Array as PropType<Rules<string>>, default: () => [] },
111
+ /** If true, the field is required */
112
+ required: { type: Boolean, default: false },
113
+ },
114
+ emits: ['input', 'change', 'blur', 'focus'],
115
+ setup(props, { emit }) {
116
+ const { value, rules, required, id } = toRefs(props);
117
+ const idWithFallback = useId(id);
118
+
119
+ const internalValue = useInternalValue(value, {
120
+ onChange: (value) => emit('input', value),
121
+ });
122
+
123
+ const messageSlotHasContent = useSlotHasContent('message');
124
+
125
+ const textarea = ref<HTMLTextAreaElement | null>(null);
126
+
127
+ const {
128
+ message: validationMessage,
129
+ valid: isValidationValid,
130
+ listeners: validationListeners,
131
+ } = useValidations({
132
+ id: idWithFallback,
133
+ value: internalValue,
134
+ rules,
135
+ required,
136
+ field: textarea,
137
+ });
138
+
139
+ const onInput = (event: Event): void => {
140
+ const target = event.target as HTMLTextAreaElement;
141
+ internalValue.value = target.value;
142
+ };
143
+
144
+ return {
145
+ textarea,
146
+ idWithFallback,
147
+ internalValue,
148
+ validationMessage,
149
+ isValidationValid,
150
+ validationListeners,
151
+ messageSlotHasContent,
152
+
153
+ onInput,
154
+ };
155
+ },
156
+ });
48
157
  </script>
49
158
 
50
159
  <style lang="scss" scoped>
51
- @import '@/styles/core.scss';
52
- @import '@/styles/form-fields.scss';
160
+ @import '@propelinc/citrus-ui/src/styles/core';
161
+ @import '@propelinc/citrus-ui/src/styles/utils/a11y';
162
+ @import '@propelinc/citrus-ui/src/styles/form-fields';
163
+
164
+ .c-text-area__label {
165
+ @include body-emphasized;
166
+
167
+ display: inline-block;
168
+ margin-bottom: 4px;
169
+ transition: color $citrus-field-transition-duration ease;
170
+
171
+ .c-text-area--disabled & {
172
+ color: $color-text-disabled;
173
+ }
53
174
 
54
- .text-area__input {
55
- @include form-field;
175
+ .c-text-area--hide-label & {
176
+ @include sr-only;
177
+ }
56
178
  }
57
179
 
58
- .text-area__input--disabled {
59
- @include form-field-disabled;
180
+ .c-text-area__input {
181
+ background-color: $color-white;
182
+ border: $border-width solid $color-gray-200;
183
+ border-radius: $border-radius-next;
184
+ padding: 16px;
185
+ resize: vertical;
186
+ transition: border-color $citrus-field-transition-duration ease;
187
+
188
+ &:focus,
189
+ &:focus-within,
190
+ .c-text-area--invalid & {
191
+ border-color: $color-black;
192
+ outline: none;
193
+ }
194
+
195
+ &:disabled {
196
+ background-color: $color-gray-100;
197
+ color: $color-text-disabled;
198
+ }
199
+ }
200
+
201
+ .c-text-area__message {
202
+ @include caption;
203
+
204
+ color: $color-gray-500;
205
+ margin-bottom: 16px;
60
206
  }
61
207
  </style>