cja-phoenix 0.3.6 → 0.4.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 (60) hide show
  1. package/README.md +2 -2
  2. package/dist/cja-phoenix.es.js +3081 -3030
  3. package/dist/style.css +1 -1
  4. package/dist/types/components/composite/CheckoutCrossSell.vue.d.ts +24 -31
  5. package/dist/types/components/composite/CheckoutLayout.vue.d.ts +14 -11
  6. package/dist/types/components/composite/CheckoutMilestones.vue.d.ts +13 -10
  7. package/dist/types/components/composite/CjaMenuBar.vue.d.ts +38 -26
  8. package/dist/types/components/composite/FunnelLayout.vue.d.ts +20 -23
  9. package/dist/types/components/composite/FunnelSubmit.vue.d.ts +16 -15
  10. package/dist/types/components/composite/FunnelSummary.vue.d.ts +55 -54
  11. package/dist/types/components/composite/FunnelTitle.vue.d.ts +17 -22
  12. package/dist/types/components/composite/InfoShowcase.vue.d.ts +21 -24
  13. package/dist/types/components/composite/JourneyMacroSteps.vue.d.ts +13 -10
  14. package/dist/types/components/forms/CheckboxInput.vue.d.ts +32 -33
  15. package/dist/types/components/forms/CurrencyInput.vue.d.ts +53 -80
  16. package/dist/types/components/forms/FileInput.vue.d.ts +67 -92
  17. package/dist/types/components/forms/NumberInput.vue.d.ts +48 -63
  18. package/dist/types/components/forms/PhoneInput.vue.d.ts +57 -92
  19. package/dist/types/components/forms/RadioInput.vue.d.ts +38 -53
  20. package/dist/types/components/forms/SelectInput.vue.d.ts +67 -108
  21. package/dist/types/components/forms/SelectionTiles.vue.d.ts +41 -54
  22. package/dist/types/components/forms/TextInput.vue.d.ts +65 -104
  23. package/dist/types/components/forms/TileCheckboxInput.vue.d.ts +20 -31
  24. package/dist/types/components/forms/ToggleInput.vue.d.ts +44 -63
  25. package/dist/types/components/forms/structure/InputContainer.vue.d.ts +14 -9
  26. package/dist/types/components/forms/structure/InputError.vue.d.ts +13 -10
  27. package/dist/types/components/forms/structure/InputTitle.vue.d.ts +17 -22
  28. package/dist/types/components/structural/CjaButton.vue.d.ts +44 -47
  29. package/dist/types/components/structural/CollapseContainer.vue.d.ts +33 -22
  30. package/dist/types/components/structural/ContentTabs.vue.d.ts +17 -20
  31. package/dist/types/components/structural/FixedContainer.vue.d.ts +55 -56
  32. package/dist/types/components/structural/GridContainer.vue.d.ts +26 -11
  33. package/dist/types/components/structural/GridItem.vue.d.ts +18 -21
  34. package/dist/types/components/structural/InfoMessage.vue.d.ts +20 -29
  35. package/dist/types/components/structural/LoadingSpinner.vue.d.ts +16 -15
  36. package/dist/types/components/structural/Modal.vue.d.ts +49 -9
  37. package/package.json +3 -6
  38. package/src/assets/breakpoints.scss +12 -0
  39. package/src/assets/forms.scss +3 -3
  40. package/src/assets/main.scss +1 -0
  41. package/src/components/composite/CheckoutCrossSell.vue +2 -0
  42. package/src/components/composite/CheckoutMilestones.vue +4 -2
  43. package/src/components/composite/CjaMenuBar.vue +130 -64
  44. package/src/components/composite/FunnelLayout.vue +7 -5
  45. package/src/components/composite/FunnelTitle.vue +3 -1
  46. package/src/components/forms/TextInput.vue +16 -0
  47. package/src/components/forms/structure/InputError.vue +3 -1
  48. package/src/components/forms/structure/InputTitle.vue +2 -1
  49. package/src/components/structural/CjaButton.vue +37 -15
  50. package/src/components/structural/GridContainer.vue +2 -1
  51. package/src/components/structural/GridItem.vue +3 -1
  52. package/src/components/structural/InfoMessage.vue +5 -3
  53. package/src/components/structural/Modal.vue +76 -63
  54. package/src/stories/Modal.story.vue +48 -9
  55. package/src/utils/cjaStore.ts +7 -15
  56. package/src/utils/useViewportDetector.ts +2 -2
  57. package/dist/types/histoire.setup.d.ts +0 -2
  58. package/src/histoire.setup.ts +0 -2
  59. /package/src/utils/{GetI18nMessages.ts → getI18nMessages.ts} +0 -0
  60. /package/src/utils/{JsonReviver.ts → jsonReviver.ts} +0 -0
@@ -1,25 +1,65 @@
1
- declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
2
- title: {
3
- type: import("vue").PropType<string>;
1
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
2
+ maxWidth?: {
3
+ md?: string | undefined;
4
+ lg?: string | undefined;
5
+ xl?: string | undefined;
6
+ } | undefined;
7
+ }>, {
8
+ maxWidth: () => {
9
+ md: string;
10
+ lg: string;
11
+ xl: string;
4
12
  };
5
- }, {
13
+ }>, {
6
14
  active: import("vue").Ref<boolean>;
7
15
  openModal: () => void;
8
16
  closeModal: () => void;
9
17
  toggleModal: () => void;
10
- }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "close"[], "close", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
11
- title: {
12
- type: import("vue").PropType<string>;
18
+ }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "close"[], "close", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
19
+ maxWidth?: {
20
+ md?: string | undefined;
21
+ lg?: string | undefined;
22
+ xl?: string | undefined;
23
+ } | undefined;
24
+ }>, {
25
+ maxWidth: () => {
26
+ md: string;
27
+ lg: string;
28
+ xl: string;
13
29
  };
14
- }>> & {
30
+ }>>> & {
15
31
  onClose?: ((...args: any[]) => any) | undefined;
16
- }, {}, {}>, {
32
+ }, {
33
+ maxWidth: {
34
+ md?: string | undefined;
35
+ lg?: string | undefined;
36
+ xl?: string | undefined;
37
+ };
38
+ }, {}>, {
39
+ header?(_: {}): any;
17
40
  body?(_: {}): any;
18
41
  footer?(_: {}): any;
19
42
  }>;
20
43
  export default _default;
44
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
45
+ type __VLS_TypePropsToRuntimeProps<T> = {
46
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
47
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
48
+ } : {
49
+ type: import('vue').PropType<T[K]>;
50
+ required: true;
51
+ };
52
+ };
53
+ type __VLS_WithDefaults<P, D> = {
54
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
55
+ default: D[K];
56
+ }> : P[K];
57
+ };
21
58
  type __VLS_WithTemplateSlots<T, S> = T & {
22
59
  new (): {
23
60
  $slots: S;
24
61
  };
25
62
  };
63
+ type __VLS_Prettify<T> = {
64
+ [K in keyof T]: T[K];
65
+ } & {};
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "cja-phoenix",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "scripts": {
5
5
  "build:dev": "rimraf dist && vue-tsc && vite build -m development",
6
6
  "build:link": "rimraf dist && vue-tsc && vite build -m development && npm link",
7
7
  "build:prod": "rimraf dist && vue-tsc && vite build -m production",
8
8
  "publish:lib": "npm run build:prod && npm publish",
9
- "docs:dev": "vitepress dev docs",
10
9
  "story:dev": "histoire dev",
11
10
  "story:build": "histoire build",
12
11
  "story:preview": "histoire preview"
@@ -23,9 +22,9 @@
23
22
  },
24
23
  "devDependencies": {
25
24
  "@gtm-support/vue-gtm": "^2.0.0",
26
- "@histoire/plugin-vue": "^0.16.1",
27
25
  "@types/node": "^17.0.14",
28
26
  "@vitejs/plugin-vue": "^2.0.0",
27
+ "@histoire/plugin-vue": "^0.16.1",
29
28
  "histoire": "^0.16.2",
30
29
  "intl-tel-input": "^17.0.19",
31
30
  "maska": "^2.1.7",
@@ -35,7 +34,6 @@
35
34
  "typescript": "^4.4.4",
36
35
  "vee-validate": "^4.7.2",
37
36
  "vite": "^3.0.0",
38
- "vitepress": "^0.21.6",
39
37
  "vue": "^3.3.4",
40
38
  "vue-currency-input": "^3.0.5",
41
39
  "vue-i18n": "^9.2.2",
@@ -46,8 +44,7 @@
46
44
  },
47
45
  "files": [
48
46
  "src",
49
- "dist",
50
- "public"
47
+ "dist"
51
48
  ],
52
49
  "types": "./dist/types/index.d.ts",
53
50
  "module": "./dist/cja-phoenix.es.js",
@@ -0,0 +1,12 @@
1
+ $break-xs-max: 419px;
2
+
3
+ $break-sm-min: 420px;
4
+ $break-sm-max: 767px;
5
+
6
+ $break-md-min: 768px;
7
+ $break-md-max: 1023px;
8
+
9
+ $break-lg-min: 1024px;
10
+ $break-lg-max: 1199px;
11
+
12
+ $break-xl-min: 1200px;
@@ -14,10 +14,10 @@ $md-padding-h: 12px;
14
14
  $md-font-size: 16px;
15
15
  $md-line-height: 18px;
16
16
 
17
- $lg-padding-v: 12px;
17
+ $lg-padding-v: 16px;
18
18
  $lg-padding-h: 18px;
19
- $lg-font-size: 16px;
20
- $lg-line-height: 20px;
19
+ $lg-font-size: 18px;
20
+ $lg-line-height: 22px;
21
21
 
22
22
  @mixin input-template {
23
23
  background-color: #fff;
@@ -1,3 +1,4 @@
1
+ @import "breakpoints";
1
2
  @import "fonts";
2
3
 
3
4
  html,
@@ -309,6 +309,8 @@ const submit = () => {
309
309
  </script>
310
310
 
311
311
  <style lang="scss" scoped>
312
+ @import "../../assets/breakpoints.scss";
313
+
312
314
  .cross-sell-container {
313
315
  .cross-sell-wrapper {
314
316
  max-width: 1050px;
@@ -33,6 +33,8 @@ defineProps<{
33
33
  </script>
34
34
 
35
35
  <style lang="scss" scoped>
36
+ @import "../../assets/breakpoints.scss";
37
+
36
38
  .checkout-milestones {
37
39
  ul {
38
40
  list-style: none;
@@ -75,7 +77,7 @@ defineProps<{
75
77
  line-height: 20px;
76
78
  font-weight: 700;
77
79
 
78
- @media screen and (min-width: 768px) {
80
+ @media screen and (min-width: $break-md-min) {
79
81
  font-size: 20px;
80
82
  line-height: 24px;
81
83
  }
@@ -85,7 +87,7 @@ defineProps<{
85
87
  font-size: 14px;
86
88
  line-height: 17px;
87
89
 
88
- @media screen and (min-width: 768px) {
90
+ @media screen and (min-width: $break-md-min) {
89
91
  font-size: 16px;
90
92
  line-height: 19px;
91
93
  }
@@ -19,16 +19,13 @@
19
19
  <slot name="content" v-else-if="$slots.content"></slot>
20
20
  </div>
21
21
 
22
- <div class="side-info" v-if="sideInfo">
23
- <slot name="side">
24
- <div class="contact-container">
25
- <a class="contact" href="tel:211165765">
26
- <span class="m-cgg-icon--phone"></span>
27
- <span class="number">211 165 765</span>
28
- </a>
29
- <div class="time">Seg - Sex: 10h às 19h</div>
30
- </div>
31
- </slot>
22
+ <div class="side-info" v-if="hasSideInfo">
23
+ <slot name="side"></slot>
24
+ <button
25
+ class="contact m-cgg-icon--phone"
26
+ v-if="hasContact"
27
+ @click="callModal.openModal()"
28
+ ></button>
32
29
  </div>
33
30
  </div>
34
31
  <FixedContainer
@@ -40,6 +37,32 @@
40
37
  </FixedContainer>
41
38
  </FixedContainer>
42
39
  </header>
40
+
41
+ <Modal
42
+ ref="callModal"
43
+ v-if="hasContact"
44
+ :maxWidth="{ md: '470px', lg: '470px', xl: '470px' }"
45
+ >
46
+ <template #header>Precisa de ajuda?</template>
47
+ <template #body>
48
+ <div class="call-modal-body">
49
+ <div class="call-info">
50
+ <a class="phone-link" href="tel:211165765">
51
+ <span class="m-cgg-icon--phone"></span>
52
+ <span>211 165 765</span>
53
+ </a>
54
+ <div class="hours-wrapper">Seg - Sex: 10h às 19h</div>
55
+ </div>
56
+ <div class="call-cost">Custo de chamada para a rede fixa nacional</div>
57
+ <div class="btn-container">
58
+ <CjaButton :type="'secondary'" @click="callModal.closeModal()">
59
+ Voltar
60
+ </CjaButton>
61
+ <CjaButton @click="callContact">Ligar</CjaButton>
62
+ </div>
63
+ </div>
64
+ </template>
65
+ </Modal>
43
66
  </template>
44
67
 
45
68
  <script lang="ts" setup>
@@ -47,23 +70,31 @@ import { inject } from "vue";
47
70
  import FixedContainer from "../structural/FixedContainer.vue";
48
71
  import { MacroStep } from "../../types";
49
72
  import JourneyMacroSteps from "./JourneyMacroSteps.vue";
73
+ import Modal from "../structural/Modal.vue";
50
74
  import { ref } from "vue";
51
- import { onMounted } from "vue";
52
- import { provide } from "vue";
75
+ import { CjaButton } from "..";
53
76
 
54
77
  const activeViewport: any = inject("activeViewport");
55
78
  withDefaults(
56
79
  defineProps<{
57
80
  homeNavigationEnabled?: boolean;
58
- sideInfo?: boolean;
81
+ hasSideInfo?: boolean;
59
82
  macroStepList?: MacroStep[];
83
+ hasContact?: boolean;
60
84
  }>(),
61
85
  {
62
86
  homeNavigationEnabled: true,
63
- sideInfo: true,
87
+ hasSideInfo: true,
88
+ hasContact: true,
64
89
  }
65
90
  );
66
91
 
92
+ const callModal = ref();
93
+
94
+ const callContact = () => {
95
+ window.open("tel:211165765", "_self");
96
+ };
97
+
67
98
  const baseImgUrl = process.env.VUE_APP_IMG_URL;
68
99
  </script>
69
100
 
@@ -77,10 +108,9 @@ header.main-header-container {
77
108
  .main-header {
78
109
  position: relative;
79
110
  z-index: 1;
80
- display: flex;
81
- flex-direction: row;
111
+ display: grid;
112
+ grid-template-columns: auto 1fr 265px;
82
113
  align-items: center;
83
- justify-content: space-between;
84
114
  gap: 16px;
85
115
  background-color: #fff;
86
116
  padding: 20px;
@@ -110,57 +140,93 @@ header.main-header-container {
110
140
  }
111
141
 
112
142
  .side-info {
113
- @media screen and (min-width: 1024px) {
114
- display: flex;
115
- align-items: center;
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: flex-end;
146
+
147
+ .contact {
148
+ background: #076b9c;
149
+ width: 20px;
150
+ height: 20px;
151
+ border-radius: 50%;
152
+ padding: 0;
153
+ border: none;
154
+ outline: none;
155
+ gap: 8px;
156
+ font-weight: 700;
157
+ font-size: 10px;
158
+ color: #fff;
116
159
  }
160
+ }
161
+ }
162
+ }
163
+
164
+ .call-modal-body {
165
+ max-width: 400px;
166
+ margin: 0 auto;
167
+ display: flex;
168
+ flex-direction: column;
169
+ align-items: center;
170
+ gap: 16px;
171
+ font-size: 14px;
172
+ line-height: 18px;
173
+
174
+ @media screen and (min-width: 420px) {
175
+ font-size: 16px;
176
+ line-height: 20px;
177
+ }
117
178
 
118
- .contact-container {
179
+ .call-info {
180
+ display: flex;
181
+ flex-direction: row;
182
+ align-items: center;
183
+ white-space: nowrap;
184
+
185
+ a {
186
+ display: flex;
187
+ flex-direction: row;
188
+ gap: 8px;
189
+ align-items: center;
190
+ color: inherit;
191
+
192
+ .m-cgg-icon--phone {
193
+ background-color: #076b9c;
194
+ height: 20px;
195
+ width: 20px;
119
196
  display: flex;
197
+ flex-direction: row;
120
198
  align-items: center;
121
- gap: 15px;
122
-
123
- .contact {
124
- display: flex;
125
- align-items: center;
126
- gap: 8px;
127
- font-weight: 700;
128
- font-size: 14px;
129
- line-height: 17px;
130
- color: inherit;
131
-
132
- &:hover {
133
- text-decoration: none;
134
- }
135
-
136
- .m-cgg-icon--phone {
137
- display: flex;
138
- justify-content: center;
139
- align-items: center;
140
- width: 20px;
141
- height: 20px;
142
- border-radius: 50%;
143
- background-color: #076b9c;
144
- color: #fff;
145
- font-size: 10px;
146
- }
147
-
148
- .number {
149
- display: none;
150
-
151
- @media screen and (min-width: 768px) {
152
- display: block;
153
- }
154
- }
155
- }
156
-
157
- .time {
158
- display: none;
159
-
160
- @media screen and (min-width: 768px) {
161
- display: block;
162
- }
163
- }
199
+ justify-content: center;
200
+ color: #fff;
201
+ border-radius: 50%;
202
+ font-size: 9px;
203
+ }
204
+ }
205
+
206
+ .hours-wrapper {
207
+ padding-left: 10px;
208
+ margin-left: 10px;
209
+ border-left: 1px solid #dedede;
210
+
211
+ @media screen and (min-width: 420px) {
212
+ padding-left: 15px;
213
+ margin-left: 15px;
214
+ }
215
+ }
216
+ }
217
+
218
+ .call-cost {
219
+ text-align: center;
220
+ }
221
+
222
+ .btn-container {
223
+ display: flex;
224
+ flex-direction: row;
225
+ gap: 16px;
226
+
227
+ .btn-cancel {
228
+ @media screen and (max-width: 419px) {
229
+ display: none;
164
230
  }
165
231
  }
166
232
  }
@@ -71,6 +71,8 @@ defineEmits(["btn:previous"]);
71
71
  </script>
72
72
 
73
73
  <style lang="scss" scoped>
74
+ @import "../../assets/breakpoints.scss";
75
+
74
76
  .funnel-container {
75
77
  padding-bottom: 100px;
76
78
 
@@ -106,7 +108,7 @@ defineEmits(["btn:previous"]);
106
108
  padding: 20px 0;
107
109
  overflow: hidden;
108
110
 
109
- @media screen and (min-width: 768px) {
111
+ @media screen and (min-width: $break-md-min) {
110
112
  padding: 30px 0;
111
113
  }
112
114
 
@@ -126,7 +128,7 @@ defineEmits(["btn:previous"]);
126
128
  align-items: center;
127
129
  margin-bottom: 30px;
128
130
 
129
- @media screen and (min-width: 768px) {
131
+ @media screen and (min-width: $break-md-min) {
130
132
  gap: 20px;
131
133
  grid-template-columns: 90px 1fr 90px;
132
134
  padding-bottom: 20px;
@@ -136,7 +138,7 @@ defineEmits(["btn:previous"]);
136
138
  .back-container {
137
139
  grid-area: 2 / 1 / 3 / 2;
138
140
 
139
- @media screen and (min-width: 768px) {
141
+ @media screen and (min-width: $break-md-min) {
140
142
  grid-area: 1 / 1 / 2 / 2;
141
143
  }
142
144
 
@@ -164,7 +166,7 @@ defineEmits(["btn:previous"]);
164
166
  height: 16px;
165
167
  border-radius: 30px;
166
168
 
167
- @media screen and (min-width: 768px) {
169
+ @media screen and (min-width: $break-md-min) {
168
170
  grid-area: 1 / 2 / 2 / 3;
169
171
  }
170
172
 
@@ -186,7 +188,7 @@ defineEmits(["btn:previous"]);
186
188
  line-height: 14px;
187
189
  color: #155072;
188
190
 
189
- @media screen and (min-width: 768px) {
191
+ @media screen and (min-width: $break-md-min) {
190
192
  grid-area: 1 / 3 / 2 / 4;
191
193
  }
192
194
  }
@@ -21,6 +21,8 @@ defineProps<{
21
21
  </script>
22
22
 
23
23
  <style lang="scss" scoped>
24
+ @import "../../assets/breakpoints.scss";
25
+
24
26
  .title-container {
25
27
  text-align: center;
26
28
  margin-bottom: 25px;
@@ -36,7 +38,7 @@ defineProps<{
36
38
  margin-bottom: 20px;
37
39
  color: #076b9c;
38
40
 
39
- @media screen and (min-width: 768px) {
41
+ @media screen and (min-width: $break-md-min) {
40
42
  font-size: 26px;
41
43
  line-height: 30px;
42
44
  }
@@ -17,6 +17,8 @@
17
17
  :placeholder="placeholder && placeholder"
18
18
  :type="type"
19
19
  :value="value"
20
+ :min="min"
21
+ :max="max"
20
22
  @input="
21
23
  emit('update:modelValue', (<HTMLInputElement>$event.target).value)
22
24
  "
@@ -59,6 +61,8 @@ const props = withDefaults(
59
61
  type?: InputHTMLAttributes["type"];
60
62
  autocomplete?: InputHTMLAttributes["autocomplete"];
61
63
  suffix?: string;
64
+ min?: InputHTMLAttributes["min"];
65
+ max?: InputHTMLAttributes["max"];
62
66
  }>(),
63
67
  {
64
68
  layout: "vertical",
@@ -106,6 +110,18 @@ const emit = defineEmits(["update:modelValue"]);
106
110
  color: #0d2745;
107
111
  }
108
112
  }
113
+
114
+ &[type="number"] {
115
+ /* Firefox */
116
+ -moz-appearance: textfield;
117
+
118
+ /* Chrome, Safari, Edge, Opera */
119
+ &::-webkit-outer-spin-button,
120
+ &::-webkit-inner-spin-button {
121
+ -webkit-appearance: none;
122
+ margin: 0;
123
+ }
124
+ }
109
125
  }
110
126
 
111
127
  &.error {
@@ -11,12 +11,14 @@ defineProps<{
11
11
  </script>
12
12
 
13
13
  <style lang="scss" scoped>
14
+ @import "../../../assets/breakpoints.scss";
15
+
14
16
  .input-error {
15
17
  color: #ff533f;
16
18
  font-size: 14px;
17
19
  line-height: 16px;
18
20
 
19
- @media screen and (min-width: 768px) {
21
+ @media screen and (min-width: $break-md-min) {
20
22
  font-size: 16px;
21
23
  line-height: 18px;
22
24
  }
@@ -18,6 +18,7 @@ defineProps<{
18
18
  </script>
19
19
 
20
20
  <style lang="scss" scoped>
21
+ @import "../../../assets/breakpoints.scss";
21
22
  @import "../../../assets/forms.scss";
22
23
 
23
24
  .input-title {
@@ -32,7 +33,7 @@ defineProps<{
32
33
  font-size: 18px;
33
34
  color: #076b9c;
34
35
 
35
- @media screen and (min-width: 768px) {
36
+ @media screen and (min-width: $break-md-min) {
36
37
  font-size: 20px;
37
38
  }
38
39
  }
@@ -1,6 +1,7 @@
1
1
  <template>
2
- <button
2
+ <component
3
3
  class="cja-btn"
4
+ :is="href ? 'a' : 'button'"
4
5
  :class="[
5
6
  `btn-${type}`,
6
7
  `btn-size-${size}`,
@@ -10,11 +11,11 @@
10
11
  ]"
11
12
  >
12
13
  <Scaffold v-if="!loading">
13
- <span v-if="$slots.default"><slot></slot></span>
14
- <span v-if="icon" :class="icon"></span>
14
+ <slot></slot>
15
+ <span v-if="icon" class="icon" :class="icon"></span>
15
16
  </Scaffold>
16
17
  <div class="spinner" v-else></div>
17
- </button>
18
+ </component>
18
19
  </template>
19
20
 
20
21
  <script lang="ts" setup>
@@ -28,6 +29,7 @@ withDefaults(
28
29
  icon?: string;
29
30
  iconPosition?: "left" | "right";
30
31
  loading?: boolean;
32
+ href?: string;
31
33
  }>(),
32
34
  {
33
35
  type: "primary",
@@ -42,11 +44,7 @@ withDefaults(
42
44
  @import "../../assets/shadows.scss";
43
45
 
44
46
  .cja-btn {
45
- display: inline-flex;
46
- flex-direction: row;
47
- justify-content: center;
48
- align-items: center;
49
- gap: 10px;
47
+ display: inline-block;
50
48
  font-weight: 700;
51
49
  cursor: pointer;
52
50
  transition: all 0.2s ease-in-out;
@@ -63,15 +61,27 @@ withDefaults(
63
61
  box-shadow: none;
64
62
  }
65
63
 
64
+ span {
65
+ vertical-align: middle;
66
+ }
67
+
66
68
  &.btn-size-sm {
67
69
  font-size: 14px;
68
70
  line-height: 18px;
69
71
  padding: 8px 12px;
70
72
  border-radius: 8px;
71
73
 
74
+ &.icon-left:not(.btn-icon-only) span {
75
+ margin-right: 8px;
76
+ }
77
+
78
+ &.icon-right:not(.btn-icon-only) span {
79
+ margin-left: 8px;
80
+ }
81
+
72
82
  &.btn-icon-only,
73
83
  &.btn-loading {
74
- padding: 4px;
84
+ padding: 4px 10px;
75
85
  }
76
86
 
77
87
  &.btn-loading .spinner {
@@ -86,9 +96,17 @@ withDefaults(
86
96
  padding: 8px 24px;
87
97
  border-radius: 8px;
88
98
 
99
+ &.icon-left:not(.btn-icon-only) span {
100
+ margin-right: 8px;
101
+ }
102
+
103
+ &.icon-right:not(.btn-icon-only) span {
104
+ margin-left: 8px;
105
+ }
106
+
89
107
  &.btn-icon-only,
90
108
  &.btn-loading {
91
- padding: 8px;
109
+ padding: 8px 12px;
92
110
  }
93
111
 
94
112
  &.btn-loading .spinner {
@@ -103,6 +121,14 @@ withDefaults(
103
121
  padding: 16px 32px;
104
122
  border-radius: 8px;
105
123
 
124
+ &.icon-left:not(.btn-icon-only) span {
125
+ margin-right: 12px;
126
+ }
127
+
128
+ &.icon-right:not(.btn-icon-only) span {
129
+ margin-left: 12px;
130
+ }
131
+
106
132
  &.btn-icon-only,
107
133
  &.btn-loading {
108
134
  padding: 16px;
@@ -291,10 +317,6 @@ withDefaults(
291
317
  }
292
318
  }
293
319
 
294
- &.icon-left {
295
- flex-direction: row-reverse;
296
- }
297
-
298
320
  &.btn-loading {
299
321
  cursor: auto;
300
322