@propelinc/citrus-ui 1.0.5 → 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.
- package/README.md +39 -14
- package/dist/citrus-ui.cdn.css +1 -0
- package/dist/citrus-ui.css +1 -0
- package/dist/colors/colors.d.ts +31 -0
- package/dist/colors/theme.d.ts +3 -0
- package/dist/colors/util-classes.d.ts +11 -0
- package/dist/components/CAccordion.vue.d.ts +34 -0
- package/dist/components/CAccordionItem.vue.d.ts +39 -0
- package/dist/components/CAppBar.vue.d.ts +59 -0
- package/dist/components/CBadge.vue.d.ts +35 -0
- package/dist/components/CBottomSheet.vue.d.ts +90 -0
- package/dist/components/CButton/CButton.vue.d.ts +97 -0
- package/dist/components/CButton/types.d.ts +5 -0
- package/dist/components/CButtonStack.vue.d.ts +27 -0
- package/dist/components/CCard.vue.d.ts +53 -0
- package/dist/components/CCardFooter.vue.d.ts +20 -0
- package/dist/components/CCardHeader.vue.d.ts +22 -0
- package/dist/components/CCardSection.vue.d.ts +26 -0
- package/dist/components/CCheckbox.vue.d.ts +62 -0
- package/dist/components/CCol.vue.d.ts +30 -0
- package/dist/components/CDivider.vue.d.ts +9 -0
- package/dist/components/CDobField.vue.d.ts +60 -0
- package/dist/components/CDobSelect.vue.d.ts +50 -0
- package/dist/components/CEmailField.vue.d.ts +48 -0
- package/dist/components/CExpandTransition.vue.d.ts +29 -0
- package/dist/components/CFadeTransition.vue.d.ts +20 -0
- package/dist/components/CFileInput.vue.d.ts +50 -0
- package/dist/components/CFixedPageFooter.vue.d.ts +153 -0
- package/dist/components/CForm.vue.d.ts +44 -0
- package/dist/components/CFormFieldCounter.vue.d.ts +15 -0
- package/dist/components/CIconButton.vue.d.ts +97 -0
- package/dist/components/CLabel.vue.d.ts +36 -0
- package/dist/components/CListItem.vue.d.ts +56 -0
- package/dist/components/CListItemContent.vue.d.ts +27 -0
- package/dist/components/CListItemIcon.vue.d.ts +28 -0
- package/dist/components/CLoader.vue.d.ts +23 -0
- package/dist/components/CLogo.vue.d.ts +9 -0
- package/dist/components/CMaskedTextField.vue.d.ts +511 -0
- package/dist/components/CMenu.vue.d.ts +17 -0
- package/dist/components/CMenuItem.vue.d.ts +37 -0
- package/dist/components/CMenuLabel.vue.d.ts +20 -0
- package/dist/components/CModal.vue.d.ts +59 -0
- package/dist/components/CModalLoading.vue.d.ts +36 -0
- package/dist/components/CNotification.vue.d.ts +64 -0
- package/dist/components/CPhoneField.vue.d.ts +792 -0
- package/dist/components/CPill.vue.d.ts +41 -0
- package/dist/components/CPillGroup.vue.d.ts +39 -0
- package/dist/components/CPopup.vue.d.ts +37 -0
- package/dist/components/CProgressLinear.vue.d.ts +21 -0
- package/dist/components/CProgressRing.vue.d.ts +48 -0
- package/dist/components/CRadio.vue.d.ts +40 -0
- package/dist/components/CRadioGroup.vue.d.ts +54 -0
- package/dist/components/CRebrand.vue.d.ts +28 -0
- package/dist/components/CRow.vue.d.ts +41 -0
- package/dist/components/CSafeArea.vue.d.ts +18 -0
- package/dist/components/CSectionHeader.vue.d.ts +29 -0
- package/dist/components/CSelect.vue.d.ts +96 -0
- package/dist/components/CSkeleton.vue.d.ts +3 -0
- package/dist/components/CSkeletonLoaderCard.vue.d.ts +9 -0
- package/dist/components/CSkeletonLoaderCircle.vue.d.ts +3 -0
- package/dist/components/CSkeletonLoaderText.vue.d.ts +16 -0
- package/dist/components/CSlideFadeTransition.vue.d.ts +36 -0
- package/dist/components/CSplitInput.vue.d.ts +56 -0
- package/dist/components/CSquaredIcon.vue.d.ts +33 -0
- package/dist/components/CSsnField.vue.d.ts +798 -0
- package/dist/components/CStatusDot.vue.d.ts +10 -0
- package/dist/components/CSwitch.vue.d.ts +39 -0
- package/dist/components/CSwitchListItem.vue.d.ts +48 -0
- package/dist/components/CTextArea.vue.d.ts +96 -0
- package/dist/components/CTextField.vue.d.ts +129 -0
- package/dist/components/CTextLink.vue.d.ts +36 -0
- package/dist/components/CThirdPartyLogo.vue.d.ts +22 -0
- package/dist/components/CTimeago.vue.d.ts +12 -0
- package/dist/components/CToast.vue.d.ts +69 -0
- package/dist/components/CToastsList.vue.d.ts +3 -0
- package/dist/components/CValidationMessage.vue.d.ts +37 -0
- package/dist/components/CZipcodeField.vue.d.ts +796 -0
- package/dist/components/index.d.ts +66 -0
- package/dist/components/internal/CCloseButton.vue.d.ts +14 -0
- package/dist/composables/accessibility.d.ts +1 -0
- package/dist/composables/animation.d.ts +12 -0
- package/dist/composables/binding.d.ts +19 -0
- package/dist/composables/colors.d.ts +13 -0
- package/dist/composables/elements.d.ts +3 -0
- package/dist/composables/fields.d.ts +10 -0
- package/dist/composables/gestures.d.ts +53 -0
- package/dist/composables/i18n.d.ts +3 -0
- package/dist/composables/id.d.ts +11 -0
- package/dist/composables/input-mask.d.ts +18 -0
- package/dist/composables/router.d.ts +30 -0
- package/dist/composables/slots.d.ts +2 -0
- package/dist/composables/toast.d.ts +21 -0
- package/dist/composables/validations.d.ts +77 -0
- package/dist/icons.cdn.mjs +3 -0
- package/dist/icons.cdn.mjs.map +1 -0
- package/dist/icons.d.ts +1 -0
- package/dist/icons.mjs +6 -0
- package/dist/icons.mjs.map +1 -0
- package/dist/index.cdn.mjs +9328 -12875
- package/dist/index.cdn.mjs.map +1 -1
- package/dist/index.cdn2.mjs +55255 -0
- package/dist/index.cdn2.mjs.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.mjs +3946 -0
- package/dist/index.mjs.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/services/animation.d.ts +17 -0
- package/dist/services/directives/index.d.ts +2 -0
- package/dist/services/directives/scroll-into-view.d.ts +7 -0
- package/dist/services/directives/tap-animation.d.ts +6 -0
- package/dist/services/id.d.ts +22 -0
- package/dist/services/injections/accordions.d.ts +3 -0
- package/dist/services/injections/animations.d.ts +2 -0
- package/dist/services/injections/buttons.d.ts +4 -0
- package/dist/services/injections/forms.d.ts +6 -0
- package/dist/services/injections/icon-buttons.d.ts +3 -0
- package/dist/services/injections/pills.d.ts +4 -0
- package/dist/services/injections/radio.d.ts +10 -0
- package/dist/{styles/main.css → styles.css} +8 -6
- package/dist/theme/icons.d.ts +36 -0
- package/dist/types/CForm.d.ts +12 -0
- package/dist/types/font-awesome.d.ts +5 -0
- package/dist/types.d.ts +13 -0
- package/package.json +8 -3
- package/src/colors/colors.ts +8 -3
- package/src/components/CAccordion.vue +31 -24
- package/src/components/CAccordionItem.vue +46 -45
- package/src/components/CAppBar.vue +108 -101
- package/src/components/CBadge.vue +33 -25
- package/src/components/CBottomSheet.vue +212 -199
- package/src/components/CButton/CButton.vue +135 -147
- package/src/components/CButtonStack.vue +21 -13
- package/src/components/CCard.vue +72 -69
- package/src/components/CCardFooter.vue +5 -5
- package/src/components/CCardHeader.vue +9 -7
- package/src/components/CCardSection.vue +15 -8
- package/src/components/CCheckbox.vue +68 -69
- package/src/components/CCol.vue +21 -22
- package/src/components/CDivider.vue +9 -8
- package/src/components/CDobField.vue +114 -105
- package/src/components/CDobSelect.vue +162 -164
- package/src/components/CEmailField.vue +39 -27
- package/src/components/CExpandTransition.vue +14 -17
- package/src/components/CFadeTransition.vue +3 -3
- package/src/components/CFileInput.vue +57 -50
- package/src/components/CFixedPageFooter.vue +23 -17
- package/src/components/CForm.vue +67 -60
- package/src/components/CFormFieldCounter.vue +25 -28
- package/src/components/CIconButton.vue +84 -65
- package/src/components/CLabel.vue +19 -13
- package/src/components/CListItem.vue +67 -66
- package/src/components/CListItemContent.vue +14 -16
- package/src/components/CListItemIcon.vue +18 -14
- package/src/components/CLoader.vue +47 -56
- package/src/components/CLogo.vue +13 -12
- package/src/components/CMaskedTextField.vue +80 -64
- package/src/components/CMenu.vue +14 -6
- package/src/components/CMenuItem.vue +28 -22
- package/src/components/CMenuLabel.vue +6 -5
- package/src/components/CModal.vue +76 -71
- package/src/components/CModalLoading.vue +24 -15
- package/src/components/CNotification.vue +77 -28
- package/src/components/CPhoneField.vue +34 -25
- package/src/components/CPill.vue +92 -88
- package/src/components/CPillGroup.vue +30 -21
- package/src/components/CPopup.vue +46 -37
- package/src/components/CProgressLinear.vue +17 -11
- package/src/components/CProgressRing.vue +33 -33
- package/src/components/CRadio.vue +57 -57
- package/src/components/CRadioGroup.vue +85 -72
- package/src/components/CRow.vue +22 -20
- package/src/components/CSectionHeader.vue +20 -12
- package/src/components/CSelect.vue +89 -73
- package/src/components/CSkeletonLoaderCard.vue +9 -15
- package/src/components/CSkeletonLoaderCircle.vue +1 -9
- package/src/components/CSkeletonLoaderText.vue +17 -18
- package/src/components/CSlideFadeTransition.vue +12 -34
- package/src/components/CSplitInput.vue +46 -45
- package/src/components/CSquaredIcon.vue +39 -29
- package/src/components/CSsnField.vue +48 -36
- package/src/components/CStatusDot.vue +16 -16
- package/src/components/CSwitch.vue +31 -22
- package/src/components/CSwitchListItem.vue +27 -28
- package/src/components/CTextArea.vue +116 -83
- package/src/components/CTextField.vue +194 -198
- package/src/components/CTextLink.vue +28 -25
- package/src/components/CThirdPartyLogo.vue +30 -59
- package/src/components/CToast.vue +135 -132
- package/src/components/CToastsList.vue +2 -15
- package/src/components/CValidationMessage.vue +31 -24
- package/src/components/CZipcodeField.vue +40 -27
- package/src/composables/elements.ts +1 -1
- package/src/composables/fields.ts +4 -4
- package/src/composables/router.ts +6 -5
- package/src/icons.ts +6 -0
- package/src/services/injections/buttons.ts +1 -1
- package/src/styles/_core.scss +1 -2
- package/src/styles/_reset.scss +1 -1
- package/src/types.ts +2 -0
- package/dist/index.cdn.css +0 -1
- package/dist/styles/utils.css +0 -2709
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
</sl-alert>
|
|
33
33
|
</template>
|
|
34
34
|
|
|
35
|
-
<script lang="ts">
|
|
35
|
+
<script setup lang="ts">
|
|
36
36
|
import {
|
|
37
37
|
faCircleCheck,
|
|
38
38
|
faCircleExclamation,
|
|
@@ -43,8 +43,8 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
|
|
43
43
|
import '@shoelace-style/shoelace/dist/components/alert/alert.js';
|
|
44
44
|
import type SlAlert from '@shoelace-style/shoelace/dist/components/alert/alert.js';
|
|
45
45
|
import type { ElementAnimation } from '@shoelace-style/shoelace/dist/utilities/animation-registry';
|
|
46
|
-
import type {
|
|
47
|
-
import { computed,
|
|
46
|
+
import type { VNode } from 'vue';
|
|
47
|
+
import { computed, onBeforeUnmount, ref, watchEffect } from 'vue';
|
|
48
48
|
|
|
49
49
|
import CIconButton from '@propelinc/citrus-ui/src/components/CIconButton.vue';
|
|
50
50
|
import { useShoelaceAnimation } from '@propelinc/citrus-ui/src/composables/animation';
|
|
@@ -62,150 +62,153 @@ const MIN_SWIPE_DISTANCE = 150;
|
|
|
62
62
|
* it to be considered a successful swipe. */
|
|
63
63
|
const MIN_SWIPE_VELOCITY = 0.75;
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
/** The message rendered in the toast, using the default slot overrides this value */
|
|
72
|
-
message: { type: String, default: '' },
|
|
65
|
+
const props = withDefaults(
|
|
66
|
+
defineProps<{
|
|
67
|
+
/** The data-test attribute for the toast. */
|
|
68
|
+
dataTest?: string;
|
|
69
|
+
/** Controls (overrides) whether the toast is dismissible. */
|
|
70
|
+
dismissible?: boolean | undefined;
|
|
73
71
|
/**
|
|
74
72
|
* @deprecated use `variant` prop instead
|
|
75
73
|
* Renders the error state
|
|
76
74
|
*/
|
|
77
|
-
error
|
|
75
|
+
error?: boolean;
|
|
76
|
+
/** The message rendered in the toast, using the default slot overrides this value */
|
|
77
|
+
message?: string;
|
|
78
78
|
/**
|
|
79
79
|
* @deprecated use `variant` prop instead
|
|
80
80
|
* Renders the success state
|
|
81
81
|
*/
|
|
82
|
-
success
|
|
82
|
+
success?: boolean;
|
|
83
|
+
/** Show/hides the toast */
|
|
84
|
+
value?: boolean;
|
|
85
|
+
/** The variant of the toast */
|
|
86
|
+
variant?: ToastVariant;
|
|
83
87
|
/**
|
|
84
88
|
* @deprecated use `variant` prop instead
|
|
85
89
|
* Renders the warning state
|
|
86
90
|
*/
|
|
87
|
-
warning
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
dismissible:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
warning?: boolean;
|
|
92
|
+
}>(),
|
|
93
|
+
{
|
|
94
|
+
dataTest: 'toast',
|
|
95
|
+
dismissible: undefined,
|
|
96
|
+
error: false,
|
|
97
|
+
message: '',
|
|
98
|
+
success: false,
|
|
99
|
+
variant: 'info',
|
|
100
|
+
value: false,
|
|
101
|
+
warning: false,
|
|
102
|
+
}
|
|
103
|
+
);
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
computedVariant,
|
|
202
|
-
close,
|
|
203
|
-
onHide,
|
|
204
|
-
transform,
|
|
205
|
-
resetAnimation,
|
|
206
|
-
};
|
|
105
|
+
const emit = defineEmits<{
|
|
106
|
+
hide: [];
|
|
107
|
+
input: [value: boolean];
|
|
108
|
+
}>();
|
|
109
|
+
|
|
110
|
+
defineSlots<{
|
|
111
|
+
icon?: () => VNode[];
|
|
112
|
+
default?: () => VNode[];
|
|
113
|
+
}>();
|
|
114
|
+
|
|
115
|
+
const alert = ref<SlAlert | null>(null);
|
|
116
|
+
const isOpen = ref(props.value);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Handle merging the deprecated `error`, `success`, and `warning` props
|
|
120
|
+
* with the `variant` prop.
|
|
121
|
+
*/
|
|
122
|
+
const computedVariant = computed(() => {
|
|
123
|
+
if (props.error) {
|
|
124
|
+
return 'error';
|
|
125
|
+
} else if (props.success) {
|
|
126
|
+
return 'success';
|
|
127
|
+
} else if (props.warning) {
|
|
128
|
+
return 'warning';
|
|
129
|
+
}
|
|
130
|
+
return props.variant;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const show = async (): Promise<void> => {
|
|
134
|
+
isOpen.value = true;
|
|
135
|
+
alert.value?.toast();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const onHide = (): void => {
|
|
139
|
+
isOpen.value = false;
|
|
140
|
+
emit('input', false);
|
|
141
|
+
emit('hide');
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const close = async (): Promise<void> => {
|
|
145
|
+
alert.value?.hide();
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// If our value changes, show or hide the toast respectively
|
|
149
|
+
watchEffect(() => (props.value ? show() : close()));
|
|
150
|
+
|
|
151
|
+
// Close the toast when the component is unmounted
|
|
152
|
+
onBeforeUnmount(() => close());
|
|
153
|
+
|
|
154
|
+
const shouldAutoDismiss = computed(() => {
|
|
155
|
+
if (props.dismissible !== undefined) {
|
|
156
|
+
return !props.dismissible;
|
|
157
|
+
}
|
|
158
|
+
return computedVariant.value === 'success';
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const duration = computed(() => {
|
|
162
|
+
return shouldAutoDismiss.value ? DEFAULT_DURATION : Infinity;
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const icon = computed(() => {
|
|
166
|
+
if (computedVariant.value === 'error') {
|
|
167
|
+
return faCircleExclamation;
|
|
168
|
+
} else if (computedVariant.value === 'success') {
|
|
169
|
+
return faCircleCheck;
|
|
170
|
+
} else {
|
|
171
|
+
return faInfoCircle;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const alertHideAnimation = ref<ElementAnimation | 'default'>('default');
|
|
176
|
+
useShoelaceAnimation(alert, 'alert.hide', alertHideAnimation);
|
|
177
|
+
|
|
178
|
+
const resetAnimation = (): void => {
|
|
179
|
+
alertHideAnimation.value = 'default';
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const { base } = useShoelaceShadowParts(alert, ['base']);
|
|
183
|
+
const { dragDistance } = useDragListener(base, {
|
|
184
|
+
onDragEnd: async ({ distance, velocity }) => {
|
|
185
|
+
const absoluteDistance = Math.abs(distance.x);
|
|
186
|
+
const absoluteVelocity = Math.abs(velocity.x);
|
|
187
|
+
const shouldDismiss =
|
|
188
|
+
absoluteDistance > MIN_SWIPE_DISTANCE || absoluteVelocity > MIN_SWIPE_VELOCITY;
|
|
189
|
+
const dismissStart = absoluteDistance / base.value!.clientWidth;
|
|
190
|
+
if (shouldDismiss) {
|
|
191
|
+
const remainingDismissDistance = Math.max(base.value!.clientWidth - absoluteDistance, 0);
|
|
192
|
+
const dismissDuration =
|
|
193
|
+
remainingDismissDistance / Math.max(absoluteVelocity, MIN_SWIPE_VELOCITY);
|
|
194
|
+
const slideDirection = velocity.x > 0 ? slideRight : slideLeft;
|
|
195
|
+
alertHideAnimation.value = slideDirection({
|
|
196
|
+
start: dismissStart,
|
|
197
|
+
duration: dismissDuration,
|
|
198
|
+
end: 1.1,
|
|
199
|
+
});
|
|
200
|
+
close();
|
|
201
|
+
} else {
|
|
202
|
+
const slideDirection = velocity.x > 0 ? slideRight : slideLeft;
|
|
203
|
+
const slideBack = slideDirection({ start: dismissStart, end: 0 });
|
|
204
|
+
base.value?.animate(slideBack.keyframes, slideBack.options);
|
|
205
|
+
}
|
|
207
206
|
},
|
|
208
207
|
});
|
|
208
|
+
|
|
209
|
+
const transform = computed(() => {
|
|
210
|
+
return `translateX(${dragDistance.value?.x ?? 0}px)`;
|
|
211
|
+
});
|
|
209
212
|
</script>
|
|
210
213
|
|
|
211
214
|
<style lang="scss" scoped>
|
|
@@ -10,23 +10,10 @@
|
|
|
10
10
|
/>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
|
-
<script lang="ts">
|
|
14
|
-
import { defineComponent } from 'vue';
|
|
15
|
-
|
|
13
|
+
<script setup lang="ts">
|
|
16
14
|
import CToast from '@propelinc/citrus-ui/src/components/CToast.vue';
|
|
17
15
|
|
|
18
16
|
import { useToast } from '../composables/toast';
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
name: 'CToastsList',
|
|
22
|
-
components: { CToast },
|
|
23
|
-
setup() {
|
|
24
|
-
const { toasts, dismissToast } = useToast();
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
toasts,
|
|
28
|
-
dismissToast,
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
|
-
});
|
|
18
|
+
const { toasts, dismissToast } = useToast();
|
|
32
19
|
</script>
|
|
@@ -19,37 +19,44 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
|
-
<script lang="ts">
|
|
23
|
-
import type {
|
|
24
|
-
import { computed
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import type { VNode } from 'vue';
|
|
24
|
+
import { computed } from 'vue';
|
|
25
25
|
|
|
26
26
|
import CFadeTransition from '@propelinc/citrus-ui/src/components/CFadeTransition.vue';
|
|
27
27
|
import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
components: { CFadeTransition },
|
|
32
|
-
props: {
|
|
29
|
+
const props = withDefaults(
|
|
30
|
+
defineProps<{
|
|
33
31
|
/** Test selector for the component */
|
|
34
|
-
dataTest
|
|
32
|
+
dataTest?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to hide the component. If "auto", the component will automatically
|
|
35
|
+
* hide itself if it has no content.
|
|
36
|
+
*/
|
|
37
|
+
hide?: boolean | 'auto';
|
|
35
38
|
/** Validation message to display */
|
|
36
|
-
validationMessage
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (props.hide === 'auto') {
|
|
45
|
-
return !props.validationMessage && !appendSlotHasContent.value;
|
|
46
|
-
} else {
|
|
47
|
-
return props.hide;
|
|
48
|
-
}
|
|
49
|
-
});
|
|
39
|
+
validationMessage?: string | null;
|
|
40
|
+
}>(),
|
|
41
|
+
{
|
|
42
|
+
dataTest: 'validation-message',
|
|
43
|
+
hide: false,
|
|
44
|
+
validationMessage: null,
|
|
45
|
+
}
|
|
46
|
+
);
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
defineSlots<{
|
|
49
|
+
default?: () => VNode[];
|
|
50
|
+
append?: () => VNode[];
|
|
51
|
+
}>();
|
|
52
|
+
|
|
53
|
+
const appendSlotHasContent = useSlotHasContent('append');
|
|
54
|
+
const isHidden = computed(() => {
|
|
55
|
+
if (props.hide === 'auto') {
|
|
56
|
+
return !props.validationMessage && !appendSlotHasContent.value;
|
|
57
|
+
} else {
|
|
58
|
+
return props.hide;
|
|
59
|
+
}
|
|
53
60
|
});
|
|
54
61
|
</script>
|
|
55
62
|
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
</CMaskedTextField>
|
|
30
30
|
</template>
|
|
31
31
|
|
|
32
|
-
<script lang="ts">
|
|
33
|
-
import
|
|
32
|
+
<script setup lang="ts">
|
|
33
|
+
import type { VNode } from 'vue';
|
|
34
|
+
import { computed } from 'vue';
|
|
34
35
|
|
|
35
36
|
import CMaskedTextField from '@propelinc/citrus-ui/src/components/CMaskedTextField.vue';
|
|
36
37
|
import { useFocusableField } from '@propelinc/citrus-ui/src/composables/fields';
|
|
@@ -38,32 +39,44 @@ import { useTranslation } from '@propelinc/citrus-ui/src/composables/i18n';
|
|
|
38
39
|
import type { Rules } from '@propelinc/citrus-ui/src/composables/validations';
|
|
39
40
|
import { minLengthRule } from '@propelinc/shared-utils';
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
const props = withDefaults(
|
|
43
|
+
defineProps<{
|
|
44
|
+
dataTest?: string;
|
|
45
|
+
id?: string;
|
|
46
|
+
label?: string | null;
|
|
47
|
+
placeholder?: string | null;
|
|
48
|
+
rules?: Rules<string>;
|
|
49
|
+
value?: string;
|
|
50
|
+
}>(),
|
|
51
|
+
{
|
|
52
|
+
dataTest: 'zipcode-field',
|
|
53
|
+
id: undefined,
|
|
54
|
+
label: null,
|
|
55
|
+
placeholder: null,
|
|
56
|
+
rules: (): Rules<string> => [],
|
|
57
|
+
value: '',
|
|
58
|
+
}
|
|
59
|
+
);
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
defineEmits<{
|
|
62
|
+
input: [value: string];
|
|
63
|
+
focus: [event: Event];
|
|
64
|
+
blur: [event: Event];
|
|
65
|
+
change: [value: string];
|
|
66
|
+
}>();
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
defineSlots<{
|
|
69
|
+
label?: () => VNode[];
|
|
70
|
+
message?: () => VNode[];
|
|
71
|
+
}>();
|
|
62
72
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
const { t } = useTranslation();
|
|
74
|
+
|
|
75
|
+
const defaultRules = [
|
|
76
|
+
minLengthRule(5, t('Please enter a valid {inputLabel}', { inputLabel: t('ZIP Code') })),
|
|
77
|
+
];
|
|
78
|
+
const computedRules = computed(() => [...defaultRules, ...props.rules]);
|
|
79
|
+
|
|
80
|
+
const { field, focus } = useFocusableField();
|
|
81
|
+
defineExpose({ focus });
|
|
69
82
|
</script>
|
|
@@ -4,7 +4,7 @@ import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
|
4
4
|
// NOTE(mohan): A simplified port of vueuse/core's useResizeObserver.
|
|
5
5
|
// vueuse has type errors because our version of vue is so old.
|
|
6
6
|
export function useResizeObserver(
|
|
7
|
-
element: Ref<HTMLElement | null>,
|
|
7
|
+
element: Ref<HTMLElement | null | undefined>,
|
|
8
8
|
callback: (entries: ResizeObserverEntry[]) => void
|
|
9
9
|
): void {
|
|
10
10
|
if (!('ResizeObserver' in window)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Ref,
|
|
1
|
+
import { type Ref, computed, ref } from 'vue';
|
|
2
2
|
|
|
3
3
|
export interface Field {
|
|
4
4
|
input: HTMLInputElement | null;
|
|
@@ -6,14 +6,14 @@ export interface Field {
|
|
|
6
6
|
|
|
7
7
|
interface FocusableField {
|
|
8
8
|
field: Ref<Field | null>;
|
|
9
|
+
focus: () => void;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
export function useFocusableField(
|
|
12
|
+
export function useFocusableField(): FocusableField {
|
|
12
13
|
const field = ref<Field | null>(null);
|
|
13
14
|
const input = computed(() => field.value?.input as HTMLInputElement);
|
|
14
15
|
function focus(): void {
|
|
15
16
|
input?.value.focus();
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
return { field };
|
|
18
|
+
return { field, focus };
|
|
19
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComputedRef, type Ref, computed } from 'vue';
|
|
1
|
+
import { type ComputedRef, type MaybeRefOrGetter, type Ref, computed, toValue } from 'vue';
|
|
2
2
|
import type { RouteLocationRaw } from 'vue-router';
|
|
3
3
|
import { useLink } from 'vue-router';
|
|
4
4
|
|
|
@@ -37,14 +37,15 @@ function useLinkAttrs(href: Ref<string | undefined>): ComputedRef<{
|
|
|
37
37
|
* @param to - The route to link to.
|
|
38
38
|
* @returns A few helpers can be used to link to the given route.
|
|
39
39
|
*/
|
|
40
|
-
export function useRouterLink(
|
|
40
|
+
export function useRouterLink(
|
|
41
|
+
to: MaybeRefOrGetter<RouteLocationRaw | undefined>
|
|
42
|
+
): RouterComposableHelpers {
|
|
41
43
|
// NOTE(mohan): We need to provide a default here or else `useLink` will throw
|
|
42
44
|
// an error.
|
|
43
|
-
const toWithDefault = computed(() => to
|
|
45
|
+
const toWithDefault = computed(() => toValue(to) ?? '');
|
|
44
46
|
const useLinkResult = useLink({ to: toWithDefault });
|
|
45
47
|
const { navigate: _navigate, href: _href } = useLinkResult;
|
|
46
|
-
|
|
47
|
-
const isRouterLink = computed(() => !!to.value);
|
|
48
|
+
const isRouterLink = computed(() => !!toValue(to));
|
|
48
49
|
const href = computed(() => (isRouterLink.value ? _href.value : undefined));
|
|
49
50
|
const linkAttrs = useLinkAttrs(href);
|
|
50
51
|
const navigate = async (event: MouseEvent): Promise<void> => {
|
package/src/icons.ts
ADDED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { InjectionKey, Ref } from 'vue';
|
|
2
2
|
|
|
3
3
|
export const BLOCK = Symbol('block') as InjectionKey<Ref<boolean>>;
|
|
4
|
-
export const LARGE = Symbol('large') as InjectionKey<Ref<boolean>>;
|
|
4
|
+
export const LARGE = Symbol('large') as InjectionKey<Ref<boolean | null>>;
|
|
5
5
|
export const BOUNCE_AMOUNT = Symbol('bounce-amount') as InjectionKey<number>;
|
package/src/styles/_core.scss
CHANGED
|
@@ -312,8 +312,7 @@ $eyebrow: (
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
@mixin link-underline {
|
|
315
|
-
|
|
316
|
-
text-decoration: underline !important;
|
|
315
|
+
text-decoration: underline;
|
|
317
316
|
text-decoration-skip-ink: none;
|
|
318
317
|
text-underline-offset: 3px;
|
|
319
318
|
}
|
package/src/styles/_reset.scss
CHANGED