@vygruppen/spor-react 9.4.0 → 9.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.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, AttachedInputs, Badge, Box, Brand, Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, ButtonGroup, Card, CardSelect, Center, Checkbox, CheckboxGroup, ChoiceChip, ClosableAlert, CloseButton, Code, Collapse, ColorInlineLoader, ColorSpinner, Combobox, Container, ContentLoader, DarkFullScreenLoader, DarkInlineLoader, DarkMode, DarkSpinner, DatePicker, DateRangePicker, Divider, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, ModalHeader as DrawerHeader, DrawerOverlay, Expandable, ExpandableAlert, ExpandableItem, Fade, Flex, FloatingActionButton, FormControl, FormErrorMessage, FormHelperText, FormLabel, FullScreenDrawer, Grid, GridItem, HStack, Heading, IconButton, Image, Img, InfoSelect, InfoTag, Input, InputGroup, InputLeftElement, InputRightElement, Item, ItemDescription, ItemLabel, JumpButton, Language, LanguageProvider, LightFullScreenLoader, LightInlineLoader, LightMode, LightSpinner, LineIcon, ListBox, ListItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, Nudge, NumericStepper, OrderedList, PasswordInput, PhoneNumberInput, PlayPauseButton, Portal, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, StaticCard, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tooltip, Tr, TravelTag, UnorderedList, VStack, VyLogo, WizardNudge, Wrap, WrapItem, brandTheme, createTexts, defineStyleConfig, extendTheme, fontFaces, slugify, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useSize, useTheme, useToast, useToken, useTranslation } from './chunk-JRXSGTL2.mjs';
1
+ export { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, AttachedInputs, Badge, Box, Brand, Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, ButtonGroup, Card, CardSelect, Center, Checkbox, CheckboxGroup, ChoiceChip, ClosableAlert, CloseButton, Code, Collapse, ColorInlineLoader, ColorSpinner, Combobox, Container, ContentLoader, DarkFullScreenLoader, DarkInlineLoader, DarkMode, DarkSpinner, DatePicker, DateRangePicker, Divider, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, ModalHeader as DrawerHeader, DrawerOverlay, Expandable, ExpandableAlert, ExpandableItem, Fade, Flex, FloatingActionButton, FormControl, FormErrorMessage, FormHelperText, FormLabel, FullScreenDrawer, Grid, GridItem, HStack, Heading, IconButton, Image, Img, InfoSelect, InfoTag, Input, InputGroup, InputLeftElement, InputRightElement, Item, ItemDescription, ItemLabel, JumpButton, Language, LanguageProvider, LightFullScreenLoader, LightInlineLoader, LightMode, LightSpinner, LineIcon, ListBox, ListItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, Nudge, NumericStepper, OrderedList, Pagination, PasswordInput, PhoneNumberInput, PlayPauseButton, Portal, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, StaticCard, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tooltip, Tr, TravelTag, UnorderedList, VStack, VyLogo, WizardNudge, Wrap, WrapItem, brandTheme, createTexts, defineStyleConfig, extendTheme, fontFaces, slugify, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useSize, useTheme, useToast, useToken, useTranslation } from './chunk-XXA3IGVH.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
- "version": "9.4.0",
3
+ "version": "9.5.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
package/src/index.tsx CHANGED
@@ -17,6 +17,7 @@ export * from "./logo";
17
17
  export * from "./media-controller";
18
18
  export * from "./modal";
19
19
  export * from "./nudge";
20
+ export * from "./pagination";
20
21
  export * from "./progress-indicator";
21
22
  export * from "./provider";
22
23
  export * from "./stepper";
@@ -0,0 +1,156 @@
1
+ import React from "react";
2
+ import { Center, createTexts, useTranslation, Flex, TextLink } from "..";
3
+ import {
4
+ ListItem,
5
+ UnorderedList,
6
+ useMultiStyleConfig,
7
+ Link,
8
+ } from "@chakra-ui/react";
9
+ import {
10
+ DropdownLeftFill18Icon,
11
+ DropdownRightFill18Icon,
12
+ } from "@vygruppen/spor-icon-react";
13
+
14
+ type PaginationProps = {
15
+ /** Specify the total amount of pages */
16
+ totalPages: number;
17
+ /** Specify the currently selected page */
18
+ selectedPage: number;
19
+ /** Callback for when a page is clicked */
20
+ onPageChange: (selected: number) => void;
21
+ };
22
+
23
+ /**
24
+ * A pagination component is used to navigate between multiple pages.
25
+ *
26
+ * You specify the total amount of pages and the currently selected page.
27
+ *
28
+ * ```tsx
29
+ * <Pagination
30
+ * totalPages={10}
31
+ * selectedPage={3}
32
+ * onPageChange={handlePageChange}
33
+ * />
34
+ * ```
35
+ **/
36
+
37
+ export const Pagination = ({
38
+ totalPages,
39
+ selectedPage,
40
+ onPageChange,
41
+ }: PaginationProps) => {
42
+ const { t } = useTranslation();
43
+
44
+ const style = useMultiStyleConfig("Pagination", { selectedPage });
45
+
46
+ const hasPreviousPage = selectedPage > 1;
47
+ const hasNextPage = selectedPage < totalPages;
48
+
49
+ const renderPaginationButtons = () => {
50
+ const displayPageNumbers = [];
51
+ const maxVisiblePages = 8;
52
+ if (totalPages <= maxVisiblePages) {
53
+ displayPageNumbers.push(
54
+ ...Array.from({ length: totalPages }, (_, i) => i + 1),
55
+ );
56
+ } else {
57
+ if (selectedPage <= Math.floor(maxVisiblePages / 2) + 1) {
58
+ // If selectedPage is near the beginning, display the first pages.
59
+ displayPageNumbers.push(
60
+ ...Array.from({ length: maxVisiblePages - 1 }, (_, i) => i + 1),
61
+ );
62
+ displayPageNumbers.push("...");
63
+ displayPageNumbers.push(totalPages);
64
+ } else if (selectedPage >= totalPages - Math.floor(maxVisiblePages / 2)) {
65
+ // If selectedPage is near the end, display the last pages.
66
+ displayPageNumbers.push(1);
67
+ displayPageNumbers.push("...");
68
+ displayPageNumbers.push(
69
+ ...Array.from(
70
+ { length: maxVisiblePages - 1 },
71
+ (_, i) => totalPages - maxVisiblePages + 2 + i,
72
+ ),
73
+ );
74
+ } else {
75
+ // Display pages with "..." in the middle.
76
+ displayPageNumbers.push(1);
77
+ displayPageNumbers.push("...");
78
+ for (
79
+ let i = selectedPage - Math.floor((maxVisiblePages - 3) / 2);
80
+ i <= selectedPage + Math.floor((maxVisiblePages - 3) / 2);
81
+ i++
82
+ ) {
83
+ displayPageNumbers.push(i);
84
+ }
85
+ displayPageNumbers.push("...");
86
+ displayPageNumbers.push(totalPages);
87
+ }
88
+ }
89
+ return displayPageNumbers.map((pageNumber, index) =>
90
+ pageNumber === "..." ? (
91
+ <ListItem key={index} sx={style.listItem}>
92
+ <Center>...</Center>
93
+ </ListItem>
94
+ ) : (
95
+ <Link
96
+ key={index}
97
+ as={ListItem}
98
+ onClick={() => {
99
+ if (pageNumber !== "...") {
100
+ onPageChange(+pageNumber);
101
+ }
102
+ }}
103
+ padding={pageNumber === "..." ? 0 : undefined}
104
+ sx={pageNumber === selectedPage ? style.activeButton : style.link}
105
+ >
106
+ {pageNumber}
107
+ </Link>
108
+ ),
109
+ );
110
+ };
111
+
112
+ return (
113
+ <Flex as="nav" aria-label="pagination">
114
+ <UnorderedList
115
+ display="flex"
116
+ listStyleType="none"
117
+ gap={[0, 1]}
118
+ padding={0}
119
+ margin={0}
120
+ >
121
+ <ListItem aria-label={t(texts.previousPage)}>
122
+ <TextLink
123
+ onClick={() => onPageChange(selectedPage - 1)}
124
+ sx={hasPreviousPage ? style.link : style.disabled}
125
+ >
126
+ <DropdownLeftFill18Icon sx={style.icon} />
127
+ </TextLink>
128
+ </ListItem>
129
+ {renderPaginationButtons()}
130
+ <ListItem aria-label={t(texts.nextPage)}>
131
+ <TextLink
132
+ onClick={() => onPageChange(selectedPage + 1)}
133
+ sx={hasNextPage ? style.link : style.disabled}
134
+ >
135
+ <DropdownRightFill18Icon sx={style.icon} />
136
+ </TextLink>
137
+ </ListItem>
138
+ </UnorderedList>
139
+ </Flex>
140
+ );
141
+ };
142
+
143
+ const texts = createTexts({
144
+ previousPage: {
145
+ nb: "Forrige side",
146
+ nn: "Førre side",
147
+ en: "Previous page",
148
+ sv: "Föregående sida",
149
+ },
150
+ nextPage: {
151
+ nb: "Neste side",
152
+ nn: "Neste side",
153
+ en: "Next page",
154
+ sv: "Nästa sida",
155
+ },
156
+ });
@@ -0,0 +1 @@
1
+ export * from "./Pagination";
@@ -87,9 +87,9 @@ const config = helpers.defineMultiStyleConfig({
87
87
  [$arrowBackground.variable]: surface("default", props).backgroundColor,
88
88
  },
89
89
  calendarPopover: {
90
- ...baseBackground("default", props),
90
+ ...floatingBackground("default", props),
91
91
  ...baseText("default", props),
92
- ...baseBorder("default", props),
92
+ ...floatingBorder("default", props),
93
93
  boxShadow: "md",
94
94
  },
95
95
  weekdays: {
@@ -26,6 +26,7 @@ export { default as ListBox } from "./listbox";
26
26
  export { default as MediaControllerButton } from "./media-controller-button";
27
27
  export { default as Modal } from "./modal";
28
28
  export { default as NumericStepper } from "./numeric-stepper";
29
+ export { default as Pagination } from "./pagination";
29
30
  export { default as Popover } from "./popover";
30
31
  export { default as ProgressBar } from "./progress-bar";
31
32
  export { default as ProgressIndicator } from "./progress-indicator";
@@ -0,0 +1,74 @@
1
+ import { createMultiStyleConfigHelpers } from "@chakra-ui/react";
2
+ import { anatomy } from "@chakra-ui/theme-tools";
3
+ import { ghostBackground } from "../utils/ghost-utils";
4
+ import { baseText } from "../utils/base-utils";
5
+
6
+ const parts = anatomy("Pagination").parts(
7
+ "listItem",
8
+ "link",
9
+ "activeButton",
10
+ "disabled",
11
+ "icon",
12
+ );
13
+
14
+ const helpers = createMultiStyleConfigHelpers(parts.keys);
15
+
16
+ const config = helpers.defineMultiStyleConfig({
17
+ baseStyle: (props: any) => ({
18
+ activeButton: {
19
+ fontWeight: "bold",
20
+ ...commonStyles,
21
+ ...ghostBackground("active", props),
22
+ _hover: {
23
+ ...ghostBackground("hover", props),
24
+ borderRadius: 50,
25
+ },
26
+ _active: {
27
+ borderRadius: 50,
28
+ ...ghostBackground("active", props),
29
+ },
30
+ },
31
+ disabled: {
32
+ ...commonStyles,
33
+ cursor: "not-allowed",
34
+ pointerEvents: "none",
35
+ boxShadow: "none",
36
+ ...baseText("disabled", props),
37
+ },
38
+ listItem: {
39
+ display: "flex",
40
+ },
41
+ link: {
42
+ ...commonStyles,
43
+ ...ghostBackground("default", props),
44
+ ...baseText("default", props),
45
+ _hover: {
46
+ ...ghostBackground("hover", props),
47
+ borderRadius: 50,
48
+ _disabled: {
49
+ ...baseText("disabled", props),
50
+ },
51
+ },
52
+ _active: {
53
+ borderRadius: 50,
54
+ ...ghostBackground("active", props),
55
+ },
56
+ },
57
+ icon: {
58
+ bottom: "-0.03em !important",
59
+ },
60
+ }),
61
+ });
62
+
63
+ const commonStyles = {
64
+ display: "flex",
65
+ alignItems: "center",
66
+ justifyContent: "center",
67
+ width: 5,
68
+ height: 5,
69
+ backgroundImage: "none",
70
+ borderRadius: 50,
71
+ fontSize: "xs",
72
+ };
73
+
74
+ export default config;