@chem-po/react-web 0.0.9 → 0.0.11
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.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +17 -38
- package/src/components/box/Expandable.tsx +6 -6
- package/src/components/box/FullSizeContainer.tsx +2 -2
- package/src/components/button/DeleteButton.tsx +1 -1
- package/src/components/form/Form.tsx +8 -5
- package/src/components/form/FormFooter.tsx +3 -3
- package/src/components/form/input/Editable.tsx +61 -69
- package/src/components/form/input/input.tsx +9 -5
- package/src/components/form/input/multipleSelect/index.tsx +2 -2
- package/src/components/form/input/select/index.tsx +9 -3
- package/src/components/form/view/multipleSelect.tsx +2 -2
- package/src/components/form/view/select.tsx +13 -6
- package/src/components/list/ListItem/ListCell.tsx +8 -7
- package/src/components/list/ListItem/ListRow.tsx +8 -2
- package/src/components/view/RedirectView.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chem-po/react-web",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"module": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.js",
|
|
13
|
-
"require": "./dist/index.js"
|
|
14
|
-
},
|
|
15
|
-
"./package.json": "./package.json"
|
|
16
|
-
},
|
|
17
|
-
"sideEffects": false,
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
18
7
|
"publishConfig": {
|
|
19
8
|
"access": "public"
|
|
20
9
|
},
|
|
10
|
+
"sideEffects": false,
|
|
21
11
|
"files": [
|
|
22
12
|
"dist",
|
|
23
13
|
"src"
|
|
@@ -26,10 +16,6 @@
|
|
|
26
16
|
"author": "",
|
|
27
17
|
"license": "ISC",
|
|
28
18
|
"dependencies": {
|
|
29
|
-
"@chem-po/core": "0.0.9",
|
|
30
|
-
"@chem-po/react": "0.0.9"
|
|
31
|
-
},
|
|
32
|
-
"peerDependencies": {
|
|
33
19
|
"@chakra-ui/anatomy": "^2.2.2",
|
|
34
20
|
"@chakra-ui/icons": "^2.1.1",
|
|
35
21
|
"@chakra-ui/react": "^2.10.3",
|
|
@@ -42,42 +28,34 @@
|
|
|
42
28
|
"howler": "^2.2.4",
|
|
43
29
|
"lottie-react": "^2.4.0",
|
|
44
30
|
"nested-property": "^4.0.0",
|
|
45
|
-
"react": "^18.0.0",
|
|
46
|
-
"react-dom": "^18.0.0",
|
|
47
31
|
"react-currency-input-field": "^3.8.0",
|
|
48
32
|
"react-day-picker": "^9.0.9",
|
|
49
33
|
"react-error-boundary": "^4.0.13",
|
|
50
34
|
"react-hook-form": "^7.55.0",
|
|
51
|
-
"react-router": "^6.
|
|
52
|
-
"react-router-dom": "^6.
|
|
35
|
+
"react-router": "^7.6.1",
|
|
36
|
+
"react-router-dom": "^7.6.1",
|
|
53
37
|
"react-textarea-autosize": "^8.5.3",
|
|
54
38
|
"react-transition-group": "^4.4.5",
|
|
55
39
|
"react-window": "^1.8.10",
|
|
56
40
|
"react-window-infinite-loader": "^1.0.9",
|
|
57
|
-
"@hello-pangea/dnd": "^
|
|
58
|
-
"zustand": "^4.3.3"
|
|
41
|
+
"@hello-pangea/dnd": "^18.0.1",
|
|
42
|
+
"zustand": "^4.3.3",
|
|
43
|
+
"@chem-po/react": "0.0.11",
|
|
44
|
+
"@chem-po/core": "0.0.11"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"react": "^19.0.0",
|
|
48
|
+
"react-dom": "^19.0.0"
|
|
59
49
|
},
|
|
60
50
|
"devDependencies": {
|
|
61
51
|
"@types/howler": "^2.2.11",
|
|
62
|
-
"@types/react": "
|
|
52
|
+
"@types/react": "~19.0.10",
|
|
63
53
|
"@types/react-beautiful-dnd": "^13.1.8",
|
|
64
54
|
"@types/react-transition-group": "^4.4.11",
|
|
65
55
|
"@types/react-window": "^1.8.8",
|
|
66
56
|
"@types/react-window-infinite-loader": "^1.0.9",
|
|
67
57
|
"replace-in-file": "^8.1.0",
|
|
68
|
-
"typescript": "^5.7.2",
|
|
69
58
|
"vite": "^5.4.6",
|
|
70
|
-
"typescript-eslint": "^8.11.0",
|
|
71
|
-
"@eslint/js": "^9.13.0",
|
|
72
|
-
"@types/eslint__js": "^8.42.3",
|
|
73
|
-
"@typescript-eslint/parser": "8.12.2",
|
|
74
|
-
"eslint": "^9.13.0",
|
|
75
|
-
"eslint-config-prettier": "^9.1.0",
|
|
76
|
-
"eslint-import-resolver-typescript": "^3.6.3",
|
|
77
|
-
"eslint-plugin-import": "^2.31.0",
|
|
78
|
-
"eslint-plugin-prettier": "^5.2.1",
|
|
79
|
-
"eslint-plugin-react-hooks": "^5.0.0",
|
|
80
|
-
"prettier": "^3.2.5",
|
|
81
59
|
"tsup": "^8.3.0"
|
|
82
60
|
},
|
|
83
61
|
"description": "",
|
|
@@ -88,5 +66,6 @@
|
|
|
88
66
|
"dev": "tsup --watch",
|
|
89
67
|
"clean": "rm -rf dist",
|
|
90
68
|
"prebuild": "pnpm lint"
|
|
91
|
-
}
|
|
69
|
+
},
|
|
70
|
+
"module": "dist/index.js"
|
|
92
71
|
}
|
|
@@ -13,14 +13,14 @@ import { useBorderColor } from '../../hooks/ui/useBorderColor'
|
|
|
13
13
|
import { ViewButton } from '../button/ViewButton'
|
|
14
14
|
|
|
15
15
|
export const Expandable = ({
|
|
16
|
-
header,
|
|
16
|
+
header: Header,
|
|
17
17
|
children,
|
|
18
18
|
initExpanded = false,
|
|
19
19
|
nested,
|
|
20
20
|
alwaysExpanded,
|
|
21
21
|
headerProps,
|
|
22
22
|
iconColor,
|
|
23
|
-
footer,
|
|
23
|
+
footer: Footer,
|
|
24
24
|
isOpen: isOpenProp,
|
|
25
25
|
onClose: onCloseProp,
|
|
26
26
|
onOpen: onOpenProp,
|
|
@@ -73,12 +73,12 @@ export const Expandable = ({
|
|
|
73
73
|
aria-label="expand/hide"
|
|
74
74
|
align="center"
|
|
75
75
|
flex={1}>
|
|
76
|
-
{typeof
|
|
76
|
+
{typeof Header === 'string' ? (
|
|
77
77
|
<Text fontWeight={600} color="gray.500" flex={1}>
|
|
78
|
-
{
|
|
78
|
+
{Header}
|
|
79
79
|
</Text>
|
|
80
80
|
) : (
|
|
81
|
-
|
|
81
|
+
<Header isOpen={isOpen} onClose={onClose} />
|
|
82
82
|
)}
|
|
83
83
|
</Flex>
|
|
84
84
|
{alwaysExpanded ? null : (
|
|
@@ -90,7 +90,7 @@ export const Expandable = ({
|
|
|
90
90
|
{children as any}
|
|
91
91
|
</Collapse>
|
|
92
92
|
</Box>
|
|
93
|
-
{
|
|
93
|
+
{Footer ? <Footer isOpen={isOpen} onClose={onClose} /> : null}
|
|
94
94
|
</VStack>
|
|
95
95
|
)
|
|
96
96
|
}
|
|
@@ -4,7 +4,7 @@ import useResizeObserver from '@react-hook/resize-observer'
|
|
|
4
4
|
import React, { FC, useCallback, useMemo, useRef, useState } from 'react'
|
|
5
5
|
|
|
6
6
|
export const FullSizeContainer = ({
|
|
7
|
-
children,
|
|
7
|
+
children: Children,
|
|
8
8
|
...props
|
|
9
9
|
}: Omit<BoxProps, 'children'> & { children: FC<{ width: number; height: number }> }) => {
|
|
10
10
|
const [width, setWidth] = useState(0)
|
|
@@ -21,7 +21,7 @@ export const FullSizeContainer = ({
|
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<Box ref={ref} {...props} width="100%" height="100%">
|
|
24
|
-
|
|
24
|
+
<Children width={width} height={height} />
|
|
25
25
|
</Box>
|
|
26
26
|
)
|
|
27
27
|
}
|
|
@@ -85,7 +85,7 @@ export const DeleteButton: React.FC<
|
|
|
85
85
|
> = ({ onDelete, itemName, noConfirm, alertBody, text, actionName = 'Delete', ...props }) => {
|
|
86
86
|
const [deleteLoading, setDeleteLoading] = useState(false)
|
|
87
87
|
const [confirmActive, setConfirmActive] = useState(false)
|
|
88
|
-
const confirmTimer = useRef<
|
|
88
|
+
const confirmTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
89
89
|
const isMounted = useRef(true)
|
|
90
90
|
useEffect(() => {
|
|
91
91
|
isMounted.current = true
|
|
@@ -18,12 +18,14 @@ import {
|
|
|
18
18
|
FieldFormProps,
|
|
19
19
|
FieldMap,
|
|
20
20
|
FieldMapFormProps,
|
|
21
|
+
FormOnSubmit,
|
|
21
22
|
FormProps,
|
|
22
23
|
IFormElement,
|
|
23
24
|
ListField,
|
|
24
25
|
useDataView,
|
|
25
26
|
useFormSubmit,
|
|
26
27
|
UseFormSubmitProps,
|
|
28
|
+
useGetItemField,
|
|
27
29
|
} from '@chem-po/react'
|
|
28
30
|
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
|
29
31
|
import React, { FC, useMemo, useState } from 'react'
|
|
@@ -208,8 +210,9 @@ const ListFieldView = ({
|
|
|
208
210
|
value: any[]
|
|
209
211
|
path: string
|
|
210
212
|
}) => {
|
|
211
|
-
const {
|
|
213
|
+
const { placeholder } = field
|
|
212
214
|
const borderColor = useBorderColor()
|
|
215
|
+
const getItemField = useGetItemField(field)
|
|
213
216
|
return (
|
|
214
217
|
<Box w="100%" p={1}>
|
|
215
218
|
<Expandable
|
|
@@ -227,7 +230,7 @@ const ListFieldView = ({
|
|
|
227
230
|
borderRadius={3}>
|
|
228
231
|
<FormElementView
|
|
229
232
|
path={`${path}.${index}`}
|
|
230
|
-
field={
|
|
233
|
+
field={getItemField(index)}
|
|
231
234
|
value={item}
|
|
232
235
|
/>
|
|
233
236
|
</Box>
|
|
@@ -413,12 +416,12 @@ export const FieldForm = <F extends Field | ListField>({
|
|
|
413
416
|
)
|
|
414
417
|
}
|
|
415
418
|
|
|
416
|
-
export const Form = <F extends IFormElement>({ field, ...props }: FormProps<F>) => {
|
|
419
|
+
export const Form = <F extends IFormElement>({ field, onSubmit, ...props }: FormProps<F>) => {
|
|
417
420
|
const body =
|
|
418
421
|
isField(field) || isListField(field) ? (
|
|
419
|
-
<FieldForm field={field} {...props} />
|
|
422
|
+
<FieldForm field={field} onSubmit={onSubmit as FormOnSubmit<Field | ListField>} {...props} />
|
|
420
423
|
) : (
|
|
421
|
-
<FieldMapForm field={field} {...props} />
|
|
424
|
+
<FieldMapForm field={field} onSubmit={onSubmit as FormOnSubmit<FieldMap>} {...props} />
|
|
422
425
|
)
|
|
423
426
|
|
|
424
427
|
return <ChempoFormProvider>{body}</ChempoFormProvider>
|
|
@@ -48,7 +48,7 @@ const FormErrorView = () => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export const FormFooter = <F extends IFormElement>({
|
|
51
|
-
renderFooter,
|
|
51
|
+
renderFooter: RenderFooter,
|
|
52
52
|
...props
|
|
53
53
|
}: Pick<FormProps<F>, 'renderFooter' | 'onBack' | 'buttonText'> &
|
|
54
54
|
Pick<UseFormSubmit, 'uploads'> & {
|
|
@@ -63,8 +63,8 @@ export const FormFooter = <F extends IFormElement>({
|
|
|
63
63
|
</Collapse>
|
|
64
64
|
<UploadProgress uploads={uploads} />
|
|
65
65
|
<FormErrorView />
|
|
66
|
-
{
|
|
67
|
-
|
|
66
|
+
{RenderFooter ? (
|
|
67
|
+
<RenderFooter {...props} />
|
|
68
68
|
) : (
|
|
69
69
|
<HStack py={2} borderTop="1px solid" borderColor="background.200" px={3} w="100%">
|
|
70
70
|
{onBack ? <CancelButton onBack={onBack}>Cancel</CancelButton> : null}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { CheckIcon, CloseIcon, EditIcon } from '@chakra-ui/icons'
|
|
2
2
|
import { Flex, IconButton } from '@chakra-ui/react'
|
|
3
3
|
import { palette } from '@chem-po/core'
|
|
4
|
-
import {
|
|
5
|
-
ChempoFormProvider,
|
|
6
|
-
EditableProps,
|
|
7
|
-
Field,
|
|
8
|
-
useColorModeValue,
|
|
9
|
-
useEditable,
|
|
10
|
-
} from '@chem-po/react'
|
|
4
|
+
import { EditableProps, Field, useColorModeValue, useEditable } from '@chem-po/react'
|
|
11
5
|
import React, { CSSProperties, useEffect, useMemo } from 'react'
|
|
12
6
|
import { LoadingOverlay } from '../../loading/Loading'
|
|
13
7
|
import { UploadProgress } from '../UploadProgress'
|
|
@@ -56,74 +50,72 @@ export const Editable = <T extends Field>({
|
|
|
56
50
|
const editingBorderColor = useColorModeValue('#00000055', '#ffffff55')
|
|
57
51
|
|
|
58
52
|
return (
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<Flex
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
53
|
+
<Flex
|
|
54
|
+
borderRadius={4}
|
|
55
|
+
border={`1px dashed ${editHovered && !isEditing ? editingBorderColor : 'transparent'}`}
|
|
56
|
+
flexFlow="column"
|
|
57
|
+
w="100%">
|
|
58
|
+
<Flex align="center" px={1} position="relative" w="100%">
|
|
59
|
+
<Flex
|
|
60
|
+
opacity={isLoading ? 0 : 1}
|
|
61
|
+
transition="all 300ms"
|
|
62
|
+
mr={1}
|
|
63
|
+
border={`1px dashed ${isEditing ? editingBorderColor : 'transparent'}`}
|
|
64
|
+
flex={1}
|
|
65
|
+
minW="0">
|
|
66
|
+
{isEditing || alwaysEditing ? (
|
|
67
|
+
<StandaloneInput
|
|
68
|
+
ref={inputRef}
|
|
69
|
+
value={formattedValue}
|
|
70
|
+
inEditable
|
|
71
|
+
field={field}
|
|
72
|
+
style={{ padding: 0, ...style }}
|
|
73
|
+
onChange={alwaysEditing ? v => submitValue(parse(v)) : v => setValue(parse(v))}
|
|
74
|
+
/>
|
|
75
|
+
) : (
|
|
76
|
+
<FieldView style={style} field={field} value={value} />
|
|
77
|
+
)}
|
|
78
|
+
</Flex>
|
|
79
|
+
{alwaysEditing ? null : (
|
|
80
|
+
<>
|
|
81
|
+
<IconButton
|
|
82
|
+
aria-label="Edit"
|
|
83
|
+
size="xs"
|
|
84
|
+
icon={isEditing ? <CloseIcon width={3} /> : <EditIcon />}
|
|
85
|
+
onMouseEnter={() => setEditHovered(true)}
|
|
86
|
+
onMouseLeave={() => setEditHovered(false)}
|
|
87
|
+
onClick={() => {
|
|
88
|
+
if (isEditing) {
|
|
89
|
+
setValue(value)
|
|
90
|
+
handleEditClose()
|
|
91
|
+
} else handleEditOpen()
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
<Flex
|
|
95
|
+
transition="all 300ms"
|
|
96
|
+
justify="flex-end"
|
|
97
|
+
opacity={isEditing ? 1 : 0}
|
|
98
|
+
overflow="hidden"
|
|
99
|
+
w={isEditing ? '30px' : '0px'}>
|
|
88
100
|
<IconButton
|
|
89
101
|
aria-label="Edit"
|
|
90
102
|
size="xs"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
103
|
+
bg={palette.cyan.light}
|
|
104
|
+
_dark={{ bg: palette.cyan.light, _hover: { bg: palette.cyan.lighter } }}
|
|
105
|
+
_hover={{
|
|
106
|
+
bg: palette.cyan.medium,
|
|
107
|
+
}}
|
|
108
|
+
icon={<CheckIcon filter="drop-shadow(1px 1px 3px #000000aa)" />}
|
|
94
109
|
onClick={() => {
|
|
95
|
-
|
|
96
|
-
setValue(value)
|
|
97
|
-
handleEditClose()
|
|
98
|
-
} else handleEditOpen()
|
|
110
|
+
submit()
|
|
99
111
|
}}
|
|
100
112
|
/>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
overflow="hidden"
|
|
106
|
-
w={isEditing ? '30px' : '0px'}>
|
|
107
|
-
<IconButton
|
|
108
|
-
aria-label="Edit"
|
|
109
|
-
size="xs"
|
|
110
|
-
bg={palette.cyan.light}
|
|
111
|
-
_dark={{ bg: palette.cyan.light, _hover: { bg: palette.cyan.lighter } }}
|
|
112
|
-
_hover={{
|
|
113
|
-
bg: palette.cyan.medium,
|
|
114
|
-
}}
|
|
115
|
-
icon={<CheckIcon filter="drop-shadow(1px 1px 3px #000000aa)" />}
|
|
116
|
-
onClick={() => {
|
|
117
|
-
submit()
|
|
118
|
-
}}
|
|
119
|
-
/>
|
|
120
|
-
</Flex>
|
|
121
|
-
</>
|
|
122
|
-
)}
|
|
123
|
-
<LoadingOverlay isLoading={isLoading} />
|
|
124
|
-
</Flex>
|
|
125
|
-
<UploadProgress uploads={uploads} />
|
|
113
|
+
</Flex>
|
|
114
|
+
</>
|
|
115
|
+
)}
|
|
116
|
+
<LoadingOverlay isLoading={isLoading} />
|
|
126
117
|
</Flex>
|
|
127
|
-
|
|
118
|
+
<UploadProgress uploads={uploads} />
|
|
119
|
+
</Flex>
|
|
128
120
|
)
|
|
129
121
|
}
|
|
@@ -50,7 +50,7 @@ const InputBase = <T extends Field>(props: FieldProps<T>, ref: ForwardedRef<Inpu
|
|
|
50
50
|
if (active) return 'rgba(0,0,0,0.7)'
|
|
51
51
|
return 'rgba(0,0,0,0.3)'
|
|
52
52
|
}, [error, active, touched])
|
|
53
|
-
const { _type, optional, label } = field
|
|
53
|
+
const { _type, optional, label: Label } = field
|
|
54
54
|
const showPlaceholder = useMemo(
|
|
55
55
|
() => _type === 'multipleSelect' || (!!value && _type !== 'file' && _type !== 'boolean'),
|
|
56
56
|
[value, _type],
|
|
@@ -84,10 +84,14 @@ const InputBase = <T extends Field>(props: FieldProps<T>, ref: ForwardedRef<Inpu
|
|
|
84
84
|
pb={pb}
|
|
85
85
|
transition="all 500ms"
|
|
86
86
|
pt={showPlaceholder && !inEditable ? 4 : 0}>
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
|
|
87
|
+
{Label && !inEditable ? (
|
|
88
|
+
typeof Label === 'string' ? (
|
|
89
|
+
<Text color="gray.800" fontSize="sm" px={2}>
|
|
90
|
+
{Label}
|
|
91
|
+
</Text>
|
|
92
|
+
) : (
|
|
93
|
+
<Label />
|
|
94
|
+
)
|
|
91
95
|
) : null}
|
|
92
96
|
<Flex width="100%" borderRadius={4} py={0.5} overflow="hidden" {...styles}>
|
|
93
97
|
<Component ref={ref} {...props} />
|
|
@@ -6,7 +6,7 @@ import { FieldProps } from '../types'
|
|
|
6
6
|
|
|
7
7
|
export const MultipleSelectComponent = forwardRef<InputRef, FieldProps<MultipleSelectField>>(
|
|
8
8
|
({ field, input, inEditable }, ref) => {
|
|
9
|
-
const { options, renderOption, getOptionKey } = field
|
|
9
|
+
const { options, renderOption: RenderOption, getOptionKey } = field
|
|
10
10
|
const { onChange, value, onFocus, onBlur } = input
|
|
11
11
|
const { colorMode } = useColorMode()
|
|
12
12
|
useImperativeHandle(ref, () => ({
|
|
@@ -34,7 +34,7 @@ export const MultipleSelectComponent = forwardRef<InputRef, FieldProps<MultipleS
|
|
|
34
34
|
onChange(value?.includes(o) ? value.filter(v => v !== o) : [...(value ?? []), o])
|
|
35
35
|
}}
|
|
36
36
|
_hover={{ opacity: 0.8 }}>
|
|
37
|
-
{
|
|
37
|
+
<RenderOption value={o} colorMode={colorMode} isSelected={!!value?.includes(o)} />
|
|
38
38
|
</Button>
|
|
39
39
|
</Box>
|
|
40
40
|
))}
|
|
@@ -34,7 +34,7 @@ export const SelectComponent = forwardRef<InputRef, FieldProps<SelectField>>(
|
|
|
34
34
|
},
|
|
35
35
|
}))
|
|
36
36
|
|
|
37
|
-
const
|
|
37
|
+
const RenderOption = customRender ?? DefaultRenderOption
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<Popover strategy="fixed" placement="bottom" matchWidth isOpen={active} onClose={onBlur}>
|
|
@@ -49,7 +49,13 @@ export const SelectComponent = forwardRef<InputRef, FieldProps<SelectField>>(
|
|
|
49
49
|
}}
|
|
50
50
|
variant="unstyled"
|
|
51
51
|
position="relative">
|
|
52
|
-
<Box>
|
|
52
|
+
<Box>
|
|
53
|
+
{selected ? (
|
|
54
|
+
<RenderOption value={selected} colorMode={colorMode} isSelected={true} />
|
|
55
|
+
) : (
|
|
56
|
+
<Text opacity={0.7}>{placeholder}</Text>
|
|
57
|
+
)}
|
|
58
|
+
</Box>
|
|
53
59
|
</Button>
|
|
54
60
|
</PopoverTrigger>
|
|
55
61
|
<PopoverContent w="100%" overflowY="auto" maxH="300px">
|
|
@@ -68,7 +74,7 @@ export const SelectComponent = forwardRef<InputRef, FieldProps<SelectField>>(
|
|
|
68
74
|
_dark={{
|
|
69
75
|
_hover: { bg: 'whiteAlpha.100' },
|
|
70
76
|
}}>
|
|
71
|
-
{
|
|
77
|
+
<RenderOption value={o} colorMode={colorMode} isSelected={o === selected} />
|
|
72
78
|
</Button>
|
|
73
79
|
))}
|
|
74
80
|
</PopoverBody>
|
|
@@ -15,7 +15,7 @@ export const MultipleSelectFieldView = ({
|
|
|
15
15
|
noLabel?: boolean
|
|
16
16
|
style?: CSSProperties
|
|
17
17
|
}) => {
|
|
18
|
-
const { placeholder, renderOption } = field
|
|
18
|
+
const { placeholder, renderOption: RenderOption } = field
|
|
19
19
|
const { colorMode } = useColorMode()
|
|
20
20
|
return (
|
|
21
21
|
<Flex maxW="100%" flexFlow="row wrap" align="center" style={style}>
|
|
@@ -27,7 +27,7 @@ export const MultipleSelectFieldView = ({
|
|
|
27
27
|
{value ? (
|
|
28
28
|
value.map((v: any) => (
|
|
29
29
|
<Box key={field.getOptionKey ? field.getOptionKey(v) : v} p={0.5}>
|
|
30
|
-
{
|
|
30
|
+
<RenderOption value={v} colorMode={colorMode} isSelected={true} />
|
|
31
31
|
</Box>
|
|
32
32
|
))
|
|
33
33
|
) : (
|
|
@@ -2,24 +2,31 @@ import { Flex, Text, useColorMode } from '@chakra-ui/react'
|
|
|
2
2
|
import { SelectField } from '@chem-po/react'
|
|
3
3
|
import React, { CSSProperties } from 'react'
|
|
4
4
|
|
|
5
|
+
const stringifyValue = (value: any) => {
|
|
6
|
+
if (typeof value === 'string') return value
|
|
7
|
+
if (typeof value === 'number') return value.toString()
|
|
8
|
+
if (typeof value === 'boolean') return value.toString()
|
|
9
|
+
return JSON.stringify(value)
|
|
10
|
+
}
|
|
5
11
|
const DefaultRenderOption = (value: any) => {
|
|
6
|
-
|
|
12
|
+
// TODO: maybe handle non-string values more gracefully
|
|
13
|
+
return <Text>{stringifyValue(value)}</Text>
|
|
7
14
|
}
|
|
8
15
|
|
|
9
|
-
export const SelectFieldView = ({
|
|
16
|
+
export const SelectFieldView = <F extends SelectField>({
|
|
10
17
|
field,
|
|
11
18
|
value,
|
|
12
19
|
noLabel,
|
|
13
20
|
style,
|
|
14
21
|
}: {
|
|
15
|
-
field:
|
|
16
|
-
value:
|
|
22
|
+
field: F
|
|
23
|
+
value: F['defaultValue']
|
|
17
24
|
noLabel?: boolean
|
|
18
25
|
style?: CSSProperties
|
|
19
26
|
}) => {
|
|
20
27
|
const { placeholder, renderOption: customRender } = field
|
|
21
28
|
const { colorMode } = useColorMode()
|
|
22
|
-
const
|
|
29
|
+
const RenderOption = customRender ?? DefaultRenderOption
|
|
23
30
|
return (
|
|
24
31
|
<Flex align="center" style={style}>
|
|
25
32
|
{noLabel ? null : (
|
|
@@ -27,7 +34,7 @@ export const SelectFieldView = ({
|
|
|
27
34
|
{placeholder}
|
|
28
35
|
</Text>
|
|
29
36
|
)}
|
|
30
|
-
{value ?
|
|
37
|
+
{value ? <RenderOption value={value} colorMode={colorMode} isSelected={true} /> : 'None'}
|
|
31
38
|
</Flex>
|
|
32
39
|
)
|
|
33
40
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Flex } from '@chakra-ui/react'
|
|
2
2
|
import { AnyObject, ColorMode, DBItem } from '@chem-po/core'
|
|
3
3
|
import { DataList, ListGridOptions } from '@chem-po/react'
|
|
4
|
-
import React
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { GridChildComponentProps } from 'react-window'
|
|
5
6
|
|
|
6
7
|
export interface GridItemProps<T extends AnyObject> {
|
|
7
8
|
list: DataList<T>
|
|
@@ -37,12 +38,12 @@ export const ListCell = <T extends AnyObject>({
|
|
|
37
38
|
px={1}
|
|
38
39
|
py={0.25}
|
|
39
40
|
key={itemIdx}>
|
|
40
|
-
|
|
41
|
-
index
|
|
42
|
-
item
|
|
43
|
-
refetch
|
|
44
|
-
colorMode
|
|
45
|
-
|
|
41
|
+
<Render
|
|
42
|
+
index={itemIdx}
|
|
43
|
+
item={item}
|
|
44
|
+
refetch={refetch ? () => refetch(item._id) : undefined}
|
|
45
|
+
colorMode={colorMode}
|
|
46
|
+
/>
|
|
46
47
|
</Flex>
|
|
47
48
|
)
|
|
48
49
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Flex } from '@chakra-ui/react'
|
|
2
2
|
import { AnyObject, ColorMode, DBItem } from '@chem-po/core'
|
|
3
3
|
import { DataList } from '@chem-po/react'
|
|
4
|
-
import React
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { ListChildComponentProps } from 'react-window'
|
|
5
6
|
|
|
6
7
|
export interface ListItemProps<T extends AnyObject = AnyObject> {
|
|
7
8
|
list: DataList<T>
|
|
@@ -32,7 +33,12 @@ export const ListRow = <T extends AnyObject>({
|
|
|
32
33
|
}}
|
|
33
34
|
style={style}
|
|
34
35
|
key={index}>
|
|
35
|
-
|
|
36
|
+
<Render
|
|
37
|
+
index={index}
|
|
38
|
+
item={item}
|
|
39
|
+
refetch={refetch ? () => refetch(item._id) : undefined}
|
|
40
|
+
colorMode={colorMode}
|
|
41
|
+
/>
|
|
36
42
|
</Flex>
|
|
37
43
|
)
|
|
38
44
|
}
|
|
@@ -7,7 +7,7 @@ import { CircularProgress } from '../loading/CircularProgress'
|
|
|
7
7
|
import { Loading } from '../loading/Loading'
|
|
8
8
|
|
|
9
9
|
export const RedirectView: React.FC<{ loading?: boolean }> = ({ loading }) => {
|
|
10
|
-
const timer = useRef<
|
|
10
|
+
const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
11
11
|
const authLoading = useAuth(s => s.loading)
|
|
12
12
|
|
|
13
13
|
const navigate = useNavigate()
|