@puzzle-ui/ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +70 -70
  2. package/dist/components/actions/button/button.css +5 -2
  3. package/dist/components/actions/button-group/button-group.css +16 -17
  4. package/dist/components/data-display/badge/badge.css +15 -2
  5. package/dist/components/data-display/badge/index.cjs +13 -2
  6. package/dist/components/data-display/badge/index.cjs.map +1 -1
  7. package/dist/components/data-display/badge/index.d.cts +7 -2
  8. package/dist/components/data-display/badge/index.d.ts +7 -2
  9. package/dist/components/data-display/badge/index.js +13 -2
  10. package/dist/components/data-display/badge/index.js.map +1 -1
  11. package/dist/components/data-display/empty-state/empty-state.css +128 -0
  12. package/dist/components/data-display/empty-state/empty-state.utils.cjs +6 -0
  13. package/dist/components/data-display/empty-state/empty-state.utils.cjs.map +1 -0
  14. package/dist/components/data-display/empty-state/empty-state.utils.js +6 -0
  15. package/dist/components/data-display/empty-state/empty-state.utils.js.map +1 -0
  16. package/dist/components/data-display/empty-state/index.cjs +49 -0
  17. package/dist/components/data-display/empty-state/index.cjs.map +1 -0
  18. package/dist/components/data-display/empty-state/index.d.cts +19 -0
  19. package/dist/components/data-display/empty-state/index.d.ts +19 -0
  20. package/dist/components/data-display/empty-state/index.js +44 -0
  21. package/dist/components/data-display/empty-state/index.js.map +1 -0
  22. package/dist/components/data-display/rating/index.cjs +84 -0
  23. package/dist/components/data-display/rating/index.cjs.map +1 -0
  24. package/dist/components/data-display/rating/index.d.cts +3 -0
  25. package/dist/components/data-display/rating/index.d.ts +3 -0
  26. package/dist/components/data-display/rating/index.js +84 -0
  27. package/dist/components/data-display/rating/index.js.map +1 -0
  28. package/dist/components/data-display/rating/rating.css +72 -0
  29. package/dist/components/data-display/rating/rating.types.d.cts +15 -0
  30. package/dist/components/data-display/rating/rating.types.d.ts +15 -0
  31. package/dist/components/data-display/rating/rating.utils.cjs +27 -0
  32. package/dist/components/data-display/rating/rating.utils.cjs.map +1 -0
  33. package/dist/components/data-display/rating/rating.utils.js +25 -0
  34. package/dist/components/data-display/rating/rating.utils.js.map +1 -0
  35. package/dist/components/editors/text-editor/editor.cjs.map +1 -1
  36. package/dist/components/editors/text-editor/editor.js.map +1 -1
  37. package/dist/components/editors/text-editor/text-document.cjs.map +1 -1
  38. package/dist/components/editors/text-editor/text-document.js.map +1 -1
  39. package/dist/components/editors/text-editor/text-parser.cjs.map +1 -1
  40. package/dist/components/editors/text-editor/text-parser.js.map +1 -1
  41. package/dist/components/editors/text-editor/text-renderer.cjs.map +1 -1
  42. package/dist/components/editors/text-editor/text-renderer.js.map +1 -1
  43. package/dist/components/forms/autocomplete/index.cjs.map +1 -1
  44. package/dist/components/forms/autocomplete/index.js.map +1 -1
  45. package/dist/components/forms/checkbox/checkbox.css +2 -10
  46. package/dist/components/forms/color-picker/color-picker.css +351 -0
  47. package/dist/components/forms/color-picker/color-picker.types.d.cts +25 -0
  48. package/dist/components/forms/color-picker/color-picker.types.d.ts +25 -0
  49. package/dist/components/forms/color-picker/color-picker.utils.cjs +116 -0
  50. package/dist/components/forms/color-picker/color-picker.utils.cjs.map +1 -0
  51. package/dist/components/forms/color-picker/color-picker.utils.js +109 -0
  52. package/dist/components/forms/color-picker/color-picker.utils.js.map +1 -0
  53. package/dist/components/forms/color-picker/index.cjs +340 -0
  54. package/dist/components/forms/color-picker/index.cjs.map +1 -0
  55. package/dist/components/forms/color-picker/index.d.cts +3 -0
  56. package/dist/components/forms/color-picker/index.d.ts +3 -0
  57. package/dist/components/forms/color-picker/index.js +340 -0
  58. package/dist/components/forms/color-picker/index.js.map +1 -0
  59. package/dist/components/forms/file-upload/file-upload.utils.cjs.map +1 -1
  60. package/dist/components/forms/file-upload/file-upload.utils.js.map +1 -1
  61. package/dist/components/forms/input/number-input.js +5 -5
  62. package/dist/components/forms/input/number-input.js.map +1 -1
  63. package/dist/components/forms/input-group/index.d.cts +3 -0
  64. package/dist/components/forms/input-group/index.d.ts +3 -0
  65. package/dist/components/forms/input-group/input-group.cjs +18 -0
  66. package/dist/components/forms/input-group/input-group.cjs.map +1 -0
  67. package/dist/components/forms/input-group/input-group.css +62 -0
  68. package/dist/components/forms/input-group/input-group.d.cts +7 -0
  69. package/dist/components/forms/input-group/input-group.d.ts +7 -0
  70. package/dist/components/forms/input-group/input-group.js +18 -0
  71. package/dist/components/forms/input-group/input-group.js.map +1 -0
  72. package/dist/components/forms/input-group/input-group.types.d.cts +7 -0
  73. package/dist/components/forms/input-group/input-group.types.d.ts +7 -0
  74. package/dist/components/forms/input-group/input-group.utils.cjs +5 -0
  75. package/dist/components/forms/input-group/input-group.utils.cjs.map +1 -0
  76. package/dist/components/forms/input-group/input-group.utils.js +5 -0
  77. package/dist/components/forms/input-group/input-group.utils.js.map +1 -0
  78. package/dist/components/forms/radio-group/index.d.cts +2 -1
  79. package/dist/components/forms/radio-group/index.d.ts +2 -1
  80. package/dist/components/forms/select/index.cjs.map +1 -1
  81. package/dist/components/forms/select/index.js.map +1 -1
  82. package/dist/components/forms/slider/index.cjs +1 -1
  83. package/dist/components/forms/slider/index.cjs.map +1 -1
  84. package/dist/components/forms/slider/index.js +1 -1
  85. package/dist/components/forms/slider/index.js.map +1 -1
  86. package/dist/components/forms/stepper/index.d.cts +4 -2
  87. package/dist/components/forms/stepper/index.d.ts +4 -2
  88. package/dist/components/forms/time-picker/index.cjs +108 -0
  89. package/dist/components/forms/time-picker/index.cjs.map +1 -0
  90. package/dist/components/forms/time-picker/index.d.cts +3 -0
  91. package/dist/components/forms/time-picker/index.d.ts +3 -0
  92. package/dist/components/forms/time-picker/index.js +108 -0
  93. package/dist/components/forms/time-picker/index.js.map +1 -0
  94. package/dist/components/forms/time-picker/time-picker.css +166 -0
  95. package/dist/components/forms/time-picker/time-picker.types.d.cts +34 -0
  96. package/dist/components/forms/time-picker/time-picker.types.d.ts +34 -0
  97. package/dist/components/forms/time-picker/time-picker.utils.cjs +25 -0
  98. package/dist/components/forms/time-picker/time-picker.utils.cjs.map +1 -0
  99. package/dist/components/forms/time-picker/time-picker.utils.js +24 -0
  100. package/dist/components/forms/time-picker/time-picker.utils.js.map +1 -0
  101. package/dist/components/forms/token-input/index.cjs +189 -0
  102. package/dist/components/forms/token-input/index.cjs.map +1 -0
  103. package/dist/components/forms/token-input/index.d.cts +3 -0
  104. package/dist/components/forms/token-input/index.d.ts +3 -0
  105. package/dist/components/forms/token-input/index.js +189 -0
  106. package/dist/components/forms/token-input/index.js.map +1 -0
  107. package/dist/components/forms/token-input/token-input.css +145 -0
  108. package/dist/components/forms/token-input/token-input.types.d.cts +48 -0
  109. package/dist/components/forms/token-input/token-input.types.d.ts +48 -0
  110. package/dist/components/forms/token-input/token-input.utils.cjs +30 -0
  111. package/dist/components/forms/token-input/token-input.utils.cjs.map +1 -0
  112. package/dist/components/forms/token-input/token-input.utils.js +24 -0
  113. package/dist/components/forms/token-input/token-input.utils.js.map +1 -0
  114. package/dist/components/layout/aspect-ratio/aspect-ratio.css +14 -0
  115. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs +11 -0
  116. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs.map +1 -0
  117. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js +11 -0
  118. package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js.map +1 -0
  119. package/dist/components/layout/aspect-ratio/index.cjs +16 -0
  120. package/dist/components/layout/aspect-ratio/index.cjs.map +1 -0
  121. package/dist/components/layout/aspect-ratio/index.d.cts +11 -0
  122. package/dist/components/layout/aspect-ratio/index.d.ts +11 -0
  123. package/dist/components/layout/aspect-ratio/index.js +16 -0
  124. package/dist/components/layout/aspect-ratio/index.js.map +1 -0
  125. package/dist/components/layout/container/container.css +1 -0
  126. package/dist/components/layout/page-layout/page-layout.css +1 -0
  127. package/dist/components/layout/resizable-panels/index.cjs +1 -1
  128. package/dist/components/layout/resizable-panels/index.cjs.map +1 -1
  129. package/dist/components/layout/resizable-panels/index.js +1 -1
  130. package/dist/components/layout/resizable-panels/index.js.map +1 -1
  131. package/dist/components/layout/resizable-panels/resizable-panels.utils.cjs.map +1 -1
  132. package/dist/components/layout/resizable-panels/resizable-panels.utils.js.map +1 -1
  133. package/dist/components/layout/scroll-area/index.cjs +27 -0
  134. package/dist/components/layout/scroll-area/index.cjs.map +1 -0
  135. package/dist/components/layout/scroll-area/index.d.cts +15 -0
  136. package/dist/components/layout/scroll-area/index.d.ts +15 -0
  137. package/dist/components/layout/scroll-area/index.js +27 -0
  138. package/dist/components/layout/scroll-area/index.js.map +1 -0
  139. package/dist/components/layout/scroll-area/scroll-area.css +25 -0
  140. package/dist/components/layout/scroll-area/scroll-area.utils.cjs +8 -0
  141. package/dist/components/layout/scroll-area/scroll-area.utils.cjs.map +1 -0
  142. package/dist/components/layout/scroll-area/scroll-area.utils.d.cts +2 -0
  143. package/dist/components/layout/scroll-area/scroll-area.utils.d.ts +2 -0
  144. package/dist/components/layout/scroll-area/scroll-area.utils.js +8 -0
  145. package/dist/components/layout/scroll-area/scroll-area.utils.js.map +1 -0
  146. package/dist/components/layout/section/index.cjs +10 -4
  147. package/dist/components/layout/section/index.cjs.map +1 -1
  148. package/dist/components/layout/section/index.d.cts +1 -1
  149. package/dist/components/layout/section/index.d.ts +1 -1
  150. package/dist/components/layout/section/index.js +11 -5
  151. package/dist/components/layout/section/index.js.map +1 -1
  152. package/dist/components/layout/section/section.css +9 -3
  153. package/dist/components/layout/section/types.d.cts +5 -5
  154. package/dist/components/layout/section/types.d.ts +5 -5
  155. package/dist/components/layout/separator/index.cjs +18 -0
  156. package/dist/components/layout/separator/index.cjs.map +1 -0
  157. package/dist/components/layout/separator/index.d.cts +17 -0
  158. package/dist/components/layout/separator/index.d.ts +17 -0
  159. package/dist/components/layout/separator/index.js +18 -0
  160. package/dist/components/layout/separator/index.js.map +1 -0
  161. package/dist/components/layout/separator/separator.css +15 -0
  162. package/dist/components/layout/separator/separator.utils.cjs +11 -0
  163. package/dist/components/layout/separator/separator.utils.cjs.map +1 -0
  164. package/dist/components/layout/separator/separator.utils.d.cts +2 -0
  165. package/dist/components/layout/separator/separator.utils.d.ts +2 -0
  166. package/dist/components/layout/separator/separator.utils.js +11 -0
  167. package/dist/components/layout/separator/separator.utils.js.map +1 -0
  168. package/dist/components/layout/stack/index.cjs +18 -2
  169. package/dist/components/layout/stack/index.cjs.map +1 -1
  170. package/dist/components/layout/stack/index.d.cts +8 -6
  171. package/dist/components/layout/stack/index.d.ts +8 -6
  172. package/dist/components/layout/stack/index.js +18 -2
  173. package/dist/components/layout/stack/index.js.map +1 -1
  174. package/dist/components/layout/stack/stack.css +118 -138
  175. package/dist/components/navigation/accordion/index.cjs.map +1 -1
  176. package/dist/components/navigation/accordion/index.js.map +1 -1
  177. package/dist/components/navigation/carousel/index.cjs +5 -2
  178. package/dist/components/navigation/carousel/index.cjs.map +1 -1
  179. package/dist/components/navigation/carousel/index.js +5 -2
  180. package/dist/components/navigation/carousel/index.js.map +1 -1
  181. package/dist/components/navigation/pagination/index.cjs +146 -0
  182. package/dist/components/navigation/pagination/index.cjs.map +1 -0
  183. package/dist/components/navigation/pagination/index.d.cts +3 -0
  184. package/dist/components/navigation/pagination/index.d.ts +3 -0
  185. package/dist/components/navigation/pagination/index.js +146 -0
  186. package/dist/components/navigation/pagination/index.js.map +1 -0
  187. package/dist/components/navigation/pagination/pagination.css +134 -0
  188. package/dist/components/navigation/pagination/pagination.types.d.cts +38 -0
  189. package/dist/components/navigation/pagination/pagination.types.d.ts +38 -0
  190. package/dist/components/navigation/pagination/pagination.utils.cjs +54 -0
  191. package/dist/components/navigation/pagination/pagination.utils.cjs.map +1 -0
  192. package/dist/components/navigation/pagination/pagination.utils.js +53 -0
  193. package/dist/components/navigation/pagination/pagination.utils.js.map +1 -0
  194. package/dist/components/navigation/tabs/index.d.cts +3 -2
  195. package/dist/components/navigation/tabs/index.d.ts +3 -2
  196. package/dist/components/navigation/tree-view/index.cjs.map +1 -1
  197. package/dist/components/navigation/tree-view/index.js.map +1 -1
  198. package/dist/components/overlays/context-menu/context-menu.css +151 -0
  199. package/dist/components/overlays/context-menu/context-menu.types.d.cts +69 -0
  200. package/dist/components/overlays/context-menu/context-menu.types.d.ts +69 -0
  201. package/dist/components/overlays/context-menu/context-menu.utils.cjs +46 -0
  202. package/dist/components/overlays/context-menu/context-menu.utils.cjs.map +1 -0
  203. package/dist/components/overlays/context-menu/context-menu.utils.js +40 -0
  204. package/dist/components/overlays/context-menu/context-menu.utils.js.map +1 -0
  205. package/dist/components/overlays/context-menu/index.cjs +830 -0
  206. package/dist/components/overlays/context-menu/index.cjs.map +1 -0
  207. package/dist/components/overlays/context-menu/index.d.cts +42 -0
  208. package/dist/components/overlays/context-menu/index.d.ts +42 -0
  209. package/dist/components/overlays/context-menu/index.js +818 -0
  210. package/dist/components/overlays/context-menu/index.js.map +1 -0
  211. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.cjs.map +1 -1
  212. package/dist/components/overlays/dropdown-menu/dropdown-menu-content.js.map +1 -1
  213. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.cjs.map +1 -1
  214. package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.js.map +1 -1
  215. package/dist/components/typography/heading.cjs +6 -2
  216. package/dist/components/typography/heading.cjs.map +1 -1
  217. package/dist/components/typography/heading.d.cts +3 -2
  218. package/dist/components/typography/heading.d.ts +3 -2
  219. package/dist/components/typography/heading.js +6 -2
  220. package/dist/components/typography/heading.js.map +1 -1
  221. package/dist/components/typography/text.cjs +6 -2
  222. package/dist/components/typography/text.cjs.map +1 -1
  223. package/dist/components/typography/text.d.cts +3 -2
  224. package/dist/components/typography/text.d.ts +3 -2
  225. package/dist/components/typography/text.js +6 -2
  226. package/dist/components/typography/text.js.map +1 -1
  227. package/dist/components/utilities/preview/index.cjs +89 -21
  228. package/dist/components/utilities/preview/index.cjs.map +1 -1
  229. package/dist/components/utilities/preview/index.d.cts +6 -2
  230. package/dist/components/utilities/preview/index.d.ts +6 -2
  231. package/dist/components/utilities/preview/index.js +89 -21
  232. package/dist/components/utilities/preview/index.js.map +1 -1
  233. package/dist/components/utilities/preview/preview.css +26 -11
  234. package/dist/components/utilities/transition/index.d.cts +1 -1
  235. package/dist/components/utilities/transition/index.d.ts +1 -1
  236. package/dist/index.cjs +136 -97
  237. package/dist/index.d.cts +23 -2
  238. package/dist/index.d.ts +23 -2
  239. package/dist/index.js +12 -1
  240. package/package.json +7 -6
@@ -0,0 +1,146 @@
1
+ "use client";
2
+ import { Link } from "../link/index.js";
3
+ import { getPaginationItems, normalizePage } from "./pagination.utils.js";
4
+ import "./pagination.css";
5
+ import { cn } from "@puzzle-ui/core";
6
+ import { useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ // src/components/navigation/pagination/index.tsx
9
+ const defaultLabels = {
10
+ navigation: "Pagination",
11
+ first: "Go to first page",
12
+ previous: "Go to previous page",
13
+ next: "Go to next page",
14
+ last: "Go to last page",
15
+ ellipsis: "More pages",
16
+ page: (page) => `Go to page ${page}`
17
+ };
18
+ const Pagination = ({ totalPages, page, defaultPage = 1, onPageChange, siblingCount = 1, boundaryCount = 1, showFirstLast = true, disabled = false, size = "md", labels, getPageHref, getPageAriaLabel, className, ...navProps }) => {
19
+ const [internalPage, setInternalPage] = useState(() => normalizePage(defaultPage, totalPages));
20
+ const isControlled = page !== void 0;
21
+ const currentPage = normalizePage(isControlled ? page : internalPage, totalPages);
22
+ const resolvedLabels = {
23
+ ...defaultLabels,
24
+ ...labels
25
+ };
26
+ const items = getPaginationItems(totalPages, currentPage, boundaryCount, siblingCount);
27
+ const changePage = (nextPage) => {
28
+ if (disabled) return;
29
+ const normalizedPage = normalizePage(nextPage, totalPages);
30
+ if (normalizedPage === 0 || normalizedPage === currentPage) return;
31
+ if (!isControlled) setInternalPage(normalizedPage);
32
+ onPageChange?.(normalizedPage);
33
+ };
34
+ const renderControl = (type, targetPage, content, ariaLabel) => {
35
+ const isDisabled = disabled || totalPages === 0 || targetPage < 1 || targetPage > totalPages || targetPage === currentPage;
36
+ const controlClass = cn("puzzle-pagination__control", "puzzle-pagination__navigation", isDisabled && "puzzle-pagination__control--disabled");
37
+ if (getPageHref && !isDisabled) return /* @__PURE__ */ jsx(Link, {
38
+ href: getPageHref(targetPage),
39
+ className: controlClass,
40
+ "aria-label": ariaLabel,
41
+ onClick: () => changePage(targetPage),
42
+ "data-pagination-action": type,
43
+ children: content
44
+ });
45
+ return /* @__PURE__ */ jsx("button", {
46
+ type: "button",
47
+ className: controlClass,
48
+ disabled: isDisabled,
49
+ "aria-label": ariaLabel,
50
+ onClick: () => changePage(targetPage),
51
+ "data-pagination-action": type,
52
+ children: content
53
+ });
54
+ };
55
+ return /* @__PURE__ */ jsx("nav", {
56
+ ...navProps,
57
+ "aria-label": navProps["aria-label"] ?? resolvedLabels.navigation,
58
+ className: cn("puzzle-pagination", `puzzle-pagination--${size}`, className),
59
+ "data-disabled": disabled || void 0,
60
+ children: /* @__PURE__ */ jsxs("ul", {
61
+ className: "puzzle-pagination__list",
62
+ children: [
63
+ showFirstLast && /* @__PURE__ */ jsx("li", {
64
+ className: "puzzle-pagination__item",
65
+ children: renderControl("first", 1, /* @__PURE__ */ jsx("span", {
66
+ "aria-hidden": "true",
67
+ children: "«"
68
+ }), resolvedLabels.first)
69
+ }),
70
+ /* @__PURE__ */ jsx("li", {
71
+ className: "puzzle-pagination__item",
72
+ children: renderControl("previous", currentPage - 1, /* @__PURE__ */ jsx("span", {
73
+ "aria-hidden": "true",
74
+ children: "‹"
75
+ }), resolvedLabels.previous)
76
+ }),
77
+ items.map((item) => {
78
+ if (item.type === "ellipsis") return /* @__PURE__ */ jsx("li", {
79
+ className: "puzzle-pagination__item",
80
+ children: /* @__PURE__ */ jsx("span", {
81
+ className: "puzzle-pagination__ellipsis",
82
+ "aria-label": resolvedLabels.ellipsis,
83
+ children: "…"
84
+ })
85
+ }, `ellipsis-${item.position}`);
86
+ const isCurrent = item.page === currentPage;
87
+ const ariaLabel = getPageAriaLabel?.(item.page) ?? resolvedLabels.page(item.page);
88
+ const pageClass = cn("puzzle-pagination__control", "puzzle-pagination__page", isCurrent && "puzzle-pagination__page--active");
89
+ return /* @__PURE__ */ jsx("li", {
90
+ className: "puzzle-pagination__item",
91
+ children: getPageHref ? isCurrent ? /* @__PURE__ */ jsx("span", {
92
+ className: pageClass,
93
+ "aria-label": ariaLabel,
94
+ "aria-current": "page",
95
+ "aria-disabled": disabled || void 0,
96
+ children: item.page
97
+ }) : disabled ? /* @__PURE__ */ jsx("span", {
98
+ className: cn(pageClass, "puzzle-pagination__control--disabled"),
99
+ "aria-label": ariaLabel,
100
+ "aria-disabled": "true",
101
+ children: item.page
102
+ }) : /* @__PURE__ */ jsx(Link, {
103
+ href: getPageHref(item.page),
104
+ className: pageClass,
105
+ "aria-label": ariaLabel,
106
+ "aria-current": void 0,
107
+ onClick: () => changePage(item.page),
108
+ children: item.page
109
+ }) : isCurrent ? /* @__PURE__ */ jsx("span", {
110
+ className: pageClass,
111
+ "aria-label": ariaLabel,
112
+ "aria-current": "page",
113
+ "aria-disabled": disabled || void 0,
114
+ children: item.page
115
+ }) : /* @__PURE__ */ jsx("button", {
116
+ type: "button",
117
+ className: pageClass,
118
+ "aria-label": ariaLabel,
119
+ "aria-current": isCurrent ? "page" : void 0,
120
+ disabled: disabled || isCurrent,
121
+ onClick: () => changePage(item.page),
122
+ children: item.page
123
+ })
124
+ }, item.page);
125
+ }),
126
+ /* @__PURE__ */ jsx("li", {
127
+ className: "puzzle-pagination__item",
128
+ children: renderControl("next", currentPage + 1, /* @__PURE__ */ jsx("span", {
129
+ "aria-hidden": "true",
130
+ children: "›"
131
+ }), resolvedLabels.next)
132
+ }),
133
+ showFirstLast && /* @__PURE__ */ jsx("li", {
134
+ className: "puzzle-pagination__item",
135
+ children: renderControl("last", totalPages, /* @__PURE__ */ jsx("span", {
136
+ "aria-hidden": "true",
137
+ children: "»"
138
+ }), resolvedLabels.last)
139
+ })
140
+ ]
141
+ })
142
+ });
143
+ };
144
+ export { Pagination };
145
+
146
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/navigation/pagination/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { cn } from \"@puzzle-ui/core\";\nimport { Link } from \"../link\";\n\nimport type {\n PaginationItemType,\n PaginationLabels,\n PaginationProps,\n} from \"./pagination.types\";\n\nimport { getPaginationItems, normalizePage } from \"./pagination.utils\";\n\nimport \"./pagination.css\";\n\nconst defaultLabels: PaginationLabels = {\n navigation: \"Pagination\",\n first: \"Go to first page\",\n previous: \"Go to previous page\",\n next: \"Go to next page\",\n last: \"Go to last page\",\n ellipsis: \"More pages\",\n page: (page) => `Go to page ${page}`,\n};\n\nconst Pagination = ({\n totalPages,\n page,\n defaultPage = 1,\n onPageChange,\n siblingCount = 1,\n boundaryCount = 1,\n showFirstLast = true,\n disabled = false,\n size = \"md\",\n labels,\n getPageHref,\n getPageAriaLabel,\n className,\n ...navProps\n}: PaginationProps) => {\n const [internalPage, setInternalPage] = useState(() =>\n normalizePage(defaultPage, totalPages),\n );\n\n const isControlled = page !== undefined;\n const currentPage = normalizePage(\n isControlled ? page : internalPage,\n totalPages,\n );\n\n const resolvedLabels = {\n ...defaultLabels,\n ...labels,\n };\n\n const items = getPaginationItems(\n totalPages,\n currentPage,\n boundaryCount,\n siblingCount,\n );\n\n const changePage = (nextPage: number) => {\n if (disabled) return;\n\n const normalizedPage = normalizePage(nextPage, totalPages);\n\n if (normalizedPage === 0 || normalizedPage === currentPage) return;\n\n if (!isControlled) {\n setInternalPage(normalizedPage);\n }\n\n onPageChange?.(normalizedPage);\n };\n\n const renderControl = (\n type: PaginationItemType,\n targetPage: number,\n content: React.ReactNode,\n ariaLabel: string,\n ) => {\n const isDisabled =\n disabled ||\n totalPages === 0 ||\n targetPage < 1 ||\n targetPage > totalPages ||\n targetPage === currentPage;\n\n const controlClass = cn(\n \"puzzle-pagination__control\",\n \"puzzle-pagination__navigation\",\n isDisabled && \"puzzle-pagination__control--disabled\",\n );\n\n if (getPageHref && !isDisabled) {\n return (\n <Link\n href={getPageHref(targetPage)}\n className={controlClass}\n aria-label={ariaLabel}\n onClick={() => changePage(targetPage)}\n data-pagination-action={type}\n >\n {content}\n </Link>\n );\n }\n\n return (\n <button\n type=\"button\"\n className={controlClass}\n disabled={isDisabled}\n aria-label={ariaLabel}\n onClick={() => changePage(targetPage)}\n data-pagination-action={type}\n >\n {content}\n </button>\n );\n };\n\n return (\n <nav\n {...navProps}\n aria-label={navProps[\"aria-label\"] ?? resolvedLabels.navigation}\n className={cn(\n \"puzzle-pagination\",\n `puzzle-pagination--${size}`,\n className,\n )}\n data-disabled={disabled || undefined}\n >\n <ul className=\"puzzle-pagination__list\">\n {showFirstLast && (\n <li className=\"puzzle-pagination__item\">\n {renderControl(\n \"first\",\n 1,\n <span aria-hidden=\"true\">«</span>,\n resolvedLabels.first,\n )}\n </li>\n )}\n\n <li className=\"puzzle-pagination__item\">\n {renderControl(\n \"previous\",\n currentPage - 1,\n <span aria-hidden=\"true\">‹</span>,\n resolvedLabels.previous,\n )}\n </li>\n\n {items.map((item) => {\n if (item.type === \"ellipsis\") {\n return (\n <li\n key={`ellipsis-${item.position}`}\n className=\"puzzle-pagination__item\"\n >\n <span\n className=\"puzzle-pagination__ellipsis\"\n aria-label={resolvedLabels.ellipsis}\n >\n …\n </span>\n </li>\n );\n }\n\n const isCurrent = item.page === currentPage;\n const ariaLabel =\n getPageAriaLabel?.(item.page) ?? resolvedLabels.page(item.page);\n\n const pageClass = cn(\n \"puzzle-pagination__control\",\n \"puzzle-pagination__page\",\n isCurrent && \"puzzle-pagination__page--active\",\n );\n\n return (\n <li key={item.page} className=\"puzzle-pagination__item\">\n {getPageHref ? (\n isCurrent ? (\n <span\n className={pageClass}\n aria-label={ariaLabel}\n aria-current=\"page\"\n aria-disabled={disabled || undefined}\n >\n {item.page}\n </span>\n ) : disabled ? (\n <span\n className={cn(\n pageClass,\n \"puzzle-pagination__control--disabled\",\n )}\n aria-label={ariaLabel}\n aria-disabled=\"true\"\n >\n {item.page}\n </span>\n ) : (\n <Link\n href={getPageHref(item.page)}\n className={pageClass}\n aria-label={ariaLabel}\n aria-current={undefined}\n onClick={() => changePage(item.page)}\n >\n {item.page}\n </Link>\n )\n ) : isCurrent ? (\n <span\n className={pageClass}\n aria-label={ariaLabel}\n aria-current=\"page\"\n aria-disabled={disabled || undefined}\n >\n {item.page}\n </span>\n ) : (\n <button\n type=\"button\"\n className={pageClass}\n aria-label={ariaLabel}\n aria-current={isCurrent ? \"page\" : undefined}\n disabled={disabled || isCurrent}\n onClick={() => changePage(item.page)}\n >\n {item.page}\n </button>\n )}\n </li>\n );\n })}\n\n <li className=\"puzzle-pagination__item\">\n {renderControl(\n \"next\",\n currentPage + 1,\n <span aria-hidden=\"true\">›</span>,\n resolvedLabels.next,\n )}\n </li>\n\n {showFirstLast && (\n <li className=\"puzzle-pagination__item\">\n {renderControl(\n \"last\",\n totalPages,\n <span aria-hidden=\"true\">»</span>,\n resolvedLabels.last,\n )}\n </li>\n )}\n </ul>\n </nav>\n );\n};\n\nexport { Pagination, type PaginationProps };\n"],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ .puzzle-pagination {
2
+ --puzzle-pagination-size: 2.25rem;
3
+ --puzzle-pagination-gap: var(--puzzle-space-1, .25rem);
4
+ --puzzle-pagination-radius: var(--puzzle-radius-md, .375rem);
5
+ --puzzle-pagination-color: var(--puzzle-color-text, #171717);
6
+ --puzzle-pagination-muted: var(--puzzle-color-text-muted, #737373);
7
+ --puzzle-pagination-border: var(--puzzle-color-border, #e5e0d6);
8
+ --puzzle-pagination-active-bg: var(--puzzle-color-primary);
9
+ --puzzle-pagination-active-color: var(--puzzle-color-on-primary, #fff);
10
+ --puzzle-pagination-focus: var(--puzzle-color-ring, currentColor);
11
+ width: fit-content;
12
+ max-width: 100%;
13
+ color: var(--puzzle-pagination-color);
14
+ display: flex;
15
+ }
16
+
17
+ .puzzle-pagination--sm {
18
+ --puzzle-pagination-size: 1.875rem;
19
+ }
20
+
21
+ .puzzle-pagination--md {
22
+ --puzzle-pagination-size: 2.25rem;
23
+ }
24
+
25
+ .puzzle-pagination__list {
26
+ justify-content: center;
27
+ align-items: center;
28
+ gap: var(--puzzle-pagination-gap);
29
+ flex-wrap: wrap;
30
+ margin: 0;
31
+ padding: 0;
32
+ list-style: none;
33
+ display: flex;
34
+ }
35
+
36
+ .puzzle-pagination__item {
37
+ flex: none;
38
+ justify-content: center;
39
+ align-items: center;
40
+ display: flex;
41
+ }
42
+
43
+ .puzzle-pagination__control {
44
+ width: var(--puzzle-pagination-size);
45
+ height: var(--puzzle-pagination-size);
46
+ border-radius: var(--puzzle-pagination-radius);
47
+ color: var(--puzzle-pagination-color);
48
+ font-family: inherit;
49
+ font-size: var(--puzzle-font-size-body2, .875rem);
50
+ font-weight: var(--puzzle-font-weight-medium, 500);
51
+ cursor: pointer;
52
+ user-select: none;
53
+ touch-action: manipulation;
54
+ transition: background-color var(--puzzle-duration-fast, .15s) ease,
55
+ color var(--puzzle-duration-fast, .15s) ease,
56
+ border-color var(--puzzle-duration-fast, .15s) ease;
57
+ background: none;
58
+ border: 1px solid #0000;
59
+ justify-content: center;
60
+ align-items: center;
61
+ padding: 0;
62
+ line-height: 1;
63
+ text-decoration: none;
64
+ display: inline-flex;
65
+ }
66
+
67
+ .puzzle-pagination__control:hover:not(:disabled):not(.puzzle-pagination__control--disabled):not(.puzzle-pagination__page--active) {
68
+ background: var(--puzzle-color-action-hover, #8080801a);
69
+ }
70
+
71
+ .puzzle-pagination__control:focus-visible {
72
+ outline: 2px solid var(--puzzle-pagination-focus);
73
+ outline-offset: 2px;
74
+ }
75
+
76
+ .puzzle-pagination__page--active {
77
+ border-color: var(--puzzle-pagination-active-bg);
78
+ background: var(--puzzle-pagination-active-bg);
79
+ color: var(--puzzle-pagination-active-color);
80
+ cursor: default;
81
+ }
82
+
83
+ .puzzle-pagination__navigation {
84
+ border-color: var(--puzzle-pagination-border);
85
+ font-size: 1.25rem;
86
+ }
87
+
88
+ .puzzle-pagination__control:disabled, .puzzle-pagination__control--disabled {
89
+ color: var(--puzzle-pagination-muted);
90
+ cursor: not-allowed;
91
+ opacity: .45;
92
+ }
93
+
94
+ .puzzle-pagination__ellipsis {
95
+ width: var(--puzzle-pagination-size);
96
+ height: var(--puzzle-pagination-size);
97
+ color: var(--puzzle-pagination-muted);
98
+ user-select: none;
99
+ justify-content: center;
100
+ align-items: center;
101
+ font-size: 1rem;
102
+ display: inline-flex;
103
+ }
104
+
105
+ .puzzle-pagination[data-disabled] {
106
+ opacity: .65;
107
+ }
108
+
109
+ @media (forced-colors: active) {
110
+ .puzzle-pagination__control {
111
+ border-color: buttontext;
112
+ }
113
+
114
+ .puzzle-pagination__page--active {
115
+ color: highlighttext;
116
+ background: highlight;
117
+ border: 2px solid highlight;
118
+ }
119
+
120
+ .puzzle-pagination__control:focus-visible {
121
+ outline: 2px solid highlight;
122
+ }
123
+
124
+ .puzzle-pagination__control:disabled, .puzzle-pagination__control--disabled {
125
+ color: graytext;
126
+ opacity: 1;
127
+ }
128
+ }
129
+
130
+ @media (prefers-reduced-motion: reduce) {
131
+ .puzzle-pagination__control {
132
+ transition: none;
133
+ }
134
+ }
@@ -0,0 +1,38 @@
1
+ import { ComponentPropsWithoutRef } from "react";
2
+ type PaginationSize = "sm" | "md";
3
+ type PaginationLabels = {
4
+ navigation: string;
5
+ first: string;
6
+ previous: string;
7
+ next: string;
8
+ last: string;
9
+ ellipsis: string;
10
+ page: (page: number) => string;
11
+ };
12
+ type PaginationProps = Omit<ComponentPropsWithoutRef<"nav">, "children" | "onChange"> & {
13
+ /** Total number of available pages. */
14
+ totalPages: number;
15
+ /** Current page for controlled usage. Pages start at 1. */
16
+ page?: number;
17
+ /** Initial page for uncontrolled usage. Defaults to 1. */
18
+ defaultPage?: number;
19
+ /** Called when the selected page changes. */
20
+ onPageChange?: (page: number) => void;
21
+ /** Number of pages displayed around the current page. */
22
+ siblingCount?: number;
23
+ /** Number of pages always displayed at both boundaries. */
24
+ boundaryCount?: number;
25
+ /** Whether first and last page controls are displayed. */
26
+ showFirstLast?: boolean;
27
+ /** Whether all pagination controls are disabled. */
28
+ disabled?: boolean;
29
+ /** Visual size of the pagination controls. */
30
+ size?: PaginationSize;
31
+ /** Accessible labels for navigation controls. */
32
+ labels?: Partial<PaginationLabels>;
33
+ /** Generate a URL for a page instead of using a button. */
34
+ getPageHref?: (page: number) => string;
35
+ /** Accessible label for a specific page. */
36
+ getPageAriaLabel?: (page: number) => string;
37
+ };
38
+ export type { PaginationLabels, PaginationProps, PaginationSize };
@@ -0,0 +1,38 @@
1
+ import { ComponentPropsWithoutRef } from "react";
2
+ type PaginationSize = "sm" | "md";
3
+ type PaginationLabels = {
4
+ navigation: string;
5
+ first: string;
6
+ previous: string;
7
+ next: string;
8
+ last: string;
9
+ ellipsis: string;
10
+ page: (page: number) => string;
11
+ };
12
+ type PaginationProps = Omit<ComponentPropsWithoutRef<"nav">, "children" | "onChange"> & {
13
+ /** Total number of available pages. */
14
+ totalPages: number;
15
+ /** Current page for controlled usage. Pages start at 1. */
16
+ page?: number;
17
+ /** Initial page for uncontrolled usage. Defaults to 1. */
18
+ defaultPage?: number;
19
+ /** Called when the selected page changes. */
20
+ onPageChange?: (page: number) => void;
21
+ /** Number of pages displayed around the current page. */
22
+ siblingCount?: number;
23
+ /** Number of pages always displayed at both boundaries. */
24
+ boundaryCount?: number;
25
+ /** Whether first and last page controls are displayed. */
26
+ showFirstLast?: boolean;
27
+ /** Whether all pagination controls are disabled. */
28
+ disabled?: boolean;
29
+ /** Visual size of the pagination controls. */
30
+ size?: PaginationSize;
31
+ /** Accessible labels for navigation controls. */
32
+ labels?: Partial<PaginationLabels>;
33
+ /** Generate a URL for a page instead of using a button. */
34
+ getPageHref?: (page: number) => string;
35
+ /** Accessible label for a specific page. */
36
+ getPageAriaLabel?: (page: number) => string;
37
+ };
38
+ export type { PaginationLabels, PaginationProps, PaginationSize };
@@ -0,0 +1,54 @@
1
+ // src/components/navigation/pagination/pagination.utils.ts
2
+ const normalizeCount = (value) => Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
3
+ const getPaginationItems = (totalPages, currentPage, boundaryCount = 1, siblingCount = 1) => {
4
+ const total = normalizeCount(totalPages);
5
+ const boundaries = normalizeCount(boundaryCount);
6
+ const siblings = normalizeCount(siblingCount);
7
+ if (total === 0) return [];
8
+ const page = Math.min(Math.max(1, normalizeCount(currentPage)), total);
9
+ if (total <= boundaries * 2 + siblings * 2 + 3) return Array.from({ length: total }, (_, index) => ({
10
+ type: "page",
11
+ page: index + 1
12
+ }));
13
+ const visiblePages = /* @__PURE__ */ new Set();
14
+ for (let index = 1; index <= Math.min(boundaries, total); index += 1) visiblePages.add(index);
15
+ for (let index = Math.max(1, total - boundaries + 1); index <= total; index += 1) visiblePages.add(index);
16
+ for (let index = Math.max(1, page - siblings); index <= Math.min(total, page + siblings); index += 1) visiblePages.add(index);
17
+ if (page - siblings <= boundaries + 1) visiblePages.add(boundaries + siblings + 1);
18
+ if (page + siblings >= total - boundaries - 1) visiblePages.add(total - boundaries - siblings);
19
+ const pages = [...visiblePages].sort((a, b) => a - b);
20
+ const items = [];
21
+ pages.forEach((current, index) => {
22
+ if (index === 0) {
23
+ items.push({
24
+ type: "page",
25
+ page: current
26
+ });
27
+ return;
28
+ }
29
+ const previous = pages[index - 1];
30
+ const difference = current - previous;
31
+ if (difference === 2) items.push({
32
+ type: "page",
33
+ page: previous + 1
34
+ });
35
+ else if (difference > 2) items.push({
36
+ type: "ellipsis",
37
+ position: index === 1 ? "start" : "end"
38
+ });
39
+ items.push({
40
+ type: "page",
41
+ page: current
42
+ });
43
+ });
44
+ return items;
45
+ };
46
+ const normalizePage = (page, totalPages) => {
47
+ const total = normalizeCount(totalPages);
48
+ if (total === 0) return 0;
49
+ return Math.min(Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1), total);
50
+ };
51
+ exports.getPaginationItems = getPaginationItems;
52
+ exports.normalizePage = normalizePage;
53
+
54
+ //# sourceMappingURL=pagination.utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.utils.cjs","names":[],"sources":["../../../../src/components/navigation/pagination/pagination.utils.ts"],"sourcesContent":["import type { PaginationItem } from \"./pagination.types\";\n\nconst normalizeCount = (value: number) =>\n Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n\nconst getPaginationItems = (\n totalPages: number,\n currentPage: number,\n boundaryCount = 1,\n siblingCount = 1,\n): PaginationItem[] => {\n const total = normalizeCount(totalPages);\n const boundaries = normalizeCount(boundaryCount);\n const siblings = normalizeCount(siblingCount);\n\n if (total === 0) return [];\n\n const page = Math.min(Math.max(1, normalizeCount(currentPage)), total);\n\n if (total <= boundaries * 2 + siblings * 2 + 3) {\n return Array.from({ length: total }, (_, index) => ({\n type: \"page\",\n page: index + 1,\n }));\n }\n\n const visiblePages = new Set<number>();\n\n for (let index = 1; index <= Math.min(boundaries, total); index += 1) {\n visiblePages.add(index);\n }\n\n for (\n let index = Math.max(1, total - boundaries + 1);\n index <= total;\n index += 1\n ) {\n visiblePages.add(index);\n }\n\n for (\n let index = Math.max(1, page - siblings);\n index <= Math.min(total, page + siblings);\n index += 1\n ) {\n visiblePages.add(index);\n }\n\n if (page - siblings <= boundaries + 1) {\n visiblePages.add(boundaries + siblings + 1);\n }\n\n if (page + siblings >= total - boundaries - 1) {\n visiblePages.add(total - boundaries - siblings);\n }\n\n const pages = [...visiblePages].sort((a, b) => a - b);\n const items: PaginationItem[] = [];\n\n pages.forEach((current, index) => {\n if (index === 0) {\n items.push({ type: \"page\", page: current });\n return;\n }\n\n const previous = pages[index - 1]!;\n const difference = current - previous;\n\n if (difference === 2) {\n items.push({\n type: \"page\",\n page: previous + 1,\n });\n } else if (difference > 2) {\n items.push({\n type: \"ellipsis\",\n position: index === 1 ? \"start\" : \"end\",\n });\n }\n\n items.push({\n type: \"page\",\n page: current,\n });\n });\n\n return items;\n};\n\nconst normalizePage = (page: number, totalPages: number) => {\n const total = normalizeCount(totalPages);\n\n if (total === 0) return 0;\n\n const normalized = Number.isFinite(page) ? Math.floor(page) : 1;\n\n return Math.min(Math.max(1, normalized), total);\n};\n\nexport { getPaginationItems, normalizePage };\n"],"mappings":";AAEA,MAAM,kBAAkB,UACtB,OAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI;AAE5D,MAAM,sBACJ,YACA,aACA,gBAAgB,GAChB,eAAe,MACM;CACrB,MAAM,QAAQ,eAAe,UAAU;CACvC,MAAM,aAAa,eAAe,aAAa;CAC/C,MAAM,WAAW,eAAe,YAAY;CAE5C,IAAI,UAAU,GAAG,OAAO,CAAC;CAEzB,MAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,eAAe,WAAW,CAAC,GAAG,KAAK;CAErE,IAAI,SAAS,aAAa,IAAI,WAAW,IAAI,GAC3C,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,WAAW;EAClD,MAAM;EACN,MAAM,QAAQ;CAChB,EAAE;CAGJ,MAAM,+BAAe,IAAI,IAAY;CAErC,KAAK,IAAI,QAAQ,GAAG,SAAS,KAAK,IAAI,YAAY,KAAK,GAAG,SAAS,GACjE,aAAa,IAAI,KAAK;CAGxB,KACE,IAAI,QAAQ,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC,GAC9C,SAAS,OACT,SAAS,GAET,aAAa,IAAI,KAAK;CAGxB,KACE,IAAI,QAAQ,KAAK,IAAI,GAAG,OAAO,QAAQ,GACvC,SAAS,KAAK,IAAI,OAAO,OAAO,QAAQ,GACxC,SAAS,GAET,aAAa,IAAI,KAAK;CAGxB,IAAI,OAAO,YAAY,aAAa,GAClC,aAAa,IAAI,aAAa,WAAW,CAAC;CAG5C,IAAI,OAAO,YAAY,QAAQ,aAAa,GAC1C,aAAa,IAAI,QAAQ,aAAa,QAAQ;CAGhD,MAAM,QAAQ,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CACpD,MAAM,QAA0B,CAAC;CAEjC,MAAM,SAAS,SAAS,UAAU;EAChC,IAAI,UAAU,GAAG;GACf,MAAM,KAAK;IAAE,MAAM;IAAQ,MAAM;GAAQ,CAAC;GAC1C;EACF;EAEA,MAAM,WAAW,MAAM,QAAQ;EAC/B,MAAM,aAAa,UAAU;EAE7B,IAAI,eAAe,GACjB,MAAM,KAAK;GACT,MAAM;GACN,MAAM,WAAW;EACnB,CAAC;OACI,IAAI,aAAa,GACtB,MAAM,KAAK;GACT,MAAM;GACN,UAAU,UAAU,IAAI,UAAU;EACpC,CAAC;EAGH,MAAM,KAAK;GACT,MAAM;GACN,MAAM;EACR,CAAC;CACH,CAAC;CAED,OAAO;AACT;AAEA,MAAM,iBAAiB,MAAc,eAAuB;CAC1D,MAAM,QAAQ,eAAe,UAAU;CAEvC,IAAI,UAAU,GAAG,OAAO;CAIxB,OAAO,KAAK,IAAI,KAAK,IAAI,GAFN,OAAO,SAAS,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAExB,GAAG,KAAK;AAChD"}
@@ -0,0 +1,53 @@
1
+ // src/components/navigation/pagination/pagination.utils.ts
2
+ const normalizeCount = (value) => Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
3
+ const getPaginationItems = (totalPages, currentPage, boundaryCount = 1, siblingCount = 1) => {
4
+ const total = normalizeCount(totalPages);
5
+ const boundaries = normalizeCount(boundaryCount);
6
+ const siblings = normalizeCount(siblingCount);
7
+ if (total === 0) return [];
8
+ const page = Math.min(Math.max(1, normalizeCount(currentPage)), total);
9
+ if (total <= boundaries * 2 + siblings * 2 + 3) return Array.from({ length: total }, (_, index) => ({
10
+ type: "page",
11
+ page: index + 1
12
+ }));
13
+ const visiblePages = /* @__PURE__ */ new Set();
14
+ for (let index = 1; index <= Math.min(boundaries, total); index += 1) visiblePages.add(index);
15
+ for (let index = Math.max(1, total - boundaries + 1); index <= total; index += 1) visiblePages.add(index);
16
+ for (let index = Math.max(1, page - siblings); index <= Math.min(total, page + siblings); index += 1) visiblePages.add(index);
17
+ if (page - siblings <= boundaries + 1) visiblePages.add(boundaries + siblings + 1);
18
+ if (page + siblings >= total - boundaries - 1) visiblePages.add(total - boundaries - siblings);
19
+ const pages = [...visiblePages].sort((a, b) => a - b);
20
+ const items = [];
21
+ pages.forEach((current, index) => {
22
+ if (index === 0) {
23
+ items.push({
24
+ type: "page",
25
+ page: current
26
+ });
27
+ return;
28
+ }
29
+ const previous = pages[index - 1];
30
+ const difference = current - previous;
31
+ if (difference === 2) items.push({
32
+ type: "page",
33
+ page: previous + 1
34
+ });
35
+ else if (difference > 2) items.push({
36
+ type: "ellipsis",
37
+ position: index === 1 ? "start" : "end"
38
+ });
39
+ items.push({
40
+ type: "page",
41
+ page: current
42
+ });
43
+ });
44
+ return items;
45
+ };
46
+ const normalizePage = (page, totalPages) => {
47
+ const total = normalizeCount(totalPages);
48
+ if (total === 0) return 0;
49
+ return Math.min(Math.max(1, Number.isFinite(page) ? Math.floor(page) : 1), total);
50
+ };
51
+ export { getPaginationItems, normalizePage };
52
+
53
+ //# sourceMappingURL=pagination.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.utils.js","names":[],"sources":["../../../../src/components/navigation/pagination/pagination.utils.ts"],"sourcesContent":["import type { PaginationItem } from \"./pagination.types\";\n\nconst normalizeCount = (value: number) =>\n Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n\nconst getPaginationItems = (\n totalPages: number,\n currentPage: number,\n boundaryCount = 1,\n siblingCount = 1,\n): PaginationItem[] => {\n const total = normalizeCount(totalPages);\n const boundaries = normalizeCount(boundaryCount);\n const siblings = normalizeCount(siblingCount);\n\n if (total === 0) return [];\n\n const page = Math.min(Math.max(1, normalizeCount(currentPage)), total);\n\n if (total <= boundaries * 2 + siblings * 2 + 3) {\n return Array.from({ length: total }, (_, index) => ({\n type: \"page\",\n page: index + 1,\n }));\n }\n\n const visiblePages = new Set<number>();\n\n for (let index = 1; index <= Math.min(boundaries, total); index += 1) {\n visiblePages.add(index);\n }\n\n for (\n let index = Math.max(1, total - boundaries + 1);\n index <= total;\n index += 1\n ) {\n visiblePages.add(index);\n }\n\n for (\n let index = Math.max(1, page - siblings);\n index <= Math.min(total, page + siblings);\n index += 1\n ) {\n visiblePages.add(index);\n }\n\n if (page - siblings <= boundaries + 1) {\n visiblePages.add(boundaries + siblings + 1);\n }\n\n if (page + siblings >= total - boundaries - 1) {\n visiblePages.add(total - boundaries - siblings);\n }\n\n const pages = [...visiblePages].sort((a, b) => a - b);\n const items: PaginationItem[] = [];\n\n pages.forEach((current, index) => {\n if (index === 0) {\n items.push({ type: \"page\", page: current });\n return;\n }\n\n const previous = pages[index - 1]!;\n const difference = current - previous;\n\n if (difference === 2) {\n items.push({\n type: \"page\",\n page: previous + 1,\n });\n } else if (difference > 2) {\n items.push({\n type: \"ellipsis\",\n position: index === 1 ? \"start\" : \"end\",\n });\n }\n\n items.push({\n type: \"page\",\n page: current,\n });\n });\n\n return items;\n};\n\nconst normalizePage = (page: number, totalPages: number) => {\n const total = normalizeCount(totalPages);\n\n if (total === 0) return 0;\n\n const normalized = Number.isFinite(page) ? Math.floor(page) : 1;\n\n return Math.min(Math.max(1, normalized), total);\n};\n\nexport { getPaginationItems, normalizePage };\n"],"mappings":";AAEA,MAAM,kBAAkB,UACtB,OAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI;AAE5D,MAAM,sBACJ,YACA,aACA,gBAAgB,GAChB,eAAe,MACM;CACrB,MAAM,QAAQ,eAAe,UAAU;CACvC,MAAM,aAAa,eAAe,aAAa;CAC/C,MAAM,WAAW,eAAe,YAAY;CAE5C,IAAI,UAAU,GAAG,OAAO,CAAC;CAEzB,MAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,eAAe,WAAW,CAAC,GAAG,KAAK;CAErE,IAAI,SAAS,aAAa,IAAI,WAAW,IAAI,GAC3C,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,WAAW;EAClD,MAAM;EACN,MAAM,QAAQ;CAChB,EAAE;CAGJ,MAAM,+BAAe,IAAI,IAAY;CAErC,KAAK,IAAI,QAAQ,GAAG,SAAS,KAAK,IAAI,YAAY,KAAK,GAAG,SAAS,GACjE,aAAa,IAAI,KAAK;CAGxB,KACE,IAAI,QAAQ,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC,GAC9C,SAAS,OACT,SAAS,GAET,aAAa,IAAI,KAAK;CAGxB,KACE,IAAI,QAAQ,KAAK,IAAI,GAAG,OAAO,QAAQ,GACvC,SAAS,KAAK,IAAI,OAAO,OAAO,QAAQ,GACxC,SAAS,GAET,aAAa,IAAI,KAAK;CAGxB,IAAI,OAAO,YAAY,aAAa,GAClC,aAAa,IAAI,aAAa,WAAW,CAAC;CAG5C,IAAI,OAAO,YAAY,QAAQ,aAAa,GAC1C,aAAa,IAAI,QAAQ,aAAa,QAAQ;CAGhD,MAAM,QAAQ,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CACpD,MAAM,QAA0B,CAAC;CAEjC,MAAM,SAAS,SAAS,UAAU;EAChC,IAAI,UAAU,GAAG;GACf,MAAM,KAAK;IAAE,MAAM;IAAQ,MAAM;GAAQ,CAAC;GAC1C;EACF;EAEA,MAAM,WAAW,MAAM,QAAQ;EAC/B,MAAM,aAAa,UAAU;EAE7B,IAAI,eAAe,GACjB,MAAM,KAAK;GACT,MAAM;GACN,MAAM,WAAW;EACnB,CAAC;OACI,IAAI,aAAa,GACtB,MAAM,KAAK;GACT,MAAM;GACN,UAAU,UAAU,IAAI,UAAU;EACpC,CAAC;EAGH,MAAM,KAAK;GACT,MAAM;GACN,MAAM;EACR,CAAC;CACH,CAAC;CAED,OAAO;AACT;AAEA,MAAM,iBAAiB,MAAc,eAAuB;CAC1D,MAAM,QAAQ,eAAe,UAAU;CAEvC,IAAI,UAAU,GAAG,OAAO;CAIxB,OAAO,KAAK,IAAI,KAAK,IAAI,GAFN,OAAO,SAAS,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAExB,GAAG,KAAK;AAChD"}
@@ -24,7 +24,8 @@ type TabsProps = Omit<ComponentPropsWithoutRef<"div">, "children" | "onChange">
24
24
  children: ReactNode;
25
25
  };
26
26
  declare const TabsTab: ({ children }: TabsTabProps) => import("react").JSX.Element;
27
- declare const Tabs: (({ tabBarPosition, initialActiveId, activeId, onActivate, forceMountContent, children, className, ...rootProps }: TabsProps) => import("react").JSX.Element) & {
28
- Tab: ({ children }: TabsTabProps) => import("react").JSX.Element;
27
+ declare const TabsRoot: ({ tabBarPosition, initialActiveId, activeId, onActivate, forceMountContent, children, className, ...rootProps }: TabsProps) => import("react").JSX.Element;
28
+ declare const Tabs: typeof TabsRoot & {
29
+ Tab: typeof TabsTab;
29
30
  };
30
31
  export { Tabs, type TabsPosition, type TabsProps, TabsTab, type TabsTabProps };
@@ -24,7 +24,8 @@ type TabsProps = Omit<ComponentPropsWithoutRef<"div">, "children" | "onChange">
24
24
  children: ReactNode;
25
25
  };
26
26
  declare const TabsTab: ({ children }: TabsTabProps) => import("react").JSX.Element;
27
- declare const Tabs: (({ tabBarPosition, initialActiveId, activeId, onActivate, forceMountContent, children, className, ...rootProps }: TabsProps) => import("react").JSX.Element) & {
28
- Tab: ({ children }: TabsTabProps) => import("react").JSX.Element;
27
+ declare const TabsRoot: ({ tabBarPosition, initialActiveId, activeId, onActivate, forceMountContent, children, className, ...rootProps }: TabsProps) => import("react").JSX.Element;
28
+ declare const Tabs: typeof TabsRoot & {
29
+ Tab: typeof TabsTab;
29
30
  };
30
31
  export { Tabs, type TabsPosition, type TabsProps, TabsTab, type TabsTabProps };