@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
@@ -9,25 +9,29 @@
9
9
  </CSquaredIcon>
10
10
  </template>
11
11
 
12
- <script lang="ts">
13
- import { defineComponent } from 'vue';
12
+ <script setup lang="ts">
13
+ import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
14
+ import type { VNode } from 'vue';
14
15
 
15
16
  import CSquaredIcon from '@propelinc/citrus-ui/src/components/CSquaredIcon.vue';
16
17
  import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
17
18
 
18
- export default defineComponent({
19
- name: 'CListItemIcon',
20
- components: { CSquaredIcon },
21
- props: {
22
- icon: CSquaredIcon.props.icon,
23
- iconColor: CSquaredIcon.props.color,
24
- },
25
- setup() {
26
- const iconSlotHasContent = useSlotHasContent('icon');
19
+ withDefaults(
20
+ defineProps<{
21
+ icon?: string | string[] | IconDefinition | null;
22
+ iconColor?: string;
23
+ }>(),
24
+ {
25
+ icon: null,
26
+ iconColor: 'gray-100',
27
+ }
28
+ );
27
29
 
28
- return { iconSlotHasContent };
29
- },
30
- });
30
+ defineSlots<{
31
+ icon?: () => VNode[];
32
+ }>();
33
+
34
+ const iconSlotHasContent = useSlotHasContent('icon');
31
35
  </script>
32
36
 
33
37
  <style lang="scss" scoped>
@@ -19,10 +19,11 @@
19
19
  </span>
20
20
  </template>
21
21
 
22
- <script lang="ts">
23
- import { type PropType, computed, defineComponent } from 'vue';
22
+ <script setup lang="ts">
23
+ import { computed } from 'vue';
24
24
 
25
- import Colors, { type HexColor, isValidColor } from '@propelinc/citrus-ui/src/colors/colors';
25
+ import type { HexColor } from '@propelinc/citrus-ui/src/colors/colors';
26
+ import Colors from '@propelinc/citrus-ui/src/colors/colors';
26
27
  import { useCssColor } from '@propelinc/citrus-ui/src/composables/colors';
27
28
 
28
29
  type Size = 'sm' | 'md' | 'lg';
@@ -39,65 +40,55 @@ const SIZE_TO_TRACK_WIDTH: Record<Size, `${number}px`> = {
39
40
  lg: '3px',
40
41
  };
41
42
 
42
- export default defineComponent({
43
- props: {
43
+ const props = withDefaults(
44
+ defineProps<{
44
45
  /** Customizes screen reader only text alternative, should be translated */
45
- accessibleText: { type: String, default: undefined },
46
+ accessibleText?: string;
46
47
  /** Sets the color of the indicator of the loader */
47
- color: {
48
- type: String as PropType<HexColor | keyof typeof Colors>,
49
- default: 'default',
50
- validator: isValidColor,
51
- },
48
+ color?: HexColor | keyof typeof Colors;
52
49
  /** @deprecated Shows a smaller version of the loading icon */
53
- small: { type: Boolean, default: false },
50
+ small?: boolean;
54
51
  /** Sets the size of the loader */
55
- size: { type: String as PropType<Size>, default: 'lg' },
52
+ size?: Size;
56
53
  /** Sets the color of the track of the loader */
57
- trackColor: {
58
- type: String as PropType<HexColor | keyof typeof Colors>,
59
- default: 'default',
60
- validator: isValidColor,
61
- },
62
- },
63
- setup(props) {
64
- const computedColor = computed(() => {
65
- return props.color === 'default' ? 'black' : props.color;
66
- });
67
-
68
- const computedTrackColor = computed(() => {
69
- // If _any_ trackColor is provided, use that
70
- if (props.trackColor !== 'default') {
71
- return props.trackColor;
72
- }
73
-
74
- // trackColor is 'default', determine which default color it should use
75
- if (props.color === 'white' || props.color === Colors.WHITE) {
76
- return 'gray-500';
77
- }
78
-
79
- return 'gray-200';
80
- });
81
-
82
- const computedSize = computed((): Size => {
83
- if (props.small) {
84
- return 'sm';
85
- }
86
- return props.size;
87
- });
88
-
89
- const { cssColor: indicatorColorCode } = useCssColor(computedColor);
90
- const { cssColor: trackColorCode } = useCssColor(computedTrackColor);
91
-
92
- return {
93
- computedSize,
94
- indicatorColorCode,
95
- SIZE_TO_FONT_SIZE,
96
- SIZE_TO_TRACK_WIDTH,
97
- trackColorCode,
98
- };
99
- },
54
+ trackColor?: HexColor | keyof typeof Colors;
55
+ }>(),
56
+ {
57
+ accessibleText: undefined,
58
+ color: 'default',
59
+ small: false,
60
+ size: 'lg',
61
+ trackColor: 'default',
62
+ }
63
+ );
64
+
65
+ const computedColor = computed(() => {
66
+ return props.color === 'default' ? 'black' : props.color;
67
+ });
68
+
69
+ const computedTrackColor = computed(() => {
70
+ // If _any_ trackColor is provided, use that
71
+ if (props.trackColor !== 'default') {
72
+ return props.trackColor;
73
+ }
74
+
75
+ // trackColor is 'default', determine which default color it should use
76
+ if (props.color === 'white' || props.color === Colors.WHITE) {
77
+ return 'gray-500';
78
+ }
79
+
80
+ return 'gray-200';
81
+ });
82
+
83
+ const computedSize = computed((): Size => {
84
+ if (props.small) {
85
+ return 'sm';
86
+ }
87
+ return props.size;
100
88
  });
89
+
90
+ const { cssColor: indicatorColorCode } = useCssColor(computedColor);
91
+ const { cssColor: trackColorCode } = useCssColor(computedTrackColor);
101
92
  </script>
102
93
 
103
94
  <style lang="scss" scoped>
@@ -2,22 +2,23 @@
2
2
  <img :src="src" :alt="$t('{appName}')" />
3
3
  </template>
4
4
 
5
- <script lang="ts">
6
- import { computed, defineComponent } from 'vue';
5
+ <script setup lang="ts">
6
+ import { computed } from 'vue';
7
7
 
8
8
  import propelIcon from '@propelinc/citrus-ui/src/assets/logos/propel/icon.svg';
9
9
  import propelLockup from '@propelinc/citrus-ui/src/assets/logos/propel/lockup.svg';
10
10
 
11
- export default defineComponent({
12
- props: {
11
+ const props = withDefaults(
12
+ defineProps<{
13
13
  /** Show just the orange icon */
14
- icon: { type: Boolean, default: false },
15
- },
16
- setup(props) {
17
- const src = computed(() => {
18
- return props.icon ? propelIcon : propelLockup;
19
- });
20
- return { src };
21
- },
14
+ icon?: boolean;
15
+ }>(),
16
+ {
17
+ icon: false,
18
+ }
19
+ );
20
+
21
+ const src = computed(() => {
22
+ return props.icon ? propelIcon : propelLockup;
22
23
  });
23
24
  </script>
@@ -35,9 +35,10 @@
35
35
  </CTextField>
36
36
  </template>
37
37
 
38
- <script lang="ts">
39
- import type { MaskOptions, MaskTokens, MaskaDetail } from 'maska';
40
- import { type PropType, computed, defineComponent, ref, toRefs } from 'vue';
38
+ <script setup lang="ts">
39
+ import type { MaskInputOptions, MaskOptions, MaskTokens, MaskaDetail } from 'maska';
40
+ import type { VNode } from 'vue';
41
+ import { computed, ref, toRefs } from 'vue';
41
42
 
42
43
  import CTextField from '@propelinc/citrus-ui/src/components/CTextField.vue';
43
44
  import {
@@ -47,72 +48,87 @@ import {
47
48
  } from '@propelinc/citrus-ui/src/composables/input-mask';
48
49
  import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
49
50
 
50
- export default defineComponent({
51
- name: 'CMaskedTextField',
52
- components: { CTextField },
53
- props: {
54
- counter: { type: Number as PropType<number | null>, default: null },
55
- dataTest: { type: String, default: 'masked-text-field' },
56
- id: { type: String, default: undefined },
57
- label: { type: String as PropType<string | null>, default: null },
58
- mask: {
59
- type: [String, Array, Function] as PropType<MaskOptions['mask'] | null>,
60
- required: true,
61
- },
62
- minlength: { type: [Number, String], default: null },
63
- maxlength: { type: [Number, String], default: null },
64
- placeholder: { type: String, default: undefined },
65
- rules: { type: Array as PropType<Rules<string>>, default: () => [] },
66
- tokens: { type: Object as PropType<MaskTokens | null>, default: null },
67
- unmaskRules: { type: Boolean, default: true },
68
- value: { type: String, default: '' },
69
- },
70
- emits: ['keyup', 'keydown', 'keypress', 'input', 'focus', 'blur', 'change', 'input:masked'],
71
- setup(props, { emit, expose }) {
72
- const { minlength, maxlength, value } = toRefs(props);
51
+ const props = withDefaults(
52
+ defineProps<{
53
+ counter?: number | null;
54
+ dataTest?: string;
55
+ id?: string;
56
+ label?: string | null;
57
+ mask: MaskOptions['mask'] | null;
58
+ minlength?: number | string | null;
59
+ maxlength?: number | string | null;
60
+ placeholder?: string;
61
+ rules?: Rules<string>;
62
+ tokens?: MaskTokens | null;
63
+ unmaskRules?: boolean;
64
+ value?: string;
65
+ }>(),
66
+ {
67
+ counter: null,
68
+ dataTest: 'masked-text-field',
69
+ id: undefined,
70
+ label: null,
71
+ minlength: null,
72
+ maxlength: null,
73
+ placeholder: undefined,
74
+ rules: () => [],
75
+ tokens: null,
76
+ unmaskRules: true,
77
+ value: '',
78
+ }
79
+ );
80
+
81
+ const emit = defineEmits<{
82
+ 'keyup': [event: KeyboardEvent];
83
+ 'keydown': [event: KeyboardEvent];
84
+ 'keypress': [event: KeyboardEvent];
85
+ 'input': [value: string];
86
+ 'focus': [event: Event];
87
+ 'blur': [event: Event];
88
+ 'change': [value: string];
89
+ 'input:masked': [value: string];
90
+ }>();
73
91
 
74
- const textField = ref<typeof CTextField | null>(null);
75
- const input = computed(() => textField.value?.input);
76
- const maskOptions = computed<MaskOptions>(() => {
77
- return {
78
- mask: props.mask,
79
- tokens: {
80
- // NOTE (ej): For the EBT Card Number we accept a mask 'N' from the server
81
- // to hide all but the last 4 digits. e.g. XXXXXXXXXXXXXXX2114
82
- N: { pattern: /[0-9X]/ },
83
- ...props.tokens,
84
- },
85
- onMaska: (detail: MaskaDetail): void => {
86
- emit('input', detail.unmasked);
87
- emit('input:masked', detail.masked);
88
- },
89
- };
90
- });
92
+ defineSlots<{
93
+ 'label'?: () => VNode[];
94
+ 'prepend-inner'?: () => VNode[];
95
+ 'append'?: () => VNode[];
96
+ 'message'?: () => VNode[];
97
+ }>();
91
98
 
92
- const { maskedValue, mask: inputMask, unmaskedValue } = useInputMask(input, value, maskOptions);
93
- const maskedMinLength = useMaskedMinLength(minlength, value, maskOptions);
94
- const maskedMaxLength = useMaskedMaxLength(maxlength, maskOptions);
95
- const counterValue = computed<number>(() => unmaskedValue.value.length);
99
+ const { minlength, maxlength, value } = toRefs(props);
96
100
 
97
- const unmaskedRules = computed<Rules<string>>(() => {
98
- return props.rules.map((rule) => {
99
- return (value): string | boolean => {
100
- const unmaskedValue = inputMask.value?.unmasked(value) ?? value;
101
- return rule(unmaskedValue);
102
- };
103
- });
104
- });
101
+ const textField = ref<InstanceType<typeof CTextField> | null>(null);
102
+ const input = computed(() => textField.value?.input ?? null);
103
+ const maskOptions = computed<MaskInputOptions>(() => {
104
+ return {
105
+ mask: props.mask,
106
+ tokens: {
107
+ // NOTE (ej): For the EBT Card Number we accept a mask 'N' from the server
108
+ // to hide all but the last 4 digits. e.g. XXXXXXXXXXXXXXX2114
109
+ N: { pattern: /[0-9X]/ },
110
+ ...props.tokens,
111
+ },
112
+ onMaska: (detail: MaskaDetail): void => {
113
+ emit('input', detail.unmasked);
114
+ emit('input:masked', detail.masked);
115
+ },
116
+ };
117
+ });
105
118
 
106
- expose({ input });
119
+ const { maskedValue, mask: inputMask, unmaskedValue } = useInputMask(input, value, maskOptions);
120
+ const maskedMinLength = useMaskedMinLength(minlength, value, maskOptions);
121
+ const maskedMaxLength = useMaskedMaxLength(maxlength, maskOptions);
122
+ const counterValue = computed<number>(() => unmaskedValue.value.length);
107
123
 
108
- return {
109
- counterValue,
110
- maskedMinLength,
111
- maskedMaxLength,
112
- maskedValue,
113
- textField,
114
- unmaskedRules,
124
+ const unmaskedRules = computed<Rules<string>>(() => {
125
+ return props.rules.map((rule) => {
126
+ return (value): string | boolean => {
127
+ const unmaskedValue = inputMask.value?.unmasked(value) ?? value;
128
+ return rule(unmaskedValue);
115
129
  };
116
- },
130
+ });
117
131
  });
132
+
133
+ defineExpose({ input });
118
134
  </script>
@@ -5,14 +5,22 @@
5
5
  </template>
6
6
 
7
7
  <script lang="ts">
8
- import '@shoelace-style/shoelace/dist/components/menu/menu.js';
9
- import { defineComponent } from 'vue';
10
8
  export type { default as SlMenuItem } from '@shoelace-style/shoelace/dist/components/menu-item/menu-item.js';
9
+ </script>
10
+
11
+ <script setup lang="ts">
12
+ import type { VNode } from 'vue';
13
+
14
+ import '@shoelace-style/shoelace/dist/components/menu/menu.js';
15
+
16
+ defineEmits<{
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ select: [item: any];
19
+ }>();
11
20
 
12
- export default defineComponent({
13
- name: 'CMenu',
14
- emits: ['select'],
15
- });
21
+ defineSlots<{
22
+ default?: () => VNode[];
23
+ }>();
16
24
  </script>
17
25
 
18
26
  <style lang="scss" scoped>
@@ -27,38 +27,44 @@
27
27
  </sl-menu-item>
28
28
  </template>
29
29
 
30
- <script lang="ts">
30
+ <script setup lang="ts">
31
31
  import { faCheck } from '@fortawesome/pro-regular-svg-icons';
32
32
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
33
- import { type PropType, defineComponent } from 'vue';
33
+ import type { VNode } from 'vue';
34
34
 
35
35
  import '@shoelace-style/shoelace/dist/components/menu-item/menu-item.js';
36
36
  import CCheckbox from '@propelinc/citrus-ui/src/components/CCheckbox.vue';
37
37
 
38
- export default defineComponent({
39
- name: 'CMenuItem',
40
- components: { CCheckbox, FontAwesomeIcon },
41
- props: {
42
- /** Controls whether the item has hover-state styles and responds to click events */
43
- selectable: { type: Boolean, default: true },
38
+ const props = withDefaults(
39
+ defineProps<{
44
40
  /** Controls whether to enable and display a checked state */
45
- checkable: { type: Boolean },
41
+ checkable?: boolean;
46
42
  /** Reflects the item's checked state */
47
- checked: { type: Boolean },
43
+ checked?: boolean;
48
44
  /** Controls what style of checking to apply, either a checkbox, or just a check icon */
49
- checkType: { type: String as PropType<'checkbox' | 'icon'>, default: 'checkbox' },
50
- },
51
- setup(props) {
52
- const onClick = (e: Event): void => {
53
- if (!props.selectable) {
54
- e.preventDefault();
55
- e.stopPropagation();
56
- }
57
- };
45
+ checkType?: 'checkbox' | 'icon';
46
+ /** Controls whether the item has hover-state styles and responds to click events */
47
+ selectable?: boolean;
48
+ }>(),
49
+ {
50
+ checkable: false,
51
+ checked: false,
52
+ checkType: 'checkbox',
53
+ selectable: true,
54
+ }
55
+ );
58
56
 
59
- return { faCheck, onClick };
60
- },
61
- });
57
+ defineSlots<{
58
+ 'prepend-inner'?: () => VNode[];
59
+ 'default'?: () => VNode[];
60
+ }>();
61
+
62
+ const onClick = (e: Event): void => {
63
+ if (!props.selectable) {
64
+ e.preventDefault();
65
+ e.stopPropagation();
66
+ }
67
+ };
62
68
  </script>
63
69
 
64
70
  <style lang="scss" scoped>
@@ -4,13 +4,14 @@
4
4
  </sl-menu-label>
5
5
  </template>
6
6
 
7
- <script lang="ts">
7
+ <script setup lang="ts">
8
+ import type { VNode } from 'vue';
9
+
8
10
  import '@shoelace-style/shoelace/dist/components/menu-label/menu-label.js';
9
- import { defineComponent } from 'vue';
10
11
 
11
- export default defineComponent({
12
- name: 'CMenuLabel',
13
- });
12
+ defineSlots<{
13
+ default?: () => VNode[];
14
+ }>();
14
15
  </script>
15
16
 
16
17
  <style lang="scss" scoped>
@@ -52,11 +52,11 @@
52
52
  </sl-dialog>
53
53
  </template>
54
54
 
55
- <script lang="ts">
55
+ <script setup lang="ts">
56
56
  import type SlDialog from '@shoelace-style/shoelace/dist/components/dialog/dialog.js';
57
57
  import '@shoelace-style/shoelace/dist/components/dialog/dialog.js';
58
- import type { PropType } from 'vue';
59
- import { computed, defineComponent, ref } from 'vue';
58
+ import type { VNode } from 'vue';
59
+ import { computed, ref } from 'vue';
60
60
 
61
61
  import CButtonStack from '@propelinc/citrus-ui/src/components/CButtonStack.vue';
62
62
  import CExpandTransition from '@propelinc/citrus-ui/src/components/CExpandTransition.vue';
@@ -64,77 +64,82 @@ import CLoader from '@propelinc/citrus-ui/src/components/CLoader.vue';
64
64
  import { useShoelaceAnimation } from '@propelinc/citrus-ui/src/composables/animation';
65
65
  import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
66
66
 
67
- export default defineComponent({
68
- name: 'CModal',
69
- components: { CButtonStack, CLoader, CExpandTransition },
70
- props: {
71
- /** Controls whether or not the modal is showing */
72
- value: { type: Boolean, default: false },
73
- /** The title of the modal */
74
- title: { type: String as PropType<string | null>, default: null },
75
- /** Shows loading state and sets loading message if string */
76
- loading: { type: [String, Boolean], default: false },
77
- /** Allows modal to be dismissed */
78
- dismissible: { type: Boolean, default: true },
67
+ const props = withDefaults(
68
+ defineProps<{
69
+ /** Aria label for the modal. This is required if title is hidden */
70
+ ariaLabel?: string;
79
71
  /** Prefix for test selectors */
80
- dataTest: { type: String, default: 'modal' },
81
- /** Toggles the open/close animation */
82
- transition: { type: Boolean, default: true },
72
+ dataTest?: string;
73
+ /** Allows modal to be dismissed */
74
+ dismissible?: boolean;
83
75
  /** Controls whether the modal displays fullscreen */
84
- fullscreen: { type: Boolean, default: false },
85
- /** Aria label for the modal. This is required if title is hidden */
86
- ariaLabel: { type: String, default: '' },
87
- },
88
- emits: ['input'],
89
- setup(props) {
90
- const onRequestClose = (event: Event): void => {
91
- if (!props.dismissible) {
92
- event.preventDefault();
93
- }
94
- };
95
-
96
- const modal = ref<SlDialog | null>(null);
97
- const animation = computed<'default' | null>(() => (props.transition ? 'default' : null));
98
- useShoelaceAnimation(modal, 'dialog.show', animation);
99
- useShoelaceAnimation(modal, 'dialog.hide', animation);
100
- useShoelaceAnimation(modal, 'dialog.overlay.show', animation);
101
- useShoelaceAnimation(modal, 'dialog.overlay.hide', animation);
102
-
103
- const isVisible = ref(false);
104
- // NOTE(mohan): Don't do any expand transitions until the modal is fully
105
- // open.
106
- const enableExpandTransition = computed(() => !props.fullscreen && isVisible.value);
107
-
108
- const getDataTestAttr = (suffix?: string): string => {
109
- return suffix ? `${props.dataTest}-${suffix}` : props.dataTest;
110
- };
111
-
112
- const loadingMessage = computed(() => {
113
- return typeof props.loading === 'string' ? props.loading : null;
114
- });
115
-
116
- const dialogLabel = computed(() => {
117
- if (loadingMessage.value) {
118
- return loadingMessage.value;
119
- }
120
-
121
- return props.title || props.ariaLabel;
122
- });
123
-
124
- const footerHasContent = useSlotHasContent('footer');
125
-
126
- return {
127
- dialogLabel,
128
- loadingMessage,
129
- isVisible,
130
- enableExpandTransition,
131
- footerHasContent,
132
- onRequestClose,
133
- getDataTestAttr,
134
- modal,
135
- };
136
- },
76
+ fullscreen?: boolean;
77
+ /** Shows loading state and sets loading message if string */
78
+ loading?: string | boolean;
79
+ /** The title of the modal */
80
+ title?: string | null;
81
+ /** Toggles the open/close animation */
82
+ transition?: boolean;
83
+ /** Controls whether or not the modal is showing */
84
+ value?: boolean;
85
+ }>(),
86
+ {
87
+ ariaLabel: '',
88
+ dataTest: 'modal',
89
+ dismissible: true,
90
+ fullscreen: false,
91
+ loading: false,
92
+ title: null,
93
+ transition: true,
94
+ value: false,
95
+ }
96
+ );
97
+
98
+ defineEmits<{
99
+ input: [value: boolean];
100
+ }>();
101
+
102
+ defineSlots<{
103
+ default?: () => VNode[];
104
+ footer?: () => VNode[];
105
+ loading?: () => VNode[];
106
+ }>();
107
+
108
+ const onRequestClose = (event: Event): void => {
109
+ if (!props.dismissible) {
110
+ event.preventDefault();
111
+ }
112
+ };
113
+
114
+ const modal = ref<SlDialog | null>(null);
115
+ const animation = computed<'default' | null>(() => (props.transition ? 'default' : null));
116
+ useShoelaceAnimation(modal, 'dialog.show', animation);
117
+ useShoelaceAnimation(modal, 'dialog.hide', animation);
118
+ useShoelaceAnimation(modal, 'dialog.overlay.show', animation);
119
+ useShoelaceAnimation(modal, 'dialog.overlay.hide', animation);
120
+
121
+ const isVisible = ref(false);
122
+ // NOTE(mohan): Don't do any expand transitions until the modal is fully
123
+ // open.
124
+ const enableExpandTransition = computed(() => !props.fullscreen && isVisible.value);
125
+
126
+ const getDataTestAttr = (suffix?: string): string => {
127
+ return suffix ? `${props.dataTest}-${suffix}` : props.dataTest;
128
+ };
129
+
130
+ const loadingMessage = computed(() => {
131
+ return typeof props.loading === 'string' ? props.loading : null;
137
132
  });
133
+
134
+ const dialogLabel = computed(() => {
135
+ if (loadingMessage.value) {
136
+ return loadingMessage.value;
137
+ }
138
+
139
+ return props.title || props.ariaLabel;
140
+ });
141
+
142
+ const footerHasContent = useSlotHasContent('footer');
138
143
  </script>
139
144
 
140
145
  <style lang="scss" scoped>