@citizenplane/pimp 18.7.0 → 18.8.1

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 (167) hide show
  1. package/biome.json +178 -0
  2. package/dist/components/BaseInputLabel.vue.d.ts.map +1 -1
  3. package/dist/components/BaseSelectClearButton.vue.d.ts.map +1 -1
  4. package/dist/components/CpAccordion.vue.d.ts.map +1 -1
  5. package/dist/components/CpAlert.vue.d.ts.map +1 -1
  6. package/dist/components/CpBadge.vue.d.ts.map +1 -1
  7. package/dist/components/CpButton.vue.d.ts.map +1 -1
  8. package/dist/components/CpButtonToggle.vue.d.ts +1 -1
  9. package/dist/components/CpButtonToggle.vue.d.ts.map +1 -1
  10. package/dist/components/CpCalendar.vue.d.ts.map +1 -1
  11. package/dist/components/CpCheckbox.vue.d.ts.map +1 -1
  12. package/dist/components/CpContextualMenu.vue.d.ts.map +1 -1
  13. package/dist/components/CpDate.vue.d.ts.map +1 -1
  14. package/dist/components/CpDatepicker.vue.d.ts.map +1 -1
  15. package/dist/components/CpInput.vue.d.ts.map +1 -1
  16. package/dist/components/CpItemActions.vue.d.ts.map +1 -1
  17. package/dist/components/CpMenu.vue.d.ts.map +1 -1
  18. package/dist/components/CpMenuItem.vue.d.ts.map +1 -1
  19. package/dist/components/CpMultiselect.vue.d.ts.map +1 -1
  20. package/dist/components/CpRadio.vue.d.ts.map +1 -1
  21. package/dist/components/CpRadioGroup.vue.d.ts.map +1 -1
  22. package/dist/components/CpRadioNew.vue.d.ts.map +1 -1
  23. package/dist/components/CpSelect.vue.d.ts.map +1 -1
  24. package/dist/components/CpSelectMenu.vue.d.ts.map +1 -1
  25. package/dist/components/CpSelectableButton.vue.d.ts +1 -1
  26. package/dist/components/CpSelectableButton.vue.d.ts.map +1 -1
  27. package/dist/components/CpSwitch.vue.d.ts.map +1 -1
  28. package/dist/components/CpTable.vue.d.ts.map +1 -1
  29. package/dist/components/CpTelInput.vue.d.ts.map +1 -1
  30. package/dist/components/CpTooltip.vue.d.ts +2 -0
  31. package/dist/components/CpTooltip.vue.d.ts.map +1 -1
  32. package/dist/components/CpTrip.vue.d.ts +48 -0
  33. package/dist/components/CpTrip.vue.d.ts.map +1 -0
  34. package/dist/components/CpTripTimeline.vue.d.ts +24 -0
  35. package/dist/components/CpTripTimeline.vue.d.ts.map +1 -0
  36. package/dist/components/icons/IconDestination.vue.d.ts +3 -0
  37. package/dist/components/icons/IconDestination.vue.d.ts.map +1 -0
  38. package/dist/components/icons/IconOrigin.vue.d.ts +3 -0
  39. package/dist/components/icons/IconOrigin.vue.d.ts.map +1 -0
  40. package/dist/components/index.d.ts +2 -1
  41. package/dist/components/index.d.ts.map +1 -1
  42. package/dist/composables/useDynamicSize.d.ts +9 -0
  43. package/dist/composables/useDynamicSize.d.ts.map +1 -0
  44. package/dist/constants/CpCustomIcons.d.ts +2 -0
  45. package/dist/constants/CpCustomIcons.d.ts.map +1 -1
  46. package/dist/constants/index.d.ts +2 -2
  47. package/dist/constants/index.d.ts.map +1 -1
  48. package/dist/constants/layout/Breakpoints.d.ts +9 -0
  49. package/dist/constants/layout/Breakpoints.d.ts.map +1 -0
  50. package/dist/constants/layout/Sizes.d.ts +2 -0
  51. package/dist/constants/layout/Sizes.d.ts.map +1 -0
  52. package/dist/constants/layout/index.d.ts +3 -0
  53. package/dist/constants/layout/index.d.ts.map +1 -0
  54. package/dist/helpers/functions.d.ts +1 -0
  55. package/dist/helpers/functions.d.ts.map +1 -1
  56. package/dist/libs/CoreDatepicker.vue.d.ts.map +1 -1
  57. package/dist/pimp.es.js +6474 -6113
  58. package/dist/pimp.umd.js +54 -54
  59. package/dist/style.css +1 -1
  60. package/package.json +14 -24
  61. package/src/assets/css/base.css +17 -11
  62. package/src/assets/css/colors.css +12 -22
  63. package/src/assets/css/dimensions.css +4 -0
  64. package/src/assets/css/shadows.css +0 -3
  65. package/src/assets/css/tokens.css +21 -65
  66. package/src/assets/css/typography.css +0 -17
  67. package/src/assets/main.css +7 -7
  68. package/src/assets/styles/helpers/_functions.scss +2 -2
  69. package/src/assets/styles/utilities/_index.scss +2 -3
  70. package/src/components/BaseInputLabel.vue +7 -11
  71. package/src/components/BaseSelectClearButton.vue +6 -7
  72. package/src/components/CpAccordion.vue +27 -28
  73. package/src/components/CpAccordionGroup.vue +2 -2
  74. package/src/components/CpAlert.vue +12 -11
  75. package/src/components/CpBadge.vue +4 -19
  76. package/src/components/CpButton.vue +23 -25
  77. package/src/components/CpButtonGroup.vue +2 -2
  78. package/src/components/CpButtonToggle.vue +22 -22
  79. package/src/components/CpCalendar.vue +30 -26
  80. package/src/components/CpCheckbox.vue +29 -33
  81. package/src/components/CpContextualMenu.vue +1 -2
  82. package/src/components/CpDate.vue +72 -76
  83. package/src/components/CpDatepicker.vue +2 -3
  84. package/src/components/CpDialog.vue +8 -8
  85. package/src/components/CpHeading.vue +6 -6
  86. package/src/components/CpIcon.vue +2 -2
  87. package/src/components/CpInput.vue +46 -48
  88. package/src/components/CpItemActions.vue +10 -10
  89. package/src/components/CpMenu.vue +8 -9
  90. package/src/components/CpMenuItem.vue +7 -7
  91. package/src/components/CpMenuList.vue +3 -3
  92. package/src/components/CpMultiselect.vue +29 -30
  93. package/src/components/CpRadio.vue +53 -59
  94. package/src/components/CpRadioGroup.vue +11 -12
  95. package/src/components/CpRadioNew.vue +56 -58
  96. package/src/components/CpSelect.vue +42 -42
  97. package/src/components/CpSelectMenu.vue +32 -32
  98. package/src/components/CpSelectableButton.vue +50 -51
  99. package/src/components/CpSwitch.vue +43 -44
  100. package/src/components/CpTable.vue +69 -81
  101. package/src/components/CpTableColumnEditor.vue +16 -16
  102. package/src/components/CpTableEmptyState.vue +4 -4
  103. package/src/components/CpTableFooter.vue +2 -2
  104. package/src/components/CpTableFooterDesktop.vue +2 -2
  105. package/src/components/CpTableFooterDetails.vue +2 -2
  106. package/src/components/CpTableFooterMobile.vue +4 -4
  107. package/src/components/CpTabs.vue +1 -1
  108. package/src/components/CpTelInput.vue +31 -32
  109. package/src/components/CpTextarea.vue +13 -13
  110. package/src/components/CpToast.vue +25 -24
  111. package/src/components/CpTooltip.vue +15 -13
  112. package/src/components/CpTransitionCounter.vue +1 -1
  113. package/src/components/CpTransitionExpand.vue +5 -5
  114. package/src/components/CpTransitionSize.vue +1 -1
  115. package/src/components/CpTrip.vue +190 -0
  116. package/src/components/CpTripTimeline.vue +272 -0
  117. package/src/components/icons/IconDestination.vue +5 -0
  118. package/src/components/icons/IconOrigin.vue +5 -0
  119. package/src/components/index.ts +36 -34
  120. package/src/composables/useDynamicSize.ts +60 -0
  121. package/src/constants/CpCustomIcons.ts +4 -0
  122. package/src/constants/index.ts +2 -2
  123. package/src/constants/layout/Breakpoints.ts +8 -0
  124. package/src/constants/layout/Sizes.ts +1 -0
  125. package/src/constants/layout/index.ts +3 -0
  126. package/src/directives/ClickOutside.ts +1 -1
  127. package/src/directives/ResizeSelect.ts +1 -1
  128. package/src/helpers/functions.ts +1 -1
  129. package/src/helpers/index.ts +1 -1
  130. package/src/libs/CoreDatepicker.vue +115 -134
  131. package/src/stories/Colors.stories.ts +2 -1
  132. package/src/stories/CpAccordion.stories.ts +2 -2
  133. package/src/stories/CpAccordionGroup.stories.ts +1 -2
  134. package/src/stories/CpButtonToggle.stories.ts +1 -2
  135. package/src/stories/CpCheckbox.stories.ts +1 -2
  136. package/src/stories/CpContextualMenu.stories.ts +1 -2
  137. package/src/stories/CpDate.stories.ts +1 -2
  138. package/src/stories/CpDatepicker.stories.ts +1 -2
  139. package/src/stories/CpDialog.stories.ts +1 -2
  140. package/src/stories/CpInput.stories.ts +1 -2
  141. package/src/stories/CpItemActions.stories.ts +1 -2
  142. package/src/stories/CpMenu.stories.ts +1 -2
  143. package/src/stories/CpMenuItem.stories.ts +1 -2
  144. package/src/stories/CpMultiselect.stories.ts +1 -2
  145. package/src/stories/CpRadio.stories.ts +1 -2
  146. package/src/stories/CpRadioGroup.stories.ts +1 -2
  147. package/src/stories/CpSelect.stories.ts +1 -2
  148. package/src/stories/CpSelectMenu.stories.ts +1 -2
  149. package/src/stories/CpSwitch.stories.ts +1 -2
  150. package/src/stories/CpTable.stories.ts +2 -3
  151. package/src/stories/CpTabs.stories.ts +1 -2
  152. package/src/stories/CpText.stories.ts +2 -1
  153. package/src/stories/CpTextarea.stories.ts +1 -2
  154. package/src/stories/CpToast.stories.ts +2 -3
  155. package/src/stories/CpTransitionCounter.stories.ts +1 -2
  156. package/src/stories/CpTransitionExpand.stories.ts +1 -2
  157. package/src/stories/CpTransitionListItems.stories.ts +1 -2
  158. package/src/stories/CpTransitionSize.stories.ts +1 -2
  159. package/src/stories/CpTransitionSlide.stories.ts +1 -2
  160. package/src/stories/CpTransitionTabContent.stories.ts +1 -2
  161. package/src/stories/CpTrip.stories.ts +323 -0
  162. package/src/stories/Dimensions.stories.ts +1 -0
  163. package/src/stories/Shadows.stories.ts +1 -0
  164. package/src/stories/Typography.stories.ts +1 -0
  165. package/src/vendors/ff-polyfill.ts +1 -1
  166. package/vitest.workspace.js +1 -1
  167. package/src/components/Pimp.vue +0 -10
@@ -0,0 +1,190 @@
1
+ <template>
2
+ <div class="cpTrip">
3
+ <div class="cpTrip__content">
4
+ <div class="cpTrip__routePoint">
5
+ <time class="cpTrip__time" :datetime="trip.departureDate.raw">{{ trip.departureTime }}</time>
6
+ <span class="cpTrip__iata">{{ trip.origin.iataCode }}</span>
7
+ </div>
8
+ <cp-trip-timeline
9
+ :airlines="uniqueAirlines"
10
+ :hide-airlines="hideAirlines"
11
+ class="cpTrip__timeline"
12
+ :flight-duration="trip.flightDuration.formatted"
13
+ :has-self-transfer="trip.hasSelfTransfer"
14
+ :labels="trip.labels"
15
+ :stops="trip.stops"
16
+ />
17
+ <div class="cpTrip__routePoint">
18
+ <time class="cpTrip__time" :datetime="trip.arrivalDate.raw">{{ trip.arrivalTime }}</time>
19
+ <span class="cpTrip__iata">
20
+ {{ trip.destination.iataCode }}
21
+ <span v-if="trip.dayCountAfterDeparture" class="cpTrip__plus">+{{ trip.dayCountAfterDeparture }}</span>
22
+ </span>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { computed } from 'vue'
30
+
31
+ import CpTripTimeline from '@/components/CpTripTimeline.vue'
32
+
33
+ type Trip = {
34
+ airlines: {
35
+ iataCode: string
36
+ name: string
37
+ }[];
38
+ arrivalDate: {
39
+ formatted: string
40
+ raw: string
41
+ }
42
+ arrivalTime: string
43
+ dayCountAfterDeparture?: number
44
+ departureDate: {
45
+ formatted: string
46
+ raw: string
47
+ }
48
+ departureTime: string
49
+ destination: {
50
+ iataCode: string
51
+ name: string
52
+ }
53
+ flightDuration: {
54
+ formatted: string
55
+ raw: string
56
+ }
57
+ hasSelfTransfer?: boolean
58
+ labels?: {
59
+ layover?: string
60
+ nonStop?: string
61
+ stopCount?: string
62
+ transfer?: string
63
+ }
64
+ origin: {
65
+ iataCode: string
66
+ name: string
67
+ }
68
+ stops?: {
69
+ duration: string
70
+ iata: string
71
+ name: string
72
+ }[]
73
+ }
74
+
75
+ interface Props {
76
+ hideAirlines?: boolean
77
+ trip: Trip
78
+ }
79
+
80
+ const props = defineProps<Props>()
81
+
82
+ const uniqueAirlines = computed(() => {
83
+ const allAirlinesIataCodes = props.trip.airlines.map((airline) => airline.iataCode)
84
+ const uniqueAirlineIatas: string[] = Array.from(new Set(allAirlinesIataCodes))
85
+
86
+ const allUniqueAirlines = uniqueAirlineIatas.map((uniqueIataCode: string) => {
87
+ return props.trip.airlines.find((airline) => airline.iataCode === uniqueIataCode)
88
+ })
89
+
90
+ return allUniqueAirlines as {
91
+ iataCode: string
92
+ name: string
93
+ }[]
94
+ })
95
+ </script>
96
+
97
+ <style lang="scss">
98
+ .cpTrip {
99
+ &__header {
100
+ display: flex;
101
+ align-items: center;
102
+ justify-content: space-between;
103
+ }
104
+
105
+ &__title {
106
+ color: var(--cp-text-secondary);
107
+ font-size: var(--cp-text-size-xs);
108
+ font-weight: 600;
109
+ line-height: var(--cp-line-height-xs);
110
+ padding-block: var(--cp-spacing-sm);
111
+ text-transform: uppercase;
112
+ }
113
+
114
+ &__content {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: var(--cp-spacing-2xl);
118
+ }
119
+
120
+ &__timeline {
121
+ min-width: 0;
122
+ flex: 1;
123
+ }
124
+
125
+ &__routePoint {
126
+ position: relative;
127
+ display: flex;
128
+ flex-direction: column;
129
+ justify-content: center;
130
+
131
+ &:last-child {
132
+ align-items: flex-end;
133
+ }
134
+ }
135
+
136
+ &__plus {
137
+ position: absolute;
138
+ top: fn.px-to-rem(-2);
139
+ right: fn.px-to-rem(-12);
140
+ color: var(--cp-text-error-primary);
141
+ font-size: fn.px-to-rem(10);
142
+ line-height: fn.px-to-rem(14);
143
+ }
144
+
145
+ &__time {
146
+ font-size: var(--cp-text-size-xl);
147
+ font-weight: 600;
148
+ line-height: var(--cp-line-height-xl);
149
+ }
150
+
151
+ &__iata {
152
+ color: var(--cp-text-secondary);
153
+ font-size: var(--cp-text-size-md);
154
+ font-weight: 500;
155
+ line-height: var(--cp-line-height-md);
156
+ }
157
+ }
158
+
159
+ @include mx.media-query-max(370px) {
160
+ .cpTrip {
161
+ &__content {
162
+ gap: var(--cp-spacing-md);
163
+ }
164
+ }
165
+ }
166
+
167
+ @include mx.media-query-max(300px) {
168
+ .cpTrip {
169
+ &__content {
170
+ justify-content: center;
171
+ gap: var(--cp-spacing-sm);
172
+ }
173
+
174
+ &__time {
175
+ font-size: var(--cp-text-size-lg);
176
+ line-height: var(--cp-line-height-sm);
177
+ }
178
+
179
+ &__iata {
180
+ font-size: var(--cp-text-size-sm);
181
+ line-height: var(--cp-line-height-sm);
182
+ }
183
+
184
+ &__plus {
185
+ font-size: fn.px-to-rem(8);
186
+ line-height: fn.px-to-rem(10);
187
+ }
188
+ }
189
+ }
190
+ </style>
@@ -0,0 +1,272 @@
1
+ <template>
2
+ <div class="cpTripTimeline">
3
+ <div class="cpTripTimeline__information">
4
+ <div class="cpTripTimeline__dotWrapper">
5
+ <span class="cpTripTimeline__dot" />
6
+ </div>
7
+ <cp-badge :size="badgeDynamicSize">
8
+ {{ flightDuration }}
9
+ </cp-badge>
10
+ <cp-tooltip v-if="!hideAirlines" allow-outside-container>
11
+ <div class="cpTripTimeline__airlines">
12
+ <div
13
+ v-for="(airline, index) in firstAirlines"
14
+ :key="airline.iataCode"
15
+ class="cpTripTimeline__airlineLogo"
16
+ >
17
+ <span v-if="displayRemainingAirlinesCount(index)" class="cpTripTimeline__remaining">+{{ remainingAirlinesCount }}</span>
18
+ <cp-airline-logo v-else :iata-code="airline.iataCode" :size="logoDynamicSize" />
19
+ </div>
20
+ </div>
21
+ <template #content>
22
+ <ul class="cpTripTimeline__airlinesList">
23
+ <li v-for="airline in airlines" :key="airline.iataCode">{{ airline.name }}</li>
24
+ </ul>
25
+ </template>
26
+ </cp-tooltip>
27
+ <div class="cpTripTimeline__dotWrapper">
28
+ <span class="cpTripTimeline__dot" />
29
+ </div>
30
+ </div>
31
+ <cp-tooltip class="cpTripTimeline__tooltip" :disabled="!hasStops" allow-outside-container>
32
+ <p class="cpTripTimeline__summary">
33
+ <template v-if="hasStops">
34
+ <span class="cpTripTimeline__stop">{{ stopLabel }}</span>
35
+ <span v-if="hasSelfTransfer" class="cpTripTimeline__transfer">
36
+ {{ transferLabel }}
37
+ </span>
38
+ <span>{{ formattedStops }}</span>
39
+ </template>
40
+ <span v-else>{{ nonStopLabel }}</span>
41
+ </p>
42
+ <template #content>
43
+ <ul class="cpTripTimeline__stops">
44
+ <li v-for="stop in stops" :key="stop.iata">
45
+ {{ stop.duration }} {{ layoverLabel }} •
46
+ <template v-if="stop.selfTransferLabel">
47
+ {{ stop.selfTransferLabel }}
48
+ </template>
49
+ <template v-else> {{ stop.name }} ({{ stop.iata }})</template>
50
+
51
+ <hr />
52
+ </li>
53
+ </ul>
54
+ </template>
55
+ </cp-tooltip>
56
+ </div>
57
+ </template>
58
+
59
+ <script setup lang="ts">
60
+ import { computed } from 'vue'
61
+
62
+ import { useDynamicSize } from '@/composables/useDynamicSize'
63
+
64
+ interface Props {
65
+ airlines: {
66
+ iataCode: string;
67
+ name: string;
68
+ }[];
69
+ flightDuration: string;
70
+ hasSelfTransfer?: boolean;
71
+ hideAirlines?: boolean;
72
+ labels?: {
73
+ layover?: string;
74
+ nonStop?: string;
75
+ stopCount?: string;
76
+ transfer?: string;
77
+ };
78
+ stops?: {
79
+ duration: string;
80
+ iata: string;
81
+ name: string;
82
+ selfTransferLabel?: string;
83
+ }[];
84
+ }
85
+
86
+ const props = defineProps<Props>()
87
+
88
+ const stopLabel = computed(() => props.labels?.stopCount)
89
+ const layoverLabel = computed(() => props.labels?.layover)
90
+ const nonStopLabel = computed(() => props.labels?.nonStop)
91
+ const transferLabel = computed(() => props.labels?.transfer)
92
+
93
+ const badgeDynamicSize = useDynamicSize({ default: 'sm', 300: 'xs' })
94
+ const logoDynamicSize = useDynamicSize({ default: 24, 300: 20 })
95
+
96
+ const hasStops = computed(() => !!props.stops?.length)
97
+
98
+ const AIRLINES_LIMIT = 3
99
+ const firstAirlines = computed(() => props.airlines.slice(0, AIRLINES_LIMIT))
100
+ const hasMoreAirlinesThanLimit = computed(() => props.airlines.length > (AIRLINES_LIMIT + 1))
101
+
102
+ const formattedStops = computed(() => {
103
+ if (!hasStops.value) return ''
104
+ return props.stops!.map(({ name }) => name).join(', ')
105
+ })
106
+
107
+ const remainingAirlinesCount = computed(() => props.airlines.length - firstAirlines.value.length)
108
+
109
+ const displayRemainingAirlinesCount = (index: number) => {
110
+ const isLastItem = index === firstAirlines.value.length - 1
111
+ return hasMoreAirlinesThanLimit.value && isLastItem
112
+ }
113
+ </script>
114
+
115
+ <style lang="scss">
116
+ .cpTripTimeline {
117
+ position: relative;
118
+ display: flex;
119
+ flex-direction: column;
120
+ align-items: center;
121
+
122
+ &__information {
123
+ display: flex;
124
+ overflow: hidden;
125
+ width: 100%;
126
+ align-items: center;
127
+ justify-content: center;
128
+ gap: var(--cp-spacing-md);
129
+ padding-block: fn.px-to-rem(3);
130
+
131
+ &::before,
132
+ &::after {
133
+ display: block;
134
+ width: 100%;
135
+ min-width: 0;
136
+ height: fn.px-to-rem(2);
137
+ flex: 1 1 fn.px-to-rem(32);
138
+ border-radius: var(--cp-radius-xs);
139
+ background-color: var(--cp-border-soft);
140
+ content: "";
141
+ transform-origin: right;
142
+ transition: transform 300ms var(--cp-easing-elastic);
143
+ }
144
+ }
145
+
146
+ &__dotWrapper {
147
+ display: flex;
148
+ width: fn.px-to-rem(16);
149
+ height: fn.px-to-rem(16);
150
+ align-items: center;
151
+ justify-content: center;
152
+
153
+ &:first-child {
154
+ order: -1;
155
+ }
156
+
157
+ &:last-child {
158
+ order: 1;
159
+ }
160
+ }
161
+
162
+ &__dot {
163
+ width: fn.px-to-rem(6);
164
+ height: fn.px-to-rem(6);
165
+ border-radius: var(--cp-radius-full);
166
+ background-color: var(--cp-foreground-quaternary);
167
+ }
168
+
169
+ &__airlines {
170
+ position: relative;
171
+ display: flex;
172
+ flex-direction: row;
173
+ align-items: center;
174
+ gap: var(--cp-spacing-xs);
175
+
176
+ > *:not(:first-child) {
177
+ margin-left: calc(var(--cp-spacing-md) * -1);
178
+ }
179
+ }
180
+
181
+ &__remaining {
182
+ display: flex;
183
+ width: fn.px-to-rem(24);
184
+ height: fn.px-to-rem(24);
185
+ align-items: center;
186
+ justify-content: center;
187
+ border-radius: var(--cp-radius-sm);
188
+ background: var(--cp-background-tertiary);
189
+ font-size: var(--cp-text-size-xs);
190
+ font-weight: 600;
191
+ line-height: var(--cp-line-height-xs);
192
+ }
193
+
194
+ &__tooltip {
195
+ display: inline-flex;
196
+ width: 100%;
197
+ justify-content: center;
198
+ padding-block: var(--cp-spacing-sm);
199
+ }
200
+
201
+ &__summary {
202
+ @extend %u-text-ellipsis;
203
+
204
+ color: var(--cp-text-secondary);
205
+ font-size: var(--cp-text-size-xs);
206
+ line-height: var(--cp-line-height-xs);
207
+
208
+ &:has(.cpTripTimeline__stop) {
209
+ border-bottom: 1px dashed var(--cp-border-strong);
210
+ cursor: help;
211
+ }
212
+
213
+ span:not(:first-child)::before {
214
+ color: var(--cp-text-secondary);
215
+ content: "•";
216
+ font-size: var(--cp-text-size-xs);
217
+ letter-spacing: var(--cp-letter-spacing-xs);
218
+ line-height: var(--cp-line-height-xs);
219
+ margin-inline: var(--cp-spacing-xs);
220
+ }
221
+ }
222
+
223
+ &__transfer {
224
+ color: var(--cp-text-error-primary);
225
+ text-transform: capitalize;
226
+ }
227
+
228
+ &__stops {
229
+ max-width: fn.px-to-rem(300);
230
+ }
231
+
232
+ &__stops li hr {
233
+ border-radius: var(--cp-radius-md);
234
+ margin-block: var(--cp-spacing-md);
235
+ }
236
+
237
+ &__stops li:last-child hr {
238
+ display: none;
239
+ }
240
+ }
241
+
242
+ @include mx.media-query-max(370px) {
243
+ .cpTripTimeline {
244
+ &__dotWrapper {
245
+ display: none;
246
+ }
247
+ }
248
+ }
249
+
250
+ @include mx.media-query-max(300px) {
251
+ .cpTripTimeline {
252
+ &__information {
253
+ padding-block: 0;
254
+
255
+ &::before,
256
+ &::after {
257
+ display: none;
258
+ }
259
+ }
260
+
261
+ &__remaining {
262
+ width: fn.px-to-rem(20);
263
+ height: fn.px-to-rem(20);
264
+ font-size: fn.px-to-rem(10);
265
+ }
266
+
267
+ &__tooltip {
268
+ padding-block: var(--cp-spacing-xs);
269
+ }
270
+ }
271
+ }
272
+ </style>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
3
+ <path d="M16 11.9999C16 9.02546 18.1644 6.55652 21.0042 6.08217C21.5489 5.99118 22 6.44763 22 6.99992C22 7.5522 21.5453 7.98709 21.0101 8.12334C19.2798 8.56386 18 10.1324 18 11.9999C18 13.8674 19.2798 15.436 21.0101 15.8765C21.5453 16.0127 22 16.4476 22 16.9999C22 17.5522 21.5489 18.0087 21.0042 17.9177C18.1644 17.4433 16 14.9744 16 11.9999ZM11.5859 12.9999L9.29297 15.2929C8.90244 15.6834 8.90244 16.3164 9.29297 16.7069C9.68349 17.0975 10.3165 17.0975 10.707 16.7069L14.6967 12.7173C14.8838 12.5356 15 12.2813 15 11.9999C15 11.7185 14.8838 11.4642 14.6967 11.2825L10.707 7.29288C10.3165 6.90236 9.68349 6.90236 9.29297 7.29288C8.90244 7.68341 8.90244 8.31642 9.29297 8.70695L11.5859 10.9999H2C1.44772 10.9999 1 11.4476 1 11.9999C1 12.5522 1.44772 12.9999 2 12.9999H11.5859Z"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
3
+ <path d="M2 6.99992C2 6.44763 2.45108 5.99118 2.99581 6.08217C5.83559 6.55653 8 9.02546 8 11.9999C8 14.9744 5.83559 17.4433 2.99581 17.9177C2.45107 18.0087 2 17.5522 2 16.9999C2 16.4476 2.45467 16.0127 2.98988 15.8765C4.72024 15.436 6 13.8674 6 11.9999C6 10.1324 4.72024 8.56386 2.98988 8.12334C2.45467 7.98709 2 7.5522 2 6.99992ZM19.5859 13H10C9.44771 13 9 12.5523 9 12C9 11.4478 9.44771 11 10 11H19.5859L17.293 8.70707C16.9024 8.31655 16.9024 7.68353 17.293 7.29301C17.6835 6.90248 18.3165 6.90248 18.707 7.29301L22.707 11.293C23.0976 11.6835 23.0976 12.3165 22.707 12.7071L18.707 16.7071C18.3165 17.0976 17.6835 17.0976 17.293 16.7071C16.9024 16.3165 16.9024 15.6835 17.293 15.293L19.5859 13Z"/>
4
+ </svg>
5
+ </template>
@@ -8,11 +8,10 @@ import { vTooltip } from 'floating-vue'
8
8
  import { vMaska } from 'maska/vue'
9
9
  import PrimeVue from 'primevue/config'
10
10
  import ToastService from 'primevue/toastservice'
11
+ import type { App, Plugin } from 'vue'
11
12
  import { BindOnceDirective } from 'vue-bind-once'
12
13
  import VueTelInput from 'vue-tel-input'
13
14
 
14
- import type { App, Plugin } from 'vue'
15
-
16
15
  import ClickOutside from '../directives/ClickOutside'
17
16
  import CpCoreDatepicker from '../libs/CoreDatepicker.vue'
18
17
  import CpAccordion from './CpAccordion.vue'
@@ -60,6 +59,7 @@ import CpTransitionListItems from './CpTransitionListItems.vue'
60
59
  import CpTransitionSize from './CpTransitionSize.vue'
61
60
  import CpTransitionSlide from './CpTransitionSlide.vue'
62
61
  import CpTransitionTabContent from './CpTransitionTabContent.vue'
62
+ import CpTrip from './CpTrip.vue'
63
63
  import IconAirline from './icons/IconAirline.vue'
64
64
  import IconCheckList from './icons/IconCheckList.vue'
65
65
  import IconCollapse from './icons/IconCollapse.vue'
@@ -126,6 +126,7 @@ const Components = {
126
126
  CpTransitionListItems,
127
127
  CpTransitionSlide,
128
128
  CpTransitionTabContent,
129
+ CpTrip,
129
130
  }
130
131
 
131
132
  const Pimp: Plugin = {
@@ -149,59 +150,60 @@ const Pimp: Plugin = {
149
150
  export {
150
151
  CpAccordion,
151
152
  CpAccordionGroup,
152
- CpToast,
153
- CpButtonToggle,
153
+ CpAirlineLogo,
154
+ CpAlert,
154
155
  CpBadge,
155
- CpTabs,
156
- CpHeading,
157
156
  CpButton,
158
157
  CpButtonGroup,
159
- CpDialog,
160
- CpDate,
158
+ CpButtonToggle,
159
+ CpCalendar,
160
+ CpCheckbox,
161
161
  CpContextualMenu,
162
- CpMenu,
163
- CpMenuItem,
164
- CpMenuList,
165
- CpItemActions,
166
162
  CpCoreDatepicker,
163
+ CpDate,
167
164
  CpDatepicker,
168
- CpRadioNew,
169
- CpCalendar,
170
- CpAlert,
171
- CpLoader,
165
+ CpDialog,
166
+ CpHeading,
167
+ CpIcon,
172
168
  CpInput,
173
- CpText,
174
- CpTextarea,
175
- CpSelect,
176
- CpSelectMenu,
169
+ CpItemActions,
170
+ CpLoader,
171
+ CpMenu,
172
+ CpMenuItem,
173
+ CpMenuList,
177
174
  CpMultiselect,
178
- CpCheckbox,
179
175
  CpRadio,
180
176
  CpRadioGroup,
177
+ CpRadioNew,
178
+ CpSelect,
181
179
  CpSelectableButton,
180
+ CpSelectMenu,
182
181
  CpSwitch,
183
182
  CpTable,
184
183
  CpTableColumnEditor,
185
- CpIcon,
184
+ CpTabs,
186
185
  CpTelInput,
186
+ CpText,
187
+ CpTextarea,
188
+ CpToast,
187
189
  CpTooltip,
188
- CpAirlineLogo,
189
- IconAirline,
190
- IconOta,
191
- IconSupplier,
192
- IconThirdParty,
193
- IconTooltip,
194
- IconGroupBy,
195
- IconCollapse,
196
- IconExpand,
197
- IconCheckList,
190
+ CpTransitionCounter,
198
191
  CpTransitionDialog,
199
192
  CpTransitionExpand,
200
- CpTransitionSize,
201
- CpTransitionCounter,
202
193
  CpTransitionListItems,
194
+ CpTransitionSize,
203
195
  CpTransitionSlide,
204
196
  CpTransitionTabContent,
197
+ CpTrip,
198
+ IconAirline,
199
+ IconCheckList,
200
+ IconCollapse,
201
+ IconExpand,
202
+ IconGroupBy,
203
+ IconOta,
204
+ IconSupplier,
205
+ IconThirdParty,
206
+ IconTooltip,
205
207
  }
206
208
 
207
209
  export default Pimp
@@ -0,0 +1,60 @@
1
+ import { useWindowSize } from '@vueuse/core'
2
+ import { computed, onMounted, ref } from 'vue'
3
+
4
+ import type { Sizes } from '@/constants/layout'
5
+
6
+ import { Breakpoints } from '@/constants/layout'
7
+
8
+ type SizeValue = Sizes | number
9
+
10
+ type BreakpointName = 'mobile' | 'tablet' | 'largeTablet' | 'desktop' | 'large'
11
+
12
+ const NAMED_BREAKPOINTS: Record<BreakpointName, number> = {
13
+ mobile: Breakpoints.MOBILE,
14
+ tablet: Breakpoints.TABLET,
15
+ largeTablet: Breakpoints.LARGE_TABLET,
16
+ desktop: Breakpoints.DESKTOP,
17
+ large: Breakpoints.LARGE,
18
+ }
19
+
20
+ export type DynamicSizeConfig = {
21
+ default: SizeValue
22
+ } & Partial<Record<number | BreakpointName, SizeValue>>
23
+
24
+ const resolveThreshold = (key: string): number => {
25
+ if (key in NAMED_BREAKPOINTS) {
26
+ return NAMED_BREAKPOINTS[key as BreakpointName]
27
+ }
28
+ return Number(key)
29
+ }
30
+
31
+ const resolveSize = (width: number, config: DynamicSizeConfig): SizeValue => {
32
+ const { default: defaultValue, ...breakpoints } = config
33
+
34
+ let match: SizeValue | undefined
35
+ let matchThreshold = -1
36
+
37
+ for (const [key, value] of Object.entries(breakpoints)) {
38
+ const threshold = resolveThreshold(key)
39
+ if (width <= threshold && threshold > matchThreshold) {
40
+ match = value
41
+ matchThreshold = threshold
42
+ }
43
+ }
44
+
45
+ return match ?? defaultValue
46
+ }
47
+
48
+ export const useDynamicSize = (config: DynamicSizeConfig) => {
49
+ if (import.meta.env.SSR) return config.default
50
+
51
+ const isMounted = ref(false)
52
+ onMounted(() => (isMounted.value = true))
53
+
54
+ const { width: windowWidth } = useWindowSize()
55
+
56
+ return computed(() => {
57
+ if (!isMounted.value) return config.default
58
+ return resolveSize(windowWidth.value, config)
59
+ })
60
+ }
@@ -38,6 +38,7 @@ import IconCorrosive from '@/components/icons/IconCorrosive.vue'
38
38
  import IconDashedCircle from '@/components/icons/IconDashedCircle.vue'
39
39
  import IconDedicated from '@/components/icons/IconDedicated.vue'
40
40
  import IconDeparture from '@/components/icons/IconDeparture.vue'
41
+ import IconDestination from '@/components/icons/IconDestination.vue'
41
42
  import IconDeviceForbidden from '@/components/icons/IconDeviceForbidden.vue'
42
43
  import IconDirectFlightAlt from '@/components/icons/IconDirectFlightAlt.vue'
43
44
  import IconDistribution from '@/components/icons/IconDistribution.vue'
@@ -92,6 +93,7 @@ import IconNoSeat from '@/components/icons/IconNoSeat.vue'
92
93
  import IconNotion from '@/components/icons/IconNotion.vue'
93
94
  import IconOffline from '@/components/icons/IconOffline.vue'
94
95
  import IconOneWay from '@/components/icons/IconOneWay.vue'
96
+ import IconOrigin from '@/components/icons/IconOrigin.vue'
95
97
  import IconOta from '@/components/icons/IconOta.vue'
96
98
  import IconOtaFilled from '@/components/icons/IconOtaFilled.vue'
97
99
  import IconPaid from '@/components/icons/IconPaid.vue'
@@ -173,6 +175,7 @@ export const CustomCpIcons = {
173
175
  dedicated: IconDedicated,
174
176
  departure: IconDeparture,
175
177
  'direct-flight-alt': IconDirectFlightAlt,
178
+ destination: IconDestination,
176
179
  'device-forbidden': IconDeviceForbidden,
177
180
  distribution: IconDistribution,
178
181
  'distribution-closed': IconDistributionClosed,
@@ -226,6 +229,7 @@ export const CustomCpIcons = {
226
229
  notion: IconNotion,
227
230
  offline: IconOffline,
228
231
  'one-way': IconOneWay,
232
+ origin: IconOrigin,
229
233
  ota: IconOta,
230
234
  'ota-filled': IconOtaFilled,
231
235
  paid: IconPaid,
@@ -1,10 +1,10 @@
1
1
  export type { Colors } from './colors/Colors'
2
- export { Position } from './Position'
3
2
  export type { ToggleColors } from './colors/ToggleColors'
4
- export { RESERVED_KEYS, VISIBLE_ROWS_MAX } from './CpTableConfig'
5
3
  export type { Sizes } from './Sizes'
6
4
 
7
5
  export { CustomCpIcons } from './CpCustomIcons'
6
+ export { RESERVED_KEYS, VISIBLE_ROWS_MAX } from './CpTableConfig'
8
7
  export { Intent } from './Intent'
8
+ export { Position } from './Position'
9
9
 
10
10
  export const HUMAN_MAX_AGE = 120