@citizenplane/pimp 8.26.0 → 8.27.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 (150) hide show
  1. package/dist/{IconAccompaniedMinorEach-DDeSlaA_.js → IconAccompaniedMinorEach-BJYaPpW3.js} +1 -1
  2. package/dist/{IconAccompaniedMinorNone-BKs1gk1K.js → IconAccompaniedMinorNone-D1JR2Qpd.js} +1 -1
  3. package/dist/{IconAccompaniedMinorOne-CpL8FNve.js → IconAccompaniedMinorOne-BJ3jzEDZ.js} +1 -1
  4. package/dist/{IconAddReceipt-DLH3pqjA.js → IconAddReceipt-BX_va94f.js} +1 -1
  5. package/dist/{IconAirportTerminal-Cc4CU6MC.js → IconAirportTerminal-Dzr98nfc.js} +1 -1
  6. package/dist/{IconArrival-CdtUsRVo.js → IconArrival-Ced9HrJH.js} +1 -1
  7. package/dist/{IconBroadcast-QjMZtFA9.js → IconBroadcast-BYX44Wak.js} +1 -1
  8. package/dist/{IconCabinBag-xVC6mOQF.js → IconCabinBag-D1Qs952U.js} +1 -1
  9. package/dist/{IconCheckedBaggage-I_1h49TJ.js → IconCheckedBaggage-Q4_SQL9l.js} +1 -1
  10. package/dist/{IconCheckedBaggage20-CyPcsqrn.js → IconCheckedBaggage20-DVH1-A0V.js} +1 -1
  11. package/dist/{IconCheckedBaggage30-s5htbUIA.js → IconCheckedBaggage30-DYOAf-7Z.js} +1 -1
  12. package/dist/{IconChild-DL43kbm1.js → IconChild-BeCLAr8Y.js} +1 -1
  13. package/dist/{IconContact-FdhTr03q.js → IconContact-B3r39fyI.js} +1 -1
  14. package/dist/{IconDeparture-DNR3OGPD.js → IconDeparture-BflKZUiE.js} +1 -1
  15. package/dist/{IconDistribution-Cl8L6177.js → IconDistribution-CBxQ7UWb.js} +1 -1
  16. package/dist/{IconDistributionClosed-DBT6wR78.js → IconDistributionClosed-BWp_k24K.js} +1 -1
  17. package/dist/{IconDistributionExclusivePair-CkRG6yNV.js → IconDistributionExclusivePair-erLbcLps.js} +1 -1
  18. package/dist/{IconDistributionSided-D_wdvDNf.js → IconDistributionSided-y000n4qB.js} +1 -1
  19. package/dist/{IconDistributionSupplySided-C3VcE8Dw.js → IconDistributionSupplySided-7kCvGwnz.js} +1 -1
  20. package/dist/{IconDynamicContent-Ct1HRd3s.js → IconDynamicContent-SwBxkPMB.js} +1 -1
  21. package/dist/{IconFares-dIGVrtE4.js → IconFares-DTm0Q_RI.js} +1 -1
  22. package/dist/{IconFaresOutlined-bd8kT44f.js → IconFaresOutlined-BFMo_x9Q.js} +1 -1
  23. package/dist/{IconFemale-CMeYHrDy.js → IconFemale-Ma0KeaEM.js} +1 -1
  24. package/dist/{IconFindConversation-BdN2Yd3R.js → IconFindConversation-CpsDYPgD.js} +1 -1
  25. package/dist/{IconFire-obwuluyJ.js → IconFire-DECrDnLM.js} +1 -1
  26. package/dist/{IconFlight-B_6tJxB3.js → IconFlight-D5M0A0CM.js} +1 -1
  27. package/dist/{IconFlightReturn-BEO97PwR.js → IconFlightReturn-CTvqEFME.js} +1 -1
  28. package/dist/{IconHandHeart-hs0yFSEL.js → IconHandHeart-ChgdfXQa.js} +1 -1
  29. package/dist/{IconHistory-CT-jOMRt.js → IconHistory-DpIXDYI5.js} +1 -1
  30. package/dist/{IconHourGlass-CF940vmy.js → IconHourGlass-CIRkFUSM.js} +1 -1
  31. package/dist/{IconIdCard-DKkU58Ix.js → IconIdCard-UD5VZsUi.js} +1 -1
  32. package/dist/{IconInfant-DIUT-6_4.js → IconInfant-CmLUvWpO.js} +1 -1
  33. package/dist/{IconItinerary-D7mOGUmj.js → IconItinerary-CY8irele.js} +1 -1
  34. package/dist/{IconLeave-BExl4uyV.js → IconLeave-C3bpPz6L.js} +1 -1
  35. package/dist/{IconMale-eHGH5XBz.js → IconMale-x4xdulWB.js} +1 -1
  36. package/dist/{IconMultiSegments-KkrKiZrK.js → IconMultiSegments-BhTMfvhQ.js} +1 -1
  37. package/dist/{IconNoPassport-PJ2QqqoI.js → IconNoPassport-_Xm76k6b.js} +1 -1
  38. package/dist/{IconNoRefund-W47AQisu.js → IconNoRefund-B78s0oyF.js} +1 -1
  39. package/dist/{IconNotion-CCnhatKK.js → IconNotion-C22PTLTU.js} +1 -1
  40. package/dist/{IconOffline-3wunTEJG.js → IconOffline-BDzikWE9.js} +1 -1
  41. package/dist/{IconOneWay-BQ5K41Bu.js → IconOneWay-DlTVxokv.js} +2 -2
  42. package/dist/{IconPaid-zwDwWzF8.js → IconPaid-DmGERe85.js} +1 -1
  43. package/dist/{IconPassport-IxhNLS8P.js → IconPassport-6VOlXjxJ.js} +1 -1
  44. package/dist/{IconPayout-BNSON3dj.js → IconPayout-abr6BXCd.js} +1 -1
  45. package/dist/{IconReceipt-DOosYtgi.js → IconReceipt-BnTaihcq.js} +1 -1
  46. package/dist/{IconRecurrence-B8i5kO2Q.js → IconRecurrence-C5TPG2ht.js} +1 -1
  47. package/dist/{IconRefund-DkjF9lEI.js → IconRefund-Ysv8pyMJ.js} +1 -1
  48. package/dist/{IconRoundTrip-BZvhS65z.js → IconRoundTrip-CIVDw8LK.js} +1 -1
  49. package/dist/{IconRouteNoStop-CeSlfnpx.js → IconRouteNoStop-DQrq4gW5.js} +1 -1
  50. package/dist/{IconRouteOneStop-aP1Mj-Bv.js → IconRouteOneStop-pzisj4i4.js} +1 -1
  51. package/dist/{IconScheduleChange-QQ4AMAMI.js → IconScheduleChange-BONs1AAT.js} +1 -1
  52. package/dist/{IconSeatEmpty-DgVBD165.js → IconSeatEmpty-CHij3aGA.js} +1 -1
  53. package/dist/{IconSeatSold-BGBwNZUa.js → IconSeatSold-QspS_zCh.js} +1 -1
  54. package/dist/{IconSeatTotal-Dq9uXccZ.js → IconSeatTotal-DTZ1TcAX.js} +1 -1
  55. package/dist/{IconTemplate-BgruEhjI.js → IconTemplate-BDmmr-9L.js} +1 -1
  56. package/dist/{IconTicket-BTaYnuPt.js → IconTicket--vVn61Ey.js} +1 -1
  57. package/dist/{IconTimer-CyJzne5T.js → IconTimer-CspKpwqZ.js} +1 -1
  58. package/dist/{IconTrafficControl-BeQtpwhK.js → IconTrafficControl-DBamcJNe.js} +1 -1
  59. package/dist/{index-B8RNa4cx.js → index-C3oHnZQk.js} +9152 -10064
  60. package/dist/pimp.es.js +1 -1
  61. package/dist/pimp.umd.js +17 -17
  62. package/dist/style.css +1 -1
  63. package/package.json +2 -1
  64. package/src/components/atomic-elements/CpAirlineLogo.vue +9 -10
  65. package/src/components/atomic-elements/CpBadge.vue +33 -41
  66. package/src/components/atomic-elements/CpDialog.vue +14 -9
  67. package/src/components/atomic-elements/CpPartnerBadge.vue +12 -20
  68. package/src/components/atomic-elements/CpTooltip.vue +12 -11
  69. package/src/components/buttons/CpButton.vue +63 -104
  70. package/src/components/core/BaseInputLabel.vue +9 -15
  71. package/src/components/core/BaseSelectClearButton.vue +1 -1
  72. package/src/components/date-pickers/CpCalendar.vue +154 -153
  73. package/src/components/date-pickers/CpDate.vue +202 -212
  74. package/src/components/date-pickers/CpDatepicker.vue +112 -138
  75. package/src/components/feedback-indicators/CpAlert.vue +16 -27
  76. package/src/components/feedback-indicators/CpLoader.vue +7 -8
  77. package/src/components/feedback-indicators/CpToaster.vue +197 -192
  78. package/src/components/helpers-utilities/TransitionExpand.vue +31 -33
  79. package/src/components/icons/IconOneWay.vue +1 -1
  80. package/src/components/index.ts +28 -40
  81. package/src/components/inputs/CpInput.vue +40 -57
  82. package/src/components/inputs/CpTextarea.vue +30 -50
  83. package/src/components/lists-and-table/CpTable.vue +165 -114
  84. package/src/components/lists-and-table/CpTableEmptyState.vue +5 -8
  85. package/src/components/selects/CpMultiselect.vue +58 -89
  86. package/src/components/selects/CpSelect.vue +70 -90
  87. package/src/components/selects/CpSelectMenu.vue +94 -96
  88. package/src/components/toggles/CpCheckbox.vue +45 -54
  89. package/src/components/toggles/CpRadio.vue +47 -58
  90. package/src/components/toggles/CpSwitch.vue +51 -67
  91. package/src/components/typography/CpHeading.vue +11 -31
  92. package/src/components/visual/CpIcon.vue +2 -1
  93. package/src/constants/{src/CpCustomIcons.ts → CpCustomIcons.ts} +1 -1
  94. package/src/constants/CpTableConfig.ts +12 -0
  95. package/src/constants/Heading.ts +8 -0
  96. package/src/{utils/constants/src/Intent.js → constants/Intent.ts} +1 -1
  97. package/src/constants/PartnerTypes.ts +6 -0
  98. package/src/constants/Position.ts +10 -0
  99. package/src/constants/Sizes.ts +5 -0
  100. package/src/constants/colors/Colors.ts +10 -0
  101. package/src/constants/colors/ToggleColors.ts +6 -0
  102. package/src/constants/index.ts +10 -5
  103. package/src/directives/ClickOutside.ts +17 -0
  104. package/src/directives/{ResizeSelect.js → ResizeSelect.ts} +3 -3
  105. package/src/helpers/{dom.js → dom.ts} +13 -9
  106. package/src/helpers/{index.js → index.ts} +13 -3
  107. package/src/helpers/object.ts +9 -0
  108. package/src/helpers/string/src/camelize.ts +6 -0
  109. package/src/helpers/string/src/{decamelize.js → decamelize.ts} +1 -1
  110. package/src/libs/CoreDatepicker.vue +4 -4
  111. package/src/plugins/toaster.ts +71 -0
  112. package/src/stories/BaseInputLabel.stories.ts +1 -0
  113. package/src/stories/CpAlert.stories.ts +1 -0
  114. package/src/stories/CpBadge.stories.ts +18 -0
  115. package/src/stories/CpCheckbox.stories.ts +3 -1
  116. package/src/stories/CpDate.stories.ts +3 -1
  117. package/src/stories/CpDatepicker.stories.ts +3 -1
  118. package/src/stories/CpDialog.stories.ts +2 -1
  119. package/src/stories/CpHeading.stories.ts +1 -0
  120. package/src/stories/CpIcon.stories.ts +2 -0
  121. package/src/stories/CpInput.stories.ts +3 -1
  122. package/src/stories/CpLoader.stories.ts +1 -0
  123. package/src/stories/CpMultiselect.stories.ts +2 -1
  124. package/src/stories/CpPartnerBadge.stories.ts +1 -1
  125. package/src/stories/CpRadio.stories.ts +3 -1
  126. package/src/stories/CpSelect.stories.ts +3 -1
  127. package/src/stories/CpSelectMenu.stories.ts +3 -1
  128. package/src/stories/CpSwitch.stories.ts +3 -1
  129. package/src/stories/CpTable.stories.ts +8 -1
  130. package/src/stories/CpTableEmptyState.stories.ts +1 -0
  131. package/src/stories/CpTextarea.stories.ts +3 -1
  132. package/src/stories/CpToaster.stories.ts +1 -0
  133. package/src/stories/CpTooltip.stories.ts +1 -0
  134. package/src/stories/TransitionExpand.stories.ts +3 -1
  135. package/src/types/luxon.d.ts +1 -0
  136. package/src/vendors/ff-polyfill.ts +38 -0
  137. package/vitest.workspace.js +1 -3
  138. package/src/constants/src/CpTableConfig.ts +0 -14
  139. package/src/constants/src/Position.ts +0 -10
  140. package/src/constants/src/colors/Colors.ts +0 -10
  141. package/src/constants/src/colors/ToggleColors.ts +0 -6
  142. package/src/directives/ClickOutside.js +0 -13
  143. package/src/helpers/object.js +0 -9
  144. package/src/helpers/string/src/camelize.js +0 -6
  145. package/src/plugins/toaster.js +0 -61
  146. package/src/utils/constants/index.js +0 -3
  147. package/src/utils/constants/src/PartnerTypes.js +0 -6
  148. package/src/utils/constants/src/Sizes.js +0 -5
  149. package/src/vendors/ff-polyfill.js +0 -36
  150. /package/src/helpers/string/{index.js → index.ts} +0 -0
@@ -8,7 +8,6 @@
8
8
  class="cpButton"
9
9
  role="button"
10
10
  tabindex="0"
11
- @click="handleClick"
12
11
  >
13
12
  <span class="cpButton__body">
14
13
  <span v-if="isLoading" class="cpButton__loader"><cp-loader color="#B2B2BD" /></span>
@@ -23,120 +22,80 @@
23
22
  </component>
24
23
  </template>
25
24
 
26
- <script>
27
- import { capitalizeFirstLetter } from '@/helpers'
28
- import { Colors } from '@/constants'
25
+ <script setup lang="ts">
26
+ import { computed, useSlots } from 'vue'
29
27
 
30
28
  import CpLoader from '@/components/feedback-indicators/CpLoader.vue'
31
29
 
32
- const ButtonAppearances = {
33
- default: 'default',
34
- primary: 'primary',
35
- minimal: 'minimal',
30
+ import { Colors } from '@/constants'
31
+ import { capitalizeFirstLetter } from '@/helpers'
32
+
33
+ enum ButtonAppearances {
34
+ DEFAULT = 'default',
35
+ PRIMARY = 'primary',
36
+ MINIMAL = 'minimal',
36
37
  }
37
38
 
38
- const ButtonTags = {
39
- button: 'button',
40
- a: 'a',
39
+ enum ButtonTags {
40
+ BUTTON = 'button',
41
+ A = 'a',
41
42
  }
42
43
 
43
- const ButtonTypes = {
44
- button: 'button',
45
- submit: 'submit',
46
- reset: 'reset',
44
+ enum ButtonTypes {
45
+ BUTTON = 'button',
46
+ SUBMIT = 'submit',
47
+ RESET = 'reset',
47
48
  }
48
49
 
49
- export default {
50
- components: {
51
- CpLoader,
52
- },
53
- props: {
54
- appearance: {
55
- type: String,
56
- default: ButtonAppearances.default,
57
- validator: (value) => {
58
- return {}.propertyIsEnumerable.call(ButtonAppearances, value)
59
- },
60
- },
61
- color: {
62
- type: String,
63
- default: '',
64
- validator: (value) => Object.values(Colors).includes(value) || value === '',
65
- },
66
- disabled: {
67
- type: Boolean,
68
- default: false,
69
- },
70
- tag: {
71
- type: String,
72
- default: ButtonTags.button,
73
- validator: (value) => {
74
- return {}.propertyIsEnumerable.call(ButtonTags, value)
75
- },
76
- },
77
- type: {
78
- type: String,
79
- default: ButtonTypes.button,
80
- validator: (value) => {
81
- return {}.propertyIsEnumerable.call(ButtonTypes, value)
82
- },
83
- },
84
- isLoading: {
85
- type: Boolean,
86
- default: false,
87
- },
88
- isSquare: {
89
- type: Boolean,
90
- default: false,
91
- },
92
- isLarge: {
93
- type: Boolean,
94
- default: false,
95
- },
96
- },
97
- emits: ['click'],
98
- computed: {
99
- capitalizedAppearance() {
100
- return capitalizeFirstLetter(this.appearance)
101
- },
102
- capitalizedColor() {
103
- return capitalizeFirstLetter(this.color)
104
- },
105
- dynamicClasses() {
106
- return [
107
- `cpButton--is${this.capitalizedAppearance}`,
108
- this.capitalizedColor && `cpButton--is${this.capitalizedColor}`,
109
- {
110
- 'cpButton--isDisabled': this.isButtonDisabled,
111
- 'cpButton--isIcon': !this.hasLabel,
112
- 'cpButton--isLoading': this.isLoading,
113
- 'cpButton--isSquare': this.isSquare,
114
- 'cpButton--isLarge': this.isLarge,
115
- },
116
- ]
117
- },
118
- hasLabel() {
119
- return !!this.$slots['default']
120
- },
121
- hasIconBefore() {
122
- return !!this.$slots['icon-before']
123
- },
124
- hasIconAfter() {
125
- return !!this.$slots['icon-after']
126
- },
127
- isButtonDisabled() {
128
- if (this.disabled || this.isLoading) return true
129
- return null
130
- },
131
- },
132
- methods: {
133
- handleClick($event) {
134
- if (this.isButtonDisabled) return
50
+ interface Props {
51
+ appearance?: ButtonAppearances
52
+ color?: Colors
53
+ disabled?: boolean
54
+ isLarge?: boolean
55
+ isLoading?: boolean
56
+ isSquare?: boolean
57
+ tag?: ButtonTags
58
+ type?: ButtonTypes
59
+ }
60
+
61
+ const props = withDefaults(defineProps<Props>(), {
62
+ appearance: ButtonAppearances.DEFAULT,
63
+ color: undefined,
64
+ disabled: false,
65
+ tag: ButtonTags.BUTTON,
66
+ type: ButtonTypes.BUTTON,
67
+ isLoading: false,
68
+ isSquare: false,
69
+ isLarge: false,
70
+ })
71
+
72
+ const slots = useSlots()
135
73
 
136
- this.$emit('click', $event)
74
+ const capitalizedAppearance = computed(() => capitalizeFirstLetter(props.appearance))
75
+
76
+ const capitalizedColor = computed(() => capitalizeFirstLetter(props.color))
77
+
78
+ const hasLabel = computed(() => !!slots.default)
79
+
80
+ const hasIconBefore = computed(() => !!slots['icon-before'])
81
+
82
+ const hasIconAfter = computed(() => !!slots['icon-after'])
83
+
84
+ const isButtonDisabled = computed(() => props.disabled || props.isLoading)
85
+
86
+ const dynamicClasses = computed(() => {
87
+ return [
88
+ `cpButton--is${capitalizedAppearance.value}`,
89
+ {
90
+ [`cpButton--is${capitalizedColor.value}`]: !!capitalizedColor.value,
91
+ 'cpButton--isDisabled': isButtonDisabled.value,
92
+ 'cpButton--isIcon': !hasLabel.value,
93
+ 'cpButton--isLoading': props.isLoading,
94
+ 'cpButton--isSquare': props.isSquare,
95
+ 'cpButton--isLarge': props.isLarge,
137
96
  },
138
- },
139
- }
97
+ ]
98
+ })
140
99
  </script>
141
100
 
142
101
  <style lang="scss">
@@ -5,22 +5,16 @@
5
5
  </label>
6
6
  </template>
7
7
 
8
- <script>
9
- export default {
10
- inheritAttrs: false,
11
- props: {
12
- isInvalid: {
13
- type: Boolean,
14
- default: false,
15
- required: false,
16
- },
17
- required: {
18
- type: Boolean,
19
- default: false,
20
- required: false,
21
- },
22
- },
8
+ <script setup lang="ts">
9
+ interface Props {
10
+ isInvalid?: boolean
11
+ required?: boolean
23
12
  }
13
+
14
+ withDefaults(defineProps<Props>(), {
15
+ isInvalid: false,
16
+ required: false,
17
+ })
24
18
  </script>
25
19
 
26
20
  <style lang="scss">
@@ -4,7 +4,7 @@
4
4
  </button>
5
5
  </template>
6
6
 
7
- <script setup>
7
+ <script setup lang="ts">
8
8
  import CpIcon from '@/components/visual/CpIcon.vue'
9
9
  </script>
10
10
 
@@ -23,9 +23,9 @@
23
23
  :locale="locale"
24
24
  class="cpCalendar__datepicker"
25
25
  :class="dynamicClasses"
26
- @date-one-selected="(date) => selectDate('dateOne', date)"
27
- @date-two-selected="(date) => selectDate('dateTwo', date)"
28
- @is-inline="(value) => (isInline = value)"
26
+ @date-one-selected="onDateSelected('dateOne', $event)"
27
+ @date-two-selected="onDateSelected('dateTwo', $event)"
28
+ @is-inline="onIsInline"
29
29
  @opened="() => (isDisabled = true)"
30
30
  @closed="() => (isDisabled = false)"
31
31
  >
@@ -86,172 +86,173 @@
86
86
  </div>
87
87
  </template>
88
88
 
89
- <script>
89
+ <script setup lang="ts">
90
90
  import { DateTime, Info, Interval } from 'luxon'
91
+ import { ref, computed, watch } from 'vue'
91
92
 
92
93
  import CpButton from '@/components/buttons/CpButton.vue'
93
94
  import CpInput from '@/components/inputs/CpInput.vue'
94
95
  import CpIcon from '@/components/visual/CpIcon.vue'
95
- import CoreDatepicker from '@/libs/CoreDatepicker.vue'
96
96
 
97
97
  import { randomString, formatDates } from '@/helpers'
98
+ import CoreDatepicker from '@/libs/CoreDatepicker.vue'
98
99
 
99
- export default {
100
- name: 'CpCalendar',
101
- components: {
102
- CoreDatepicker,
103
- CpInput,
104
- CpIcon,
105
- CpButton,
106
- },
107
- props: {
108
- triggerElementId: {
109
- type: String,
110
- default: 'calendar-trigger-' + randomString(5),
111
- },
112
- closeAfterSelect: {
113
- type: Boolean,
114
- default: false,
115
- },
116
- label: {
117
- type: String,
118
- default: '',
119
- },
120
- isError: {
121
- type: Boolean,
122
- default: false,
123
- },
124
- errorMessage: {
125
- type: String,
126
- default: '',
127
- },
128
- initDateOne: {
129
- type: String,
130
- default: '',
131
- validator: (value) => {
132
- return value === '' || value.length === 10
133
- },
134
- },
135
- locale: {
136
- type: String,
137
- default: () => {
138
- return navigator.language
139
- },
140
- },
141
- },
142
- emits: ['dates'],
143
- data() {
144
- return {
145
- humanFormat: 'EEE DD',
146
- dateOne: this.initDateOne || '',
147
- dateTwo: '',
148
- days: Info.weekdays('short', { locale: 'en-EN' }).map((day, value) => {
149
- return { day, selected: false, value }
150
- }),
151
- recurenceDates: [],
152
- mode: 'single',
153
- triggerCalendar: false,
154
- isInline: false,
155
- isDisabled: null,
156
- }
157
- },
158
- computed: {
159
- selectedDays() {
160
- return this.days.filter((day) => day.selected === true).map((day) => day.value + 1)
161
- },
162
- summary() {
163
- const start = DateTime.fromISO(this.dateOne).toFormat(this.humanFormat)
164
- const end = DateTime.fromISO(this.dateTwo).toFormat(this.humanFormat)
165
-
166
- return {
167
- start,
168
- end,
169
- }
170
- },
171
- isDaysDisplayed() {
172
- return this.mode === 'range'
173
- },
174
- dynamicClasses() {
175
- return { 'cpCalendar__datepicker--isInline': this.isInline }
176
- },
177
- },
178
- watch: {
179
- isInline(value) {
180
- if (value) this.removeRecurency()
181
- },
182
- },
183
- methods: {
184
- done() {
185
- this.emitToParent()
186
- this.closeCalendar()
187
- },
188
- closeCalendar() {
189
- this.triggerCalendar = !this.triggerCalendar
190
- },
191
- humanDateFormat(dateOne, dateTwo) {
192
- return formatDates({ dateOne, dateTwo, format: this.humanFormat, locale: this.locale })
193
- },
194
- toggleDay(index) {
195
- this.days[index].selected = !this.days[index].selected
196
- this.recurenceDates = this.generateDates(this.dateOne, this.dateTwo, this.selectedDays)
197
- this.emitToParent()
198
- },
199
- addRecurency() {
200
- const dt = DateTime.local()
201
- this.mode = 'range'
202
-
203
- if (!this.dateOne) this.dateOne = dt.plus({ days: 1 }).toISODate()
204
- if (!this.dateTwo) this.dateTwo = DateTime.fromISO(this.dateOne).plus({ days: 7 }).toISODate()
205
- },
206
- removeRecurency() {
207
- this.mode = 'single'
208
- this.recurenceDates = []
209
- this.dateTwo = ''
210
- this.days = Info.weekdays('short', { locale: 'en-EN' }).map((day, value) => {
211
- return { day, selected: false, value }
212
- })
213
- },
214
- emitToParent() {
215
- let dates = [this.dateOne]
216
- if (this.isDaysDisplayed) {
217
- dates = this.recurenceDates.length ? this.datesToStringArray(this.recurenceDates) : []
218
- }
219
- return this.$emit('dates', dates)
220
- },
221
- generateDates(startDate, endDate, selectedWeekDaysIndex) {
222
- const isoStartDate = DateTime.fromISO(startDate)
223
- const isoEndDate = DateTime.fromISO(endDate)
100
+ interface DayOption {
101
+ day: string
102
+ selected: boolean
103
+ value: number
104
+ }
224
105
 
225
- let selectedDaysFinalList = []
106
+ interface Props {
107
+ closeAfterSelect?: boolean
108
+ errorMessage?: string
109
+ initDateOne?: string
110
+ isError?: boolean
111
+ label?: string
112
+ locale?: string
113
+ triggerElementId?: string
114
+ }
226
115
 
227
- const daysIntervalBetweenTwoDates = Interval.fromDateTimes(isoStartDate.startOf('day'), isoEndDate.endOf('day'))
228
- .splitBy({ days: 1 })
229
- .map((day) => day.start)
116
+ interface Emits {
117
+ (e: 'dates', dates: string[]): void
118
+ }
230
119
 
231
- daysIntervalBetweenTwoDates.forEach((day) => {
232
- const dayOfWeekAsNumber = Number(DateTime.fromISO(day).toFormat('c'))
120
+ const props = withDefaults(defineProps<Props>(), {
121
+ triggerElementId: () => `calendar-trigger-${randomString()}`,
122
+ closeAfterSelect: false,
123
+ label: '',
124
+ isError: false,
125
+ errorMessage: '',
126
+ initDateOne: '',
127
+ locale: () => navigator.language,
128
+ })
129
+
130
+ const emit = defineEmits<Emits>()
131
+
132
+ const humanFormat = 'EEE DD'
133
+ const dateOne = ref(props.initDateOne || '')
134
+ const dateTwo = ref('')
135
+ const days = ref<DayOption[]>(
136
+ Info.weekdays('short', { locale: 'en-EN' }).map((day: string, value: number) => ({ day, selected: false, value })),
137
+ )
138
+ const recurenceDates = ref<string[]>([])
139
+ const mode = ref<'single' | 'range'>('single')
140
+ const triggerCalendar = ref(false)
141
+ const isInline = ref(false)
142
+ const isDisabled = ref(false)
143
+
144
+ const selectedDays = computed(() => {
145
+ return days.value.filter((day) => day.selected === true).map((day) => day.value + 1)
146
+ })
147
+
148
+ const summary = computed(() => {
149
+ const start = DateTime.fromISO(dateOne.value).toFormat(humanFormat)
150
+ const end = DateTime.fromISO(dateTwo.value).toFormat(humanFormat)
151
+
152
+ return {
153
+ start,
154
+ end,
155
+ }
156
+ })
233
157
 
234
- if (selectedWeekDaysIndex.includes(dayOfWeekAsNumber)) {
235
- selectedDaysFinalList.push(day)
236
- }
237
- })
158
+ const isDaysDisplayed = computed(() => {
159
+ return mode.value === 'range'
160
+ })
238
161
 
239
- return selectedDaysFinalList
240
- },
241
- selectDate(key, value) {
242
- this[key] = value
162
+ const dynamicClasses = computed(() => {
163
+ return { 'cpCalendar__datepicker--isInline': isInline.value }
164
+ })
243
165
 
244
- if (this.isDaysDisplayed) {
245
- this.recurenceDates = this.generateDates(this.dateOne, this.dateTwo, this.selectedDays)
246
- }
166
+ const done = (): void => {
167
+ emitToParent()
168
+ closeCalendar()
169
+ }
170
+
171
+ const onDateSelected = (dateSelector: 'dateOne' | 'dateTwo', date: string) => selectDate(dateSelector, date)
172
+
173
+ const onIsInline = (value: boolean) => (isInline.value = value)
247
174
 
248
- return this.emitToParent()
249
- },
250
- datesToStringArray(dates) {
251
- return dates.map((date) => date.toISODate())
252
- },
253
- },
175
+ const closeCalendar = (): void => {
176
+ triggerCalendar.value = !triggerCalendar.value
254
177
  }
178
+
179
+ const humanDateFormat = (dateOne: string, dateTwo: string): string => {
180
+ return formatDates({ dateOne, dateTwo, format: humanFormat, locale: props.locale })
181
+ }
182
+
183
+ const toggleDay = (index: number): void => {
184
+ days.value[index].selected = !days.value[index].selected
185
+ recurenceDates.value = generateDates(dateOne.value, dateTwo.value, selectedDays.value)
186
+ emitToParent()
187
+ }
188
+
189
+ const addRecurency = (): void => {
190
+ const dt = DateTime.local()
191
+ mode.value = 'range'
192
+
193
+ if (!dateOne.value) dateOne.value = dt.plus({ days: 1 }).toISODate()
194
+ if (!dateTwo.value) dateTwo.value = DateTime.fromISO(dateOne.value).plus({ days: 7 }).toISODate()
195
+ }
196
+
197
+ const removeRecurency = (): void => {
198
+ mode.value = 'single'
199
+ recurenceDates.value = []
200
+ dateTwo.value = ''
201
+ days.value = Info.weekdays('short', { locale: 'en-EN' }).map((day: string, value: number) => {
202
+ return { day, selected: false, value }
203
+ })
204
+ }
205
+
206
+ const emitToParent = (): void => {
207
+ let dates = [dateOne.value]
208
+ if (isDaysDisplayed.value) {
209
+ dates = recurenceDates.value.length ? datesToStringArray(recurenceDates.value) : []
210
+ }
211
+ return emit('dates', dates)
212
+ }
213
+
214
+ const generateDates = (startDate: string, endDate: string, selectedWeekDaysIndex: number[]): string[] => {
215
+ const isoStartDate = DateTime.fromISO(startDate)
216
+ const isoEndDate = DateTime.fromISO(endDate)
217
+
218
+ let selectedDaysFinalList: string[] = []
219
+
220
+ const daysIntervalBetweenTwoDates = Interval.fromDateTimes(isoStartDate.startOf('day'), isoEndDate.endOf('day'))
221
+ .splitBy({ days: 1 })
222
+ .map((day: typeof Interval) => day.start)
223
+
224
+ daysIntervalBetweenTwoDates.forEach((day: string) => {
225
+ const dayOfWeekAsNumber = Number(DateTime.fromISO(day).toFormat('c'))
226
+
227
+ if (selectedWeekDaysIndex.includes(dayOfWeekAsNumber)) {
228
+ selectedDaysFinalList.push(day)
229
+ }
230
+ })
231
+
232
+ return selectedDaysFinalList
233
+ }
234
+
235
+ const selectDate = (key: 'dateOne' | 'dateTwo', value: string): void => {
236
+ if (key === 'dateOne') {
237
+ dateOne.value = value
238
+ } else {
239
+ dateTwo.value = value
240
+ }
241
+
242
+ if (isDaysDisplayed.value) {
243
+ recurenceDates.value = generateDates(dateOne.value, dateTwo.value, selectedDays.value)
244
+ }
245
+
246
+ return emitToParent()
247
+ }
248
+
249
+ const datesToStringArray = (dates: string[]): string[] => {
250
+ return dates.map((date) => DateTime.fromISO(date).toISODate() || '')
251
+ }
252
+
253
+ watch(isInline, (value) => {
254
+ if (value) removeRecurency()
255
+ })
255
256
  </script>
256
257
 
257
258
  <style lang="scss">