@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,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 { ItemOptionProps, ItemProps, OnPressOptionProps, OptionProps, SectionFiltersProps, SectionFilterFooterProps } from './types'
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={String(option?.label)}
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
- style,
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 styles = useStylesFor(SectionFilters.styleRegistryName, style)
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 compositionStyles = useCompositionStyles(['itemOptionButton', 'clearButton', 'applyButton'], styles)
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={{ ...compositionStyles?.itemOptionButton }}
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={styles.optionWrapper}>
160
- {showDescriptionLabel && description ? <Text style={styles.label} text={`${description}`} /> : null}
161
- <View style={styles.optionInnerWrapper}>
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, styles, compositionStyles?.itemOptionButton])
191
+ }, [_draft, variantStyles, itemOptionButtonStyles])
177
192
 
178
193
  const DefaultFooter = ({ onApply, onClear, shouldDisableActions }: SectionFilterFooterProps) => {
179
194
  return (
180
- <View style={styles.footerWrapper}>
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={styles.wrapper}>
220
- <View style={styles.innerWrapper}>
221
- {isEmpty ? null : data?.map((item) => renderItem(item))}
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 { ButtonComposition, ButtonProps } from '../Button'
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 | number
6
+ label?: string
8
7
  value: string | number
9
- itemProps?: Omit<ButtonProps, 'debugName'>
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 | number
20
+ label?: string
22
21
  canSelectMultiple?: boolean
23
22
  descriptionLabel?: string
24
23
  showDescriptionLabel?: boolean
25
24
  options?: ItemOptionProps[]
26
- itemProps?: Omit<ButtonProps, 'debugName'>
27
- selectedItemProps?: Omit<ButtonProps, 'debugName'>
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<ButtonProps, 'debugName'>
57
- clearFilterButtonProps?: Omit<ButtonProps, 'debugName'>
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
- style?: StyledProp<SectionFiltersComposition>
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, { forwardRef } from 'react'
1
+ import React from 'react'
2
2
  import { View } from '../View'
3
- import { useRef, TypeGuards } from '@codeleap/common'
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 { Icon } from '../Icon'
10
- import { useStylesFor } from '../../lib/hooks/useStylesFor'
11
- import { WebStyleRegistry } from '../../lib/WebStyleRegistry'
12
- import { AnyRecord, IJSX, mergeStyles, StyledComponentProps } from '@codeleap/styles'
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 * from './styles'
15
- export * from './types'
13
+ export type SegmentedControlOptionProps<T = string> = {
14
+ label: string
15
+ value: T
16
+ icon?: IconPlaceholder
17
+ }
16
18
 
17
- const Option = forwardRef<HTMLButtonElement, SegmentedControlOptionProps>((props, ref) => {
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
- const iconStyles = mergeStyles([
32
- styles.icon,
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
- return (
38
- <Touchable
39
- key={touchableProps.key}
40
- ref={ref as unknown as React.Ref<HTMLButtonElement>}
41
- onPress={onPress}
42
- disabled={disabled}
43
- {...touchableProps}
44
- style={{
45
- ...styles.button,
46
- ...(selected ? styles['button:selected'] : {}),
47
- ...(disabled ? styles['button:disabled'] : {}),
48
- width: largestWidth?.width,
49
- }}
50
- >
51
- {!!icon ? (
52
- <Icon
53
- debugName={touchableProps?.debugName}
54
- name={icon}
55
- {...iconProps}
56
- style={iconStyles}
57
- />
58
- ) : null}
59
- <Text
60
- text={label}
61
- debugName={touchableProps?.debugName}
62
- {...textProps}
63
- style={{
64
- ...styles.text,
65
- ...(selected ? styles['text:selected'] : {}),
66
- ...(disabled ? styles['text:disabled'] : {}),
67
- }}
68
- />
69
- </Touchable>
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
- ...SegmentedControl.defaultProps,
93
- ...props,
94
- }
95
-
96
- const styles = useStylesFor(SegmentedControl.styleRegistryName, style)
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: styles,
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
- styles.selectedBubble,
130
- disabled && styles['selectedBubble: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?.(option?.value)
141
+ onValueChange(option.value)
138
142
  return
139
143
  }
140
144
 
141
145
  if (sectionPressedRef.current !== null) return
142
146
 
143
- onValueChange?.(option?.value)
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 {...rest} style={styles.wrapper}>
155
- {label ? <Text text={label} style={[styles.label, disabled && styles['label:disabled']]} /> : null}
156
- <View style={[styles.innerWrapper, disabled && styles['innerWrapper:disabled']]}>
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
- <Option
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
- styles={styles}
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
- SegmentedControl.styleRegistryName = 'SegmentedControl'
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
- WebStyleRegistry.registerComponent(SegmentedControl)
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
- 'wrapper' |
5
- 'innerWrapper' |
6
- 'selectedBubble' |
7
- 'text' |
8
- 'icon' |
9
- 'button' |
10
- `label`
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 })))