@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.
- package/package.json +1 -2
- package/src/components/ActionIcon/index.tsx +52 -51
- package/src/components/ActionIcon/styles.ts +5 -1
- package/src/components/ActivityIndicator/index.tsx +55 -34
- package/src/components/ActivityIndicator/styles.ts +6 -0
- package/src/components/Badge/index.tsx +80 -43
- package/src/components/Badge/styles.ts +11 -1
- package/src/components/Button/index.tsx +89 -46
- package/src/components/Button/styles.ts +5 -0
- package/src/components/Checkbox/index.tsx +97 -83
- package/src/components/Checkbox/styles.ts +5 -1
- package/src/components/Collapse/index.tsx +83 -41
- package/src/components/Collapse/styles.ts +6 -3
- package/src/components/ColorPicker/index.tsx +48 -95
- package/src/components/ColorPicker/styles.ts +11 -11
- package/src/components/ColorPicker/types.ts +12 -26
- package/src/components/CropPicker/index.tsx +104 -100
- package/src/components/CropPicker/styles.ts +7 -0
- package/src/components/CropPicker/types.ts +17 -8
- package/src/{lib/hooks/useCropPicker.ts → components/CropPicker/useCropPicker.tsx} +15 -68
- package/src/components/CropPicker/utils.ts +51 -0
- package/src/components/DatePicker/{components → defaultComponents}/Header.tsx +17 -9
- package/src/components/DatePicker/{components → defaultComponents}/OuterInput.tsx +7 -6
- package/src/components/DatePicker/index.tsx +124 -110
- package/src/components/DatePicker/styles.ts +12 -1
- package/src/components/DatePicker/types.ts +33 -16
- package/src/components/Drawer/index.tsx +125 -133
- package/src/components/Drawer/styles.ts +5 -0
- package/src/components/Dropzone/index.tsx +63 -87
- package/src/components/Dropzone/styles.ts +6 -0
- package/src/components/Dropzone/types.ts +37 -29
- package/src/components/EmptyPlaceholder/index.tsx +83 -63
- package/src/components/EmptyPlaceholder/styles.ts +5 -0
- package/src/components/FileInput.tsx +91 -0
- package/src/components/Grid/index.tsx +41 -40
- package/src/components/Grid/styles.ts +9 -2
- package/src/components/Grid/types.ts +12 -10
- package/src/components/Icon/index.tsx +47 -45
- package/src/components/Icon/styles.ts +8 -0
- package/src/components/InputBase/index.tsx +42 -71
- package/src/components/InputBase/styles.ts +47 -37
- package/src/components/InputBase/types.ts +7 -19
- package/src/components/InputBase/utils.ts +23 -3
- package/src/components/List/ListLayout.tsx +37 -20
- package/src/components/List/PaginationIndicator.tsx +102 -0
- package/src/components/List/index.tsx +41 -36
- package/src/components/List/styles.ts +11 -5
- package/src/components/List/types.ts +20 -30
- package/src/components/List/useInfiniteScroll.ts +159 -0
- package/src/components/LoadingOverlay/index.tsx +33 -31
- package/src/components/LoadingOverlay/styles.ts +8 -3
- package/src/components/Modal/index.tsx +160 -98
- package/src/components/Modal/styles.ts +5 -0
- package/src/components/NumberIncrement/index.tsx +98 -67
- package/src/components/NumberIncrement/styles.ts +5 -0
- package/src/components/Overlay/index.tsx +35 -37
- package/src/components/Overlay/styles.ts +5 -3
- package/src/components/Pager/index.tsx +81 -65
- package/src/components/Pager/styles.ts +9 -3
- package/src/components/Progress/Bar/index.tsx +50 -45
- package/src/components/Progress/Bar/styles.tsx +7 -0
- package/src/components/Progress/Bar/types.tsx +30 -0
- package/src/components/Progress/Circle/index.tsx +48 -45
- package/src/components/Progress/Circle/styles.ts +8 -1
- package/src/components/Progress/Circle/types.ts +22 -10
- package/src/components/RadioInput/index.tsx +124 -78
- package/src/components/RadioInput/styles.ts +6 -0
- package/src/components/Scroll/index.tsx +32 -0
- package/src/components/Scroll/styles.ts +8 -0
- package/src/components/SearchInput/index.tsx +10 -10
- package/src/components/SectionFilters/index.tsx +36 -47
- package/src/components/SectionFilters/styles.ts +5 -1
- package/src/components/SectionFilters/types.ts +13 -14
- package/src/components/SegmentedControl/SegmentedControlOption.tsx +84 -0
- package/src/components/SegmentedControl/index.tsx +89 -111
- package/src/components/SegmentedControl/styles.ts +21 -7
- package/src/components/Select/index.tsx +58 -92
- package/src/components/Select/styles.ts +36 -19
- package/src/components/Select/types.ts +13 -17
- package/src/components/Slider/index.tsx +93 -85
- package/src/components/Slider/styles.ts +6 -13
- package/src/components/Switch/index.tsx +74 -63
- package/src/components/Switch/styles.ts +6 -1
- package/src/components/Tag/index.tsx +44 -39
- package/src/components/Tag/styles.ts +9 -1
- package/src/components/Tag/types.ts +10 -10
- package/src/components/Text/index.tsx +48 -37
- package/src/components/Text/styles.ts +8 -0
- package/src/components/Text/types.ts +8 -8
- package/src/components/TextEditor/index.tsx +28 -49
- package/src/components/TextEditor/styles.ts +8 -1
- package/src/components/TextEditor/types.ts +6 -11
- package/src/components/TextInput/index.tsx +96 -58
- package/src/components/TextInput/mask.tsx +50 -2
- package/src/components/TextInput/styles.ts +8 -3
- package/src/components/Tooltip/index.tsx +84 -61
- package/src/components/Tooltip/styles.ts +10 -3
- package/src/components/Touchable/index.tsx +86 -43
- package/src/components/Touchable/styles.ts +6 -0
- package/src/components/View/index.tsx +50 -36
- package/src/components/View/styles.ts +6 -0
- package/src/components/View/types.ts +15 -14
- package/src/components/components.ts +3 -2
- package/src/components/defaultStyles.ts +79 -0
- package/src/index.ts +0 -1
- package/src/lib/hooks/index.ts +0 -5
- package/src/lib/hooks/useBreakpointMatch.ts +7 -8
- package/src/lib/hooks/useMediaQuery.ts +3 -4
- package/src/lib/hooks/usePagination.ts +63 -79
- package/src/lib/index.ts +0 -1
- package/src/lib/utils/index.ts +0 -1
- package/src/lib/utils/test.ts +2 -2
- package/src/components/ActionIcon/types.ts +0 -15
- package/src/components/ActivityIndicator/types.ts +0 -12
- package/src/components/Badge/types.ts +0 -28
- package/src/components/Button/types.ts +0 -25
- package/src/components/Checkbox/types.ts +0 -15
- package/src/components/Collapse/types.ts +0 -11
- package/src/components/Drawer/types.ts +0 -23
- package/src/components/EmptyPlaceholder/types.ts +0 -32
- package/src/components/FileInput/index.tsx +0 -72
- package/src/components/FileInput/types.ts +0 -14
- package/src/components/Icon/types.ts +0 -15
- package/src/components/LoadingOverlay/types.ts +0 -16
- package/src/components/Modal/types.ts +0 -55
- package/src/components/NumberIncrement/types.ts +0 -29
- package/src/components/Overlay/types.ts +0 -13
- package/src/components/Pager/types.ts +0 -35
- package/src/components/PaginationButtons/index.tsx +0 -173
- package/src/components/PaginationButtons/styles.ts +0 -7
- package/src/components/PaginationButtons/types.ts +0 -26
- package/src/components/PaginationIndicator/index.tsx +0 -69
- package/src/components/PaginationIndicator/styles.ts +0 -3
- package/src/components/PaginationIndicator/types.ts +0 -18
- package/src/components/Progress/Bar/styles.ts +0 -10
- package/src/components/Progress/Bar/types.ts +0 -26
- package/src/components/RadioInput/types.ts +0 -29
- package/src/components/SegmentedControl/types.ts +0 -44
- package/src/components/Slider/types.ts +0 -29
- package/src/components/Switch/types.ts +0 -13
- package/src/components/TextInput/types.ts +0 -85
- package/src/components/Tooltip/types.ts +0 -46
- package/src/components/Touchable/types.ts +0 -22
- package/src/lib/WebStyleRegistry.ts +0 -51
- package/src/lib/hooks/useFileInput.ts +0 -15
- package/src/lib/hooks/useInfiniteScroll.ts +0 -77
- package/src/lib/hooks/useRefresh.ts +0 -87
- package/src/lib/hooks/useStylesFor.ts +0 -13
- package/src/lib/utils/cache.ts +0 -9
- /package/src/components/DatePicker/{components → defaultComponents}/index.tsx +0 -0
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import { TypeGuards, useCallback, useMemo, useConditionalState } from '@codeleap/common'
|
|
5
|
-
import {
|
|
4
|
+
import { TypeGuards, getNestedStylesByKey, useCallback, useDefaultComponentStyle, useMemo, useConditionalState } from '@codeleap/common'
|
|
5
|
+
import { SectionFilterPresets } from './styles'
|
|
6
|
+
import { ItemOptionProps, ItemProps, OnPressOptionProps, OptionProps, SectionFiltersProps, SectionFilterFooterProps, onSelectItemProps } from './types'
|
|
6
7
|
import { View } from '../View'
|
|
7
8
|
import { Text } from '../Text'
|
|
8
9
|
import { Button } from '../Button'
|
|
9
|
-
import { useStylesFor } from '../../lib/hooks/useStylesFor'
|
|
10
|
-
import { WebStyleRegistry } from '../../lib/WebStyleRegistry'
|
|
11
|
-
import { AnyRecord, IJSX, StyledComponentProps, useCompositionStyles } from '@codeleap/styles'
|
|
12
10
|
|
|
13
11
|
export * from './styles'
|
|
14
12
|
export * from './types'
|
|
15
13
|
|
|
16
14
|
const ItemOption = (props: OptionProps) => {
|
|
15
|
+
|
|
17
16
|
const {
|
|
18
17
|
option,
|
|
19
18
|
item,
|
|
@@ -50,21 +49,24 @@ const ItemOption = (props: OptionProps) => {
|
|
|
50
49
|
return (
|
|
51
50
|
<Button
|
|
52
51
|
debugName='Item option'
|
|
53
|
-
text={
|
|
52
|
+
text={option?.label}
|
|
54
53
|
onPress={onPress}
|
|
55
54
|
selected={isItemSelected}
|
|
55
|
+
styles={styles}
|
|
56
56
|
{...buttonProps}
|
|
57
|
-
style={styles}
|
|
58
57
|
/>
|
|
59
58
|
)
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export const SectionFilters = (props: SectionFiltersProps) => {
|
|
62
|
+
|
|
63
63
|
const {
|
|
64
64
|
data,
|
|
65
65
|
onSelectItem,
|
|
66
66
|
renderFooterComponent,
|
|
67
|
-
|
|
67
|
+
responsiveVariants,
|
|
68
|
+
variants,
|
|
69
|
+
styles,
|
|
68
70
|
applyFilterButtonProps,
|
|
69
71
|
clearFilterButtonProps,
|
|
70
72
|
applyButtonText,
|
|
@@ -75,9 +77,19 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
75
77
|
...props,
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
const
|
|
80
|
+
const variantStyles = useDefaultComponentStyle<'u:SectionFilters', typeof SectionFilterPresets>(
|
|
81
|
+
'u:SectionFilters',
|
|
82
|
+
{
|
|
83
|
+
responsiveVariants,
|
|
84
|
+
variants,
|
|
85
|
+
styles,
|
|
86
|
+
rootElement: 'wrapper',
|
|
87
|
+
},
|
|
88
|
+
)
|
|
79
89
|
|
|
80
|
-
const
|
|
90
|
+
const applyButtonStyles = getNestedStylesByKey('applyButton', variantStyles)
|
|
91
|
+
const clearButtonStyles = getNestedStylesByKey('clearButton', variantStyles)
|
|
92
|
+
const itemOptionButtonStyles = getNestedStylesByKey('itemOptionButton', variantStyles)
|
|
81
93
|
|
|
82
94
|
const [_selectedItems, _setSelectedItems] = useConditionalState(props?.selectedItems, props?.setSelectedItems, { initialValue: {}})
|
|
83
95
|
const [_draft, _setDraft] = useConditionalState(props?.draftItems, props?.setDraftItems, { initialValue: {}})
|
|
@@ -86,6 +98,7 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
86
98
|
const shouldDisableActions = Object.keys(_draft)?.length === 0 && Object.keys(_selectedItems)?.length === 0
|
|
87
99
|
|
|
88
100
|
const onPressOption = useCallback((params: OnPressOptionProps) => {
|
|
101
|
+
|
|
89
102
|
const { item, option, canSelectMultiple, hasMultipleOptions } = params
|
|
90
103
|
|
|
91
104
|
_setDraft((state) => {
|
|
@@ -129,6 +142,7 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
129
142
|
}, [_draft, onSelectItem])
|
|
130
143
|
|
|
131
144
|
const renderItem = useCallback((item: ItemProps) => {
|
|
145
|
+
|
|
132
146
|
const {
|
|
133
147
|
showDescriptionLabel = true,
|
|
134
148
|
} = item
|
|
@@ -139,6 +153,7 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
139
153
|
const description = TypeGuards.isString(item?.descriptionLabel) ? item?.descriptionLabel : item?.label
|
|
140
154
|
|
|
141
155
|
const Option = ({ option }: { option: ItemOptionProps}) => {
|
|
156
|
+
|
|
142
157
|
if (TypeGuards.isNil(item?.id)) {
|
|
143
158
|
return null
|
|
144
159
|
}
|
|
@@ -148,7 +163,7 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
148
163
|
option={option}
|
|
149
164
|
item={item}
|
|
150
165
|
selectedItems={_draft}
|
|
151
|
-
styles={
|
|
166
|
+
styles={itemOptionButtonStyles}
|
|
152
167
|
onPress={() => onPressOption({ option, item, canSelectMultiple, hasMultipleOptions })}
|
|
153
168
|
canSelectMultiple={canSelectMultiple}
|
|
154
169
|
/>
|
|
@@ -156,9 +171,9 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
156
171
|
}
|
|
157
172
|
|
|
158
173
|
return (
|
|
159
|
-
<View style={
|
|
160
|
-
{showDescriptionLabel
|
|
161
|
-
<View style={
|
|
174
|
+
<View style={variantStyles.optionWrapper}>
|
|
175
|
+
{showDescriptionLabel ? <Text style={variantStyles.label} text={description} /> : null}
|
|
176
|
+
<View style={variantStyles.optionInnerWrapper}>
|
|
162
177
|
{hasMultipleOptions ? (
|
|
163
178
|
item?.options?.map?.((option) => <Option option={option} />)
|
|
164
179
|
) : (
|
|
@@ -173,26 +188,26 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
173
188
|
</View>
|
|
174
189
|
)
|
|
175
190
|
|
|
176
|
-
}, [_draft,
|
|
191
|
+
}, [_draft, variantStyles, itemOptionButtonStyles])
|
|
177
192
|
|
|
178
193
|
const DefaultFooter = ({ onApply, onClear, shouldDisableActions }: SectionFilterFooterProps) => {
|
|
179
194
|
return (
|
|
180
|
-
<View style={
|
|
195
|
+
<View style={variantStyles.footerWrapper}>
|
|
181
196
|
<Button
|
|
197
|
+
styles={applyButtonStyles}
|
|
182
198
|
text={applyButtonText}
|
|
183
199
|
debugName={`Section Filters Footer - Apply items`}
|
|
184
200
|
onPress={onApply}
|
|
185
201
|
disabled={shouldDisableActions}
|
|
186
202
|
{...applyFilterButtonProps}
|
|
187
|
-
style={compositionStyles?.applyButton}
|
|
188
203
|
/>
|
|
189
204
|
<Button
|
|
205
|
+
styles={clearButtonStyles}
|
|
190
206
|
text={clearButtonText}
|
|
191
207
|
debugName={`Section Filters Footer - Apply items`}
|
|
192
208
|
onPress={onClear}
|
|
193
209
|
disabled={shouldDisableActions}
|
|
194
210
|
{...clearFilterButtonProps}
|
|
195
|
-
style={compositionStyles?.clearButton}
|
|
196
211
|
/>
|
|
197
212
|
</View>
|
|
198
213
|
)
|
|
@@ -211,14 +226,10 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
211
226
|
|
|
212
227
|
const Footer = renderFooterComponent || DefaultFooter
|
|
213
228
|
|
|
214
|
-
if (!data?.length) {
|
|
215
|
-
return null
|
|
216
|
-
}
|
|
217
|
-
|
|
218
229
|
return (
|
|
219
|
-
<View style={
|
|
220
|
-
<View style={
|
|
221
|
-
{isEmpty ? null : data
|
|
230
|
+
<View style={variantStyles.wrapper}>
|
|
231
|
+
<View style={variantStyles.innerWrapper}>
|
|
232
|
+
{isEmpty ? null : data.map((item) => renderItem(item))}
|
|
222
233
|
</View>
|
|
223
234
|
|
|
224
235
|
<Footer
|
|
@@ -230,30 +241,8 @@ export const SectionFilters = (props: SectionFiltersProps) => {
|
|
|
230
241
|
)
|
|
231
242
|
}
|
|
232
243
|
|
|
233
|
-
SectionFilters.styleRegistryName = 'SectionFilters'
|
|
234
|
-
|
|
235
|
-
SectionFilters.elements = [
|
|
236
|
-
'wrapper',
|
|
237
|
-
'innerWrapper',
|
|
238
|
-
'label',
|
|
239
|
-
'optionWrapper',
|
|
240
|
-
'optionInnerWrapper',
|
|
241
|
-
'itemOptionButton',
|
|
242
|
-
'footerWrapper',
|
|
243
|
-
'applyButton',
|
|
244
|
-
'clearButton',
|
|
245
|
-
]
|
|
246
|
-
|
|
247
|
-
SectionFilters.rootElement = 'wrapper'
|
|
248
|
-
|
|
249
|
-
SectionFilters.withVariantTypes = <S extends AnyRecord>(styles: S) => {
|
|
250
|
-
return SectionFilters as (props: StyledComponentProps<SectionFiltersProps, typeof styles>) => IJSX
|
|
251
|
-
}
|
|
252
|
-
|
|
253
244
|
SectionFilters.defaultProps = {
|
|
254
245
|
applyButtonText: 'Filter',
|
|
255
246
|
clearButtonText: 'Clear',
|
|
256
247
|
filterOnOptionPress: false,
|
|
257
248
|
}
|
|
258
|
-
|
|
259
|
-
WebStyleRegistry.registerComponent(SectionFilters)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ButtonComposition } from '@codeleap/common'
|
|
1
|
+
import { ButtonComposition, createDefaultVariantFactory, includePresets } from '@codeleap/common'
|
|
2
2
|
|
|
3
3
|
export type SectionFiltersComposition =
|
|
4
4
|
'wrapper' |
|
|
@@ -10,3 +10,7 @@ export type SectionFiltersComposition =
|
|
|
10
10
|
'footerWrapper' |
|
|
11
11
|
`applyButton${Capitalize<ButtonComposition>}` |
|
|
12
12
|
`clearButton${Capitalize<ButtonComposition>}`
|
|
13
|
+
|
|
14
|
+
const createSectionFiltersStyle = createDefaultVariantFactory<SectionFiltersComposition>()
|
|
15
|
+
|
|
16
|
+
export const SectionFilterPresets = includePresets((styles) => createSectionFiltersStyle(() => ({ wrapper: styles })))
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { StylesOf } from '@codeleap/common'
|
|
3
|
-
import { SectionFiltersComposition } from './styles'
|
|
4
|
-
import { StyledProp } from '@codeleap/styles'
|
|
1
|
+
import { Button, ButtonComposition } from '../Button'
|
|
2
|
+
import { ComponentVariants, PropsOf, StylesOf } from '@codeleap/common'
|
|
3
|
+
import { SectionFiltersComposition, SectionFilterPresets } from './styles'
|
|
5
4
|
|
|
6
5
|
export type ItemOptionProps = {
|
|
7
|
-
label?: string
|
|
6
|
+
label?: string
|
|
8
7
|
value: string | number
|
|
9
|
-
itemProps?: Omit<
|
|
8
|
+
itemProps?: Omit<PropsOf<typeof Button>, 'debugName'>
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export type OnPressOptionProps = {
|
|
@@ -18,13 +17,13 @@ export type OnPressOptionProps = {
|
|
|
18
17
|
|
|
19
18
|
export type ItemProps = {
|
|
20
19
|
id: string | number
|
|
21
|
-
label?: string
|
|
20
|
+
label?: string
|
|
22
21
|
canSelectMultiple?: boolean
|
|
23
22
|
descriptionLabel?: string
|
|
24
23
|
showDescriptionLabel?: boolean
|
|
25
24
|
options?: ItemOptionProps[]
|
|
26
|
-
itemProps?: Omit<
|
|
27
|
-
selectedItemProps?: Omit<
|
|
25
|
+
itemProps?: Omit<PropsOf<typeof Button>, 'debugName'>
|
|
26
|
+
selectedItemProps?: Omit<PropsOf<typeof Button>, 'debugName'>
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
export type onSelectItemProps = {
|
|
@@ -53,18 +52,18 @@ export type SectionFiltersProps = {
|
|
|
53
52
|
onClearItems?: ClearFunction
|
|
54
53
|
onApplyItems?: ApplyFunction
|
|
55
54
|
renderFooterComponent?: (props: SectionFilterFooterProps) => JSX.Element
|
|
56
|
-
applyFilterButtonProps?: Omit<
|
|
57
|
-
clearFilterButtonProps?: Omit<
|
|
55
|
+
applyFilterButtonProps?: Omit<PropsOf<typeof Button>, 'debugName'>
|
|
56
|
+
clearFilterButtonProps?: Omit<PropsOf<typeof Button>, 'debugName'>
|
|
58
57
|
filterOnOptionPress?: boolean
|
|
59
58
|
applyButtonText?: string
|
|
60
59
|
clearButtonText?: string
|
|
61
|
-
|
|
62
|
-
}
|
|
60
|
+
styles?: StylesOf<SectionFiltersComposition>
|
|
61
|
+
} & ComponentVariants<typeof SectionFilterPresets>
|
|
63
62
|
|
|
64
63
|
export type OptionProps = {
|
|
65
64
|
option: ItemOptionProps
|
|
66
65
|
item: ItemProps
|
|
67
|
-
styles: StylesOf<ButtonComposition
|
|
66
|
+
styles: Partial<StylesOf<ButtonComposition>>
|
|
68
67
|
selectedItems: object
|
|
69
68
|
onPress: () => void
|
|
70
69
|
canSelectMultiple: boolean
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { CSSObject, jsx } from '@emotion/react'
|
|
3
|
+
|
|
4
|
+
import React, { forwardRef } from 'react'
|
|
5
|
+
import { PropsOf, IconPlaceholder } from '@codeleap/common'
|
|
6
|
+
import { StylesOf } from '../../types'
|
|
7
|
+
import { Text } from '../Text'
|
|
8
|
+
import { Touchable } from '../Touchable'
|
|
9
|
+
import { SegmentedControlComposition } from './styles'
|
|
10
|
+
import { Icon, IconProps } from '../Icon'
|
|
11
|
+
|
|
12
|
+
type OptionRef = PropsOf<typeof Touchable>['ref']
|
|
13
|
+
|
|
14
|
+
export type SegmentedControlOptionProps = PropsOf<typeof Touchable> & {
|
|
15
|
+
selected?: boolean
|
|
16
|
+
label: string
|
|
17
|
+
variantStyles?: StylesOf<SegmentedControlComposition>
|
|
18
|
+
value?: any
|
|
19
|
+
textProps?: Omit<PropsOf<typeof Text>, 'key'>
|
|
20
|
+
iconProps?: Partial<IconProps>
|
|
21
|
+
icon?: IconPlaceholder
|
|
22
|
+
ref?: OptionRef
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const SegmentedControlOptionCP = (props: SegmentedControlOptionProps, ref: OptionRef) => {
|
|
26
|
+
const {
|
|
27
|
+
selected,
|
|
28
|
+
onPress,
|
|
29
|
+
style,
|
|
30
|
+
variantStyles = {},
|
|
31
|
+
iconProps = {},
|
|
32
|
+
label,
|
|
33
|
+
icon,
|
|
34
|
+
textProps,
|
|
35
|
+
disabled,
|
|
36
|
+
...touchableProps
|
|
37
|
+
} = props
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const iconStyles = {
|
|
41
|
+
...variantStyles.icon as object,
|
|
42
|
+
...(selected ? variantStyles['icon:selected'] as object : {}),
|
|
43
|
+
...(disabled ? variantStyles['icon:disabled'] as object : {}),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Touchable
|
|
48
|
+
key={touchableProps.key}
|
|
49
|
+
ref={ref}
|
|
50
|
+
css={[
|
|
51
|
+
variantStyles.button,
|
|
52
|
+
selected && variantStyles['button:selected'],
|
|
53
|
+
disabled && variantStyles['button:disabled'],
|
|
54
|
+
style as any,
|
|
55
|
+
]}
|
|
56
|
+
onPress={onPress}
|
|
57
|
+
disabled={disabled}
|
|
58
|
+
{...touchableProps}
|
|
59
|
+
>
|
|
60
|
+
{
|
|
61
|
+
!!icon && (
|
|
62
|
+
<Icon
|
|
63
|
+
debugName={touchableProps?.debugName}
|
|
64
|
+
name={icon}
|
|
65
|
+
style={iconStyles}
|
|
66
|
+
{...iconProps}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
<Text
|
|
71
|
+
text={label}
|
|
72
|
+
debugName={touchableProps?.debugName}
|
|
73
|
+
css={[
|
|
74
|
+
variantStyles.text,
|
|
75
|
+
selected && variantStyles['text:selected'],
|
|
76
|
+
disabled && variantStyles['text:disabled'],
|
|
77
|
+
]}
|
|
78
|
+
{...textProps}
|
|
79
|
+
/>
|
|
80
|
+
</Touchable>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const SegmentedControlOption = forwardRef(SegmentedControlOptionCP) as ((props: SegmentedControlOptionProps) => JSX.Element)
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import { View } from '../View'
|
|
3
|
-
import {
|
|
3
|
+
import { SegmentedControlOption } from './SegmentedControlOption'
|
|
4
|
+
import { ComponentVariants, useDefaultComponentStyle, PropsOf, IconPlaceholder, StylesOf, useRef, TypeGuards } from '@codeleap/common'
|
|
5
|
+
import { SegmentedControlPresets } from './styles'
|
|
4
6
|
import { Text } from '../Text'
|
|
5
|
-
import { motion, AnimationProps } from 'framer-motion'
|
|
6
|
-
import { useAnimatedVariantStyles } from '../../lib'
|
|
7
|
-
import { SegmentedControlOptionProps, SegmentedControlProps } from './types'
|
|
8
7
|
import { Touchable } from '../Touchable'
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import { SegmentedControlComposition } from './styles'
|
|
9
|
+
import { motion, MotionProps, AnimationProps, ForwardRefComponent } from 'framer-motion'
|
|
10
|
+
import { useAnimatedVariantStyles } from '../../lib'
|
|
11
|
+
import { IconProps } from '../Icon'
|
|
13
12
|
|
|
14
|
-
export
|
|
15
|
-
|
|
13
|
+
export type SegmentedControlOptionProps<T = string> = {
|
|
14
|
+
label: string
|
|
15
|
+
value: T
|
|
16
|
+
icon?: IconPlaceholder
|
|
17
|
+
}
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
selected,
|
|
20
|
-
onPress,
|
|
21
|
-
styles,
|
|
22
|
-
iconProps = {},
|
|
23
|
-
label,
|
|
24
|
-
icon,
|
|
25
|
-
largestWidth,
|
|
26
|
-
textProps,
|
|
27
|
-
disabled,
|
|
28
|
-
...touchableProps
|
|
29
|
-
} = props
|
|
19
|
+
export type SegmentedControlProps<T = string> = ComponentVariants<typeof SegmentedControlPresets> & {
|
|
30
20
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
(selected ? styles['icon:selected'] : null),
|
|
34
|
-
(disabled ? styles['icon:disabled'] : null),
|
|
35
|
-
])
|
|
21
|
+
/** options that the segmented control will receive */
|
|
22
|
+
options : SegmentedControlOptionProps[]
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
24
|
+
/** the value of the segmented control */
|
|
25
|
+
value?: T
|
|
26
|
+
|
|
27
|
+
/** all styles from the segmented control */
|
|
28
|
+
styles?: StylesOf<SegmentedControlComposition>
|
|
29
|
+
|
|
30
|
+
/** view style */
|
|
31
|
+
style?: PropsOf<typeof View>['style']
|
|
32
|
+
|
|
33
|
+
/** prop to control when te value of the segmented control changes */
|
|
34
|
+
onValueChange?: (v: any) => void
|
|
35
|
+
|
|
36
|
+
/** motion div props */
|
|
37
|
+
bubbleProps?: React.HTMLAttributes<HTMLDivElement> & MotionProps
|
|
38
|
+
|
|
39
|
+
/** label that will be shown above the segmented control */
|
|
40
|
+
label?: string
|
|
41
|
+
|
|
42
|
+
/** * all the touchable props */
|
|
43
|
+
touchableProps?: Partial<PropsOf<typeof Touchable>>
|
|
44
|
+
|
|
45
|
+
debugName?: string
|
|
46
|
+
disabled?: boolean
|
|
47
|
+
animationProps?: AnimationProps
|
|
48
|
+
transitionDuration?: number
|
|
49
|
+
RenderAnimatedView?: ForwardRefComponent<HTMLDivElement, any>
|
|
50
|
+
textProps?: Omit<PropsOf<typeof Text>, 'key'>
|
|
51
|
+
iconProps?: Partial<IconProps>
|
|
52
|
+
debounce?: number
|
|
53
|
+
debounceEnabled?: boolean
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const defaultProps: Partial<SegmentedControlProps> = {
|
|
57
|
+
animationProps: {},
|
|
58
|
+
transitionDuration: 0.2,
|
|
59
|
+
disabled: false,
|
|
60
|
+
RenderAnimatedView: motion.div,
|
|
61
|
+
debounce: 1000,
|
|
62
|
+
debounceEnabled: true,
|
|
63
|
+
}
|
|
72
64
|
|
|
73
65
|
export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
66
|
+
const allProps = {
|
|
67
|
+
...SegmentedControl.defaultProps,
|
|
68
|
+
...props,
|
|
69
|
+
}
|
|
70
|
+
|
|
74
71
|
const {
|
|
75
72
|
label,
|
|
76
73
|
options,
|
|
74
|
+
styles = {},
|
|
77
75
|
value,
|
|
76
|
+
variants = [],
|
|
77
|
+
responsiveVariants = {},
|
|
78
78
|
onValueChange,
|
|
79
79
|
style,
|
|
80
80
|
bubbleProps,
|
|
@@ -82,18 +82,22 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
82
82
|
transitionDuration,
|
|
83
83
|
disabled,
|
|
84
84
|
RenderAnimatedView: Bubble,
|
|
85
|
-
textProps,
|
|
86
|
-
iconProps,
|
|
85
|
+
textProps = {},
|
|
86
|
+
iconProps = {},
|
|
87
87
|
debugName,
|
|
88
88
|
debounce,
|
|
89
89
|
debounceEnabled,
|
|
90
90
|
...rest
|
|
91
|
-
} =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
} = allProps
|
|
92
|
+
|
|
93
|
+
const variantStyles = useDefaultComponentStyle<'u:SegmentedControl', typeof SegmentedControlPresets>(
|
|
94
|
+
'u:SegmentedControl',
|
|
95
|
+
{
|
|
96
|
+
variants,
|
|
97
|
+
responsiveVariants,
|
|
98
|
+
styles,
|
|
99
|
+
},
|
|
100
|
+
)
|
|
97
101
|
|
|
98
102
|
const currentOptionIdx = React.useMemo(() => {
|
|
99
103
|
return options?.findIndex(o => o?.value === value) || 0
|
|
@@ -109,7 +113,7 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
109
113
|
}, [maxDivWidthRef.current])
|
|
110
114
|
|
|
111
115
|
const bubbleAnimation = useAnimatedVariantStyles({
|
|
112
|
-
variantStyles
|
|
116
|
+
variantStyles,
|
|
113
117
|
animatedProperties: [],
|
|
114
118
|
updater: () => {
|
|
115
119
|
'worklet'
|
|
@@ -126,21 +130,21 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
126
130
|
})
|
|
127
131
|
|
|
128
132
|
const selectedBubbleStyles = [
|
|
129
|
-
|
|
130
|
-
disabled &&
|
|
133
|
+
variantStyles.selectedBubble,
|
|
134
|
+
disabled && variantStyles['selectedBubble:disabled'],
|
|
131
135
|
largestWidth,
|
|
132
136
|
]
|
|
133
137
|
|
|
134
138
|
const onSelectTab = (option: SegmentedControlOptionProps, e?: React.KeyboardEvent<HTMLButtonElement>) => {
|
|
135
139
|
if (!e || e?.keyCode === 13 || e?.key === 'Enter') {
|
|
136
140
|
if (!debounceEnabled || !TypeGuards.isNumber(debounce)) {
|
|
137
|
-
onValueChange
|
|
141
|
+
onValueChange(option.value)
|
|
138
142
|
return
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
if (sectionPressedRef.current !== null) return
|
|
142
146
|
|
|
143
|
-
onValueChange
|
|
147
|
+
onValueChange(option.value)
|
|
144
148
|
sectionPressedRef.current = setTimeout(() => {
|
|
145
149
|
clearTimeout(sectionPressedRef.current)
|
|
146
150
|
sectionPressedRef.current = null
|
|
@@ -151,18 +155,17 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
151
155
|
}
|
|
152
156
|
|
|
153
157
|
return (
|
|
154
|
-
<View
|
|
155
|
-
{label
|
|
156
|
-
<View
|
|
158
|
+
<View css={[variantStyles.wrapper, style]} {...rest}>
|
|
159
|
+
{label && <Text text={label} css={[variantStyles.label, disabled && variantStyles['label:disabled']]} />}
|
|
160
|
+
<View css={[variantStyles.innerWrapper, disabled && variantStyles['innerWrapper:disabled']]}>
|
|
157
161
|
<Bubble
|
|
158
|
-
// @ts-expect-error
|
|
159
162
|
css={selectedBubbleStyles}
|
|
160
163
|
animate={bubbleAnimation}
|
|
161
164
|
initial={false}
|
|
162
165
|
{...bubbleProps}
|
|
163
166
|
/>
|
|
164
167
|
{options.map((o, idx) => (
|
|
165
|
-
<
|
|
168
|
+
<SegmentedControlOption
|
|
166
169
|
ref={(ref) => {
|
|
167
170
|
if (ref && ref.offsetWidth > maxDivWidthRef.current) {
|
|
168
171
|
maxDivWidthRef.current = ref.offsetWidth
|
|
@@ -176,11 +179,11 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
176
179
|
key={idx}
|
|
177
180
|
icon={o.icon}
|
|
178
181
|
selected={value === o.value}
|
|
179
|
-
|
|
182
|
+
variantStyles={variantStyles}
|
|
183
|
+
style={largestWidth}
|
|
180
184
|
disabled={disabled}
|
|
181
185
|
textProps={textProps}
|
|
182
186
|
iconProps={iconProps}
|
|
183
|
-
largestWidth={largestWidth}
|
|
184
187
|
tabIndex={0}
|
|
185
188
|
{...props?.touchableProps}
|
|
186
189
|
/>
|
|
@@ -190,31 +193,6 @@ export const SegmentedControl = (props: SegmentedControlProps) => {
|
|
|
190
193
|
)
|
|
191
194
|
}
|
|
192
195
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
SegmentedControl.elements = [
|
|
196
|
-
'wrapper',
|
|
197
|
-
'innerWrapper',
|
|
198
|
-
'selectedBubble',
|
|
199
|
-
'text',
|
|
200
|
-
'icon',
|
|
201
|
-
'button',
|
|
202
|
-
'label',
|
|
203
|
-
]
|
|
204
|
-
|
|
205
|
-
SegmentedControl.rootElement = 'wrapper'
|
|
206
|
-
|
|
207
|
-
SegmentedControl.withVariantTypes = <S extends AnyRecord>(styles: S) => {
|
|
208
|
-
return SegmentedControl as (props: StyledComponentProps<SegmentedControlProps, typeof styles>) => IJSX
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
SegmentedControl.defaultProps = {
|
|
212
|
-
animationProps: {},
|
|
213
|
-
transitionDuration: 0.2,
|
|
214
|
-
disabled: false,
|
|
215
|
-
RenderAnimatedView: motion.div,
|
|
216
|
-
debounce: 1000,
|
|
217
|
-
debounceEnabled: true,
|
|
218
|
-
} as Partial<SegmentedControlProps>
|
|
196
|
+
export * from './styles'
|
|
219
197
|
|
|
220
|
-
|
|
198
|
+
SegmentedControl.defaultProps = defaultProps
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
+
import { createDefaultVariantFactory, includePresets, StylesOf } from '@codeleap/common'
|
|
2
|
+
|
|
1
3
|
export type SegmentedControlStates = 'selected' | 'disabled'
|
|
2
4
|
|
|
3
5
|
type SegmentedControlParts =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
'selectedBubble' |
|
|
7
|
+
'wrapper' |
|
|
8
|
+
'innerWrapper' |
|
|
9
|
+
'text' |
|
|
10
|
+
'icon' |
|
|
11
|
+
'button' |
|
|
12
|
+
`label`
|
|
11
13
|
|
|
12
14
|
export type SegmentedControlComposition = SegmentedControlParts | `${SegmentedControlParts}:${SegmentedControlStates}`
|
|
15
|
+
|
|
16
|
+
export type SegmentedControlStylesGen<TCSS = any> =
|
|
17
|
+
StylesOf<
|
|
18
|
+
Exclude<SegmentedControlComposition, 'buttonFeedback'>
|
|
19
|
+
>
|
|
20
|
+
|
|
21
|
+
const createSegmentedControlStyle = createDefaultVariantFactory<
|
|
22
|
+
SegmentedControlComposition,
|
|
23
|
+
SegmentedControlStylesGen
|
|
24
|
+
>()
|
|
25
|
+
|
|
26
|
+
export const SegmentedControlPresets = includePresets((style) => createSegmentedControlStyle(() => ({ wrapper: style })))
|