@codeleap/web 3.25.0 → 3.25.3

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