@codeleap/web 3.24.3 → 4.0.0

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 +2 -1
  2. package/src/components/ActionIcon/index.tsx +51 -52
  3. package/src/components/ActionIcon/styles.ts +1 -5
  4. package/src/components/ActionIcon/types.ts +15 -0
  5. package/src/components/ActivityIndicator/index.tsx +34 -55
  6. package/src/components/ActivityIndicator/styles.ts +0 -6
  7. package/src/components/ActivityIndicator/types.ts +12 -0
  8. package/src/components/Badge/index.tsx +43 -80
  9. package/src/components/Badge/styles.ts +1 -11
  10. package/src/components/Badge/types.ts +28 -0
  11. package/src/components/Button/index.tsx +46 -89
  12. package/src/components/Button/styles.ts +0 -5
  13. package/src/components/Button/types.ts +25 -0
  14. package/src/components/Checkbox/index.tsx +83 -97
  15. package/src/components/Checkbox/styles.ts +1 -5
  16. package/src/components/Checkbox/types.ts +15 -0
  17. package/src/components/Collapse/index.tsx +41 -83
  18. package/src/components/Collapse/styles.ts +3 -6
  19. package/src/components/Collapse/types.ts +11 -0
  20. package/src/components/ColorPicker/index.tsx +95 -48
  21. package/src/components/ColorPicker/styles.ts +11 -11
  22. package/src/components/ColorPicker/types.ts +26 -12
  23. package/src/components/CropPicker/index.tsx +100 -104
  24. package/src/components/CropPicker/styles.ts +0 -7
  25. package/src/components/CropPicker/types.ts +8 -15
  26. package/src/components/DatePicker/{defaultComponents → components}/Header.tsx +9 -17
  27. package/src/components/DatePicker/{defaultComponents → components}/OuterInput.tsx +6 -7
  28. package/src/components/DatePicker/index.tsx +110 -124
  29. package/src/components/DatePicker/styles.ts +1 -12
  30. package/src/components/DatePicker/types.ts +16 -33
  31. package/src/components/Drawer/index.tsx +133 -125
  32. package/src/components/Drawer/styles.ts +0 -5
  33. package/src/components/Drawer/types.ts +23 -0
  34. package/src/components/Dropzone/index.tsx +87 -63
  35. package/src/components/Dropzone/styles.ts +0 -6
  36. package/src/components/Dropzone/types.ts +29 -37
  37. package/src/components/EmptyPlaceholder/index.tsx +63 -83
  38. package/src/components/EmptyPlaceholder/styles.ts +0 -5
  39. package/src/components/EmptyPlaceholder/types.ts +32 -0
  40. package/src/components/FileInput/index.tsx +72 -0
  41. package/src/components/FileInput/types.ts +14 -0
  42. package/src/components/Grid/index.tsx +40 -41
  43. package/src/components/Grid/styles.ts +2 -9
  44. package/src/components/Grid/types.ts +10 -12
  45. package/src/components/Icon/index.tsx +45 -47
  46. package/src/components/Icon/styles.ts +0 -8
  47. package/src/components/Icon/types.ts +15 -0
  48. package/src/components/InputBase/index.tsx +71 -42
  49. package/src/components/InputBase/styles.ts +37 -47
  50. package/src/components/InputBase/types.ts +19 -7
  51. package/src/components/InputBase/utils.ts +3 -23
  52. package/src/components/List/ListLayout.tsx +20 -37
  53. package/src/components/List/index.tsx +36 -41
  54. package/src/components/List/styles.ts +5 -11
  55. package/src/components/List/types.ts +30 -20
  56. package/src/components/LoadingOverlay/index.tsx +31 -33
  57. package/src/components/LoadingOverlay/styles.ts +3 -8
  58. package/src/components/LoadingOverlay/types.ts +16 -0
  59. package/src/components/Modal/index.tsx +98 -160
  60. package/src/components/Modal/styles.ts +0 -5
  61. package/src/components/Modal/types.ts +55 -0
  62. package/src/components/NumberIncrement/index.tsx +67 -98
  63. package/src/components/NumberIncrement/styles.ts +0 -5
  64. package/src/components/NumberIncrement/types.ts +29 -0
  65. package/src/components/Overlay/index.tsx +37 -35
  66. package/src/components/Overlay/styles.ts +3 -5
  67. package/src/components/Overlay/types.ts +13 -0
  68. package/src/components/Pager/index.tsx +65 -81
  69. package/src/components/Pager/styles.ts +3 -9
  70. package/src/components/Pager/types.ts +35 -0
  71. package/src/components/PaginationButtons/index.tsx +173 -0
  72. package/src/components/PaginationButtons/styles.ts +7 -0
  73. package/src/components/PaginationButtons/types.ts +26 -0
  74. package/src/components/PaginationIndicator/index.tsx +69 -0
  75. package/src/components/PaginationIndicator/styles.ts +3 -0
  76. package/src/components/PaginationIndicator/types.ts +18 -0
  77. package/src/components/Progress/Bar/index.tsx +45 -50
  78. package/src/components/Progress/Bar/styles.ts +10 -0
  79. package/src/components/Progress/Bar/types.ts +26 -0
  80. package/src/components/Progress/Circle/index.tsx +45 -48
  81. package/src/components/Progress/Circle/styles.ts +1 -8
  82. package/src/components/Progress/Circle/types.ts +10 -22
  83. package/src/components/RadioInput/index.tsx +78 -124
  84. package/src/components/RadioInput/styles.ts +0 -6
  85. package/src/components/RadioInput/types.ts +29 -0
  86. package/src/components/SearchInput/index.tsx +10 -10
  87. package/src/components/SectionFilters/index.tsx +47 -36
  88. package/src/components/SectionFilters/styles.ts +1 -5
  89. package/src/components/SectionFilters/types.ts +14 -13
  90. package/src/components/SegmentedControl/index.tsx +111 -89
  91. package/src/components/SegmentedControl/styles.ts +7 -21
  92. package/src/components/SegmentedControl/types.ts +44 -0
  93. package/src/components/Select/index.tsx +92 -56
  94. package/src/components/Select/styles.ts +19 -36
  95. package/src/components/Select/types.ts +15 -10
  96. package/src/components/Slider/index.tsx +85 -93
  97. package/src/components/Slider/styles.ts +13 -6
  98. package/src/components/Slider/types.ts +29 -0
  99. package/src/components/Switch/index.tsx +63 -74
  100. package/src/components/Switch/styles.ts +1 -6
  101. package/src/components/Switch/types.ts +13 -0
  102. package/src/components/Tag/index.tsx +39 -44
  103. package/src/components/Tag/styles.ts +1 -9
  104. package/src/components/Tag/types.ts +10 -10
  105. package/src/components/Text/index.tsx +37 -48
  106. package/src/components/Text/styles.ts +0 -8
  107. package/src/components/Text/types.ts +8 -8
  108. package/src/components/TextEditor/index.tsx +49 -28
  109. package/src/components/TextEditor/styles.ts +1 -8
  110. package/src/components/TextEditor/types.ts +11 -6
  111. package/src/components/TextInput/index.tsx +58 -96
  112. package/src/components/TextInput/mask.tsx +2 -50
  113. package/src/components/TextInput/styles.ts +3 -8
  114. package/src/components/TextInput/types.ts +85 -0
  115. package/src/components/Tooltip/index.tsx +61 -84
  116. package/src/components/Tooltip/styles.ts +3 -10
  117. package/src/components/Tooltip/types.ts +46 -0
  118. package/src/components/Touchable/index.tsx +43 -86
  119. package/src/components/Touchable/styles.ts +0 -6
  120. package/src/components/Touchable/types.ts +22 -0
  121. package/src/components/View/index.tsx +36 -50
  122. package/src/components/View/styles.ts +0 -6
  123. package/src/components/View/types.ts +14 -15
  124. package/src/components/components.ts +2 -3
  125. package/src/index.ts +1 -0
  126. package/src/lib/WebStyleRegistry.ts +51 -0
  127. package/src/lib/hooks/index.ts +5 -0
  128. package/src/lib/hooks/useBreakpointMatch.ts +8 -7
  129. package/src/{components/CropPicker/useCropPicker.tsx → lib/hooks/useCropPicker.ts} +66 -13
  130. package/src/lib/hooks/useFileInput.ts +15 -0
  131. package/src/lib/hooks/useInfiniteScroll.ts +77 -0
  132. package/src/lib/hooks/useMediaQuery.ts +4 -3
  133. package/src/lib/hooks/usePagination.ts +79 -63
  134. package/src/lib/hooks/useRefresh.ts +87 -0
  135. package/src/lib/hooks/useStylesFor.ts +13 -0
  136. package/src/lib/index.ts +1 -0
  137. package/src/lib/utils/cache.ts +9 -0
  138. package/src/lib/utils/index.ts +1 -0
  139. package/src/lib/utils/test.ts +2 -2
  140. package/src/components/CropPicker/utils.ts +0 -51
  141. package/src/components/FileInput.tsx +0 -91
  142. package/src/components/List/PaginationIndicator.tsx +0 -102
  143. package/src/components/List/useInfiniteScroll.ts +0 -159
  144. package/src/components/Progress/Bar/styles.tsx +0 -7
  145. package/src/components/Progress/Bar/types.tsx +0 -30
  146. package/src/components/Scroll/index.tsx +0 -32
  147. package/src/components/Scroll/styles.ts +0 -8
  148. package/src/components/SegmentedControl/SegmentedControlOption.tsx +0 -84
  149. package/src/components/defaultStyles.ts +0 -79
  150. /package/src/components/DatePicker/{defaultComponents → components}/index.tsx +0 -0
@@ -1,81 +1,47 @@
1
- import {
2
- AnyFunction,
3
- ComponentVariants,
4
- IconPlaceholder,
5
- TypeGuards,
6
- useDefaultComponentStyle,
7
- useNestedStylesByKey,
8
- } from '@codeleap/common'
9
- import { CSSObject } from '@emotion/react'
10
- import React from 'react'
1
+ import { TypeGuards, useMemo } from '@codeleap/common'
11
2
  import { Overlay } from '../Overlay'
12
3
  import { View } from '../View'
13
4
  import { Text } from '../Text'
14
- import { ComponentCommonProps, StylesOf } from '../../types/utility'
15
- import { DrawerComposition, DrawerPresets } from './styles'
16
- import { ActionIcon, ActionIconProps } from '../ActionIcon'
17
- import { usePopState } from '../../lib'
5
+ import { ActionIcon } from '../ActionIcon'
6
+ import ReactDOM from 'react-dom'
7
+ import { useAnimatedStyle, usePopState } from '../../lib'
8
+ import { WebStyleRegistry } from '../../lib/WebStyleRegistry'
9
+ import { DrawerProps } from './types'
10
+ import { AnyRecord, AppIcon, IJSX, StyledComponentProps, useNestedStylesByKey } from '@codeleap/styles'
11
+ import { useStylesFor } from '../../lib/hooks/useStylesFor'
18
12
 
19
- const axisMap = {
20
- top: [-1, 'Y'],
21
- bottom: [1, 'Y'],
22
- left: [-1, 'X'],
23
- right: [1, 'X'],
24
- } as const
25
-
26
- export type DrawerProps = {
27
- open: boolean
28
- toggle: AnyFunction
29
- darkenBackground?: boolean
30
- size?: string | number
31
- showCloseButton?: boolean
32
- title?: React.ReactNode | string
33
- footer?: React.ReactNode
34
- position?: keyof typeof axisMap
35
- styles?: StylesOf<DrawerComposition>
36
- style?: React.CSSProperties
37
- animationDuration?: string
38
- closeButtonProps?: Partial<ActionIconProps>
39
- closeIcon?: IconPlaceholder
40
- children?: React.ReactNode
41
- } & ComponentVariants<typeof DrawerPresets> & ComponentCommonProps
42
-
43
- const resolveHiddenDrawerPosition = (
44
- position: DrawerProps['position'],
45
- ): [string, string, CSSObject] => {
46
- const [translateOrient, translateAxis] = axisMap[position]
47
-
48
- const translateValues = {
49
- X: 0,
50
- Y: 0,
51
- }
52
-
53
- translateValues[translateAxis] = 100 * translateOrient
54
-
55
- const css = `translate(${translateValues.X}%, ${translateValues.Y}%)`
56
- const positioningKeys =
57
- translateAxis === 'X' ? ['top', 'bottom'] : ['left', 'right']
13
+ export * from './styles'
14
+ export * from './types'
58
15
 
59
- const positioning = Object.fromEntries(positioningKeys.map((k) => [k, 0]))
60
- return [css, translateAxis, positioning]
16
+ const axisMap = {
17
+ 'left': ['top', 'left'],
18
+ 'right': ['top', 'right'],
19
+ 'top': ['top', 'right', 'left'],
20
+ 'bottom': ['bottom', 'right', 'left']
61
21
  }
62
22
 
63
- const defaultProps: Partial<DrawerProps> = {
64
- animationDuration: '0.3s',
65
- position: 'bottom',
66
- showCloseButton: false,
67
- darkenBackground: true,
68
- size: '75vw',
69
- title: null,
70
- closeIcon: 'x' as IconPlaceholder,
23
+ const getInsetPath = (position: DrawerProps['position'], value: number) => {
24
+ let inset = ''
25
+
26
+ switch (position) {
27
+ case 'left':
28
+ inset = `inset(0 ${value}% 0 0)`
29
+ break
30
+ case 'right':
31
+ inset = `inset(0 0 0 ${value}%)`
32
+ break
33
+ case 'top':
34
+ inset = `inset(0 0 ${value}% 0)`
35
+ break
36
+ case 'bottom':
37
+ inset = `inset(${value}% 0 0 0)`
38
+ break
39
+ }
40
+
41
+ return inset
71
42
  }
72
43
 
73
44
  export const Drawer = (props: DrawerProps) => {
74
- const allProps = {
75
- ...Drawer.defaultProps,
76
- ...props,
77
- }
78
-
79
45
  const {
80
46
  open,
81
47
  toggle,
@@ -85,99 +51,141 @@ export const Drawer = (props: DrawerProps) => {
85
51
  footer,
86
52
  darkenBackground,
87
53
  showCloseButton,
88
- closeButtonProps = {},
54
+ closeButtonProps,
89
55
  position,
90
- variants = [],
91
- responsiveVariants = {},
92
- styles,
93
56
  style,
94
- animationDuration,
95
57
  debugName,
96
58
  closeIcon,
97
- } = allProps as DrawerProps
59
+ } = {
60
+ ...Drawer.defaultProps,
61
+ ...props,
62
+ }
98
63
 
99
64
  usePopState(open, toggle)
100
65
 
101
- const [hiddenStyle, axis, positioning] = resolveHiddenDrawerPosition(position)
66
+ const styles = useStylesFor(Drawer.styleRegistryName, style)
102
67
 
103
- const sizeProperty = axis === 'X' ? 'width' : 'height'
104
- const fullProperty = sizeProperty === 'height' ? 'width' : 'height'
68
+ const closeButtonStyles = useNestedStylesByKey('closeButton', styles)
105
69
 
106
- const variantStyles = useDefaultComponentStyle<'u:Drawer', typeof DrawerPresets>('u:Drawer', {
107
- styles,
108
- variants,
109
- responsiveVariants,
110
- })
70
+ const pose = useMemo(() => {
71
+ const pose = {}
111
72
 
112
- const closeButtonStyles = useNestedStylesByKey('closeButton', variantStyles)
73
+ for (const p of axisMap[position]) {
74
+ pose[p] = 0
75
+ }
113
76
 
114
- const showHeader = (!TypeGuards.isNil(title) || showCloseButton)
77
+ return pose
78
+ }, [])
115
79
 
116
- const wrapperStyles = React.useMemo(() => ([
117
- variantStyles.wrapper,
80
+ const expansionProperty = ['left', 'right'].includes(position) ? 'width': 'height'
81
+ const fixedProperty = expansionProperty == 'width' ? 'height' : 'width'
82
+ const fixedValue = fixedProperty == 'width' ? '100vw' : '100vh'
83
+ const measureProperty = expansionProperty == 'width' ? 'svw' : 'svh'
84
+
85
+ const animatedStyle = useAnimatedStyle(() => {
86
+ const value = open ? 0 : 100
87
+
88
+ return {
89
+ clipPath: getInsetPath(position, value),
90
+ transition: {
91
+ duration: 0.25,
92
+ }
93
+ }
94
+ }, [open])
95
+
96
+ const wrapperAnimatedStyle = useAnimatedStyle(() => ({
97
+ opacity: open ? 1 : 0,
98
+ pointerEvents: open ? 'auto' : 'none',
99
+ transition: {
100
+ duration: open ? 0.2 : 1.5,
101
+ }
102
+ }), [open])
103
+
104
+ const boxStyles = [
105
+ styles.box,
106
+ pose,
118
107
  {
119
- transition: 'visibility 0.01s ease',
120
- transitionDelay: open ? '0' : animationDuration,
121
- visibility: open ? 'visible' : 'hidden',
122
- },
123
- style,
124
- ]), [open, variantStyles])
108
+ zIndex: 999,
109
+ position: 'fixed',
110
+ [fixedProperty]: fixedValue,
111
+ [expansionProperty]: `${size}${measureProperty}`
112
+ }
113
+ ]
125
114
 
126
- return (
127
- <View debugName={debugName} css={wrapperStyles}>
128
- {darkenBackground && (
115
+ const showHeader = (!TypeGuards.isNil(title) || showCloseButton)
116
+
117
+ const content = (
118
+ <View
119
+ debugName={debugName}
120
+ animated
121
+ animatedProps={wrapperAnimatedStyle}
122
+ style={styles.wrapper}
123
+ >
124
+ {darkenBackground ? (
129
125
  <Overlay
130
126
  debugName={debugName}
131
127
  visible={open}
132
- css={variantStyles.overlay}
128
+ style={[
129
+ styles.overlay,
130
+ open ? styles['overlay:visible'] : styles['overlay:hidden'],
131
+ ]}
133
132
  onPress={toggle}
134
133
  />
135
- )}
136
-
137
- <View
138
- variants={['fixed']}
139
- css={{
140
- transform: open ? `translate(0%, 0%)` : hiddenStyle,
141
- transition: `transform ${animationDuration} ease`,
142
- [sizeProperty]: size,
143
- [fullProperty]: '100%',
144
- ...positioning,
145
- [position]: 0,
146
- ...variantStyles.box,
147
- }}
148
- >
134
+ ) : null}
135
+
136
+ <View animated animatedProps={animatedStyle} style={boxStyles}>
149
137
  {
150
138
  showHeader ? (
151
- <View
152
- component='header'
153
- css={[variantStyles.header]}
154
- >
155
- {TypeGuards.isString(title) ? <Text css={variantStyles.title} text={title} /> : title}
156
- {showCloseButton && (
139
+ <View component='header' style={styles.header}>
140
+ {TypeGuards.isString(title) ? <Text style={styles.title} text={title} /> : title}
141
+
142
+ {showCloseButton ? (
157
143
  <ActionIcon
158
144
  debugName={debugName}
145
+ icon={closeIcon as AppIcon}
159
146
  onPress={toggle}
160
- icon={closeIcon as IconPlaceholder}
147
+ propagate={false}
161
148
  {...closeButtonProps}
162
- styles={closeButtonStyles}
149
+ style={closeButtonStyles}
163
150
  />
164
- )}
151
+ ) : null}
165
152
  </View>
166
153
  ) : null
167
154
  }
168
155
 
169
- <View css={variantStyles.body}>{children}</View>
156
+ <View style={styles.body}>{children}</View>
170
157
 
171
- {footer && (
172
- <View component='footer' css={variantStyles.footer}>
158
+ {footer ? (
159
+ <View component='footer' style={styles.footer}>
173
160
  {footer}
174
161
  </View>
175
- )}
162
+ ) : null}
176
163
  </View>
177
164
  </View>
178
165
  )
166
+
167
+ if (typeof window === 'undefined') return content
168
+
169
+ return ReactDOM.createPortal(
170
+ content,
171
+ document.body,
172
+ )
179
173
  }
180
174
 
181
- Drawer.defaultProps = defaultProps
175
+ Drawer.styleRegistryName = 'Drawer'
176
+ Drawer.elements = ['wrapper', 'overlay', 'header', 'footer', 'closeButton', 'body', 'box', 'title']
177
+ Drawer.rootElement = 'wrapper'
182
178
 
183
- export * from './styles'
179
+ Drawer.withVariantTypes = <S extends AnyRecord>(styles: S) => {
180
+ return Drawer as (props: StyledComponentProps<DrawerProps, typeof styles>) => IJSX
181
+ }
182
+
183
+ Drawer.defaultProps = {
184
+ position: 'left',
185
+ showCloseButton: false,
186
+ darkenBackground: true,
187
+ size: 75,
188
+ closeIcon: 'x' as AppIcon,
189
+ } as Partial<DrawerProps>
190
+
191
+ WebStyleRegistry.registerComponent(Drawer)
@@ -1,4 +1,3 @@
1
- import { createDefaultVariantFactory, includePresets } from "@codeleap/common"
2
1
  import { ActionIconComposition } from '../ActionIcon'
3
2
 
4
3
  export type DrawerComposition =
@@ -10,7 +9,3 @@ export type DrawerComposition =
10
9
  | 'body'
11
10
  | 'box'
12
11
  | 'title'
13
-
14
- const createDrawerStyle = createDefaultVariantFactory<DrawerComposition>()
15
-
16
- export const DrawerPresets = includePresets((styles) => createDrawerStyle(() => ({ wrapper: styles })))
@@ -0,0 +1,23 @@
1
+ import { AnyFunction } from '@codeleap/common'
2
+ import React from 'react'
3
+ import { ComponentCommonProps } from '../../types/utility'
4
+ import { DrawerComposition } from './styles'
5
+ import { ActionIconProps } from '../ActionIcon'
6
+ import { AppIcon, StyledProp } from '@codeleap/styles'
7
+
8
+ export type DrawerProps =
9
+ ComponentCommonProps &
10
+ {
11
+ open: boolean
12
+ toggle: AnyFunction
13
+ darkenBackground?: boolean
14
+ size?: number
15
+ showCloseButton?: boolean
16
+ title?: React.ReactNode | string
17
+ footer?: React.ReactNode
18
+ position?: 'left' | 'right' | 'top' | 'bottom'
19
+ style?: StyledProp<DrawerComposition>
20
+ closeButtonProps?: Partial<ActionIconProps>
21
+ closeIcon?: AppIcon
22
+ children?: React.ReactNode
23
+ }
@@ -1,21 +1,17 @@
1
1
  import { DropzoneFilePreviewProps, DropzoneInnerFilePreviewProps, DropzoneProps, DropzoneRef } from './types'
2
- import { DropzonePresets } from './styles'
3
- import { IconPlaceholder, PropsOf, TypeGuards, onUpdate, useCallback, useDefaultComponentStyle, useNestedStylesByKey, useRef } from '@codeleap/common'
2
+ import { PropsOf, TypeGuards, onUpdate, useCallback } from '@codeleap/common'
4
3
  import { FileRejection, useDropzone } from 'react-dropzone'
5
4
  import { View, ViewProps } from '../View'
6
5
  import { Text } from '../Text'
7
6
  import { Icon } from '../Icon'
8
7
  import { forwardRef, useImperativeHandle, useState, HTMLProps } from 'react'
9
8
  import { ActionIcon } from '../ActionIcon'
9
+ import { useStylesFor } from '../../lib/hooks/useStylesFor'
10
+ import { WebStyleRegistry } from '../../lib/WebStyleRegistry'
11
+ import { AnyRecord, AppIcon, IJSX, StyledComponentProps, StyledComponentWithProps, useNestedStylesByKey } from '@codeleap/styles'
10
12
 
11
- const defaultProps: Partial<DropzoneProps> = {
12
- icon: 'file-plus' as IconPlaceholder,
13
- multiple: false,
14
- acceptedFiles: [],
15
- fileLeftIcon: 'file' as IconPlaceholder,
16
- fileRightIcon: 'x' as IconPlaceholder,
17
- withImagePreview: true,
18
- }
13
+ export * from './styles'
14
+ export * from './types'
19
15
 
20
16
  function isImage(file) {
21
17
  return file?.type?.startsWith('image/')
@@ -24,7 +20,7 @@ function isImage(file) {
24
20
  const DefaultFilePreview = (props: DropzoneInnerFilePreviewProps) => {
25
21
  const {
26
22
  file,
27
- variantStyles,
23
+ styles,
28
24
  errors = [],
29
25
  onRemove,
30
26
  fileLeftIcon,
@@ -36,34 +32,38 @@ const DefaultFilePreview = (props: DropzoneInnerFilePreviewProps) => {
36
32
  isPreview,
37
33
  } = props
38
34
 
35
+ const handleRemove = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
36
+ e?.stopPropagation?.()
37
+ onRemove?.()
38
+ }
39
+
39
40
  return (
40
- <View css={[variantStyles.fileWrapper, hasErrors && variantStyles['fileWrapper:error']]}>
41
- {isPreview ?
41
+ <View style={[styles.fileWrapper, hasErrors && styles['fileWrapper:error']]}>
42
+ {isPreview ? (
42
43
  <img
43
44
  onLoad={revokeImageUrl}
44
45
  src={imageUrl}
45
- css={variantStyles.fileImage}
46
+ css={styles.fileImage}
46
47
  />
47
- :
48
+ ) : (
48
49
  <Icon
49
50
  debugName='DropzoneFilePreview:LeftIcon'
50
51
  name={fileLeftIcon}
51
- css={variantStyles.fileLeftIcon}
52
- />
52
+ style={styles.fileLeftIcon}
53
+ />)
53
54
  }
54
55
 
55
- <View css={variantStyles.fileNameWrapper}>
56
- <Text text={file.name} css={variantStyles.fileName} />
57
- {hasErrors && errors?.map(error => <Text text={error.message} css={variantStyles.fileError} />)}
56
+ <View style={styles.fileNameWrapper}>
57
+ <Text text={file.name} style={styles.fileName} />
58
+ {hasErrors && errors?.map(error => <Text text={error.message} style={styles.fileError} />)}
58
59
  </View>
59
60
 
60
61
  <ActionIcon
61
- onClick={e => {
62
- e.stopPropagation()
63
- onRemove?.()
64
- }} debugName='DropzoneFilePreview:RightIcon'
62
+ onPress={handleRemove}
63
+ propagate={false}
64
+ debugName='DropzoneFilePreview:RightIcon'
65
65
  name={fileRightIcon}
66
- styles={fileRightIconStyles}
66
+ style={fileRightIconStyles}
67
67
  />
68
68
  </View>
69
69
  )
@@ -77,9 +77,9 @@ const FilePreview = (props: DropzoneFilePreviewProps) => {
77
77
  FilePreviewComponent,
78
78
  ...rest
79
79
  } = props
80
+
80
81
  const hasErrors = errors?.length > 0
81
- const _isImage = isImage(file)
82
- const isPreview = withImagePreview && _isImage
82
+ const isPreview = withImagePreview && isImage(file)
83
83
 
84
84
  const [imageUrl, setImageUrl] = useState<string>()
85
85
 
@@ -88,8 +88,10 @@ const FilePreview = (props: DropzoneFilePreviewProps) => {
88
88
  }
89
89
 
90
90
  onUpdate(() => {
91
- if (_isImage) setImageUrl(URL.createObjectURL(file))
92
- }, [file, _isImage])
91
+ if (isImage(file)) {
92
+ setImageUrl(URL.createObjectURL(file))
93
+ }
94
+ }, [file])
93
95
 
94
96
  const _FilePreview = !TypeGuards.isNil(FilePreviewComponent) ? FilePreviewComponent : DefaultFilePreview
95
97
 
@@ -106,15 +108,8 @@ const FilePreview = (props: DropzoneFilePreviewProps) => {
106
108
  )
107
109
  }
108
110
 
109
- const DropzoneComponent = (props: DropzoneProps, ref: React.ForwardedRef<DropzoneRef>) => {
110
- const allProps = {
111
- ...DropzoneComponent.defaultProps,
112
- ...props,
113
- }
111
+ export const Dropzone = forwardRef<DropzoneRef, DropzoneProps>((props, ref) => {
114
112
  const {
115
- responsiveVariants,
116
- styles,
117
- variants,
118
113
  icon,
119
114
  placeholder,
120
115
  multiple,
@@ -129,19 +124,19 @@ const DropzoneComponent = (props: DropzoneProps, ref: React.ForwardedRef<Dropzon
129
124
  onRemove,
130
125
  children,
131
126
  FilePreviewComponent,
132
- ...rest } = allProps
127
+ style,
128
+ ...rest
129
+ } = {
130
+ ...Dropzone.defaultProps,
131
+ ...props,
132
+ }
133
+
134
+ const styles = useStylesFor(Dropzone.styleRegistryName, style)
133
135
 
134
136
  const [rejectedFilesState, setRejectedFilesState] = useState<DropzoneProps['rejectedFiles']>([])
135
137
  const [rejectedFiles, setRejectedFiles] = [rejectedFilesProps || rejectedFilesState, setRejectedFilesProps || setRejectedFilesState]
136
138
 
137
- const variantStyles = useDefaultComponentStyle<'u:Dropzone', typeof DropzonePresets>('u:Dropzone', {
138
- responsiveVariants,
139
- variants,
140
- styles,
141
- rootElement: 'wrapper',
142
- })
143
-
144
- const fileRightIconStyles = useNestedStylesByKey('fileRightIcon', variantStyles)
139
+ const fileRightIconStyles = useNestedStylesByKey('fileRightIcon', styles)
145
140
 
146
141
  const handleDrop = useCallback((newAcceptedFiles: File[], newRejectedFiles: FileRejection[], event) => {
147
142
  setRejectedFiles(newRejectedFiles)
@@ -178,23 +173,23 @@ const DropzoneComponent = (props: DropzoneProps, ref: React.ForwardedRef<Dropzon
178
173
  const fileProps = {
179
174
  fileLeftIcon,
180
175
  fileRightIcon,
181
- variantStyles,
176
+ styles,
182
177
  withImagePreview,
183
178
  fileRightIconStyles,
184
179
  }
185
180
 
186
181
  return (
187
- <View css={variantStyles.wrapper}>
188
- <View {...getRootProps() as PropsOf<ViewProps<'div'>>} css={variantStyles.dropzone}>
182
+ <View style={styles.wrapper}>
183
+ <View {...getRootProps() as PropsOf<ViewProps>} style={styles.dropzone}>
189
184
 
190
- {icon && !hasFiles &&
191
- <View css={variantStyles.iconWrapper}>
192
- <Icon debugName='Dropzone:Icon' name={icon} css={variantStyles.icon} />
185
+ {icon && !hasFiles ? (
186
+ <View style={styles.iconWrapper}>
187
+ <Icon debugName='Dropzone:Icon' name={icon} style={styles.icon} />
193
188
  </View>
194
- }
189
+ ) : null}
195
190
 
196
- {hasFiles && (
197
- <View css={variantStyles.filesWrapper}>
191
+ {hasFiles ? (
192
+ <View style={styles.filesWrapper}>
198
193
  {acceptedFiles?.map?.((file, index) => (
199
194
  <FilePreview
200
195
  {...fileProps}
@@ -216,20 +211,49 @@ const DropzoneComponent = (props: DropzoneProps, ref: React.ForwardedRef<Dropzon
216
211
  FilePreviewComponent={FilePreviewComponent}
217
212
  />))}
218
213
  </View>
219
- )}
214
+ ) : null}
220
215
 
221
216
  {children}
222
- {!!placeholder && <Text text={placeholder} css={variantStyles.placeholder} />}
217
+
218
+ {!!placeholder ? <Text text={placeholder} style={styles.placeholder} /> : null}
223
219
 
224
220
  <input {...getInputProps() as HTMLProps<HTMLInputElement>} />
225
221
  </View>
226
222
  </View>)
223
+ }) as StyledComponentWithProps<DropzoneProps>
224
+
225
+ Dropzone.styleRegistryName = 'Dropzone'
226
+
227
+ Dropzone.elements = [
228
+ 'wrapper',
229
+ 'dropzone',
230
+ 'icon',
231
+ 'placeholder',
232
+ 'filesWrapper',
233
+ 'fileWrapper',
234
+ 'fileLeftIcon',
235
+ 'fileName',
236
+ 'fileError',
237
+ 'fileErrors',
238
+ 'fileNameWrapper',
239
+ 'fileImage',
240
+ 'iconWrapper',
241
+ `fileRightIcon`,
242
+ ]
243
+
244
+ Dropzone.rootElement = 'wrapper'
245
+
246
+ Dropzone.withVariantTypes = <S extends AnyRecord>(styles: S) => {
247
+ return Dropzone as (props: StyledComponentProps<DropzoneProps, typeof styles>) => IJSX
227
248
  }
228
249
 
229
- export * from './styles'
230
- export * from './types'
231
-
232
- DropzoneComponent.defaultProps = defaultProps
250
+ Dropzone.defaultProps = {
251
+ icon: 'file-plus' as AppIcon,
252
+ multiple: false,
253
+ acceptedFiles: [],
254
+ fileLeftIcon: 'file' as AppIcon,
255
+ fileRightIcon: 'x' as AppIcon,
256
+ withImagePreview: true,
257
+ } as Partial<DropzoneProps>
233
258
 
234
- // @ts-ignore
235
- export const Dropzone = forwardRef(DropzoneComponent)
259
+ WebStyleRegistry.registerComponent(Dropzone)
@@ -1,4 +1,3 @@
1
- import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
1
  import { ActionIconComposition } from '../ActionIcon'
3
2
 
4
3
  export type DropzoneComposition =
@@ -16,8 +15,3 @@ export type DropzoneComposition =
16
15
  | 'fileImage'
17
16
  | 'iconWrapper'
18
17
  | `fileRightIcon${Capitalize<ActionIconComposition>}`
19
-
20
- const createDropzoneStyle = createDefaultVariantFactory<DropzoneComposition>()
21
-
22
- export const DropzonePresets = includePresets((styles) => createDropzoneStyle(() => ({ wrapper: styles })),
23
- )