@vygruppen/spor-react 3.3.0 → 3.3.1

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, 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, 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, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, NumericStepper, PasswordInput, PhoneNumberInput, PlayPauseButton, Popover, PopoverAnchor, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger, PopoverWizardBody, ProgressBar, ProgressLoader, Radio, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, SimplePopover, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tr, TravelTag, VStack, VyLogo, WizardPopover, Wrap, WrapItem, createTexts, extendTheme, fontFaces, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useTheme, useToast, useToken, useTranslation } from './chunk-INCE2TKZ.mjs';
1
+ export { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, AttachedInputs, Badge, Box, 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, 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, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, NumericStepper, PasswordInput, PhoneNumberInput, PlayPauseButton, Popover, PopoverAnchor, PopoverArrow, PopoverBody, PopoverCloseButton, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger, PopoverWizardBody, ProgressBar, ProgressLoader, Radio, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, SimplePopover, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tr, TravelTag, VStack, VyLogo, WizardPopover, Wrap, WrapItem, createTexts, extendTheme, fontFaces, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useTheme, useToast, useToken, useTranslation } from './chunk-5JEY3QEF.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -9,11 +9,13 @@ import {
9
9
  import { CalendarGrid } from "./CalendarGrid";
10
10
  import { CalendarHeader } from "./CalendarHeader";
11
11
  import { useCurrentLocale } from "./utils";
12
+ import { createTexts, useTranslation } from "../i18n";
12
13
 
13
14
  type CalendarProps = ReactAriaCalendarProps<DateValue> & {
14
15
  showYearNavigation?: boolean;
15
16
  };
16
17
  export function Calendar({ showYearNavigation, ...props }: CalendarProps) {
18
+ const { t } = useTranslation();
17
19
  const locale = useCurrentLocale();
18
20
  const state = useCalendarState({
19
21
  ...props,
@@ -22,11 +24,24 @@ export function Calendar({ showYearNavigation, ...props }: CalendarProps) {
22
24
  });
23
25
 
24
26
  const { calendarProps } = useCalendar(props, state);
27
+ const calendarAriaLabel = calendarProps["aria-label"];
28
+
29
+ const ariaLabel =
30
+ t(texts.calendar) + (calendarAriaLabel ? ` ${calendarAriaLabel}` : "");
25
31
 
26
32
  return (
27
- <Box {...calendarProps}>
33
+ <Box {...calendarProps} aria-label={ariaLabel}>
28
34
  <CalendarHeader state={state} showYearNavigation={showYearNavigation} />
29
35
  <CalendarGrid state={state} />
30
36
  </Box>
31
37
  );
32
38
  }
39
+
40
+ const texts = createTexts({
41
+ calendar: {
42
+ nb: "Kalender",
43
+ nn: "Kalender",
44
+ sv: "Kalender",
45
+ en: "Calendar",
46
+ },
47
+ });
@@ -16,8 +16,14 @@ type CalendarCellProps = {
16
16
  };
17
17
  export function CalendarCell({ state, date, currentMonth }: CalendarCellProps) {
18
18
  const ref = useRef(null);
19
- const { cellProps, buttonProps, isSelected, isDisabled, isUnavailable } =
20
- useCalendarCell({ date }, state, ref);
19
+ const {
20
+ cellProps,
21
+ buttonProps,
22
+ isSelected,
23
+ isDisabled,
24
+ isUnavailable,
25
+ isOutsideVisibleRange,
26
+ } = useCalendarCell({ date }, state, ref);
21
27
 
22
28
  const isOutsideMonth = !isSameMonth(currentMonth, date);
23
29
  const styles = useMultiStyleConfig("Datepicker", {});
@@ -35,7 +41,7 @@ export function CalendarCell({ state, date, currentMonth }: CalendarCellProps) {
35
41
  if (isOutsideMonth) {
36
42
  stateProps["data-unavailable"] = true;
37
43
  }
38
-
44
+
39
45
  return (
40
46
  <Box
41
47
  as="td"
@@ -65,6 +71,7 @@ export function CalendarCell({ state, date, currentMonth }: CalendarCellProps) {
65
71
  {...stateProps}
66
72
  ref={ref}
67
73
  sx={styles.dateCell}
74
+ hidden={isOutsideVisibleRange}
68
75
  width="100%"
69
76
  >
70
77
  {date.day}
@@ -1,30 +1,36 @@
1
- import { Box, PopoverAnchor, useMultiStyleConfig } from "@chakra-ui/react";
1
+ import {
2
+ Box,
3
+ PopoverAnchor,
4
+ useMultiStyleConfig,
5
+ forwardRef,
6
+ As,
7
+ } from "@chakra-ui/react";
2
8
  import { CalendarOutline24Icon } from "@vygruppen/spor-icon-react";
3
- import React, { useRef } from "react";
4
- import { AriaButtonProps, useButton } from "react-aria";
9
+ import React from "react";
10
+ import { AriaButtonProps } from "react-aria";
5
11
  import { createTexts, useTranslation } from "..";
6
12
 
7
13
  type CalendarTriggerButtonProps = AriaButtonProps<"button">;
8
- export const CalendarTriggerButton = (props: CalendarTriggerButtonProps) => {
9
- const { t } = useTranslation();
10
- const styles = useMultiStyleConfig("Datepicker", {});
11
- const ref = useRef(null);
12
- const { buttonProps } = useButton(props, ref);
13
- return (
14
- <PopoverAnchor>
15
- <Box
16
- ref={ref}
17
- as="button"
18
- type="button"
19
- aria-label={t(texts.openCalendar)}
20
- sx={styles.calendarTriggerButton}
21
- {...(buttonProps as any)}
22
- >
23
- <CalendarOutline24Icon />
24
- </Box>
25
- </PopoverAnchor>
26
- );
27
- };
14
+ export const CalendarTriggerButton = forwardRef<CalendarTriggerButtonProps, As>(
15
+ ({ ...buttonProps }, ref) => {
16
+ const { t } = useTranslation();
17
+ const styles = useMultiStyleConfig("Datepicker", {});
18
+
19
+ return (
20
+ <PopoverAnchor>
21
+ <Box
22
+ ref={ref}
23
+ as="button"
24
+ aria-label={t(texts.openCalendar)}
25
+ sx={styles.calendarTriggerButton}
26
+ {...buttonProps}
27
+ >
28
+ <CalendarOutline24Icon />
29
+ </Box>
30
+ </PopoverAnchor>
31
+ );
32
+ }
33
+ );
28
34
 
29
35
  const texts = createTexts({
30
36
  openCalendar: {
@@ -1,12 +1,14 @@
1
1
  import {
2
2
  Box,
3
3
  BoxProps,
4
+ FocusLock,
4
5
  InputGroup,
5
6
  Popover,
6
7
  PopoverAnchor,
7
8
  PopoverArrow,
8
9
  PopoverBody,
9
10
  PopoverContent,
11
+ PopoverTrigger,
10
12
  Portal,
11
13
  ResponsiveValue,
12
14
  useBreakpointValue,
@@ -17,7 +19,12 @@ import { DateValue } from "@internationalized/date";
17
19
  import { useDatePickerState } from "@react-stately/datepicker";
18
20
  import { CalendarOutline24Icon } from "@vygruppen/spor-icon-react";
19
21
  import React, { forwardRef, useRef } from "react";
20
- import { AriaDatePickerProps, I18nProvider, useDatePicker } from "react-aria";
22
+ import {
23
+ AriaDatePickerProps,
24
+ CalendarProps,
25
+ I18nProvider,
26
+ useDatePicker,
27
+ } from "react-aria";
21
28
  import { FormErrorMessage } from "..";
22
29
  import { Calendar } from "./Calendar";
23
30
  import { CalendarTriggerButton } from "./CalendarTriggerButton";
@@ -30,6 +37,7 @@ type DatePickerProps = AriaDatePickerProps<DateValue> &
30
37
  variant: ResponsiveValue<"simple" | "with-trigger">;
31
38
  name?: string;
32
39
  showYearNavigation?: boolean;
40
+ withPortal?: boolean;
33
41
  };
34
42
  /**
35
43
  * A date picker component.
@@ -47,6 +55,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
47
55
  errorMessage,
48
56
  minHeight,
49
57
  showYearNavigation,
58
+ withPortal = true,
50
59
  width = "auto",
51
60
  ...props
52
61
  },
@@ -76,23 +85,13 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
76
85
  ref as React.MutableRefObject<HTMLDivElement>
77
86
  );
78
87
 
88
+ const styles = useMultiStyleConfig("Datepicker", {});
89
+ const locale = useCurrentLocale();
90
+
79
91
  const responsiveVariant =
80
92
  useBreakpointValue(typeof variant === "string" ? [variant] : variant) ??
81
93
  "simple";
82
-
83
- const locale = useCurrentLocale();
84
-
85
- const handleEnterClick = (e: React.KeyboardEvent) => {
86
- if (
87
- responsiveVariant === "simple" &&
88
- e.key === "Enter" &&
89
- !state.isOpen
90
- ) {
91
- // Don't submit the form
92
- e.stopPropagation();
93
- state.setOpen(true);
94
- }
95
- };
94
+ const hasTrigger = responsiveVariant === "with-trigger";
96
95
 
97
96
  const onFieldClick = () => {
98
97
  if (!hasTrigger) {
@@ -100,9 +99,19 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
100
99
  }
101
100
  };
102
101
 
103
- const hasTrigger = responsiveVariant === "with-trigger";
104
-
105
- const styles = useMultiStyleConfig("Datepicker", {});
102
+ const popoverContent = (
103
+ <PopoverContent color="darkGrey" boxShadow="md" sx={styles.calendar}>
104
+ <PopoverArrow sx={styles.arrow} />
105
+ <PopoverBody>
106
+ <FocusLock>
107
+ <Calendar
108
+ {...calendarProps}
109
+ showYearNavigation={showYearNavigation}
110
+ />
111
+ </FocusLock>
112
+ </PopoverBody>
113
+ </PopoverContent>
114
+ );
106
115
 
107
116
  return (
108
117
  <I18nProvider locale={locale}>
@@ -115,18 +124,14 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
115
124
  <Popover
116
125
  {...dialogProps}
117
126
  isOpen={state.isOpen}
118
- onClose={state.close}
119
127
  onOpen={state.open}
120
- closeOnBlur
121
- closeOnEsc
122
- returnFocusOnClose
128
+ onClose={state.close}
123
129
  >
124
130
  <InputGroup {...groupProps} display="inline-flex">
125
131
  <PopoverAnchor>
126
132
  <StyledField
127
133
  variant={responsiveVariant}
128
134
  onClick={onFieldClick}
129
- onKeyPress={handleEnterClick}
130
135
  paddingX={3}
131
136
  minHeight={minHeight}
132
137
  >
@@ -137,33 +142,24 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
137
142
  label={props.label}
138
143
  labelProps={labelProps}
139
144
  name={props.name}
140
- ref={ref}
145
+ ref={hasTrigger ? undefined : ref}
141
146
  {...fieldProps}
142
147
  />
143
148
  </StyledField>
144
149
  </PopoverAnchor>
145
- {hasTrigger && <CalendarTriggerButton {...buttonProps} />}
150
+ {hasTrigger && (
151
+ <PopoverTrigger>
152
+ <CalendarTriggerButton ref={ref} {...buttonProps} />
153
+ </PopoverTrigger>
154
+ )}
146
155
  </InputGroup>
147
156
  <FormErrorMessage {...errorMessageProps}>
148
157
  {errorMessage}
149
158
  </FormErrorMessage>
150
- {state.isOpen && !props.isDisabled && (
151
- <Portal>
152
- <PopoverContent
153
- color="darkGrey"
154
- boxShadow="md"
155
- sx={styles.calendar}
156
- >
157
- <PopoverArrow sx={styles.arrow} />
158
- <PopoverBody>
159
- <Calendar
160
- {...calendarProps}
161
- showYearNavigation={showYearNavigation}
162
- />
163
- </PopoverBody>
164
- </PopoverContent>
165
- </Portal>
159
+ {state.isOpen && !props.isDisabled && withPortal && (
160
+ <Portal>{popoverContent}</Portal>
166
161
  )}
162
+ {state.isOpen && !props.isDisabled && !withPortal && popoverContent}
167
163
  </Popover>
168
164
  </Box>
169
165
  </I18nProvider>
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  Box,
3
3
  BoxProps,
4
+ FocusLock,
4
5
  FormLabel,
5
6
  InputGroup,
6
7
  Popover,
@@ -8,6 +9,7 @@ import {
8
9
  PopoverArrow,
9
10
  PopoverBody,
10
11
  PopoverContent,
12
+ PopoverTrigger,
11
13
  Portal,
12
14
  ResponsiveValue,
13
15
  useBreakpointValue,
@@ -36,6 +38,7 @@ type DateRangePickerProps = AriaDateRangePickerProps<DateValue> &
36
38
  endLabel?: string;
37
39
  endName?: string;
38
40
  variant: ResponsiveValue<"simple" | "with-trigger">;
41
+ withPortal?: boolean;
39
42
  };
40
43
  /**
41
44
  * A date range picker component.
@@ -51,6 +54,7 @@ export function DateRangePicker({
51
54
  minHeight,
52
55
  startName,
53
56
  endName,
57
+ withPortal = true,
54
58
  ...props
55
59
  }: DateRangePickerProps) {
56
60
  const formControlProps = useFormControlContext();
@@ -96,6 +100,17 @@ export function DateRangePicker({
96
100
 
97
101
  const hasTrigger = responsiveVariant === "with-trigger";
98
102
 
103
+ const popoverContent = (
104
+ <PopoverContent sx={styles.calendar} boxShadow="md" maxWidth="none">
105
+ <PopoverArrow sx={styles.arrow} />
106
+ <PopoverBody>
107
+ <FocusLock>
108
+ <RangeCalendar {...calendarProps} />
109
+ </FocusLock>
110
+ </PopoverBody>
111
+ </PopoverContent>
112
+ );
113
+
99
114
  return (
100
115
  <I18nProvider locale={locale}>
101
116
  <Box position="relative" display="inline-flex" flexDirection="column">
@@ -107,17 +122,10 @@ export function DateRangePicker({
107
122
  <Popover
108
123
  {...dialogProps}
109
124
  isOpen={state.isOpen}
110
- onClose={() => state.setOpen(false)}
111
- closeOnBlur
112
- closeOnEsc
113
- returnFocusOnClose
125
+ onOpen={state.open}
126
+ onClose={state.close}
114
127
  >
115
- <InputGroup
116
- {...groupProps}
117
- ref={ref}
118
- width="auto"
119
- display="inline-flex"
120
- >
128
+ <InputGroup {...groupProps} width="auto" display="inline-flex">
121
129
  <PopoverAnchor>
122
130
  <StyledField
123
131
  alignItems="center"
@@ -134,6 +142,7 @@ export function DateRangePicker({
134
142
  {...startFieldProps}
135
143
  name={startName}
136
144
  label={props.startLabel}
145
+ ref={hasTrigger ? undefined : ref}
137
146
  labelProps={labelProps}
138
147
  />
139
148
  <Box as="span" aria-hidden="true" px="2">
@@ -147,22 +156,14 @@ export function DateRangePicker({
147
156
  />
148
157
  </StyledField>
149
158
  </PopoverAnchor>
150
- {hasTrigger && <CalendarTriggerButton {...buttonProps} />}
159
+ {hasTrigger && (
160
+ <PopoverTrigger>
161
+ <CalendarTriggerButton ref={ref} {...buttonProps} />
162
+ </PopoverTrigger>
163
+ )}
151
164
  </InputGroup>
152
- {state.isOpen && (
153
- <Portal>
154
- <PopoverContent
155
- sx={styles.calendar}
156
- boxShadow="md"
157
- maxWidth="none"
158
- >
159
- <PopoverArrow sx={styles.arrow} />
160
- <PopoverBody>
161
- <RangeCalendar {...calendarProps} />
162
- </PopoverBody>
163
- </PopoverContent>
164
- </Portal>
165
- )}
165
+ {state.isOpen && withPortal && <Portal>{popoverContent}</Portal>}
166
+ {state.isOpen && !withPortal && popoverContent}
166
167
  </Popover>
167
168
  </Box>
168
169
  </I18nProvider>
@@ -2,7 +2,6 @@ import { Box, useMultiStyleConfig } from "@chakra-ui/react";
2
2
  import React, { RefObject, forwardRef, useRef } from "react";
3
3
  import { useDateSegment } from "react-aria";
4
4
  import { DateFieldState, DateSegment } from "react-stately";
5
- import { colors } from "../theme/foundations";
6
5
 
7
6
  type DateTimeSegmentProps = {
8
7
  segment: DateSegment;
@@ -38,13 +37,12 @@ export const DateTimeSegment = forwardRef<HTMLDivElement, DateTimeSegmentProps>(
38
37
  ...segmentProps.style,
39
38
  fontVariantNumeric: "tabular-nums",
40
39
  boxSizing: "content-box",
41
- color: colors.darkGrey,
42
40
  }}
43
41
  paddingX="1px"
44
42
  textAlign="end"
45
43
  outline="none"
46
44
  borderRadius="xs"
47
- fontSize="mobile.md"
45
+ fontSize={["mobile.sm", "desktop.sm"]}
48
46
  sx={styles.dateTimeSegment}
49
47
  _focus={{
50
48
  backgroundColor: "darkTeal",
@@ -9,15 +9,15 @@ export const useCurrentLocale = () => {
9
9
  const { language } = useTranslation();
10
10
  switch (language) {
11
11
  case "nb":
12
- return "no";
12
+ return "nb-NO";
13
13
  case "nn":
14
- return "no";
14
+ return "nb-NO";
15
15
  case "sv":
16
- return "sv";
16
+ return "sv-SE";
17
17
  case "en":
18
18
  return "en-GB";
19
19
  default:
20
- return "no";
20
+ return "nb-NO";
21
21
  }
22
22
  };
23
23
 
@@ -74,7 +74,7 @@ const config = helpers.defineMultiStyleConfig({
74
74
  },
75
75
  dateTimeSegment: {
76
76
  color: mode(
77
- props.isEditable ? "darkGrey" : "dimGrey",
77
+ "darkGrey",
78
78
  props.isPlaceholder ? "whiteAlpha.400" : "white"
79
79
  )(props),
80
80
  },
@@ -125,11 +125,11 @@ const config = helpers.defineMultiStyleConfig({
125
125
  },
126
126
  },
127
127
  arrow: {
128
- [$arrowBackground.variable]: mode("white", colors.night)(props)
128
+ [$arrowBackground.variable]: mode("white", colors.night)(props),
129
129
  },
130
130
  calendar: {
131
131
  backgroundColor: mode("white", "night")(props),
132
- color: mode("darkGrey", "white")(props)
132
+ color: mode("darkGrey", "white")(props),
133
133
  },
134
134
  weekdays: {
135
135
  color: mode("darkGrey", "white")(props),
@@ -197,6 +197,13 @@ const config = helpers.defineMultiStyleConfig({
197
197
  borderWidth: 1,
198
198
  borderColor: mode("osloGrey", "dimGrey")(props),
199
199
  }),
200
+ _focus: {
201
+ outline: "none",
202
+ boxShadow: getBoxShadowString({
203
+ borderWidth: 2,
204
+ borderColor: mode("greenHaze", "azure")(props),
205
+ }),
206
+ },
200
207
  },
201
208
  "&[data-unavailable]": {
202
209
  pointerEvents: "none",