@codeleap/web 3.14.1 → 3.14.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeleap/web",
3
- "version": "3.14.1",
3
+ "version": "3.14.2",
4
4
  "main": "src/index.ts",
5
5
  "repository": {
6
6
  "url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
@@ -27,6 +27,8 @@
27
27
  "masonic": "^3.7.0",
28
28
  "rc-slider": "^9.7.5",
29
29
  "react-autosize-textarea": "^7.1.0",
30
+ "react-dropzone": "^14.2.3",
31
+ "react-image-crop": "^10.1.8",
30
32
  "react-input-mask": "^2.0.4",
31
33
  "react-number-format": "^5.2.1",
32
34
  "react-select": "^5.7.3",
@@ -68,6 +68,7 @@ export const Button = (buttonProps: ButtonProps) => {
68
68
  selected,
69
69
  loaderProps = {},
70
70
  debugName,
71
+ style = {},
71
72
  ...props
72
73
  } = allProps
73
74
 
@@ -114,7 +115,7 @@ export const Button = (buttonProps: ButtonProps) => {
114
115
 
115
116
  return (
116
117
  <Touchable
117
- css={_styles.wrapper}
118
+ css={[_styles.wrapper, style]}
118
119
  component='button'
119
120
  debugComponent='Button'
120
121
  disabled={disabled}
@@ -0,0 +1,101 @@
1
+ import React, { forwardRef } from 'react'
2
+ import {
3
+ getNestedStylesByKey,
4
+ useDefaultComponentStyle,
5
+ } from '@codeleap/common'
6
+ import { CropPickerPresets } from './styles'
7
+ import { CropPickerProps } from './types'
8
+ import { useCropPicker } from './useCropPicker'
9
+ import { Modal, Button, FileInput, FileInputRef } from '../components'
10
+
11
+ const ReactCrop: React.Component = require('react-image-crop').Component
12
+ import 'react-image-crop/dist/ReactCrop.css'
13
+
14
+ export * from './styles'
15
+ export * from './types'
16
+ export * from './utils'
17
+ export * from './useCropPicker'
18
+
19
+ export const _CropPicker = forwardRef<FileInputRef, CropPickerProps>(
20
+ (props: CropPickerProps, ref) => {
21
+ const {
22
+ onFileSelect,
23
+ targetCrop,
24
+ variants = [],
25
+ responsiveVariants = {},
26
+ styles = {},
27
+ modalProps = {},
28
+ title = 'Crop Image',
29
+ confirmButton = 'Confirm Crop',
30
+ debugName,
31
+ handle,
32
+ ...fileInputProps
33
+ } = props
34
+
35
+ const {
36
+ onConfirmCrop,
37
+ onFilesReturned,
38
+ onClose,
39
+ fileInputRef,
40
+ visible,
41
+ image,
42
+ crop,
43
+ setRelativeCrop,
44
+ handleCropChange,
45
+ } = handle || useCropPicker({ onFileSelect, ref, ...targetCrop })
46
+
47
+ const variantStyles = useDefaultComponentStyle<
48
+ 'u:CropPicker',
49
+ typeof CropPickerPresets
50
+ >('u:CropPicker', {
51
+ variants,
52
+ responsiveVariants,
53
+ styles,
54
+ })
55
+
56
+ const buttonStyles = getNestedStylesByKey('confirmButton', variantStyles)
57
+ const modalStyles = getNestedStylesByKey('modal', variantStyles)
58
+
59
+ return (
60
+ <>
61
+ <FileInput
62
+ ref={fileInputRef}
63
+ onChange={(files) => onFilesReturned(files)}
64
+ {...fileInputProps}
65
+ />
66
+ <Modal
67
+ visible={visible}
68
+ toggle={onClose}
69
+ title={title}
70
+ styles={modalStyles}
71
+ footer={
72
+ <Button
73
+ text={confirmButton}
74
+ styles={buttonStyles}
75
+ onPress={onConfirmCrop}
76
+ debugName={debugName}
77
+ />
78
+ }
79
+ {...modalProps}
80
+ >
81
+ {!!image?.src && (
82
+ <ReactCrop
83
+ crop={crop}
84
+ onChange={handleCropChange}
85
+ onComplete={(_, relCrop) => setRelativeCrop(relCrop)}
86
+ style={variantStyles.previewSize}
87
+ {...targetCrop}
88
+ >
89
+ <img
90
+ src={image?.src}
91
+ css={[variantStyles.cropPreview, variantStyles.previewSize]}
92
+ />
93
+ </ReactCrop>
94
+ )}
95
+ </Modal>
96
+ </>
97
+ )
98
+ },
99
+ )
100
+
101
+ export const CropPicker = React.memo(_CropPicker) as (props: CropPickerProps) => JSX.Element
@@ -0,0 +1,15 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { ButtonComposition } from '../Button'
3
+ import { ModalComposition } from '../Modal'
4
+
5
+ export type CropPickerComposition =
6
+ | 'cropPreview'
7
+ | 'previewSize'
8
+ | `confirmButton${Capitalize<ButtonComposition>}`
9
+ | `modal${Capitalize<ModalComposition>}`
10
+
11
+ const createCropPickerStyle =
12
+ createDefaultVariantFactory<CropPickerComposition>()
13
+
14
+ export const CropPickerPresets = includePresets((style) => createCropPickerStyle(() => ({ modalWrapper: style })),
15
+ )
@@ -0,0 +1,29 @@
1
+ import { AnyRef, ComponentVariants } from '@codeleap/common'
2
+ import { FileInputProps, FileInputRef } from '../FileInput'
3
+ import { CropPickerComposition, CropPickerPresets } from './styles'
4
+ import { StylesOf } from '../../types'
5
+ import { ReactCropProps } from 'react-image-crop'
6
+ import { ModalProps } from '../Modal'
7
+ import { useCropPicker } from './useCropPicker'
8
+
9
+ export type BaseCropProps = Partial<ReactCropProps>
10
+
11
+ export type CropPickerProps = Partial<FileInputProps> &
12
+ ComponentVariants<typeof CropPickerPresets> & {
13
+ styles?: StylesOf<CropPickerComposition>
14
+ style?: React.CSSProperties
15
+ targetCrop?: BaseCropProps
16
+ modalProps?: Partial<ModalProps>
17
+ title?: string
18
+ confirmButton?: string
19
+ debugName: string
20
+ handle?: ReturnType<typeof useCropPicker>
21
+ ref: AnyRef<HTMLElement>
22
+ }
23
+
24
+ export type ImageReading = HTMLImageElement
25
+
26
+ export type UseCropPickerProps = Partial<ReactCropProps> & {
27
+ onFileSelect: FileInputProps['onFileSelect']
28
+ ref: React.MutableRefObject<FileInputRef> | React.Ref<FileInputRef>
29
+ }
@@ -0,0 +1,134 @@
1
+ import {
2
+ WebInputFile,
3
+ useBooleanToggle,
4
+ useCallback,
5
+ useImperativeHandle,
6
+ usePromise,
7
+ useRef,
8
+ useState,
9
+ } from '@codeleap/common'
10
+ import { ImageReading, UseCropPickerProps } from './types'
11
+ import { Crop } from 'react-image-crop'
12
+ import { cropImage, readImage } from './utils'
13
+ import { FileInputRef } from '../FileInput'
14
+
15
+ export function useCropPicker({
16
+ onFileSelect,
17
+ ref,
18
+ aspect,
19
+ minWidth: minW,
20
+ minHeight: minH,
21
+ }: UseCropPickerProps) {
22
+ const [visible, toggle] = useBooleanToggle(false)
23
+ const [image, setImage] = useState<ImageReading>(null)
24
+ const [crop, setCrop] = useState<Crop>()
25
+ const [relativeCrop, setRelativeCrop] = useState<Crop>()
26
+ const croppedPromise = usePromise<WebInputFile[]>({})
27
+
28
+ const onCancel = () => croppedPromise.resolve([])
29
+
30
+ const onResolved = (files: WebInputFile[]) => {
31
+ croppedPromise.resolve?.(files)
32
+ onFileSelect?.(files)
33
+ }
34
+
35
+ const cleanup = () => {
36
+ setImage(null)
37
+ setRelativeCrop(null)
38
+ setCrop(undefined)
39
+ }
40
+
41
+ const onConfirmCrop = async () => {
42
+ const [preview, croppedFile] = await cropImage(image, relativeCrop)
43
+ onResolved([
44
+ {
45
+ file: new File([croppedFile], 'cropped.jpg'),
46
+ preview,
47
+ },
48
+ ])
49
+ toggle()
50
+ setTimeout(() => cleanup())
51
+ }
52
+
53
+ const onFilesReturned = async (
54
+ event: React.ChangeEvent<HTMLInputElement>,
55
+ ) => {
56
+ const file = event?.target?.files?.[0]
57
+ const imageData = await readImage(file)
58
+ const { naturalWidth, naturalHeight } = imageData
59
+ const imageAspect = naturalWidth / naturalHeight
60
+ const v =
61
+ imageAspect >= aspect
62
+ ? {
63
+ width: ((naturalHeight * aspect) / naturalWidth) * 100,
64
+ height: 100,
65
+ }
66
+ : {
67
+ width: 100,
68
+ height: (naturalWidth / aspect / naturalHeight) * 100,
69
+ }
70
+ const initialCrop = {
71
+ ...v,
72
+ x: (100 - v.width) / 2,
73
+ y: (100 - v.height) / 2,
74
+ unit: '%',
75
+ }
76
+ setCrop(initialCrop)
77
+ setRelativeCrop(initialCrop)
78
+ setImage(imageData)
79
+ setTimeout(() => toggle())
80
+ }
81
+
82
+ const onClose = () => {
83
+ toggle()
84
+ onCancel()
85
+ setTimeout(() => cleanup())
86
+ }
87
+
88
+ const fileInputRef = useRef<FileInputRef>(null)
89
+
90
+ useImperativeHandle(ref, () => ({
91
+ openFilePicker: () => {
92
+ fileInputRef.current.openFilePicker()
93
+ return croppedPromise._await()
94
+ },
95
+ clear: () => {
96
+ fileInputRef.current.clear()
97
+ return croppedPromise._await()
98
+ },
99
+ }))
100
+
101
+ const minWidth = (minW ?? 100) * aspect
102
+ const minHeight = minH ?? 100
103
+
104
+ const handleCropChange = useCallback(
105
+ (newCrop: Crop) => {
106
+ setCrop({
107
+ ...newCrop,
108
+ width: newCrop.width < minWidth ? minWidth : newCrop.width,
109
+ height: newCrop.height < minHeight ? minHeight : newCrop.height,
110
+ })
111
+ },
112
+ [crop],
113
+ )
114
+
115
+ return {
116
+ onCancel,
117
+ onResolved,
118
+ cleanup,
119
+ onConfirmCrop,
120
+ onFilesReturned,
121
+ onClose,
122
+ fileInputRef,
123
+ visible,
124
+ toggle,
125
+ image,
126
+ setImage,
127
+ crop,
128
+ setCrop,
129
+ relativeCrop,
130
+ setRelativeCrop,
131
+ croppedPromise,
132
+ handleCropChange,
133
+ }
134
+ }
@@ -0,0 +1,51 @@
1
+ import { Crop } from 'react-image-crop'
2
+ import { ImageReading } from './types'
3
+
4
+ export function readImage(file: File | Blob): Promise<ImageReading> {
5
+ const reader = new FileReader()
6
+ return new Promise<ImageReading>((resolve) => {
7
+ reader.onload = () => {
8
+ const image = new Image()
9
+ image.onload = () => resolve(image)
10
+ image.src = reader.result as string
11
+ }
12
+ reader.readAsDataURL(file)
13
+ })
14
+ }
15
+
16
+ export function cropImage(image: ImageReading, crop: Crop): Promise<[string, Blob]> {
17
+ const canvas = document.createElement('canvas')
18
+ const ctx = canvas.getContext('2d', { alpha: true })
19
+
20
+ if (!ctx) throw new Error('No 2d context')
21
+
22
+ canvas.width = image.naturalWidth * (crop.width / 100)
23
+ canvas.height = image.naturalHeight * (crop.height / 100)
24
+
25
+ const x = image.naturalWidth * (crop.x / 100)
26
+ const y = image.naturalHeight * (crop.y / 100)
27
+
28
+ ctx.drawImage(
29
+ image,
30
+ x,
31
+ y,
32
+ canvas.width,
33
+ canvas.height,
34
+ 0,
35
+ 0,
36
+ canvas.width,
37
+ canvas.height,
38
+ )
39
+
40
+ return new Promise<[string, Blob]>((resolve, reject) => {
41
+ canvas.toBlob(blob => {
42
+ if (!blob) {
43
+ reject(new Error('Canvas is empty'))
44
+ return
45
+ }
46
+ readImage(blob).then(cropped => {
47
+ resolve([cropped.src, blob])
48
+ }).catch(reject)
49
+ }, 'image/png')
50
+ })
51
+ }
@@ -0,0 +1,204 @@
1
+ import { DropzoneFilePreviewProps, DropzoneProps, DropzoneRef } from './types'
2
+ import { DropzonePresets } from './styles'
3
+ import { IconPlaceholder, PropsOf, onUpdate, useCallback, useDefaultComponentStyle, useNestedStylesByKey, useRef } from '@codeleap/common'
4
+ import { FileRejection, useDropzone } from 'react-dropzone'
5
+ import { View, ViewProps } from '../View'
6
+ import { Text } from '../Text'
7
+ import { Icon } from '../Icon'
8
+
9
+ import { forwardRef, useImperativeHandle, useState, HTMLProps } from 'react'
10
+ import { ActionIcon } from '../ActionIcon'
11
+
12
+ const defaultProps: Partial<DropzoneProps> = {
13
+ icon: 'file-plus' as IconPlaceholder,
14
+ multiple: false,
15
+ acceptedFiles: [],
16
+ fileLeftIcon: 'file' as IconPlaceholder,
17
+ fileRightIcon: 'x' as IconPlaceholder,
18
+ withImagePreview: true,
19
+
20
+ }
21
+
22
+ function isImage(file) {
23
+ return file?.type?.startsWith('image/')
24
+ }
25
+
26
+ const FilePreview = ({
27
+ file,
28
+ variantStyles,
29
+ withImagePreview,
30
+ errors = [],
31
+ onRemove,
32
+ fileLeftIcon,
33
+ fileRightIcon,
34
+ fileRightIconStyles,
35
+ }: DropzoneFilePreviewProps) => {
36
+ const hasErrors = errors?.length > 0
37
+ const _isImage = isImage(file)
38
+ const isPreview = withImagePreview && _isImage
39
+
40
+ const [imageUrl, setImageUrl] = useState()
41
+
42
+ const revokeImageUrl = () => {
43
+ URL.revokeObjectURL(imageUrl)
44
+ }
45
+
46
+ onUpdate(() => {
47
+ if (_isImage) setImageUrl(URL.createObjectURL(file))
48
+ }, [file, _isImage])
49
+
50
+ return (
51
+ <View css={[variantStyles.fileWrapper, hasErrors && variantStyles['fileWrapper:error']]}>
52
+ {isPreview ?
53
+ <img
54
+ onLoad={revokeImageUrl}
55
+ src={imageUrl}
56
+ css={variantStyles.fileImage}
57
+ />
58
+ :
59
+ <Icon
60
+ debugName='DropzoneFilePreview:LeftIcon'
61
+ name={fileLeftIcon}
62
+ css={variantStyles.fileLeftIcon}
63
+ />
64
+ }
65
+
66
+ <View css={variantStyles.fileNameWrapper}>
67
+ <Text text={file.name} css={variantStyles.fileName} />
68
+ {hasErrors && errors?.map(error => <Text text={error.message} css={variantStyles.fileError} />)}
69
+ </View>
70
+
71
+ <ActionIcon
72
+ onClick={e => {
73
+ e.stopPropagation()
74
+ onRemove?.()
75
+ }} debugName='DropzoneFilePreview:RightIcon'
76
+ name={fileRightIcon}
77
+ styles={fileRightIconStyles}
78
+ />
79
+ </View>)
80
+ }
81
+
82
+ const DropzoneComponent = (props: DropzoneProps, ref: React.ForwardedRef<DropzoneRef>) => {
83
+ const allProps = {
84
+ ...defaultProps,
85
+ ...props,
86
+ }
87
+ const {
88
+ responsiveVariants,
89
+ styles,
90
+ variants,
91
+ icon,
92
+ placeholder,
93
+ multiple,
94
+ acceptedFiles,
95
+ setAcceptedFiles,
96
+ rejectedFiles: rejectedFilesProps,
97
+ setRejectedFiles: setRejectedFilesProps,
98
+ fileLeftIcon,
99
+ fileRightIcon,
100
+ withImagePreview,
101
+ onDrop,
102
+ onRemove,
103
+ children,
104
+ ...rest } = allProps
105
+
106
+ const [rejectedFilesState,
107
+ setRejectedFilesState] = useState<DropzoneProps['rejectedFiles']>([])
108
+ const [rejectedFiles, setRejectedFiles] = [rejectedFilesProps || rejectedFilesState, setRejectedFilesProps || setRejectedFilesState]
109
+
110
+ const variantStyles = useDefaultComponentStyle<'u:Dropzone',
111
+ typeof DropzonePresets>('u:Dropzone', {
112
+ responsiveVariants,
113
+ variants,
114
+ styles,
115
+ rootElement: 'wrapper',
116
+ })
117
+
118
+ const fileRightIconStyles = useNestedStylesByKey('fileRightIcon', variantStyles)
119
+
120
+ const handleDrop = useCallback((newAcceptedFiles: File[], newRejectedFiles: FileRejection[], event) => {
121
+ setRejectedFiles(newRejectedFiles)
122
+ setAcceptedFiles?.(state => multiple ? [...state, ...newAcceptedFiles] : newAcceptedFiles)
123
+ onDrop?.(newAcceptedFiles, newRejectedFiles, event)
124
+ }, [onDrop, setAcceptedFiles])
125
+
126
+ const handleRemoveFile = useCallback((file: File, isRejected = false) => {
127
+ if (!isRejected) {
128
+ setAcceptedFiles?.(state => state.filter(f => f.name !== file.name))
129
+ } else {
130
+ setRejectedFiles(state => state.filter(f => f.file.name !== file.name))
131
+ }
132
+ }, [setAcceptedFiles])
133
+
134
+ const { getRootProps, getInputProps, open } = useDropzone({
135
+ ...rest,
136
+ multiple,
137
+ onDrop: handleDrop,
138
+ })
139
+
140
+ const clear = useCallback(() => {
141
+ setAcceptedFiles?.([])
142
+ setRejectedFiles([])
143
+ }, [setAcceptedFiles])
144
+
145
+ useImperativeHandle(ref, () => ({
146
+ clear,
147
+ open,
148
+ }))
149
+
150
+ const hasFiles = acceptedFiles.length > 0 || rejectedFiles.length > 0
151
+
152
+ const fileProps = {
153
+ fileLeftIcon,
154
+ fileRightIcon,
155
+ variantStyles,
156
+ withImagePreview,
157
+ fileRightIconStyles,
158
+ }
159
+
160
+ return (
161
+ <View css={variantStyles.wrapper}>
162
+ <View {...getRootProps() as PropsOf<ViewProps<'div'>>} css={variantStyles.dropzone}>
163
+
164
+ {icon && !hasFiles &&
165
+ <View css={variantStyles.iconWrapper}>
166
+ <Icon debugName='Dropzone:Icon' name={icon} css={variantStyles.icon} />
167
+ </View>
168
+ }
169
+
170
+ {hasFiles && (
171
+ <View css={variantStyles.filesWrapper}>
172
+ {acceptedFiles.map(file => (
173
+ <FilePreview
174
+ {...fileProps}
175
+ file={file}
176
+ key={file.name}
177
+ onRemove={() => handleRemoveFile(file)}
178
+ />))}
179
+
180
+ {rejectedFiles.map(({ file, errors }) => (
181
+ <FilePreview
182
+ {...fileProps}
183
+ key={file.name}
184
+ file={file}
185
+ errors={errors}
186
+ onRemove={() => handleRemoveFile(file, true)}
187
+ />))}
188
+ </View>
189
+ )}
190
+
191
+ {children}
192
+ {!!placeholder && <Text text={placeholder} css={variantStyles.placeholder} />}
193
+
194
+ <input {...getInputProps() as HTMLProps<HTMLInputElement>} />
195
+ </View>
196
+ </View>)
197
+ }
198
+
199
+ export * from './styles'
200
+ export * from './types'
201
+
202
+ DropzoneComponent.defaultProps = defaultProps
203
+
204
+ export const Dropzone = forwardRef(DropzoneComponent)
@@ -0,0 +1,23 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { ActionIconComposition } from '../ActionIcon'
3
+
4
+ export type DropzoneComposition =
5
+ | 'wrapper'
6
+ | 'dropzone'
7
+ | 'icon'
8
+ | 'placeholder'
9
+ | 'filesWrapper'
10
+ | 'fileWrapper'
11
+ | 'fileLeftIcon'
12
+ | 'fileName'
13
+ | 'fileError'
14
+ | 'fileErrors'
15
+ | 'fileNameWrapper'
16
+ | 'fileImage'
17
+ | 'iconWrapper'
18
+ | `fileRightIcon${Capitalize<ActionIconComposition>}`
19
+
20
+ const createDropzoneStyle = createDefaultVariantFactory<DropzoneComposition>()
21
+
22
+ export const DropzonePresets = includePresets((styles) => createDropzoneStyle(() => ({ wrapper: styles })),
23
+ )
@@ -0,0 +1,53 @@
1
+ import {
2
+ ComponentVariants,
3
+ IconPlaceholder,
4
+ PropsOf,
5
+ StylesOf,
6
+ } from '@codeleap/common'
7
+ import { DropzoneComposition, DropzonePresets } from './styles'
8
+ import { View } from '../View'
9
+ import {
10
+ DropzoneOptions,
11
+ FileRejection,
12
+ DropzoneRef as ReactDropzoneRef,
13
+ } from 'react-dropzone'
14
+ import { ReactDispatch } from 'react'
15
+ import { ActionIconComposition } from '../ActionIcon'
16
+
17
+ export type DropzoneFile = File
18
+
19
+ export type DropzoneFileRejection = FileRejection
20
+
21
+ export type DropzoneProps = ComponentVariants<typeof DropzonePresets> &
22
+ DropzoneOptions & {
23
+ styles?: StylesOf<DropzoneComposition>
24
+ style?: PropsOf<typeof View>['style']
25
+ icon?: IconPlaceholder
26
+ placeholder?: string
27
+ acceptedFiles: File[]
28
+ rejectedFiles?: DropzoneFileRejection[]
29
+ setAcceptedFiles: ReactDispatch<React.SetStateAction<DropzoneFile[]>>
30
+ setRejectedFiles?: ReactDispatch<
31
+ React.SetStateAction<DropzoneFileRejection[]>
32
+ >
33
+ onRemove?: (file: DropzoneFile) => void
34
+ children?: React.ReactNode
35
+ fileRightIcon?: IconPlaceholder
36
+ fileLeftIcon?: IconPlaceholder
37
+ withImagePreview?: boolean
38
+ }
39
+
40
+ export type DropzoneFilePreviewProps = Pick<
41
+ DropzoneProps,
42
+ 'fileRightIcon' | 'fileLeftIcon' | 'withImagePreview'
43
+ > & {
44
+ file: DropzoneFile
45
+ errors?: DropzoneFileRejection['errors']
46
+ variantStyles: StylesOf<DropzoneComposition>
47
+ onRemove?: () => void
48
+ fileRightIconStyles?: StylesOf<ActionIconComposition>
49
+ }
50
+
51
+ export type DropzoneRef = ReactDropzoneRef & {
52
+ clear: () => void
53
+ }
@@ -30,4 +30,6 @@ export * from './Pager'
30
30
  export * from './EmptyPlaceholder'
31
31
  export * from './Grid'
32
32
  export * from './Badge'
33
+ export * from './CropPicker'
33
34
  export * from './defaultStyles'
35
+ export * from './Dropzone'
@@ -26,6 +26,7 @@ import { PagerPresets } from './Pager/styles'
26
26
  import { EmptyPlaceholderPresets } from './EmptyPlaceholder/styles'
27
27
  import { GridPresets } from './Grid/styles'
28
28
  import { BadgePresets } from './Badge/styles'
29
+ import { CropPickerPresets } from './CropPicker'
29
30
 
30
31
  export const defaultStyles = {
31
32
  View: ViewPresets,
@@ -58,9 +59,12 @@ export const defaultStyles = {
58
59
  PaginationIndicator: PaginationIndicatorStyles,
59
60
  Grid: GridPresets,
60
61
  Badge: BadgePresets,
62
+ Dropzone: DropzonePresets,
63
+ CropPicker: CropPickerPresets,
61
64
  }
62
65
 
63
66
  import createCache from '@emotion/cache'
67
+ import { DropzonePresets } from './Dropzone/styles'
64
68
 
65
69
  export const createCodeleapWebCache = () => {
66
70
  return createCache({