@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
@@ -111,98 +111,109 @@
111
111
  </div>
112
112
  </template>
113
113
 
114
- <script setup>
114
+ <script setup lang="ts">
115
115
  import { ref, computed } from 'vue'
116
116
 
117
+ import CpTableEmptyState from '@/components/lists-and-table/CpTableEmptyState.vue'
118
+
117
119
  import { camelize, decamelize } from '@/helpers/string'
120
+
121
+ import { PAGINATION_FORMATS, RESERVED_KEYS, VISIBLE_ROWS_MAX } from '@/constants'
118
122
  import { randomString } from '@/helpers'
119
123
 
120
- import CpTableEmptyState from '@/components/lists-and-table/CpTableEmptyState.vue'
124
+ const LoaderColor = '#5341F9'
121
125
 
122
- import { CpTableConfig } from '@/constants'
126
+ interface ColumnDefinition {
127
+ id: string
128
+ name: string
129
+ textAlign?: 'left' | 'center' | 'right'
130
+ width?: number
131
+ }
123
132
 
124
- const LoaderColor = '#5341F9'
133
+ interface PaginationServer {
134
+ activePage: number
135
+ total: number
136
+ }
137
+
138
+ interface Pagination {
139
+ enabled?: boolean
140
+ format?: (typeof PAGINATION_FORMATS)[keyof typeof PAGINATION_FORMATS]
141
+ limit?: number
142
+ server?: PaginationServer
143
+ }
144
+
145
+ interface RowOptions {
146
+ action: (payload: { rowData: Record<string, unknown>; rowIndex: number }, event: Event) => void
147
+ disabled?: boolean
148
+ icon: string
149
+ id: string
150
+ isCritical?: boolean
151
+ label: string
152
+ }
153
+
154
+ interface GroupByData {
155
+ groupBy: string
156
+ rows: Record<string, unknown>[]
157
+ }
125
158
 
126
- const props = defineProps({
127
- caption: {
128
- type: String,
129
- default: '',
130
- required: false,
131
- },
132
- columns: {
133
- type: Array,
134
- default: () => [],
135
- required: false,
136
- },
137
- data: {
138
- type: Array,
139
- required: true,
140
- },
141
- pagination: {
142
- type: [Boolean, Object],
143
- default: false,
144
- required: false,
145
- validator: (value) => {
146
- const isLimitValid = value.limit ? value.limit <= CpTableConfig.VISIBLE_ROWS_MAX : true
147
- const isFooterDetailsFormatValid = value.format
148
- ? Object.values(CpTableConfig.PAGINATION_FORMATS).includes(value.format)
149
- : true
150
-
151
- return isLimitValid && isFooterDetailsFormatValid
152
- },
153
- },
154
- areRowsClickable: {
155
- type: Boolean,
156
- default: false,
157
- required: false,
158
- },
159
- emptyCellPlaceholder: {
160
- type: String,
161
- default: 'n/a',
162
- required: false,
163
- },
164
- noResultPlaceholder: {
165
- type: String,
166
- default: 'No results found',
167
- required: false,
168
- },
169
- isLoading: {
170
- type: Boolean,
171
- default: false,
172
- required: false,
173
- },
174
- enableRowOptions: {
175
- type: Boolean,
176
- default: false,
177
- required: false,
178
- },
179
- quickOptionsLimit: {
180
- type: Number,
181
- default: 3,
182
- required: false,
183
- },
184
- rowOptions: {
185
- type: Array,
186
- default: () => [],
187
- required: false,
188
- },
159
+ interface Props {
160
+ areRowsClickable?: boolean
161
+ caption?: string
162
+ columns?: string[] | ColumnDefinition[]
163
+ data: (Record<string, unknown> | GroupByData)[]
164
+ emptyCellPlaceholder?: string
165
+ enableRowOptions?: boolean
166
+ isLoading?: boolean
167
+ noResultPlaceholder?: string
168
+ pagination?: Pagination
169
+ quickOptionsLimit?: number
170
+ rowOptions?: RowOptions[]
171
+ }
172
+
173
+ const props = withDefaults(defineProps<Props>(), {
174
+ caption: '',
175
+ columns: () => [],
176
+ pagination: undefined,
177
+ areRowsClickable: false,
178
+ emptyCellPlaceholder: 'n/a',
179
+ noResultPlaceholder: 'No results found',
180
+ isLoading: false,
181
+ enableRowOptions: false,
182
+ quickOptionsLimit: 3,
183
+ rowOptions: () => [],
189
184
  })
190
185
 
191
- const emit = defineEmits(['onRowClick', 'onRowRightClick', 'onNextClick', 'onPreviousClick'])
186
+ interface Emits {
187
+ (e: 'onRowClick', data: Record<string, unknown>): void
188
+ (e: 'onRowRightClick', payload: { data: Record<string, unknown>; event: Event }): void
189
+ (e: 'onNextClick'): void
190
+ (e: 'onPreviousClick'): void
191
+ }
192
+
193
+ const emit = defineEmits<Emits>()
192
194
 
193
195
  const uniqueId = ref(randomString())
194
196
  const pageNumber = ref(0)
195
- const cpTableContainer = ref(null)
197
+ const cpTableContainer = ref<HTMLElement | null>(null)
196
198
 
197
199
  const hasQuickOptions = computed(() => !!quickOptions.value.length)
198
200
  const hasMoreQuickActionsThanLimit = computed(() => props.rowOptions.length >= props.quickOptionsLimit)
199
201
 
200
- const defaultRowOptions = computed(() => {
201
- if (!props.enableRowOptions || !props.rowOptions.length) return {}
202
+ const defaultRowOptions = computed<RowOptions>(() => {
203
+ if (!props.enableRowOptions || !props.rowOptions.length) {
204
+ return {
205
+ id: 'default',
206
+ label: 'More',
207
+ icon: 'more-vertical',
208
+ action: () => {},
209
+ }
210
+ }
202
211
  return {
212
+ id: 'more',
203
213
  label: 'More',
204
214
  icon: 'more-vertical',
205
- action: ({ rowData, rowIndex }, $event) => handleRowRightClick({ rowData, rowIndex }, $event),
215
+ action: ({ rowData, rowIndex }: { rowData: Record<string, unknown>; rowIndex: number }, $event: Event) =>
216
+ handleRowRightClick({ rowData, rowIndex }, $event),
206
217
  }
207
218
  })
208
219
 
@@ -222,7 +233,7 @@ const containerDOMElement = computed(() => cpTableContainer.value)
222
233
  const mainClasses = computed(() => ({ 'cpTable--isLoading': props.isLoading }))
223
234
  const containerClasses = computed(() => ({ 'cpTable__container--hasPagination': hasPagination.value }))
224
235
 
225
- const normalizedColumns = computed(() => {
236
+ const normalizedColumns = computed<ColumnDefinition[]>(() => {
226
237
  if (!props.columns) return []
227
238
  const columns = props.columns.length ? [...props.columns] : [...columnsFromRows.value]
228
239
 
@@ -235,8 +246,8 @@ const normalizedColumns = computed(() => {
235
246
  }
236
247
 
237
248
  return {
238
- id: column.id || camelize(column.name),
239
249
  ...column,
250
+ id: column.id || camelize(column.name),
240
251
  }
241
252
  })
242
253
  })
@@ -245,30 +256,39 @@ const numberOfColumns = computed(() => normalizedColumns.value.length)
245
256
 
246
257
  const hasGroupBy = computed(() => {
247
258
  if (!props.data.length) return false
248
- return props.data.some((item) => CpTableConfig.RESERVED_KEYS.GROUP_BY in item)
259
+ return props.data.some((item) => RESERVED_KEYS.GROUP_BY in item)
249
260
  })
250
261
 
251
262
  const columnsFromRows = computed(() => {
252
263
  if (!props.data.length) return []
253
- const firstRow = hasGroupBy.value ? props.data[0].rows[0] : props.data[0]
254
- return Object.keys(firstRow)
264
+ const firstItem = props.data[0]
265
+ const firstRow = hasGroupBy.value && 'rows' in firstItem ? (firstItem as GroupByData).rows[0] : firstItem
266
+ return Object.keys(firstRow as Record<string, unknown>)
255
267
  })
256
268
 
257
269
  const numberOfResults = computed(() => {
258
- return isServerSidePagination.value ? props.pagination.server.total : flattenedRows.value.length
270
+ return isServerSidePagination.value ? props.pagination?.server?.total || 0 : flattenedRows.value.length
259
271
  })
260
272
 
261
273
  const hasNoResult = computed(() => numberOfResults.value === 0)
262
- const rowsPerPageLimit = computed(() => props.pagination.limit || CpTableConfig.VISIBLE_ROWS_MAX)
274
+ const rowsPerPageLimit = computed(() => {
275
+ if (typeof props.pagination === 'object' && props.pagination.limit) {
276
+ return props.pagination.limit
277
+ }
278
+ return VISIBLE_ROWS_MAX
279
+ })
263
280
 
264
281
  const flattenedRows = computed(() => {
265
282
  if (!props.data) return []
266
- if (!hasGroupBy.value) return props.data
283
+ if (!hasGroupBy.value) return props.data as Record<string, unknown>[]
267
284
 
268
- // Transform groupBy key into a row and add it in between others
269
- return props.data.reduce((flattenedRows, groupByItem) => {
270
- const fullWidthRow = { [CpTableConfig.RESERVED_KEYS.GROUP_BY]: groupByItem.groupBy }
271
- return [...flattenedRows, fullWidthRow, ...groupByItem.rows]
285
+ return props.data.reduce((flattenedRows: Record<string, unknown>[], item) => {
286
+ if ('groupBy' in item) {
287
+ const groupByItem = item as GroupByData
288
+ const fullWidthRow = { [RESERVED_KEYS.GROUP_BY]: groupByItem.groupBy }
289
+ return [...flattenedRows, fullWidthRow, ...groupByItem.rows]
290
+ }
291
+ return [...flattenedRows, item as Record<string, unknown>]
272
292
  }, [])
273
293
  })
274
294
 
@@ -286,11 +306,16 @@ const visibleRows = computed(() =>
286
306
  )
287
307
 
288
308
  const paginationState = computed(() => {
289
- return typeof props.pagination === 'boolean' ? props.pagination : props.pagination.enabled
309
+ return typeof props.pagination === 'boolean' ? props.pagination : props.pagination?.enabled
290
310
  })
291
311
 
292
- const hasPagination = computed(() => paginationState.value || numberOfResults.value > CpTableConfig.VISIBLE_ROWS_MAX)
293
- const paginationFormat = computed(() => props.pagination?.format || CpTableConfig.PAGINATION_FORMATS.PAGES)
312
+ const hasPagination = computed(() => paginationState.value || numberOfResults.value > VISIBLE_ROWS_MAX)
313
+ const paginationFormat = computed(() => {
314
+ if (typeof props.pagination === 'object' && props.pagination.format) {
315
+ return props.pagination.format
316
+ }
317
+ return PAGINATION_FORMATS.PAGES
318
+ })
294
319
  const hasRemainingPages = computed(() => numberOfPages.value > activePage.value)
295
320
  const isNextEnabled = computed(() => hasRemainingPages.value && !props.isLoading)
296
321
 
@@ -307,11 +332,11 @@ const activePage = computed(() => {
307
332
  })
308
333
 
309
334
  const isServerSidePagination = computed(() => {
310
- if (typeof props.pagination === 'boolean') return false
335
+ if (!props.pagination) return false
311
336
  return 'server' in props.pagination
312
337
  })
313
338
 
314
- const serverActivePage = computed(() => props.pagination.server.activePage)
339
+ const serverActivePage = computed(() => props.pagination?.server?.activePage || 0)
315
340
  const serverPagesStartIndex = computed(() => serverActivePage.value * rowsPerPageLimit.value + 1)
316
341
  const serverPagesEndIndex = computed(() => rowsPerPageLimit.value * (1 + serverActivePage.value))
317
342
 
@@ -325,7 +350,7 @@ const pageLastResultIndex = computed(() => {
325
350
  })
326
351
 
327
352
  const paginationLabel = computed(() => {
328
- if (paginationFormat.value === CpTableConfig.PAGINATION_FORMATS.PAGES) {
353
+ if (paginationFormat.value === PAGINATION_FORMATS.PAGES) {
329
354
  const pluralizedCount = numberOfPages.value > 1 ? 'pages' : 'page'
330
355
  return `${activePage.value}/${numberOfPages.value} ${pluralizedCount}`
331
356
  }
@@ -338,22 +363,25 @@ const paginationResultsDetails = computed(() => {
338
363
  return `${formattedNumberOfResults} ${pluralizedCount}`
339
364
  })
340
365
 
341
- const getQuickOptionTooltip = (option) => (!option.disabled ? option.label : '')
366
+ const getQuickOptionTooltip = (option: RowOptions) => (!option.disabled ? option.label : '')
342
367
 
343
- const getQuickOptionClasses = (option) => {
368
+ const getQuickOptionClasses = (option: RowOptions) => {
344
369
  return { 'cpTable__action--isCritical': option.isCritical }
345
370
  }
346
371
 
347
- const getRowPayload = (rowIndex) => rawVisibleRows.value[rowIndex]
372
+ const getRowPayload = (rowIndex: number) => rawVisibleRows.value[rowIndex]
348
373
 
349
- const handleRowClick = (rowData, rowIndex) => {
374
+ const handleRowClick = (rowData: Record<string, unknown>, rowIndex: number) => {
350
375
  if (isFullWidthRow(rowData)) return
351
376
 
352
377
  const data = getRowPayload(rowIndex)
353
378
  emit('onRowClick', data)
354
379
  }
355
380
 
356
- const handleRowRightClick = ({ rowData, rowIndex }, event) => {
381
+ const handleRowRightClick = (
382
+ { rowData, rowIndex }: { rowData: Record<string, unknown>; rowIndex: number },
383
+ event: Event,
384
+ ) => {
357
385
  if (isFullWidthRow(rowData)) return
358
386
 
359
387
  const data = getRowPayload(rowIndex)
@@ -375,7 +403,13 @@ const handleNavigationClick = (isNext = true) => {
375
403
  emit('onPreviousClick')
376
404
  }
377
405
 
378
- const normalizeRowData = ({ columns = normalizedColumns.value, rowPayload }) => {
406
+ const normalizeRowData = ({
407
+ columns = normalizedColumns.value,
408
+ rowPayload,
409
+ }: {
410
+ columns?: ColumnDefinition[]
411
+ rowPayload: Record<string, unknown>
412
+ }) => {
379
413
  if (!Array.isArray(rowPayload)) {
380
414
  return { ...rowPayload }
381
415
  }
@@ -390,12 +424,18 @@ const normalizeRowData = ({ columns = normalizedColumns.value, rowPayload }) =>
390
424
  }, {})
391
425
  }
392
426
 
393
- const mapCellToColumn = ({ columns = normalizedColumns.value, rowPayload }) => {
427
+ const mapCellToColumn = ({
428
+ columns = normalizedColumns.value,
429
+ rowPayload,
430
+ }: {
431
+ columns?: ColumnDefinition[]
432
+ rowPayload: Record<string, unknown>
433
+ }) => {
394
434
  if (isFullWidthRow(rowPayload)) return rowPayload
395
435
  // Bind column id with each row key
396
436
  // and replace row missing keys with the emptyCellPlaceholder value
397
437
  return columns.reduce((finalRow, currentColumn) => {
398
- const correspondingColumn = currentColumn?.id || currentColumn
438
+ const correspondingColumn = currentColumn.id
399
439
  const correspondingValue = rowPayload[correspondingColumn] || props.emptyCellPlaceholder
400
440
  const cellValue = { [correspondingColumn]: correspondingValue }
401
441
 
@@ -411,9 +451,13 @@ const decreaseOffset = () => {
411
451
  if (isPreviousEnabled.value) pageNumber.value--
412
452
  }
413
453
 
414
- const resetScrollPosition = () => (containerDOMElement.value.scrollTop = 0)
454
+ const resetScrollPosition = () => {
455
+ if (containerDOMElement.value) {
456
+ containerDOMElement.value.scrollTop = 0
457
+ }
458
+ }
415
459
 
416
- const getColumnStyle = (columnPayload) => {
460
+ const getColumnStyle = (columnPayload: ColumnDefinition) => {
417
461
  const formattedWidth = columnPayload?.width && `${columnPayload.width}px`
418
462
 
419
463
  return {
@@ -422,14 +466,14 @@ const getColumnStyle = (columnPayload) => {
422
466
  }
423
467
  }
424
468
 
425
- const getCellStyle = (cellKey, columnIndex) => {
469
+ const getCellStyle = (cellKey: RESERVED_KEYS, cellIndex: number) => {
426
470
  if (isFullWidthCell(cellKey)) return null
427
471
  return {
428
- textAlign: normalizedColumns.value[columnIndex]?.textAlign,
472
+ textAlign: normalizedColumns.value[cellIndex]?.textAlign,
429
473
  }
430
474
  }
431
475
 
432
- const getRowClasses = (rowData, rowIndex) => {
476
+ const getRowClasses = (rowData: Record<string, unknown>, rowIndex: number) => {
433
477
  return {
434
478
  'cpTable__row--isFullWidth': isFullWidthRow(rowData),
435
479
  'cpTable__row--isClickable': !isFullWidthRow(rowData) && props.areRowsClickable,
@@ -437,24 +481,26 @@ const getRowClasses = (rowData, rowIndex) => {
437
481
  }
438
482
  }
439
483
 
440
- const getCellClasses = (cellKey) => {
484
+ const getCellClasses = (cellKey: RESERVED_KEYS) => {
441
485
  return { 'cpTable__cell--isFullWidth': isFullWidthCell(cellKey) }
442
486
  }
443
487
 
444
- const getColspan = (cellKey) => {
488
+ const getColspan = (cellKey: RESERVED_KEYS) => {
445
489
  const numberOfColumnsValue = props.enableRowOptions ? numberOfColumns.value + 1 : numberOfColumns.value
446
- return isFullWidthCell(cellKey) ? numberOfColumnsValue : null
490
+ return isFullWidthCell(cellKey) ? numberOfColumnsValue : undefined
447
491
  }
448
492
 
449
- const getTabindex = (rowData) => (isFullWidthRow(rowData) ? -1 : 0)
450
-
451
- const fullWidthCellKeys = [CpTableConfig.RESERVED_KEYS.FULL_WIDTH, CpTableConfig.RESERVED_KEYS.GROUP_BY]
493
+ const getTabindex = (rowData: Record<string, unknown>) => (isFullWidthRow(rowData) ? -1 : 0)
452
494
 
453
- const isFullWidthCell = (cellKey) => fullWidthCellKeys.includes(cellKey)
454
- const isFullWidthRow = (rowData) => fullWidthCellKeys.some((key) => rowData[key])
495
+ const fullWidthCellKeys = [RESERVED_KEYS.FULL_WIDTH, RESERVED_KEYS.GROUP_BY]
496
+ const isFullWidthCell = (cellKey: RESERVED_KEYS) => fullWidthCellKeys.includes(cellKey)
497
+ const isFullWidthRow = (rowData: Record<string, unknown>) => fullWidthCellKeys.some((key) => rowData[key])
455
498
 
456
- const isRowSelected = (rowIndex) => rawVisibleRows.value[rowIndex][CpTableConfig.RESERVED_KEYS.IS_SELECTED]
457
- const areRowOptionsEnabled = (rowData) => props.enableRowOptions && !isFullWidthRow(rowData)
499
+ const isRowSelected = (rowIndex: number) => {
500
+ const row = rawVisibleRows.value[rowIndex] as Record<string, unknown>
501
+ return row?.[RESERVED_KEYS.IS_SELECTED] || false
502
+ }
503
+ const areRowOptionsEnabled = (rowData: Record<string, unknown>) => props.enableRowOptions && !isFullWidthRow(rowData)
458
504
 
459
505
  const resetPagination = () => (pageNumber.value = 0)
460
506
 
@@ -679,12 +725,17 @@ defineExpose({ resetPagination })
679
725
  @media (hover: hover) and (pointer: fine) {
680
726
  &__cell--isOptions {
681
727
  opacity: 0;
728
+ min-width: fn.px-to-rem(50);
682
729
  transition: opacity 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.175);
683
730
  }
684
731
 
685
732
  // Actions wrapper on desktop : displayed only if there are quick actions inside
686
733
  &__cell--isOptions:has(.cpTable__action) .cpTable__actions {
687
- display: flex;
734
+ position: absolute;
735
+ top: 50%;
736
+ transform: translateY(-50%);
737
+ right: fn.px-to-rem(12);
738
+ display: inline-flex;
688
739
  overflow: hidden;
689
740
  border: 1px solid colors.$border-color;
690
741
  border-radius: fn.px-to-rem(8);
@@ -10,15 +10,12 @@
10
10
  </div>
11
11
  </template>
12
12
 
13
- <script>
14
- export default {
15
- props: {
16
- placeholder: {
17
- type: String,
18
- required: true,
19
- },
20
- },
13
+ <script setup lang="ts">
14
+ interface Props {
15
+ placeholder: string
21
16
  }
17
+
18
+ defineProps<Props>()
22
19
  </script>
23
20
 
24
21
  <style lang="scss">
@@ -67,96 +67,61 @@
67
67
  </div>
68
68
  </template>
69
69
 
70
- <script setup>
71
- import { ref, computed, onMounted } from 'vue'
72
- import AutoComplete from 'primevue/autocomplete'
73
-
70
+ <script setup lang="ts">
74
71
  import { absolutePosition, getOuterWidth } from '@primeuix/utils/dom'
72
+ import AutoComplete from 'primevue/autocomplete'
73
+ import { ref, computed, onMounted } from 'vue'
75
74
 
76
75
  import BaseInputLabel from '@/components/core/BaseInputLabel.vue'
77
- import TransitionExpand from '@/components/helpers-utilities/TransitionExpand.vue'
78
76
  import BaseSelectClearButton from '@/components/core/BaseSelectClearButton.vue'
77
+ import TransitionExpand from '@/components/helpers-utilities/TransitionExpand.vue'
79
78
 
80
79
  import { isEmpty } from '@/helpers/object'
81
80
 
82
- const props = defineProps({
83
- label: {
84
- type: String,
85
- required: false,
86
- default: '',
87
- },
88
- required: {
89
- type: Boolean,
90
- required: false,
91
- default: false,
92
- },
93
- name: {
94
- type: String,
95
- required: false,
96
- default: '',
97
- },
98
- placeholder: {
99
- type: String,
100
- required: false,
101
- default: '',
102
- },
103
- isInvalid: {
104
- type: Boolean,
105
- required: false,
106
- default: false,
107
- },
108
- isClearable: {
109
- type: Boolean,
110
- required: false,
111
- default: false,
112
- },
113
- isLoading: {
114
- type: Boolean,
115
- required: false,
116
- default: false,
117
- },
118
- disabled: {
119
- type: Boolean,
120
- required: false,
121
- default: false,
122
- },
123
- multiple: {
124
- type: Boolean,
125
- required: false,
126
- default: false,
127
- },
128
- options: {
129
- type: Array,
130
- required: false,
131
- default: () => [],
132
- },
133
- optionLabel: {
134
- type: String,
135
- required: false,
136
- default: 'name',
137
- },
138
- trackBy: {
139
- type: String,
140
- required: false,
141
- default: 'id',
142
- },
143
- emptyMessage: {
144
- type: String,
145
- required: false,
146
- default: 'No results found',
147
- },
148
- errorMessage: {
149
- type: String,
150
- required: false,
151
- default: '',
152
- },
153
- modelValue: {
154
- type: [Array, Object],
155
- required: false,
156
- },
81
+ interface Props {
82
+ disabled?: boolean
83
+ emptyMessage?: string
84
+ errorMessage?: string
85
+ isClearable?: boolean
86
+ isInvalid?: boolean
87
+ isLoading?: boolean
88
+ label?: string
89
+ modelValue?: Record<string, unknown>[] | Record<string, unknown> | null
90
+ multiple?: boolean
91
+ name?: string
92
+ optionLabel?: string
93
+ options?: unknown[]
94
+ placeholder?: string
95
+ required?: boolean
96
+ trackBy?: string
97
+ }
98
+
99
+ const props = withDefaults(defineProps<Props>(), {
100
+ label: '',
101
+ required: false,
102
+ name: '',
103
+ placeholder: '',
104
+ isInvalid: false,
105
+ isClearable: false,
106
+ isLoading: false,
107
+ disabled: false,
108
+ multiple: false,
109
+ options: () => [],
110
+ optionLabel: 'name',
111
+ trackBy: 'id',
112
+ emptyMessage: 'No results found',
113
+ errorMessage: '',
114
+ modelValue: null,
157
115
  })
158
116
 
159
- const emit = defineEmits(['search', 'select', 'clear'])
117
+ interface Emits {
118
+ (e: 'search', query: string): void
119
+ (e: 'select', option: Record<string, unknown>): void
120
+ (e: 'clear'): void
121
+ (e: 'update:modelValue', value: Record<string, unknown> | Record<string, unknown>[] | null): void
122
+ }
123
+
124
+ const emit = defineEmits<Emits>()
160
125
 
161
126
  const selectModel = computed({
162
127
  get() {
@@ -183,7 +148,7 @@ const passThroughConfig = {
183
148
  loader: { class: 'cpMultiselect__hidden' },
184
149
  }
185
150
 
186
- const multiselect = ref(null)
151
+ const multiselect = ref<InstanceType<typeof AutoComplete> | null>(null)
187
152
 
188
153
  const isDropdownOpen = computed(() => multiselect.value?.overlayVisible)
189
154
 
@@ -203,29 +168,33 @@ const displayClearButton = computed(() => {
203
168
  return props.isClearable && !isEmpty(selectModel.value)
204
169
  })
205
170
 
206
- const handleSearch = (event) => emit('search', event.query)
171
+ const handleSearch = (event: { query: string }) => emit('search', event.query)
207
172
  const handleClear = () => (selectModel.value = null)
208
173
 
209
174
  const toggleDropdown = () => {
210
175
  if (isDropdownOpen.value) {
211
- multiselect.value.hide()
176
+ multiselect.value?.hide()
212
177
  } else {
213
- multiselect.value.show()
178
+ multiselect.value?.show()
214
179
  }
215
180
  }
216
181
 
217
- const handleUpdateModelValue = (value) => {
182
+ const handleUpdateModelValue = (value: Record<string, unknown> | null) => {
218
183
  // Autocomplete will set the model value to the query string if not blocked
219
184
  if (!value || typeof value === 'string') {
220
185
  return
221
186
  }
222
187
  }
223
188
 
224
- const overrideAlignOverlay = () => (multiselect.value.alignOverlay = alignOverlay)
189
+ const overrideAlignOverlay = () => {
190
+ if (multiselect.value) {
191
+ multiselect.value.alignOverlay = alignOverlay
192
+ }
193
+ }
225
194
 
226
195
  const alignOverlay = () => {
227
- const target = multiselect.value.$el
228
- if (!multiselect.value.overlay || !target) return
196
+ const target = multiselect.value?.$el
197
+ if (!multiselect.value?.overlay || !target) return
229
198
 
230
199
  multiselect.value.overlay.style.width = `${getOuterWidth(target)}px`
231
200