@vygruppen/spor-react 12.14.1 → 12.15.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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-postinstall.log +2 -2
- package/CHANGELOG.md +18 -0
- package/dist/index.cjs +91 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.mjs +93 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/alert/AlertIcon.tsx +30 -15
- package/src/button/ResponsiveButton.tsx +27 -0
- package/src/datepicker/CalendarCell.tsx +5 -3
- package/src/dialog/Drawer.tsx +38 -30
- package/src/dialog/types.ts +5 -0
- package/src/input/Switch.tsx +1 -1
- package/src/theme/slot-recipes/drawer.ts +2 -1
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vygruppen/spor-react",
|
3
3
|
"type": "module",
|
4
|
-
"version": "12.
|
4
|
+
"version": "12.15.0",
|
5
5
|
"exports": {
|
6
6
|
".": {
|
7
7
|
"types": "./dist/index.d.ts",
|
@@ -47,8 +47,8 @@
|
|
47
47
|
"react-swipeable": "^7.0.1",
|
48
48
|
"usehooks-ts": "^3.1.0",
|
49
49
|
"@vygruppen/spor-design-tokens": "4.2.0",
|
50
|
-
"@vygruppen/spor-
|
51
|
-
"@vygruppen/spor-
|
50
|
+
"@vygruppen/spor-icon-react": "4.2.1",
|
51
|
+
"@vygruppen/spor-loader": "0.7.0"
|
52
52
|
},
|
53
53
|
"devDependencies": {
|
54
54
|
"@react-types/datepicker": "^3.10.0",
|
package/src/alert/AlertIcon.tsx
CHANGED
@@ -26,49 +26,64 @@ type AlertIconProps = {
|
|
26
26
|
* Internal component that shows the correct icon for the alert
|
27
27
|
*/
|
28
28
|
export const AlertIcon = forwardRef<SVGSVGElement, AlertIconProps>(
|
29
|
-
({ variant, customIcon }, ref) => {
|
29
|
+
({ variant, customIcon: CustomAlertIcon }, ref) => {
|
30
30
|
const { t } = useTranslation();
|
31
31
|
|
32
|
-
const Icon = customIcon ?? getIcon(variant);
|
33
|
-
|
34
32
|
return (
|
35
33
|
<Box
|
36
|
-
|
34
|
+
asChild
|
37
35
|
ref={ref}
|
38
36
|
aria-label={t(texts[variant as keyof typeof texts])}
|
39
|
-
|
40
|
-
|
37
|
+
>
|
38
|
+
{CustomAlertIcon ? (
|
39
|
+
<CustomAlertIcon color={`alert.${variant}.icon`} />
|
40
|
+
) : (
|
41
|
+
<BaseAlertIcon variant={variant} />
|
42
|
+
)}
|
43
|
+
</Box>
|
41
44
|
);
|
42
45
|
},
|
43
46
|
);
|
44
47
|
|
45
48
|
AlertIcon.displayName = "AlertIcon";
|
46
49
|
|
47
|
-
const
|
50
|
+
const BaseAlertIcon = ({ variant }: { variant: AlertProps["variant"] }) => {
|
51
|
+
const css = {
|
52
|
+
"& path:first-of-type": {
|
53
|
+
fill: `alert.${variant}.icon`,
|
54
|
+
},
|
55
|
+
"& path:not(:first-of-type)": {
|
56
|
+
fill: `alert.${variant}.surface`,
|
57
|
+
},
|
58
|
+
};
|
59
|
+
|
48
60
|
switch (variant) {
|
49
61
|
case "info": {
|
50
|
-
return InformationFill24Icon
|
62
|
+
return <InformationFill24Icon css={css} />;
|
51
63
|
}
|
52
64
|
case "success": {
|
53
|
-
return SuccessFill24Icon
|
65
|
+
return <SuccessFill24Icon css={css} />;
|
54
66
|
}
|
55
67
|
case "important": {
|
56
|
-
return WarningFill24Icon
|
68
|
+
return <WarningFill24Icon />;
|
57
69
|
}
|
58
70
|
case "alt": {
|
59
|
-
return AltTransportFill24Icon
|
71
|
+
return <AltTransportFill24Icon css={css} />;
|
60
72
|
}
|
61
73
|
case "error": {
|
62
|
-
return ErrorFill24Icon
|
74
|
+
return <ErrorFill24Icon css={css} />;
|
63
75
|
}
|
64
76
|
case "error-secondary": {
|
65
|
-
return ErrorOutline24Icon
|
77
|
+
return <ErrorOutline24Icon css={css} />;
|
66
78
|
}
|
67
79
|
case "neutral": {
|
68
|
-
return QuestionFill24Icon
|
80
|
+
return <QuestionFill24Icon css={css} />;
|
69
81
|
}
|
70
82
|
case "service": {
|
71
|
-
return ServiceFill24Icon
|
83
|
+
return <ServiceFill24Icon />;
|
84
|
+
}
|
85
|
+
default: {
|
86
|
+
return <InformationFill24Icon css={css} />;
|
72
87
|
}
|
73
88
|
}
|
74
89
|
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Button, ButtonProps } from "./Button";
|
2
|
+
import { IconButton, IconButtonProps } from "./IconButton";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* For internal use
|
6
|
+
*/
|
7
|
+
|
8
|
+
type Props = IconButtonProps &
|
9
|
+
Omit<ButtonProps, "leftIcon" | "rightIcon"> & {
|
10
|
+
label: string;
|
11
|
+
};
|
12
|
+
|
13
|
+
export const ResponsiveButton = ({ label, icon, ...props }: Props) => {
|
14
|
+
return (
|
15
|
+
<>
|
16
|
+
<Button display={["none", "flex"]} leftIcon={icon} {...props}>
|
17
|
+
{label}
|
18
|
+
</Button>
|
19
|
+
<IconButton
|
20
|
+
display={["flex", "none"]}
|
21
|
+
aria-label={label}
|
22
|
+
icon={icon}
|
23
|
+
{...props}
|
24
|
+
/>
|
25
|
+
</>
|
26
|
+
);
|
27
|
+
};
|
@@ -11,6 +11,8 @@ import { PropsWithChildren, useEffect, useRef } from "react";
|
|
11
11
|
import { useCalendarCell } from "react-aria";
|
12
12
|
import { CalendarState, RangeCalendarState } from "react-stately";
|
13
13
|
|
14
|
+
import { spor } from "@/util";
|
15
|
+
|
14
16
|
import { DatePickerVariantProps } from "./DatePicker";
|
15
17
|
import { CalendarVariants } from "./types";
|
16
18
|
|
@@ -74,8 +76,8 @@ export function CalendarCell({
|
|
74
76
|
|
75
77
|
return (
|
76
78
|
<Box as="td" {...cellProps} textAlign="center" css={styles.cell}>
|
77
|
-
<
|
78
|
-
|
79
|
+
<spor.button
|
80
|
+
type="button" // Prevents form submission
|
79
81
|
{...buttonProps}
|
80
82
|
{...stateProps}
|
81
83
|
ref={ref}
|
@@ -83,7 +85,7 @@ export function CalendarCell({
|
|
83
85
|
hidden={isOutsideVisibleRange}
|
84
86
|
>
|
85
87
|
{date.day}
|
86
|
-
</
|
88
|
+
</spor.button>
|
87
89
|
</Box>
|
88
90
|
);
|
89
91
|
}
|
package/src/dialog/Drawer.tsx
CHANGED
@@ -4,8 +4,6 @@ import {
|
|
4
4
|
Box,
|
5
5
|
createContext,
|
6
6
|
Drawer as ChakraDrawer,
|
7
|
-
Grid,
|
8
|
-
GridItem,
|
9
7
|
Portal,
|
10
8
|
useDialogContext,
|
11
9
|
} from "@chakra-ui/react";
|
@@ -16,9 +14,12 @@ import {
|
|
16
14
|
import { forwardRef } from "react";
|
17
15
|
import { useSwipeable } from "react-swipeable";
|
18
16
|
|
19
|
-
import {
|
17
|
+
import { ResponsiveButton } from "@/button/ResponsiveButton";
|
18
|
+
|
19
|
+
import { CloseButton } from "../button";
|
20
20
|
import { createTexts, useTranslation } from "../i18n";
|
21
21
|
import {
|
22
|
+
DrawerCloseTriggerProps,
|
22
23
|
DrawerContentProps,
|
23
24
|
DrawerFullScreenHeaderProps,
|
24
25
|
DrawerProps,
|
@@ -56,7 +57,13 @@ const [RootDrawerProvider, useRootDrawerProps] =
|
|
56
57
|
|
57
58
|
export const DrawerContent = forwardRef<HTMLDivElement, DrawerContentProps>(
|
58
59
|
(props, ref) => {
|
59
|
-
const {
|
60
|
+
const {
|
61
|
+
children,
|
62
|
+
portalled = true,
|
63
|
+
portalRef,
|
64
|
+
hideHandle = false,
|
65
|
+
...rest
|
66
|
+
} = props;
|
60
67
|
const { size, placement } = useRootDrawerProps();
|
61
68
|
const { setOpen } = useDialogContext();
|
62
69
|
const handlers = useSwipeable({
|
@@ -73,14 +80,20 @@ export const DrawerContent = forwardRef<HTMLDivElement, DrawerContentProps>(
|
|
73
80
|
swipeDuration: 250,
|
74
81
|
});
|
75
82
|
const sizeNotFull = size !== "full";
|
83
|
+
const showHandle = !hideHandle;
|
84
|
+
|
76
85
|
return (
|
77
86
|
<Portal disabled={!portalled} container={portalRef}>
|
78
87
|
<ChakraDrawer.Positioner asChild>
|
79
88
|
<Box {...handlers} width="100%">
|
80
89
|
<ChakraDrawer.Content ref={ref} {...rest}>
|
81
|
-
{sizeNotFull && placement === "bottom" &&
|
90
|
+
{showHandle && sizeNotFull && placement === "bottom" && (
|
91
|
+
<CloseDrawerLine />
|
92
|
+
)}
|
82
93
|
{children}
|
83
|
-
{sizeNotFull && placement === "top" &&
|
94
|
+
{showHandle && sizeNotFull && placement === "top" && (
|
95
|
+
<CloseDrawerLine />
|
96
|
+
)}
|
84
97
|
</ChakraDrawer.Content>
|
85
98
|
</Box>
|
86
99
|
</ChakraDrawer.Positioner>
|
@@ -109,16 +122,19 @@ CloseDrawerLine.displayName = "CloseDrawerLine";
|
|
109
122
|
|
110
123
|
export const DrawerCloseTrigger = forwardRef<
|
111
124
|
HTMLButtonElement,
|
112
|
-
|
125
|
+
DrawerCloseTriggerProps
|
113
126
|
>(function DrawerCloseTrigger(props, ref) {
|
127
|
+
const { showText = false, ...rest } = props;
|
114
128
|
const { size } = useRootDrawerProps();
|
115
129
|
const { t } = useTranslation();
|
116
130
|
return (
|
117
|
-
<ChakraDrawer.CloseTrigger ref={ref} {...
|
118
|
-
{size === "full" ? (
|
119
|
-
<
|
120
|
-
|
121
|
-
|
131
|
+
<ChakraDrawer.CloseTrigger ref={ref} {...rest} asChild>
|
132
|
+
{showText || size === "full" ? (
|
133
|
+
<ResponsiveButton
|
134
|
+
variant="ghost"
|
135
|
+
icon={<CloseFill24Icon />}
|
136
|
+
label={t(texts.close)}
|
137
|
+
/>
|
122
138
|
) : (
|
123
139
|
<CloseButton size="md" />
|
124
140
|
)}
|
@@ -132,10 +148,12 @@ export const DrawerBackTrigger = forwardRef<
|
|
132
148
|
>((props, ref) => {
|
133
149
|
const { t } = useTranslation();
|
134
150
|
return (
|
135
|
-
<ChakraDrawer.CloseTrigger asChild {...props} ref={ref}
|
136
|
-
<
|
137
|
-
|
138
|
-
|
151
|
+
<ChakraDrawer.CloseTrigger asChild {...props} ref={ref}>
|
152
|
+
<ResponsiveButton
|
153
|
+
variant="ghost"
|
154
|
+
icon={<ArrowLeftFill24Icon />}
|
155
|
+
label={t(texts.back)}
|
156
|
+
/>
|
139
157
|
</ChakraDrawer.CloseTrigger>
|
140
158
|
);
|
141
159
|
});
|
@@ -147,20 +165,10 @@ export const DrawerFullScreenHeader = forwardRef<
|
|
147
165
|
>((props, ref) => {
|
148
166
|
const { backTrigger = true, closeTrigger = true, children } = props;
|
149
167
|
return (
|
150
|
-
<ChakraDrawer.Header {...props} ref={ref}
|
151
|
-
<
|
152
|
-
|
153
|
-
|
154
|
-
</GridItem>
|
155
|
-
<GridItem width="full" alignSelf="end" asChild>
|
156
|
-
{children && <DrawerTitle>{children}</DrawerTitle>}
|
157
|
-
</GridItem>
|
158
|
-
{closeTrigger && (
|
159
|
-
<GridItem width="full" alignSelf="end">
|
160
|
-
<DrawerCloseTrigger justifySelf="end" top="0" />
|
161
|
-
</GridItem>
|
162
|
-
)}
|
163
|
-
</Grid>
|
168
|
+
<ChakraDrawer.Header {...props} ref={ref}>
|
169
|
+
<Box>{backTrigger && <DrawerBackTrigger />}</Box>
|
170
|
+
{<DrawerTitle>{children}</DrawerTitle>}
|
171
|
+
<Box> {closeTrigger && <DrawerCloseTrigger />}</Box>
|
164
172
|
</ChakraDrawer.Header>
|
165
173
|
);
|
166
174
|
});
|
package/src/dialog/types.ts
CHANGED
@@ -10,6 +10,7 @@ export type DrawerContentProps = ChakraDrawer.ContentProps &
|
|
10
10
|
children: React.ReactNode;
|
11
11
|
portalled?: boolean;
|
12
12
|
portalRef?: React.RefObject<HTMLElement>;
|
13
|
+
hideHandle?: boolean;
|
13
14
|
};
|
14
15
|
|
15
16
|
export type DrawerProps = Omit<
|
@@ -28,3 +29,7 @@ export type DrawerFullScreenHeaderProps = Omit<
|
|
28
29
|
backTrigger?: boolean;
|
29
30
|
closeTrigger?: boolean;
|
30
31
|
};
|
32
|
+
|
33
|
+
export type DrawerCloseTriggerProps = ChakraDrawer.CloseTriggerProps & {
|
34
|
+
showText?: boolean;
|
35
|
+
};
|
package/src/input/Switch.tsx
CHANGED
@@ -78,7 +78,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
|
|
78
78
|
<ChakraSwitch.Control css={styles.control}>
|
79
79
|
<ChakraSwitch.Thumb />
|
80
80
|
</ChakraSwitch.Control>
|
81
|
-
<ChakraSwitch.Label>{label}</ChakraSwitch.Label>
|
81
|
+
{label && <ChakraSwitch.Label>{label}</ChakraSwitch.Label>}
|
82
82
|
</ChakraSwitch.Root>
|
83
83
|
</Field>
|
84
84
|
);
|
@@ -59,7 +59,8 @@ export const drawerSlotRecipe = defineSlotRecipe({
|
|
59
59
|
display: "flex",
|
60
60
|
alignItems: "center",
|
61
61
|
justifyContent: "space-between",
|
62
|
-
paddingX: ["
|
62
|
+
paddingX: ["2", null, null, "5"],
|
63
|
+
gap: "1",
|
63
64
|
paddingBottom: "1",
|
64
65
|
},
|
65
66
|
body: {
|