@vygruppen/spor-react 9.13.1 → 9.13.3
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +14 -0
- package/dist/{CountryCodeSelect-XKJDLCJZ.mjs → CountryCodeSelect-7VDV2T5R.mjs} +1 -1
- package/dist/{chunk-NMEIV2NI.mjs → chunk-Y56HXMZC.mjs} +113 -79
- package/dist/index.d.mts +83 -48
- package/dist/index.d.ts +83 -48
- package/dist/index.js +112 -79
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/button/Button.tsx +1 -0
- package/src/layout/RadioCard.tsx +48 -33
- package/src/layout/RadioCardGroup.tsx +9 -9
- package/src/modal/FullScreenDrawer.tsx +5 -1
- package/src/modal/SimpleDrawer.tsx +8 -1
- package/src/theme/components/radio-card.ts +41 -21
- package/src/theme/font-faces.ts +3 -0
package/src/layout/RadioCard.tsx
CHANGED
@@ -5,7 +5,7 @@ import {
|
|
5
5
|
forwardRef,
|
6
6
|
useMultiStyleConfig,
|
7
7
|
} from "@chakra-ui/react";
|
8
|
-
import React, { useContext, useEffect, useId } from "react";
|
8
|
+
import React, { useContext, useEffect, useId, useState } from "react";
|
9
9
|
import { RadioCardGroupContext } from "./RadioCardGroup";
|
10
10
|
|
11
11
|
/**
|
@@ -32,13 +32,16 @@ import { RadioCardGroupContext } from "./RadioCardGroup";
|
|
32
32
|
*/
|
33
33
|
|
34
34
|
export type RadioCardProps = BoxProps & {
|
35
|
+
/** The value that will be passed to the `RadioCardGroup`'s `onChange` function if this `RadioCard` is selected.. */
|
35
36
|
value: string;
|
37
|
+
/** The content of the RadioCard. */
|
36
38
|
children: React.ReactNode;
|
39
|
+
/** Determines if the RadioCard is disabled. */
|
37
40
|
isDisabled?: boolean;
|
38
41
|
};
|
39
42
|
|
40
43
|
export const RadioCard = forwardRef(
|
41
|
-
({ children, value
|
44
|
+
({ children, value, isDisabled, ...props }: RadioCardProps, ref) => {
|
42
45
|
const context = useContext(RadioCardGroupContext);
|
43
46
|
|
44
47
|
if (!context) {
|
@@ -51,57 +54,69 @@ export const RadioCard = forwardRef(
|
|
51
54
|
|
52
55
|
const styles = useMultiStyleConfig("RadioCard", { variant });
|
53
56
|
|
57
|
+
const [isKeyboardUser, setKeyboardUser] = useState(false);
|
58
|
+
const [isFocused, setFocus] = useState(false);
|
59
|
+
|
54
60
|
const isChecked = selectedValue === value;
|
55
61
|
|
56
|
-
|
62
|
+
useEffect(() => {
|
63
|
+
const handleMouseDown = () => setKeyboardUser(false);
|
64
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
65
|
+
if (event.key === " ") {
|
66
|
+
setFocus(false);
|
67
|
+
} else {
|
68
|
+
setKeyboardUser(true);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
window.addEventListener("mousedown", handleMouseDown);
|
73
|
+
window.addEventListener("keydown", handleKeyDown);
|
74
|
+
|
75
|
+
return () => {
|
76
|
+
window.removeEventListener("mousedown", handleMouseDown);
|
77
|
+
window.removeEventListener("keydown", handleKeyDown);
|
78
|
+
};
|
79
|
+
}, []);
|
57
80
|
|
58
81
|
useEffect(() => {
|
59
|
-
if (
|
60
|
-
|
82
|
+
if (isKeyboardUser && isChecked) {
|
83
|
+
setFocus(true);
|
84
|
+
} else {
|
85
|
+
setFocus(false);
|
61
86
|
}
|
62
|
-
}, [isChecked]);
|
87
|
+
}, [isKeyboardUser, isChecked]);
|
63
88
|
|
64
|
-
const
|
65
|
-
if (event.key === "Enter" || event.key === " ") {
|
66
|
-
onChange(value);
|
67
|
-
}
|
68
|
-
if (
|
69
|
-
event.key === "ArrowRight" ||
|
70
|
-
event.key === "ArrowDown" ||
|
71
|
-
event.key === "ArrowLeft" ||
|
72
|
-
event.key === "ArrowUp"
|
73
|
-
) {
|
74
|
-
const nextRadioCard = event.currentTarget
|
75
|
-
.nextElementSibling as HTMLElement;
|
76
|
-
if (nextRadioCard) {
|
77
|
-
nextRadioCard.focus();
|
78
|
-
}
|
79
|
-
}
|
80
|
-
};
|
89
|
+
const inputId = `radio-card-${useId()}`;
|
81
90
|
|
82
91
|
return (
|
83
|
-
<Box
|
92
|
+
<Box
|
93
|
+
onFocus={() => isKeyboardUser && setFocus(true)}
|
94
|
+
onBlur={() => setFocus(false)}
|
95
|
+
>
|
84
96
|
<chakra.input
|
85
97
|
type="radio"
|
86
|
-
id={
|
87
|
-
ref={ref}
|
88
|
-
value={value}
|
98
|
+
id={inputId}
|
89
99
|
name={name}
|
100
|
+
ref={ref}
|
90
101
|
checked={isChecked}
|
91
102
|
onChange={() => onChange(value)}
|
92
103
|
disabled={isDisabled}
|
93
104
|
__css={styles.radioInput}
|
94
105
|
/>
|
95
106
|
<Box
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
role="radio"
|
107
|
+
as="label"
|
108
|
+
name={name}
|
109
|
+
htmlFor={inputId}
|
100
110
|
aria-checked={isChecked}
|
101
|
-
aria-labelledby={radioCardId}
|
102
|
-
__css={{ ...styles.container, ...(isChecked && styles.checked) }}
|
103
111
|
data-checked={isChecked}
|
104
112
|
data-disabled={isDisabled}
|
113
|
+
{...props}
|
114
|
+
__css={{
|
115
|
+
...styles.container,
|
116
|
+
...(isChecked && styles.checked),
|
117
|
+
...(isFocused && !isChecked && styles.focused),
|
118
|
+
...(isChecked && isFocused && styles.focusedChecked),
|
119
|
+
}}
|
105
120
|
>
|
106
121
|
{children}
|
107
122
|
</Box>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { BoxProps, Stack } from "@chakra-ui/react";
|
2
2
|
import React, { useState } from "react";
|
3
3
|
import { FormLabel } from "../input";
|
4
|
-
import { RadioCard } from "./RadioCard";
|
5
4
|
|
6
5
|
/**
|
7
6
|
* RadioCardGroupContext is used to pass down the state and handlers to the RadioCard components.
|
@@ -15,18 +14,26 @@ type RadioGroupContextProps = {
|
|
15
14
|
onChange: (value: string) => void;
|
16
15
|
variant?: "base" | "floating";
|
17
16
|
defaultValue?: string;
|
17
|
+
value?: string;
|
18
18
|
};
|
19
19
|
|
20
20
|
export const RadioCardGroupContext =
|
21
21
|
React.createContext<RadioGroupContextProps | null>(null);
|
22
22
|
|
23
23
|
type RadioCardGroupProps = BoxProps & {
|
24
|
+
/** A string that will be assigned as the name attribute to all RadioCard components within the group. */
|
24
25
|
name: string;
|
26
|
+
/** The RadioCard components that make up the group. */
|
25
27
|
children: React.ReactNode;
|
28
|
+
/** Optional. Determines the style of the RadioCard. Can be either "base" or "floating". */
|
26
29
|
variant?: "base" | "floating";
|
30
|
+
/** Optional. Determines the direction of the group. Can be either "row" or "column". */
|
27
31
|
direction?: "row" | "column";
|
32
|
+
/** Optional. A label for the group. */
|
28
33
|
groupLabel?: string;
|
34
|
+
/** Optional. The default value of the RadioCard group. */
|
29
35
|
defaultValue?: string;
|
36
|
+
/** Optional. A function that will be called when the selected value changes. The function receives the value of the selected RadioCard. */
|
30
37
|
onChange?: (value: string) => void;
|
31
38
|
};
|
32
39
|
|
@@ -59,14 +66,7 @@ export const RadioCardGroup: React.FC<RadioCardGroupProps> = ({
|
|
59
66
|
defaultValue: defaultValue || "",
|
60
67
|
}}
|
61
68
|
>
|
62
|
-
<Stack
|
63
|
-
as="fieldset"
|
64
|
-
direction={direction}
|
65
|
-
aria-labelledby={groupLabel || name}
|
66
|
-
role="radiogroup"
|
67
|
-
tabIndex={0}
|
68
|
-
{...props}
|
69
|
-
>
|
69
|
+
<Stack as="fieldset" direction={direction} {...props}>
|
70
70
|
{groupLabel && (
|
71
71
|
<FormLabel as="legend" id={groupLabel}>
|
72
72
|
{groupLabel}
|
@@ -15,6 +15,7 @@ import React, { useEffect, useState } from "react";
|
|
15
15
|
import { Button, IconButton } from "../button";
|
16
16
|
import { createTexts, useTranslation } from "../i18n";
|
17
17
|
import { Drawer } from "./Drawer";
|
18
|
+
import { DrawerBodyProps } from "./SimpleDrawer";
|
18
19
|
|
19
20
|
type DrawerPlacement = "top" | "right" | "bottom" | "left";
|
20
21
|
|
@@ -33,6 +34,8 @@ type FullScreenDrawerProps = {
|
|
33
34
|
isOpen: boolean;
|
34
35
|
/** Function that will be called when the drawer closes */
|
35
36
|
onClose: () => void;
|
37
|
+
/** Props for drawer body */
|
38
|
+
body?: DrawerBodyProps;
|
36
39
|
};
|
37
40
|
|
38
41
|
export const FullScreenDrawer = ({
|
@@ -43,6 +46,7 @@ export const FullScreenDrawer = ({
|
|
43
46
|
rightButton = <DrawerCloseButton />,
|
44
47
|
isOpen,
|
45
48
|
onClose,
|
49
|
+
body,
|
46
50
|
}: FullScreenDrawerProps) => {
|
47
51
|
const [isContentBoxScrolled, setContentBoxScrolled] = useState(false);
|
48
52
|
|
@@ -75,7 +79,7 @@ export const FullScreenDrawer = ({
|
|
75
79
|
leftButton={leftButton}
|
76
80
|
rightButton={rightButton}
|
77
81
|
/>
|
78
|
-
<DrawerBody overflow="auto" onScroll={onContentScroll}>
|
82
|
+
<DrawerBody overflow="auto" onScroll={onContentScroll} {...body}>
|
79
83
|
{children}
|
80
84
|
</DrawerBody>
|
81
85
|
</DrawerContent>
|
@@ -8,12 +8,18 @@ import {
|
|
8
8
|
DrawerOverlay,
|
9
9
|
} from "./Drawer";
|
10
10
|
|
11
|
+
export type DrawerBodyProps = {
|
12
|
+
id?: string;
|
13
|
+
};
|
14
|
+
|
11
15
|
export type SimpleDrawerProps = {
|
12
16
|
children: React.ReactNode;
|
13
17
|
title?: React.ReactNode;
|
14
18
|
placement: "top" | "right" | "bottom" | "left";
|
15
19
|
isOpen: boolean;
|
16
20
|
onClose: () => void;
|
21
|
+
/** Props for drawer body */
|
22
|
+
body?: DrawerBodyProps;
|
17
23
|
};
|
18
24
|
/** A very basic drawer component that's easy to use
|
19
25
|
*
|
@@ -29,6 +35,7 @@ export const SimpleDrawer = ({
|
|
29
35
|
placement,
|
30
36
|
children,
|
31
37
|
title,
|
38
|
+
body,
|
32
39
|
...props
|
33
40
|
}: SimpleDrawerProps) => {
|
34
41
|
return (
|
@@ -37,7 +44,7 @@ export const SimpleDrawer = ({
|
|
37
44
|
<DrawerContent>
|
38
45
|
<DrawerCloseButton />
|
39
46
|
{title && <DrawerHeader>{title}</DrawerHeader>}
|
40
|
-
<DrawerBody>{children}</DrawerBody>
|
47
|
+
<DrawerBody {...body}>{children}</DrawerBody>
|
41
48
|
</DrawerContent>
|
42
49
|
</Drawer>
|
43
50
|
);
|
@@ -1,25 +1,29 @@
|
|
1
1
|
import { createMultiStyleConfigHelpers } from "@chakra-ui/react";
|
2
2
|
import { baseBackground, baseBorder, baseText } from "../utils/base-utils";
|
3
3
|
import { floatingBackground, floatingBorder } from "../utils/floating-utils";
|
4
|
-
import {
|
5
|
-
import { anatomy, mode } from "@chakra-ui/theme-tools";
|
4
|
+
import { anatomy } from "@chakra-ui/theme-tools";
|
6
5
|
import { outlineBorder } from "../utils/outline-utils";
|
7
6
|
|
8
|
-
const parts = anatomy("radio-card").parts(
|
7
|
+
const parts = anatomy("radio-card").parts(
|
8
|
+
"container",
|
9
|
+
"checked",
|
10
|
+
"radioInput",
|
11
|
+
"focused",
|
12
|
+
"focusedChecked",
|
13
|
+
);
|
9
14
|
const helpers = createMultiStyleConfigHelpers(parts.keys);
|
10
15
|
|
11
16
|
const config = helpers.defineMultiStyleConfig({
|
12
17
|
baseStyle: (props: any) => ({
|
13
18
|
container: {
|
14
|
-
border: "none",
|
15
19
|
overflow: "hidden",
|
16
20
|
fontSize: "inherit",
|
17
21
|
display: "block",
|
18
22
|
cursor: "pointer",
|
19
23
|
borderRadius: "sm",
|
20
|
-
...focusVisibleStyles(props),
|
21
24
|
transitionProperty: "common",
|
22
25
|
transitionDuration: "fast",
|
26
|
+
|
23
27
|
_disabled: {
|
24
28
|
pointerEvents: "none",
|
25
29
|
...baseBackground("disabled", props),
|
@@ -53,9 +57,6 @@ const config = helpers.defineMultiStyleConfig({
|
|
53
57
|
...baseBackground("active", props),
|
54
58
|
...baseBorder("active", props),
|
55
59
|
},
|
56
|
-
_focus: {
|
57
|
-
...outlineBorder("focus", props),
|
58
|
-
},
|
59
60
|
},
|
60
61
|
checked: {
|
61
62
|
_hover: {
|
@@ -65,11 +66,22 @@ const config = helpers.defineMultiStyleConfig({
|
|
65
66
|
...baseBackground("active", props),
|
66
67
|
...baseBorder("active", props),
|
67
68
|
},
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
},
|
70
|
+
focusedChecked: {
|
71
|
+
outline: "4px solid",
|
72
|
+
outlineStyle: "double",
|
73
|
+
...outlineBorder("focus", props),
|
74
|
+
outlineOffset: "-1px",
|
75
|
+
},
|
76
|
+
focused: {
|
77
|
+
outline: "2px solid",
|
78
|
+
...outlineBorder("focus", props),
|
79
|
+
outlineOffset: "1px",
|
80
|
+
boxShadow: `inset 0 0 0 1px rgba(0, 0, 0, 0.40)`,
|
81
|
+
_hover: {
|
82
|
+
...baseBorder("hover", props),
|
83
|
+
boxShadow: "none",
|
84
|
+
outlineOffset: "0px",
|
73
85
|
},
|
74
86
|
},
|
75
87
|
}),
|
@@ -87,9 +99,6 @@ const config = helpers.defineMultiStyleConfig({
|
|
87
99
|
...floatingBackground("active", props),
|
88
100
|
...floatingBorder("active", props),
|
89
101
|
},
|
90
|
-
_focus: {
|
91
|
-
...outlineBorder("focus", props),
|
92
|
-
},
|
93
102
|
},
|
94
103
|
checked: {
|
95
104
|
_hover: {
|
@@ -100,11 +109,22 @@ const config = helpers.defineMultiStyleConfig({
|
|
100
109
|
...floatingBackground("active", props),
|
101
110
|
...floatingBorder("active", props),
|
102
111
|
},
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
112
|
+
},
|
113
|
+
focusedChecked: {
|
114
|
+
outline: "4px solid",
|
115
|
+
outlineStyle: "double",
|
116
|
+
...outlineBorder("focus", props),
|
117
|
+
outlineOffset: "-1px",
|
118
|
+
},
|
119
|
+
focused: {
|
120
|
+
outline: "2px solid",
|
121
|
+
...outlineBorder("focus", props),
|
122
|
+
outlineOffset: "1px",
|
123
|
+
boxShadow: `inset 0 0 0 1px rgba(0, 0, 0, 0.10)`,
|
124
|
+
_hover: {
|
125
|
+
...floatingBorder("hover", props),
|
126
|
+
boxShadow: "md",
|
127
|
+
outlineOffset: "0px",
|
108
128
|
},
|
109
129
|
},
|
110
130
|
}),
|