@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.
- package/README.md +51 -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} +40 -2
- 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 +11 -4
- 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/styles/main.scss +2 -0
- package/src/types.ts +2 -0
- package/dist/index.cdn.css +0 -1
- package/dist/styles/utils.css +0 -2709
package/src/components/CForm.vue
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
</form>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
|
-
<script lang="ts">
|
|
7
|
+
<script setup lang="ts">
|
|
8
8
|
import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed';
|
|
9
|
-
import {
|
|
9
|
+
import type { VNode } from 'vue';
|
|
10
|
+
import { computed, onMounted, provide, ref, watch } from 'vue';
|
|
10
11
|
|
|
11
12
|
import { VALIDATIONS } from '@propelinc/citrus-ui/src/services/injections/forms';
|
|
12
13
|
import type { ValidationState } from '@propelinc/citrus-ui/src/types/CForm';
|
|
@@ -18,69 +19,75 @@ interface FormValidation {
|
|
|
18
19
|
field?: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setup(_, { expose, emit }) {
|
|
30
|
-
const form = ref<HTMLFormElement | null>(null);
|
|
31
|
-
const inputs = ref<Record<string, FormValidation>>({});
|
|
32
|
-
|
|
33
|
-
provide(VALIDATIONS, {
|
|
34
|
-
register: (input: ValidationState) => {
|
|
35
|
-
// NOTE(ram): Vue collapses the ref to input.field automatically so we need to adjust types.
|
|
36
|
-
inputs.value = { ...inputs.value, [input.id]: input as unknown as FormValidation };
|
|
37
|
-
},
|
|
38
|
-
unregister: (id: string) => {
|
|
39
|
-
const filteredInputs = { ...inputs.value };
|
|
40
|
-
delete filteredInputs[id];
|
|
41
|
-
inputs.value = filteredInputs;
|
|
42
|
-
},
|
|
43
|
-
});
|
|
22
|
+
withDefaults(
|
|
23
|
+
defineProps<{
|
|
24
|
+
dataTest?: string;
|
|
25
|
+
}>(),
|
|
26
|
+
{
|
|
27
|
+
dataTest: 'form',
|
|
28
|
+
}
|
|
29
|
+
);
|
|
44
30
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
};
|
|
31
|
+
const emit = defineEmits<{
|
|
32
|
+
submit: [event: Event];
|
|
33
|
+
input: [value: boolean];
|
|
34
|
+
}>();
|
|
51
35
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
watch(getInvalidInputs, (newInvalidInputs, oldInvalidInputs) => {
|
|
56
|
-
const newValid = newInvalidInputs.length === 0;
|
|
57
|
-
const oldValid = oldInvalidInputs?.length === 0;
|
|
58
|
-
if (newValid !== oldValid) {
|
|
59
|
-
emit('input', newValid);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
onMounted(() => emit('input', getInvalidInputs().length === 0));
|
|
36
|
+
defineSlots<{
|
|
37
|
+
default?: () => VNode[];
|
|
38
|
+
}>();
|
|
63
39
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
40
|
+
const form = ref<HTMLFormElement | null>(null);
|
|
41
|
+
const inputs = ref<Record<string, FormValidation>>({});
|
|
68
42
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
43
|
+
provide(VALIDATIONS, {
|
|
44
|
+
register: (input: ValidationState) => {
|
|
45
|
+
// NOTE(ram): Vue collapses the ref to input.field automatically so we need to adjust types.
|
|
46
|
+
inputs.value = { ...inputs.value, [input.id]: input as unknown as FormValidation };
|
|
47
|
+
},
|
|
48
|
+
unregister: (id: string) => {
|
|
49
|
+
const filteredInputs = { ...inputs.value };
|
|
50
|
+
delete filteredInputs[id];
|
|
51
|
+
inputs.value = filteredInputs;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
78
54
|
|
|
79
|
-
|
|
80
|
-
|
|
55
|
+
const inputArray = computed(() => Object.values(inputs.value));
|
|
56
|
+
const getInvalidInputs = (startValidating?: boolean): FormValidation[] => {
|
|
57
|
+
return inputArray.value.filter((input) => {
|
|
58
|
+
return startValidating ? !input.validate() : !input.valid;
|
|
59
|
+
});
|
|
60
|
+
};
|
|
81
61
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
62
|
+
// NOTE(mohan): I would love for this to be a computed property, but Vue 2's
|
|
63
|
+
// the reactivity system can't seem to track refs inside of refs, though it
|
|
64
|
+
// should work in Vue 3.
|
|
65
|
+
watch(getInvalidInputs, (newInvalidInputs, oldInvalidInputs) => {
|
|
66
|
+
const newValid = newInvalidInputs.length === 0;
|
|
67
|
+
const oldValid = oldInvalidInputs?.length === 0;
|
|
68
|
+
if (newValid !== oldValid) {
|
|
69
|
+
emit('input', newValid);
|
|
70
|
+
}
|
|
85
71
|
});
|
|
72
|
+
onMounted(() => emit('input', getInvalidInputs().length === 0));
|
|
73
|
+
|
|
74
|
+
const validate = (): boolean => {
|
|
75
|
+
if (!form.value) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const invalidInputs = getInvalidInputs(true);
|
|
80
|
+
const firstInvalidField = invalidInputs.find((input) => input.field)?.field;
|
|
81
|
+
if (firstInvalidField) {
|
|
82
|
+
scrollIntoViewIfNeeded(firstInvalidField, {
|
|
83
|
+
behavior: 'smooth',
|
|
84
|
+
block: 'center',
|
|
85
|
+
scrollMode: 'if-needed',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return invalidInputs.length === 0;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
defineExpose({ validate, inputs: inputArray });
|
|
86
93
|
</script>
|
|
@@ -2,39 +2,36 @@
|
|
|
2
2
|
<div>{{ displayText }}</div>
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
import
|
|
7
|
-
import { computed, defineComponent } from 'vue';
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { computed } from 'vue';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
props: {
|
|
8
|
+
const props = withDefaults(
|
|
9
|
+
defineProps<{
|
|
12
10
|
/** Sets the denominator of the counter. */
|
|
13
|
-
counter
|
|
11
|
+
counter?: number | null;
|
|
14
12
|
/** Function or number that determines the numerator of the counter. */
|
|
15
|
-
counterValue
|
|
16
|
-
type: [Number, Function] as PropType<number | (() => number | null)>,
|
|
17
|
-
default: null,
|
|
18
|
-
},
|
|
13
|
+
counterValue?: number | (() => number | null) | null;
|
|
19
14
|
/** Input value of the parent form field */
|
|
20
|
-
value
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} else {
|
|
29
|
-
return props.value.length;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
15
|
+
value?: string;
|
|
16
|
+
}>(),
|
|
17
|
+
{
|
|
18
|
+
counter: null,
|
|
19
|
+
counterValue: null,
|
|
20
|
+
value: '',
|
|
21
|
+
}
|
|
22
|
+
);
|
|
32
23
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
const numerator = computed(() => {
|
|
25
|
+
if (typeof props.counterValue === 'function') {
|
|
26
|
+
return props.counterValue();
|
|
27
|
+
} else if (typeof props.counterValue === 'number') {
|
|
28
|
+
return props.counterValue;
|
|
29
|
+
} else {
|
|
30
|
+
return props.value.length;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
}
|
|
34
|
+
const displayText = computed(() => {
|
|
35
|
+
return `${numerator.value}/${props.counter}`;
|
|
39
36
|
});
|
|
40
37
|
</script>
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
</CButton>
|
|
41
41
|
</template>
|
|
42
42
|
|
|
43
|
-
<script lang="ts">
|
|
43
|
+
<script setup lang="ts">
|
|
44
44
|
import type { IconDefinition } from '@fortawesome/pro-light-svg-icons';
|
|
45
45
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
|
46
|
-
import type {
|
|
47
|
-
import { computed,
|
|
46
|
+
import type { VNode } from 'vue';
|
|
47
|
+
import { computed, inject, provide } from 'vue';
|
|
48
48
|
import type { RouteLocationRaw } from 'vue-router';
|
|
49
49
|
|
|
50
50
|
import CButton from '@propelinc/citrus-ui/src/components/CButton/CButton.vue';
|
|
@@ -57,105 +57,124 @@ import { useA11yLabelCheck } from '@propelinc/citrus-ui/src/composables/accessib
|
|
|
57
57
|
import { BOUNCE_AMOUNT } from '@propelinc/citrus-ui/src/services/injections/buttons';
|
|
58
58
|
import { INHERIT_COLOR, TERTIARY } from '@propelinc/citrus-ui/src/services/injections/icon-buttons';
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
props: {
|
|
60
|
+
const props = withDefaults(
|
|
61
|
+
defineProps<{
|
|
63
62
|
/** ARIA label for the button. You must use either this or ariaLabelledby. */
|
|
64
|
-
ariaLabel
|
|
63
|
+
ariaLabel?: string;
|
|
65
64
|
/** ARIA labelledby for the button. You must use either this or ariaLabel. */
|
|
66
|
-
ariaLabelledby
|
|
65
|
+
ariaLabelledby?: string;
|
|
67
66
|
/** Controls whether button is disabled */
|
|
68
|
-
disabled
|
|
67
|
+
disabled?: boolean;
|
|
69
68
|
/** Designates the button as an anchor and applies the href attribute */
|
|
70
|
-
href
|
|
69
|
+
href?: string;
|
|
71
70
|
/** Specifies a Font Awesome icon */
|
|
72
|
-
icon
|
|
73
|
-
type: [String, Array, Object] as PropType<string | string[] | IconDefinition>,
|
|
74
|
-
default: undefined,
|
|
75
|
-
},
|
|
71
|
+
icon?: string | string[] | IconDefinition;
|
|
76
72
|
/**
|
|
77
73
|
* Controls whether button uses the large variant
|
|
78
74
|
* @deprecated Use `size="large"` instead
|
|
79
75
|
*/
|
|
80
|
-
large
|
|
76
|
+
large?: boolean;
|
|
81
77
|
/**
|
|
82
78
|
* Controls the level of the button
|
|
83
79
|
* @default 'normal'
|
|
84
80
|
*/
|
|
85
|
-
level
|
|
81
|
+
level?: ButtonLevel;
|
|
86
82
|
/** Controls whether button is loading */
|
|
87
|
-
loading
|
|
83
|
+
loading?: boolean;
|
|
88
84
|
/**
|
|
89
85
|
* Controls whether button uses the secondary variant
|
|
90
86
|
* @deprecated Use `variant="secondary"` instead
|
|
91
87
|
*/
|
|
92
|
-
secondary
|
|
88
|
+
secondary?: boolean;
|
|
93
89
|
/**
|
|
94
90
|
* Controls the size of the button
|
|
95
91
|
* @default 'medium'
|
|
96
92
|
*/
|
|
97
|
-
size
|
|
93
|
+
size?: ButtonSize;
|
|
98
94
|
/** Spins the icon for loading states */
|
|
99
|
-
spinIcon
|
|
95
|
+
spinIcon?: boolean;
|
|
100
96
|
/** Designates the target attribute. Only use with the href prop. */
|
|
101
|
-
target
|
|
97
|
+
target?: string;
|
|
102
98
|
/**
|
|
103
99
|
* Controls whether button uses the tertiary variant
|
|
104
100
|
* @deprecated Use `variant="tertiary"` instead
|
|
105
101
|
*/
|
|
106
|
-
tertiary
|
|
102
|
+
tertiary?: boolean;
|
|
107
103
|
/** Controls whether button functions as a router-link */
|
|
108
|
-
to
|
|
104
|
+
to?: RouteLocationRaw;
|
|
109
105
|
/**
|
|
110
106
|
* Controls the variant of the button
|
|
111
107
|
* @default 'primary'
|
|
112
108
|
*/
|
|
113
|
-
variant
|
|
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
|
-
|
|
109
|
+
variant?: ButtonVariant;
|
|
110
|
+
}>(),
|
|
111
|
+
{
|
|
112
|
+
ariaLabel: undefined,
|
|
113
|
+
ariaLabelledby: undefined,
|
|
114
|
+
disabled: false,
|
|
115
|
+
href: undefined,
|
|
116
|
+
icon: undefined,
|
|
117
|
+
large: false,
|
|
118
|
+
level: 'normal',
|
|
119
|
+
loading: false,
|
|
120
|
+
secondary: false,
|
|
121
|
+
size: 'medium',
|
|
122
|
+
spinIcon: false,
|
|
123
|
+
target: undefined,
|
|
124
|
+
tertiary: false,
|
|
125
|
+
to: undefined,
|
|
126
|
+
variant: 'primary',
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
defineEmits<{
|
|
131
|
+
blur: [event: Event];
|
|
132
|
+
click: [event: MouseEvent];
|
|
133
|
+
focus: [event: Event];
|
|
134
|
+
}>();
|
|
135
|
+
|
|
136
|
+
defineSlots<{
|
|
137
|
+
default?: () => VNode[];
|
|
138
|
+
}>();
|
|
139
|
+
|
|
140
|
+
useA11yLabelCheck('CIconButton', props);
|
|
141
|
+
|
|
142
|
+
const injectedTertiary = inject(TERTIARY, undefined);
|
|
143
|
+
const injectedOrPropTertiary = computed(() => injectedTertiary?.value ?? props.tertiary);
|
|
144
|
+
/**
|
|
145
|
+
* Handle the `variant` prop. `secondary` and `tertiary` are deprecated, but because we set a
|
|
146
|
+
* default `variant`, we need to give them precedence.
|
|
147
|
+
*
|
|
148
|
+
* This is slightly different than the implementation of `computedVariant` in CButton, as
|
|
149
|
+
* `CButton` does not make use of an injected `TERTIARY` value.
|
|
150
|
+
*/
|
|
151
|
+
const computedVariant = computed((): ButtonVariant => {
|
|
152
|
+
if (props.secondary) {
|
|
153
|
+
return 'secondary';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (injectedOrPropTertiary.value) {
|
|
157
|
+
return 'tertiary';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return props.variant;
|
|
161
|
+
});
|
|
148
162
|
|
|
149
|
-
|
|
150
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Handle the `size` prop. `large` is deprecated, but because we set a default `size`, we need
|
|
165
|
+
* to give it precedence.
|
|
166
|
+
*/
|
|
167
|
+
const computedSize = computed((): ButtonSize => {
|
|
168
|
+
if (props.large) {
|
|
169
|
+
return 'large';
|
|
170
|
+
}
|
|
151
171
|
|
|
152
|
-
|
|
172
|
+
return props.size;
|
|
173
|
+
});
|
|
153
174
|
|
|
154
|
-
|
|
175
|
+
const inheritColor = inject(INHERIT_COLOR, undefined);
|
|
155
176
|
|
|
156
|
-
|
|
157
|
-
},
|
|
158
|
-
});
|
|
177
|
+
provide(BOUNCE_AMOUNT, 0.9);
|
|
159
178
|
</script>
|
|
160
179
|
|
|
161
180
|
<style lang="scss" scoped>
|
|
@@ -9,24 +9,30 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
|
-
<script lang="ts">
|
|
12
|
+
<script setup lang="ts">
|
|
13
13
|
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
14
14
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
|
15
|
-
import type {
|
|
16
|
-
import { defineComponent } from 'vue';
|
|
15
|
+
import type { VNode } from 'vue';
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
props: {
|
|
17
|
+
withDefaults(
|
|
18
|
+
defineProps<{
|
|
21
19
|
/** Specifies the label's icon, overwritten if icon slot is used */
|
|
22
|
-
icon
|
|
23
|
-
type: [Array, String, Object] as PropType<string | string[] | IconDefinition>,
|
|
24
|
-
default: null,
|
|
25
|
-
},
|
|
20
|
+
icon?: string | string[] | IconDefinition | null;
|
|
26
21
|
/** A custom data test string */
|
|
27
|
-
dataTest
|
|
28
|
-
},
|
|
29
|
-
|
|
22
|
+
dataTest?: string;
|
|
23
|
+
}>(),
|
|
24
|
+
{
|
|
25
|
+
icon: null,
|
|
26
|
+
dataTest: 'label',
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
defineSlots<{
|
|
31
|
+
/** Icon slot, overrides icon prop */
|
|
32
|
+
icon?: () => VNode[];
|
|
33
|
+
/** Default content */
|
|
34
|
+
default?: () => VNode[];
|
|
35
|
+
}>();
|
|
30
36
|
</script>
|
|
31
37
|
|
|
32
38
|
<style lang="scss" scoped>
|
|
@@ -51,92 +51,93 @@
|
|
|
51
51
|
</component>
|
|
52
52
|
</template>
|
|
53
53
|
|
|
54
|
-
<script lang="ts">
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
55
56
|
import { faChevronRight } from '@fortawesome/pro-regular-svg-icons';
|
|
56
57
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
|
57
|
-
import {
|
|
58
|
+
import { computed, mergeProps, toRefs, useAttrs } from 'vue';
|
|
58
59
|
import type { RouteLocationRaw } from 'vue-router';
|
|
59
60
|
|
|
60
61
|
import CListItemContent from '@propelinc/citrus-ui/src/components/CListItemContent.vue';
|
|
61
62
|
import CListItemIcon from '@propelinc/citrus-ui/src/components/CListItemIcon.vue';
|
|
62
63
|
import { useRouterLink } from '@propelinc/citrus-ui/src/composables/router';
|
|
63
64
|
import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
|
|
64
|
-
import type { FaPropType } from '@propelinc/citrus-ui/src/types/font-awesome';
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
props: {
|
|
66
|
+
const props = withDefaults(
|
|
67
|
+
defineProps<{
|
|
69
68
|
/** The Font Awesome icon to display */
|
|
70
|
-
icon
|
|
69
|
+
icon?: string | string[] | IconDefinition | null;
|
|
71
70
|
/** The icon to display on the right side for clickable items, defaulting to right arrow */
|
|
72
|
-
actionIcon
|
|
71
|
+
actionIcon?: string | string[] | IconDefinition | null;
|
|
73
72
|
/** Color of the icon background */
|
|
74
|
-
iconColor
|
|
73
|
+
iconColor?: string;
|
|
75
74
|
/** Emphasized text above body text. Overridden by the default slot. */
|
|
76
|
-
title
|
|
75
|
+
title?: string;
|
|
77
76
|
/** Plain body copy. Overridden by the default slot. */
|
|
78
|
-
label
|
|
77
|
+
label?: string;
|
|
79
78
|
/** Router location for links within the app */
|
|
80
|
-
to
|
|
79
|
+
to?: RouteLocationRaw;
|
|
81
80
|
/** HTML target attribute for links to outside the app */
|
|
82
|
-
target
|
|
81
|
+
target?: string;
|
|
83
82
|
/** Location for links to outside the app */
|
|
84
|
-
href
|
|
83
|
+
href?: string;
|
|
85
84
|
/** Changes alignment of icon and action icon */
|
|
86
|
-
align
|
|
85
|
+
align?: 'top' | 'center';
|
|
87
86
|
/** Overrides default behavior to display a chevron in the action slot */
|
|
88
|
-
hideAction
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
return {
|
|
129
|
-
allAttrs,
|
|
130
|
-
faChevronRight,
|
|
131
|
-
iconSlotHasContent,
|
|
132
|
-
isTappable,
|
|
133
|
-
navigate,
|
|
134
|
-
renderActionSlot,
|
|
135
|
-
routerDestinationOrHref,
|
|
136
|
-
tag,
|
|
137
|
-
};
|
|
138
|
-
},
|
|
87
|
+
hideAction?: boolean;
|
|
88
|
+
}>(),
|
|
89
|
+
{
|
|
90
|
+
icon: null,
|
|
91
|
+
actionIcon: null,
|
|
92
|
+
iconColor: 'gray-100',
|
|
93
|
+
title: undefined,
|
|
94
|
+
label: undefined,
|
|
95
|
+
to: undefined,
|
|
96
|
+
target: undefined,
|
|
97
|
+
href: undefined,
|
|
98
|
+
align: 'center',
|
|
99
|
+
hideAction: false,
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const attrs = useAttrs();
|
|
104
|
+
|
|
105
|
+
const { to } = toRefs(props);
|
|
106
|
+
const { href: routerDestination, navigate } = useRouterLink(to);
|
|
107
|
+
const routerDestinationOrHref = computed(() => routerDestination.value ?? props.href);
|
|
108
|
+
|
|
109
|
+
const isLink = computed(() => !!routerDestinationOrHref.value);
|
|
110
|
+
const isButton = computed(() => !!attrs.onClick);
|
|
111
|
+
const isTappable = computed(() => isLink.value || isButton.value);
|
|
112
|
+
|
|
113
|
+
const tag = computed(() => {
|
|
114
|
+
if (isLink.value) {
|
|
115
|
+
return 'a';
|
|
116
|
+
} else if (isButton.value) {
|
|
117
|
+
return 'button';
|
|
118
|
+
} else {
|
|
119
|
+
return 'div';
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const tagAttrs = computed(() => {
|
|
123
|
+
if (isButton.value) {
|
|
124
|
+
return { type: 'button' };
|
|
125
|
+
}
|
|
126
|
+
return {};
|
|
139
127
|
});
|
|
128
|
+
|
|
129
|
+
const actionSlotHasContent = useSlotHasContent('action');
|
|
130
|
+
|
|
131
|
+
const renderActionSlot = computed(() => {
|
|
132
|
+
if (props.hideAction) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return isTappable.value || actionSlotHasContent.value;
|
|
137
|
+
});
|
|
138
|
+
const iconSlotHasContent = useSlotHasContent('icon');
|
|
139
|
+
|
|
140
|
+
const allAttrs = computed(() => mergeProps(attrs, tagAttrs.value));
|
|
140
141
|
</script>
|
|
141
142
|
|
|
142
143
|
<style lang="scss" scoped>
|
|
@@ -19,24 +19,22 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
|
-
<script lang="ts">
|
|
23
|
-
import { defineComponent } from 'vue';
|
|
24
|
-
|
|
22
|
+
<script setup lang="ts">
|
|
25
23
|
import { useSlotHasContent } from '@propelinc/citrus-ui/src/composables/slots';
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
withDefaults(
|
|
26
|
+
defineProps<{
|
|
27
|
+
title?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
}>(),
|
|
30
|
+
{
|
|
31
|
+
title: '',
|
|
32
|
+
label: '',
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const titleSlotHasContent = useSlotHasContent('title');
|
|
37
|
+
const labelSlotHasContent = useSlotHasContent('label');
|
|
40
38
|
</script>
|
|
41
39
|
|
|
42
40
|
<style lang="scss" scoped>
|