table-layout.mjs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { ref, isRef, nextTick } from 'vue';
  2. import { isClient } from '@vueuse/core';
  3. import '../../../utils/index.mjs';
  4. import { parseHeight } from './util.mjs';
  5. import { hasOwn } from '@vue/shared';
  6. class TableLayout {
  7. constructor(options) {
  8. this.observers = [];
  9. this.table = null;
  10. this.store = null;
  11. this.columns = [];
  12. this.fit = true;
  13. this.showHeader = true;
  14. this.height = ref(null);
  15. this.scrollX = ref(false);
  16. this.scrollY = ref(false);
  17. this.bodyWidth = ref(null);
  18. this.fixedWidth = ref(null);
  19. this.rightFixedWidth = ref(null);
  20. this.gutterWidth = 0;
  21. for (const name in options) {
  22. if (hasOwn(options, name)) {
  23. if (isRef(this[name])) {
  24. this[name].value = options[name];
  25. } else {
  26. this[name] = options[name];
  27. }
  28. }
  29. }
  30. if (!this.table) {
  31. throw new Error("Table is required for Table Layout");
  32. }
  33. if (!this.store) {
  34. throw new Error("Store is required for Table Layout");
  35. }
  36. }
  37. updateScrollY() {
  38. const height = this.height.value;
  39. if (height === null)
  40. return false;
  41. const scrollBarRef = this.table.refs.scrollBarRef;
  42. if (this.table.vnode.el && scrollBarRef) {
  43. let scrollY = true;
  44. const prevScrollY = this.scrollY.value;
  45. scrollY = scrollBarRef.wrapRef.scrollHeight > scrollBarRef.wrapRef.clientHeight;
  46. this.scrollY.value = scrollY;
  47. return prevScrollY !== scrollY;
  48. }
  49. return false;
  50. }
  51. setHeight(value, prop = "height") {
  52. if (!isClient)
  53. return;
  54. const el = this.table.vnode.el;
  55. value = parseHeight(value);
  56. this.height.value = Number(value);
  57. if (!el && (value || value === 0))
  58. return nextTick(() => this.setHeight(value, prop));
  59. if (typeof value === "number") {
  60. el.style[prop] = `${value}px`;
  61. this.updateElsHeight();
  62. } else if (typeof value === "string") {
  63. el.style[prop] = value;
  64. this.updateElsHeight();
  65. }
  66. }
  67. setMaxHeight(value) {
  68. this.setHeight(value, "max-height");
  69. }
  70. getFlattenColumns() {
  71. const flattenColumns = [];
  72. const columns = this.table.store.states.columns.value;
  73. columns.forEach((column) => {
  74. if (column.isColumnGroup) {
  75. flattenColumns.push.apply(flattenColumns, column.columns);
  76. } else {
  77. flattenColumns.push(column);
  78. }
  79. });
  80. return flattenColumns;
  81. }
  82. updateElsHeight() {
  83. this.updateScrollY();
  84. this.notifyObservers("scrollable");
  85. }
  86. headerDisplayNone(elm) {
  87. if (!elm)
  88. return true;
  89. let headerChild = elm;
  90. while (headerChild.tagName !== "DIV") {
  91. if (getComputedStyle(headerChild).display === "none") {
  92. return true;
  93. }
  94. headerChild = headerChild.parentElement;
  95. }
  96. return false;
  97. }
  98. updateColumnsWidth() {
  99. if (!isClient)
  100. return;
  101. const fit = this.fit;
  102. const bodyWidth = this.table.vnode.el.clientWidth;
  103. let bodyMinWidth = 0;
  104. const flattenColumns = this.getFlattenColumns();
  105. const flexColumns = flattenColumns.filter((column) => typeof column.width !== "number");
  106. flattenColumns.forEach((column) => {
  107. if (typeof column.width === "number" && column.realWidth)
  108. column.realWidth = null;
  109. });
  110. if (flexColumns.length > 0 && fit) {
  111. flattenColumns.forEach((column) => {
  112. bodyMinWidth += Number(column.width || column.minWidth || 80);
  113. });
  114. if (bodyMinWidth <= bodyWidth) {
  115. this.scrollX.value = false;
  116. const totalFlexWidth = bodyWidth - bodyMinWidth;
  117. if (flexColumns.length === 1) {
  118. flexColumns[0].realWidth = Number(flexColumns[0].minWidth || 80) + totalFlexWidth;
  119. } else {
  120. const allColumnsWidth = flexColumns.reduce((prev, column) => prev + Number(column.minWidth || 80), 0);
  121. const flexWidthPerPixel = totalFlexWidth / allColumnsWidth;
  122. let noneFirstWidth = 0;
  123. flexColumns.forEach((column, index) => {
  124. if (index === 0)
  125. return;
  126. const flexWidth = Math.floor(Number(column.minWidth || 80) * flexWidthPerPixel);
  127. noneFirstWidth += flexWidth;
  128. column.realWidth = Number(column.minWidth || 80) + flexWidth;
  129. });
  130. flexColumns[0].realWidth = Number(flexColumns[0].minWidth || 80) + totalFlexWidth - noneFirstWidth;
  131. }
  132. } else {
  133. this.scrollX.value = true;
  134. flexColumns.forEach((column) => {
  135. column.realWidth = Number(column.minWidth);
  136. });
  137. }
  138. this.bodyWidth.value = Math.max(bodyMinWidth, bodyWidth);
  139. this.table.state.resizeState.value.width = this.bodyWidth.value;
  140. } else {
  141. flattenColumns.forEach((column) => {
  142. if (!column.width && !column.minWidth) {
  143. column.realWidth = 80;
  144. } else {
  145. column.realWidth = Number(column.width || column.minWidth);
  146. }
  147. bodyMinWidth += column.realWidth;
  148. });
  149. this.scrollX.value = bodyMinWidth > bodyWidth;
  150. this.bodyWidth.value = bodyMinWidth;
  151. }
  152. const fixedColumns = this.store.states.fixedColumns.value;
  153. if (fixedColumns.length > 0) {
  154. let fixedWidth = 0;
  155. fixedColumns.forEach((column) => {
  156. fixedWidth += Number(column.realWidth || column.width);
  157. });
  158. this.fixedWidth.value = fixedWidth;
  159. }
  160. const rightFixedColumns = this.store.states.rightFixedColumns.value;
  161. if (rightFixedColumns.length > 0) {
  162. let rightFixedWidth = 0;
  163. rightFixedColumns.forEach((column) => {
  164. rightFixedWidth += Number(column.realWidth || column.width);
  165. });
  166. this.rightFixedWidth.value = rightFixedWidth;
  167. }
  168. this.notifyObservers("columns");
  169. }
  170. addObserver(observer) {
  171. this.observers.push(observer);
  172. }
  173. removeObserver(observer) {
  174. const index = this.observers.indexOf(observer);
  175. if (index !== -1) {
  176. this.observers.splice(index, 1);
  177. }
  178. }
  179. notifyObservers(event) {
  180. const observers = this.observers;
  181. observers.forEach((observer) => {
  182. var _a, _b;
  183. switch (event) {
  184. case "columns":
  185. (_a = observer.state) == null ? void 0 : _a.onColumnsChange(this);
  186. break;
  187. case "scrollable":
  188. (_b = observer.state) == null ? void 0 : _b.onScrollableChange(this);
  189. break;
  190. default:
  191. throw new Error(`Table Layout don't have event ${event}.`);
  192. }
  193. });
  194. }
  195. }
  196. export { TableLayout as default };
  197. //# sourceMappingURL=table-layout.mjs.map