d602c57a014e50d55d46ffbffee892620e35204004b1fbd6225086ca6adcb2518b4476aa27f2ed063b76ab5414b476e11cd4ced3521e1e22bfab296c8ad0bb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var core = require('@vueuse/core');
  5. var scrollbar = require('../components/scrollbar.js');
  6. var useGridWheel = require('../hooks/use-grid-wheel.js');
  7. var useCache = require('../hooks/use-cache.js');
  8. var props = require('../props.js');
  9. var utils = require('../utils.js');
  10. var defaults = require('../defaults.js');
  11. var index = require('../../../../hooks/use-namespace/index.js');
  12. var types = require('../../../../utils/types.js');
  13. var scroll = require('../../../../utils/dom/scroll.js');
  14. var shared = require('@vue/shared');
  15. const createGrid = ({
  16. name,
  17. clearCache,
  18. getColumnPosition,
  19. getColumnStartIndexForOffset,
  20. getColumnStopIndexForStartIndex,
  21. getEstimatedTotalHeight,
  22. getEstimatedTotalWidth,
  23. getColumnOffset,
  24. getRowOffset,
  25. getRowPosition,
  26. getRowStartIndexForOffset,
  27. getRowStopIndexForStartIndex,
  28. initCache,
  29. injectToInstance,
  30. validateProps
  31. }) => {
  32. return vue.defineComponent({
  33. name: name != null ? name : "ElVirtualList",
  34. props: props.virtualizedGridProps,
  35. emits: [defaults.ITEM_RENDER_EVT, defaults.SCROLL_EVT],
  36. setup(props, { emit, expose, slots }) {
  37. const ns = index.useNamespace("vl");
  38. validateProps(props);
  39. const instance = vue.getCurrentInstance();
  40. const cache = vue.ref(initCache(props, instance));
  41. injectToInstance == null ? void 0 : injectToInstance(instance, cache);
  42. const windowRef = vue.ref();
  43. const hScrollbar = vue.ref();
  44. const vScrollbar = vue.ref();
  45. const innerRef = vue.ref(null);
  46. const states = vue.ref({
  47. isScrolling: false,
  48. scrollLeft: types.isNumber(props.initScrollLeft) ? props.initScrollLeft : 0,
  49. scrollTop: types.isNumber(props.initScrollTop) ? props.initScrollTop : 0,
  50. updateRequested: false,
  51. xAxisScrollDir: defaults.FORWARD,
  52. yAxisScrollDir: defaults.FORWARD
  53. });
  54. const getItemStyleCache = useCache.useCache();
  55. const parsedHeight = vue.computed(() => Number.parseInt(`${props.height}`, 10));
  56. const parsedWidth = vue.computed(() => Number.parseInt(`${props.width}`, 10));
  57. const columnsToRender = vue.computed(() => {
  58. const { totalColumn, totalRow, columnCache } = props;
  59. const { isScrolling, xAxisScrollDir, scrollLeft } = vue.unref(states);
  60. if (totalColumn === 0 || totalRow === 0) {
  61. return [0, 0, 0, 0];
  62. }
  63. const startIndex = getColumnStartIndexForOffset(props, scrollLeft, vue.unref(cache));
  64. const stopIndex = getColumnStopIndexForStartIndex(props, startIndex, scrollLeft, vue.unref(cache));
  65. const cacheBackward = !isScrolling || xAxisScrollDir === defaults.BACKWARD ? Math.max(1, columnCache) : 1;
  66. const cacheForward = !isScrolling || xAxisScrollDir === defaults.FORWARD ? Math.max(1, columnCache) : 1;
  67. return [
  68. Math.max(0, startIndex - cacheBackward),
  69. Math.max(0, Math.min(totalColumn - 1, stopIndex + cacheForward)),
  70. startIndex,
  71. stopIndex
  72. ];
  73. });
  74. const rowsToRender = vue.computed(() => {
  75. const { totalColumn, totalRow, rowCache } = props;
  76. const { isScrolling, yAxisScrollDir, scrollTop } = vue.unref(states);
  77. if (totalColumn === 0 || totalRow === 0) {
  78. return [0, 0, 0, 0];
  79. }
  80. const startIndex = getRowStartIndexForOffset(props, scrollTop, vue.unref(cache));
  81. const stopIndex = getRowStopIndexForStartIndex(props, startIndex, scrollTop, vue.unref(cache));
  82. const cacheBackward = !isScrolling || yAxisScrollDir === defaults.BACKWARD ? Math.max(1, rowCache) : 1;
  83. const cacheForward = !isScrolling || yAxisScrollDir === defaults.FORWARD ? Math.max(1, rowCache) : 1;
  84. return [
  85. Math.max(0, startIndex - cacheBackward),
  86. Math.max(0, Math.min(totalRow - 1, stopIndex + cacheForward)),
  87. startIndex,
  88. stopIndex
  89. ];
  90. });
  91. const estimatedTotalHeight = vue.computed(() => getEstimatedTotalHeight(props, vue.unref(cache)));
  92. const estimatedTotalWidth = vue.computed(() => getEstimatedTotalWidth(props, vue.unref(cache)));
  93. const windowStyle = vue.computed(() => {
  94. var _a;
  95. return [
  96. {
  97. position: "relative",
  98. overflow: "hidden",
  99. WebkitOverflowScrolling: "touch",
  100. willChange: "transform"
  101. },
  102. {
  103. direction: props.direction,
  104. height: types.isNumber(props.height) ? `${props.height}px` : props.height,
  105. width: types.isNumber(props.width) ? `${props.width}px` : props.width
  106. },
  107. (_a = props.style) != null ? _a : {}
  108. ];
  109. });
  110. const innerStyle = vue.computed(() => {
  111. const width = `${vue.unref(estimatedTotalWidth)}px`;
  112. const height = `${vue.unref(estimatedTotalHeight)}px`;
  113. return {
  114. height,
  115. pointerEvents: vue.unref(states).isScrolling ? "none" : void 0,
  116. width
  117. };
  118. });
  119. const emitEvents = () => {
  120. const { totalColumn, totalRow } = props;
  121. if (totalColumn > 0 && totalRow > 0) {
  122. const [
  123. columnCacheStart,
  124. columnCacheEnd,
  125. columnVisibleStart,
  126. columnVisibleEnd
  127. ] = vue.unref(columnsToRender);
  128. const [rowCacheStart, rowCacheEnd, rowVisibleStart, rowVisibleEnd] = vue.unref(rowsToRender);
  129. emit(defaults.ITEM_RENDER_EVT, {
  130. columnCacheStart,
  131. columnCacheEnd,
  132. rowCacheStart,
  133. rowCacheEnd,
  134. columnVisibleStart,
  135. columnVisibleEnd,
  136. rowVisibleStart,
  137. rowVisibleEnd
  138. });
  139. }
  140. const {
  141. scrollLeft,
  142. scrollTop,
  143. updateRequested,
  144. xAxisScrollDir,
  145. yAxisScrollDir
  146. } = vue.unref(states);
  147. emit(defaults.SCROLL_EVT, {
  148. xAxisScrollDir,
  149. scrollLeft,
  150. yAxisScrollDir,
  151. scrollTop,
  152. updateRequested
  153. });
  154. };
  155. const onScroll = (e) => {
  156. const {
  157. clientHeight,
  158. clientWidth,
  159. scrollHeight,
  160. scrollLeft,
  161. scrollTop,
  162. scrollWidth
  163. } = e.currentTarget;
  164. const _states = vue.unref(states);
  165. if (_states.scrollTop === scrollTop && _states.scrollLeft === scrollLeft) {
  166. return;
  167. }
  168. let _scrollLeft = scrollLeft;
  169. if (utils.isRTL(props.direction)) {
  170. switch (utils.getRTLOffsetType()) {
  171. case defaults.RTL_OFFSET_NAG:
  172. _scrollLeft = -scrollLeft;
  173. break;
  174. case defaults.RTL_OFFSET_POS_DESC:
  175. _scrollLeft = scrollWidth - clientWidth - scrollLeft;
  176. break;
  177. }
  178. }
  179. states.value = {
  180. ..._states,
  181. isScrolling: true,
  182. scrollLeft: _scrollLeft,
  183. scrollTop: Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight)),
  184. updateRequested: true,
  185. xAxisScrollDir: utils.getScrollDir(_states.scrollLeft, _scrollLeft),
  186. yAxisScrollDir: utils.getScrollDir(_states.scrollTop, scrollTop)
  187. };
  188. vue.nextTick(() => resetIsScrolling());
  189. onUpdated();
  190. emitEvents();
  191. };
  192. const onVerticalScroll = (distance, totalSteps) => {
  193. const height = vue.unref(parsedHeight);
  194. const offset = (estimatedTotalHeight.value - height) / totalSteps * distance;
  195. scrollTo({
  196. scrollTop: Math.min(estimatedTotalHeight.value - height, offset)
  197. });
  198. };
  199. const onHorizontalScroll = (distance, totalSteps) => {
  200. const width = vue.unref(parsedWidth);
  201. const offset = (estimatedTotalWidth.value - width) / totalSteps * distance;
  202. scrollTo({
  203. scrollLeft: Math.min(estimatedTotalWidth.value - width, offset)
  204. });
  205. };
  206. const { onWheel } = useGridWheel.useGridWheel({
  207. atXStartEdge: vue.computed(() => states.value.scrollLeft <= 0),
  208. atXEndEdge: vue.computed(() => states.value.scrollLeft >= estimatedTotalWidth.value - vue.unref(parsedWidth)),
  209. atYStartEdge: vue.computed(() => states.value.scrollTop <= 0),
  210. atYEndEdge: vue.computed(() => states.value.scrollTop >= estimatedTotalHeight.value - vue.unref(parsedHeight))
  211. }, (x, y) => {
  212. var _a, _b, _c, _d;
  213. (_b = (_a = hScrollbar.value) == null ? void 0 : _a.onMouseUp) == null ? void 0 : _b.call(_a);
  214. (_d = (_c = vScrollbar.value) == null ? void 0 : _c.onMouseUp) == null ? void 0 : _d.call(_c);
  215. const width = vue.unref(parsedWidth);
  216. const height = vue.unref(parsedHeight);
  217. scrollTo({
  218. scrollLeft: Math.min(states.value.scrollLeft + x, estimatedTotalWidth.value - width),
  219. scrollTop: Math.min(states.value.scrollTop + y, estimatedTotalHeight.value - height)
  220. });
  221. });
  222. core.useEventListener(windowRef, "wheel", onWheel, {
  223. passive: false
  224. });
  225. const scrollTo = ({
  226. scrollLeft = states.value.scrollLeft,
  227. scrollTop = states.value.scrollTop
  228. }) => {
  229. scrollLeft = Math.max(scrollLeft, 0);
  230. scrollTop = Math.max(scrollTop, 0);
  231. const _states = vue.unref(states);
  232. if (scrollTop === _states.scrollTop && scrollLeft === _states.scrollLeft) {
  233. return;
  234. }
  235. states.value = {
  236. ..._states,
  237. xAxisScrollDir: utils.getScrollDir(_states.scrollLeft, scrollLeft),
  238. yAxisScrollDir: utils.getScrollDir(_states.scrollTop, scrollTop),
  239. scrollLeft,
  240. scrollTop,
  241. updateRequested: true
  242. };
  243. vue.nextTick(() => resetIsScrolling());
  244. onUpdated();
  245. emitEvents();
  246. };
  247. const scrollToItem = (rowIndex = 0, columnIdx = 0, alignment = defaults.AUTO_ALIGNMENT) => {
  248. const _states = vue.unref(states);
  249. columnIdx = Math.max(0, Math.min(columnIdx, props.totalColumn - 1));
  250. rowIndex = Math.max(0, Math.min(rowIndex, props.totalRow - 1));
  251. const scrollBarWidth = scroll.getScrollBarWidth(ns.namespace.value);
  252. const _cache = vue.unref(cache);
  253. const estimatedHeight = getEstimatedTotalHeight(props, _cache);
  254. const estimatedWidth = getEstimatedTotalWidth(props, _cache);
  255. scrollTo({
  256. scrollLeft: getColumnOffset(props, columnIdx, alignment, _states.scrollLeft, _cache, estimatedWidth > props.width ? scrollBarWidth : 0),
  257. scrollTop: getRowOffset(props, rowIndex, alignment, _states.scrollTop, _cache, estimatedHeight > props.height ? scrollBarWidth : 0)
  258. });
  259. };
  260. const getItemStyle = (rowIndex, columnIndex) => {
  261. const { columnWidth, direction, rowHeight } = props;
  262. const itemStyleCache = getItemStyleCache.value(clearCache && columnWidth, clearCache && rowHeight, clearCache && direction);
  263. const key = `${rowIndex},${columnIndex}`;
  264. if (shared.hasOwn(itemStyleCache, key)) {
  265. return itemStyleCache[key];
  266. } else {
  267. const [, left] = getColumnPosition(props, columnIndex, vue.unref(cache));
  268. const _cache = vue.unref(cache);
  269. const rtl = utils.isRTL(direction);
  270. const [height, top] = getRowPosition(props, rowIndex, _cache);
  271. const [width] = getColumnPosition(props, columnIndex, _cache);
  272. itemStyleCache[key] = {
  273. position: "absolute",
  274. left: rtl ? void 0 : `${left}px`,
  275. right: rtl ? `${left}px` : void 0,
  276. top: `${top}px`,
  277. height: `${height}px`,
  278. width: `${width}px`
  279. };
  280. return itemStyleCache[key];
  281. }
  282. };
  283. const resetIsScrolling = () => {
  284. states.value.isScrolling = false;
  285. vue.nextTick(() => {
  286. getItemStyleCache.value(-1, null, null);
  287. });
  288. };
  289. vue.onMounted(() => {
  290. if (!core.isClient)
  291. return;
  292. const { initScrollLeft, initScrollTop } = props;
  293. const windowElement = vue.unref(windowRef);
  294. if (windowElement) {
  295. if (types.isNumber(initScrollLeft)) {
  296. windowElement.scrollLeft = initScrollLeft;
  297. }
  298. if (types.isNumber(initScrollTop)) {
  299. windowElement.scrollTop = initScrollTop;
  300. }
  301. }
  302. emitEvents();
  303. });
  304. const onUpdated = () => {
  305. const { direction } = props;
  306. const { scrollLeft, scrollTop, updateRequested } = vue.unref(states);
  307. const windowElement = vue.unref(windowRef);
  308. if (updateRequested && windowElement) {
  309. if (direction === defaults.RTL) {
  310. switch (utils.getRTLOffsetType()) {
  311. case defaults.RTL_OFFSET_NAG: {
  312. windowElement.scrollLeft = -scrollLeft;
  313. break;
  314. }
  315. case defaults.RTL_OFFSET_POS_ASC: {
  316. windowElement.scrollLeft = scrollLeft;
  317. break;
  318. }
  319. default: {
  320. const { clientWidth, scrollWidth } = windowElement;
  321. windowElement.scrollLeft = scrollWidth - clientWidth - scrollLeft;
  322. break;
  323. }
  324. }
  325. } else {
  326. windowElement.scrollLeft = Math.max(0, scrollLeft);
  327. }
  328. windowElement.scrollTop = Math.max(0, scrollTop);
  329. }
  330. };
  331. const { resetAfterColumnIndex, resetAfterRowIndex, resetAfter } = instance.proxy;
  332. expose({
  333. windowRef,
  334. innerRef,
  335. getItemStyleCache,
  336. scrollTo,
  337. scrollToItem,
  338. states,
  339. resetAfterColumnIndex,
  340. resetAfterRowIndex,
  341. resetAfter
  342. });
  343. const renderScrollbars = () => {
  344. const {
  345. scrollbarAlwaysOn,
  346. scrollbarStartGap,
  347. scrollbarEndGap,
  348. totalColumn,
  349. totalRow
  350. } = props;
  351. const width = vue.unref(parsedWidth);
  352. const height = vue.unref(parsedHeight);
  353. const estimatedWidth = vue.unref(estimatedTotalWidth);
  354. const estimatedHeight = vue.unref(estimatedTotalHeight);
  355. const { scrollLeft, scrollTop } = vue.unref(states);
  356. const horizontalScrollbar = vue.h(scrollbar["default"], {
  357. ref: hScrollbar,
  358. alwaysOn: scrollbarAlwaysOn,
  359. startGap: scrollbarStartGap,
  360. endGap: scrollbarEndGap,
  361. class: ns.e("horizontal"),
  362. clientSize: width,
  363. layout: "horizontal",
  364. onScroll: onHorizontalScroll,
  365. ratio: width * 100 / estimatedWidth,
  366. scrollFrom: scrollLeft / (estimatedWidth - width),
  367. total: totalRow,
  368. visible: true
  369. });
  370. const verticalScrollbar = vue.h(scrollbar["default"], {
  371. ref: vScrollbar,
  372. alwaysOn: scrollbarAlwaysOn,
  373. startGap: scrollbarStartGap,
  374. endGap: scrollbarEndGap,
  375. class: ns.e("vertical"),
  376. clientSize: height,
  377. layout: "vertical",
  378. onScroll: onVerticalScroll,
  379. ratio: height * 100 / estimatedHeight,
  380. scrollFrom: scrollTop / (estimatedHeight - height),
  381. total: totalColumn,
  382. visible: true
  383. });
  384. return {
  385. horizontalScrollbar,
  386. verticalScrollbar
  387. };
  388. };
  389. const renderItems = () => {
  390. var _a;
  391. const [columnStart, columnEnd] = vue.unref(columnsToRender);
  392. const [rowStart, rowEnd] = vue.unref(rowsToRender);
  393. const { data, totalColumn, totalRow, useIsScrolling, itemKey } = props;
  394. const children = [];
  395. if (totalRow > 0 && totalColumn > 0) {
  396. for (let row = rowStart; row <= rowEnd; row++) {
  397. for (let column = columnStart; column <= columnEnd; column++) {
  398. const key = itemKey({ columnIndex: column, data, rowIndex: row });
  399. children.push(vue.h(vue.Fragment, { key }, (_a = slots.default) == null ? void 0 : _a.call(slots, {
  400. columnIndex: column,
  401. data,
  402. isScrolling: useIsScrolling ? vue.unref(states).isScrolling : void 0,
  403. style: getItemStyle(row, column),
  404. rowIndex: row
  405. })));
  406. }
  407. }
  408. }
  409. return children;
  410. };
  411. const renderInner = () => {
  412. const Inner = vue.resolveDynamicComponent(props.innerElement);
  413. const children = renderItems();
  414. return [
  415. vue.h(Inner, {
  416. style: vue.unref(innerStyle),
  417. ref: innerRef
  418. }, !shared.isString(Inner) ? {
  419. default: () => children
  420. } : children)
  421. ];
  422. };
  423. const renderWindow = () => {
  424. const Container = vue.resolveDynamicComponent(props.containerElement);
  425. const { horizontalScrollbar, verticalScrollbar } = renderScrollbars();
  426. const Inner = renderInner();
  427. return vue.h("div", {
  428. key: 0,
  429. class: ns.e("wrapper"),
  430. role: props.role
  431. }, [
  432. vue.h(Container, {
  433. class: props.className,
  434. style: vue.unref(windowStyle),
  435. onScroll,
  436. ref: windowRef
  437. }, !shared.isString(Container) ? { default: () => Inner } : Inner),
  438. horizontalScrollbar,
  439. verticalScrollbar
  440. ]);
  441. };
  442. return renderWindow;
  443. }
  444. });
  445. };
  446. exports["default"] = createGrid;
  447. //# sourceMappingURL=build-grid.js.map