@chem-po/react-web 0.0.15 → 0.0.17
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.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
- package/src/components/feed/MediaFeed.tsx +1 -1
- package/src/components/form/FormFooter.tsx +9 -2
- package/src/components/form/input/Editable.tsx +2 -4
- package/src/components/form/input/hooks/index.ts +1 -1
- package/src/components/form/input/hooks/useInputStyles.ts +125 -0
- package/src/components/form/input/input.tsx +4 -4
- package/src/components/form/input/multipleSelect/index.tsx +42 -8
- package/src/components/form/input/number/index.tsx +43 -39
- package/src/components/form/input/select/index.tsx +32 -18
- package/src/components/form/input/shared/InputContainer.tsx +13 -0
- package/src/components/form/input/text/index.tsx +26 -20
- package/src/components/form/input/text/textarea.tsx +0 -1
- package/src/components/form/view/file.tsx +3 -12
- package/src/components/form/view/index.tsx +4 -13
- package/src/components/form/view/multipleSelect.tsx +26 -13
- package/src/components/form/view/select.tsx +18 -8
- package/src/components/form/view/types.ts +11 -0
- package/src/components/list/Body/InfiniteScrollGridBody.tsx +2 -2
- package/src/components/list/Body/InfiniteScrollListBody.tsx +3 -3
- package/src/components/list/Body/PagedGridBody.tsx +1 -1
- package/src/components/list/Body/PagedListBody.tsx +1 -1
- package/src/components/list/ListItem/ListCell.tsx +1 -1
- package/src/components/list/ListItem/ListRow.tsx +1 -1
- package/src/components/list/ListItemView.tsx +1 -1
- package/src/components/list/utils.ts +1 -0
- package/src/components/view/RedirectView.tsx +2 -1
- package/src/components/form/input/hooks/useInputStyle.ts +0 -39
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { ViewIcon, ViewOffIcon } from '@chakra-ui/icons'
|
|
2
|
-
import {
|
|
2
|
+
import { IconButton, Input } from '@chakra-ui/react'
|
|
3
3
|
import { InputRef } from '@chem-po/core'
|
|
4
4
|
import { TextField } from '@chem-po/react'
|
|
5
5
|
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'
|
|
6
|
+
import { useInputStyles } from '../hooks'
|
|
7
|
+
import { InputContainer } from '../shared/InputContainer'
|
|
6
8
|
import { FieldProps } from '../types'
|
|
7
9
|
import { TextAreaComponent } from './textarea'
|
|
8
10
|
|
|
9
11
|
export const TextComponent = forwardRef<InputRef, FieldProps<TextField>>(
|
|
10
|
-
({ input, inEditable, meta, field }, ref) => {
|
|
12
|
+
({ input, inEditable, meta, field, formSize }, ref) => {
|
|
11
13
|
const { placeholder, type } = field
|
|
12
14
|
const [isHidden, setIsHidden] = useState(type === 'password')
|
|
15
|
+
const { text, container } = useInputStyles(inEditable, field.size, formSize)
|
|
13
16
|
const { value } = input
|
|
14
17
|
const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null)
|
|
15
18
|
|
|
@@ -32,15 +35,18 @@ export const TextComponent = forwardRef<InputRef, FieldProps<TextField>>(
|
|
|
32
35
|
border: 'none',
|
|
33
36
|
}}
|
|
34
37
|
borderRadius={0}
|
|
35
|
-
px={inEditable ? 0 : 3}
|
|
36
38
|
background="transparent"
|
|
37
39
|
_focus={{
|
|
38
40
|
border: 'none',
|
|
41
|
+
boxShadow: 'none',
|
|
39
42
|
}}
|
|
40
|
-
py={
|
|
43
|
+
py={0}
|
|
44
|
+
px={0}
|
|
45
|
+
height="auto"
|
|
46
|
+
outline="none"
|
|
41
47
|
type={isHidden ? 'password' : 'text'}
|
|
42
|
-
height={inEditable ? 'auto' : 10}
|
|
43
48
|
placeholder={placeholder}
|
|
49
|
+
style={text}
|
|
44
50
|
{...input}
|
|
45
51
|
onChange={e => {
|
|
46
52
|
input.onChange({ target: { value: e.target.value } })
|
|
@@ -49,22 +55,22 @@ export const TextComponent = forwardRef<InputRef, FieldProps<TextField>>(
|
|
|
49
55
|
/>
|
|
50
56
|
)
|
|
51
57
|
|
|
52
|
-
return
|
|
53
|
-
<
|
|
58
|
+
return (
|
|
59
|
+
<InputContainer style={container}>
|
|
54
60
|
{body}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
{type === 'password' && (
|
|
62
|
+
<IconButton
|
|
63
|
+
position="absolute"
|
|
64
|
+
right={2}
|
|
65
|
+
onClick={() => setIsHidden(!isHidden)}
|
|
66
|
+
variant="ghost"
|
|
67
|
+
icon={isHidden ? <ViewIcon /> : <ViewOffIcon />}
|
|
68
|
+
aria-label={isHidden ? 'show' : 'hide'}
|
|
69
|
+
title={isHidden ? 'Show' : 'Hide'}
|
|
70
|
+
size="xs"
|
|
71
|
+
/>
|
|
72
|
+
)}
|
|
73
|
+
</InputContainer>
|
|
68
74
|
)
|
|
69
75
|
},
|
|
70
76
|
)
|
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
import { Box, Flex, Text } from '@chakra-ui/react'
|
|
2
2
|
import { ImageViewOptions } from '@chem-po/core'
|
|
3
3
|
import { FileField } from '@chem-po/react'
|
|
4
|
-
import React, {
|
|
4
|
+
import React, { useMemo } from 'react'
|
|
5
5
|
import { ExpandOnMount } from '../../box/ExpandOnMount'
|
|
6
6
|
import { FileView } from '../input/file'
|
|
7
|
+
import { FieldViewProps } from './types'
|
|
7
8
|
|
|
8
|
-
export const FileFieldView = ({
|
|
9
|
-
field,
|
|
10
|
-
value,
|
|
11
|
-
noLabel,
|
|
12
|
-
style,
|
|
13
|
-
}: {
|
|
14
|
-
field: FileField
|
|
15
|
-
value: any
|
|
16
|
-
noLabel?: boolean
|
|
17
|
-
style?: CSSProperties
|
|
18
|
-
}) => {
|
|
9
|
+
export const FileFieldView = ({ field, value, noLabel, style }: FieldViewProps<FileField>) => {
|
|
19
10
|
const { imageOptions, placeholder } = field
|
|
20
11
|
const options = useMemo<ImageViewOptions>(
|
|
21
12
|
() => ({
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
import { Flex, Text } from '@chakra-ui/react'
|
|
2
2
|
|
|
3
3
|
import { formatField } from '@chem-po/core'
|
|
4
|
-
import { Field } from '@chem-po/react'
|
|
4
|
+
import { Field, FormatField } from '@chem-po/react'
|
|
5
5
|
import React, { CSSProperties, useMemo } from 'react'
|
|
6
6
|
import { FileFieldView } from './file'
|
|
7
7
|
import { MultipleSelectFieldView } from './multipleSelect'
|
|
8
8
|
import { SelectFieldView } from './select'
|
|
9
|
+
import { FieldViewProps } from './types'
|
|
9
10
|
|
|
10
|
-
const DefaultFieldView = ({
|
|
11
|
-
field,
|
|
12
|
-
value,
|
|
13
|
-
noLabel,
|
|
14
|
-
style,
|
|
15
|
-
}: {
|
|
16
|
-
field: Field
|
|
17
|
-
value: any
|
|
18
|
-
noLabel?: boolean
|
|
19
|
-
style?: CSSProperties
|
|
20
|
-
}) => {
|
|
11
|
+
const DefaultFieldView = <F extends Field>({ field, value, noLabel, style }: FieldViewProps<F>) => {
|
|
21
12
|
const { placeholder } = field
|
|
22
13
|
|
|
23
14
|
const formatted = useMemo(() => {
|
|
24
|
-
const format = formatField[field._type]
|
|
15
|
+
const format = formatField[field._type] as FormatField<F>
|
|
25
16
|
if (!format) return value
|
|
26
17
|
return format(field, value)
|
|
27
18
|
}, [value, field])
|
|
@@ -2,20 +2,27 @@ import { Box, Text } from '@chakra-ui/react'
|
|
|
2
2
|
|
|
3
3
|
import { Flex, useColorMode } from '@chakra-ui/react'
|
|
4
4
|
import { MultipleSelectField } from '@chem-po/react'
|
|
5
|
-
import React, {
|
|
5
|
+
import React, { useMemo } from 'react'
|
|
6
|
+
import { useInputStyles } from '../input/hooks/useInputStyles'
|
|
7
|
+
import { getRenderSelectedOptionText } from '../input/multipleSelect'
|
|
8
|
+
import { FieldViewProps } from './types'
|
|
6
9
|
|
|
7
|
-
export const MultipleSelectFieldView = ({
|
|
10
|
+
export const MultipleSelectFieldView = <F extends MultipleSelectField>({
|
|
8
11
|
field,
|
|
9
12
|
value,
|
|
10
13
|
noLabel,
|
|
11
14
|
style,
|
|
12
|
-
}: {
|
|
13
|
-
field
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
}: FieldViewProps<F>) => {
|
|
16
|
+
const { placeholder, options } = field
|
|
17
|
+
const { size, text } = useInputStyles(undefined, field.size)
|
|
18
|
+
const selectedOptions = useMemo(
|
|
19
|
+
() => options.filter(o => value?.includes(o.value)),
|
|
20
|
+
[value, options],
|
|
21
|
+
)
|
|
22
|
+
const RenderSelectedOptionText = useMemo(
|
|
23
|
+
() => getRenderSelectedOptionText(field, text),
|
|
24
|
+
[field, text],
|
|
25
|
+
)
|
|
19
26
|
const { colorMode } = useColorMode()
|
|
20
27
|
return (
|
|
21
28
|
<Flex maxW="100%" flexFlow="row wrap" align="center" style={style}>
|
|
@@ -24,10 +31,16 @@ export const MultipleSelectFieldView = ({
|
|
|
24
31
|
{placeholder}
|
|
25
32
|
</Text>
|
|
26
33
|
)}
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
<Box key={
|
|
30
|
-
<
|
|
34
|
+
{selectedOptions.length ? (
|
|
35
|
+
selectedOptions.map(o => (
|
|
36
|
+
<Box key={o.value} p={0.5}>
|
|
37
|
+
<RenderSelectedOptionText
|
|
38
|
+
value={o.value}
|
|
39
|
+
option={o}
|
|
40
|
+
colorMode={colorMode}
|
|
41
|
+
isSelected={true}
|
|
42
|
+
size={size}
|
|
43
|
+
/>
|
|
31
44
|
</Box>
|
|
32
45
|
))
|
|
33
46
|
) : (
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Flex, Text, useColorMode } from '@chakra-ui/react'
|
|
2
2
|
import { SelectField } from '@chem-po/react'
|
|
3
|
-
import React
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { useInputStyles } from '../input/hooks/useInputStyles'
|
|
5
|
+
import { FieldViewProps } from './types'
|
|
4
6
|
|
|
5
7
|
const stringifyValue = (value: any) => {
|
|
6
8
|
if (typeof value === 'string') return value
|
|
@@ -18,14 +20,12 @@ export const SelectFieldView = <F extends SelectField>({
|
|
|
18
20
|
value,
|
|
19
21
|
noLabel,
|
|
20
22
|
style,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
value: F['defaultValue']
|
|
24
|
-
noLabel?: boolean
|
|
25
|
-
style?: CSSProperties
|
|
26
|
-
}) => {
|
|
23
|
+
size: propSize,
|
|
24
|
+
}: FieldViewProps<F>) => {
|
|
27
25
|
const { placeholder, renderOption: customRender } = field
|
|
28
26
|
const { colorMode } = useColorMode()
|
|
27
|
+
const { size } = useInputStyles(undefined, field.size, propSize)
|
|
28
|
+
const selectedOption = field.options.find(o => o.value === value)
|
|
29
29
|
const RenderOption = customRender ?? DefaultRenderOption
|
|
30
30
|
return (
|
|
31
31
|
<Flex align="center" style={style}>
|
|
@@ -34,7 +34,17 @@ export const SelectFieldView = <F extends SelectField>({
|
|
|
34
34
|
{placeholder}
|
|
35
35
|
</Text>
|
|
36
36
|
)}
|
|
37
|
-
{value
|
|
37
|
+
{value && selectedOption ? (
|
|
38
|
+
<RenderOption
|
|
39
|
+
value={value}
|
|
40
|
+
option={selectedOption}
|
|
41
|
+
colorMode={colorMode}
|
|
42
|
+
isSelected={true}
|
|
43
|
+
size={size}
|
|
44
|
+
/>
|
|
45
|
+
) : (
|
|
46
|
+
<Text>None</Text>
|
|
47
|
+
)}
|
|
38
48
|
</Flex>
|
|
39
49
|
)
|
|
40
50
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InputSize } from '@chem-po/core'
|
|
2
|
+
import { Field } from '@chem-po/react'
|
|
3
|
+
import { CSSProperties } from 'react'
|
|
4
|
+
|
|
5
|
+
export interface FieldViewProps<F extends Field> {
|
|
6
|
+
field: F
|
|
7
|
+
value: F['defaultValue']
|
|
8
|
+
noLabel?: boolean
|
|
9
|
+
size?: InputSize
|
|
10
|
+
style?: CSSProperties
|
|
11
|
+
}
|
|
@@ -42,7 +42,7 @@ export const InfiniteScrollGridBody = <T extends AnyObject>({
|
|
|
42
42
|
grid: options,
|
|
43
43
|
colorMode,
|
|
44
44
|
numCols,
|
|
45
|
-
onSelect: (item: WithId<T>) => onSelectItem(item.
|
|
45
|
+
onSelect: (item: WithId<T>) => onSelectItem(item.id),
|
|
46
46
|
refetch: refetchItem,
|
|
47
47
|
}),
|
|
48
48
|
[items, list, refetchItem, onSelectItem, mobileLayout, numCols, options, colorMode],
|
|
@@ -83,7 +83,7 @@ export const InfiniteScrollGridBody = <T extends AnyObject>({
|
|
|
83
83
|
data: ListItemProps<T>
|
|
84
84
|
}) => {
|
|
85
85
|
const index = rowIndex * numCols + columnIndex
|
|
86
|
-
return data.items[index]?.
|
|
86
|
+
return data.items[index]?.id || `${index}`
|
|
87
87
|
},
|
|
88
88
|
[numCols],
|
|
89
89
|
)
|
|
@@ -26,7 +26,7 @@ export const InfiniteScrollListBody = ({ height }: { height: number }) => {
|
|
|
26
26
|
items,
|
|
27
27
|
mobileLayout,
|
|
28
28
|
colorMode,
|
|
29
|
-
onSelect: (item: WithId<AnyObject>) => onSelectItem(item.
|
|
29
|
+
onSelect: (item: WithId<AnyObject>) => onSelectItem(item.id),
|
|
30
30
|
refetch: refetchItem,
|
|
31
31
|
}),
|
|
32
32
|
[items, list, refetchItem, onSelectItem, mobileLayout, colorMode],
|
|
@@ -78,7 +78,7 @@ export const InfiniteScrollListBody = ({ height }: { height: number }) => {
|
|
|
78
78
|
itemCount={totalCount ?? 0}
|
|
79
79
|
itemData={itemData}
|
|
80
80
|
style={{ overflowX: 'hidden' }}
|
|
81
|
-
itemKey={index => items[index]?.
|
|
81
|
+
itemKey={index => items[index]?.id || `${index}`}
|
|
82
82
|
onItemsRendered={i => {
|
|
83
83
|
onItemsRendered(i)
|
|
84
84
|
}}
|
|
@@ -100,7 +100,7 @@ export const InfiniteScrollListBody = ({ height }: { height: number }) => {
|
|
|
100
100
|
itemSize={itemHeight as number}
|
|
101
101
|
itemCount={totalCount ?? 0}
|
|
102
102
|
itemData={itemData}
|
|
103
|
-
itemKey={index => items[index]?.
|
|
103
|
+
itemKey={index => items[index]?.id || `${index}`}
|
|
104
104
|
style={{
|
|
105
105
|
overflowX: 'hidden',
|
|
106
106
|
}}
|
|
@@ -22,7 +22,7 @@ const BasePagedListBody = ({ height }: { height: number }) => {
|
|
|
22
22
|
list,
|
|
23
23
|
colorMode,
|
|
24
24
|
items,
|
|
25
|
-
onSelect: item => onSelectItem(item.
|
|
25
|
+
onSelect: item => onSelectItem(item.id),
|
|
26
26
|
mobileLayout,
|
|
27
27
|
}),
|
|
28
28
|
[items, list, onSelectItem, mobileLayout, colorMode],
|
|
@@ -13,7 +13,7 @@ export const ListItemView = () => {
|
|
|
13
13
|
// refetchItem,
|
|
14
14
|
} = usePaginatedList()
|
|
15
15
|
const item = useMemo(
|
|
16
|
-
() => data.find(d => d.
|
|
16
|
+
() => data.find(d => d.id === selectedItemId) ?? null,
|
|
17
17
|
[data, selectedItemId],
|
|
18
18
|
)
|
|
19
19
|
const { colorMode } = useColorMode()
|
|
@@ -30,6 +30,7 @@ export const getSearchQueries = <T extends AnyObject>(
|
|
|
30
30
|
baseQuery: Query<T>,
|
|
31
31
|
searchData: BaseQuery<T>['search'],
|
|
32
32
|
): Array<Query<T>> => {
|
|
33
|
+
if (!searchData) return [baseQuery]
|
|
33
34
|
const { paths, query: search } = searchData
|
|
34
35
|
if (!paths?.length || !search) return [baseQuery]
|
|
35
36
|
return paths.map(path => getTextSearchQuery(baseQuery, search, path))
|
|
@@ -8,7 +8,8 @@ import { Loading } from '../loading/Loading'
|
|
|
8
8
|
|
|
9
9
|
export const RedirectView: React.FC<{ loading?: boolean }> = ({ loading }) => {
|
|
10
10
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
11
|
-
const authLoading = useAuth(s => s.
|
|
11
|
+
const authLoading = useAuth(s => s.signInLoading)
|
|
12
|
+
const multiFactorLoading = useAuth(s => s.multiFactorLoading)
|
|
12
13
|
|
|
13
14
|
const navigate = useNavigate()
|
|
14
15
|
useEffect(() => {
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { InputSize } from '@chem-po/react'
|
|
2
|
-
import { CSSProperties, useMemo } from 'react'
|
|
3
|
-
|
|
4
|
-
const inputPaddingY: Record<InputSize, number> = {
|
|
5
|
-
xs: 0.25,
|
|
6
|
-
sm: 0.35,
|
|
7
|
-
md: 0.5,
|
|
8
|
-
lg: 0.5,
|
|
9
|
-
xl: 0.5,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const inputPaddingX: Record<InputSize, number> = {
|
|
13
|
-
xs: 0.5,
|
|
14
|
-
sm: 0.75,
|
|
15
|
-
md: 0.75,
|
|
16
|
-
lg: 0.75,
|
|
17
|
-
xl: 0.75,
|
|
18
|
-
}
|
|
19
|
-
const getInputPadding = (size: InputSize) => {
|
|
20
|
-
const paddingY = inputPaddingY[size]
|
|
21
|
-
const paddingX = inputPaddingX[size]
|
|
22
|
-
return `${paddingY}rem ${paddingX}rem`
|
|
23
|
-
}
|
|
24
|
-
const fontSize: Record<InputSize, string> = {
|
|
25
|
-
xs: '0.75rem',
|
|
26
|
-
sm: '0.875rem',
|
|
27
|
-
md: '1rem',
|
|
28
|
-
lg: '1.125rem',
|
|
29
|
-
xl: '1.25rem',
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const useInputStyle = (size?: InputSize) =>
|
|
33
|
-
useMemo<Partial<CSSProperties>>(
|
|
34
|
-
() => ({
|
|
35
|
-
padding: getInputPadding(size ?? 'md'),
|
|
36
|
-
fontSize: fontSize[size ?? 'md'],
|
|
37
|
-
}),
|
|
38
|
-
[size],
|
|
39
|
-
)
|