@takaro/lib-components 0.0.10 → 0.0.13
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/package.json +47 -47
- package/src/components/actions/IconButton/index.tsx +2 -1
- package/src/components/actions/IconButton/style.ts +0 -19
- package/src/components/data/Table/index.tsx +14 -2
- package/src/components/data/Table/react-table.d.ts +4 -1
- package/src/components/data/Table/subcomponents/ColumnHeader/index.tsx +1 -1
- package/src/components/data/Table/subcomponents/ColumnVisibility/index.tsx +10 -1
- package/src/components/feedback/Alert/index.tsx +22 -21
- package/src/components/feedback/Alert/style.ts +9 -3
- package/src/components/feedback/Badge/Badge.stories.tsx +23 -0
- package/src/components/feedback/Badge/index.tsx +47 -0
- package/src/components/feedback/index.ts +3 -0
- package/src/components/inputs/DurationField/Duration.stories.tsx +4 -1
- package/src/components/inputs/selects/index.tsx +0 -1
- package/src/components/other/Collapsible/CollapsibleContent.tsx +7 -0
- package/src/components/other/Collapsible/CollapsibleTrigger.tsx +12 -0
- package/src/helpers/getInitials.ts +1 -0
- package/src/hooks/useLocalStorage.tsx +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takaro/lib-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Takaro UI is a simple and customizable component library to build React apps faster within the Takaro eco system",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -15,58 +15,58 @@
|
|
|
15
15
|
"test:update": "jest --updateSnapshot"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@hookform/devtools": "
|
|
19
|
-
"@mdx-js/react": "
|
|
20
|
-
"@types/jest": "
|
|
21
|
-
"@types/react-window": "
|
|
22
|
-
"@types/styled-components": "
|
|
23
|
-
"@types/topojson-client": "
|
|
24
|
-
"react": "
|
|
25
|
-
"react-dom": "
|
|
18
|
+
"@hookform/devtools": "4.3.1",
|
|
19
|
+
"@mdx-js/react": "3.0.1",
|
|
20
|
+
"@types/jest": "29.5.13",
|
|
21
|
+
"@types/react-window": "1.8.8",
|
|
22
|
+
"@types/styled-components": "5.1.34",
|
|
23
|
+
"@types/topojson-client": "3.1.5",
|
|
24
|
+
"react": "18.3.1",
|
|
25
|
+
"react-dom": "18.3.1",
|
|
26
26
|
"storybook": "7.6.20"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@floating-ui/react": "
|
|
30
|
-
"@monaco-editor/react": "
|
|
31
|
-
"@rjsf/core": "
|
|
32
|
-
"@rjsf/utils": "
|
|
33
|
-
"@rjsf/validator-ajv8": "
|
|
34
|
-
"@tanstack/react-table": "
|
|
35
|
-
"@tanstack/react-router": "1.
|
|
29
|
+
"@floating-ui/react": "0.26.24",
|
|
30
|
+
"@monaco-editor/react": "4.6.0",
|
|
31
|
+
"@rjsf/core": "5.20.0",
|
|
32
|
+
"@rjsf/utils": "5.20.0",
|
|
33
|
+
"@rjsf/validator-ajv8": "5.20.0",
|
|
34
|
+
"@tanstack/react-table": "8.20.5",
|
|
35
|
+
"@tanstack/react-router": "1.58.15",
|
|
36
36
|
"@types/luxon": "3.4.2",
|
|
37
|
-
"framer-motion": "
|
|
37
|
+
"framer-motion": "11.9.0",
|
|
38
38
|
"luxon": "3.5.0",
|
|
39
|
-
"notistack": "
|
|
40
|
-
"polished": "
|
|
41
|
-
"react": "
|
|
42
|
-
"react-dnd": "
|
|
43
|
-
"@sentry/react": "
|
|
44
|
-
"react-dnd-html5-backend": "
|
|
45
|
-
"react-dom": "
|
|
46
|
-
"react-hook-form": "
|
|
47
|
-
"react-icons": "
|
|
48
|
-
"react-intersection-observer": "
|
|
49
|
-
"react-virtualized-auto-sizer": "
|
|
50
|
-
"react-window": "
|
|
51
|
-
"simplebar-react": "
|
|
52
|
-
"styled-components": "
|
|
53
|
-
"web-vitals": "
|
|
54
|
-
"@visx/scale": "
|
|
55
|
-
"@visx/responsive": "
|
|
56
|
-
"@visx/group": "
|
|
57
|
-
"@visx/heatmap": "
|
|
58
|
-
"@visx/tooltip": "
|
|
59
|
-
"@visx/event": "
|
|
60
|
-
"@visx/shape": "
|
|
61
|
-
"@visx/grid": "
|
|
62
|
-
"@visx/vendor": "
|
|
63
|
-
"@visx/brush": "
|
|
64
|
-
"@visx/axis": "
|
|
39
|
+
"notistack": "3.0.1",
|
|
40
|
+
"polished": "4.3.1",
|
|
41
|
+
"react": "18.3.1",
|
|
42
|
+
"react-dnd": "16.0.1",
|
|
43
|
+
"@sentry/react": "8.32.0",
|
|
44
|
+
"react-dnd-html5-backend": "16.0.1",
|
|
45
|
+
"react-dom": "18.3.1",
|
|
46
|
+
"react-hook-form": "7.53.0",
|
|
47
|
+
"react-icons": "5.3.0",
|
|
48
|
+
"react-intersection-observer": "9.13.1",
|
|
49
|
+
"react-virtualized-auto-sizer": "1.0.24",
|
|
50
|
+
"react-window": "1.8.10",
|
|
51
|
+
"simplebar-react": "3.2.6",
|
|
52
|
+
"styled-components": "5.3.11",
|
|
53
|
+
"web-vitals": "4.2.3",
|
|
54
|
+
"@visx/scale": "3.5.0",
|
|
55
|
+
"@visx/responsive": "3.10.2",
|
|
56
|
+
"@visx/group": "3.3.0",
|
|
57
|
+
"@visx/heatmap": "3.3.0",
|
|
58
|
+
"@visx/tooltip": "3.3.0",
|
|
59
|
+
"@visx/event": "3.3.0",
|
|
60
|
+
"@visx/shape": "3.5.0",
|
|
61
|
+
"@visx/grid": "3.5.0",
|
|
62
|
+
"@visx/vendor": "3.5.0",
|
|
63
|
+
"@visx/brush": "3.10.4",
|
|
64
|
+
"@visx/axis": "3.10.1",
|
|
65
65
|
"@visx/pattern": "3.3.0",
|
|
66
|
-
"@visx/curve": "
|
|
67
|
-
"@visx/gradient": "
|
|
68
|
-
"@visx/mock-data": "
|
|
66
|
+
"@visx/curve": "3.3.0",
|
|
67
|
+
"@visx/gradient": "3.3.0",
|
|
68
|
+
"@visx/mock-data": "3.3.0",
|
|
69
69
|
"@visx/geo": "3.5.0",
|
|
70
|
-
"topojson-client": "
|
|
70
|
+
"topojson-client": "3.1.0"
|
|
71
71
|
}
|
|
72
72
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cloneElement, forwardRef, ReactElement } from 'react';
|
|
2
2
|
import { Color, Size } from '../../../styled/types';
|
|
3
|
+
import { Badge } from '../../../components';
|
|
3
4
|
import { Default } from './style';
|
|
4
5
|
|
|
5
6
|
export interface IconButtonProps {
|
|
@@ -35,7 +36,7 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(functio
|
|
|
35
36
|
return (
|
|
36
37
|
<Default type="button" color={color} onClick={onClick} ref={ref} disabled={disabled} aria-label={ariaLabel}>
|
|
37
38
|
{cloneElement(icon, { size: getSize(size) })}
|
|
38
|
-
{badge && <
|
|
39
|
+
{badge && <Badge>{badge}</Badge>}
|
|
39
40
|
</Default>
|
|
40
41
|
);
|
|
41
42
|
});
|
|
@@ -51,25 +51,6 @@ export const Default = styled.button<{ color: Color }>`
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
div {
|
|
55
|
-
background-color: ${({ theme }) => theme.colors.background};
|
|
56
|
-
color: ${({ theme }) => theme.colors.text};
|
|
57
|
-
font-size: ${({ theme }) => theme.fontSize.tiny};
|
|
58
|
-
font-weight: 600;
|
|
59
|
-
border-radius: ${({ theme }) => theme.borderRadius.small};
|
|
60
|
-
width: fit-content;
|
|
61
|
-
height: 1.5rem;
|
|
62
|
-
line-height: 1.1rem;
|
|
63
|
-
display: flex;
|
|
64
|
-
align-items: center;
|
|
65
|
-
justify-content: center;
|
|
66
|
-
position: absolute;
|
|
67
|
-
top: -${({ theme }) => theme.spacing['0_75']};
|
|
68
|
-
right: -${({ theme }) => theme.spacing['0_75']};
|
|
69
|
-
padding: ${({ theme }) => theme.spacing['0_25']};
|
|
70
|
-
border: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
54
|
svg {
|
|
74
55
|
cursor: pointer;
|
|
75
56
|
fill: ${({ theme }) => theme.colors.text};
|
|
@@ -38,7 +38,7 @@ export interface TableProps<DataType extends object> {
|
|
|
38
38
|
isLoading?: boolean;
|
|
39
39
|
|
|
40
40
|
// currently not possible to type this properly: https://github.com/TanStack/table/issues/4241
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
columns: ColumnDef<DataType, any>[];
|
|
43
43
|
|
|
44
44
|
/// Renders actions that are always visible
|
|
@@ -93,7 +93,19 @@ export function Table<DataType extends object>({
|
|
|
93
93
|
if (column.id === undefined) {
|
|
94
94
|
throw new Error('ColumnDef must have an id');
|
|
95
95
|
}
|
|
96
|
-
|
|
96
|
+
|
|
97
|
+
if (column?.meta?.includeColumn == false) {
|
|
98
|
+
acc[column.id] = false;
|
|
99
|
+
return acc;
|
|
100
|
+
} else {
|
|
101
|
+
acc[column.id] = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (column?.meta?.hideColumn) {
|
|
105
|
+
acc[column.id] = !column.meta.hideColumn;
|
|
106
|
+
} else {
|
|
107
|
+
acc[column.id] = true;
|
|
108
|
+
}
|
|
97
109
|
return acc;
|
|
98
110
|
},
|
|
99
111
|
{} as Record<string, boolean>,
|
|
@@ -5,7 +5,10 @@ type DataTypes = 'datetime' | 'number' | 'string' | 'boolean' | 'uuid';
|
|
|
5
5
|
|
|
6
6
|
declare module '@tanstack/table-core' {
|
|
7
7
|
interface ColumnMeta<TData extends RowData, TValue> {
|
|
8
|
-
|
|
8
|
+
/// Column is not visible in table by default, but can be enabled with view options
|
|
9
|
+
hideColumn?: boolean;
|
|
10
|
+
canShowColumn?: boolean;
|
|
11
|
+
includeColumn?: boolean;
|
|
9
12
|
dataType?: DataTypes;
|
|
10
13
|
}
|
|
11
14
|
}
|
|
@@ -72,7 +72,7 @@ export function ColumnHeader<DataType extends object>({ header, table, isLoading
|
|
|
72
72
|
const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
|
|
73
73
|
|
|
74
74
|
// Determine mouse position
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
const clientOffset = monitor.getClientOffset()!;
|
|
77
77
|
|
|
78
78
|
// Get pixels to the top
|
|
@@ -18,7 +18,16 @@ export function ColumnVisibility<DataType extends object>({
|
|
|
18
18
|
openColumnVisibilityTooltip,
|
|
19
19
|
setHasShownColumnVisibilityTooltip,
|
|
20
20
|
}: ColumnVisibilityProps<DataType>) {
|
|
21
|
-
const viableColumns = table
|
|
21
|
+
const viableColumns = table
|
|
22
|
+
.getAllLeafColumns()
|
|
23
|
+
.filter((column) => column.getCanHide() === true)
|
|
24
|
+
.filter((column) => {
|
|
25
|
+
if (column.columnDef.meta?.includeColumn === false) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
});
|
|
30
|
+
|
|
22
31
|
const hiddenColumns = viableColumns.filter((column) => column.getIsVisible() === false);
|
|
23
32
|
|
|
24
33
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, MouseEvent, useState } from 'react';
|
|
1
|
+
import { forwardRef, isValidElement, MouseEvent, ReactElement, useState } from 'react';
|
|
2
2
|
import { Container, Grid, IconContainer, ButtonContainer } from './style';
|
|
3
3
|
import {
|
|
4
4
|
AiFillCheckCircle as Success,
|
|
@@ -20,14 +20,15 @@ type Action = {
|
|
|
20
20
|
export interface AlertProps {
|
|
21
21
|
variant: AlertVariants;
|
|
22
22
|
title?: string;
|
|
23
|
-
text?: string | string[];
|
|
23
|
+
text?: string | string[] | ReactElement;
|
|
24
24
|
elevation?: Elevation;
|
|
25
25
|
dismiss?: boolean;
|
|
26
26
|
action?: Action;
|
|
27
|
+
showIcon?: boolean;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
30
|
-
{ variant, title, text, dismiss = false, elevation = 4, action },
|
|
31
|
+
{ variant, title, text, dismiss = false, elevation = 4, action, showIcon = true },
|
|
31
32
|
ref,
|
|
32
33
|
) {
|
|
33
34
|
const [visible, setVisible] = useState(true);
|
|
@@ -39,7 +40,6 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
|
39
40
|
e.stopPropagation();
|
|
40
41
|
action?.execute();
|
|
41
42
|
};
|
|
42
|
-
|
|
43
43
|
const handleDismiss = (e: MouseEvent<HTMLButtonElement>) => {
|
|
44
44
|
e.preventDefault();
|
|
45
45
|
e.stopPropagation();
|
|
@@ -58,6 +58,19 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
|
58
58
|
return <Info size={24} />;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
|
|
62
|
+
function renderText() {
|
|
63
|
+
if (isValidElement(text)) {
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (typeof text === 'string') {
|
|
68
|
+
return <p>{text}</p>;
|
|
69
|
+
} else if (Array.isArray(text)) {
|
|
70
|
+
return <ul>{text?.map((message) => <li key={'message-' + message}>{message}</li>)}</ul>;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
return (
|
|
62
75
|
<AnimatePresence>
|
|
63
76
|
{visible && (
|
|
@@ -72,8 +85,8 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
|
72
85
|
ref={ref}
|
|
73
86
|
role="status"
|
|
74
87
|
>
|
|
75
|
-
<Grid hasTitle={hasTitle}>
|
|
76
|
-
<IconContainer variant={variant}>{getIcon()}</IconContainer>
|
|
88
|
+
<Grid hasTitle={hasTitle} showIcon={showIcon}>
|
|
89
|
+
{showIcon && <IconContainer variant={variant}>{getIcon()}</IconContainer>}
|
|
77
90
|
|
|
78
91
|
{/* If title is declared set title, otherwise put everything on single line */}
|
|
79
92
|
{title && (
|
|
@@ -82,25 +95,13 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
|
82
95
|
<div />
|
|
83
96
|
</>
|
|
84
97
|
)}
|
|
85
|
-
{
|
|
86
|
-
<p>{text}</p>
|
|
87
|
-
) : (
|
|
88
|
-
text && (
|
|
89
|
-
<ul>
|
|
90
|
-
{text.map((message) => (
|
|
91
|
-
<li key={'message-' + message}>{message}</li>
|
|
92
|
-
))}
|
|
93
|
-
</ul>
|
|
94
|
-
)
|
|
95
|
-
)}
|
|
98
|
+
{renderText()}
|
|
96
99
|
{hasTitle ? <div /> : null}
|
|
97
100
|
<ButtonContainer hasTitle={hasTitle} show={dismiss || action ? true : false} variant={variant}>
|
|
98
101
|
{action && (
|
|
99
|
-
<Button size="
|
|
100
|
-
)}
|
|
101
|
-
{dismiss && (
|
|
102
|
-
<Button size="small" color="white" variant="outline" onClick={handleDismiss} text="Dismiss" />
|
|
102
|
+
<Button size="tiny" variant="outline" onClick={handleExecute} text={action.text} color={variant} />
|
|
103
103
|
)}
|
|
104
|
+
{dismiss && <Button size="tiny" color="white" variant="outline" onClick={handleDismiss} text="Dismiss" />}
|
|
104
105
|
</ButtonContainer>
|
|
105
106
|
</Grid>
|
|
106
107
|
</Container>
|
|
@@ -58,10 +58,15 @@ export const Container = styled(motion.div)<{
|
|
|
58
58
|
}}
|
|
59
59
|
`;
|
|
60
60
|
|
|
61
|
-
export const Grid = styled.div<{ hasTitle: boolean }>`
|
|
61
|
+
export const Grid = styled.div<{ hasTitle: boolean; showIcon: boolean }>`
|
|
62
62
|
display: grid;
|
|
63
|
-
grid-template-columns: ${({ theme, hasTitle }) =>
|
|
64
|
-
|
|
63
|
+
grid-template-columns: ${({ theme, hasTitle, showIcon }) => {
|
|
64
|
+
const result = '';
|
|
65
|
+
if (showIcon) result.concat(`${theme.spacing[5]}`);
|
|
66
|
+
result.concat(' 1fr');
|
|
67
|
+
if (hasTitle) result.concat(' fit-content(100px)');
|
|
68
|
+
return result;
|
|
69
|
+
}}
|
|
65
70
|
align-items: center;
|
|
66
71
|
gap: ${({ theme, hasTitle }) => (hasTitle ? 0 : theme.spacing['0_5'])};
|
|
67
72
|
`;
|
|
@@ -83,5 +88,6 @@ export const ButtonContainer = styled.div<{
|
|
|
83
88
|
}>`
|
|
84
89
|
display: ${({ show }): string => (show ? 'flex' : 'none')};
|
|
85
90
|
align-items: center;
|
|
91
|
+
white-space: nowrap;
|
|
86
92
|
margin-top: ${({ theme, hasTitle }): string => (hasTitle ? theme.spacing['1'] : theme.spacing[0])};
|
|
87
93
|
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Meta, StoryFn } from '@storybook/react';
|
|
3
|
+
import { Badge, BadgeProps } from '.';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Feedback/Badge',
|
|
7
|
+
component: Badge,
|
|
8
|
+
args: {
|
|
9
|
+
variant: 'warning',
|
|
10
|
+
animate: false,
|
|
11
|
+
},
|
|
12
|
+
} as Meta<BadgeProps>;
|
|
13
|
+
|
|
14
|
+
export const Default: StoryFn<BadgeProps> = (args) => (
|
|
15
|
+
<div>
|
|
16
|
+
<h2 style={{ backgroundColor: 'orange', position: 'relative', width: 'fit-content' }}>
|
|
17
|
+
this is the title{' '}
|
|
18
|
+
<Badge variant={args.variant} animate={args.animate}>
|
|
19
|
+
here
|
|
20
|
+
</Badge>
|
|
21
|
+
</h2>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { forwardRef, PropsWithChildren } from 'react';
|
|
2
|
+
import { pulseAnimation, styled } from '../../../styled';
|
|
3
|
+
import { AlertVariants, Color } from '../../../styled';
|
|
4
|
+
import { shade } from 'polished';
|
|
5
|
+
|
|
6
|
+
type ColorVariant = AlertVariants | Color | 'default';
|
|
7
|
+
|
|
8
|
+
const Container = styled.div<{ variant: ColorVariant; animate: boolean }>`
|
|
9
|
+
background-color: ${({ theme, variant }) =>
|
|
10
|
+
variant === 'default' ? theme.colors.background : shade('0.8', theme.colors[variant])};
|
|
11
|
+
color: ${({ theme, variant }) => (variant === 'default' ? theme.colors.text : theme.colors[variant])};
|
|
12
|
+
font-size: ${({ theme }) => theme.fontSize.tiny};
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
border-radius: ${({ theme }) => theme.borderRadius.small};
|
|
15
|
+
width: fit-content;
|
|
16
|
+
height: 1.5rem;
|
|
17
|
+
line-height: 1.1rem;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: -${({ theme }) => theme.spacing['1']};
|
|
23
|
+
right: -${({ theme }) => theme.spacing['0_75']};
|
|
24
|
+
padding: ${({ theme }) => theme.spacing['0_25']};
|
|
25
|
+
border: 1px solid
|
|
26
|
+
${({ theme, variant }) => (variant === 'default' ? theme.colors.backgroundAccent : theme.colors[variant])};
|
|
27
|
+
|
|
28
|
+
animation: ${({ animate, variant, theme }) =>
|
|
29
|
+
animate ? pulseAnimation(variant === 'default' ? theme.colors.backgroundAccent : theme.colors[variant]) : 'none'}
|
|
30
|
+
5s infinite ease-in-out;
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
export interface BadgeProps {
|
|
34
|
+
variant?: ColorVariant;
|
|
35
|
+
animate?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const Badge = forwardRef<HTMLDivElement, PropsWithChildren<BadgeProps>>(function Badge(
|
|
39
|
+
{ variant = 'default', children, animate = false },
|
|
40
|
+
ref,
|
|
41
|
+
) {
|
|
42
|
+
return (
|
|
43
|
+
<Container ref={ref} variant={variant} animate={animate}>
|
|
44
|
+
{children}
|
|
45
|
+
</Container>
|
|
46
|
+
);
|
|
47
|
+
});
|
|
@@ -3,6 +3,7 @@ import { DurationField, DurationFieldProps } from '../../../components';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { StoryFn, Meta } from '@storybook/react';
|
|
5
5
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
|
6
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
6
7
|
|
|
7
8
|
export default {
|
|
8
9
|
title: 'Inputs/DurationField',
|
|
@@ -26,7 +27,9 @@ export const Default: StoryFn<DurationFieldProps> = (args) => {
|
|
|
26
27
|
duration: z.number().positive(),
|
|
27
28
|
});
|
|
28
29
|
|
|
29
|
-
const { control, handleSubmit } = useForm<z.infer<typeof validationSchema>>(
|
|
30
|
+
const { control, handleSubmit } = useForm<z.infer<typeof validationSchema>>({
|
|
31
|
+
resolver: zodResolver(validationSchema),
|
|
32
|
+
});
|
|
30
33
|
const onSubmit: SubmitHandler<z.infer<typeof validationSchema>> = ({ duration }) => {
|
|
31
34
|
setResult(duration);
|
|
32
35
|
};
|
|
@@ -42,7 +42,6 @@ export const getLabelFromChildren = (children: ReactNode, value: string) => {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
// eslint-disable-next-line no-console
|
|
46
45
|
console.error(
|
|
47
46
|
`No label found for value ${value}. This occurs when a value is passed through the defaultValue prop of useForm, but the value is not present in the options.`,
|
|
48
47
|
);
|
|
@@ -6,6 +6,13 @@ const Container = styled.div`
|
|
|
6
6
|
margin-bottom: ${({ theme }) => theme.spacing['1']};
|
|
7
7
|
hyphens: auto;
|
|
8
8
|
|
|
9
|
+
border: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
10
|
+
padding: 10px 5px 0px 5px;
|
|
11
|
+
border-top-left-radius: 0;
|
|
12
|
+
border-top-right-radius: 0;
|
|
13
|
+
border-bottom-left-radius: 5px;
|
|
14
|
+
border-bottom-right-radius: 5px;
|
|
15
|
+
|
|
9
16
|
p {
|
|
10
17
|
hypens: auto;
|
|
11
18
|
}
|
|
@@ -22,6 +22,18 @@ const Container = styled.button<{ open: boolean }>`
|
|
|
22
22
|
margin-bottom: ${({ theme, open }) => (!open ? theme.spacing['1'] : theme.spacing['0_5'])};
|
|
23
23
|
border: 1px solid ${({ theme }) => theme.colors.backgroundAccent};
|
|
24
24
|
color: ${({ theme }) => theme.colors.textAlt};
|
|
25
|
+
font-size: ${({ theme }) => theme.fontSize.mediumLarge};
|
|
26
|
+
|
|
27
|
+
${({ open }) => {
|
|
28
|
+
if (open) {
|
|
29
|
+
return `
|
|
30
|
+
border-bottom: 0;
|
|
31
|
+
border-bottom-left-radius: 0;
|
|
32
|
+
border-bottom-right-radius: 0;
|
|
33
|
+
margin-bottom: 0;
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
36
|
+
}}
|
|
25
37
|
|
|
26
38
|
svg {
|
|
27
39
|
fill: ${({ theme }) => theme.colors.textAlt};
|
|
@@ -8,7 +8,6 @@ export function useLocalStorage<T>(key: string, initialValue: T) {
|
|
|
8
8
|
const item = window.localStorage.getItem(key);
|
|
9
9
|
return item ? JSON.parse(item) : initialValue;
|
|
10
10
|
} catch (e) {
|
|
11
|
-
// eslint-disable-next-line no-console
|
|
12
11
|
console.error('Error reading the local storage value', e);
|
|
13
12
|
return initialValue;
|
|
14
13
|
}
|
|
@@ -24,11 +23,9 @@ export function useLocalStorage<T>(key: string, initialValue: T) {
|
|
|
24
23
|
} catch (e) {
|
|
25
24
|
// DOMException code 22 for QuotaExceededError
|
|
26
25
|
if (e instanceof DOMException && e.name === 'QuotaExceededError') {
|
|
27
|
-
// eslint-disable-next-line no-console
|
|
28
26
|
console.error('LocalStorage quota exceeded', e);
|
|
29
27
|
setError(e);
|
|
30
28
|
} else {
|
|
31
|
-
// eslint-disable-next-line no-console
|
|
32
29
|
console.error('Error setting the local storage value', e);
|
|
33
30
|
}
|
|
34
31
|
}
|