classcard-ui 0.2.1473 → 0.2.1475

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 (209) hide show
  1. package/README.md +24 -24
  2. package/dist/classcard-ui.common.js +413 -135
  3. package/dist/classcard-ui.common.js.map +1 -1
  4. package/dist/classcard-ui.css +2 -2
  5. package/dist/classcard-ui.umd.js +413 -135
  6. package/dist/classcard-ui.umd.js.map +1 -1
  7. package/dist/classcard-ui.umd.min.js +3 -3
  8. package/dist/classcard-ui.umd.min.js.map +1 -1
  9. package/package.json +83 -83
  10. package/src/App.vue +16 -16
  11. package/src/colorConfig.js +52 -52
  12. package/src/components/CAlertModal/CAlertModal.vue +179 -179
  13. package/src/components/CAlertModal/index.js +3 -3
  14. package/src/components/CAlerts/CAlerts.vue +114 -114
  15. package/src/components/CAlerts/index.js +2 -2
  16. package/src/components/CAnchorTabs/CAnchorTabs.vue +100 -100
  17. package/src/components/CAnchorTabs/index.js +2 -2
  18. package/src/components/CAnchorTag/CAnchorTag.vue +84 -84
  19. package/src/components/CAnchorTag/index.js +2 -2
  20. package/src/components/CAvatar/CAvatar.vue +230 -230
  21. package/src/components/CAvatar/index.js +2 -2
  22. package/src/components/CAvatarGroup/CAvatarGroup.vue +213 -213
  23. package/src/components/CAvatarGroup/index.js +2 -2
  24. package/src/components/CBasicTable/CBasicTable.vue +184 -184
  25. package/src/components/CBasicTable/index.js +2 -2
  26. package/src/components/CBreadcrumbs/CBreadcrumbs.vue +38 -38
  27. package/src/components/CBreadcrumbs/index.js +2 -2
  28. package/src/components/CButton/CButton.vue +239 -239
  29. package/src/components/CButton/index.js +2 -2
  30. package/src/components/CButtonGroup/CButtonGroup.vue +155 -155
  31. package/src/components/CButtonGroup/index.js +2 -2
  32. package/src/components/CButtonIcon/CButtonIcon.vue +166 -166
  33. package/src/components/CButtonIcon/index.js +2 -2
  34. package/src/components/CButtonLink/CButtonLink.vue +43 -43
  35. package/src/components/CButtonLink/index.js +2 -2
  36. package/src/components/CButtonSelect/CButtonSelect.vue +186 -186
  37. package/src/components/CButtonSelect/index.js +2 -2
  38. package/src/components/CButtonSelectBorder/CButtonSelectBorder.vue +265 -265
  39. package/src/components/CButtonSelectBorder/index.js +3 -3
  40. package/src/components/CButtonWithDropdown/CButtonWithDropdown.vue +152 -152
  41. package/src/components/CButtonWithDropdown/index.js +2 -2
  42. package/src/components/CCalendar/CCalendar.vue +443 -443
  43. package/src/components/CCalendar/index.js +3 -3
  44. package/src/components/CCard/CCard.vue +53 -53
  45. package/src/components/CCard/index.js +2 -2
  46. package/src/components/CCheckbox/CCheckbox.vue +200 -200
  47. package/src/components/CCheckbox/index.js +2 -2
  48. package/src/components/CCircularButton/CCircularButton.vue +57 -57
  49. package/src/components/CCircularButton/index.js +2 -2
  50. package/src/components/CCollapsibleSection/CCollapsibleSection.vue +121 -121
  51. package/src/components/CCollapsibleSection/index.js +2 -2
  52. package/src/components/CColorDots/CColorDots.vue +52 -52
  53. package/src/components/CColorDots/index.js +3 -3
  54. package/src/components/CConfirmActionModal/CConfirmActionModal.vue +221 -221
  55. package/src/components/CConfirmActionModal/index.js +3 -3
  56. package/src/components/CDatepicker/CDatepicker.vue +235 -235
  57. package/src/components/CDatepicker/index.js +2 -2
  58. package/src/components/CDualSelect/CDualSelect.vue +193 -193
  59. package/src/components/CDualSelect/index.js +2 -2
  60. package/src/components/CEditor/CEditor.vue +114 -114
  61. package/src/components/CEditor/index.js +2 -2
  62. package/src/components/CFormSectionHeading/CFormSectionHeading.vue +76 -76
  63. package/src/components/CFormSectionHeading/index.js +2 -2
  64. package/src/components/CGroupedFilterDropdown/CGroupedFilterDropdown.vue +263 -263
  65. package/src/components/CGroupedFilterDropdown/index.js +2 -2
  66. package/src/components/CGroupedSelect/CGroupedSelect.vue +366 -366
  67. package/src/components/CGroupedSelect/index.js +3 -3
  68. package/src/components/CIcon/CIcon.vue +112 -112
  69. package/src/components/CIcon/index.js +2 -2
  70. package/src/components/CIconDropdown/CIconDropdown.vue +206 -206
  71. package/src/components/CIconDropdown/index.js +2 -2
  72. package/src/components/CIconSelect/CIconSelect.vue +182 -182
  73. package/src/components/CIconSelect/index.js +3 -3
  74. package/src/components/CInput/CInput.vue +173 -173
  75. package/src/components/CInput/index.js +2 -2
  76. package/src/components/CInputAddon/CInputAddon.vue +297 -297
  77. package/src/components/CInputAddon/index.js +2 -2
  78. package/src/components/CInputEmail/CInputEmail.vue +107 -107
  79. package/src/components/CInputEmail/index.js +2 -2
  80. package/src/components/CInsetTabs/CInsetTabs.vue +134 -134
  81. package/src/components/CInsetTabs/index.js +3 -3
  82. package/src/components/CModalHeading/CModalHeading.vue +22 -22
  83. package/src/components/CModalHeading/index.js +2 -2
  84. package/src/components/CModuleHelpLinks/CModuleHelpLinks.vue +88 -88
  85. package/src/components/CModuleHelpLinks/index.js +3 -3
  86. package/src/components/CMultiselect/CMultiselect.vue +1170 -937
  87. package/src/components/CMultiselect/index.js +2 -2
  88. package/src/components/CMultiselectr/CMultiselectr.vue +44 -44
  89. package/src/components/CMultiselectr/index.js +2 -2
  90. package/src/components/CPageHeading/CPageHeading.vue +83 -83
  91. package/src/components/CPageHeading/index.js +2 -2
  92. package/src/components/CPagination/CPagination.vue +239 -239
  93. package/src/components/CPagination/index.js +2 -2
  94. package/src/components/CPhoneNumber/CPhoneNumber.vue +213 -213
  95. package/src/components/CPhoneNumber/index.js +2 -2
  96. package/src/components/CProgress/CProgress.vue +91 -91
  97. package/src/components/CProgress/index.js +2 -2
  98. package/src/components/CRadio/CRadio.vue +197 -197
  99. package/src/components/CRadio/index.js +2 -2
  100. package/src/components/CRadioGroup/CRadioGroup.vue +96 -96
  101. package/src/components/CRadioGroup/index.js +2 -2
  102. package/src/components/CRangeSlider/CRangeSlider.vue +55 -55
  103. package/src/components/CRangeSlider/index.js +2 -2
  104. package/src/components/CReorderableStackedList/CReorderableStackedList.vue +94 -94
  105. package/src/components/CReorderableStackedList/index.js +2 -2
  106. package/src/components/CSelect/CSelect.vue +1210 -1165
  107. package/src/components/CSelect/index.js +2 -2
  108. package/src/components/CSmallTimeline/CSmallTimeline.vue +40 -40
  109. package/src/components/CSmallTimeline/index.js +2 -2
  110. package/src/components/CStackedList/CStackedList.vue +162 -162
  111. package/src/components/CStackedList/index.js +2 -2
  112. package/src/components/CStats/CStats.vue +157 -157
  113. package/src/components/CStats/index.js +2 -2
  114. package/src/components/CSwitch/CSwitch.vue +200 -200
  115. package/src/components/CSwitch/index.js +2 -2
  116. package/src/components/CTabLazy/CTabLazy.vue +83 -83
  117. package/src/components/CTabLazy/index.js +2 -2
  118. package/src/components/CTable/CTable.vue +1114 -1114
  119. package/src/components/CTable/index.js +2 -2
  120. package/src/components/CTabs/CTabs.vue +250 -250
  121. package/src/components/CTabs/index.js +2 -2
  122. package/src/components/CTag/CTag.vue +109 -109
  123. package/src/components/CTag/index.js +2 -2
  124. package/src/components/CTextarea/CTextarea.vue +118 -118
  125. package/src/components/CTextarea/index.js +2 -2
  126. package/src/components/CTimeline/CTimeline.vue +237 -237
  127. package/src/components/CTimeline/index.js +2 -2
  128. package/src/components/CToolTip/CToolTip.vue +108 -108
  129. package/src/components/CToolTip/index.js +3 -3
  130. package/src/components/CUpload/CUpload.vue +331 -331
  131. package/src/components/CUpload/index.js +2 -2
  132. package/src/components/NumberAnimator.vue +112 -112
  133. package/src/components/index.js +57 -57
  134. package/src/helper.js +8 -8
  135. package/src/icons.js +830 -830
  136. package/src/main.js +22 -22
  137. package/src/stories/CAlertModal.stories.js +30 -30
  138. package/src/stories/CAlerts.stories.js +39 -39
  139. package/src/stories/CAnchorTabs.stories.js +29 -29
  140. package/src/stories/CAnchorTag.stories.js +38 -38
  141. package/src/stories/CAvatar.stories.js +38 -38
  142. package/src/stories/CAvatarGroup.stories.js +136 -136
  143. package/src/stories/CBasicTable.stories.js +316 -316
  144. package/src/stories/CBreadcrumbs.stories.js +24 -24
  145. package/src/stories/CButton.stories.js +49 -49
  146. package/src/stories/CButtonGroup.stories.js +43 -43
  147. package/src/stories/CButtonIcon.stories.js +27 -27
  148. package/src/stories/CButtonLink.stories.js +24 -24
  149. package/src/stories/CButtonSelect.stories.js +44 -44
  150. package/src/stories/CButtonSelectBorder.stories.js +56 -56
  151. package/src/stories/CButtonWithDropdown.stories.js +41 -41
  152. package/src/stories/CCalendar.stories.js +16 -16
  153. package/src/stories/CCard.stories.js +30 -30
  154. package/src/stories/CCheckbox.stories.js +38 -38
  155. package/src/stories/CCircularButton.stories.js +29 -29
  156. package/src/stories/CCollapsibleSection.stories.js +29 -29
  157. package/src/stories/CColorDots.stories.js +37 -37
  158. package/src/stories/CConfirmActionModal.stories.js +60 -60
  159. package/src/stories/CDatepicker.stories.js +31 -31
  160. package/src/stories/CDualSelect.stories.js +29 -29
  161. package/src/stories/CEditor.stories.js +30 -30
  162. package/src/stories/CFormSectionHeading.stories.js +37 -37
  163. package/src/stories/CGroupedFilterDropdown.stories.js +176 -176
  164. package/src/stories/CGroupedSelect.stories.js +103 -103
  165. package/src/stories/CIcon.stories.js +31 -31
  166. package/src/stories/CIconDropdown.stories.js +52 -52
  167. package/src/stories/CIconSelect.stories.js +45 -45
  168. package/src/stories/CInput.stories.js +36 -36
  169. package/src/stories/CInputAddon.stories.js +37 -37
  170. package/src/stories/CInputEmail.stories.js +27 -27
  171. package/src/stories/CInsetTabs.stories.js +48 -48
  172. package/src/stories/CModalHeading.stories.js +25 -25
  173. package/src/stories/CModuleHelpLinks.stories.js +25 -25
  174. package/src/stories/CMultiselect.stories.js +136 -136
  175. package/src/stories/CMultiselectr.stories.js +23 -23
  176. package/src/stories/CPageHeading.stories.js +32 -32
  177. package/src/stories/CPagination.stories.js +30 -30
  178. package/src/stories/CPhoneNumber.stories.js +37 -37
  179. package/src/stories/CProgress.stories.js +23 -23
  180. package/src/stories/CRadio.stories.js +44 -44
  181. package/src/stories/CRadioGroup.stories.js +51 -51
  182. package/src/stories/CRangeSlider.stories.js +23 -23
  183. package/src/stories/CReorderableStackedList.stories.js +23 -23
  184. package/src/stories/CSelect.stories.js +157 -157
  185. package/src/stories/CSmallTimeline.stories.js +26 -26
  186. package/src/stories/CStackedList.stories.js +37 -37
  187. package/src/stories/CStats.stories.js +53 -53
  188. package/src/stories/CSwitch.stories.js +28 -28
  189. package/src/stories/CTabLazy.stories.js +42 -42
  190. package/src/stories/CTable.stories.js +203 -203
  191. package/src/stories/CTabs.stories.js +36 -36
  192. package/src/stories/CTag.stories.js +37 -37
  193. package/src/stories/CTextarea.stories.js +32 -32
  194. package/src/stories/CTimeline.stories.js +26 -26
  195. package/src/stories/CToolTip.stories.js +27 -27
  196. package/src/stories/CUpload.stories.js +36 -36
  197. package/src/stories/Introduction.stories.mdx +207 -207
  198. package/src/stories/Page.vue +88 -88
  199. package/src/stories/assets/code-brackets.svg +0 -0
  200. package/src/stories/assets/colors.svg +0 -0
  201. package/src/stories/assets/comments.svg +0 -0
  202. package/src/stories/assets/direction.svg +0 -0
  203. package/src/stories/assets/flow.svg +0 -0
  204. package/src/stories/assets/plugin.svg +0 -0
  205. package/src/stories/assets/repo.svg +0 -0
  206. package/src/stories/assets/stackalt.svg +0 -0
  207. package/src/stories/header.css +26 -26
  208. package/src/stories/page.css +69 -69
  209. package/src/stories/utils.css +32 -32
@@ -1,1114 +1,1114 @@
1
- <template>
2
- <div :style="cssVars">
3
- <div
4
- slot="table-actions"
5
- v-if="tableActions"
6
- class="mb-4 rounded-lg bg-gray-50 p-3"
7
- >
8
- <div class="flex items-center justify-between">
9
- <slot name="customTableFilterActions"></slot>
10
- <div v-if="searching" class="flex items-center">
11
- <c-input
12
- v-model="searchTerm"
13
- :isValidate="searching"
14
- :placeholder="searchPlaceholder"
15
- class="mr-3"
16
- :class="searchInputClass"
17
- :inputWrapperClass="inputWrapperClass"
18
- type="text"
19
- :id="id + '_input_search'"
20
- ></c-input>
21
- <slot name="tableInfo"></slot>
22
- </div>
23
- <div class="flex flex-1 justify-end">
24
- <!-- dropdown icon on top right of table -->
25
- <slot name="customTableActions"></slot>
26
- <div
27
- :class="`relative inline-block text-left ${
28
- disableColumnsDropdown ? 'pointer-events-none opacity-50' : ''
29
- }`"
30
- v-if="enableVisibility"
31
- >
32
- <!-- button to show list of columns to show hide in table -->
33
- <div v-if="showNewShowHideColumnButton" class="relative">
34
- <c-tool-tip
35
- v-if="showShowHideColumnTooltip"
36
- color="#1f2937"
37
- classes="text-white absolute -mt-12 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
38
- :isTopAligned="true"
39
- :tooltip-text="'Column Visibility, Download'"
40
- ></c-tool-tip>
41
- <button
42
- @mouseover="handleToolTipDisplay(true, 'showHideColumn')"
43
- @mouseleave="handleToolTipDisplay(false, 'showHideColumn')"
44
- @click="handleToggle"
45
- class="inline-flex h-9 items-center justify-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
46
- aria-haspopup="true"
47
- aria-expanded="true"
48
- >
49
- <c-icon
50
- name="dots-vertical-solid-v2"
51
- type="solid"
52
- cursorType="cursor-pointer"
53
- class="h-5 w-5 text-gray-400"
54
- viewBox="0 0 24 24"
55
- ></c-icon>
56
- </button>
57
- </div>
58
- <div v-else class="relative">
59
- <c-tool-tip
60
- v-if="showShowHideColumnTooltip"
61
- color="#1f2937"
62
- classes="text-white absolute -mt-12 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
63
- :isTopAligned="true"
64
- :tooltip-text="'Column Visibility'"
65
- ></c-tool-tip>
66
- <button
67
- @mouseover="handleToolTipDisplay(true, 'showHideColumn')"
68
- @mouseleave="handleToolTipDisplay(false, 'showHideColumn')"
69
- @click="handleToggle"
70
- class="inline-flex h-9 items-center justify-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
71
- aria-haspopup="true"
72
- aria-expanded="true"
73
- >
74
- <c-icon
75
- name="view-board"
76
- type="solid"
77
- cursorType="cursor-pointer"
78
- class="h-5 w-5 text-gray-400"
79
- ></c-icon>
80
- <c-icon
81
- name="chevron-down"
82
- type="solid"
83
- cursorType="cursor-pointer"
84
- class="ml-1 h-5 w-5 text-gray-400"
85
- ></c-icon>
86
- </button>
87
- </div>
88
- <!-- dropdown having list of all columns to show hide -->
89
- <div
90
- v-if="toggleDropdown"
91
- @click="handleToggle"
92
- class="fixed inset-0 z-20"
93
- ></div>
94
- <div
95
- v-if="toggleDropdown"
96
- class="absolute right-0 z-30 mt-2 -mr-1 max-h-96 w-56 origin-top-right overflow-y-auto rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5"
97
- tabindex="0"
98
- >
99
- <div
100
- class="pt-1"
101
- role="menu"
102
- aria-orientation="vertical"
103
- aria-labelledby="option-menu"
104
- >
105
- <div
106
- v-for="(column, index) in showHideColumnList"
107
- :key="index"
108
- :class="[
109
- column.isActionColumn && showNewShowHideColumnButton
110
- ? column.customClasses +
111
- ' sticky bottom-0 z-10 w-full bg-white'
112
- : '',
113
- ]"
114
- >
115
- <div
116
- v-if="column.isRowHeaderCol && showNewShowHideColumnButton"
117
- class="block px-3 py-2 text-sm font-medium text-gray-900"
118
- >
119
- {{ column.label }}
120
- </div>
121
- <div
122
- v-else-if="
123
- column.isActionColumn && showNewShowHideColumnButton
124
- "
125
- class="block px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
126
- @click="$emit('actionColumnClick', column)"
127
- >
128
- <c-icon
129
- v-if="column.showActionIcon"
130
- :name="column.icon.name"
131
- :type="column.icon.type"
132
- :class="column.icon.class"
133
- :viewBox="column.icon.viewBox"
134
- ></c-icon>
135
- <span>{{ column.label }}</span>
136
- </div>
137
- <a
138
- v-else
139
- href="#"
140
- role="menuitem"
141
- class="block px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
142
- >
143
- <c-checkbox
144
- :label="column.label"
145
- @onChange="showHideColumn($event, column.field)"
146
- :value="!column.hidden"
147
- ></c-checkbox>
148
- </a>
149
- </div>
150
- </div>
151
- </div>
152
- </div>
153
- <slot name="customDatePicker"></slot>
154
-
155
- <!-- simple download button -->
156
- <div
157
- v-if="enableDownload && !downloadDropdown"
158
- @click="startDownload"
159
- class="relative"
160
- :id="id + '_button_download'"
161
- >
162
- <c-tool-tip
163
- v-if="showDownloadTooltip"
164
- color="#1f2937"
165
- classes="text-white absolute -mt-12 ml-1.5 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
166
- :isTopAligned="true"
167
- :tooltip-text="'Download'"
168
- ></c-tool-tip>
169
- <c-button-icon
170
- @mouseover.native="handleToolTipDisplay(true, 'download')"
171
- @mouseleave.native="handleToolTipDisplay(false, 'download')"
172
- type="white"
173
- :icon="
174
- downloadLoader
175
- ? null
176
- : {
177
- name: 'arrow-down-tray-solid-v2',
178
- type: 'solid',
179
- class: 'h-5 w-5 text-gray-400',
180
- viewBox: '0 0 24 24',
181
- }
182
- "
183
- class="ml-3"
184
- loaderClasses="ml-2"
185
- :isLoading="downloadLoader"
186
- :disabled="disableDownloadButton"
187
- ></c-button-icon>
188
- </div>
189
- <!-- no download buttons -->
190
- <div v-if="!enableDownload && !downloadDropdown"></div>
191
- <!-- download button with download options -->
192
- <div v-if="enableDownload && downloadDropdown" class="relative ml-3">
193
- <div>
194
- <button
195
- @click="handleDownloadToggle"
196
- class="inline-flex w-full justify-center rounded-md border border-gray-200 bg-white px-2 py-2 text-sm font-medium shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
197
- aria-haspopup="true"
198
- aria-expanded="true"
199
- :id="id + '_button_toggle_download'"
200
- >
201
- <c-icon
202
- v-if="downloadOptionLoader"
203
- cursorType="cursor-pointer"
204
- class="mr-2 h-5 w-5 text-gray-400"
205
- name="loader"
206
- ></c-icon>
207
- <c-icon
208
- v-else
209
- name="download-solid"
210
- type="solid"
211
- class="h-5 w-5 text-gray-400"
212
- cursorType="cursor-pointer"
213
- ></c-icon>
214
- <c-icon
215
- name="chevron-down"
216
- type="solid"
217
- class="ml-1 h-5 w-5 text-gray-400"
218
- cursorType="cursor-pointer"
219
- ></c-icon>
220
- </button>
221
- </div>
222
- <!-- download options dropdown -->
223
- <div
224
- v-if="toggleDownloadDropdown"
225
- @click="handleDownloadToggle"
226
- class="fixed inset-0 z-20"
227
- ></div>
228
- <div
229
- v-if="toggleDownloadDropdown"
230
- class="absolute right-0 z-30 mt-2 -mr-1 max-h-96 w-64 origin-top-right overflow-y-auto rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5"
231
- tabindex="0"
232
- >
233
- <div
234
- class="py-1"
235
- role="menu"
236
- aria-orientation="vertical"
237
- aria-labelledby="option-menu"
238
- >
239
- <div
240
- v-for="(item, index) in showDownloadDropdownList"
241
- :key="index"
242
- class="cursor-pointer px-3 py-2 text-sm text-gray-900 hover:bg-gray-100 hover:text-gray-900"
243
- role="menuitem"
244
- @click="downloadFromOption(item.value)"
245
- :id="getActionIDFn(item.title)"
246
- >
247
- <p>{{ item.title }}</p>
248
- <p class="text-sm text-gray-400">{{ item.description }}</p>
249
- </div>
250
- </div>
251
- </div>
252
- </div>
253
- <slot name="customTableExtraActions"></slot>
254
- </div>
255
- </div>
256
- </div>
257
-
258
- <vue-good-table
259
- :class="`rounded-lg ${
260
- hideBorder ? ' border-none' : 'border-2 border-solid border-gray-100'
261
- }`"
262
- mode="remote"
263
- ref="my-table"
264
- :styleClass="
265
- isLoading ? 'vgt-table opacity-50 pointer-events-none' : 'vgt-table'
266
- "
267
- :row-style-class="rowStyleClassFn"
268
- min-height="400px"
269
- :globalSearch="true"
270
- :totalRows="totalRecords"
271
- :columns="colsWithHeaderClasses"
272
- :rows="rows"
273
- :search-options="{
274
- enabled: searching,
275
- externalQuery: searchTerm,
276
- placeholder: searchPlaceholder,
277
- trigger: 'enter',
278
- }"
279
- :select-options="{
280
- enabled: enableSelection,
281
- selectOnCheckboxOnly: selectOnCheckBoxClickOnly, // only select when checkbox is clicked instead of the row
282
- selectionInfoClass: 'custom-class',
283
- selectionText: 'rows selected',
284
- clearSelectionText: 'clear',
285
- disableSelectInfo: true, // disable the select info panel on top
286
- selectAllByGroup: true, // when used in combination with a grouped table, add a checkbox in the header row to check/uncheck the entire group
287
- }"
288
- :sort-options="{
289
- enabled: sorting,
290
- initialSortBy: initialSortField,
291
- }"
292
- :pagination-options="{ enabled: pagination }"
293
- :fixed-header="fixedHeader"
294
- :group-options="{
295
- enabled: enableGrouping,
296
- collapsable: enableGrouping,
297
- maintainExpanded: enableGrouping,
298
- }"
299
- :id="id"
300
- @on-selected-rows-change="selectionChanged"
301
- @on-sort-change="sortChange"
302
- @on-search="onSearching"
303
- @on-row-click="onRowClick"
304
- @on-row-mouseenter="onRowMouseover"
305
- @on-row-mouseleave="onRowMouseleave"
306
- >
307
- <template slot="table-column" slot-scope="props">
308
- <span :id="`${id}_header_${props.column.field}`">
309
- <!-- custom sorting icon -->
310
- <span v-if="props.column.sortable || sorting" class="flex">
311
- <div>
312
- {{ props.column.label }}
313
- </div>
314
- <!-- render if there is no sorting order, appears on hover -->
315
- <c-icon
316
- v-if="props.column.direction == null"
317
- name="sort-ascending-solid"
318
- class="sortingIcon invisible ml-3 h-5 w-5"
319
- type="solid"
320
- ></c-icon>
321
- <!-- renders when direction is asc -->
322
- <c-icon
323
- v-else-if="props.column.direction == 'asc'"
324
- name="sort-ascending-solid"
325
- class="ml-3 h-5 w-5"
326
- type="solid"
327
- ></c-icon>
328
- <!-- renders when direction is desc -->
329
- <c-icon
330
- v-else-if="props.column.direction == 'desc'"
331
- name="sort-descending-solid"
332
- class="ml-3 h-5 w-5"
333
- type="solid"
334
- ></c-icon>
335
- </span>
336
- <span class="font-medium text-gray-500" v-else-if="fontHeader">
337
- {{ props.column.label }}
338
- </span>
339
- <span v-else-if="props.column.hasIcon" class="flex">
340
- {{ props.column.label }}
341
- <c-icon
342
- name="information-circle"
343
- type="solid"
344
- class="mr-2 h-5 w-5 shrink-0 text-gray-400 hover:text-gray-500"
345
- cursorType="cursor-pointer"
346
- @mouseover.native="props.column.showToolTipText = true"
347
- @mouseleave.native="props.column.showToolTipText = false"
348
- ></c-icon>
349
-
350
- <div
351
- :class="['absolute', `${props.column.toolTipBoxClass}`]"
352
- v-if="props.column.showToolTipText"
353
- >
354
- <c-tool-tip
355
- color="#1f2937"
356
- classes="text-white whitespace-nowrap font-normal sticky bg-gray-800 w-auto"
357
- :tooltip-text="props.column.tooltipText"
358
- ></c-tool-tip>
359
- </div>
360
- </span>
361
- <span v-else> {{ props.column.label }}</span>
362
- </span>
363
- </template>
364
- <div slot="emptystate">
365
- <template v-if="isLoading">
366
- <div class="flex flex-col gap-3 py-[1.5px]">
367
- <div class="flex flex-col gap-3" v-for="idx in 10" :key="idx">
368
- <div class="flex w-full items-center justify-between gap-2">
369
- <div class="flex items-center gap-2" v-if="addAvatarLoader">
370
- <vue-skeleton-loader
371
- type="table-tbody: table-row-divider@6"
372
- animation="fade"
373
- :width="32"
374
- :rounded="true"
375
- :height="32"
376
- :radius="200"
377
- ></vue-skeleton-loader>
378
- <vue-skeleton-loader
379
- type="table-tbody: table-row-divider@6"
380
- animation="fade"
381
- :width="100"
382
- :rounded="true"
383
- :height="32"
384
- ></vue-skeleton-loader>
385
- </div>
386
- <vue-skeleton-loader
387
- type="table-tbody: table-row-divider@6"
388
- animation="fade"
389
- class="!w-full"
390
- :rounded="true"
391
- :height="32"
392
- ></vue-skeleton-loader>
393
- </div>
394
- </div>
395
- </div>
396
- </template>
397
- <template v-else>
398
- <p class="vgt-center-align vgt-text-disabled">
399
- {{ emptyStatePlaceholderText }}
400
- </p>
401
- </template>
402
- </div>
403
- <template slot="table-row" slot-scope="props">
404
- <!-- renders if drag and drop is present in table -->
405
- <span v-if="props.column.field == 'drag'">
406
- <c-icon
407
- name="draggable"
408
- type="solid"
409
- :class="`handle h-5 w-5 ${
410
- props.row.status && props.row.status === 2
411
- ? 'pointer-events-none cursor-default opacity-50'
412
- : 'text-gray-500'
413
- }`"
414
- :cursorType="'cursor-grab'"
415
- ></c-icon>
416
- </span>
417
- <!-- if customization or adding another form element is required -->
418
- <span v-else-if="props.column.customizeColumn">
419
- <slot
420
- :records="props"
421
- :isHovered="enableRowHover && isRowHovered(props)"
422
- >
423
- </slot>
424
- </span>
425
- <span v-else-if="props.column.field === '__hoverText'">
426
- <span
427
- v-if="isRowHovered(props)"
428
- class="text-sm text-gray-500 whitespace-nowrap"
429
- >
430
- {{ rowHoverText }}
431
- </span>
432
- </span>
433
- <!-- renders records as per column name -->
434
- <span v-else>
435
- {{ props.formattedRow[props.column.field] }}
436
- </span>
437
- </template>
438
- <!-- Custom pagination component -->
439
- <template v-if="pagination" slot="pagination-bottom">
440
- <c-pagination
441
- v-if="paginationRecords.totalRecords > 0"
442
- :setPaginationRecords="paginationRecords"
443
- :totalRecordsOnPage="recordsToDisplay"
444
- :showEntryPicker="showEntryPicker"
445
- :id="id"
446
- @setCurrentPage="setCurrentPageRecords"
447
- @setPreviousPage="setPreviousPageRecords"
448
- @setNextPage="setNextPageRecords"
449
- @handle-Row-Count-Change="handleChangeRowCount"
450
- ></c-pagination>
451
- </template>
452
- </vue-good-table>
453
-
454
- <!-- Floating Action Bar -->
455
- <transition name="floating-action-bar">
456
- <div
457
- v-if="shouldShowFloatingActionBar"
458
- ref="floatingActionBar"
459
- :style="floatingActionBarStyle"
460
- class="fixed bottom-8 left-1/2 z-10 -translate-x-1/2"
461
- >
462
- <div
463
- class="flex shrink-0 items-center justify-center rounded-xl bg-gray-900 p-3 shadow-lg"
464
- :style="floatingActionBarGapStyle"
465
- >
466
- <!-- Close button and selection count -->
467
- <div class="flex items-center gap-1">
468
- <c-button-icon
469
- :id="id + '_button_close_action_bar'"
470
- type="dark-blue"
471
- :icon="{
472
- name: 'x-mark-solid-v2',
473
- type: 'solid',
474
- class: 'h-5 w-5 text-gray-300 group-hover:text-white',
475
- viewBox: '0 0 24 24',
476
- }"
477
- title="Close selection"
478
- aria-label="Close selection"
479
- customButtonClasses="group"
480
- @action="handleClearSelectedRows"
481
- ></c-button-icon>
482
- <slot name="floatingActionBarActionsInfo"></slot>
483
- </div>
484
-
485
- <!-- Custom action buttons slot -->
486
- <div class="flex items-center gap-1">
487
- <slot
488
- name="floatingActionBarActions"
489
- :clearSelection="handleClearSelectedRows"
490
- ></slot>
491
- </div>
492
- </div>
493
- </div>
494
- </transition>
495
- </div>
496
- </template>
497
- <script>
498
- import CIcon from "../CIcon/CIcon.vue";
499
- import CCheckbox from "../CCheckbox/CCheckbox.vue";
500
- import CPagination from "../CPagination/CPagination.vue";
501
- import CButtonIcon from "../CButtonIcon/CButtonIcon.vue";
502
- import CToolTip from "../CToolTip/CToolTip.vue";
503
- import "vue-good-table/dist/vue-good-table.css";
504
- import { VueGoodTable } from "vue-good-table";
505
- import Sortable from "@shopify/draggable/lib/es5/sortable.js";
506
- import CInput from "../CInput/CInput.vue";
507
- import { debounce, isEqual } from "lodash-es";
508
- import VueSkeletonLoader from "skeleton-loader-vue";
509
- import { getActionID } from "../../helper";
510
-
511
- const RESIZE_DEBOUNCE_DELAY = 150;
512
-
513
- export default {
514
- name: "CTable",
515
- components: {
516
- CCheckbox,
517
- CIcon,
518
- VueGoodTable,
519
- CPagination,
520
- CButtonIcon,
521
- CInput,
522
- VueSkeletonLoader,
523
- CToolTip,
524
- },
525
- props: {
526
- fontHeader: {
527
- type: Boolean,
528
- default: false,
529
- },
530
- // To show or hide pagination section
531
- pagination: {
532
- type: Boolean,
533
- },
534
- // To enable or disable sorting
535
- sorting: {
536
- type: Boolean,
537
- },
538
- // To show or hide search input
539
- searching: {
540
- type: Boolean,
541
- },
542
- // To add checkbox to select rows
543
- enableSelection: {
544
- type: Boolean,
545
- },
546
- enableVisibility: {
547
- type: Boolean,
548
- default: true,
549
- },
550
- disableColumnsDropdown: {
551
- type: Boolean,
552
- default: false,
553
- },
554
- enableDownload: {
555
- type: Boolean,
556
- default: true,
557
- },
558
- // All the buttons displayed on top right side of table
559
- tableActions: {
560
- type: Boolean,
561
- },
562
- // Placeholder text for search
563
- searchPlaceholder: {
564
- type: String,
565
- },
566
- // Existing text for search
567
- searchQuery: {
568
- type: String,
569
- },
570
- isLoading: {
571
- type: Boolean,
572
- },
573
- // ID
574
- totalRecords: {
575
- type: String,
576
- },
577
- // Total number of rows in a table to calculate page numbers
578
- id: {
579
- type: String,
580
- },
581
- // Shows current selected page and records on per page
582
- paginationData: {
583
- type: Object,
584
- },
585
- // Pass a column on which initial sorting will be applied
586
- initialSortField: {
587
- type: Object,
588
- },
589
- // all columns of the table
590
- cols: {
591
- type: Array,
592
- required: true,
593
- },
594
- // row records of the table
595
- rows: {
596
- type: Array,
597
- required: true,
598
- },
599
- // List of columns to show hide
600
- showHideColumnList: {
601
- type: Array,
602
- },
603
- // List of items to show download options
604
- showDownloadDropdownList: {
605
- type: Array,
606
- },
607
- // Function on changing page number
608
- onPageChange: {
609
- type: Function,
610
- },
611
- // Function on changing sorting on column
612
- onSortChange: {
613
- type: Function,
614
- },
615
- // Function to fetch results on search query
616
- onSearch: {
617
- type: Function,
618
- },
619
- // Emit action on clicking the row
620
- onRowClickAction: {
621
- type: Function,
622
- },
623
- // Start the loader
624
- downloadLoader: {
625
- type: Boolean,
626
- },
627
- // Start the loader
628
- downloadOptionLoader: {
629
- type: Boolean,
630
- },
631
- downloadDropdown: {
632
- type: Boolean,
633
- },
634
- rowStyleClassFn: {
635
- type: Function,
636
- default: () => "",
637
- },
638
- fixedHeader: {
639
- type: Boolean,
640
- default: false,
641
- },
642
- hideBorder: {
643
- type: Boolean,
644
- default: false,
645
- },
646
- showEntryPicker: {
647
- type: Boolean,
648
- default: false,
649
- },
650
- enableGrouping: {
651
- type: Boolean,
652
- default: false,
653
- },
654
- //enables user to select rows by clicking on the row
655
- selectOnCheckBoxClickOnly: {
656
- type: Boolean,
657
- default: true,
658
- },
659
- //shows new show hide column button
660
- showNewShowHideColumnButton: {
661
- type: Boolean,
662
- default: false,
663
- },
664
- disableDownloadButton: {
665
- type: Boolean,
666
- default: false,
667
- },
668
- searchInputClass: {
669
- type: String,
670
- default: "w-auto sm:w-56",
671
- },
672
- showTableActionsTooltip: {
673
- type: Boolean,
674
- default: false,
675
- },
676
- emptyStatePlaceholderText: {
677
- type: String,
678
- default: "No data for table",
679
- },
680
- inputWrapperClass: {
681
- type: String,
682
- default: "",
683
- },
684
- addAvatarLoader: {
685
- type: Boolean,
686
- default: false,
687
- },
688
- // Enable row hover effects (color change and hover text)
689
- enableRowHover: {
690
- type: Boolean,
691
- default: false,
692
- },
693
- // Text to show at the end of row on hover
694
- rowHoverText: {
695
- type: String,
696
- default: "",
697
- },
698
- showFloatingActionBar: {
699
- type: Boolean,
700
- default: false,
701
- },
702
- // Selector for the container element used for floating action bar positioning
703
- // Defaults to '.content-container > div' for backward compatibility which is the main layout of the page
704
- containerSelector: {
705
- type: String,
706
- default: ".content-container > div",
707
- },
708
- },
709
- computed: {
710
- cssVars() {
711
- return {
712
- "--vgt-bottom-radius": this.pagination ? "0" : "8px",
713
- };
714
- },
715
- colsWithHeaderClasses() {
716
- const cols = this.cols.map((col) => ({
717
- ...col,
718
- thClass: `${this.id}_header_${col.field}`,
719
- }));
720
-
721
- // Add hover text column at the end if enabled
722
- if (this.enableRowHover && this.rowHoverText) {
723
- cols.push({
724
- label: "",
725
- field: "__hoverText",
726
- hidden: false,
727
- sortable: false,
728
- thClass: `${this.id}_header___hoverText`,
729
- tdClass: "hover-text-column",
730
- });
731
- }
732
-
733
- return cols;
734
- },
735
- shouldShowFloatingActionBar() {
736
- return this.showFloatingActionBar && this.enableSelection;
737
- },
738
- floatingActionBarGapStyle() {
739
- if (!this.shouldShowFloatingActionBar) return {};
740
-
741
- /*
742
- Responsive gap using clamp(min, preferred, max)
743
- - Minimum: 12px → gap will never go below 12px
744
- - Preferred: 4vw → scales fluidly with viewport width i.e., 4% of viewport width
745
- - Maximum: 80px → gap will never exceed 80px
746
- */
747
- return {
748
- gap: "clamp(12px, 4vw, 80px)",
749
- };
750
- },
751
- },
752
- mounted() {
753
- // to add drag and drop in table
754
- this.reorderedArray = this.rows;
755
- let sortable = new Sortable(document.querySelectorAll("tbody"), {
756
- draggable: "tr",
757
- handle: ".handle",
758
- classes: {
759
- mirror: ["bg-white"],
760
- },
761
- mirror: {
762
- constrainDimensions: true,
763
- },
764
- });
765
- sortable.on("sortable:stop", (e) => this.rearrange(e.oldIndex, e.newIndex));
766
- document.addEventListener("keydown", this.handleControlClick, true);
767
- document.addEventListener("keyup", this.handleControlRelease, true);
768
-
769
- // Setup floating action bar positioning
770
- if (this.shouldShowFloatingActionBar) {
771
- this.$nextTick(() => {
772
- this.updateFloatingActionBarPosition();
773
- this.setupResizeObserver();
774
- })
775
- }
776
- },
777
- destroyed() {
778
- //to remove the event listener
779
- document.removeEventListener("keydown", this.handleControlClick, true);
780
- document.removeEventListener("keyup", this.handleControlRelease, true);
781
-
782
- this.cleanupResizeObserver();
783
- },
784
- data() {
785
- return {
786
- toggleDropdown: false,
787
- toggleDownloadDropdown: false,
788
- searchTerm: this.searchQuery ? this.searchQuery : "",
789
- paginationRecords: this.paginationData,
790
- reorderedArray: [],
791
- controlClick: false,
792
- attrs: {
793
- boilerplate: true,
794
- elevation: 2,
795
- },
796
- recordsToDisplay: {
797
- option: 10,
798
- value: 10,
799
- },
800
- showShowHideColumnTooltip: false,
801
- showDownloadTooltip: false,
802
- hoveredRowId: null,
803
- floatingActionBarStyle: {},
804
- };
805
- },
806
- methods: {
807
- getActionIDFn(name) {
808
- return getActionID(name, this.id);
809
- },
810
- handleChangeRowCount(value) {
811
- this.recordsToDisplay = value;
812
- this.$emit("change-row-count", value.value);
813
- },
814
- handleToolTipDisplay(value, type) {
815
- if (!this.showTableActionsTooltip) {
816
- return;
817
- }
818
- if (type === "showHideColumn") {
819
- this.showShowHideColumnTooltip = value;
820
- } else if (type === "download") {
821
- this.showDownloadTooltip = value;
822
- }
823
- },
824
- handleControlClick(event) {
825
- if (event.keyCode === 17 || event.keyCode === 91) {
826
- event.preventDefault();
827
- this.controlClick = true;
828
- }
829
- },
830
- handleControlRelease(event) {
831
- if (event.keyCode === 17 || event.keyCode === 91) {
832
- event.preventDefault();
833
- this.controlClick = false;
834
- }
835
- },
836
- handleToggle() {
837
- this.toggleDropdown = !this.toggleDropdown;
838
- },
839
- handleDownloadToggle() {
840
- this.toggleDownloadDropdown = !this.toggleDownloadDropdown;
841
- },
842
- showHideColumn(value, name) {
843
- this.$emit("hideCols", value, name);
844
- },
845
- handleClearSelectedRows() {
846
- if (this.$refs["my-table"]) {
847
- this.$refs["my-table"].unselectAllInternal();
848
- }
849
- this.$emit("closeSelection");
850
- },
851
- // Function to get selected rows on checking the checkbox
852
- selectionChanged() {
853
- this.$emit(
854
- "selectRows",
855
- this.$refs["my-table"].selectedRows,
856
- this.$refs["my-table"].allSelected
857
- );
858
- },
859
- // array of rows after drag and drop
860
- rearrange(oldIndex, newIndex) {
861
- const movedItem = this.reorderedArray.find(
862
- (item, index) => index === oldIndex
863
- );
864
- const remainingItems = this.reorderedArray.filter(
865
- (item, index) => index !== oldIndex
866
- );
867
- const reorderedItems = [
868
- ...remainingItems.slice(0, newIndex),
869
- movedItem,
870
- ...remainingItems.slice(newIndex),
871
- ];
872
- this.reorderedArray = [...reorderedItems];
873
- this.$emit(
874
- "reordered",
875
- this.reorderedArray,
876
- movedItem,
877
- oldIndex,
878
- newIndex
879
- );
880
- },
881
- // listing functions
882
- sortChange(params) {
883
- if (params[0].type == "none") {
884
- params[0].type = "asc";
885
- }
886
- this.$emit("onSortChange", params);
887
- },
888
- onSearching: debounce(function (params) {
889
- this.$emit("onSearch", params);
890
- }, 500),
891
- setCurrentPageRecords(page) {
892
- this.paginationRecords.currentPage = page;
893
- this.$emit("pageChange", page);
894
- },
895
- setPreviousPageRecords(page) {
896
- this.paginationRecords.currentPage = page;
897
- this.$emit("pageChange", page);
898
- },
899
- setNextPageRecords(page) {
900
- this.paginationRecords.currentPage = page;
901
- this.$emit("pageChange", page);
902
- },
903
- onRowClick(params) {
904
- if (!this.selectOnCheckBoxClickOnly) {
905
- return;
906
- }
907
- if (params.event.target.type === undefined) {
908
- if (this.controlClick) {
909
- this.$emit("onRowControlClickAction", params);
910
- } else {
911
- this.$emit("onRowClickAction", params);
912
- }
913
- } else {
914
- return false;
915
- }
916
- },
917
- startDownload() {
918
- this.$emit("handleDownloadButton");
919
- },
920
- downloadFromOption(value) {
921
- this.toggleDownloadDropdown = false;
922
- this.$emit("handleDownloadOptionButton", value);
923
- },
924
-
925
- handleRowExpand() {
926
- this.$refs["my-table"].expandAll();
927
- },
928
- onRowMouseover(params) {
929
- if (this.enableRowHover) {
930
- this.hoveredRowId = params.row.id;
931
- }
932
- },
933
- onRowMouseleave() {
934
- if (this.enableRowHover) {
935
- this.hoveredRowId = null;
936
- }
937
- },
938
- isRowHovered(props) {
939
- if (!this.enableRowHover || !this.hoveredRowId) {
940
- return false;
941
- }
942
- return props.row.id === this.hoveredRowId;
943
- },
944
- updateFloatingActionBarPosition() {
945
- if (!this.shouldShowFloatingActionBar) {
946
- this.floatingActionBarStyle = {};
947
- return;
948
- }
949
-
950
- let contentContainer = document.querySelector(this.containerSelector);
951
- if (!contentContainer && this.$el) {
952
- contentContainer = this.$el.closest(".content");
953
- }
954
- if (!contentContainer) {
955
- this.floatingActionBarStyle = {
956
- maxWidth: "100%",
957
- };
958
- return;
959
- }
960
-
961
- const rect = contentContainer.getBoundingClientRect();
962
- const containerCenter = rect.left + rect.width / 2;
963
-
964
- this.floatingActionBarStyle = {
965
- left: `${containerCenter}px`,
966
- width: "max-content",
967
- maxWidth: "100%",
968
- };
969
- },
970
- cleanupResizeObserver() {
971
- if (this._resizeHandler) {
972
- window.removeEventListener("resize", this._resizeHandler);
973
- this._resizeHandler = null;
974
- }
975
- },
976
- setupResizeObserver() {
977
- // Remove existing listener if any
978
- if (this._resizeHandler) {
979
- window.removeEventListener("resize", this._resizeHandler);
980
- }
981
-
982
- // Create debounced resize handler
983
- this._resizeHandler = debounce(() => {
984
- if (this.shouldShowFloatingActionBar) {
985
- this.updateFloatingActionBarPosition();
986
- }
987
- }, RESIZE_DEBOUNCE_DELAY);
988
-
989
- window.addEventListener("resize", this._resizeHandler);
990
- },
991
- },
992
- watch: {
993
- paginationData(newValue, oldValue) {
994
- if (!isEqual(newValue, oldValue)) {
995
- this.paginationRecords = newValue;
996
- }
997
- },
998
- rows(newValue, oldValue) {
999
- if (!isEqual(newValue, oldValue)) {
1000
- this.reorderedArray = newValue;
1001
- }
1002
- },
1003
- shouldShowFloatingActionBar(newValue) {
1004
- if (newValue) {
1005
- this.$nextTick(() => {
1006
- this.updateFloatingActionBarPosition();
1007
- this.setupResizeObserver();
1008
- });
1009
- } else {
1010
- this.floatingActionBarStyle = {};
1011
- this.cleanupResizeObserver();
1012
- }
1013
- },
1014
- },
1015
- };
1016
- </script>
1017
- <style>
1018
- .vgt-table {
1019
- border-spacing: 0;
1020
- border: none !important;
1021
- font-family: "Inter";
1022
- font-size: 14px !important;
1023
- }
1024
- table.vgt-table td {
1025
- vertical-align: middle;
1026
- }
1027
- .vgt-table thead th {
1028
- background: linear-gradient(#fff, #fff);
1029
- }
1030
- .vgt-table th.vgt-checkbox-col {
1031
- border-right: 0;
1032
- border-bottom: 1px solid #dcdfe6;
1033
- background: linear-gradient(#fff, #fff);
1034
- }
1035
- table.vgt-table tr.clickable:hover {
1036
- background-color: #f9fafb;
1037
- border-bottom: 1px solid #dcdfe6 !important;
1038
- }
1039
- .vgt-table th.sortable button::before,
1040
- .vgt-table th.sortable button::after {
1041
- border-right: 0;
1042
- border-left: 0;
1043
- }
1044
- [type="checkbox"],
1045
- [type="checkbox"]:focus {
1046
- border-radius: 4px;
1047
- border-color: #d1d5db;
1048
- cursor: pointer;
1049
- color: #0284c7;
1050
- --tw-ring-color: #0284c7;
1051
- }
1052
-
1053
- /* tbody > tr > th.vgt-checkbox-col {
1054
- background: linear-gradient(#fff, #fff);
1055
- border-bottom: 1px solid #dcdfe6;
1056
- } */
1057
- .vgt-global-search {
1058
- background: none;
1059
- border: none;
1060
- padding: 0 0 12px 0;
1061
- }
1062
- .vgt-global-search__input {
1063
- padding-left: 0;
1064
- }
1065
- .input__icon {
1066
- display: none;
1067
- }
1068
- .vgt-global-search__input .vgt-input {
1069
- height: 38px;
1070
- width: 250px;
1071
- }
1072
- .vgt-inner-wrap {
1073
- box-shadow: none;
1074
- }
1075
- .vgt-inner-wrap.is-loading {
1076
- opacity: 1;
1077
- pointer-events: auto;
1078
- }
1079
- .vgt-table th.sortable:hover .sortingIcon {
1080
- visibility: visible;
1081
- }
1082
- .vgt-responsive {
1083
- position: static;
1084
- border-top-left-radius: 8px;
1085
- border-top-right-radius: 8px;
1086
- border-bottom-left-radius: var(--vgt-bottom-radius, 0);
1087
- border-bottom-right-radius: var(--vgt-bottom-radius, 0);
1088
- }
1089
- .vgt-wrap {
1090
- position: static;
1091
- }
1092
- .hover-text-column {
1093
- text-align: right;
1094
- padding-right: 1rem;
1095
- width: 180px;
1096
- min-width: 180px;
1097
- }
1098
- .floating-action-bar-enter-active,
1099
- .floating-action-bar-leave-active {
1100
- transition: opacity 300ms ease, transform 300ms ease;
1101
- }
1102
-
1103
- .floating-action-bar-enter,
1104
- .floating-action-bar-leave-to {
1105
- opacity: 0;
1106
- transform: translate(-50%, 100%);
1107
- }
1108
-
1109
- .floating-action-bar-enter-to,
1110
- .floating-action-bar-leave {
1111
- opacity: 1;
1112
- transform: translate(-50%, 0);
1113
- }
1114
- </style>
1
+ <template>
2
+ <div :style="cssVars">
3
+ <div
4
+ slot="table-actions"
5
+ v-if="tableActions"
6
+ class="mb-4 rounded-lg bg-gray-50 p-3"
7
+ >
8
+ <div class="flex items-center justify-between">
9
+ <slot name="customTableFilterActions"></slot>
10
+ <div v-if="searching" class="flex items-center">
11
+ <c-input
12
+ v-model="searchTerm"
13
+ :isValidate="searching"
14
+ :placeholder="searchPlaceholder"
15
+ class="mr-3"
16
+ :class="searchInputClass"
17
+ :inputWrapperClass="inputWrapperClass"
18
+ type="text"
19
+ :id="id + '_input_search'"
20
+ ></c-input>
21
+ <slot name="tableInfo"></slot>
22
+ </div>
23
+ <div class="flex flex-1 justify-end">
24
+ <!-- dropdown icon on top right of table -->
25
+ <slot name="customTableActions"></slot>
26
+ <div
27
+ :class="`relative inline-block text-left ${
28
+ disableColumnsDropdown ? 'pointer-events-none opacity-50' : ''
29
+ }`"
30
+ v-if="enableVisibility"
31
+ >
32
+ <!-- button to show list of columns to show hide in table -->
33
+ <div v-if="showNewShowHideColumnButton" class="relative">
34
+ <c-tool-tip
35
+ v-if="showShowHideColumnTooltip"
36
+ color="#1f2937"
37
+ classes="text-white absolute -mt-12 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
38
+ :isTopAligned="true"
39
+ :tooltip-text="'Column Visibility, Download'"
40
+ ></c-tool-tip>
41
+ <button
42
+ @mouseover="handleToolTipDisplay(true, 'showHideColumn')"
43
+ @mouseleave="handleToolTipDisplay(false, 'showHideColumn')"
44
+ @click="handleToggle"
45
+ class="inline-flex h-9 items-center justify-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
46
+ aria-haspopup="true"
47
+ aria-expanded="true"
48
+ >
49
+ <c-icon
50
+ name="dots-vertical-solid-v2"
51
+ type="solid"
52
+ cursorType="cursor-pointer"
53
+ class="h-5 w-5 text-gray-400"
54
+ viewBox="0 0 24 24"
55
+ ></c-icon>
56
+ </button>
57
+ </div>
58
+ <div v-else class="relative">
59
+ <c-tool-tip
60
+ v-if="showShowHideColumnTooltip"
61
+ color="#1f2937"
62
+ classes="text-white absolute -mt-12 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
63
+ :isTopAligned="true"
64
+ :tooltip-text="'Column Visibility'"
65
+ ></c-tool-tip>
66
+ <button
67
+ @mouseover="handleToolTipDisplay(true, 'showHideColumn')"
68
+ @mouseleave="handleToolTipDisplay(false, 'showHideColumn')"
69
+ @click="handleToggle"
70
+ class="inline-flex h-9 items-center justify-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
71
+ aria-haspopup="true"
72
+ aria-expanded="true"
73
+ >
74
+ <c-icon
75
+ name="view-board"
76
+ type="solid"
77
+ cursorType="cursor-pointer"
78
+ class="h-5 w-5 text-gray-400"
79
+ ></c-icon>
80
+ <c-icon
81
+ name="chevron-down"
82
+ type="solid"
83
+ cursorType="cursor-pointer"
84
+ class="ml-1 h-5 w-5 text-gray-400"
85
+ ></c-icon>
86
+ </button>
87
+ </div>
88
+ <!-- dropdown having list of all columns to show hide -->
89
+ <div
90
+ v-if="toggleDropdown"
91
+ @click="handleToggle"
92
+ class="fixed inset-0 z-20"
93
+ ></div>
94
+ <div
95
+ v-if="toggleDropdown"
96
+ class="absolute right-0 z-30 mt-2 -mr-1 max-h-96 w-56 origin-top-right overflow-y-auto rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5"
97
+ tabindex="0"
98
+ >
99
+ <div
100
+ class="pt-1"
101
+ role="menu"
102
+ aria-orientation="vertical"
103
+ aria-labelledby="option-menu"
104
+ >
105
+ <div
106
+ v-for="(column, index) in showHideColumnList"
107
+ :key="index"
108
+ :class="[
109
+ column.isActionColumn && showNewShowHideColumnButton
110
+ ? column.customClasses +
111
+ ' sticky bottom-0 z-10 w-full bg-white'
112
+ : '',
113
+ ]"
114
+ >
115
+ <div
116
+ v-if="column.isRowHeaderCol && showNewShowHideColumnButton"
117
+ class="block px-3 py-2 text-sm font-medium text-gray-900"
118
+ >
119
+ {{ column.label }}
120
+ </div>
121
+ <div
122
+ v-else-if="
123
+ column.isActionColumn && showNewShowHideColumnButton
124
+ "
125
+ class="block px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
126
+ @click="$emit('actionColumnClick', column)"
127
+ >
128
+ <c-icon
129
+ v-if="column.showActionIcon"
130
+ :name="column.icon.name"
131
+ :type="column.icon.type"
132
+ :class="column.icon.class"
133
+ :viewBox="column.icon.viewBox"
134
+ ></c-icon>
135
+ <span>{{ column.label }}</span>
136
+ </div>
137
+ <a
138
+ v-else
139
+ href="#"
140
+ role="menuitem"
141
+ class="block px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
142
+ >
143
+ <c-checkbox
144
+ :label="column.label"
145
+ @onChange="showHideColumn($event, column.field)"
146
+ :value="!column.hidden"
147
+ ></c-checkbox>
148
+ </a>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ <slot name="customDatePicker"></slot>
154
+
155
+ <!-- simple download button -->
156
+ <div
157
+ v-if="enableDownload && !downloadDropdown"
158
+ @click="startDownload"
159
+ class="relative"
160
+ :id="id + '_button_download'"
161
+ >
162
+ <c-tool-tip
163
+ v-if="showDownloadTooltip"
164
+ color="#1f2937"
165
+ classes="text-white absolute -mt-12 ml-1.5 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal bg-gray-800 w-auto"
166
+ :isTopAligned="true"
167
+ :tooltip-text="'Download'"
168
+ ></c-tool-tip>
169
+ <c-button-icon
170
+ @mouseover.native="handleToolTipDisplay(true, 'download')"
171
+ @mouseleave.native="handleToolTipDisplay(false, 'download')"
172
+ type="white"
173
+ :icon="
174
+ downloadLoader
175
+ ? null
176
+ : {
177
+ name: 'arrow-down-tray-solid-v2',
178
+ type: 'solid',
179
+ class: 'h-5 w-5 text-gray-400',
180
+ viewBox: '0 0 24 24',
181
+ }
182
+ "
183
+ class="ml-3"
184
+ loaderClasses="ml-2"
185
+ :isLoading="downloadLoader"
186
+ :disabled="disableDownloadButton"
187
+ ></c-button-icon>
188
+ </div>
189
+ <!-- no download buttons -->
190
+ <div v-if="!enableDownload && !downloadDropdown"></div>
191
+ <!-- download button with download options -->
192
+ <div v-if="enableDownload && downloadDropdown" class="relative ml-3">
193
+ <div>
194
+ <button
195
+ @click="handleDownloadToggle"
196
+ class="inline-flex w-full justify-center rounded-md border border-gray-200 bg-white px-2 py-2 text-sm font-medium shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
197
+ aria-haspopup="true"
198
+ aria-expanded="true"
199
+ :id="id + '_button_toggle_download'"
200
+ >
201
+ <c-icon
202
+ v-if="downloadOptionLoader"
203
+ cursorType="cursor-pointer"
204
+ class="mr-2 h-5 w-5 text-gray-400"
205
+ name="loader"
206
+ ></c-icon>
207
+ <c-icon
208
+ v-else
209
+ name="download-solid"
210
+ type="solid"
211
+ class="h-5 w-5 text-gray-400"
212
+ cursorType="cursor-pointer"
213
+ ></c-icon>
214
+ <c-icon
215
+ name="chevron-down"
216
+ type="solid"
217
+ class="ml-1 h-5 w-5 text-gray-400"
218
+ cursorType="cursor-pointer"
219
+ ></c-icon>
220
+ </button>
221
+ </div>
222
+ <!-- download options dropdown -->
223
+ <div
224
+ v-if="toggleDownloadDropdown"
225
+ @click="handleDownloadToggle"
226
+ class="fixed inset-0 z-20"
227
+ ></div>
228
+ <div
229
+ v-if="toggleDownloadDropdown"
230
+ class="absolute right-0 z-30 mt-2 -mr-1 max-h-96 w-64 origin-top-right overflow-y-auto rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5"
231
+ tabindex="0"
232
+ >
233
+ <div
234
+ class="py-1"
235
+ role="menu"
236
+ aria-orientation="vertical"
237
+ aria-labelledby="option-menu"
238
+ >
239
+ <div
240
+ v-for="(item, index) in showDownloadDropdownList"
241
+ :key="index"
242
+ class="cursor-pointer px-3 py-2 text-sm text-gray-900 hover:bg-gray-100 hover:text-gray-900"
243
+ role="menuitem"
244
+ @click="downloadFromOption(item.value)"
245
+ :id="getActionIDFn(item.title)"
246
+ >
247
+ <p>{{ item.title }}</p>
248
+ <p class="text-sm text-gray-400">{{ item.description }}</p>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ </div>
253
+ <slot name="customTableExtraActions"></slot>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <vue-good-table
259
+ :class="`rounded-lg ${
260
+ hideBorder ? ' border-none' : 'border-2 border-solid border-gray-100'
261
+ }`"
262
+ mode="remote"
263
+ ref="my-table"
264
+ :styleClass="
265
+ isLoading ? 'vgt-table opacity-50 pointer-events-none' : 'vgt-table'
266
+ "
267
+ :row-style-class="rowStyleClassFn"
268
+ min-height="400px"
269
+ :globalSearch="true"
270
+ :totalRows="totalRecords"
271
+ :columns="colsWithHeaderClasses"
272
+ :rows="rows"
273
+ :search-options="{
274
+ enabled: searching,
275
+ externalQuery: searchTerm,
276
+ placeholder: searchPlaceholder,
277
+ trigger: 'enter',
278
+ }"
279
+ :select-options="{
280
+ enabled: enableSelection,
281
+ selectOnCheckboxOnly: selectOnCheckBoxClickOnly, // only select when checkbox is clicked instead of the row
282
+ selectionInfoClass: 'custom-class',
283
+ selectionText: 'rows selected',
284
+ clearSelectionText: 'clear',
285
+ disableSelectInfo: true, // disable the select info panel on top
286
+ selectAllByGroup: true, // when used in combination with a grouped table, add a checkbox in the header row to check/uncheck the entire group
287
+ }"
288
+ :sort-options="{
289
+ enabled: sorting,
290
+ initialSortBy: initialSortField,
291
+ }"
292
+ :pagination-options="{ enabled: pagination }"
293
+ :fixed-header="fixedHeader"
294
+ :group-options="{
295
+ enabled: enableGrouping,
296
+ collapsable: enableGrouping,
297
+ maintainExpanded: enableGrouping,
298
+ }"
299
+ :id="id"
300
+ @on-selected-rows-change="selectionChanged"
301
+ @on-sort-change="sortChange"
302
+ @on-search="onSearching"
303
+ @on-row-click="onRowClick"
304
+ @on-row-mouseenter="onRowMouseover"
305
+ @on-row-mouseleave="onRowMouseleave"
306
+ >
307
+ <template slot="table-column" slot-scope="props">
308
+ <span :id="`${id}_header_${props.column.field}`">
309
+ <!-- custom sorting icon -->
310
+ <span v-if="props.column.sortable || sorting" class="flex">
311
+ <div>
312
+ {{ props.column.label }}
313
+ </div>
314
+ <!-- render if there is no sorting order, appears on hover -->
315
+ <c-icon
316
+ v-if="props.column.direction == null"
317
+ name="sort-ascending-solid"
318
+ class="sortingIcon invisible ml-3 h-5 w-5"
319
+ type="solid"
320
+ ></c-icon>
321
+ <!-- renders when direction is asc -->
322
+ <c-icon
323
+ v-else-if="props.column.direction == 'asc'"
324
+ name="sort-ascending-solid"
325
+ class="ml-3 h-5 w-5"
326
+ type="solid"
327
+ ></c-icon>
328
+ <!-- renders when direction is desc -->
329
+ <c-icon
330
+ v-else-if="props.column.direction == 'desc'"
331
+ name="sort-descending-solid"
332
+ class="ml-3 h-5 w-5"
333
+ type="solid"
334
+ ></c-icon>
335
+ </span>
336
+ <span class="font-medium text-gray-500" v-else-if="fontHeader">
337
+ {{ props.column.label }}
338
+ </span>
339
+ <span v-else-if="props.column.hasIcon" class="flex">
340
+ {{ props.column.label }}
341
+ <c-icon
342
+ name="information-circle"
343
+ type="solid"
344
+ class="mr-2 h-5 w-5 shrink-0 text-gray-400 hover:text-gray-500"
345
+ cursorType="cursor-pointer"
346
+ @mouseover.native="props.column.showToolTipText = true"
347
+ @mouseleave.native="props.column.showToolTipText = false"
348
+ ></c-icon>
349
+
350
+ <div
351
+ :class="['absolute', `${props.column.toolTipBoxClass}`]"
352
+ v-if="props.column.showToolTipText"
353
+ >
354
+ <c-tool-tip
355
+ color="#1f2937"
356
+ classes="text-white whitespace-nowrap font-normal sticky bg-gray-800 w-auto"
357
+ :tooltip-text="props.column.tooltipText"
358
+ ></c-tool-tip>
359
+ </div>
360
+ </span>
361
+ <span v-else> {{ props.column.label }}</span>
362
+ </span>
363
+ </template>
364
+ <div slot="emptystate">
365
+ <template v-if="isLoading">
366
+ <div class="flex flex-col gap-3 py-[1.5px]">
367
+ <div class="flex flex-col gap-3" v-for="idx in 10" :key="idx">
368
+ <div class="flex w-full items-center justify-between gap-2">
369
+ <div class="flex items-center gap-2" v-if="addAvatarLoader">
370
+ <vue-skeleton-loader
371
+ type="table-tbody: table-row-divider@6"
372
+ animation="fade"
373
+ :width="32"
374
+ :rounded="true"
375
+ :height="32"
376
+ :radius="200"
377
+ ></vue-skeleton-loader>
378
+ <vue-skeleton-loader
379
+ type="table-tbody: table-row-divider@6"
380
+ animation="fade"
381
+ :width="100"
382
+ :rounded="true"
383
+ :height="32"
384
+ ></vue-skeleton-loader>
385
+ </div>
386
+ <vue-skeleton-loader
387
+ type="table-tbody: table-row-divider@6"
388
+ animation="fade"
389
+ class="!w-full"
390
+ :rounded="true"
391
+ :height="32"
392
+ ></vue-skeleton-loader>
393
+ </div>
394
+ </div>
395
+ </div>
396
+ </template>
397
+ <template v-else>
398
+ <p class="vgt-center-align vgt-text-disabled">
399
+ {{ emptyStatePlaceholderText }}
400
+ </p>
401
+ </template>
402
+ </div>
403
+ <template slot="table-row" slot-scope="props">
404
+ <!-- renders if drag and drop is present in table -->
405
+ <span v-if="props.column.field == 'drag'">
406
+ <c-icon
407
+ name="draggable"
408
+ type="solid"
409
+ :class="`handle h-5 w-5 ${
410
+ props.row.status && props.row.status === 2
411
+ ? 'pointer-events-none cursor-default opacity-50'
412
+ : 'text-gray-500'
413
+ }`"
414
+ :cursorType="'cursor-grab'"
415
+ ></c-icon>
416
+ </span>
417
+ <!-- if customization or adding another form element is required -->
418
+ <span v-else-if="props.column.customizeColumn">
419
+ <slot
420
+ :records="props"
421
+ :isHovered="enableRowHover && isRowHovered(props)"
422
+ >
423
+ </slot>
424
+ </span>
425
+ <span v-else-if="props.column.field === '__hoverText'">
426
+ <span
427
+ v-if="isRowHovered(props)"
428
+ class="text-sm text-gray-500 whitespace-nowrap"
429
+ >
430
+ {{ rowHoverText }}
431
+ </span>
432
+ </span>
433
+ <!-- renders records as per column name -->
434
+ <span v-else>
435
+ {{ props.formattedRow[props.column.field] }}
436
+ </span>
437
+ </template>
438
+ <!-- Custom pagination component -->
439
+ <template v-if="pagination" slot="pagination-bottom">
440
+ <c-pagination
441
+ v-if="paginationRecords.totalRecords > 0"
442
+ :setPaginationRecords="paginationRecords"
443
+ :totalRecordsOnPage="recordsToDisplay"
444
+ :showEntryPicker="showEntryPicker"
445
+ :id="id"
446
+ @setCurrentPage="setCurrentPageRecords"
447
+ @setPreviousPage="setPreviousPageRecords"
448
+ @setNextPage="setNextPageRecords"
449
+ @handle-Row-Count-Change="handleChangeRowCount"
450
+ ></c-pagination>
451
+ </template>
452
+ </vue-good-table>
453
+
454
+ <!-- Floating Action Bar -->
455
+ <transition name="floating-action-bar">
456
+ <div
457
+ v-if="shouldShowFloatingActionBar"
458
+ ref="floatingActionBar"
459
+ :style="floatingActionBarStyle"
460
+ class="fixed bottom-8 left-1/2 z-10 -translate-x-1/2"
461
+ >
462
+ <div
463
+ class="flex shrink-0 items-center justify-center rounded-xl bg-gray-900 p-3 shadow-lg"
464
+ :style="floatingActionBarGapStyle"
465
+ >
466
+ <!-- Close button and selection count -->
467
+ <div class="flex items-center gap-1">
468
+ <c-button-icon
469
+ :id="id + '_button_close_action_bar'"
470
+ type="dark-blue"
471
+ :icon="{
472
+ name: 'x-mark-solid-v2',
473
+ type: 'solid',
474
+ class: 'h-5 w-5 text-gray-300 group-hover:text-white',
475
+ viewBox: '0 0 24 24',
476
+ }"
477
+ title="Close selection"
478
+ aria-label="Close selection"
479
+ customButtonClasses="group"
480
+ @action="handleClearSelectedRows"
481
+ ></c-button-icon>
482
+ <slot name="floatingActionBarActionsInfo"></slot>
483
+ </div>
484
+
485
+ <!-- Custom action buttons slot -->
486
+ <div class="flex items-center gap-1">
487
+ <slot
488
+ name="floatingActionBarActions"
489
+ :clearSelection="handleClearSelectedRows"
490
+ ></slot>
491
+ </div>
492
+ </div>
493
+ </div>
494
+ </transition>
495
+ </div>
496
+ </template>
497
+ <script>
498
+ import CIcon from "../CIcon/CIcon.vue";
499
+ import CCheckbox from "../CCheckbox/CCheckbox.vue";
500
+ import CPagination from "../CPagination/CPagination.vue";
501
+ import CButtonIcon from "../CButtonIcon/CButtonIcon.vue";
502
+ import CToolTip from "../CToolTip/CToolTip.vue";
503
+ import "vue-good-table/dist/vue-good-table.css";
504
+ import { VueGoodTable } from "vue-good-table";
505
+ import Sortable from "@shopify/draggable/lib/es5/sortable.js";
506
+ import CInput from "../CInput/CInput.vue";
507
+ import { debounce, isEqual } from "lodash-es";
508
+ import VueSkeletonLoader from "skeleton-loader-vue";
509
+ import { getActionID } from "../../helper";
510
+
511
+ const RESIZE_DEBOUNCE_DELAY = 150;
512
+
513
+ export default {
514
+ name: "CTable",
515
+ components: {
516
+ CCheckbox,
517
+ CIcon,
518
+ VueGoodTable,
519
+ CPagination,
520
+ CButtonIcon,
521
+ CInput,
522
+ VueSkeletonLoader,
523
+ CToolTip,
524
+ },
525
+ props: {
526
+ fontHeader: {
527
+ type: Boolean,
528
+ default: false,
529
+ },
530
+ // To show or hide pagination section
531
+ pagination: {
532
+ type: Boolean,
533
+ },
534
+ // To enable or disable sorting
535
+ sorting: {
536
+ type: Boolean,
537
+ },
538
+ // To show or hide search input
539
+ searching: {
540
+ type: Boolean,
541
+ },
542
+ // To add checkbox to select rows
543
+ enableSelection: {
544
+ type: Boolean,
545
+ },
546
+ enableVisibility: {
547
+ type: Boolean,
548
+ default: true,
549
+ },
550
+ disableColumnsDropdown: {
551
+ type: Boolean,
552
+ default: false,
553
+ },
554
+ enableDownload: {
555
+ type: Boolean,
556
+ default: true,
557
+ },
558
+ // All the buttons displayed on top right side of table
559
+ tableActions: {
560
+ type: Boolean,
561
+ },
562
+ // Placeholder text for search
563
+ searchPlaceholder: {
564
+ type: String,
565
+ },
566
+ // Existing text for search
567
+ searchQuery: {
568
+ type: String,
569
+ },
570
+ isLoading: {
571
+ type: Boolean,
572
+ },
573
+ // ID
574
+ totalRecords: {
575
+ type: String,
576
+ },
577
+ // Total number of rows in a table to calculate page numbers
578
+ id: {
579
+ type: String,
580
+ },
581
+ // Shows current selected page and records on per page
582
+ paginationData: {
583
+ type: Object,
584
+ },
585
+ // Pass a column on which initial sorting will be applied
586
+ initialSortField: {
587
+ type: Object,
588
+ },
589
+ // all columns of the table
590
+ cols: {
591
+ type: Array,
592
+ required: true,
593
+ },
594
+ // row records of the table
595
+ rows: {
596
+ type: Array,
597
+ required: true,
598
+ },
599
+ // List of columns to show hide
600
+ showHideColumnList: {
601
+ type: Array,
602
+ },
603
+ // List of items to show download options
604
+ showDownloadDropdownList: {
605
+ type: Array,
606
+ },
607
+ // Function on changing page number
608
+ onPageChange: {
609
+ type: Function,
610
+ },
611
+ // Function on changing sorting on column
612
+ onSortChange: {
613
+ type: Function,
614
+ },
615
+ // Function to fetch results on search query
616
+ onSearch: {
617
+ type: Function,
618
+ },
619
+ // Emit action on clicking the row
620
+ onRowClickAction: {
621
+ type: Function,
622
+ },
623
+ // Start the loader
624
+ downloadLoader: {
625
+ type: Boolean,
626
+ },
627
+ // Start the loader
628
+ downloadOptionLoader: {
629
+ type: Boolean,
630
+ },
631
+ downloadDropdown: {
632
+ type: Boolean,
633
+ },
634
+ rowStyleClassFn: {
635
+ type: Function,
636
+ default: () => "",
637
+ },
638
+ fixedHeader: {
639
+ type: Boolean,
640
+ default: false,
641
+ },
642
+ hideBorder: {
643
+ type: Boolean,
644
+ default: false,
645
+ },
646
+ showEntryPicker: {
647
+ type: Boolean,
648
+ default: false,
649
+ },
650
+ enableGrouping: {
651
+ type: Boolean,
652
+ default: false,
653
+ },
654
+ //enables user to select rows by clicking on the row
655
+ selectOnCheckBoxClickOnly: {
656
+ type: Boolean,
657
+ default: true,
658
+ },
659
+ //shows new show hide column button
660
+ showNewShowHideColumnButton: {
661
+ type: Boolean,
662
+ default: false,
663
+ },
664
+ disableDownloadButton: {
665
+ type: Boolean,
666
+ default: false,
667
+ },
668
+ searchInputClass: {
669
+ type: String,
670
+ default: "w-auto sm:w-56",
671
+ },
672
+ showTableActionsTooltip: {
673
+ type: Boolean,
674
+ default: false,
675
+ },
676
+ emptyStatePlaceholderText: {
677
+ type: String,
678
+ default: "No data for table",
679
+ },
680
+ inputWrapperClass: {
681
+ type: String,
682
+ default: "",
683
+ },
684
+ addAvatarLoader: {
685
+ type: Boolean,
686
+ default: false,
687
+ },
688
+ // Enable row hover effects (color change and hover text)
689
+ enableRowHover: {
690
+ type: Boolean,
691
+ default: false,
692
+ },
693
+ // Text to show at the end of row on hover
694
+ rowHoverText: {
695
+ type: String,
696
+ default: "",
697
+ },
698
+ showFloatingActionBar: {
699
+ type: Boolean,
700
+ default: false,
701
+ },
702
+ // Selector for the container element used for floating action bar positioning
703
+ // Defaults to '.content-container > div' for backward compatibility which is the main layout of the page
704
+ containerSelector: {
705
+ type: String,
706
+ default: ".content-container > div",
707
+ },
708
+ },
709
+ computed: {
710
+ cssVars() {
711
+ return {
712
+ "--vgt-bottom-radius": this.pagination ? "0" : "8px",
713
+ };
714
+ },
715
+ colsWithHeaderClasses() {
716
+ const cols = this.cols.map((col) => ({
717
+ ...col,
718
+ thClass: `${this.id}_header_${col.field}`,
719
+ }));
720
+
721
+ // Add hover text column at the end if enabled
722
+ if (this.enableRowHover && this.rowHoverText) {
723
+ cols.push({
724
+ label: "",
725
+ field: "__hoverText",
726
+ hidden: false,
727
+ sortable: false,
728
+ thClass: `${this.id}_header___hoverText`,
729
+ tdClass: "hover-text-column",
730
+ });
731
+ }
732
+
733
+ return cols;
734
+ },
735
+ shouldShowFloatingActionBar() {
736
+ return this.showFloatingActionBar && this.enableSelection;
737
+ },
738
+ floatingActionBarGapStyle() {
739
+ if (!this.shouldShowFloatingActionBar) return {};
740
+
741
+ /*
742
+ Responsive gap using clamp(min, preferred, max)
743
+ - Minimum: 12px → gap will never go below 12px
744
+ - Preferred: 4vw → scales fluidly with viewport width i.e., 4% of viewport width
745
+ - Maximum: 80px → gap will never exceed 80px
746
+ */
747
+ return {
748
+ gap: "clamp(12px, 4vw, 80px)",
749
+ };
750
+ },
751
+ },
752
+ mounted() {
753
+ // to add drag and drop in table
754
+ this.reorderedArray = this.rows;
755
+ let sortable = new Sortable(document.querySelectorAll("tbody"), {
756
+ draggable: "tr",
757
+ handle: ".handle",
758
+ classes: {
759
+ mirror: ["bg-white"],
760
+ },
761
+ mirror: {
762
+ constrainDimensions: true,
763
+ },
764
+ });
765
+ sortable.on("sortable:stop", (e) => this.rearrange(e.oldIndex, e.newIndex));
766
+ document.addEventListener("keydown", this.handleControlClick, true);
767
+ document.addEventListener("keyup", this.handleControlRelease, true);
768
+
769
+ // Setup floating action bar positioning
770
+ if (this.shouldShowFloatingActionBar) {
771
+ this.$nextTick(() => {
772
+ this.updateFloatingActionBarPosition();
773
+ this.setupResizeObserver();
774
+ })
775
+ }
776
+ },
777
+ destroyed() {
778
+ //to remove the event listener
779
+ document.removeEventListener("keydown", this.handleControlClick, true);
780
+ document.removeEventListener("keyup", this.handleControlRelease, true);
781
+
782
+ this.cleanupResizeObserver();
783
+ },
784
+ data() {
785
+ return {
786
+ toggleDropdown: false,
787
+ toggleDownloadDropdown: false,
788
+ searchTerm: this.searchQuery ? this.searchQuery : "",
789
+ paginationRecords: this.paginationData,
790
+ reorderedArray: [],
791
+ controlClick: false,
792
+ attrs: {
793
+ boilerplate: true,
794
+ elevation: 2,
795
+ },
796
+ recordsToDisplay: {
797
+ option: 10,
798
+ value: 10,
799
+ },
800
+ showShowHideColumnTooltip: false,
801
+ showDownloadTooltip: false,
802
+ hoveredRowId: null,
803
+ floatingActionBarStyle: {},
804
+ };
805
+ },
806
+ methods: {
807
+ getActionIDFn(name) {
808
+ return getActionID(name, this.id);
809
+ },
810
+ handleChangeRowCount(value) {
811
+ this.recordsToDisplay = value;
812
+ this.$emit("change-row-count", value.value);
813
+ },
814
+ handleToolTipDisplay(value, type) {
815
+ if (!this.showTableActionsTooltip) {
816
+ return;
817
+ }
818
+ if (type === "showHideColumn") {
819
+ this.showShowHideColumnTooltip = value;
820
+ } else if (type === "download") {
821
+ this.showDownloadTooltip = value;
822
+ }
823
+ },
824
+ handleControlClick(event) {
825
+ if (event.keyCode === 17 || event.keyCode === 91) {
826
+ event.preventDefault();
827
+ this.controlClick = true;
828
+ }
829
+ },
830
+ handleControlRelease(event) {
831
+ if (event.keyCode === 17 || event.keyCode === 91) {
832
+ event.preventDefault();
833
+ this.controlClick = false;
834
+ }
835
+ },
836
+ handleToggle() {
837
+ this.toggleDropdown = !this.toggleDropdown;
838
+ },
839
+ handleDownloadToggle() {
840
+ this.toggleDownloadDropdown = !this.toggleDownloadDropdown;
841
+ },
842
+ showHideColumn(value, name) {
843
+ this.$emit("hideCols", value, name);
844
+ },
845
+ handleClearSelectedRows() {
846
+ if (this.$refs["my-table"]) {
847
+ this.$refs["my-table"].unselectAllInternal();
848
+ }
849
+ this.$emit("closeSelection");
850
+ },
851
+ // Function to get selected rows on checking the checkbox
852
+ selectionChanged() {
853
+ this.$emit(
854
+ "selectRows",
855
+ this.$refs["my-table"].selectedRows,
856
+ this.$refs["my-table"].allSelected
857
+ );
858
+ },
859
+ // array of rows after drag and drop
860
+ rearrange(oldIndex, newIndex) {
861
+ const movedItem = this.reorderedArray.find(
862
+ (item, index) => index === oldIndex
863
+ );
864
+ const remainingItems = this.reorderedArray.filter(
865
+ (item, index) => index !== oldIndex
866
+ );
867
+ const reorderedItems = [
868
+ ...remainingItems.slice(0, newIndex),
869
+ movedItem,
870
+ ...remainingItems.slice(newIndex),
871
+ ];
872
+ this.reorderedArray = [...reorderedItems];
873
+ this.$emit(
874
+ "reordered",
875
+ this.reorderedArray,
876
+ movedItem,
877
+ oldIndex,
878
+ newIndex
879
+ );
880
+ },
881
+ // listing functions
882
+ sortChange(params) {
883
+ if (params[0].type == "none") {
884
+ params[0].type = "asc";
885
+ }
886
+ this.$emit("onSortChange", params);
887
+ },
888
+ onSearching: debounce(function (params) {
889
+ this.$emit("onSearch", params);
890
+ }, 500),
891
+ setCurrentPageRecords(page) {
892
+ this.paginationRecords.currentPage = page;
893
+ this.$emit("pageChange", page);
894
+ },
895
+ setPreviousPageRecords(page) {
896
+ this.paginationRecords.currentPage = page;
897
+ this.$emit("pageChange", page);
898
+ },
899
+ setNextPageRecords(page) {
900
+ this.paginationRecords.currentPage = page;
901
+ this.$emit("pageChange", page);
902
+ },
903
+ onRowClick(params) {
904
+ if (!this.selectOnCheckBoxClickOnly) {
905
+ return;
906
+ }
907
+ if (params.event.target.type === undefined) {
908
+ if (this.controlClick) {
909
+ this.$emit("onRowControlClickAction", params);
910
+ } else {
911
+ this.$emit("onRowClickAction", params);
912
+ }
913
+ } else {
914
+ return false;
915
+ }
916
+ },
917
+ startDownload() {
918
+ this.$emit("handleDownloadButton");
919
+ },
920
+ downloadFromOption(value) {
921
+ this.toggleDownloadDropdown = false;
922
+ this.$emit("handleDownloadOptionButton", value);
923
+ },
924
+
925
+ handleRowExpand() {
926
+ this.$refs["my-table"].expandAll();
927
+ },
928
+ onRowMouseover(params) {
929
+ if (this.enableRowHover) {
930
+ this.hoveredRowId = params.row.id;
931
+ }
932
+ },
933
+ onRowMouseleave() {
934
+ if (this.enableRowHover) {
935
+ this.hoveredRowId = null;
936
+ }
937
+ },
938
+ isRowHovered(props) {
939
+ if (!this.enableRowHover || !this.hoveredRowId) {
940
+ return false;
941
+ }
942
+ return props.row.id === this.hoveredRowId;
943
+ },
944
+ updateFloatingActionBarPosition() {
945
+ if (!this.shouldShowFloatingActionBar) {
946
+ this.floatingActionBarStyle = {};
947
+ return;
948
+ }
949
+
950
+ let contentContainer = document.querySelector(this.containerSelector);
951
+ if (!contentContainer && this.$el) {
952
+ contentContainer = this.$el.closest(".content");
953
+ }
954
+ if (!contentContainer) {
955
+ this.floatingActionBarStyle = {
956
+ maxWidth: "100%",
957
+ };
958
+ return;
959
+ }
960
+
961
+ const rect = contentContainer.getBoundingClientRect();
962
+ const containerCenter = rect.left + rect.width / 2;
963
+
964
+ this.floatingActionBarStyle = {
965
+ left: `${containerCenter}px`,
966
+ width: "max-content",
967
+ maxWidth: "100%",
968
+ };
969
+ },
970
+ cleanupResizeObserver() {
971
+ if (this._resizeHandler) {
972
+ window.removeEventListener("resize", this._resizeHandler);
973
+ this._resizeHandler = null;
974
+ }
975
+ },
976
+ setupResizeObserver() {
977
+ // Remove existing listener if any
978
+ if (this._resizeHandler) {
979
+ window.removeEventListener("resize", this._resizeHandler);
980
+ }
981
+
982
+ // Create debounced resize handler
983
+ this._resizeHandler = debounce(() => {
984
+ if (this.shouldShowFloatingActionBar) {
985
+ this.updateFloatingActionBarPosition();
986
+ }
987
+ }, RESIZE_DEBOUNCE_DELAY);
988
+
989
+ window.addEventListener("resize", this._resizeHandler);
990
+ },
991
+ },
992
+ watch: {
993
+ paginationData(newValue, oldValue) {
994
+ if (!isEqual(newValue, oldValue)) {
995
+ this.paginationRecords = newValue;
996
+ }
997
+ },
998
+ rows(newValue, oldValue) {
999
+ if (!isEqual(newValue, oldValue)) {
1000
+ this.reorderedArray = newValue;
1001
+ }
1002
+ },
1003
+ shouldShowFloatingActionBar(newValue) {
1004
+ if (newValue) {
1005
+ this.$nextTick(() => {
1006
+ this.updateFloatingActionBarPosition();
1007
+ this.setupResizeObserver();
1008
+ });
1009
+ } else {
1010
+ this.floatingActionBarStyle = {};
1011
+ this.cleanupResizeObserver();
1012
+ }
1013
+ },
1014
+ },
1015
+ };
1016
+ </script>
1017
+ <style>
1018
+ .vgt-table {
1019
+ border-spacing: 0;
1020
+ border: none !important;
1021
+ font-family: "Inter";
1022
+ font-size: 14px !important;
1023
+ }
1024
+ table.vgt-table td {
1025
+ vertical-align: middle;
1026
+ }
1027
+ .vgt-table thead th {
1028
+ background: linear-gradient(#fff, #fff);
1029
+ }
1030
+ .vgt-table th.vgt-checkbox-col {
1031
+ border-right: 0;
1032
+ border-bottom: 1px solid #dcdfe6;
1033
+ background: linear-gradient(#fff, #fff);
1034
+ }
1035
+ table.vgt-table tr.clickable:hover {
1036
+ background-color: #f9fafb;
1037
+ border-bottom: 1px solid #dcdfe6 !important;
1038
+ }
1039
+ .vgt-table th.sortable button::before,
1040
+ .vgt-table th.sortable button::after {
1041
+ border-right: 0;
1042
+ border-left: 0;
1043
+ }
1044
+ [type="checkbox"],
1045
+ [type="checkbox"]:focus {
1046
+ border-radius: 4px;
1047
+ border-color: #d1d5db;
1048
+ cursor: pointer;
1049
+ color: #0284c7;
1050
+ --tw-ring-color: #0284c7;
1051
+ }
1052
+
1053
+ /* tbody > tr > th.vgt-checkbox-col {
1054
+ background: linear-gradient(#fff, #fff);
1055
+ border-bottom: 1px solid #dcdfe6;
1056
+ } */
1057
+ .vgt-global-search {
1058
+ background: none;
1059
+ border: none;
1060
+ padding: 0 0 12px 0;
1061
+ }
1062
+ .vgt-global-search__input {
1063
+ padding-left: 0;
1064
+ }
1065
+ .input__icon {
1066
+ display: none;
1067
+ }
1068
+ .vgt-global-search__input .vgt-input {
1069
+ height: 38px;
1070
+ width: 250px;
1071
+ }
1072
+ .vgt-inner-wrap {
1073
+ box-shadow: none;
1074
+ }
1075
+ .vgt-inner-wrap.is-loading {
1076
+ opacity: 1;
1077
+ pointer-events: auto;
1078
+ }
1079
+ .vgt-table th.sortable:hover .sortingIcon {
1080
+ visibility: visible;
1081
+ }
1082
+ .vgt-responsive {
1083
+ position: static;
1084
+ border-top-left-radius: 8px;
1085
+ border-top-right-radius: 8px;
1086
+ border-bottom-left-radius: var(--vgt-bottom-radius, 0);
1087
+ border-bottom-right-radius: var(--vgt-bottom-radius, 0);
1088
+ }
1089
+ .vgt-wrap {
1090
+ position: static;
1091
+ }
1092
+ .hover-text-column {
1093
+ text-align: right;
1094
+ padding-right: 1rem;
1095
+ width: 180px;
1096
+ min-width: 180px;
1097
+ }
1098
+ .floating-action-bar-enter-active,
1099
+ .floating-action-bar-leave-active {
1100
+ transition: opacity 300ms ease, transform 300ms ease;
1101
+ }
1102
+
1103
+ .floating-action-bar-enter,
1104
+ .floating-action-bar-leave-to {
1105
+ opacity: 0;
1106
+ transform: translate(-50%, 100%);
1107
+ }
1108
+
1109
+ .floating-action-bar-enter-to,
1110
+ .floating-action-bar-leave {
1111
+ opacity: 1;
1112
+ transform: translate(-50%, 0);
1113
+ }
1114
+ </style>