@vygruppen/spor-react 9.9.0 → 9.10.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, Pagination, PasswordInput, PhoneNumberInput, PlayPauseButton, Portal, PressableCard, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioCard, RadioCardGroup, 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-TEDOVPXZ.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, PressableCard, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioCard, RadioCardGroup, 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-WZYWSOJB.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
- "version": "9.9.0",
3
+ "version": "9.10.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "@emotion/react": "^11.10.4",
23
23
  "@emotion/styled": "^11.10.4",
24
24
  "@internationalized/date": "^3.0.1",
25
- "@vygruppen/spor-design-tokens": ">3.4.0",
25
+ "@vygruppen/spor-design-tokens": ">3.6.0",
26
26
  "@vygruppen/spor-icon-react": ">3.6.0",
27
27
  "@vygruppen/spor-loader": ">0.3.1",
28
28
  "awesome-phonenumber": "^5.10.0",
@@ -1,23 +1,15 @@
1
1
  import {
2
+ Box,
2
3
  BoxProps,
3
4
  UseRadioProps,
4
5
  chakra,
5
6
  forwardRef,
6
- useRadio,
7
- useStyleConfig,
7
+ useMultiStyleConfig,
8
8
  } from "@chakra-ui/react";
9
- import { dataAttr } from "@chakra-ui/utils";
10
9
  import React, { useId } from "react";
11
10
 
12
- export type RadioCardProps = UseRadioProps &
13
- BoxProps & {
14
- children: React.ReactNode;
15
- /** Defaults to "base" */
16
- variant: "floating" | "base";
17
- };
18
-
19
11
  /**
20
- * Renders a radio card.
12
+ * Radio cards are used to present a set of options where only one option can be selected.
21
13
  *
22
14
  * The most basic version looks like this:
23
15
  *
@@ -27,6 +19,14 @@ export type RadioCardProps = UseRadioProps &
27
19
  * </RadioCard>
28
20
  * ```
29
21
  *
22
+ * In order to use RadioCard outside a RadioCardGroup, you need to pass the `isChecked` and `onChange` props.
23
+ *
24
+ * ```tsx
25
+ * <RadioCard isChecked={true} onChange={(e) => console.log(e.target.value)}>
26
+ * Content
27
+ * </RadioCard>
28
+ * ```
29
+ *
30
30
  * In order to use RadioCard, you typically want to place these components in a group with several other RadioCards.
31
31
  *
32
32
  * ```tsx
@@ -59,38 +59,47 @@ export type RadioCardProps = UseRadioProps &
59
59
  * ```
60
60
  */
61
61
 
62
- export const RadioCard = forwardRef<RadioCardProps, "div">(
63
- ({ children, variant = "base", ...props }, ref) => {
64
- const { getInputProps, getRadioProps, getRootProps, state } =
65
- useRadio(props);
66
-
67
- const styles = useStyleConfig("RadioCard", { variant });
62
+ export type RadioCardProps = UseRadioProps &
63
+ BoxProps & {
64
+ children: React.ReactNode;
65
+ /** Defaults to "base" */
66
+ variant?: "floating" | "base";
67
+ /** Needs to be defined if RadioCard is used outside RadioCardGroup */
68
+ isChecked?: boolean;
69
+ /** Needs to be defined if RadioCard is used outside RadioCardGroup */
70
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
71
+ };
68
72
 
69
- const input = getInputProps({}, ref);
70
- const radio = getRadioProps();
73
+ export const RadioCard = forwardRef<RadioCardProps, "div">(
74
+ ({ children, variant = "base", isChecked, onChange, ...props }, ref) => {
75
+ const styles = useMultiStyleConfig("RadioCard", { variant });
71
76
 
72
77
  const id = `radio-card-${useId()}`;
73
78
 
79
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
80
+ onChange && onChange(event);
81
+ };
82
+
74
83
  return (
75
- <chakra.label
76
- htmlFor={id}
77
- {...getRootProps()}
78
- aria-label={String(children)}
79
- >
80
- <chakra.input {...input} id={id} disabled={state.isDisabled} />
81
- <chakra.div
82
- __css={styles}
83
- {...radio}
84
- data-checked={dataAttr(state.isChecked)}
85
- data-hover={dataAttr(state.isHovered)}
86
- data-focus={dataAttr(state.isFocused)}
87
- data-active={dataAttr(state.isActive)}
88
- data-disabled={dataAttr(state.isDisabled)}
84
+ <Box as="label" htmlFor={id} aria-label={String(children)} ref={ref}>
85
+ <chakra.input
86
+ type="radio"
87
+ id={id}
88
+ checked={isChecked}
89
+ onChange={handleChange}
90
+ {...props}
91
+ sx={styles.radioInput}
92
+ />
93
+ <Box
89
94
  {...props}
95
+ __css={{
96
+ ...styles.container,
97
+ ...(isChecked && styles.checked),
98
+ }}
90
99
  >
91
100
  {children}
92
- </chakra.div>
93
- </chakra.label>
101
+ </Box>
102
+ </Box>
94
103
  );
95
104
  },
96
105
  );
@@ -4,7 +4,7 @@ import {
4
4
  StackDirection,
5
5
  Stack,
6
6
  } from "@chakra-ui/react";
7
- import React, { Children } from "react";
7
+ import React from "react";
8
8
  import { RadioCard, RadioCardProps } from "./RadioCard";
9
9
 
10
10
  type RadioCardGroupProps = RadioGroupProps & {
@@ -75,17 +75,21 @@ export const RadioCardGroup = ({
75
75
  ...props,
76
76
  });
77
77
 
78
- const group = getRootProps();
78
+ const rootProps = getRootProps();
79
79
 
80
80
  return (
81
- <Stack direction={direction} {...group}>
81
+ <Stack direction={direction} {...rootProps}>
82
82
  {recursiveMap(children, (child: React.ReactElement) => {
83
83
  if (child.type === RadioCard) {
84
- const radio = getRadioProps({ value: child.props.value });
84
+ const radioProps = getRadioProps({ value: child.props.value });
85
85
  const variantValue = variant as "base" | "floating" | undefined;
86
86
  return React.cloneElement(
87
87
  child as React.ReactElement<RadioCardProps>,
88
- { ...radio, variant: variantValue, ...props },
88
+ {
89
+ ...radioProps,
90
+ variant: variantValue,
91
+ ...props,
92
+ },
89
93
  );
90
94
  }
91
95
  return child;
@@ -28,6 +28,7 @@ const config = defineStyleConfig({
28
28
  }),
29
29
  variants: {
30
30
  base: (props) => ({
31
+ cursor: "pointer",
31
32
  ...baseBorder("default", props),
32
33
  _hover: {
33
34
  ...baseBorder("hover", props),
@@ -42,7 +43,7 @@ const config = defineStyleConfig({
42
43
  boxShadow: "sm",
43
44
  _hover: {
44
45
  ...accentBackground("hover", props),
45
- boxShadow: "sm",
46
+ boxShadow: "md",
46
47
  },
47
48
  _active: {
48
49
  ...accentBackground("active", props),
@@ -51,6 +52,7 @@ const config = defineStyleConfig({
51
52
  }),
52
53
  floating: (props) => ({
53
54
  ...floatingBackground("default", props),
55
+ ...floatingBorder("default", props),
54
56
  boxShadow: "sm",
55
57
  _hover: {
56
58
  ...floatingBackground("hover", props),
@@ -58,6 +60,7 @@ const config = defineStyleConfig({
58
60
  boxShadow: "md",
59
61
  },
60
62
  _active: {
63
+ ...floatingBorder("default", props),
61
64
  ...floatingBackground("active", props),
62
65
  boxShadow: "none",
63
66
  },
@@ -1,60 +1,99 @@
1
- import { defineStyleConfig } from "@chakra-ui/react";
1
+ import {
2
+ createMultiStyleConfigHelpers,
3
+ defineStyleConfig,
4
+ } from "@chakra-ui/react";
2
5
  import { baseBackground, baseBorder, baseText } from "../utils/base-utils";
3
6
  import { floatingBackground, floatingBorder } from "../utils/floating-utils";
4
7
  import { focusVisibleStyles } from "../utils/focus-utils";
8
+ import { anatomy } from "@chakra-ui/theme-tools";
9
+ import { outlineBorder } from "../utils/outline-utils";
5
10
 
6
- const config = defineStyleConfig({
11
+ const parts = anatomy("radio-card").parts("container", "checked", "radioInput");
12
+ const helpers = createMultiStyleConfigHelpers(parts.keys);
13
+
14
+ const config = helpers.defineMultiStyleConfig({
7
15
  baseStyle: (props: any) => ({
8
- appearance: "none",
9
- border: "none",
10
- overflow: "hidden",
11
- fontSize: "inherit",
12
- display: "block",
13
- borderRadius: "sm",
14
- ...focusVisibleStyles(props),
15
- _checked: {
16
- outline: "1px solid",
17
- outlineColor: "greenHaze",
18
- ...floatingBackground("active", props),
19
- _hover: {
20
- ...floatingBackground("active", props),
16
+ container: {
17
+ appearance: "none",
18
+ border: "none",
19
+ overflow: "hidden",
20
+ fontSize: "inherit",
21
+ display: "block",
22
+ cursor: "pointer",
23
+ borderRadius: "sm",
24
+ ...focusVisibleStyles(props),
25
+ transitionProperty: "common",
26
+ transitionDuration: "fast",
27
+ _disabled: {
28
+ pointerEvents: "none",
29
+ ...baseBackground("disabled", props),
30
+ ...baseBorder("disabled", props),
31
+ ...baseText("disabled", props),
21
32
  },
22
33
  },
23
- _disabled: {
24
- pointerEvents: "none",
25
- ...baseBackground("disabled", props),
26
- ...baseBorder("disabled", props),
27
- ...baseText("disabled", props),
34
+ checked: {
35
+ outline: "2px solid",
36
+ ...outlineBorder("focus", props),
37
+ ...floatingBackground("active", props),
38
+ },
39
+ radioInput: {
40
+ appearance: "none",
41
+ position: "absolute",
42
+ opacity: 0,
43
+ zIndex: -1,
28
44
  },
29
45
  }),
30
46
  variants: {
31
47
  base: (props) => ({
32
- ...baseBackground("default", props),
33
- ...baseBorder("default", props),
34
- _hover: {
35
- ...baseBackground("hover", props),
36
- ...baseBorder("hover", props),
48
+ container: {
49
+ ...baseText("default", props),
50
+ ...baseBackground("default", props),
51
+ ...baseBorder("default", props),
52
+ _hover: {
53
+ ...baseBackground("hover", props),
54
+ ...baseBorder("hover", props),
55
+ },
56
+ _active: {
57
+ ...baseBackground("active", props),
58
+ ...baseBorder("active", props),
59
+ },
37
60
  },
38
- _active: {
39
- ...baseBackground("active", props),
61
+ checked: {
62
+ _hover: {
63
+ ...baseBorder("hover", props),
64
+ },
65
+ _active: {
66
+ ...baseBackground("active", props),
67
+ ...baseBorder("active", props),
68
+ },
40
69
  },
41
70
  }),
42
71
  floating: (props) => ({
43
- ...floatingBackground("default", props),
44
- boxShadow: "sm",
45
- _hover: {
46
- ...floatingBackground("hover", props),
47
- ...floatingBorder("hover", props),
48
- boxShadow: "md",
49
- },
50
- _active: {
51
- ...floatingBackground("active", props),
52
- ...floatingBorder("active", props),
72
+ container: {
73
+ ...baseText("default", props),
74
+ ...baseBackground("default", props),
75
+ ...floatingBackground("default", props),
76
+ ...floatingBorder("default", props),
77
+ boxShadow: "sm",
78
+ _hover: {
79
+ ...floatingBackground("hover", props),
80
+ ...floatingBorder("hover", props),
81
+ boxShadow: "md",
82
+ },
83
+ _active: {
84
+ ...floatingBackground("active", props),
85
+ ...floatingBorder("active", props),
86
+ },
53
87
  },
54
- _checked: {
88
+ checked: {
89
+ cursor: "normal",
90
+
55
91
  _hover: {
56
- outline: "1px solid",
57
- outlineColor: "silver",
92
+ ...floatingBorder("hover", props),
93
+ },
94
+ _active: {
95
+ ...floatingBackground("active", props),
96
+ ...floatingBorder("active", props),
58
97
  },
59
98
  },
60
99
  }),
@@ -60,8 +60,11 @@ export function baseBorder(state: BorderState, props: StyleFunctionProps) {
60
60
  }
61
61
  case "active": {
62
62
  return {
63
- outline: "2px solid",
64
- outlineColor: mode("base.outline.light", "base.outline.dark")(props),
63
+ outline: "1px solid",
64
+ outlineColor: mode(
65
+ "base.outline.default.light",
66
+ "base.outline.default.dark",
67
+ )(props),
65
68
  };
66
69
  }
67
70
  case "invalid": {
@@ -0,0 +1,26 @@
1
+ import { mode, StyleFunctionProps } from "@chakra-ui/theme-tools";
2
+ import { State, Subset } from "./types";
3
+
4
+ type OutlineBorderState = Subset<State, "default" | "error" | "focus">;
5
+ export function outlineBorder(
6
+ state: OutlineBorderState,
7
+ props: StyleFunctionProps,
8
+ ) {
9
+ switch (state) {
10
+ case "error":
11
+ return {
12
+ outlineColor: mode("outline.error.light", "outline.error.dark")(props),
13
+ };
14
+ case "focus":
15
+ return {
16
+ outlineColor: mode("outline.focus.light", "outline.focus.dark")(props),
17
+ };
18
+ default:
19
+ return {
20
+ outlineColor: mode(
21
+ "outline.default.light",
22
+ "outline.default.dark",
23
+ )(props),
24
+ };
25
+ }
26
+ }
@@ -5,7 +5,9 @@ export type State =
5
5
  | "focus"
6
6
  | "selected"
7
7
  | "invalid"
8
- | "disabled";
8
+ | "disabled"
9
+ | "error"
10
+ | "focus";
9
11
 
10
12
  // Helper type to extract subset of union types
11
13
  export type Subset<T, U extends T> = T extends U ? T : never;