Pagination.mjs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { computed, watchEffect, defineComponent, createVNode as _createVNode } from "vue";
  2. import { clamp, truthProp, makeStringProp, makeNumberProp, makeNumericProp, createNamespace, BORDER_SURROUND } from "../utils/index.mjs";
  3. const [name, bem, t] = createNamespace("pagination");
  4. const makePage = (number, text, active) => ({
  5. number,
  6. text,
  7. active
  8. });
  9. const paginationProps = {
  10. mode: makeStringProp("multi"),
  11. prevText: String,
  12. nextText: String,
  13. pageCount: makeNumericProp(0),
  14. modelValue: makeNumberProp(0),
  15. totalItems: makeNumericProp(0),
  16. showPageSize: makeNumericProp(5),
  17. itemsPerPage: makeNumericProp(10),
  18. forceEllipses: Boolean,
  19. showPrevButton: truthProp,
  20. showNextButton: truthProp
  21. };
  22. var stdin_default = defineComponent({
  23. name,
  24. props: paginationProps,
  25. emits: ["change", "update:modelValue"],
  26. setup(props, {
  27. emit,
  28. slots
  29. }) {
  30. const count = computed(() => {
  31. const {
  32. pageCount,
  33. totalItems,
  34. itemsPerPage
  35. } = props;
  36. const count2 = +pageCount || Math.ceil(+totalItems / +itemsPerPage);
  37. return Math.max(1, count2);
  38. });
  39. const pages = computed(() => {
  40. const items = [];
  41. const pageCount = count.value;
  42. const showPageSize = +props.showPageSize;
  43. const {
  44. modelValue,
  45. forceEllipses
  46. } = props;
  47. let startPage = 1;
  48. let endPage = pageCount;
  49. const isMaxSized = showPageSize < pageCount;
  50. if (isMaxSized) {
  51. startPage = Math.max(modelValue - Math.floor(showPageSize / 2), 1);
  52. endPage = startPage + showPageSize - 1;
  53. if (endPage > pageCount) {
  54. endPage = pageCount;
  55. startPage = endPage - showPageSize + 1;
  56. }
  57. }
  58. for (let number = startPage; number <= endPage; number++) {
  59. const page = makePage(number, number, number === modelValue);
  60. items.push(page);
  61. }
  62. if (isMaxSized && showPageSize > 0 && forceEllipses) {
  63. if (startPage > 1) {
  64. const prevPages = makePage(startPage - 1, "...");
  65. items.unshift(prevPages);
  66. }
  67. if (endPage < pageCount) {
  68. const nextPages = makePage(endPage + 1, "...");
  69. items.push(nextPages);
  70. }
  71. }
  72. return items;
  73. });
  74. const updateModelValue = (value, emitChange) => {
  75. value = clamp(value, 1, count.value);
  76. if (props.modelValue !== value) {
  77. emit("update:modelValue", value);
  78. if (emitChange) {
  79. emit("change", value);
  80. }
  81. }
  82. };
  83. watchEffect(() => updateModelValue(props.modelValue));
  84. const renderDesc = () => _createVNode("li", {
  85. "class": bem("page-desc")
  86. }, [slots.pageDesc ? slots.pageDesc() : `${props.modelValue}/${count.value}`]);
  87. const renderPrevButton = () => {
  88. const {
  89. mode,
  90. modelValue,
  91. showPrevButton
  92. } = props;
  93. if (!showPrevButton) {
  94. return;
  95. }
  96. const slot = slots["prev-text"];
  97. const disabled = modelValue === 1;
  98. return _createVNode("li", {
  99. "class": [bem("item", {
  100. disabled,
  101. border: mode === "simple",
  102. prev: true
  103. }), BORDER_SURROUND]
  104. }, [_createVNode("button", {
  105. "type": "button",
  106. "disabled": disabled,
  107. "onClick": () => updateModelValue(modelValue - 1, true)
  108. }, [slot ? slot() : props.prevText || t("prev")])]);
  109. };
  110. const renderNextButton = () => {
  111. const {
  112. mode,
  113. modelValue,
  114. showNextButton
  115. } = props;
  116. if (!showNextButton) {
  117. return;
  118. }
  119. const slot = slots["next-text"];
  120. const disabled = modelValue === count.value;
  121. return _createVNode("li", {
  122. "class": [bem("item", {
  123. disabled,
  124. border: mode === "simple",
  125. next: true
  126. }), BORDER_SURROUND]
  127. }, [_createVNode("button", {
  128. "type": "button",
  129. "disabled": disabled,
  130. "onClick": () => updateModelValue(modelValue + 1, true)
  131. }, [slot ? slot() : props.nextText || t("next")])]);
  132. };
  133. const renderPages = () => pages.value.map((page) => _createVNode("li", {
  134. "class": [bem("item", {
  135. active: page.active,
  136. page: true
  137. }), BORDER_SURROUND]
  138. }, [_createVNode("button", {
  139. "type": "button",
  140. "aria-current": page.active || void 0,
  141. "onClick": () => updateModelValue(page.number, true)
  142. }, [slots.page ? slots.page(page) : page.text])]));
  143. return () => _createVNode("nav", {
  144. "role": "navigation",
  145. "class": bem()
  146. }, [_createVNode("ul", {
  147. "class": bem("items")
  148. }, [renderPrevButton(), props.mode === "simple" ? renderDesc() : renderPages(), renderNextButton()])]);
  149. }
  150. });
  151. export {
  152. stdin_default as default,
  153. paginationProps
  154. };