Pagination.mjs 4.5 KB

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