@codeleap/web 3.25.0 → 3.25.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.
Files changed (150) hide show
  1. package/package.json +1 -2
  2. package/src/components/ActionIcon/index.tsx +52 -51
  3. package/src/components/ActionIcon/styles.ts +5 -1
  4. package/src/components/ActivityIndicator/index.tsx +55 -34
  5. package/src/components/ActivityIndicator/styles.ts +6 -0
  6. package/src/components/Badge/index.tsx +80 -43
  7. package/src/components/Badge/styles.ts +11 -1
  8. package/src/components/Button/index.tsx +89 -46
  9. package/src/components/Button/styles.ts +5 -0
  10. package/src/components/Checkbox/index.tsx +97 -83
  11. package/src/components/Checkbox/styles.ts +5 -1
  12. package/src/components/Collapse/index.tsx +83 -41
  13. package/src/components/Collapse/styles.ts +6 -3
  14. package/src/components/ColorPicker/index.tsx +48 -95
  15. package/src/components/ColorPicker/styles.ts +11 -11
  16. package/src/components/ColorPicker/types.ts +12 -26
  17. package/src/components/CropPicker/index.tsx +104 -100
  18. package/src/components/CropPicker/styles.ts +7 -0
  19. package/src/components/CropPicker/types.ts +17 -8
  20. package/src/{lib/hooks/useCropPicker.ts → components/CropPicker/useCropPicker.tsx} +15 -68
  21. package/src/components/CropPicker/utils.ts +51 -0
  22. package/src/components/DatePicker/{components → defaultComponents}/Header.tsx +17 -9
  23. package/src/components/DatePicker/{components → defaultComponents}/OuterInput.tsx +7 -6
  24. package/src/components/DatePicker/index.tsx +124 -110
  25. package/src/components/DatePicker/styles.ts +12 -1
  26. package/src/components/DatePicker/types.ts +33 -16
  27. package/src/components/Drawer/index.tsx +125 -133
  28. package/src/components/Drawer/styles.ts +5 -0
  29. package/src/components/Dropzone/index.tsx +63 -87
  30. package/src/components/Dropzone/styles.ts +6 -0
  31. package/src/components/Dropzone/types.ts +37 -29
  32. package/src/components/EmptyPlaceholder/index.tsx +83 -63
  33. package/src/components/EmptyPlaceholder/styles.ts +5 -0
  34. package/src/components/FileInput.tsx +91 -0
  35. package/src/components/Grid/index.tsx +41 -40
  36. package/src/components/Grid/styles.ts +9 -2
  37. package/src/components/Grid/types.ts +12 -10
  38. package/src/components/Icon/index.tsx +47 -45
  39. package/src/components/Icon/styles.ts +8 -0
  40. package/src/components/InputBase/index.tsx +42 -71
  41. package/src/components/InputBase/styles.ts +47 -37
  42. package/src/components/InputBase/types.ts +7 -19
  43. package/src/components/InputBase/utils.ts +23 -3
  44. package/src/components/List/ListLayout.tsx +37 -20
  45. package/src/components/List/PaginationIndicator.tsx +102 -0
  46. package/src/components/List/index.tsx +41 -36
  47. package/src/components/List/styles.ts +11 -5
  48. package/src/components/List/types.ts +20 -30
  49. package/src/components/List/useInfiniteScroll.ts +159 -0
  50. package/src/components/LoadingOverlay/index.tsx +33 -31
  51. package/src/components/LoadingOverlay/styles.ts +8 -3
  52. package/src/components/Modal/index.tsx +160 -98
  53. package/src/components/Modal/styles.ts +5 -0
  54. package/src/components/NumberIncrement/index.tsx +98 -67
  55. package/src/components/NumberIncrement/styles.ts +5 -0
  56. package/src/components/Overlay/index.tsx +35 -37
  57. package/src/components/Overlay/styles.ts +5 -3
  58. package/src/components/Pager/index.tsx +81 -65
  59. package/src/components/Pager/styles.ts +9 -3
  60. package/src/components/Progress/Bar/index.tsx +50 -45
  61. package/src/components/Progress/Bar/styles.tsx +7 -0
  62. package/src/components/Progress/Bar/types.tsx +30 -0
  63. package/src/components/Progress/Circle/index.tsx +48 -45
  64. package/src/components/Progress/Circle/styles.ts +8 -1
  65. package/src/components/Progress/Circle/types.ts +22 -10
  66. package/src/components/RadioInput/index.tsx +124 -78
  67. package/src/components/RadioInput/styles.ts +6 -0
  68. package/src/components/Scroll/index.tsx +32 -0
  69. package/src/components/Scroll/styles.ts +8 -0
  70. package/src/components/SearchInput/index.tsx +10 -10
  71. package/src/components/SectionFilters/index.tsx +36 -47
  72. package/src/components/SectionFilters/styles.ts +5 -1
  73. package/src/components/SectionFilters/types.ts +13 -14
  74. package/src/components/SegmentedControl/SegmentedControlOption.tsx +84 -0
  75. package/src/components/SegmentedControl/index.tsx +89 -111
  76. package/src/components/SegmentedControl/styles.ts +21 -7
  77. package/src/components/Select/index.tsx +58 -92
  78. package/src/components/Select/styles.ts +36 -19
  79. package/src/components/Select/types.ts +13 -17
  80. package/src/components/Slider/index.tsx +93 -85
  81. package/src/components/Slider/styles.ts +6 -13
  82. package/src/components/Switch/index.tsx +74 -63
  83. package/src/components/Switch/styles.ts +6 -1
  84. package/src/components/Tag/index.tsx +44 -39
  85. package/src/components/Tag/styles.ts +9 -1
  86. package/src/components/Tag/types.ts +10 -10
  87. package/src/components/Text/index.tsx +48 -37
  88. package/src/components/Text/styles.ts +8 -0
  89. package/src/components/Text/types.ts +8 -8
  90. package/src/components/TextEditor/index.tsx +28 -49
  91. package/src/components/TextEditor/styles.ts +8 -1
  92. package/src/components/TextEditor/types.ts +6 -11
  93. package/src/components/TextInput/index.tsx +96 -58
  94. package/src/components/TextInput/mask.tsx +50 -2
  95. package/src/components/TextInput/styles.ts +8 -3
  96. package/src/components/Tooltip/index.tsx +84 -61
  97. package/src/components/Tooltip/styles.ts +10 -3
  98. package/src/components/Touchable/index.tsx +86 -43
  99. package/src/components/Touchable/styles.ts +6 -0
  100. package/src/components/View/index.tsx +50 -36
  101. package/src/components/View/styles.ts +6 -0
  102. package/src/components/View/types.ts +15 -14
  103. package/src/components/components.ts +3 -2
  104. package/src/components/defaultStyles.ts +79 -0
  105. package/src/index.ts +0 -1
  106. package/src/lib/hooks/index.ts +0 -5
  107. package/src/lib/hooks/useBreakpointMatch.ts +7 -8
  108. package/src/lib/hooks/useMediaQuery.ts +3 -4
  109. package/src/lib/hooks/usePagination.ts +63 -79
  110. package/src/lib/index.ts +0 -1
  111. package/src/lib/utils/index.ts +0 -1
  112. package/src/lib/utils/test.ts +2 -2
  113. package/src/components/ActionIcon/types.ts +0 -15
  114. package/src/components/ActivityIndicator/types.ts +0 -12
  115. package/src/components/Badge/types.ts +0 -28
  116. package/src/components/Button/types.ts +0 -25
  117. package/src/components/Checkbox/types.ts +0 -15
  118. package/src/components/Collapse/types.ts +0 -11
  119. package/src/components/Drawer/types.ts +0 -23
  120. package/src/components/EmptyPlaceholder/types.ts +0 -32
  121. package/src/components/FileInput/index.tsx +0 -72
  122. package/src/components/FileInput/types.ts +0 -14
  123. package/src/components/Icon/types.ts +0 -15
  124. package/src/components/LoadingOverlay/types.ts +0 -16
  125. package/src/components/Modal/types.ts +0 -55
  126. package/src/components/NumberIncrement/types.ts +0 -29
  127. package/src/components/Overlay/types.ts +0 -13
  128. package/src/components/Pager/types.ts +0 -35
  129. package/src/components/PaginationButtons/index.tsx +0 -173
  130. package/src/components/PaginationButtons/styles.ts +0 -7
  131. package/src/components/PaginationButtons/types.ts +0 -26
  132. package/src/components/PaginationIndicator/index.tsx +0 -69
  133. package/src/components/PaginationIndicator/styles.ts +0 -3
  134. package/src/components/PaginationIndicator/types.ts +0 -18
  135. package/src/components/Progress/Bar/styles.ts +0 -10
  136. package/src/components/Progress/Bar/types.ts +0 -26
  137. package/src/components/RadioInput/types.ts +0 -29
  138. package/src/components/SegmentedControl/types.ts +0 -44
  139. package/src/components/Slider/types.ts +0 -29
  140. package/src/components/Switch/types.ts +0 -13
  141. package/src/components/TextInput/types.ts +0 -85
  142. package/src/components/Tooltip/types.ts +0 -46
  143. package/src/components/Touchable/types.ts +0 -22
  144. package/src/lib/WebStyleRegistry.ts +0 -51
  145. package/src/lib/hooks/useFileInput.ts +0 -15
  146. package/src/lib/hooks/useInfiniteScroll.ts +0 -77
  147. package/src/lib/hooks/useRefresh.ts +0 -87
  148. package/src/lib/hooks/useStylesFor.ts +0 -13
  149. package/src/lib/utils/cache.ts +0 -9
  150. /package/src/components/DatePicker/{components → defaultComponents}/index.tsx +0 -0
@@ -1,39 +1,25 @@
1
1
  import React from 'react'
2
- import { ActionIconProps, ColorPickerComposition } from '../components'
3
- import { AppIcon, ICSS, StyledProp } from '@codeleap/styles'
2
+ import { ActionIconProps, IconProps } from '../components'
4
3
  import { RgbColor, RgbaColor, HslColor, HsvColor, HslaColor, HsvaColor } from 'react-colorful'
4
+ import { ComponentVariants } from '@codeleap/common'
5
+ import { ColorPickerComposition, ColorPickerPresets } from './styles'
5
6
 
6
7
  export type ColorTypes = RgbColor | HslColor | HsvColor | RgbaColor | HslaColor | HsvaColor | string
7
8
 
8
- export type ColorPickerFooterProps = Pick<ColorPickerProps, 'confirmIcon' | 'clearIcon'> & {
9
- color?: ColorTypes
10
- handleConfirmation: (value: ColorTypes) => void
11
- handleClear: (value: ColorTypes) => void
12
- styles: Record<ColorPickerComposition, ICSS>
13
- }
14
-
15
- export type ColorPickerPickerProps = {
16
- color: ColorTypes
17
- visible: boolean
18
- toggle: (v?: boolean) => void
19
- }
20
-
21
- export type ColorPickerProps = {
22
- style?: StyledProp<ColorPickerComposition>
9
+ export type ColorPickerProps = React.PropsWithChildren<{
10
+ styles?: ColorPickerComposition
11
+ style?: React.CSSProperties
23
12
  isPlain?: boolean
24
13
  closeOnConfirm?: boolean
25
14
  initialColor?: ColorTypes
26
15
  showFooter?: boolean
27
- icon?: AppIcon
28
- clearIcon?: AppIcon
29
- confirmIcon?: AppIcon
16
+ icon?: IconProps['name']
17
+ clearIcon?: IconProps['name']
18
+ confirmIcon?: IconProps['name']
30
19
  openPickerProps?: ActionIconProps
31
20
  onConfirm?: (color: ColorTypes) => void
32
21
  onClear?: () => void
33
- openPickerComponent?: (props: ColorPickerPickerProps) => JSX.Element
22
+ openPickerComponent?: (props: { color: ColorTypes; visible: boolean; toggle: (v?: boolean) => void }) => JSX.Element
34
23
  pickerComponent?: (props: any) => JSX.Element
35
- footerComponent?: (props: ColorPickerFooterProps) => JSX.Element
36
- visible?: boolean
37
- toggle?: React.Dispatch<React.SetStateAction<boolean>>
38
- children?: React.ReactNode
39
- }
24
+ footerComponent?: (props: {color: ColorTypes; handleConfirmation: () => void; handleClear: () => void}) => JSX.Element
25
+ } & ComponentVariants<typeof ColorPickerPresets>>
@@ -1,115 +1,119 @@
1
- import React, { forwardRef, Ref } from 'react'
2
- import { StyledComponentWithProps, useCompositionStyles } from '@codeleap/styles'
1
+ import React, { forwardRef } from 'react'
2
+ import {
3
+ getNestedStylesByKey,
4
+ useDefaultComponentStyle,
5
+ } from '@codeleap/common'
6
+ import { CropPickerPresets } from './styles'
3
7
  import { CropPickerProps } from './types'
4
- import { useCropPicker } from '../../lib'
5
- import { WebStyleRegistry } from '../../lib/WebStyleRegistry'
6
- import { useStylesFor } from '../../lib/hooks/useStylesFor'
7
- import { AnyRecord, IJSX, StyledComponentProps } from '@codeleap/styles'
8
- import { FileInput, FileInputRef } from '../FileInput'
9
- import { Modal } from '../Modal'
10
- import { Button } from '../Button'
11
- import { LoadingOverlay } from '../LoadingOverlay'
8
+ import { useCropPicker } from './useCropPicker'
9
+ import { Modal, Button, FileInput, FileInputRef, LoadingOverlay } from '../components'
12
10
 
13
11
  const ReactCrop: React.ElementType = require('react-image-crop').Component
14
-
15
12
  import 'react-image-crop/dist/ReactCrop.css'
16
13
 
17
14
  export * from './styles'
18
15
  export * from './types'
16
+ export * from './utils'
17
+ export * from './useCropPicker'
19
18
 
20
- export const CropPicker = forwardRef<FileInputRef, CropPickerProps>((props, ref) => {
21
- const {
22
- onFileSelect,
23
- targetCrop,
24
- modalProps,
25
- title,
26
- confirmButton,
27
- debugName,
28
- handle,
29
- withLoading,
30
- style,
31
- confirmButtonProps,
32
- ...fileInputProps
33
- } = {
34
- ...CropPicker.defaultProps,
35
- ...props,
36
- }
19
+ export const _CropPicker = forwardRef<FileInputRef, CropPickerProps>(
20
+ (props: CropPickerProps, ref) => {
21
+ const allProps = {
22
+ // @ts-ignore
23
+ ...CropPicker.defaultProps,
24
+ ...props,
25
+ }
37
26
 
38
- const {
39
- onConfirmCrop,
40
- onFilesReturned,
41
- onClose,
42
- fileInputRef,
43
- visible,
44
- image,
45
- crop,
46
- setRelativeCrop,
47
- isLoading,
48
- handleCropChange,
49
- } = handle || useCropPicker({ onFileSelect, ref: ref as unknown as Ref<FileInputRef>, ...targetCrop })
27
+ const {
28
+ onFileSelect,
29
+ targetCrop,
30
+ variants = [],
31
+ responsiveVariants = {},
32
+ styles = {},
33
+ modalProps = {},
34
+ title = 'Crop Image',
35
+ confirmButton = 'Confirm Crop',
36
+ debugName,
37
+ handle,
38
+ withLoading = false,
39
+ confirmButtonProps,
40
+ ...fileInputProps
41
+ } = allProps
50
42
 
51
- const styles = useStylesFor(CropPicker.styleRegistryName, style)
43
+ const {
44
+ onConfirmCrop,
45
+ onFilesReturned,
46
+ onClose,
47
+ fileInputRef,
48
+ visible,
49
+ image,
50
+ crop,
51
+ setRelativeCrop,
52
+ isLoading,
53
+ handleCropChange,
54
+ } = handle || useCropPicker({ onFileSelect, ref, ...targetCrop })
52
55
 
53
- const composition = useCompositionStyles(['confirmButton', 'modal'], styles)
56
+ const variantStyles = useDefaultComponentStyle<
57
+ 'u:CropPicker',
58
+ typeof CropPickerPresets
59
+ >('u:CropPicker', {
60
+ variants,
61
+ responsiveVariants,
62
+ styles,
63
+ })
54
64
 
55
- return (
56
- <>
57
- <FileInput
58
- // @ts-ignore
59
- ref={fileInputRef}
60
- onChange={(files) => onFilesReturned(files)}
61
- {...fileInputProps}
62
- />
65
+ const buttonStyles = getNestedStylesByKey('confirmButton', variantStyles)
66
+ const modalStyles = getNestedStylesByKey('modal', variantStyles)
63
67
 
64
- <Modal
65
- visible={visible}
66
- toggle={onClose}
67
- title={title}
68
- footer={
69
- <Button
70
- text={confirmButton}
71
- style={composition?.confirmButton}
72
- onPress={onConfirmCrop}
73
- debugName={debugName}
74
- {...confirmButtonProps}
75
- />
76
- }
77
- {...modalProps}
78
- style={composition?.modal}
79
- >
80
- {!!image?.src ? (
81
- <ReactCrop
82
- crop={crop}
83
- onChange={handleCropChange}
84
- onComplete={(_, relCrop) => setRelativeCrop(relCrop)}
85
- {...targetCrop}
86
- style={styles.previewSize}
87
- >
88
- <img
89
- src={image?.src}
90
- // @ts-expect-error
91
- css={[styles.cropPreview, styles.previewSize]}
68
+ return (
69
+ <>
70
+ <FileInput
71
+ ref={fileInputRef}
72
+ onChange={(files) => onFilesReturned(files)}
73
+ {...fileInputProps}
74
+ />
75
+ <Modal
76
+ visible={visible}
77
+ toggle={onClose}
78
+ title={title}
79
+ styles={modalStyles}
80
+ footer={
81
+ <Button
82
+ text={confirmButton}
83
+ styles={buttonStyles}
84
+ onPress={onConfirmCrop}
85
+ debugName={debugName}
86
+ {...confirmButtonProps}
92
87
  />
93
- </ReactCrop>
94
- ) : null}
95
- {withLoading ? <LoadingOverlay debugName='CropPicker' visible={isLoading} /> : null}
96
- </Modal>
97
- </>
98
- )
99
- }) as StyledComponentWithProps<CropPickerProps>
100
-
101
- CropPicker.styleRegistryName = 'CropPicker'
102
- CropPicker.elements = ['previewSize', 'cropPreview', 'confirmButton', 'modal']
103
- CropPicker.rootElement = 'previewSize'
104
-
105
- CropPicker.withVariantTypes = <S extends AnyRecord>(styles: S) => {
106
- return CropPicker as (props: StyledComponentProps<CropPickerProps, typeof styles>) => IJSX
107
- }
108
-
109
- CropPicker.defaultProps = {
110
- title: 'Crop Image',
111
- confirmButton: 'Confirm Crop',
112
- withLoading: false,
113
- } as Partial<CropPickerProps>
88
+ }
89
+ {...modalProps}
90
+ >
91
+ {!!image?.src && (
92
+ <ReactCrop
93
+ crop={crop}
94
+ onChange={handleCropChange}
95
+ onComplete={(_, relCrop) => setRelativeCrop(relCrop)}
96
+ style={variantStyles.previewSize}
97
+ {...targetCrop}
98
+ >
99
+ <img
100
+ src={image?.src}
101
+ css={[variantStyles.cropPreview, variantStyles.previewSize]}
102
+ />
103
+ </ReactCrop>
104
+ )}
105
+ {
106
+ withLoading ? (
107
+ <LoadingOverlay
108
+ debugName='CropPicker'
109
+ visible={isLoading}
110
+ />
111
+ ) : null
112
+ }
113
+ </Modal>
114
+ </>
115
+ )
116
+ },
117
+ )
114
118
 
115
- WebStyleRegistry.registerComponent(CropPicker)
119
+ export const CropPicker = React.memo(_CropPicker)
@@ -1,3 +1,4 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
1
2
  import { ButtonComposition } from '../Button'
2
3
  import { ModalComposition } from '../Modal'
3
4
 
@@ -6,3 +7,9 @@ export type CropPickerComposition =
6
7
  | 'previewSize'
7
8
  | `confirmButton${Capitalize<ButtonComposition>}`
8
9
  | `modal${Capitalize<ModalComposition>}`
10
+
11
+ const createCropPickerStyle =
12
+ createDefaultVariantFactory<CropPickerComposition>()
13
+
14
+ export const CropPickerPresets = includePresets((style) => createCropPickerStyle(() => ({ modalWrapper: style })),
15
+ )
@@ -1,25 +1,34 @@
1
- import { StyledProp } from '@codeleap/styles'
2
- import { FileInputProps } from '../FileInput'
3
- import { CropPickerComposition } from './styles'
1
+ import { AnyRef, ComponentVariants } from '@codeleap/common'
2
+ import { FileInputProps, FileInputRef } from '../FileInput'
3
+ import { CropPickerComposition, CropPickerPresets } from './styles'
4
+ import { StylesOf } from '../../types'
4
5
  import { ReactCropProps } from 'react-image-crop'
5
6
  import { ModalProps } from '../Modal'
6
- import { useCropPicker } from '../../lib'
7
+ import { useCropPicker } from './useCropPicker'
7
8
  import { ButtonProps } from '../Button'
8
9
 
10
+ export type CropImageType = 'png' | 'jpeg' | 'webp'
11
+
9
12
  export type BaseCropProps = Partial<ReactCropProps>
10
13
 
11
- export type CropPickerProps =
12
- Partial<FileInputProps> &
13
- {
14
- style?: StyledProp<CropPickerComposition>
14
+ export type CropPickerProps = Partial<FileInputProps> &
15
+ ComponentVariants<typeof CropPickerPresets> & {
16
+ styles?: StylesOf<CropPickerComposition>
17
+ style?: React.CSSProperties
15
18
  targetCrop?: BaseCropProps
16
19
  modalProps?: Partial<ModalProps>
17
20
  title?: string
18
21
  confirmButton?: string
19
22
  debugName: string
20
23
  handle?: ReturnType<typeof useCropPicker>
24
+ ref: AnyRef<HTMLElement>
21
25
  withLoading?: boolean
22
26
  confirmButtonProps?: Partial<ButtonProps>
23
27
  }
24
28
 
25
29
  export type ImageReading = HTMLImageElement
30
+
31
+ export type UseCropPickerProps = Partial<ReactCropProps> & {
32
+ onFileSelect: FileInputProps['onFileSelect']
33
+ ref: React.MutableRefObject<FileInputRef> | React.Ref<FileInputRef>
34
+ }
@@ -7,63 +7,10 @@ import {
7
7
  useRef,
8
8
  useState,
9
9
  } from '@codeleap/common'
10
- import { ImageReading } from '../../components/CropPicker'
11
- import { FileInputProps, FileInputRef } from '../../components/FileInput'
12
- import { Crop, ReactCropProps } from 'react-image-crop'
13
-
14
- export type UseCropPickerProps = Partial<ReactCropProps> & {
15
- onFileSelect: FileInputProps['onFileSelect']
16
- ref: React.MutableRefObject<FileInputRef> | React.Ref<FileInputRef>
17
- }
18
-
19
- export function readImage(file: File | Blob): Promise<ImageReading> {
20
- const reader = new FileReader()
21
- return new Promise<ImageReading>((resolve) => {
22
- reader.onload = () => {
23
- const image = new Image()
24
- image.onload = () => resolve(image)
25
- image.src = reader.result as string
26
- }
27
- reader.readAsDataURL(file)
28
- })
29
- }
30
-
31
- export function cropImage(image: ImageReading, crop: Crop): Promise<[string, Blob]> {
32
- const canvas = document.createElement('canvas')
33
- const ctx = canvas.getContext('2d', { alpha: true })
34
-
35
- if (!ctx) throw new Error('No 2d context')
36
-
37
- canvas.width = image.naturalWidth * (crop.width / 100)
38
- canvas.height = image.naturalHeight * (crop.height / 100)
39
-
40
- const x = image.naturalWidth * (crop.x / 100)
41
- const y = image.naturalHeight * (crop.y / 100)
42
-
43
- ctx.drawImage(
44
- image,
45
- x,
46
- y,
47
- canvas.width,
48
- canvas.height,
49
- 0,
50
- 0,
51
- canvas.width,
52
- canvas.height,
53
- )
54
-
55
- return new Promise<[string, Blob]>((resolve, reject) => {
56
- canvas.toBlob(blob => {
57
- if (!blob) {
58
- reject(new Error('Canvas is empty'))
59
- return
60
- }
61
- readImage(blob).then(cropped => {
62
- resolve([cropped.src, blob])
63
- }).catch(reject)
64
- }, 'image/png')
65
- })
66
- }
10
+ import { CropImageType, ImageReading, UseCropPickerProps } from './types'
11
+ import { Crop } from 'react-image-crop'
12
+ import { cropImage, readImage } from './utils'
13
+ import { FileInputRef } from '../FileInput'
67
14
 
68
15
  export function useCropPicker({
69
16
  onFileSelect,
@@ -93,9 +40,9 @@ export function useCropPicker({
93
40
  setTimeout(() => setImage(null), 500)
94
41
  }
95
42
 
96
- const onConfirmCrop = async () => {
43
+ const onConfirmCrop = async (imageType: CropImageType = 'jpeg') => {
97
44
  setIsLoading(true)
98
- const [preview, croppedFile] = await cropImage(image, relativeCrop)
45
+ const [preview, croppedFile] = await cropImage(image, relativeCrop, imageType)
99
46
  onResolved([
100
47
  {
101
48
  file: new File([croppedFile], 'cropped.jpg'),
@@ -114,15 +61,15 @@ export function useCropPicker({
114
61
  const { naturalWidth, naturalHeight } = imageData
115
62
  const imageAspect = naturalWidth / naturalHeight
116
63
  const v =
117
- imageAspect >= aspect
118
- ? {
119
- width: ((naturalHeight * aspect) / naturalWidth) * 100,
120
- height: 100,
121
- }
122
- : {
123
- width: 100,
124
- height: (naturalWidth / aspect / naturalHeight) * 100,
125
- }
64
+ imageAspect >= aspect
65
+ ? {
66
+ width: ((naturalHeight * aspect) / naturalWidth) * 100,
67
+ height: 100,
68
+ }
69
+ : {
70
+ width: 100,
71
+ height: (naturalWidth / aspect / naturalHeight) * 100,
72
+ }
126
73
  const initialCrop: Crop = {
127
74
  ...v,
128
75
  x: (100 - v.width) / 2,
@@ -0,0 +1,51 @@
1
+ import { Crop } from 'react-image-crop'
2
+ import { CropImageType, 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, type: CropImageType): 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/${type}`)
50
+ })
51
+ }
@@ -1,13 +1,20 @@
1
- import { TypeGuards } from '@codeleap/common'
1
+ import {
2
+ IconPlaceholder,
3
+ TypeGuards,
4
+ getNestedStylesByKey,
5
+ } from '@codeleap/common'
2
6
  import { ActionIcon, Text, View } from '../../components'
3
7
  import { DatePickerArrowProps, DatePickerHeaderComponent } from '../types'
4
8
  import { format, getYear } from 'date-fns'
5
- import { AppIcon, useCompositionStyles } from '@codeleap/styles'
6
9
 
7
- export const ArrowLabel = ({ name, direction, ...props }: DatePickerArrowProps) => {
10
+ export const ArrowLabel: React.FC<DatePickerArrowProps> = ({
11
+ name,
12
+ direction,
13
+ ...props
14
+ }) => {
8
15
  return (
9
16
  <ActionIcon
10
- name={name ?? (`chevron-${direction}` as AppIcon)}
17
+ name={name ?? (`chevron-${direction}` as IconPlaceholder)}
11
18
  debugName={'Calendar arrowLabel'}
12
19
  {...props}
13
20
  />
@@ -37,14 +44,15 @@ export const Header = (props: DatePickerHeaderComponent) => {
37
44
  ? formatHeaderTitle(date)
38
45
  : `${month} ${year}`
39
46
 
40
- const compositionStyles = useCompositionStyles(['prevButton', 'nextButton'], styles)
47
+ const prevArrow = getNestedStylesByKey('prevButton', styles)
48
+ const nextArrow = getNestedStylesByKey('nextButton', styles)
41
49
 
42
50
  return (
43
51
  <View style={styles.wrapper}>
44
52
  <View style={styles.buttonsWrapper}>
45
53
  <ArrowLabel
46
54
  direction='left'
47
- style={compositionStyles.prevButton}
55
+ styles={prevArrow}
48
56
  onPress={decreaseYear}
49
57
  disabled={prevYearButtonDisabled}
50
58
  />
@@ -55,7 +63,7 @@ export const Header = (props: DatePickerHeaderComponent) => {
55
63
  />
56
64
  <ArrowLabel
57
65
  direction='right'
58
- style={compositionStyles.nextButton}
66
+ styles={nextArrow}
59
67
  onPress={increaseYear}
60
68
  disabled={nextYearButtonDisabled}
61
69
  />
@@ -63,13 +71,13 @@ export const Header = (props: DatePickerHeaderComponent) => {
63
71
  <View style={styles.buttonsWrapper}>
64
72
  <ArrowLabel
65
73
  direction='left'
66
- style={compositionStyles.prevButton}
74
+ styles={prevArrow}
67
75
  onPress={decreaseMonth}
68
76
  disabled={prevMonthButtonDisabled}
69
77
  />
70
78
  <ArrowLabel
71
79
  direction='right'
72
- style={compositionStyles.nextButton}
80
+ styles={nextArrow}
73
81
  onPress={increaseMonth}
74
82
  disabled={nextMonthButtonDisabled}
75
83
  />
@@ -1,12 +1,13 @@
1
1
  import { TextInput } from '../../components'
2
2
  import { DatePickerProps } from '../types'
3
3
 
4
- export const OuterInput: DatePickerProps['outerInputComponent'] = ({ valueLabel, focused, hideInput, ...props }) => {
5
- if (hideInput) {
6
- return null
7
- }
8
-
9
- return (
4
+ export const OuterInput: DatePickerProps['outerInputComponent'] = ({
5
+ valueLabel,
6
+ focused,
7
+ hideInput,
8
+ ...props
9
+ }) => {
10
+ return hideInput ? null : (
10
11
  <TextInput
11
12
  validate={!focused && props?.validate}
12
13
  debugName='DatePicker - OuterInputComponent'