VDataTableHeaders.mjs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import { resolveDirective as _resolveDirective, Fragment as _Fragment, mergeProps as _mergeProps, createVNode as _createVNode } from "vue";
  2. // Components
  3. import { VDataTableColumn } from "./VDataTableColumn.mjs";
  4. import { VCheckboxBtn } from "../VCheckbox/index.mjs";
  5. import { VChip } from "../VChip/index.mjs";
  6. import { VIcon } from "../VIcon/index.mjs";
  7. import { VSelect } from "../VSelect/index.mjs"; // Composables
  8. import { useHeaders } from "./composables/headers.mjs";
  9. import { useSelection } from "./composables/select.mjs";
  10. import { useSort } from "./composables/sort.mjs";
  11. import { useBackgroundColor } from "../../composables/color.mjs";
  12. import { makeDisplayProps, useDisplay } from "../../composables/display.mjs";
  13. import { IconValue } from "../../composables/icons.mjs";
  14. import { LoaderSlot, makeLoaderProps, useLoader } from "../../composables/loader.mjs";
  15. import { useLocale } from "../../composables/locale.mjs"; // Utilities
  16. import { computed, mergeProps } from 'vue';
  17. import { convertToUnit, genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types
  18. export const makeVDataTableHeadersProps = propsFactory({
  19. color: String,
  20. sticky: Boolean,
  21. disableSort: Boolean,
  22. multiSort: Boolean,
  23. sortAscIcon: {
  24. type: IconValue,
  25. default: '$sortAsc'
  26. },
  27. sortDescIcon: {
  28. type: IconValue,
  29. default: '$sortDesc'
  30. },
  31. headerProps: {
  32. type: Object
  33. },
  34. ...makeDisplayProps(),
  35. ...makeLoaderProps()
  36. }, 'VDataTableHeaders');
  37. export const VDataTableHeaders = genericComponent()({
  38. name: 'VDataTableHeaders',
  39. props: makeVDataTableHeadersProps(),
  40. setup(props, _ref) {
  41. let {
  42. slots
  43. } = _ref;
  44. const {
  45. t
  46. } = useLocale();
  47. const {
  48. toggleSort,
  49. sortBy,
  50. isSorted
  51. } = useSort();
  52. const {
  53. someSelected,
  54. allSelected,
  55. selectAll,
  56. showSelectAll
  57. } = useSelection();
  58. const {
  59. columns,
  60. headers
  61. } = useHeaders();
  62. const {
  63. loaderClasses
  64. } = useLoader(props);
  65. function getFixedStyles(column, y) {
  66. if (!props.sticky && !column.fixed) return undefined;
  67. return {
  68. position: 'sticky',
  69. left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
  70. top: props.sticky ? `calc(var(--v-table-header-height) * ${y})` : undefined
  71. };
  72. }
  73. function getSortIcon(column) {
  74. const item = sortBy.value.find(item => item.key === column.key);
  75. if (!item) return props.sortAscIcon;
  76. return item.order === 'asc' ? props.sortAscIcon : props.sortDescIcon;
  77. }
  78. const {
  79. backgroundColorClasses,
  80. backgroundColorStyles
  81. } = useBackgroundColor(props, 'color');
  82. const {
  83. displayClasses,
  84. mobile
  85. } = useDisplay(props);
  86. const slotProps = computed(() => ({
  87. headers: headers.value,
  88. columns: columns.value,
  89. toggleSort,
  90. isSorted,
  91. sortBy: sortBy.value,
  92. someSelected: someSelected.value,
  93. allSelected: allSelected.value,
  94. selectAll,
  95. getSortIcon
  96. }));
  97. const headerCellClasses = computed(() => ['v-data-table__th', {
  98. 'v-data-table__th--sticky': props.sticky
  99. }, displayClasses.value, loaderClasses.value]);
  100. const VDataTableHeaderCell = _ref2 => {
  101. let {
  102. column,
  103. x,
  104. y
  105. } = _ref2;
  106. const noPadding = column.key === 'data-table-select' || column.key === 'data-table-expand';
  107. const headerProps = mergeProps(props.headerProps ?? {}, column.headerProps ?? {});
  108. return _createVNode(VDataTableColumn, _mergeProps({
  109. "tag": "th",
  110. "align": column.align,
  111. "class": [{
  112. 'v-data-table__th--sortable': column.sortable && !props.disableSort,
  113. 'v-data-table__th--sorted': isSorted(column),
  114. 'v-data-table__th--fixed': column.fixed
  115. }, ...headerCellClasses.value],
  116. "style": {
  117. width: convertToUnit(column.width),
  118. minWidth: convertToUnit(column.minWidth),
  119. maxWidth: convertToUnit(column.maxWidth),
  120. ...getFixedStyles(column, y)
  121. },
  122. "colspan": column.colspan,
  123. "rowspan": column.rowspan,
  124. "onClick": column.sortable ? () => toggleSort(column) : undefined,
  125. "fixed": column.fixed,
  126. "nowrap": column.nowrap,
  127. "lastFixed": column.lastFixed,
  128. "noPadding": noPadding
  129. }, headerProps), {
  130. default: () => {
  131. const columnSlotName = `header.${column.key}`;
  132. const columnSlotProps = {
  133. column,
  134. selectAll,
  135. isSorted,
  136. toggleSort,
  137. sortBy: sortBy.value,
  138. someSelected: someSelected.value,
  139. allSelected: allSelected.value,
  140. getSortIcon
  141. };
  142. if (slots[columnSlotName]) return slots[columnSlotName](columnSlotProps);
  143. if (column.key === 'data-table-select') {
  144. return slots['header.data-table-select']?.(columnSlotProps) ?? (showSelectAll.value && _createVNode(VCheckboxBtn, {
  145. "modelValue": allSelected.value,
  146. "indeterminate": someSelected.value && !allSelected.value,
  147. "onUpdate:modelValue": selectAll
  148. }, null));
  149. }
  150. return _createVNode("div", {
  151. "class": "v-data-table-header__content"
  152. }, [_createVNode("span", null, [column.title]), column.sortable && !props.disableSort && _createVNode(VIcon, {
  153. "key": "icon",
  154. "class": "v-data-table-header__sort-icon",
  155. "icon": getSortIcon(column)
  156. }, null), props.multiSort && isSorted(column) && _createVNode("div", {
  157. "key": "badge",
  158. "class": ['v-data-table-header__sort-badge', ...backgroundColorClasses.value],
  159. "style": backgroundColorStyles.value
  160. }, [sortBy.value.findIndex(x => x.key === column.key) + 1])]);
  161. }
  162. });
  163. };
  164. const VDataTableMobileHeaderCell = () => {
  165. const headerProps = mergeProps(props.headerProps ?? {} ?? {});
  166. const displayItems = computed(() => {
  167. return columns.value.filter(column => column?.sortable && !props.disableSort);
  168. });
  169. const appendIcon = computed(() => {
  170. const showSelectColumn = columns.value.find(column => column.key === 'data-table-select');
  171. if (showSelectColumn == null) return;
  172. return allSelected.value ? '$checkboxOn' : someSelected.value ? '$checkboxIndeterminate' : '$checkboxOff';
  173. });
  174. return _createVNode(VDataTableColumn, _mergeProps({
  175. "tag": "th",
  176. "class": [...headerCellClasses.value],
  177. "colspan": headers.value.length + 1
  178. }, headerProps), {
  179. default: () => [_createVNode("div", {
  180. "class": "v-data-table-header__content"
  181. }, [_createVNode(VSelect, {
  182. "chips": true,
  183. "class": "v-data-table__td-sort-select",
  184. "clearable": true,
  185. "density": "default",
  186. "items": displayItems.value,
  187. "label": t('$vuetify.dataTable.sortBy'),
  188. "multiple": props.multiSort,
  189. "variant": "underlined",
  190. "onClick:clear": () => sortBy.value = [],
  191. "appendIcon": appendIcon.value,
  192. "onClick:append": () => selectAll(!allSelected.value)
  193. }, {
  194. ...slots,
  195. chip: props => _createVNode(VChip, {
  196. "onClick": props.item.raw?.sortable ? () => toggleSort(props.item.raw) : undefined,
  197. "onMousedown": e => {
  198. e.preventDefault();
  199. e.stopPropagation();
  200. }
  201. }, {
  202. default: () => [props.item.title, _createVNode(VIcon, {
  203. "class": ['v-data-table__td-sort-icon', isSorted(props.item.raw) && 'v-data-table__td-sort-icon-active'],
  204. "icon": getSortIcon(props.item.raw),
  205. "size": "small"
  206. }, null)]
  207. })
  208. })])]
  209. });
  210. };
  211. useRender(() => {
  212. return mobile.value ? _createVNode("tr", null, [_createVNode(VDataTableMobileHeaderCell, null, null)]) : _createVNode(_Fragment, null, [slots.headers ? slots.headers(slotProps.value) : headers.value.map((row, y) => _createVNode("tr", null, [row.map((column, x) => _createVNode(VDataTableHeaderCell, {
  213. "column": column,
  214. "x": x,
  215. "y": y
  216. }, null))])), props.loading && _createVNode("tr", {
  217. "class": "v-data-table-progress"
  218. }, [_createVNode("th", {
  219. "colspan": columns.value.length
  220. }, [_createVNode(LoaderSlot, {
  221. "name": "v-data-table-progress",
  222. "absolute": true,
  223. "active": true,
  224. "color": typeof props.loading === 'boolean' ? undefined : props.loading,
  225. "indeterminate": true
  226. }, {
  227. default: slots.loader
  228. })])])]);
  229. });
  230. }
  231. });
  232. //# sourceMappingURL=VDataTableHeaders.mjs.map