@chem-po/react-web 0.0.51 → 0.0.53

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.
Files changed (127) hide show
  1. package/package.json +4 -5
  2. package/src/components/auth/SignIn.tsx +0 -43
  3. package/src/components/auth/index.ts +0 -1
  4. package/src/components/box/CollapseHorizontal.tsx +0 -19
  5. package/src/components/box/ContentBox.tsx +0 -17
  6. package/src/components/box/ExpandOnMount.tsx +0 -48
  7. package/src/components/box/Expandable.tsx +0 -96
  8. package/src/components/box/FullSizeContainer.tsx +0 -50
  9. package/src/components/box/MobileFrame/index.tsx +0 -146
  10. package/src/components/box/MobileFrame/styles.css +0 -35
  11. package/src/components/box/index.ts +0 -6
  12. package/src/components/button/DeleteButton.tsx +0 -178
  13. package/src/components/button/Toggle.tsx +0 -88
  14. package/src/components/button/ViewButton.tsx +0 -30
  15. package/src/components/button/index.ts +0 -3
  16. package/src/components/feed/FeedContentPane.tsx +0 -111
  17. package/src/components/feed/MediaFeed.tsx +0 -200
  18. package/src/components/feed/MediaFeedBackground.tsx +0 -127
  19. package/src/components/feed/MediaFeedRefresh.tsx +0 -78
  20. package/src/components/feed/MediaFeedSwipeUp.tsx +0 -35
  21. package/src/components/feed/constants.ts +0 -11
  22. package/src/components/feed/context.tsx +0 -19
  23. package/src/components/feed/hooks.ts +0 -290
  24. package/src/components/feed/index.ts +0 -2
  25. package/src/components/feed/types.ts +0 -50
  26. package/src/components/form/Condition.tsx +0 -26
  27. package/src/components/form/Field.tsx +0 -39
  28. package/src/components/form/Form.tsx +0 -428
  29. package/src/components/form/FormFooter.tsx +0 -90
  30. package/src/components/form/UploadProgress/index.tsx +0 -38
  31. package/src/components/form/UploadProgress/styles.css +0 -23
  32. package/src/components/form/index.ts +0 -4
  33. package/src/components/form/input/Editable.tsx +0 -155
  34. package/src/components/form/input/InputSlider.tsx +0 -76
  35. package/src/components/form/input/OptionalTag.tsx +0 -33
  36. package/src/components/form/input/StandaloneInput.tsx +0 -41
  37. package/src/components/form/input/boolean/index.tsx +0 -53
  38. package/src/components/form/input/color/index.tsx +0 -126
  39. package/src/components/form/input/date/index.tsx +0 -122
  40. package/src/components/form/input/datetime/index.tsx +0 -93
  41. package/src/components/form/input/file.tsx +0 -379
  42. package/src/components/form/input/hooks/index.ts +0 -2
  43. package/src/components/form/input/hooks/useInputImperativeHandle.ts +0 -16
  44. package/src/components/form/input/hooks/useInputStyles.ts +0 -125
  45. package/src/components/form/input/index.ts +0 -2
  46. package/src/components/form/input/input.css +0 -44
  47. package/src/components/form/input/input.tsx +0 -134
  48. package/src/components/form/input/multipleSelect/index.tsx +0 -89
  49. package/src/components/form/input/number/index.tsx +0 -87
  50. package/src/components/form/input/number/styles.css +0 -8
  51. package/src/components/form/input/select/index.tsx +0 -109
  52. package/src/components/form/input/shared/InputContainer.tsx +0 -13
  53. package/src/components/form/input/socialMedia/index.tsx +0 -165
  54. package/src/components/form/input/text/index.tsx +0 -78
  55. package/src/components/form/input/text/textarea.tsx +0 -43
  56. package/src/components/form/input/time/index.tsx +0 -33
  57. package/src/components/form/input/type.ts +0 -0
  58. package/src/components/form/input/types.ts +0 -4
  59. package/src/components/form/view/file.tsx +0 -36
  60. package/src/components/form/view/index.tsx +0 -52
  61. package/src/components/form/view/multipleSelect.tsx +0 -51
  62. package/src/components/form/view/select.tsx +0 -50
  63. package/src/components/form/view/types.ts +0 -11
  64. package/src/components/index.ts +0 -14
  65. package/src/components/list/Body/InfiniteScrollGridBody.tsx +0 -177
  66. package/src/components/list/Body/InfiniteScrollListBody.tsx +0 -114
  67. package/src/components/list/Body/ListBody.tsx +0 -24
  68. package/src/components/list/Body/PagedGridBody.tsx +0 -104
  69. package/src/components/list/Body/PagedListBody.tsx +0 -92
  70. package/src/components/list/Body/hooks.ts +0 -84
  71. package/src/components/list/DataList.tsx +0 -33
  72. package/src/components/list/ListContainer.tsx +0 -21
  73. package/src/components/list/ListContent.tsx +0 -54
  74. package/src/components/list/ListCreate.tsx +0 -57
  75. package/src/components/list/ListFilters.tsx +0 -182
  76. package/src/components/list/ListFooter.tsx +0 -458
  77. package/src/components/list/ListHeader.tsx +0 -180
  78. package/src/components/list/ListItem/ListCell.tsx +0 -49
  79. package/src/components/list/ListItem/ListRow.tsx +0 -44
  80. package/src/components/list/ListItemView.tsx +0 -53
  81. package/src/components/list/ListSort.tsx +0 -84
  82. package/src/components/list/NoItems.tsx +0 -33
  83. package/src/components/list/constants.ts +0 -1
  84. package/src/components/list/index.ts +0 -4
  85. package/src/components/list/types.ts +0 -26
  86. package/src/components/list/utils.ts +0 -63
  87. package/src/components/loading/CircularProgress.tsx +0 -12
  88. package/src/components/loading/Loading.tsx +0 -160
  89. package/src/components/loading/LoadingImage.tsx +0 -128
  90. package/src/components/loading/LoadingSwitch.tsx +0 -78
  91. package/src/components/loading/index.ts +0 -4
  92. package/src/components/media/PlayButton.tsx +0 -95
  93. package/src/components/media/index.ts +0 -1
  94. package/src/components/modal/DefaultModal.tsx +0 -18
  95. package/src/components/modal/DesktopModal.tsx +0 -16
  96. package/src/components/modal/ForceMobile.tsx +0 -7
  97. package/src/components/modal/MobileModal.tsx +0 -89
  98. package/src/components/modal/index.ts +0 -3
  99. package/src/components/modal/type.ts +0 -7
  100. package/src/components/nav/NavBar.tsx +0 -102
  101. package/src/components/nav/index.ts +0 -1
  102. package/src/components/overlay/ImageViewOverlay.tsx +0 -88
  103. package/src/components/overlay/MobileOverlay.tsx +0 -23
  104. package/src/components/overlay/index.ts +0 -2
  105. package/src/components/text/GradientText/index.tsx +0 -17
  106. package/src/components/text/GradientText/styles.css +0 -5
  107. package/src/components/text/NumberTicker.tsx +0 -28
  108. package/src/components/text/index.ts +0 -1
  109. package/src/components/theme/colorMode/DarkModeToggle.tsx +0 -40
  110. package/src/components/theme/colorMode/index.ts +0 -1
  111. package/src/components/theme/index.ts +0 -1
  112. package/src/components/view/ErrorView.tsx +0 -14
  113. package/src/components/view/RedirectView.tsx +0 -43
  114. package/src/components/view/index.ts +0 -2
  115. package/src/contexts/index.ts +0 -2
  116. package/src/contexts/theme.ts +0 -316
  117. package/src/contexts/view.tsx +0 -26
  118. package/src/custom.d.ts +0 -4
  119. package/src/hooks/index.ts +0 -1
  120. package/src/hooks/ui/index.ts +0 -1
  121. package/src/hooks/ui/useBorderColor.ts +0 -4
  122. package/src/index.ts +0 -5
  123. package/src/store/index.ts +0 -1
  124. package/src/store/usePlayer.ts +0 -75
  125. package/src/store/useScreen.ts +0 -22
  126. package/src/types/forms.ts +0 -5
  127. package/src/types/index.ts +0 -1
@@ -1,44 +0,0 @@
1
- import { Flex } from '@chakra-ui/react'
2
- import { AnyObject, ColorMode, DBItem } from '@chem-po/core'
3
- import { DataList } from '@chem-po/react'
4
- import React from 'react'
5
- import { ListChildComponentProps } from 'react-window'
6
-
7
- export interface ListItemProps<T extends AnyObject = AnyObject> {
8
- list: DataList<T>
9
- items: Array<DBItem<T>>
10
- mobileLayout: boolean
11
- onSelect: (item: DBItem<T>) => void
12
- colorMode: ColorMode
13
- refetch?: (id: string) => Promise<void>
14
- }
15
- export const ListRow = <T extends AnyObject>({
16
- data,
17
- index,
18
- style,
19
- }: ListChildComponentProps<ListItemProps<T>>) => {
20
- const { list, items, onSelect, refetch, mobileLayout, colorMode } = data || {}
21
- const { ItemPreview: RenderItem, mobile } = list
22
-
23
- const Render = mobileLayout ? (mobile?.ItemPreview ?? RenderItem) : RenderItem
24
- const item = items[index]
25
- if (!item) return null
26
- return (
27
- <Flex
28
- display="flex"
29
- cursor="pointer"
30
- aria-label="list-item"
31
- onClick={() => {
32
- onSelect(items[index])
33
- }}
34
- style={style}
35
- key={index}>
36
- <Render
37
- index={index}
38
- item={item}
39
- refetch={refetch ? () => refetch(item.id) : undefined}
40
- colorMode={colorMode}
41
- />
42
- </Flex>
43
- )
44
- }
@@ -1,53 +0,0 @@
1
- import { Text, useColorMode, useColorModeValue } from '@chakra-ui/react'
2
- import { AnyObject, DBItem } from '@chem-po/core'
3
- import { useDataList, usePaginatedList } from '@chem-po/react'
4
- import React, { useEffect, useMemo, useState } from 'react'
5
- import { DefaultModal } from '../modal'
6
-
7
- export const ListItemView = () => {
8
- const { selectedItemId, deselectItem, list } = useDataList()
9
- const { ItemView, itemName } = list || {}
10
- const [contentOffset, setContentOffset] = useState({ x: 0, y: 0 })
11
- const {
12
- data: { data },
13
- // refetchItem,
14
- } = usePaginatedList()
15
- const item = useMemo(
16
- () => data.find(d => d.id === selectedItemId) ?? null,
17
- [data, selectedItemId],
18
- )
19
- const { colorMode } = useColorMode()
20
- const errorColor = useColorModeValue('red.600', 'red.300')
21
- const [prevItem, setPrevItem] = useState<DBItem<AnyObject> | null>(null)
22
- useEffect(() => {
23
- if (item) {
24
- setPrevItem(item)
25
- }
26
- }, [item])
27
-
28
- return (
29
- <DefaultModal
30
- contentProps={{
31
- p: 0,
32
- transition: 'all 300ms',
33
- transform: `translate(${contentOffset.x}px, ${contentOffset.y}px)`,
34
- }}
35
- scrollBehavior="inside"
36
- onClose={deselectItem}
37
- isOpen={!!ItemView && !!selectedItemId}>
38
- {ItemView && prevItem ? (
39
- <ItemView
40
- item={prevItem}
41
- colorMode={colorMode}
42
- clearContentOffset={() => setContentOffset({ x: 0, y: 0 })}
43
- updateContentOffset={(x, y) => setContentOffset({ x, y })}
44
- // onEdited={onEdited}
45
- />
46
- ) : (
47
- <Text color={errorColor} p={4}>
48
- Error displaying {itemName}
49
- </Text>
50
- )}
51
- </DefaultModal>
52
- )
53
- }
@@ -1,84 +0,0 @@
1
- import { ArrowDownIcon, ArrowUpIcon } from '@chakra-ui/icons'
2
- import { Button, HStack, Text, useColorMode } from '@chakra-ui/react'
3
- import { SortDirection } from '@chem-po/core'
4
- import { SortPreset, useDataList } from '@chem-po/react'
5
- import React, { useMemo } from 'react'
6
- import { CollapseHorizontal } from '../box/CollapseHorizontal'
7
-
8
- const SortButton = ({ preset }: { preset: SortPreset }) => {
9
- const { setSort: setSortFromPreset, query } = useDataList()
10
- const { sort } = query
11
- const { label, key, Render } = preset
12
- const active = useMemo<SortDirection | null>(
13
- () => (sort?.key === key ? sort.direction : null),
14
- [sort, key],
15
- )
16
- const { colorMode } = useColorMode()
17
-
18
- const color = useMemo(() => {
19
- if (active) return 'white'
20
- return colorMode === 'light' ? 'gray.500' : 'gray.400'
21
- }, [active, colorMode])
22
- const icon = useMemo(
23
- () => (sort?.direction === 'asc' ? <ArrowUpIcon w={4} h={4} /> : <ArrowDownIcon w={4} h={4} />),
24
- [sort],
25
- )
26
-
27
- return (
28
- <Button
29
- size="xs"
30
- variant="outline"
31
- bg={active ? 'accent.400' : 'transparent'}
32
- transition="all 300ms"
33
- textShadow={active ? '0 0 2px rgba(0,0,0,0.7)' : 'none'}
34
- boxShadow={`0px 0px 1px 1px ${active ? 'transparent' : '#00000033'}`}
35
- border="none"
36
- // borderColor={active ? 'transparent' : 'blackAlpha.200'}
37
- _dark={{
38
- // borderColor: active ? 'transparent' : 'whiteAlpha.300',
39
- boxShadow: `0px 0px 1px 1px ${active ? 'transparent' : '#ffffff66'}`,
40
- color,
41
- textShadow: active ? '0 0 2px rgba(0,0,0,0.7)' : 'none',
42
- }}
43
- aria-label={label}
44
- opacity={active ? 1 : 0.8}
45
- height={6}
46
- pl={active ? 3 : 2}
47
- pr={2}
48
- _hover={{ opacity: 1 }}
49
- gap={0}
50
- color={color}
51
- onClick={() =>
52
- setSortFromPreset({
53
- direction: active && sort?.direction === 'asc' ? 'desc' : 'asc',
54
- key,
55
- })
56
- }>
57
- {Render ? (
58
- <Render active={active} colorMode={colorMode} preset={preset} />
59
- ) : (
60
- <Text fontWeight={600} fontSize="sm" color={color}>
61
- {label}
62
- </Text>
63
- )}
64
- <CollapseHorizontal active={!!active} h="16px" width={20}>
65
- {icon}
66
- </CollapseHorizontal>
67
- </Button>
68
- )
69
- }
70
-
71
- export const ListSortView = () => {
72
- const {
73
- list: { sortPresets },
74
- } = useDataList()
75
-
76
- if (!sortPresets) return null
77
- return (
78
- <HStack spacing={2}>
79
- {sortPresets.map(preset => (
80
- <SortButton key={preset.label} preset={preset} />
81
- ))}
82
- </HStack>
83
- )
84
- }
@@ -1,33 +0,0 @@
1
- import { Flex, Text } from '@chakra-ui/react'
2
- import { toPlural } from '@chem-po/core'
3
- import { useDataList, usePaginatedList } from '@chem-po/react'
4
- import React, { useMemo } from 'react'
5
- import { Loading } from '../loading'
6
-
7
- export const NoItemsRow = () => {
8
- const {
9
- list,
10
- search: { debounced, search },
11
- } = useDataList()
12
- const {
13
- data: { isLoading },
14
- } = usePaginatedList()
15
- const showLoading = useMemo(
16
- () => isLoading || debounced !== search,
17
- [isLoading, debounced, search],
18
- )
19
- const { itemName, pluralItemName, noItemsMessage, searchRequired } = list
20
- return (
21
- <Flex justify="center" align="flex-start" w="100%" h="100%">
22
- {showLoading ? (
23
- <Loading text={`Loading ${pluralItemName ?? toPlural(itemName)}`} />
24
- ) : (
25
- <Text textAlign="center" flex={1} p={3} fontStyle="italic" opacity={0.7}>
26
- {!debounced && searchRequired
27
- ? `Search ${pluralItemName ?? toPlural(itemName)}`
28
- : (noItemsMessage ?? `No ${pluralItemName ?? toPlural(itemName)}`)}
29
- </Text>
30
- )}
31
- </Flex>
32
- )
33
- }
@@ -1 +0,0 @@
1
- export const FETCH_LIMIT = 15
@@ -1,4 +0,0 @@
1
- export * from './DataList'
2
- export * from './ListContainer'
3
- export * from './ListContent'
4
- export * from './types'
@@ -1,26 +0,0 @@
1
- import { BoxProps, FlexProps } from '@chakra-ui/react'
2
- import { AnyObject } from '@chem-po/core'
3
- import { ListProviderProps } from '@chem-po/react'
4
- import { ReactNode } from 'react'
5
-
6
- export interface DataListHeaderProps {
7
- onResize: (size: { height: number; width: number }) => void
8
- refetch?: () => void
9
- boxProps?: BoxProps
10
- }
11
-
12
- export interface DataListFooterProps {
13
- flexProps?: FlexProps
14
- noFooter?: boolean
15
- onResize: (size: { height: number; width: number }) => void
16
- }
17
-
18
- export type ListViewProps<T extends AnyObject> = ListProviderProps<T> & {
19
- flexProps?: FlexProps
20
- footerProps?: FlexProps
21
- noFooter?: boolean
22
- headerProps?: BoxProps
23
- modals?: ReactNode
24
- }
25
-
26
- export type ListContentProps<T extends AnyObject> = Omit<ListViewProps<T>, 'list' | 'flexProps'>
@@ -1,63 +0,0 @@
1
- import {
2
- AnyObject,
3
- arrayOperators,
4
- BaseQuery,
5
- QueryFilter,
6
- SearchPath,
7
- stringTransforms,
8
- } from '@chem-po/core'
9
- import { FilterPreset } from '@chem-po/react'
10
- import { Query, query, where } from 'firebase/firestore'
11
-
12
- export const getIsDynamicSize = (itemHeight: number | ((item: any) => number)) =>
13
- typeof itemHeight === 'function'
14
-
15
- export const getTextSearchQuery = <T extends AnyObject>(
16
- baseQuery: Query<T>,
17
- searchQuery: string,
18
- searchPath: SearchPath<T>,
19
- ) => {
20
- let trimmed = searchQuery.trim()
21
- if (!trimmed) return baseQuery
22
- if (searchPath.transform) trimmed = stringTransforms[searchPath.transform](trimmed)
23
- return query(
24
- baseQuery,
25
- where(searchPath.prop, '>=', trimmed),
26
- where(searchPath.prop, '<=', `${trimmed}\uf8ff`),
27
- )
28
- }
29
- export const getSearchQueries = <T extends AnyObject>(
30
- baseQuery: Query<T>,
31
- searchData: BaseQuery<T>['search'],
32
- ): Array<Query<T>> => {
33
- if (!searchData) return [baseQuery]
34
- const { paths, query: search } = searchData
35
- if (!paths?.length || !search) return [baseQuery]
36
- return paths.map(path => getTextSearchQuery(baseQuery, search, path))
37
- }
38
- const nativeFilterMatchesPreset = <T extends AnyObject>(
39
- nativeFilter: QueryFilter<T>,
40
- presetFilter: QueryFilter<T>,
41
- ) => {
42
- if (nativeFilter.key !== presetFilter.key) return false
43
- if (nativeFilter.operator !== presetFilter.operator) return false
44
- if (arrayOperators.includes(nativeFilter.operator)) {
45
- const nativeValues = Array.isArray(nativeFilter.value)
46
- ? nativeFilter.value
47
- : [nativeFilter.value]
48
- const presetValues = Array.isArray(presetFilter.value)
49
- ? presetFilter.value
50
- : [presetFilter.value]
51
- if (presetValues.every(value => !nativeValues.includes(value))) return false
52
- return true
53
- }
54
- return nativeFilter.value === presetFilter.value
55
- }
56
-
57
- export const filterMatchesPreset = <T extends AnyObject>(
58
- filter: QueryFilter<T>,
59
- { nativeFilter }: FilterPreset<T>,
60
- ) => {
61
- const nativeFilters = Array.isArray(nativeFilter) ? nativeFilter : [nativeFilter]
62
- return nativeFilters.every(nativeFilter => nativeFilterMatchesPreset(nativeFilter, filter))
63
- }
@@ -1,12 +0,0 @@
1
- import {
2
- CircularProgressProps,
3
- CircularProgress as Orig,
4
- useColorModeValue,
5
- } from '@chakra-ui/react'
6
- import React from 'react'
7
-
8
- export const CircularProgress = (props: CircularProgressProps) => {
9
- const color = useColorModeValue('gray.400', 'gray.400')
10
- const bg = useColorModeValue('gray.300', 'gray.600')
11
- return <Orig isIndeterminate trackColor={bg} color={color} {...props} />
12
- }
@@ -1,160 +0,0 @@
1
- import { Center, CenterProps, HStack, StackProps, Text, useColorModeValue } from '@chakra-ui/react'
2
- import { ThemedAsset, useAppAssets } from '@chem-po/react'
3
- import { LottieOptions, useLottie } from 'lottie-react'
4
- import React, { useEffect, useMemo } from 'react'
5
- import { ContentBox } from '../box/ContentBox'
6
- // import loadingAnimation from './circles_loading.json'
7
- // import loadingAnimationLight from './circles_loading_light.json'
8
-
9
- export const LottieLoadingLogo = ({
10
- size = 30,
11
- isLoading,
12
- speed = 2,
13
- inFeed,
14
- asset,
15
- }: {
16
- size?: number | string
17
- color?: string
18
- isLoading: boolean
19
- asset: ThemedAsset
20
- inFeed?: boolean
21
- speed?: number
22
- }) => {
23
- const _animationData = useColorModeValue(asset.default, asset.dark ?? asset.default)
24
- const animationData = useMemo(
25
- () => (inFeed ? (asset.dark ?? asset.default) : _animationData),
26
- [_animationData, asset, inFeed],
27
- )
28
- const options = useMemo<LottieOptions>(
29
- () => ({
30
- // animationData: getLoaderJson(propColor || defaultColor),
31
- animationData,
32
- loop: true,
33
- }),
34
- [animationData],
35
- )
36
- const style = useMemo(
37
- () => ({
38
- width: size,
39
- height: size,
40
- opacity: isLoading ? 0.85 : 0,
41
- transition: 'opacity 300ms ease-in-out',
42
- }),
43
- [size, isLoading],
44
- )
45
- const { View, pause, play, setSpeed } = useLottie(options, style)
46
- useEffect(() => {
47
- setSpeed(speed)
48
- }, [setSpeed, speed])
49
- useEffect(() => {
50
- if (isLoading) {
51
- play()
52
- } else pause()
53
- }, [isLoading, play, pause])
54
-
55
- return <>{View}</>
56
- }
57
-
58
- const SVGLoadingLogo = ({
59
- size = 30,
60
- isLoading,
61
- asset,
62
- inFeed,
63
- }: {
64
- size?: number | string
65
- isLoading: boolean
66
- asset: ThemedAsset
67
- inFeed?: boolean
68
- }) => {
69
- const _svg = useColorModeValue(asset.default, asset.dark ?? asset.default)
70
- const svg = useMemo(() => (inFeed ? (asset.dark ?? asset.default) : _svg), [_svg, asset, inFeed])
71
- const style = useMemo(
72
- () => ({
73
- width: size,
74
- height: size,
75
- opacity: isLoading ? 0.85 : 0,
76
- transition: 'opacity 300ms ease-in-out',
77
- }),
78
- [size, isLoading],
79
- )
80
- return <img src={svg} style={style} alt="loading" />
81
- }
82
-
83
- const LoadingBody = ({ isLoading, size }: { isLoading: boolean; size?: number | string }) => {
84
- const { loading } = useAppAssets()
85
- if (loading.lottieJson)
86
- return <LottieLoadingLogo isLoading={isLoading} size={size} asset={loading.lottieJson} />
87
- if (loading.svg) return <SVGLoadingLogo isLoading={isLoading} size={size} asset={loading.svg} />
88
- return null
89
- }
90
-
91
- export const LoadingLogo = ({
92
- isLoading,
93
- size,
94
- inFeed,
95
- }: {
96
- isLoading: boolean
97
- size?: number | string
98
- inFeed?: boolean
99
- }) => {
100
- const { loading } = useAppAssets()
101
- if (loading.lottieJson)
102
- return (
103
- <LottieLoadingLogo
104
- inFeed={inFeed}
105
- isLoading={isLoading}
106
- size={size}
107
- asset={loading.lottieJson}
108
- />
109
- )
110
- if (loading.svg)
111
- return <SVGLoadingLogo inFeed={inFeed} isLoading={isLoading} size={size} asset={loading.svg} />
112
- return <Text color="red">ERROR: No loading animation found</Text>
113
- }
114
-
115
- export const Loading = ({
116
- text = 'Loading...',
117
- inBox,
118
- stackProps,
119
- }: {
120
- text?: string
121
- inBox?: boolean
122
- stackProps?: StackProps
123
- }) => {
124
- const body = (
125
- <HStack p={2} {...stackProps}>
126
- <LoadingBody isLoading />
127
- <Text opacity={0.8} fontSize="sm">
128
- {text}
129
- </Text>
130
- </HStack>
131
- )
132
- return inBox ? <ContentBox>{body}</ContentBox> : body
133
- }
134
-
135
- export const LoadingOverlay = ({
136
- isLoading,
137
- text,
138
- inFeed,
139
- ...props
140
- }: { isLoading: boolean; text?: string; inFeed?: boolean } & CenterProps) => {
141
- const bg = useColorModeValue('#ffffffaa', '#00000088')
142
- return (
143
- <Center
144
- pos={'absolute'}
145
- top={0}
146
- left={0}
147
- right={0}
148
- bottom={0}
149
- bg={bg}
150
- pointerEvents={isLoading ? 'auto' : 'none'}
151
- opacity={isLoading ? 1 : 0}
152
- {...props}>
153
- {!text ? (
154
- <LoadingLogo inFeed={inFeed} size={100} isLoading={isLoading} />
155
- ) : (
156
- <Loading text={text} />
157
- )}
158
- </Center>
159
- )
160
- }
@@ -1,128 +0,0 @@
1
- import { BoxProps, Center, IconButton, Image, ImageProps } from '@chakra-ui/react'
2
- import { useColorModeValue, useMounted } from '@chem-po/react'
3
- import React, { SyntheticEvent, useCallback, useEffect, useRef, useState } from 'react'
4
- import { ImageViewOverlay } from '../overlay/ImageViewOverlay'
5
- import { LoadingLogo } from './Loading'
6
-
7
- export interface LoadingImageProps {
8
- src?: string | null
9
- loadingOverride?: boolean
10
- onLoad?: ImageProps['onLoad']
11
- alt?: string
12
- withFullView?: boolean
13
- buttonFullView?: boolean
14
- imageProps?: Omit<ImageProps, 'onLoad'>
15
- }
16
-
17
- const emptyPng =
18
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII='
19
- export const LoadingImage = ({
20
- src,
21
- loadingOverride,
22
- alt,
23
- onLoad,
24
- width,
25
- height,
26
- withFullView,
27
- buttonFullView,
28
- imageProps,
29
- ...boxProps
30
- }: LoadingImageProps & Omit<BoxProps, 'onLoad'>) => {
31
- const [imageLoading, setImageLoading] = useState(!!src)
32
- const imageRef = useRef<HTMLImageElement>(null)
33
-
34
- const [viewing, setViewing] = useState(false)
35
- const mounted = useMounted(100)
36
- useEffect(() => {
37
- if (imageRef.current?.complete) {
38
- setImageLoading(true)
39
- }
40
- }, [imageRef])
41
-
42
- const handleImageLoad = useCallback(
43
- (e: SyntheticEvent<HTMLImageElement>) => {
44
- setImageLoading(false)
45
- if (onLoad) onLoad(e)
46
- },
47
- [onLoad],
48
- )
49
-
50
- const [prevSrc, setPrevSrc] = useState(src)
51
- useEffect(() => {
52
- if (src) setPrevSrc(src)
53
- }, [src, prevSrc])
54
-
55
- const fullViewButtonFilter = useColorModeValue(
56
- 'none',
57
- 'brightness(300%) drop-shadow(1px 1px 3px #00000066)',
58
- )
59
-
60
- const loading = imageLoading || !!loadingOverride
61
- return (
62
- <Center
63
- opacity={mounted ? 1 : 0}
64
- transition="opacity 333ms"
65
- w={width ?? '100%'}
66
- h={height ?? '100%'}
67
- overflow="hidden"
68
- position="relative"
69
- {...boxProps}>
70
- <Image
71
- src={src ?? emptyPng}
72
- alt={alt}
73
- onClick={!withFullView || buttonFullView ? undefined : () => setViewing(true)}
74
- onLoad={handleImageLoad}
75
- onLoadStart={() => setImageLoading(true)}
76
- top={0}
77
- left={0}
78
- cursor={!withFullView || buttonFullView ? 'default' : 'pointer'}
79
- draggable={false}
80
- opacity={src && !loading ? 1 : 0}
81
- transition="opacity 300ms ease-in-out"
82
- w="100%"
83
- h="100%"
84
- objectFit={src ? 'cover' : 'contain'}
85
- zIndex={0}
86
- {...imageProps}
87
- />
88
- {buttonFullView ? (
89
- <IconButton
90
- pos="absolute"
91
- top={2}
92
- right={2}
93
- zIndex={1}
94
- w={7}
95
- minW={0}
96
- borderRadius={10}
97
- h={7}
98
- size="sm"
99
- aria-label="View Image"
100
- icon={
101
- <Image
102
- height="20px"
103
- src="/icons/open_in_full.svg"
104
- opacity={0.8}
105
- filter={fullViewButtonFilter}
106
- />
107
- }
108
- onClick={() => setViewing(true)}
109
- />
110
- ) : null}
111
- <Center
112
- pos="absolute"
113
- top={0}
114
- left={0}
115
- zIndex={2}
116
- pointerEvents="none"
117
- transition="opacity 0.5s ease-in-out"
118
- opacity={loading || !src ? 1 : 0}
119
- w="100%"
120
- h="100%">
121
- <LoadingLogo isLoading={loading} size="60%" />
122
- </Center>
123
- {viewing ? (
124
- <ImageViewOverlay src={src ?? emptyPng} onClose={() => setViewing(false)} />
125
- ) : null}
126
- </Center>
127
- )
128
- }
@@ -1,78 +0,0 @@
1
- import { Center, Flex, Switch, Text, useToast } from '@chakra-ui/react'
2
- import React, { useCallback, useState } from 'react'
3
- import { Loading } from './Loading'
4
-
5
- export const LoadingSwitch = ({
6
- value,
7
- label,
8
- onChange,
9
- }: {
10
- value: boolean
11
- label: string
12
- onChange: (updated: boolean) => Promise<void>
13
- }) => {
14
- const toast = useToast()
15
- const [isLoading, setIsLoading] = useState(false)
16
-
17
- const reportComplete = useCallback((fetchedOn: number) => {
18
- const buffer = Math.max(0, 1000 - (Date.now() - fetchedOn))
19
- setTimeout(() => {
20
- setIsLoading(false)
21
- }, buffer)
22
- }, [])
23
-
24
- return (
25
- <Flex
26
- py={1}
27
- pr={2}
28
- pl={3}
29
- bg="gray.700"
30
- borderRadius={12}
31
- boxShadow="0 0 4px black"
32
- pos="relative"
33
- align="center">
34
- <Flex
35
- opacity={isLoading ? 0 : 1}
36
- transition={`opacity 300ms ${isLoading ? 'ease-out' : 'ease-in'}`}
37
- pointerEvents={isLoading ? 'none' : 'auto'}
38
- align="center"
39
- gap={2}>
40
- <Text style={{ fontSize: '1.2rem', height: '24px' }}>{label}</Text>
41
- <Switch
42
- size="md"
43
- isChecked={value}
44
- onChange={e => {
45
- setIsLoading(true)
46
- const fetchedOn = Date.now()
47
- onChange(e.target.checked).catch(err => {
48
- console.error(err)
49
- toast({
50
- title: 'Error',
51
- description: err?.message ?? 'Error occurred',
52
- status: 'error',
53
- duration: 5000,
54
- isClosable: true,
55
- })
56
- })
57
-
58
- reportComplete(fetchedOn)
59
- }}
60
- />
61
- </Flex>
62
- <Center
63
- opacity={isLoading ? 1 : 0}
64
- transition={`opacity 300ms ${!isLoading ? 'ease-out' : 'ease-in'}`}
65
- pointerEvents={isLoading ? 'auto' : 'none'}
66
- pos="absolute"
67
- top="-10%"
68
- left="-10%"
69
- w="120%"
70
- borderRadius={8}
71
- p={1}
72
- gap={2}
73
- h="120%">
74
- <Loading />
75
- </Center>
76
- </Flex>
77
- )
78
- }