@propelinc/citrus-ui 1.0.4 → 1.3.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 (202) hide show
  1. package/README.md +51 -14
  2. package/dist/citrus-ui.cdn.css +1 -0
  3. package/dist/citrus-ui.css +1 -0
  4. package/dist/colors/colors.d.ts +31 -0
  5. package/dist/colors/theme.d.ts +3 -0
  6. package/dist/colors/util-classes.d.ts +11 -0
  7. package/dist/components/CAccordion.vue.d.ts +34 -0
  8. package/dist/components/CAccordionItem.vue.d.ts +39 -0
  9. package/dist/components/CAppBar.vue.d.ts +59 -0
  10. package/dist/components/CBadge.vue.d.ts +35 -0
  11. package/dist/components/CBottomSheet.vue.d.ts +90 -0
  12. package/dist/components/CButton/CButton.vue.d.ts +97 -0
  13. package/dist/components/CButton/types.d.ts +5 -0
  14. package/dist/components/CButtonStack.vue.d.ts +27 -0
  15. package/dist/components/CCard.vue.d.ts +53 -0
  16. package/dist/components/CCardFooter.vue.d.ts +20 -0
  17. package/dist/components/CCardHeader.vue.d.ts +22 -0
  18. package/dist/components/CCardSection.vue.d.ts +26 -0
  19. package/dist/components/CCheckbox.vue.d.ts +62 -0
  20. package/dist/components/CCol.vue.d.ts +30 -0
  21. package/dist/components/CDivider.vue.d.ts +9 -0
  22. package/dist/components/CDobField.vue.d.ts +60 -0
  23. package/dist/components/CDobSelect.vue.d.ts +50 -0
  24. package/dist/components/CEmailField.vue.d.ts +48 -0
  25. package/dist/components/CExpandTransition.vue.d.ts +29 -0
  26. package/dist/components/CFadeTransition.vue.d.ts +20 -0
  27. package/dist/components/CFileInput.vue.d.ts +50 -0
  28. package/dist/components/CFixedPageFooter.vue.d.ts +153 -0
  29. package/dist/components/CForm.vue.d.ts +44 -0
  30. package/dist/components/CFormFieldCounter.vue.d.ts +15 -0
  31. package/dist/components/CIconButton.vue.d.ts +97 -0
  32. package/dist/components/CLabel.vue.d.ts +36 -0
  33. package/dist/components/CListItem.vue.d.ts +56 -0
  34. package/dist/components/CListItemContent.vue.d.ts +27 -0
  35. package/dist/components/CListItemIcon.vue.d.ts +28 -0
  36. package/dist/components/CLoader.vue.d.ts +23 -0
  37. package/dist/components/CLogo.vue.d.ts +9 -0
  38. package/dist/components/CMaskedTextField.vue.d.ts +511 -0
  39. package/dist/components/CMenu.vue.d.ts +17 -0
  40. package/dist/components/CMenuItem.vue.d.ts +37 -0
  41. package/dist/components/CMenuLabel.vue.d.ts +20 -0
  42. package/dist/components/CModal.vue.d.ts +59 -0
  43. package/dist/components/CModalLoading.vue.d.ts +36 -0
  44. package/dist/components/CNotification.vue.d.ts +64 -0
  45. package/dist/components/CPhoneField.vue.d.ts +792 -0
  46. package/dist/components/CPill.vue.d.ts +41 -0
  47. package/dist/components/CPillGroup.vue.d.ts +39 -0
  48. package/dist/components/CPopup.vue.d.ts +37 -0
  49. package/dist/components/CProgressLinear.vue.d.ts +21 -0
  50. package/dist/components/CProgressRing.vue.d.ts +48 -0
  51. package/dist/components/CRadio.vue.d.ts +40 -0
  52. package/dist/components/CRadioGroup.vue.d.ts +54 -0
  53. package/dist/components/CRebrand.vue.d.ts +28 -0
  54. package/dist/components/CRow.vue.d.ts +41 -0
  55. package/dist/components/CSafeArea.vue.d.ts +18 -0
  56. package/dist/components/CSectionHeader.vue.d.ts +29 -0
  57. package/dist/components/CSelect.vue.d.ts +96 -0
  58. package/dist/components/CSkeleton.vue.d.ts +3 -0
  59. package/dist/components/CSkeletonLoaderCard.vue.d.ts +9 -0
  60. package/dist/components/CSkeletonLoaderCircle.vue.d.ts +3 -0
  61. package/dist/components/CSkeletonLoaderText.vue.d.ts +16 -0
  62. package/dist/components/CSlideFadeTransition.vue.d.ts +36 -0
  63. package/dist/components/CSplitInput.vue.d.ts +56 -0
  64. package/dist/components/CSquaredIcon.vue.d.ts +33 -0
  65. package/dist/components/CSsnField.vue.d.ts +798 -0
  66. package/dist/components/CStatusDot.vue.d.ts +10 -0
  67. package/dist/components/CSwitch.vue.d.ts +39 -0
  68. package/dist/components/CSwitchListItem.vue.d.ts +48 -0
  69. package/dist/components/CTextArea.vue.d.ts +96 -0
  70. package/dist/components/CTextField.vue.d.ts +129 -0
  71. package/dist/components/CTextLink.vue.d.ts +36 -0
  72. package/dist/components/CThirdPartyLogo.vue.d.ts +22 -0
  73. package/dist/components/CTimeago.vue.d.ts +12 -0
  74. package/dist/components/CToast.vue.d.ts +69 -0
  75. package/dist/components/CToastsList.vue.d.ts +3 -0
  76. package/dist/components/CValidationMessage.vue.d.ts +37 -0
  77. package/dist/components/CZipcodeField.vue.d.ts +796 -0
  78. package/dist/components/index.d.ts +66 -0
  79. package/dist/components/internal/CCloseButton.vue.d.ts +14 -0
  80. package/dist/composables/accessibility.d.ts +1 -0
  81. package/dist/composables/animation.d.ts +12 -0
  82. package/dist/composables/binding.d.ts +19 -0
  83. package/dist/composables/colors.d.ts +13 -0
  84. package/dist/composables/elements.d.ts +3 -0
  85. package/dist/composables/fields.d.ts +10 -0
  86. package/dist/composables/gestures.d.ts +53 -0
  87. package/dist/composables/i18n.d.ts +3 -0
  88. package/dist/composables/id.d.ts +11 -0
  89. package/dist/composables/input-mask.d.ts +18 -0
  90. package/dist/composables/router.d.ts +30 -0
  91. package/dist/composables/slots.d.ts +2 -0
  92. package/dist/composables/toast.d.ts +21 -0
  93. package/dist/composables/validations.d.ts +77 -0
  94. package/dist/icons.cdn.mjs +3 -0
  95. package/dist/icons.cdn.mjs.map +1 -0
  96. package/dist/icons.d.ts +1 -0
  97. package/dist/icons.mjs +6 -0
  98. package/dist/icons.mjs.map +1 -0
  99. package/dist/index.cdn.mjs +9328 -12875
  100. package/dist/index.cdn.mjs.map +1 -1
  101. package/dist/index.cdn2.mjs +55255 -0
  102. package/dist/index.cdn2.mjs.map +1 -0
  103. package/dist/index.d.ts +8 -0
  104. package/dist/index.mjs +3946 -0
  105. package/dist/index.mjs.map +1 -0
  106. package/dist/plugin.d.ts +3 -0
  107. package/dist/services/animation.d.ts +17 -0
  108. package/dist/services/directives/index.d.ts +2 -0
  109. package/dist/services/directives/scroll-into-view.d.ts +7 -0
  110. package/dist/services/directives/tap-animation.d.ts +6 -0
  111. package/dist/services/id.d.ts +22 -0
  112. package/dist/services/injections/accordions.d.ts +3 -0
  113. package/dist/services/injections/animations.d.ts +2 -0
  114. package/dist/services/injections/buttons.d.ts +4 -0
  115. package/dist/services/injections/forms.d.ts +6 -0
  116. package/dist/services/injections/icon-buttons.d.ts +3 -0
  117. package/dist/services/injections/pills.d.ts +4 -0
  118. package/dist/services/injections/radio.d.ts +10 -0
  119. package/dist/{styles/main.css → styles.css} +40 -2
  120. package/dist/theme/icons.d.ts +36 -0
  121. package/dist/types/CForm.d.ts +12 -0
  122. package/dist/types/font-awesome.d.ts +5 -0
  123. package/dist/types.d.ts +13 -0
  124. package/package.json +11 -4
  125. package/src/colors/colors.ts +8 -3
  126. package/src/components/CAccordion.vue +31 -24
  127. package/src/components/CAccordionItem.vue +46 -45
  128. package/src/components/CAppBar.vue +108 -101
  129. package/src/components/CBadge.vue +33 -25
  130. package/src/components/CBottomSheet.vue +212 -199
  131. package/src/components/CButton/CButton.vue +135 -147
  132. package/src/components/CButtonStack.vue +21 -13
  133. package/src/components/CCard.vue +72 -69
  134. package/src/components/CCardFooter.vue +5 -5
  135. package/src/components/CCardHeader.vue +9 -7
  136. package/src/components/CCardSection.vue +15 -8
  137. package/src/components/CCheckbox.vue +68 -69
  138. package/src/components/CCol.vue +21 -22
  139. package/src/components/CDivider.vue +9 -8
  140. package/src/components/CDobField.vue +114 -105
  141. package/src/components/CDobSelect.vue +162 -164
  142. package/src/components/CEmailField.vue +39 -27
  143. package/src/components/CExpandTransition.vue +14 -17
  144. package/src/components/CFadeTransition.vue +3 -3
  145. package/src/components/CFileInput.vue +57 -50
  146. package/src/components/CFixedPageFooter.vue +23 -17
  147. package/src/components/CForm.vue +67 -60
  148. package/src/components/CFormFieldCounter.vue +25 -28
  149. package/src/components/CIconButton.vue +84 -65
  150. package/src/components/CLabel.vue +19 -13
  151. package/src/components/CListItem.vue +67 -66
  152. package/src/components/CListItemContent.vue +14 -16
  153. package/src/components/CListItemIcon.vue +18 -14
  154. package/src/components/CLoader.vue +47 -56
  155. package/src/components/CLogo.vue +13 -12
  156. package/src/components/CMaskedTextField.vue +80 -64
  157. package/src/components/CMenu.vue +14 -6
  158. package/src/components/CMenuItem.vue +28 -22
  159. package/src/components/CMenuLabel.vue +6 -5
  160. package/src/components/CModal.vue +76 -71
  161. package/src/components/CModalLoading.vue +24 -15
  162. package/src/components/CNotification.vue +77 -28
  163. package/src/components/CPhoneField.vue +34 -25
  164. package/src/components/CPill.vue +92 -88
  165. package/src/components/CPillGroup.vue +30 -21
  166. package/src/components/CPopup.vue +46 -37
  167. package/src/components/CProgressLinear.vue +17 -11
  168. package/src/components/CProgressRing.vue +33 -33
  169. package/src/components/CRadio.vue +57 -57
  170. package/src/components/CRadioGroup.vue +85 -72
  171. package/src/components/CRow.vue +22 -20
  172. package/src/components/CSectionHeader.vue +20 -12
  173. package/src/components/CSelect.vue +89 -73
  174. package/src/components/CSkeletonLoaderCard.vue +9 -15
  175. package/src/components/CSkeletonLoaderCircle.vue +1 -9
  176. package/src/components/CSkeletonLoaderText.vue +17 -18
  177. package/src/components/CSlideFadeTransition.vue +12 -34
  178. package/src/components/CSplitInput.vue +46 -45
  179. package/src/components/CSquaredIcon.vue +39 -29
  180. package/src/components/CSsnField.vue +48 -36
  181. package/src/components/CStatusDot.vue +16 -16
  182. package/src/components/CSwitch.vue +31 -22
  183. package/src/components/CSwitchListItem.vue +27 -28
  184. package/src/components/CTextArea.vue +116 -83
  185. package/src/components/CTextField.vue +194 -198
  186. package/src/components/CTextLink.vue +28 -25
  187. package/src/components/CThirdPartyLogo.vue +30 -59
  188. package/src/components/CToast.vue +135 -132
  189. package/src/components/CToastsList.vue +2 -15
  190. package/src/components/CValidationMessage.vue +31 -24
  191. package/src/components/CZipcodeField.vue +40 -27
  192. package/src/composables/elements.ts +1 -1
  193. package/src/composables/fields.ts +4 -4
  194. package/src/composables/router.ts +6 -5
  195. package/src/icons.ts +6 -0
  196. package/src/services/injections/buttons.ts +1 -1
  197. package/src/styles/_core.scss +1 -2
  198. package/src/styles/_reset.scss +1 -1
  199. package/src/styles/main.scss +2 -0
  200. package/src/types.ts +2 -0
  201. package/dist/index.cdn.css +0 -1
  202. package/dist/styles/utils.css +0 -2709
@@ -62,10 +62,11 @@
62
62
  </div>
63
63
  </template>
64
64
 
65
- <script lang="ts">
65
+ <script setup lang="ts">
66
66
  import { faChevronDown } from '@fortawesome/pro-regular-svg-icons';
67
67
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
68
- import { type PropType, defineComponent, ref, toRefs } from 'vue';
68
+ import type { VNode } from 'vue';
69
+ import { ref, toRefs } from 'vue';
69
70
 
70
71
  import CLoader from '@propelinc/citrus-ui/src/components/CLoader.vue';
71
72
  import CValidationMessage from '@propelinc/citrus-ui/src/components/CValidationMessage.vue';
@@ -73,92 +74,107 @@ import { useInternalValue } from '@propelinc/citrus-ui/src/composables/binding';
73
74
  import { useId } from '@propelinc/citrus-ui/src/composables/id';
74
75
  import { useValidations } from '@propelinc/citrus-ui/src/composables/validations';
75
76
 
76
- export default defineComponent({
77
- name: 'CSelect',
78
- components: { CLoader, CValidationMessage, FontAwesomeIcon },
79
- props: {
80
- /** The select's label, both visual and screenreader-only */
81
- label: { type: String, default: undefined },
77
+ interface SelectItem {
78
+ label: string;
79
+ value: string;
80
+ disabled?: boolean;
81
+ }
82
+
83
+ const props = withDefaults(
84
+ defineProps<{
82
85
  /** 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: '' },
86
+ ariaLabel?: string;
97
87
  /** 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 },
88
+ dataTest?: string;
89
+ /** Controls whether the select is disabled */
90
+ disabled?: boolean;
101
91
  /**
102
92
  * Hides the validation message area. Defaults to `false` (show message area even
103
93
  * when valid), so validations transition in gracefully.
104
94
  *
105
95
  * If set to 'auto', the validation message area will only display if there is a message.
106
96
  */
107
- hideDetails: { type: [Boolean, String] as PropType<boolean | 'auto'>, default: false },
97
+ hideDetails?: boolean | 'auto';
98
+ /** Hides the label and instead labels the field with `aria-label` */
99
+ hideLabel?: boolean;
100
+ /** Assigns the select input's id */
101
+ id?: string;
102
+ /** List of options like `{ label: 'Yes', value: 'yes' }` */
103
+ items?: SelectItem[];
104
+ /** The select's label, both visual and screenreader-only */
105
+ label?: string;
108
106
  /** Controls whether the select is loading */
109
- loading: { type: Boolean, default: false },
107
+ loading?: boolean;
108
+ /** Set the select's placeholder text */
109
+ placeholder?: string;
110
+ /** If true, the select will be required */
111
+ required?: boolean;
110
112
  /**
111
113
  * An array of functions that either return either true / false or a string
112
114
  * containing an error message. The component passes the input value as an
113
115
  * argument. The input field will enter an error state if a function does
114
116
  * 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
- },
117
+ */
118
+ rules?: ((value: string) => string | boolean)[];
119
+ /** Controls the value of the select */
120
+ value?: string;
121
+ }>(),
122
+ {
123
+ ariaLabel: undefined,
124
+ dataTest: 'select',
125
+ disabled: false,
126
+ hideDetails: false,
127
+ hideLabel: false,
128
+ id: undefined,
129
+ items: () => [],
130
+ label: undefined,
131
+ loading: false,
132
+ placeholder: undefined,
133
+ required: false,
134
+ rules: () => [],
135
+ value: '',
136
+ }
137
+ );
138
+
139
+ const emit = defineEmits<{
140
+ (e: 'input', value: string): void;
141
+ (e: 'focus', event: FocusEvent): void;
142
+ (e: 'blur', event: FocusEvent): void;
143
+ (e: 'keydown', event: KeyboardEvent): void;
144
+ }>();
145
+
146
+ defineSlots<{
147
+ label?: () => VNode[];
148
+ message?: () => VNode[];
149
+ }>();
150
+
151
+ const { id, value, rules, required } = toRefs(props);
152
+ const idWithFallback = useId(id);
153
+ const inputValue = useInternalValue(value, {
154
+ onChange: (newValue) => emit('input', newValue),
155
+ });
156
+ const select = ref<HTMLSelectElement | null>(null);
157
+ const {
158
+ message: validationMessage,
159
+ valid: isValidationValid,
160
+ listeners: validationListeners,
161
+ startValidating,
162
+ clearValidations,
163
+ } = useValidations({
164
+ id: idWithFallback,
165
+ field: select,
166
+ value: inputValue,
167
+ rules,
168
+ required,
169
+ validateOn: 'blur',
161
170
  });
171
+
172
+ function onInput(event: Event): void {
173
+ const target = event.target as HTMLSelectElement;
174
+ inputValue.value = target.value;
175
+ }
176
+
177
+ defineExpose({ startValidating, clearValidations });
162
178
  </script>
163
179
 
164
180
  <style scoped lang="scss">
@@ -8,22 +8,16 @@
8
8
  </div>
9
9
  </template>
10
10
 
11
- <script lang="ts">
12
- import { defineComponent } from 'vue';
13
-
11
+ <script setup lang="ts">
14
12
  import CSkeleton from '@propelinc/citrus-ui/src/components/CSkeleton.vue';
15
13
 
16
- export default defineComponent({
17
- components: {
18
- CSkeleton,
19
- },
20
- props: {
14
+ withDefaults(
15
+ defineProps<{
21
16
  /** Controls the height of the skeleton loader card */
22
- height: {
23
- type: [Number, String],
24
- required: false,
25
- default: 100,
26
- },
27
- },
28
- });
17
+ height?: number | string;
18
+ }>(),
19
+ {
20
+ height: 100,
21
+ }
22
+ );
29
23
  </script>
@@ -4,16 +4,8 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
- <script lang="ts">
8
- import { defineComponent } from 'vue';
9
-
7
+ <script setup lang="ts">
10
8
  import CSkeleton from '@propelinc/citrus-ui/src/components/CSkeleton.vue';
11
-
12
- export default defineComponent({
13
- components: {
14
- CSkeleton,
15
- },
16
- });
17
9
  </script>
18
10
 
19
11
  <style scoped>
@@ -18,8 +18,8 @@
18
18
  </div>
19
19
  </template>
20
20
 
21
- <script lang="ts">
22
- import { type PropType, computed, defineComponent } from 'vue';
21
+ <script setup lang="ts">
22
+ import { computed } from 'vue';
23
23
 
24
24
  import CSkeleton from '@propelinc/citrus-ui/src/components/CSkeleton.vue';
25
25
 
@@ -52,25 +52,24 @@ const LINE_TYPE_TO_CLASS: Record<SkeletonLoaderType, string> = {
52
52
  'x-large-headline': 'c-skeleton-loader-text__line--x-large-headline',
53
53
  };
54
54
 
55
- export default defineComponent({
56
- components: {
57
- CSkeleton,
58
- },
59
- props: {
55
+ const props = withDefaults(
56
+ defineProps<{
60
57
  /** Applies the align-items css property. */
61
- align: { type: String as PropType<'center' | 'start' | 'end'>, default: 'start' },
58
+ align?: 'center' | 'start' | 'end';
62
59
  /** Controls how many rows of loading text are shown */
63
- rows: { type: Number, default: 2 },
60
+ rows?: number;
64
61
  /** Controls the appearance of the loading text */
65
- type: { type: String as PropType<SkeletonLoaderType>, default: 'body' },
66
- },
67
- setup(props) {
68
- const lineTypeClass = computed(() => {
69
- return LINE_TYPE_TO_CLASS[props.type];
70
- });
71
-
72
- return { lineTypeClass };
73
- },
62
+ type?: SkeletonLoaderType;
63
+ }>(),
64
+ {
65
+ align: 'start',
66
+ rows: 2,
67
+ type: 'body',
68
+ }
69
+ );
70
+
71
+ const lineTypeClass = computed(() => {
72
+ return LINE_TYPE_TO_CLASS[props.type];
74
73
  });
75
74
  </script>
76
75
 
@@ -6,50 +6,28 @@
6
6
  </div>
7
7
  </template>
8
8
 
9
- <script lang="ts">
10
- import { type PropType, defineComponent } from 'vue';
9
+ <script setup lang="ts">
10
+ import type { VNode } from 'vue';
11
11
 
12
12
  type Direction = 'to-left' | 'to-right' | 'to-top' | 'to-bottom';
13
13
 
14
- /**
15
- * This component can be used to create a slide-fade transition for children.
16
- *
17
- * FIXME: Vue 3 Conversion - Remove this comment when Vue 3 conversion is complete.
18
- * NOTE: For Vue 2 usage: if you are conditionally rendering children, be sure to add unique
19
- * keys to each child!
20
- *
21
- * Example:
22
- * ```vue
23
- * <CSlideFadeTransition>
24
- * <div v-if="condition" :key="if">This will slide in</div>
25
- * <div v-else :key="else">This will slide out</div>
26
- * </CSlideFadeTransition>
27
- * ```
28
- */
29
- export default defineComponent({
30
- name: 'CSlideFadeTransition',
31
- props: {
14
+ defineSlots<{ default: () => VNode[] }>();
15
+
16
+ withDefaults(
17
+ defineProps<{
32
18
  /**
33
- * The amount of pixels to slide the elements in or out
19
+ * The amount of pixels to slide the elements in or out. Should be >= 0
34
20
  * @default 20
35
21
  */
36
- amount: {
37
- type: Number,
38
- default: 20,
39
- validator(value: number) {
40
- return value >= 0;
41
- },
42
- },
22
+ amount?: number;
43
23
  /**
44
24
  * Changes the direction of the slide fade transition
45
25
  * @default 'to-left'
46
26
  */
47
- direction: {
48
- type: String as PropType<Direction>,
49
- default: 'to-left',
50
- },
51
- },
52
- });
27
+ direction?: Direction;
28
+ }>(),
29
+ { amount: 20, direction: 'to-left' }
30
+ );
53
31
  </script>
54
32
 
55
33
  <style scoped>
@@ -25,64 +25,65 @@
25
25
  </CMaskedTextField>
26
26
  </template>
27
27
 
28
- <script lang="ts">
29
- import type { HTMLAttributes, PropType } from 'vue';
30
- import { computed, defineComponent, ref, toRefs } from 'vue';
28
+ <script setup lang="ts">
29
+ import type { HTMLAttributes, VNode } from 'vue';
30
+ import { computed, ref } from 'vue';
31
31
 
32
32
  import CMaskedTextField from '@propelinc/citrus-ui/src/components/CMaskedTextField.vue';
33
33
  import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
34
34
  import type { SplitInputField } from '@propelinc/citrus-ui/src/types';
35
35
 
36
- export default defineComponent({
37
- name: 'CSplitInput',
38
- components: { CMaskedTextField },
39
- props: {
36
+ const props = withDefaults(
37
+ defineProps<{
38
+ /** Controls the underlying input's autocomplete attribute */
39
+ autocomplete?: string;
40
40
  /** Custom data-test selector */
41
- dataTest: { type: String, default: 'split-input' },
42
- /** The input's type, either text or tel */
43
- type: { type: String as PropType<'text' | 'tel'>, default: 'text' },
41
+ dataTest?: string;
42
+ /** Controls whether the input is disabled */
43
+ disabled?: boolean;
44
+ /** The fields for each of the split inputs of type SplitInputField */
45
+ fields: SplitInputField[];
46
+ /** A hint to show the appropriate virtual keyboard, e.g. "numeric". */
47
+ inputmode?: HTMLAttributes['inputmode'];
44
48
  /** The input's label */
45
- label: { type: String as PropType<string | null>, default: null },
49
+ label?: string | null;
46
50
  /** The input's name */
47
- name: { type: String as PropType<string | undefined>, default: undefined },
48
- /** A hint to show the appropriate virtual keyboard, e.g. "numeric". */
49
- inputmode: {
50
- type: String as PropType<HTMLAttributes['inputmode'] | undefined>,
51
- default: undefined,
52
- },
53
- /** The input's value */
54
- value: { type: String, default: '' },
55
- /** The fields for each of the split inputs of type SplitInputField */
56
- fields: {
57
- type: Array as PropType<SplitInputField[]>,
58
- required: true,
59
- },
51
+ name?: string;
60
52
  /** Validation rules */
61
- rules: { type: Array as PropType<Rules<string>>, default: () => [] },
62
- /** Controls whether the input is disabled */
63
- disabled: { type: Boolean, default: false },
64
- /** Controls the underlying input's autocomplete attribute */
65
- autocomplete: { type: String, default: undefined },
66
- },
67
- setup(props) {
68
- const { fields } = toRefs(props);
53
+ rules?: Rules<string>;
54
+ /** The input's type, either text or tel */
55
+ type?: 'text' | 'tel';
56
+ /** The input's value */
57
+ value?: string;
58
+ }>(),
59
+ {
60
+ autocomplete: undefined,
61
+ dataTest: 'split-input',
62
+ disabled: false,
63
+ inputmode: undefined,
64
+ label: null,
65
+ name: undefined,
66
+ rules: () => [],
67
+ type: 'text',
68
+ value: '',
69
+ }
70
+ );
69
71
 
70
- const maskedValue = ref('');
72
+ defineSlots<{
73
+ label?: () => VNode[];
74
+ message?: () => VNode[];
75
+ }>();
71
76
 
72
- const placeholder = computed(() => {
73
- return fields.value
74
- .map((field) => `${field.placeholder ?? ''}${field.separator ?? ''}`)
75
- .join('');
76
- });
77
+ const maskedValue = ref('');
77
78
 
78
- const mask = computed(() => {
79
- return fields.value
80
- .map((field) => `${Array(field.characters).fill('*').join('')}${field.separator ?? ''}`)
81
- .join('');
82
- });
79
+ const placeholder = computed(() => {
80
+ return props.fields.map((field) => `${field.placeholder ?? ''}${field.separator ?? ''}`).join('');
81
+ });
83
82
 
84
- return { placeholder, mask, maskedValue };
85
- },
83
+ const mask = computed(() => {
84
+ return props.fields
85
+ .map((field) => `${Array(field.characters).fill('*').join('')}${field.separator ?? ''}`)
86
+ .join('');
86
87
  });
87
88
  </script>
88
89
 
@@ -13,43 +13,53 @@
13
13
  </div>
14
14
  </template>
15
15
 
16
- <script lang="ts">
17
- import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
18
- import { computed, defineComponent, onMounted } from 'vue';
16
+ <script setup lang="ts">
17
+ import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
18
+ import { FontAwesomeIcon as FontAwesomeIconComponent } from '@fortawesome/vue-fontawesome';
19
+ import type { Component, VNode } from 'vue';
20
+ import { computed, onMounted } from 'vue';
19
21
 
20
22
  import { useCssColor } from '@propelinc/citrus-ui/src/composables/colors';
21
- import type { FaIconArray, FaPropType } from '@propelinc/citrus-ui/src/types/font-awesome';
23
+ import type { FaIconArray } from '@propelinc/citrus-ui/src/types/font-awesome';
22
24
 
23
- export default defineComponent({
24
- components: { FontAwesomeIcon },
25
- props: {
26
- /** The Font Awesome icon to display */
27
- icon: { type: [String, Array, Object] as FaPropType, default: null },
25
+ // FontAwesomeIcon's prop types produce a union too complex for TypeScript to resolve
26
+ const FontAwesomeIcon = FontAwesomeIconComponent as unknown as Component;
27
+
28
+ const props = withDefaults(
29
+ defineProps<{
28
30
  /** The background color */
29
- color: { type: String, default: 'gray-100' },
31
+ color?: string;
32
+ /** The Font Awesome icon to display */
33
+ icon?: string | string[] | IconDefinition | null;
30
34
  /** Makes the icon and background larger */
31
- large: { type: Boolean, default: false },
32
- },
33
- setup(props) {
34
- onMounted(() => {
35
- const enableCheck = process.env.VUE_APP_DEBUG === 'yes' || process.env.NODE_ENV === 'test';
36
- if (enableCheck && Array.isArray(props.icon)) {
37
- const [prefix, iconName] = props.icon as FaIconArray;
38
- if (prefix === 'fal') {
39
- console.error(
40
- `We no longer use light Font Awesome icons. Please change ['${prefix}', '${iconName}'] to ['far', '${iconName}'].`
41
- );
42
- }
43
- }
44
- });
35
+ large?: boolean;
36
+ }>(),
37
+ {
38
+ color: 'gray-100',
39
+ icon: null,
40
+ large: false,
41
+ }
42
+ );
45
43
 
46
- const { cssColor } = useCssColor(() => props.color);
44
+ defineSlots<{
45
+ default?: () => VNode[];
46
+ }>();
47
47
 
48
- const useWhiteIcon = computed(() => props.color === 'black');
49
-
50
- return { cssColor, useWhiteIcon };
51
- },
48
+ onMounted(() => {
49
+ const enableCheck = process.env.VUE_APP_DEBUG === 'yes' || process.env.NODE_ENV === 'test';
50
+ if (enableCheck && Array.isArray(props.icon)) {
51
+ const [prefix, iconName] = props.icon as FaIconArray;
52
+ if (prefix === 'fal') {
53
+ console.error(
54
+ `We no longer use light Font Awesome icons. Please change ['${prefix}', '${iconName}'] to ['far', '${iconName}'].`
55
+ );
56
+ }
57
+ }
52
58
  });
59
+
60
+ const { cssColor } = useCssColor(() => props.color);
61
+
62
+ const useWhiteIcon = computed(() => props.color === 'black');
53
63
  </script>
54
64
 
55
65
  <style lang="scss" scoped>
@@ -34,10 +34,11 @@
34
34
  </CMaskedTextField>
35
35
  </template>
36
36
 
37
- <script lang="ts">
37
+ <script setup lang="ts">
38
38
  import { faLock } from '@fortawesome/pro-regular-svg-icons';
39
39
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
40
- import { type PropType, computed, defineComponent } from 'vue';
40
+ import type { VNode } from 'vue';
41
+ import { computed } from 'vue';
41
42
 
42
43
  import CMaskedTextField from '@propelinc/citrus-ui/src/components/CMaskedTextField.vue';
43
44
  import { useFocusableField } from '@propelinc/citrus-ui/src/composables/fields';
@@ -45,42 +46,53 @@ import { useTranslation } from '@propelinc/citrus-ui/src/composables/i18n';
45
46
  import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
46
47
  import { minLengthRule } from '@propelinc/shared-utils';
47
48
 
48
- export default defineComponent({
49
- name: 'CSsnField',
50
- components: { CMaskedTextField, FontAwesomeIcon },
51
- props: {
52
- dataTest: { type: String, default: 'ssn-field' },
53
- id: { type: String, default: undefined },
54
- label: { type: String as PropType<string | null>, default: null },
55
- rules: { type: Array as PropType<Rules<string>>, default: () => [] },
56
- value: { type: String, default: '' },
57
- fourDigitSsn: { type: Boolean, default: false },
58
- },
59
- emits: ['input', 'focus', 'blur', 'change'],
60
- setup(props, { expose }) {
61
- const { t } = useTranslation();
62
- const defaultLabel = computed(() => {
63
- return props.fourDigitSsn ? t('Last 4 digits of SSN') : t('Social Security number');
64
- });
65
- const defaultRules = computed(() => {
66
- const fourDigitRule = minLengthRule(4, t('Please enter the last four digits of your SSN'));
67
- const fullSsnRule = minLengthRule(
68
- 9,
69
- t('Please enter a valid {inputLabel}', { inputLabel: t('Social Security number') })
70
- );
71
- return [props.fourDigitSsn ? fourDigitRule : fullSsnRule];
72
- });
49
+ const props = withDefaults(
50
+ defineProps<{
51
+ dataTest?: string;
52
+ id?: string;
53
+ label?: string | null;
54
+ rules?: Rules<string>;
55
+ value?: string;
56
+ fourDigitSsn?: boolean;
57
+ }>(),
58
+ {
59
+ dataTest: 'ssn-field',
60
+ id: undefined,
61
+ label: null,
62
+ rules: (): Rules<string> => [],
63
+ value: '',
64
+ fourDigitSsn: false,
65
+ }
66
+ );
73
67
 
74
- const computedRules = computed(() => [...defaultRules.value, ...props.rules]);
68
+ defineEmits<{
69
+ input: [value: string];
70
+ focus: [event: Event];
71
+ blur: [event: Event];
72
+ change: [value: string];
73
+ }>();
75
74
 
76
- const { field } = useFocusableField(expose);
75
+ defineSlots<{
76
+ label?: () => VNode[];
77
+ message?: () => VNode[];
78
+ append?: () => VNode[];
79
+ }>();
77
80
 
78
- return {
79
- defaultLabel,
80
- computedRules,
81
- faLock,
82
- field,
83
- };
84
- },
81
+ const { t } = useTranslation();
82
+ const defaultLabel = computed(() => {
83
+ return props.fourDigitSsn ? t('Last 4 digits of SSN') : t('Social Security number');
85
84
  });
85
+ const defaultRules = computed(() => {
86
+ const fourDigitRule = minLengthRule(4, t('Please enter the last four digits of your SSN'));
87
+ const fullSsnRule = minLengthRule(
88
+ 9,
89
+ t('Please enter a valid {inputLabel}', { inputLabel: t('Social Security number') })
90
+ );
91
+ return [props.fourDigitSsn ? fourDigitRule : fullSsnRule];
92
+ });
93
+
94
+ const computedRules = computed(() => [...defaultRules.value, ...props.rules]);
95
+
96
+ const { field, focus } = useFocusableField();
97
+ defineExpose({ focus });
86
98
  </script>